@botharness/core 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/index.mjs CHANGED
@@ -3,7 +3,7 @@ import { createHash, randomBytes, randomUUID } from "node:crypto";
3
3
  import { execFile, execFileSync, spawnSync } from "node:child_process";
4
4
  import { chmodSync, closeSync, constants, copyFileSync, cpSync, createReadStream, createWriteStream, existsSync, fstatSync, fsyncSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, stat, statSync, unlinkSync, unwatchFile, watch, watchFile, writeFileSync } from "node:fs";
5
5
  import * as sp from "node:path";
6
- import { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
6
+ import { basename, delimiter, dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
7
7
  import { isDeepStrictEqual, parseArgs, promisify } from "node:util";
8
8
  import { EventEmitter } from "node:events";
9
9
  import { lstat, mkdir, open, opendir, readFile, readdir, realpath, rename, rm, stat as stat$1, writeFile } from "node:fs/promises";
@@ -11,6 +11,7 @@ import { Readable } from "node:stream";
11
11
  import { homedir, hostname, tmpdir, type } from "node:os";
12
12
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
13
13
  import { DatabaseSync } from "node:sqlite";
14
+ import { parse, walk } from "css-tree";
14
15
  import { deflateRawSync, deflateSync, inflateRawSync } from "node:zlib";
15
16
  import { Resvg } from "@resvg/resvg-js";
16
17
  import { pipeline } from "node:stream/promises";
@@ -15790,7 +15791,7 @@ const initializer = (inst, issues) => {
15790
15791
  const ZodRealError = /*@__PURE__*/ $constructor("ZodError", initializer, { Parent: Error });
15791
15792
  //#endregion
15792
15793
  //#region node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/parse.js
15793
- const parse$1 = /* @__PURE__ */ _parse(ZodRealError);
15794
+ const parse$2 = /* @__PURE__ */ _parse(ZodRealError);
15794
15795
  const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
15795
15796
  const safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
15796
15797
  const safeParseAsync = /* @__PURE__ */ _safeParseAsync(ZodRealError);
@@ -15850,7 +15851,7 @@ const ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => {
15850
15851
  inst.def = def;
15851
15852
  inst.type = def.type;
15852
15853
  Object.defineProperty(inst, "_def", { value: def });
15853
- inst.parse = (data, params) => parse$1(inst, data, params, { callee: inst.parse });
15854
+ inst.parse = (data, params) => parse$2(inst, data, params, { callee: inst.parse });
15854
15855
  inst.safeParse = (data, params) => safeParse(inst, data, params);
15855
15856
  inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
15856
15857
  inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
@@ -16778,6 +16779,7 @@ function isChannelMessage(value) {
16778
16779
  const switchTarget = message["memorySwitchTarget"];
16779
16780
  if (switchTarget !== void 0 && (typeof switchTarget !== "string" || switchTarget.length === 0 || switchTarget.length > 255 || message["author"]?.kind !== "human")) return false;
16780
16781
  if (message["grantRequest"] !== void 0 && (message["grantRequest"] !== true || !isChannelMessageAuthor(message["author"]) || message["author"].kind !== "bot")) return false;
16782
+ if (message["grantRequestOwner"] !== void 0 && (message["grantRequest"] !== true || typeof message["grantRequestOwner"] !== "string" || !message["grantRequestOwner"])) return false;
16781
16783
  const grantResolution = message["grantRequestResolution"];
16782
16784
  const assignmentReply = message["assignmentReply"];
16783
16785
  if (assignmentReply !== void 0) {
@@ -16817,7 +16819,7 @@ function isChannelMessage(value) {
16817
16819
  if (typeof toolDecision !== "object" || toolDecision === null || message["author"]?.kind !== "human") return false;
16818
16820
  const decision = toolDecision;
16819
16821
  if (decision["actor"] !== void 0 && !parseToolApprovalActor(decision["actor"])) return false;
16820
- if (typeof decision["requestMessageId"] !== "string" || decision["outcome"] !== "allowed-once" && decision["outcome"] !== "allowed-always-exact" && decision["outcome"] !== "allowed-always-all" && decision["outcome"] !== "rejected" || message["replyTo"] !== decision["requestMessageId"]) return false;
16822
+ if (typeof decision["requestMessageId"] !== "string" || decision["outcome"] !== "allowed-once" && decision["outcome"] !== "allowed-always-tool" && decision["outcome"] !== "allowed-always-exact" && decision["outcome"] !== "allowed-always-all" && decision["outcome"] !== "rejected" || message["replyTo"] !== decision["requestMessageId"]) return false;
16821
16823
  }
16822
16824
  const mentions = message["mentions"];
16823
16825
  if (mentions !== void 0 && (!Array.isArray(mentions) || mentions.some((item) => typeof item !== "object" || item === null || typeof item.botSlug !== "string" || typeof item.label !== "string" || typeof item.start !== "number" || typeof item.end !== "number" || !Number.isSafeInteger(item.start) || !Number.isSafeInteger(item.end) || item.start < 0 || item.end <= item.start))) return false;
@@ -19631,6 +19633,15 @@ function createSqliteChannelStore(options) {
19631
19633
  if (channel === void 0) throw new Error("Group Channel not found");
19632
19634
  return allBotPreview(channel, isBotActive, options.botDisplayName ?? (() => void 0));
19633
19635
  },
19636
+ grantRequestResolution(channelId, requestMessageId) {
19637
+ const row = database.read((db) => db.prepare(`SELECT e.payload_json, e.source_event_id
19638
+ FROM source_events e JOIN channel_placements p ON p.source_event_id = e.source_event_id
19639
+ WHERE p.channel_id = ? AND json_extract(e.payload_json, '$.grantRequestResolution.requestMessageId') = ?
19640
+ LIMIT 1`).get(channelId, requestMessageId));
19641
+ if (!row) return void 0;
19642
+ const payload = JSON.parse(row.payload_json);
19643
+ return allMessages(channelId).find((message) => message.id === payload.id);
19644
+ },
19634
19645
  async appendMessageOnce(id, message, preview, origin, canCommit) {
19635
19646
  return append(id, message, true, preview, origin, canCommit) ?? { status: "missing" };
19636
19647
  },
@@ -40207,6 +40218,45 @@ function createWorkspaceGrantStore(options) {
40207
40218
  return current;
40208
40219
  }, ["workspace-grants"]));
40209
40220
  },
40221
+ async prepareWrite(botSlug, workspaceId, validate) {
40222
+ validate();
40223
+ const existing = this.list(botSlug).find((grant) => grant.workspaceId === workspaceId && grant.revokedAt === void 0);
40224
+ const revokedCount = () => this.list(botSlug).filter((grant) => grant.workspaceId === workspaceId && grant.revokedAt !== void 0).length;
40225
+ const generation = revokedCount();
40226
+ const workspace = lookup().get(workspaceId);
40227
+ if (!workspace || await workspace.status() !== "ok" || !isCurrentDirectory(workspace.path)) throw new WorkspaceGrantError("unavailable-workspace", "Workspace is unavailable");
40228
+ const grant = {
40229
+ id: existing?.id ?? createId(),
40230
+ botSlug,
40231
+ workspaceId,
40232
+ workspacePath: workspace.path,
40233
+ workspaceTitle: workspace.title,
40234
+ createdAt: existing?.createdAt ?? now().toISOString(),
40235
+ orchestratorWrite: true,
40236
+ writeRevision: (existing?.writeRevision ?? 0) + (existing?.orchestratorWrite ? 0 : 1)
40237
+ };
40238
+ return {
40239
+ grant,
40240
+ commit(connection) {
40241
+ if (!connection || !connection.isTransaction || database.read((db) => db !== connection)) throw new WorkspaceGrantError("invalid-grant", "Authorization requires the owning Channel transaction");
40242
+ validate();
40243
+ const current = read(botSlug, grant.id);
40244
+ if (revokedCount() !== generation || existing && (!current || current.revokedAt || current.writeRevision !== existing.writeRevision) || lookup().get(workspaceId)?.path !== workspace.path || !isCurrentDirectory(workspace.path)) throw new WorkspaceGrantError("invalid-grant", "Workspace authority changed while authorization was pending");
40245
+ if (existing) {
40246
+ if (current?.workspacePath !== workspace.path) throw new WorkspaceGrantError("invalid-grant", "Workspace directory changed");
40247
+ connection.prepare(`UPDATE workspace_grants SET orchestrator_write = 1,
40248
+ write_revision = write_revision + CASE WHEN orchestrator_write = 0 THEN 1 ELSE 0 END
40249
+ WHERE bot_slug = ? AND id = ? AND revoked_at IS NULL`).run(botSlug, grant.id);
40250
+ } else {
40251
+ if (connection.prepare("SELECT id FROM workspace_grants WHERE bot_slug = ? AND workspace_id = ? AND revoked_at IS NULL").get(botSlug, workspaceId)) throw new WorkspaceGrantError("invalid-grant", "Workspace was authorized concurrently; read back and retry");
40252
+ connection.prepare(`INSERT INTO workspace_grants
40253
+ (id, bot_slug, workspace_id, workspace_path, workspace_title, created_at, orchestrator_write, write_revision)
40254
+ VALUES (?, ?, ?, ?, ?, ?, 1, 1)`).run(grant.id, botSlug, workspaceId, workspace.path, workspace.title, grant.createdAt);
40255
+ }
40256
+ return true;
40257
+ }
40258
+ };
40259
+ },
40210
40260
  availableWorkspaces() {
40211
40261
  return lookup().list().map(({ id, path, title }) => ({
40212
40262
  id,
@@ -42585,6 +42635,58 @@ const BOT_HARNESS_SCHEMA_PLAN = defineSchemaPlan([
42585
42635
  session_id TEXT NOT NULL, recorded_at TEXT NOT NULL,
42586
42636
  PRIMARY KEY (operation_key, kind)
42587
42637
  );
42638
+ `);
42639
+ }
42640
+ },
42641
+ {
42642
+ generation: 103,
42643
+ module: "usage",
42644
+ description: "Record idle Orchestrator Session compactions for Bot activity",
42645
+ migrate(database) {
42646
+ database.exec(`
42647
+ CREATE TABLE usage_idle_compactions (
42648
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
42649
+ bot_slug TEXT NOT NULL,
42650
+ at TEXT NOT NULL,
42651
+ provider TEXT NOT NULL,
42652
+ model TEXT NOT NULL,
42653
+ idle_gap_ms INTEGER NOT NULL,
42654
+ cache_lifetime_ms INTEGER NOT NULL,
42655
+ cache_lifetime_source TEXT NOT NULL,
42656
+ tokens_before INTEGER NOT NULL,
42657
+ tokens_after INTEGER,
42658
+ outcome TEXT NOT NULL CHECK (outcome IN ('compacted', 'nothing', 'failed')),
42659
+ error TEXT,
42660
+ input_tokens INTEGER,
42661
+ cache_read_tokens INTEGER,
42662
+ output_tokens INTEGER
42663
+ );
42664
+ CREATE INDEX usage_idle_compactions_bot_at ON usage_idle_compactions (bot_slug, at);
42665
+ `);
42666
+ }
42667
+ },
42668
+ {
42669
+ generation: 104,
42670
+ module: "tool-approval-rules",
42671
+ description: "Remember one tool per authority scope and retain native ask for Full Access",
42672
+ migrate(database) {
42673
+ database.exec(`
42674
+ CREATE TABLE tool_approval_rules_next (
42675
+ id TEXT PRIMARY KEY, bot_slug TEXT NOT NULL,
42676
+ role TEXT NOT NULL CHECK (role IN ('orchestrator', 'assignment')),
42677
+ scope_key TEXT NOT NULL,
42678
+ kind TEXT NOT NULL CHECK (kind IN ('exact', 'tool', 'all-opaque', 'secret-cli')),
42679
+ tool_name TEXT NOT NULL, input TEXT NOT NULL, created_at TEXT NOT NULL,
42680
+ active INTEGER NOT NULL CHECK (active IN (0, 1)), revoked_at TEXT, external_creator TEXT
42681
+ );
42682
+ INSERT INTO tool_approval_rules_next
42683
+ SELECT * FROM tool_approval_rules;
42684
+ DROP TABLE tool_approval_rules;
42685
+ ALTER TABLE tool_approval_rules_next RENAME TO tool_approval_rules;
42686
+ CREATE INDEX tool_approval_rules_lookup
42687
+ ON tool_approval_rules (bot_slug, role, scope_key, active, revoked_at);
42688
+ UPDATE assignments SET approval_policy = 'ask'
42689
+ WHERE permission_mode = 'danger-full-access' AND approval_policy = 'never';
42588
42690
  `);
42589
42691
  }
42590
42692
  }
@@ -43063,6 +43165,2367 @@ function inspectMemoryRepository(options) {
43063
43165
  }
43064
43166
  }
43065
43167
  //#endregion
43168
+ //#region node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.0/ed5.js
43169
+ var require_ed5 = /* @__PURE__ */ __commonJSMin(((exports) => {
43170
+ /**
43171
+ * Character classes and associated utilities for the 5th edition of XML 1.0.
43172
+ *
43173
+ * @author Louis-Dominique Dubeau
43174
+ * @license MIT
43175
+ * @copyright Louis-Dominique Dubeau
43176
+ */
43177
+ Object.defineProperty(exports, "__esModule", { value: true });
43178
+ exports.CHAR = " \n\r -퟿-�𐀀-􏿿";
43179
+ exports.S = " \r\n";
43180
+ exports.NAME_START_CHAR = ":A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿";
43181
+ exports.NAME_CHAR = "-" + exports.NAME_START_CHAR + ".0-9·̀-ͯ‿-⁀";
43182
+ exports.CHAR_RE = new RegExp("^[" + exports.CHAR + "]$", "u");
43183
+ exports.S_RE = new RegExp("^[" + exports.S + "]+$", "u");
43184
+ exports.NAME_START_CHAR_RE = new RegExp("^[" + exports.NAME_START_CHAR + "]$", "u");
43185
+ exports.NAME_CHAR_RE = new RegExp("^[" + exports.NAME_CHAR + "]$", "u");
43186
+ exports.NAME_RE = new RegExp("^[" + exports.NAME_START_CHAR + "][" + exports.NAME_CHAR + "]*$", "u");
43187
+ exports.NMTOKEN_RE = new RegExp("^[" + exports.NAME_CHAR + "]+$", "u");
43188
+ var TAB = 9;
43189
+ var NL = 10;
43190
+ var CR = 13;
43191
+ var SPACE = 32;
43192
+ /** All characters in the ``S`` production. */
43193
+ exports.S_LIST = [
43194
+ SPACE,
43195
+ NL,
43196
+ CR,
43197
+ TAB
43198
+ ];
43199
+ /**
43200
+ * Determines whether a codepoint matches the ``CHAR`` production.
43201
+ *
43202
+ * @param c The code point.
43203
+ *
43204
+ * @returns ``true`` if the codepoint matches ``CHAR``.
43205
+ */
43206
+ function isChar(c) {
43207
+ return c >= SPACE && c <= 55295 || c === NL || c === CR || c === TAB || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
43208
+ }
43209
+ exports.isChar = isChar;
43210
+ /**
43211
+ * Determines whether a codepoint matches the ``S`` (space) production.
43212
+ *
43213
+ * @param c The code point.
43214
+ *
43215
+ * @returns ``true`` if the codepoint matches ``S``.
43216
+ */
43217
+ function isS(c) {
43218
+ return c === SPACE || c === NL || c === CR || c === TAB;
43219
+ }
43220
+ exports.isS = isS;
43221
+ /**
43222
+ * Determines whether a codepoint matches the ``NAME_START_CHAR`` production.
43223
+ *
43224
+ * @param c The code point.
43225
+ *
43226
+ * @returns ``true`` if the codepoint matches ``NAME_START_CHAR``.
43227
+ */
43228
+ function isNameStartChar(c) {
43229
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 58 || c === 95 || c === 8204 || c === 8205 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
43230
+ }
43231
+ exports.isNameStartChar = isNameStartChar;
43232
+ /**
43233
+ * Determines whether a codepoint matches the ``NAME_CHAR`` production.
43234
+ *
43235
+ * @param c The code point.
43236
+ *
43237
+ * @returns ``true`` if the codepoint matches ``NAME_CHAR``.
43238
+ */
43239
+ function isNameChar(c) {
43240
+ return isNameStartChar(c) || c >= 48 && c <= 57 || c === 45 || c === 46 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256;
43241
+ }
43242
+ exports.isNameChar = isNameChar;
43243
+ }));
43244
+ //#endregion
43245
+ //#region node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xml/1.1/ed2.js
43246
+ var require_ed2 = /* @__PURE__ */ __commonJSMin(((exports) => {
43247
+ /**
43248
+ * Character classes and associated utilities for the 2nd edition of XML 1.1.
43249
+ *
43250
+ * @author Louis-Dominique Dubeau
43251
+ * @license MIT
43252
+ * @copyright Louis-Dominique Dubeau
43253
+ */
43254
+ Object.defineProperty(exports, "__esModule", { value: true });
43255
+ exports.CHAR = "-퟿-�𐀀-􏿿";
43256
+ exports.RESTRICTED_CHAR = "-\b\v\f--„†-Ÿ";
43257
+ exports.S = " \r\n";
43258
+ exports.NAME_START_CHAR = ":A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿";
43259
+ exports.NAME_CHAR = "-" + exports.NAME_START_CHAR + ".0-9·̀-ͯ‿-⁀";
43260
+ exports.CHAR_RE = new RegExp("^[" + exports.CHAR + "]$", "u");
43261
+ exports.RESTRICTED_CHAR_RE = new RegExp("^[" + exports.RESTRICTED_CHAR + "]$", "u");
43262
+ exports.S_RE = new RegExp("^[" + exports.S + "]+$", "u");
43263
+ exports.NAME_START_CHAR_RE = new RegExp("^[" + exports.NAME_START_CHAR + "]$", "u");
43264
+ exports.NAME_CHAR_RE = new RegExp("^[" + exports.NAME_CHAR + "]$", "u");
43265
+ exports.NAME_RE = new RegExp("^[" + exports.NAME_START_CHAR + "][" + exports.NAME_CHAR + "]*$", "u");
43266
+ exports.NMTOKEN_RE = new RegExp("^[" + exports.NAME_CHAR + "]+$", "u");
43267
+ var TAB = 9;
43268
+ var NL = 10;
43269
+ var CR = 13;
43270
+ var SPACE = 32;
43271
+ /** All characters in the ``S`` production. */
43272
+ exports.S_LIST = [
43273
+ SPACE,
43274
+ NL,
43275
+ CR,
43276
+ TAB
43277
+ ];
43278
+ /**
43279
+ * Determines whether a codepoint matches the ``CHAR`` production.
43280
+ *
43281
+ * @param c The code point.
43282
+ *
43283
+ * @returns ``true`` if the codepoint matches ``CHAR``.
43284
+ */
43285
+ function isChar(c) {
43286
+ return c >= 1 && c <= 55295 || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
43287
+ }
43288
+ exports.isChar = isChar;
43289
+ /**
43290
+ * Determines whether a codepoint matches the ``RESTRICTED_CHAR`` production.
43291
+ *
43292
+ * @param c The code point.
43293
+ *
43294
+ * @returns ``true`` if the codepoint matches ``RESTRICTED_CHAR``.
43295
+ */
43296
+ function isRestrictedChar(c) {
43297
+ return c >= 1 && c <= 8 || c === 11 || c === 12 || c >= 14 && c <= 31 || c >= 127 && c <= 132 || c >= 134 && c <= 159;
43298
+ }
43299
+ exports.isRestrictedChar = isRestrictedChar;
43300
+ /**
43301
+ * Determines whether a codepoint matches the ``CHAR`` production and does not
43302
+ * match the ``RESTRICTED_CHAR`` production. ``isCharAndNotRestricted(x)`` is
43303
+ * equivalent to ``isChar(x) && !isRestrictedChar(x)``. This function is faster
43304
+ * than running the two-call equivalent.
43305
+ *
43306
+ * @param c The code point.
43307
+ *
43308
+ * @returns ``true`` if the codepoint matches ``CHAR`` and does not match
43309
+ * ``RESTRICTED_CHAR``.
43310
+ */
43311
+ function isCharAndNotRestricted(c) {
43312
+ return c === 9 || c === 10 || c === 13 || c > 31 && c < 127 || c === 133 || c > 159 && c <= 55295 || c >= 57344 && c <= 65533 || c >= 65536 && c <= 1114111;
43313
+ }
43314
+ exports.isCharAndNotRestricted = isCharAndNotRestricted;
43315
+ /**
43316
+ * Determines whether a codepoint matches the ``S`` (space) production.
43317
+ *
43318
+ * @param c The code point.
43319
+ *
43320
+ * @returns ``true`` if the codepoint matches ``S``.
43321
+ */
43322
+ function isS(c) {
43323
+ return c === SPACE || c === NL || c === CR || c === TAB;
43324
+ }
43325
+ exports.isS = isS;
43326
+ /**
43327
+ * Determines whether a codepoint matches the ``NAME_START_CHAR`` production.
43328
+ *
43329
+ * @param c The code point.
43330
+ *
43331
+ * @returns ``true`` if the codepoint matches ``NAME_START_CHAR``.
43332
+ */
43333
+ function isNameStartChar(c) {
43334
+ return c >= 65 && c <= 90 || c >= 97 && c <= 122 || c === 58 || c === 95 || c === 8204 || c === 8205 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
43335
+ }
43336
+ exports.isNameStartChar = isNameStartChar;
43337
+ /**
43338
+ * Determines whether a codepoint matches the ``NAME_CHAR`` production.
43339
+ *
43340
+ * @param c The code point.
43341
+ *
43342
+ * @returns ``true`` if the codepoint matches ``NAME_CHAR``.
43343
+ */
43344
+ function isNameChar(c) {
43345
+ return isNameStartChar(c) || c >= 48 && c <= 57 || c === 45 || c === 46 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256;
43346
+ }
43347
+ exports.isNameChar = isNameChar;
43348
+ }));
43349
+ //#endregion
43350
+ //#region node_modules/.pnpm/xmlchars@2.2.0/node_modules/xmlchars/xmlns/1.0/ed3.js
43351
+ var require_ed3 = /* @__PURE__ */ __commonJSMin(((exports) => {
43352
+ /**
43353
+ * Character class utilities for XML NS 1.0 edition 3.
43354
+ *
43355
+ * @author Louis-Dominique Dubeau
43356
+ * @license MIT
43357
+ * @copyright Louis-Dominique Dubeau
43358
+ */
43359
+ Object.defineProperty(exports, "__esModule", { value: true });
43360
+ exports.NC_NAME_START_CHAR = "A-Z_a-zÀ-ÖØ-öø-˿Ͱ-ͽͿ-῿‌-‍⁰-↏Ⰰ-⿯、-퟿豈-﷏ﷰ-�𐀀-󯿿";
43361
+ exports.NC_NAME_CHAR = "-" + exports.NC_NAME_START_CHAR + ".0-9·̀-ͯ‿-⁀";
43362
+ exports.NC_NAME_START_CHAR_RE = new RegExp("^[" + exports.NC_NAME_START_CHAR + "]$", "u");
43363
+ exports.NC_NAME_CHAR_RE = new RegExp("^[" + exports.NC_NAME_CHAR + "]$", "u");
43364
+ exports.NC_NAME_RE = new RegExp("^[" + exports.NC_NAME_START_CHAR + "][" + exports.NC_NAME_CHAR + "]*$", "u");
43365
+ /**
43366
+ * Determines whether a codepoint matches [[NC_NAME_START_CHAR]].
43367
+ *
43368
+ * @param c The code point.
43369
+ *
43370
+ * @returns ``true`` if the codepoint matches.
43371
+ */
43372
+ function isNCNameStartChar(c) {
43373
+ return c >= 65 && c <= 90 || c === 95 || c >= 97 && c <= 122 || c >= 192 && c <= 214 || c >= 216 && c <= 246 || c >= 248 && c <= 767 || c >= 880 && c <= 893 || c >= 895 && c <= 8191 || c >= 8204 && c <= 8205 || c >= 8304 && c <= 8591 || c >= 11264 && c <= 12271 || c >= 12289 && c <= 55295 || c >= 63744 && c <= 64975 || c >= 65008 && c <= 65533 || c >= 65536 && c <= 983039;
43374
+ }
43375
+ exports.isNCNameStartChar = isNCNameStartChar;
43376
+ /**
43377
+ * Determines whether a codepoint matches [[NC_NAME_CHAR]].
43378
+ *
43379
+ * @param c The code point.
43380
+ *
43381
+ * @returns ``true`` if the codepoint matches.
43382
+ */
43383
+ function isNCNameChar(c) {
43384
+ return isNCNameStartChar(c) || c === 45 || c === 46 || c >= 48 && c <= 57 || c === 183 || c >= 768 && c <= 879 || c >= 8255 && c <= 8256;
43385
+ }
43386
+ exports.isNCNameChar = isNCNameChar;
43387
+ }));
43388
+ //#endregion
43389
+ //#region packages/core/src/media/image-format.ts
43390
+ var import_saxes = (/* @__PURE__ */ __commonJSMin(((exports) => {
43391
+ Object.defineProperty(exports, "__esModule", { value: true });
43392
+ exports.SaxesParser = exports.EVENTS = void 0;
43393
+ const ed5 = require_ed5();
43394
+ const ed2 = require_ed2();
43395
+ const NSed3 = require_ed3();
43396
+ var isS = ed5.isS;
43397
+ var isChar10 = ed5.isChar;
43398
+ var isNameStartChar = ed5.isNameStartChar;
43399
+ var isNameChar = ed5.isNameChar;
43400
+ var S_LIST = ed5.S_LIST;
43401
+ var NAME_RE = ed5.NAME_RE;
43402
+ var isChar11 = ed2.isChar;
43403
+ var isNCNameStartChar = NSed3.isNCNameStartChar;
43404
+ var isNCNameChar = NSed3.isNCNameChar;
43405
+ var NC_NAME_RE = NSed3.NC_NAME_RE;
43406
+ const XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
43407
+ const XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/";
43408
+ const rootNS = {
43409
+ __proto__: null,
43410
+ xml: XML_NAMESPACE,
43411
+ xmlns: XMLNS_NAMESPACE
43412
+ };
43413
+ const XML_ENTITIES = {
43414
+ __proto__: null,
43415
+ amp: "&",
43416
+ gt: ">",
43417
+ lt: "<",
43418
+ quot: "\"",
43419
+ apos: "'"
43420
+ };
43421
+ const EOC = -1;
43422
+ const NL_LIKE = -2;
43423
+ const S_BEGIN = 0;
43424
+ const S_BEGIN_WHITESPACE = 1;
43425
+ const S_DOCTYPE = 2;
43426
+ const S_DOCTYPE_QUOTE = 3;
43427
+ const S_DTD = 4;
43428
+ const S_DTD_QUOTED = 5;
43429
+ const S_DTD_OPEN_WAKA = 6;
43430
+ const S_DTD_OPEN_WAKA_BANG = 7;
43431
+ const S_DTD_COMMENT = 8;
43432
+ const S_DTD_COMMENT_ENDING = 9;
43433
+ const S_DTD_COMMENT_ENDED = 10;
43434
+ const S_DTD_PI = 11;
43435
+ const S_DTD_PI_ENDING = 12;
43436
+ const S_TEXT = 13;
43437
+ const S_ENTITY = 14;
43438
+ const S_OPEN_WAKA = 15;
43439
+ const S_OPEN_WAKA_BANG = 16;
43440
+ const S_COMMENT = 17;
43441
+ const S_COMMENT_ENDING = 18;
43442
+ const S_COMMENT_ENDED = 19;
43443
+ const S_CDATA = 20;
43444
+ const S_CDATA_ENDING = 21;
43445
+ const S_CDATA_ENDING_2 = 22;
43446
+ const S_PI_FIRST_CHAR = 23;
43447
+ const S_PI_REST = 24;
43448
+ const S_PI_BODY = 25;
43449
+ const S_PI_ENDING = 26;
43450
+ const S_XML_DECL_NAME_START = 27;
43451
+ const S_XML_DECL_NAME = 28;
43452
+ const S_XML_DECL_EQ = 29;
43453
+ const S_XML_DECL_VALUE_START = 30;
43454
+ const S_XML_DECL_VALUE = 31;
43455
+ const S_XML_DECL_SEPARATOR = 32;
43456
+ const S_XML_DECL_ENDING = 33;
43457
+ const S_OPEN_TAG = 34;
43458
+ const S_OPEN_TAG_SLASH = 35;
43459
+ const S_ATTRIB = 36;
43460
+ const S_ATTRIB_NAME = 37;
43461
+ const S_ATTRIB_NAME_SAW_WHITE = 38;
43462
+ const S_ATTRIB_VALUE = 39;
43463
+ const S_ATTRIB_VALUE_QUOTED = 40;
43464
+ const S_ATTRIB_VALUE_CLOSED = 41;
43465
+ const S_ATTRIB_VALUE_UNQUOTED = 42;
43466
+ const S_CLOSE_TAG = 43;
43467
+ const S_CLOSE_TAG_SAW_WHITE = 44;
43468
+ const TAB = 9;
43469
+ const NL = 10;
43470
+ const CR = 13;
43471
+ const SPACE = 32;
43472
+ const BANG = 33;
43473
+ const DQUOTE = 34;
43474
+ const AMP = 38;
43475
+ const SQUOTE = 39;
43476
+ const MINUS = 45;
43477
+ const FORWARD_SLASH = 47;
43478
+ const SEMICOLON = 59;
43479
+ const LESS = 60;
43480
+ const EQUAL = 61;
43481
+ const GREATER = 62;
43482
+ const QUESTION = 63;
43483
+ const OPEN_BRACKET = 91;
43484
+ const CLOSE_BRACKET = 93;
43485
+ const NEL = 133;
43486
+ const LS = 8232;
43487
+ const isQuote = (c) => c === DQUOTE || c === SQUOTE;
43488
+ const QUOTES = [DQUOTE, SQUOTE];
43489
+ const DOCTYPE_TERMINATOR = [
43490
+ ...QUOTES,
43491
+ OPEN_BRACKET,
43492
+ GREATER
43493
+ ];
43494
+ const DTD_TERMINATOR = [
43495
+ ...QUOTES,
43496
+ LESS,
43497
+ CLOSE_BRACKET
43498
+ ];
43499
+ const XML_DECL_NAME_TERMINATOR = [
43500
+ EQUAL,
43501
+ QUESTION,
43502
+ ...S_LIST
43503
+ ];
43504
+ const ATTRIB_VALUE_UNQUOTED_TERMINATOR = [
43505
+ ...S_LIST,
43506
+ GREATER,
43507
+ AMP,
43508
+ LESS
43509
+ ];
43510
+ function nsPairCheck(parser, prefix, uri) {
43511
+ switch (prefix) {
43512
+ case "xml":
43513
+ if (uri !== XML_NAMESPACE) parser.fail(`xml prefix must be bound to ${XML_NAMESPACE}.`);
43514
+ break;
43515
+ case "xmlns": if (uri !== XMLNS_NAMESPACE) parser.fail(`xmlns prefix must be bound to ${XMLNS_NAMESPACE}.`);
43516
+ }
43517
+ switch (uri) {
43518
+ case XMLNS_NAMESPACE:
43519
+ parser.fail(prefix === "" ? `the default namespace may not be set to ${uri}.` : `may not assign a prefix (even "xmlns") to the URI \
43520
+ ${XMLNS_NAMESPACE}.`);
43521
+ break;
43522
+ case XML_NAMESPACE: switch (prefix) {
43523
+ case "xml": break;
43524
+ case "":
43525
+ parser.fail(`the default namespace may not be set to ${uri}.`);
43526
+ break;
43527
+ default: parser.fail("may not assign the xml namespace to another prefix.");
43528
+ }
43529
+ }
43530
+ }
43531
+ function nsMappingCheck(parser, mapping) {
43532
+ for (const local of Object.keys(mapping)) nsPairCheck(parser, local, mapping[local]);
43533
+ }
43534
+ const isNCName = (name) => NC_NAME_RE.test(name);
43535
+ const isName = (name) => NAME_RE.test(name);
43536
+ const FORBIDDEN_START = 0;
43537
+ const FORBIDDEN_BRACKET = 1;
43538
+ const FORBIDDEN_BRACKET_BRACKET = 2;
43539
+ /**
43540
+ * The list of supported events.
43541
+ */
43542
+ exports.EVENTS = [
43543
+ "xmldecl",
43544
+ "text",
43545
+ "processinginstruction",
43546
+ "doctype",
43547
+ "comment",
43548
+ "opentagstart",
43549
+ "attribute",
43550
+ "opentag",
43551
+ "closetag",
43552
+ "cdata",
43553
+ "error",
43554
+ "end",
43555
+ "ready"
43556
+ ];
43557
+ const EVENT_NAME_TO_HANDLER_NAME = {
43558
+ xmldecl: "xmldeclHandler",
43559
+ text: "textHandler",
43560
+ processinginstruction: "piHandler",
43561
+ doctype: "doctypeHandler",
43562
+ comment: "commentHandler",
43563
+ opentagstart: "openTagStartHandler",
43564
+ attribute: "attributeHandler",
43565
+ opentag: "openTagHandler",
43566
+ closetag: "closeTagHandler",
43567
+ cdata: "cdataHandler",
43568
+ error: "errorHandler",
43569
+ end: "endHandler",
43570
+ ready: "readyHandler"
43571
+ };
43572
+ var SaxesParser = class {
43573
+ /**
43574
+ * @param opt The parser options.
43575
+ */
43576
+ constructor(opt) {
43577
+ this.opt = opt !== null && opt !== void 0 ? opt : {};
43578
+ this.fragmentOpt = !!this.opt.fragment;
43579
+ const xmlnsOpt = this.xmlnsOpt = !!this.opt.xmlns;
43580
+ this.trackPosition = this.opt.position !== false;
43581
+ this.fileName = this.opt.fileName;
43582
+ if (xmlnsOpt) {
43583
+ this.nameStartCheck = isNCNameStartChar;
43584
+ this.nameCheck = isNCNameChar;
43585
+ this.isName = isNCName;
43586
+ this.processAttribs = this.processAttribsNS;
43587
+ this.pushAttrib = this.pushAttribNS;
43588
+ this.ns = Object.assign({ __proto__: null }, rootNS);
43589
+ const additional = this.opt.additionalNamespaces;
43590
+ if (additional != null) {
43591
+ nsMappingCheck(this, additional);
43592
+ Object.assign(this.ns, additional);
43593
+ }
43594
+ } else {
43595
+ this.nameStartCheck = isNameStartChar;
43596
+ this.nameCheck = isNameChar;
43597
+ this.isName = isName;
43598
+ this.processAttribs = this.processAttribsPlain;
43599
+ this.pushAttrib = this.pushAttribPlain;
43600
+ }
43601
+ this.stateTable = [
43602
+ this.sBegin,
43603
+ this.sBeginWhitespace,
43604
+ this.sDoctype,
43605
+ this.sDoctypeQuote,
43606
+ this.sDTD,
43607
+ this.sDTDQuoted,
43608
+ this.sDTDOpenWaka,
43609
+ this.sDTDOpenWakaBang,
43610
+ this.sDTDComment,
43611
+ this.sDTDCommentEnding,
43612
+ this.sDTDCommentEnded,
43613
+ this.sDTDPI,
43614
+ this.sDTDPIEnding,
43615
+ this.sText,
43616
+ this.sEntity,
43617
+ this.sOpenWaka,
43618
+ this.sOpenWakaBang,
43619
+ this.sComment,
43620
+ this.sCommentEnding,
43621
+ this.sCommentEnded,
43622
+ this.sCData,
43623
+ this.sCDataEnding,
43624
+ this.sCDataEnding2,
43625
+ this.sPIFirstChar,
43626
+ this.sPIRest,
43627
+ this.sPIBody,
43628
+ this.sPIEnding,
43629
+ this.sXMLDeclNameStart,
43630
+ this.sXMLDeclName,
43631
+ this.sXMLDeclEq,
43632
+ this.sXMLDeclValueStart,
43633
+ this.sXMLDeclValue,
43634
+ this.sXMLDeclSeparator,
43635
+ this.sXMLDeclEnding,
43636
+ this.sOpenTag,
43637
+ this.sOpenTagSlash,
43638
+ this.sAttrib,
43639
+ this.sAttribName,
43640
+ this.sAttribNameSawWhite,
43641
+ this.sAttribValue,
43642
+ this.sAttribValueQuoted,
43643
+ this.sAttribValueClosed,
43644
+ this.sAttribValueUnquoted,
43645
+ this.sCloseTag,
43646
+ this.sCloseTagSawWhite
43647
+ ];
43648
+ this._init();
43649
+ }
43650
+ /**
43651
+ * Indicates whether or not the parser is closed. If ``true``, wait for
43652
+ * the ``ready`` event to write again.
43653
+ */
43654
+ get closed() {
43655
+ return this._closed;
43656
+ }
43657
+ _init() {
43658
+ var _a;
43659
+ this.openWakaBang = "";
43660
+ this.text = "";
43661
+ this.name = "";
43662
+ this.piTarget = "";
43663
+ this.entity = "";
43664
+ this.q = null;
43665
+ this.tags = [];
43666
+ this.tag = null;
43667
+ this.topNS = null;
43668
+ this.chunk = "";
43669
+ this.chunkPosition = 0;
43670
+ this.i = 0;
43671
+ this.prevI = 0;
43672
+ this.carriedFromPrevious = void 0;
43673
+ this.forbiddenState = FORBIDDEN_START;
43674
+ this.attribList = [];
43675
+ const { fragmentOpt } = this;
43676
+ this.state = fragmentOpt ? S_TEXT : S_BEGIN;
43677
+ this.reportedTextBeforeRoot = this.reportedTextAfterRoot = this.closedRoot = this.sawRoot = fragmentOpt;
43678
+ this.xmlDeclPossible = !fragmentOpt;
43679
+ this.xmlDeclExpects = ["version"];
43680
+ this.entityReturnState = void 0;
43681
+ let { defaultXMLVersion } = this.opt;
43682
+ if (defaultXMLVersion === void 0) {
43683
+ if (this.opt.forceXMLVersion === true) throw new Error("forceXMLVersion set but defaultXMLVersion is not set");
43684
+ defaultXMLVersion = "1.0";
43685
+ }
43686
+ this.setXMLVersion(defaultXMLVersion);
43687
+ this.positionAtNewLine = 0;
43688
+ this.doctype = false;
43689
+ this._closed = false;
43690
+ this.xmlDecl = {
43691
+ version: void 0,
43692
+ encoding: void 0,
43693
+ standalone: void 0
43694
+ };
43695
+ this.line = 1;
43696
+ this.column = 0;
43697
+ this.ENTITIES = Object.create(XML_ENTITIES);
43698
+ (_a = this.readyHandler) === null || _a === void 0 || _a.call(this);
43699
+ }
43700
+ /**
43701
+ * The stream position the parser is currently looking at. This field is
43702
+ * zero-based.
43703
+ *
43704
+ * This field is not based on counting Unicode characters but is to be
43705
+ * interpreted as a plain index into a JavaScript string.
43706
+ */
43707
+ get position() {
43708
+ return this.chunkPosition + this.i;
43709
+ }
43710
+ /**
43711
+ * The column number of the next character to be read by the parser. *
43712
+ * This field is zero-based. (The first column in a line is 0.)
43713
+ *
43714
+ * This field reports the index at which the next character would be in the
43715
+ * line if the line were represented as a JavaScript string. Note that this
43716
+ * *can* be different to a count based on the number of *Unicode characters*
43717
+ * due to how JavaScript handles astral plane characters.
43718
+ *
43719
+ * See [[column]] for a number that corresponds to a count of Unicode
43720
+ * characters.
43721
+ */
43722
+ get columnIndex() {
43723
+ return this.position - this.positionAtNewLine;
43724
+ }
43725
+ /**
43726
+ * Set an event listener on an event. The parser supports one handler per
43727
+ * event type. If you try to set an event handler over an existing handler,
43728
+ * the old handler is silently overwritten.
43729
+ *
43730
+ * @param name The event to listen to.
43731
+ *
43732
+ * @param handler The handler to set.
43733
+ */
43734
+ on(name, handler) {
43735
+ this[EVENT_NAME_TO_HANDLER_NAME[name]] = handler;
43736
+ }
43737
+ /**
43738
+ * Unset an event handler.
43739
+ *
43740
+ * @parma name The event to stop listening to.
43741
+ */
43742
+ off(name) {
43743
+ this[EVENT_NAME_TO_HANDLER_NAME[name]] = void 0;
43744
+ }
43745
+ /**
43746
+ * Make an error object. The error object will have a message that contains
43747
+ * the ``fileName`` option passed at the creation of the parser. If position
43748
+ * tracking was turned on, it will also have line and column number
43749
+ * information.
43750
+ *
43751
+ * @param message The message describing the error to report.
43752
+ *
43753
+ * @returns An error object with a properly formatted message.
43754
+ */
43755
+ makeError(message) {
43756
+ var _a;
43757
+ let msg = (_a = this.fileName) !== null && _a !== void 0 ? _a : "";
43758
+ if (this.trackPosition) {
43759
+ if (msg.length > 0) msg += ":";
43760
+ msg += `${this.line}:${this.column}`;
43761
+ }
43762
+ if (msg.length > 0) msg += ": ";
43763
+ return new Error(msg + message);
43764
+ }
43765
+ /**
43766
+ * Report a parsing error. This method is made public so that client code may
43767
+ * check for issues that are outside the scope of this project and can report
43768
+ * errors.
43769
+ *
43770
+ * @param message The error to report.
43771
+ *
43772
+ * @returns this
43773
+ */
43774
+ fail(message) {
43775
+ const err = this.makeError(message);
43776
+ const handler = this.errorHandler;
43777
+ if (handler === void 0) throw err;
43778
+ else handler(err);
43779
+ return this;
43780
+ }
43781
+ /**
43782
+ * Write a XML data to the parser.
43783
+ *
43784
+ * @param chunk The XML data to write.
43785
+ *
43786
+ * @returns this
43787
+ */
43788
+ write(chunk) {
43789
+ if (this.closed) return this.fail("cannot write after close; assign an onready handler.");
43790
+ let end = false;
43791
+ if (chunk === null) {
43792
+ end = true;
43793
+ chunk = "";
43794
+ } else if (typeof chunk === "object") chunk = chunk.toString();
43795
+ if (this.carriedFromPrevious !== void 0) {
43796
+ chunk = `${this.carriedFromPrevious}${chunk}`;
43797
+ this.carriedFromPrevious = void 0;
43798
+ }
43799
+ let limit = chunk.length;
43800
+ const lastCode = chunk.charCodeAt(limit - 1);
43801
+ if (!end && (lastCode === CR || lastCode >= 55296 && lastCode <= 56319)) {
43802
+ this.carriedFromPrevious = chunk[limit - 1];
43803
+ limit--;
43804
+ chunk = chunk.slice(0, limit);
43805
+ }
43806
+ const { stateTable } = this;
43807
+ this.chunk = chunk;
43808
+ this.i = 0;
43809
+ while (this.i < limit) stateTable[this.state].call(this);
43810
+ this.chunkPosition += limit;
43811
+ return end ? this.end() : this;
43812
+ }
43813
+ /**
43814
+ * Close the current stream. Perform final well-formedness checks and reset
43815
+ * the parser tstate.
43816
+ *
43817
+ * @returns this
43818
+ */
43819
+ close() {
43820
+ return this.write(null);
43821
+ }
43822
+ /**
43823
+ * Get a single code point out of the current chunk. This updates the current
43824
+ * position if we do position tracking.
43825
+ *
43826
+ * This is the algorithm to use for XML 1.0.
43827
+ *
43828
+ * @returns The character read.
43829
+ */
43830
+ getCode10() {
43831
+ const { chunk, i } = this;
43832
+ this.prevI = i;
43833
+ this.i = i + 1;
43834
+ if (i >= chunk.length) return EOC;
43835
+ const code = chunk.charCodeAt(i);
43836
+ this.column++;
43837
+ if (code < 55296) {
43838
+ if (code >= SPACE || code === TAB) return code;
43839
+ switch (code) {
43840
+ case NL:
43841
+ this.line++;
43842
+ this.column = 0;
43843
+ this.positionAtNewLine = this.position;
43844
+ return NL;
43845
+ case CR:
43846
+ if (chunk.charCodeAt(i + 1) === NL) this.i = i + 2;
43847
+ this.line++;
43848
+ this.column = 0;
43849
+ this.positionAtNewLine = this.position;
43850
+ return NL_LIKE;
43851
+ default:
43852
+ this.fail("disallowed character.");
43853
+ return code;
43854
+ }
43855
+ }
43856
+ if (code > 56319) {
43857
+ if (!(code >= 57344 && code <= 65533)) this.fail("disallowed character.");
43858
+ return code;
43859
+ }
43860
+ const final = 65536 + (code - 55296) * 1024 + (chunk.charCodeAt(i + 1) - 56320);
43861
+ this.i = i + 2;
43862
+ if (final > 1114111) this.fail("disallowed character.");
43863
+ return final;
43864
+ }
43865
+ /**
43866
+ * Get a single code point out of the current chunk. This updates the current
43867
+ * position if we do position tracking.
43868
+ *
43869
+ * This is the algorithm to use for XML 1.1.
43870
+ *
43871
+ * @returns {number} The character read.
43872
+ */
43873
+ getCode11() {
43874
+ const { chunk, i } = this;
43875
+ this.prevI = i;
43876
+ this.i = i + 1;
43877
+ if (i >= chunk.length) return EOC;
43878
+ const code = chunk.charCodeAt(i);
43879
+ this.column++;
43880
+ if (code < 55296) {
43881
+ if (code > 31 && code < 127 || code > 159 && code !== LS || code === TAB) return code;
43882
+ switch (code) {
43883
+ case NL:
43884
+ this.line++;
43885
+ this.column = 0;
43886
+ this.positionAtNewLine = this.position;
43887
+ return NL;
43888
+ case CR: {
43889
+ const next = chunk.charCodeAt(i + 1);
43890
+ if (next === NL || next === NEL) this.i = i + 2;
43891
+ }
43892
+ case NEL:
43893
+ case LS:
43894
+ this.line++;
43895
+ this.column = 0;
43896
+ this.positionAtNewLine = this.position;
43897
+ return NL_LIKE;
43898
+ default:
43899
+ this.fail("disallowed character.");
43900
+ return code;
43901
+ }
43902
+ }
43903
+ if (code > 56319) {
43904
+ if (!(code >= 57344 && code <= 65533)) this.fail("disallowed character.");
43905
+ return code;
43906
+ }
43907
+ const final = 65536 + (code - 55296) * 1024 + (chunk.charCodeAt(i + 1) - 56320);
43908
+ this.i = i + 2;
43909
+ if (final > 1114111) this.fail("disallowed character.");
43910
+ return final;
43911
+ }
43912
+ /**
43913
+ * Like ``getCode`` but with the return value normalized so that ``NL`` is
43914
+ * returned for ``NL_LIKE``.
43915
+ */
43916
+ getCodeNorm() {
43917
+ const c = this.getCode();
43918
+ return c === NL_LIKE ? NL : c;
43919
+ }
43920
+ unget() {
43921
+ this.i = this.prevI;
43922
+ this.column--;
43923
+ }
43924
+ /**
43925
+ * Capture characters into a buffer until encountering one of a set of
43926
+ * characters.
43927
+ *
43928
+ * @param chars An array of codepoints. Encountering a character in the array
43929
+ * ends the capture. (``chars`` may safely contain ``NL``.)
43930
+ *
43931
+ * @return The character code that made the capture end, or ``EOC`` if we hit
43932
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
43933
+ * instead.
43934
+ */
43935
+ captureTo(chars) {
43936
+ let { i: start } = this;
43937
+ const { chunk } = this;
43938
+ while (true) {
43939
+ const c = this.getCode();
43940
+ const isNLLike = c === NL_LIKE;
43941
+ const final = isNLLike ? NL : c;
43942
+ if (final === EOC || chars.includes(final)) {
43943
+ this.text += chunk.slice(start, this.prevI);
43944
+ return final;
43945
+ }
43946
+ if (isNLLike) {
43947
+ this.text += `${chunk.slice(start, this.prevI)}\n`;
43948
+ start = this.i;
43949
+ }
43950
+ }
43951
+ }
43952
+ /**
43953
+ * Capture characters into a buffer until encountering a character.
43954
+ *
43955
+ * @param char The codepoint that ends the capture. **NOTE ``char`` MAY NOT
43956
+ * CONTAIN ``NL``.** Passing ``NL`` will result in buggy behavior.
43957
+ *
43958
+ * @return ``true`` if we ran into the character. Otherwise, we ran into the
43959
+ * end of the current chunk.
43960
+ */
43961
+ captureToChar(char) {
43962
+ let { i: start } = this;
43963
+ const { chunk } = this;
43964
+ while (true) {
43965
+ let c = this.getCode();
43966
+ switch (c) {
43967
+ case NL_LIKE:
43968
+ this.text += `${chunk.slice(start, this.prevI)}\n`;
43969
+ start = this.i;
43970
+ c = NL;
43971
+ break;
43972
+ case EOC:
43973
+ this.text += chunk.slice(start);
43974
+ return false;
43975
+ }
43976
+ if (c === char) {
43977
+ this.text += chunk.slice(start, this.prevI);
43978
+ return true;
43979
+ }
43980
+ }
43981
+ }
43982
+ /**
43983
+ * Capture characters that satisfy ``isNameChar`` into the ``name`` field of
43984
+ * this parser.
43985
+ *
43986
+ * @return The character code that made the test fail, or ``EOC`` if we hit
43987
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
43988
+ * instead.
43989
+ */
43990
+ captureNameChars() {
43991
+ const { chunk, i: start } = this;
43992
+ while (true) {
43993
+ const c = this.getCode();
43994
+ if (c === EOC) {
43995
+ this.name += chunk.slice(start);
43996
+ return EOC;
43997
+ }
43998
+ if (!isNameChar(c)) {
43999
+ this.name += chunk.slice(start, this.prevI);
44000
+ return c === NL_LIKE ? NL : c;
44001
+ }
44002
+ }
44003
+ }
44004
+ /**
44005
+ * Skip white spaces.
44006
+ *
44007
+ * @return The character that ended the skip, or ``EOC`` if we hit
44008
+ * the end of the chunk. The return value cannot be NL_LIKE: NL is returned
44009
+ * instead.
44010
+ */
44011
+ skipSpaces() {
44012
+ while (true) {
44013
+ const c = this.getCodeNorm();
44014
+ if (c === EOC || !isS(c)) return c;
44015
+ }
44016
+ }
44017
+ setXMLVersion(version) {
44018
+ this.currentXMLVersion = version;
44019
+ if (version === "1.0") {
44020
+ this.isChar = isChar10;
44021
+ this.getCode = this.getCode10;
44022
+ } else {
44023
+ this.isChar = isChar11;
44024
+ this.getCode = this.getCode11;
44025
+ }
44026
+ }
44027
+ sBegin() {
44028
+ if (this.chunk.charCodeAt(0) === 65279) {
44029
+ this.i++;
44030
+ this.column++;
44031
+ }
44032
+ this.state = S_BEGIN_WHITESPACE;
44033
+ }
44034
+ sBeginWhitespace() {
44035
+ const iBefore = this.i;
44036
+ const c = this.skipSpaces();
44037
+ if (this.prevI !== iBefore) this.xmlDeclPossible = false;
44038
+ switch (c) {
44039
+ case LESS:
44040
+ this.state = S_OPEN_WAKA;
44041
+ if (this.text.length !== 0) throw new Error("no-empty text at start");
44042
+ break;
44043
+ case EOC: break;
44044
+ default:
44045
+ this.unget();
44046
+ this.state = S_TEXT;
44047
+ this.xmlDeclPossible = false;
44048
+ }
44049
+ }
44050
+ sDoctype() {
44051
+ var _a;
44052
+ const c = this.captureTo(DOCTYPE_TERMINATOR);
44053
+ switch (c) {
44054
+ case GREATER:
44055
+ (_a = this.doctypeHandler) === null || _a === void 0 || _a.call(this, this.text);
44056
+ this.text = "";
44057
+ this.state = S_TEXT;
44058
+ this.doctype = true;
44059
+ break;
44060
+ case EOC: break;
44061
+ default:
44062
+ this.text += String.fromCodePoint(c);
44063
+ if (c === OPEN_BRACKET) this.state = S_DTD;
44064
+ else if (isQuote(c)) {
44065
+ this.state = S_DOCTYPE_QUOTE;
44066
+ this.q = c;
44067
+ }
44068
+ }
44069
+ }
44070
+ sDoctypeQuote() {
44071
+ const q = this.q;
44072
+ if (this.captureToChar(q)) {
44073
+ this.text += String.fromCodePoint(q);
44074
+ this.q = null;
44075
+ this.state = S_DOCTYPE;
44076
+ }
44077
+ }
44078
+ sDTD() {
44079
+ const c = this.captureTo(DTD_TERMINATOR);
44080
+ if (c === EOC) return;
44081
+ this.text += String.fromCodePoint(c);
44082
+ if (c === CLOSE_BRACKET) this.state = S_DOCTYPE;
44083
+ else if (c === LESS) this.state = S_DTD_OPEN_WAKA;
44084
+ else if (isQuote(c)) {
44085
+ this.state = S_DTD_QUOTED;
44086
+ this.q = c;
44087
+ }
44088
+ }
44089
+ sDTDQuoted() {
44090
+ const q = this.q;
44091
+ if (this.captureToChar(q)) {
44092
+ this.text += String.fromCodePoint(q);
44093
+ this.state = S_DTD;
44094
+ this.q = null;
44095
+ }
44096
+ }
44097
+ sDTDOpenWaka() {
44098
+ const c = this.getCodeNorm();
44099
+ this.text += String.fromCodePoint(c);
44100
+ switch (c) {
44101
+ case BANG:
44102
+ this.state = S_DTD_OPEN_WAKA_BANG;
44103
+ this.openWakaBang = "";
44104
+ break;
44105
+ case QUESTION:
44106
+ this.state = S_DTD_PI;
44107
+ break;
44108
+ default: this.state = S_DTD;
44109
+ }
44110
+ }
44111
+ sDTDOpenWakaBang() {
44112
+ const char = String.fromCodePoint(this.getCodeNorm());
44113
+ const owb = this.openWakaBang += char;
44114
+ this.text += char;
44115
+ if (owb !== "-") {
44116
+ this.state = owb === "--" ? S_DTD_COMMENT : S_DTD;
44117
+ this.openWakaBang = "";
44118
+ }
44119
+ }
44120
+ sDTDComment() {
44121
+ if (this.captureToChar(MINUS)) {
44122
+ this.text += "-";
44123
+ this.state = S_DTD_COMMENT_ENDING;
44124
+ }
44125
+ }
44126
+ sDTDCommentEnding() {
44127
+ const c = this.getCodeNorm();
44128
+ this.text += String.fromCodePoint(c);
44129
+ this.state = c === MINUS ? S_DTD_COMMENT_ENDED : S_DTD_COMMENT;
44130
+ }
44131
+ sDTDCommentEnded() {
44132
+ const c = this.getCodeNorm();
44133
+ this.text += String.fromCodePoint(c);
44134
+ if (c === GREATER) this.state = S_DTD;
44135
+ else {
44136
+ this.fail("malformed comment.");
44137
+ this.state = S_DTD_COMMENT;
44138
+ }
44139
+ }
44140
+ sDTDPI() {
44141
+ if (this.captureToChar(QUESTION)) {
44142
+ this.text += "?";
44143
+ this.state = S_DTD_PI_ENDING;
44144
+ }
44145
+ }
44146
+ sDTDPIEnding() {
44147
+ const c = this.getCodeNorm();
44148
+ this.text += String.fromCodePoint(c);
44149
+ if (c === GREATER) this.state = S_DTD;
44150
+ }
44151
+ sText() {
44152
+ if (this.tags.length !== 0) this.handleTextInRoot();
44153
+ else this.handleTextOutsideRoot();
44154
+ }
44155
+ sEntity() {
44156
+ let { i: start } = this;
44157
+ const { chunk } = this;
44158
+ loop: while (true) switch (this.getCode()) {
44159
+ case NL_LIKE:
44160
+ this.entity += `${chunk.slice(start, this.prevI)}\n`;
44161
+ start = this.i;
44162
+ break;
44163
+ case SEMICOLON: {
44164
+ const { entityReturnState } = this;
44165
+ const entity = this.entity + chunk.slice(start, this.prevI);
44166
+ this.state = entityReturnState;
44167
+ let parsed;
44168
+ if (entity === "") {
44169
+ this.fail("empty entity name.");
44170
+ parsed = "&;";
44171
+ } else {
44172
+ parsed = this.parseEntity(entity);
44173
+ this.entity = "";
44174
+ }
44175
+ if (entityReturnState !== S_TEXT || this.textHandler !== void 0) this.text += parsed;
44176
+ break loop;
44177
+ }
44178
+ case EOC:
44179
+ this.entity += chunk.slice(start);
44180
+ break loop;
44181
+ }
44182
+ }
44183
+ sOpenWaka() {
44184
+ const c = this.getCode();
44185
+ if (isNameStartChar(c)) {
44186
+ this.state = S_OPEN_TAG;
44187
+ this.unget();
44188
+ this.xmlDeclPossible = false;
44189
+ } else switch (c) {
44190
+ case FORWARD_SLASH:
44191
+ this.state = S_CLOSE_TAG;
44192
+ this.xmlDeclPossible = false;
44193
+ break;
44194
+ case BANG:
44195
+ this.state = S_OPEN_WAKA_BANG;
44196
+ this.openWakaBang = "";
44197
+ this.xmlDeclPossible = false;
44198
+ break;
44199
+ case QUESTION:
44200
+ this.state = S_PI_FIRST_CHAR;
44201
+ break;
44202
+ default:
44203
+ this.fail("disallowed character in tag name");
44204
+ this.state = S_TEXT;
44205
+ this.xmlDeclPossible = false;
44206
+ }
44207
+ }
44208
+ sOpenWakaBang() {
44209
+ this.openWakaBang += String.fromCodePoint(this.getCodeNorm());
44210
+ switch (this.openWakaBang) {
44211
+ case "[CDATA[":
44212
+ if (!this.sawRoot && !this.reportedTextBeforeRoot) {
44213
+ this.fail("text data outside of root node.");
44214
+ this.reportedTextBeforeRoot = true;
44215
+ }
44216
+ if (this.closedRoot && !this.reportedTextAfterRoot) {
44217
+ this.fail("text data outside of root node.");
44218
+ this.reportedTextAfterRoot = true;
44219
+ }
44220
+ this.state = S_CDATA;
44221
+ this.openWakaBang = "";
44222
+ break;
44223
+ case "--":
44224
+ this.state = S_COMMENT;
44225
+ this.openWakaBang = "";
44226
+ break;
44227
+ case "DOCTYPE":
44228
+ this.state = S_DOCTYPE;
44229
+ if (this.doctype || this.sawRoot) this.fail("inappropriately located doctype declaration.");
44230
+ this.openWakaBang = "";
44231
+ break;
44232
+ default: if (this.openWakaBang.length >= 7) this.fail("incorrect syntax.");
44233
+ }
44234
+ }
44235
+ sComment() {
44236
+ if (this.captureToChar(MINUS)) this.state = S_COMMENT_ENDING;
44237
+ }
44238
+ sCommentEnding() {
44239
+ var _a;
44240
+ const c = this.getCodeNorm();
44241
+ if (c === MINUS) {
44242
+ this.state = S_COMMENT_ENDED;
44243
+ (_a = this.commentHandler) === null || _a === void 0 || _a.call(this, this.text);
44244
+ this.text = "";
44245
+ } else {
44246
+ this.text += `-${String.fromCodePoint(c)}`;
44247
+ this.state = S_COMMENT;
44248
+ }
44249
+ }
44250
+ sCommentEnded() {
44251
+ const c = this.getCodeNorm();
44252
+ if (c !== GREATER) {
44253
+ this.fail("malformed comment.");
44254
+ this.text += `--${String.fromCodePoint(c)}`;
44255
+ this.state = S_COMMENT;
44256
+ } else this.state = S_TEXT;
44257
+ }
44258
+ sCData() {
44259
+ if (this.captureToChar(CLOSE_BRACKET)) this.state = S_CDATA_ENDING;
44260
+ }
44261
+ sCDataEnding() {
44262
+ const c = this.getCodeNorm();
44263
+ if (c === CLOSE_BRACKET) this.state = S_CDATA_ENDING_2;
44264
+ else {
44265
+ this.text += `]${String.fromCodePoint(c)}`;
44266
+ this.state = S_CDATA;
44267
+ }
44268
+ }
44269
+ sCDataEnding2() {
44270
+ var _a;
44271
+ const c = this.getCodeNorm();
44272
+ switch (c) {
44273
+ case GREATER:
44274
+ (_a = this.cdataHandler) === null || _a === void 0 || _a.call(this, this.text);
44275
+ this.text = "";
44276
+ this.state = S_TEXT;
44277
+ break;
44278
+ case CLOSE_BRACKET:
44279
+ this.text += "]";
44280
+ break;
44281
+ default:
44282
+ this.text += `]]${String.fromCodePoint(c)}`;
44283
+ this.state = S_CDATA;
44284
+ }
44285
+ }
44286
+ sPIFirstChar() {
44287
+ const c = this.getCodeNorm();
44288
+ if (this.nameStartCheck(c)) {
44289
+ this.piTarget += String.fromCodePoint(c);
44290
+ this.state = S_PI_REST;
44291
+ } else if (c === QUESTION || isS(c)) {
44292
+ this.fail("processing instruction without a target.");
44293
+ this.state = c === QUESTION ? S_PI_ENDING : S_PI_BODY;
44294
+ } else {
44295
+ this.fail("disallowed character in processing instruction name.");
44296
+ this.piTarget += String.fromCodePoint(c);
44297
+ this.state = S_PI_REST;
44298
+ }
44299
+ }
44300
+ sPIRest() {
44301
+ const { chunk, i: start } = this;
44302
+ while (true) {
44303
+ const c = this.getCodeNorm();
44304
+ if (c === EOC) {
44305
+ this.piTarget += chunk.slice(start);
44306
+ return;
44307
+ }
44308
+ if (!this.nameCheck(c)) {
44309
+ this.piTarget += chunk.slice(start, this.prevI);
44310
+ const isQuestion = c === QUESTION;
44311
+ if (isQuestion || isS(c)) {
44312
+ if (this.piTarget === "xml") {
44313
+ if (!this.xmlDeclPossible) this.fail("an XML declaration must be at the start of the document.");
44314
+ this.state = isQuestion ? S_XML_DECL_ENDING : S_XML_DECL_NAME_START;
44315
+ } else this.state = isQuestion ? S_PI_ENDING : S_PI_BODY;
44316
+ } else {
44317
+ this.fail("disallowed character in processing instruction name.");
44318
+ this.piTarget += String.fromCodePoint(c);
44319
+ }
44320
+ break;
44321
+ }
44322
+ }
44323
+ }
44324
+ sPIBody() {
44325
+ if (this.text.length === 0) {
44326
+ const c = this.getCodeNorm();
44327
+ if (c === QUESTION) this.state = S_PI_ENDING;
44328
+ else if (!isS(c)) this.text = String.fromCodePoint(c);
44329
+ } else if (this.captureToChar(QUESTION)) this.state = S_PI_ENDING;
44330
+ }
44331
+ sPIEnding() {
44332
+ var _a;
44333
+ const c = this.getCodeNorm();
44334
+ if (c === GREATER) {
44335
+ const { piTarget } = this;
44336
+ if (piTarget.toLowerCase() === "xml") this.fail("the XML declaration must appear at the start of the document.");
44337
+ (_a = this.piHandler) === null || _a === void 0 || _a.call(this, {
44338
+ target: piTarget,
44339
+ body: this.text
44340
+ });
44341
+ this.piTarget = this.text = "";
44342
+ this.state = S_TEXT;
44343
+ } else if (c === QUESTION) this.text += "?";
44344
+ else {
44345
+ this.text += `?${String.fromCodePoint(c)}`;
44346
+ this.state = S_PI_BODY;
44347
+ }
44348
+ this.xmlDeclPossible = false;
44349
+ }
44350
+ sXMLDeclNameStart() {
44351
+ const c = this.skipSpaces();
44352
+ if (c === QUESTION) {
44353
+ this.state = S_XML_DECL_ENDING;
44354
+ return;
44355
+ }
44356
+ if (c !== EOC) {
44357
+ this.state = S_XML_DECL_NAME;
44358
+ this.name = String.fromCodePoint(c);
44359
+ }
44360
+ }
44361
+ sXMLDeclName() {
44362
+ const c = this.captureTo(XML_DECL_NAME_TERMINATOR);
44363
+ if (c === QUESTION) {
44364
+ this.state = S_XML_DECL_ENDING;
44365
+ this.name += this.text;
44366
+ this.text = "";
44367
+ this.fail("XML declaration is incomplete.");
44368
+ return;
44369
+ }
44370
+ if (!(isS(c) || c === EQUAL)) return;
44371
+ this.name += this.text;
44372
+ this.text = "";
44373
+ if (!this.xmlDeclExpects.includes(this.name)) switch (this.name.length) {
44374
+ case 0:
44375
+ this.fail("did not expect any more name/value pairs.");
44376
+ break;
44377
+ case 1:
44378
+ this.fail(`expected the name ${this.xmlDeclExpects[0]}.`);
44379
+ break;
44380
+ default: this.fail(`expected one of ${this.xmlDeclExpects.join(", ")}`);
44381
+ }
44382
+ this.state = c === EQUAL ? S_XML_DECL_VALUE_START : S_XML_DECL_EQ;
44383
+ }
44384
+ sXMLDeclEq() {
44385
+ const c = this.getCodeNorm();
44386
+ if (c === QUESTION) {
44387
+ this.state = S_XML_DECL_ENDING;
44388
+ this.fail("XML declaration is incomplete.");
44389
+ return;
44390
+ }
44391
+ if (isS(c)) return;
44392
+ if (c !== EQUAL) this.fail("value required.");
44393
+ this.state = S_XML_DECL_VALUE_START;
44394
+ }
44395
+ sXMLDeclValueStart() {
44396
+ const c = this.getCodeNorm();
44397
+ if (c === QUESTION) {
44398
+ this.state = S_XML_DECL_ENDING;
44399
+ this.fail("XML declaration is incomplete.");
44400
+ return;
44401
+ }
44402
+ if (isS(c)) return;
44403
+ if (!isQuote(c)) {
44404
+ this.fail("value must be quoted.");
44405
+ this.q = SPACE;
44406
+ } else this.q = c;
44407
+ this.state = S_XML_DECL_VALUE;
44408
+ }
44409
+ sXMLDeclValue() {
44410
+ const c = this.captureTo([this.q, QUESTION]);
44411
+ if (c === QUESTION) {
44412
+ this.state = S_XML_DECL_ENDING;
44413
+ this.text = "";
44414
+ this.fail("XML declaration is incomplete.");
44415
+ return;
44416
+ }
44417
+ if (c === EOC) return;
44418
+ const value = this.text;
44419
+ this.text = "";
44420
+ switch (this.name) {
44421
+ case "version": {
44422
+ this.xmlDeclExpects = ["encoding", "standalone"];
44423
+ const version = value;
44424
+ this.xmlDecl.version = version;
44425
+ if (!/^1\.[0-9]+$/.test(version)) this.fail("version number must match /^1\\.[0-9]+$/.");
44426
+ else if (!this.opt.forceXMLVersion) this.setXMLVersion(version);
44427
+ break;
44428
+ }
44429
+ case "encoding":
44430
+ if (!/^[A-Za-z][A-Za-z0-9._-]*$/.test(value)) this.fail("encoding value must match /^[A-Za-z0-9][A-Za-z0-9._-]*$/.");
44431
+ this.xmlDeclExpects = ["standalone"];
44432
+ this.xmlDecl.encoding = value;
44433
+ break;
44434
+ case "standalone":
44435
+ if (value !== "yes" && value !== "no") this.fail("standalone value must match \"yes\" or \"no\".");
44436
+ this.xmlDeclExpects = [];
44437
+ this.xmlDecl.standalone = value;
44438
+ }
44439
+ this.name = "";
44440
+ this.state = S_XML_DECL_SEPARATOR;
44441
+ }
44442
+ sXMLDeclSeparator() {
44443
+ const c = this.getCodeNorm();
44444
+ if (c === QUESTION) {
44445
+ this.state = S_XML_DECL_ENDING;
44446
+ return;
44447
+ }
44448
+ if (!isS(c)) {
44449
+ this.fail("whitespace required.");
44450
+ this.unget();
44451
+ }
44452
+ this.state = S_XML_DECL_NAME_START;
44453
+ }
44454
+ sXMLDeclEnding() {
44455
+ var _a;
44456
+ if (this.getCodeNorm() === GREATER) {
44457
+ if (this.piTarget !== "xml") this.fail("processing instructions are not allowed before root.");
44458
+ else if (this.name !== "version" && this.xmlDeclExpects.includes("version")) this.fail("XML declaration must contain a version.");
44459
+ (_a = this.xmldeclHandler) === null || _a === void 0 || _a.call(this, this.xmlDecl);
44460
+ this.name = "";
44461
+ this.piTarget = this.text = "";
44462
+ this.state = S_TEXT;
44463
+ } else this.fail("The character ? is disallowed anywhere in XML declarations.");
44464
+ this.xmlDeclPossible = false;
44465
+ }
44466
+ sOpenTag() {
44467
+ var _a;
44468
+ const c = this.captureNameChars();
44469
+ if (c === EOC) return;
44470
+ const tag = this.tag = {
44471
+ name: this.name,
44472
+ attributes: Object.create(null)
44473
+ };
44474
+ this.name = "";
44475
+ if (this.xmlnsOpt) this.topNS = tag.ns = Object.create(null);
44476
+ (_a = this.openTagStartHandler) === null || _a === void 0 || _a.call(this, tag);
44477
+ this.sawRoot = true;
44478
+ if (!this.fragmentOpt && this.closedRoot) this.fail("documents may contain only one root.");
44479
+ switch (c) {
44480
+ case GREATER:
44481
+ this.openTag();
44482
+ break;
44483
+ case FORWARD_SLASH:
44484
+ this.state = S_OPEN_TAG_SLASH;
44485
+ break;
44486
+ default:
44487
+ if (!isS(c)) this.fail("disallowed character in tag name.");
44488
+ this.state = S_ATTRIB;
44489
+ }
44490
+ }
44491
+ sOpenTagSlash() {
44492
+ if (this.getCode() === GREATER) this.openSelfClosingTag();
44493
+ else {
44494
+ this.fail("forward-slash in opening tag not followed by >.");
44495
+ this.state = S_ATTRIB;
44496
+ }
44497
+ }
44498
+ sAttrib() {
44499
+ const c = this.skipSpaces();
44500
+ if (c === EOC) return;
44501
+ if (isNameStartChar(c)) {
44502
+ this.unget();
44503
+ this.state = S_ATTRIB_NAME;
44504
+ } else if (c === GREATER) this.openTag();
44505
+ else if (c === FORWARD_SLASH) this.state = S_OPEN_TAG_SLASH;
44506
+ else this.fail("disallowed character in attribute name.");
44507
+ }
44508
+ sAttribName() {
44509
+ const c = this.captureNameChars();
44510
+ if (c === EQUAL) this.state = S_ATTRIB_VALUE;
44511
+ else if (isS(c)) this.state = S_ATTRIB_NAME_SAW_WHITE;
44512
+ else if (c === GREATER) {
44513
+ this.fail("attribute without value.");
44514
+ this.pushAttrib(this.name, this.name);
44515
+ this.name = this.text = "";
44516
+ this.openTag();
44517
+ } else if (c !== EOC) this.fail("disallowed character in attribute name.");
44518
+ }
44519
+ sAttribNameSawWhite() {
44520
+ const c = this.skipSpaces();
44521
+ switch (c) {
44522
+ case EOC: return;
44523
+ case EQUAL:
44524
+ this.state = S_ATTRIB_VALUE;
44525
+ break;
44526
+ default:
44527
+ this.fail("attribute without value.");
44528
+ this.text = "";
44529
+ this.name = "";
44530
+ if (c === GREATER) this.openTag();
44531
+ else if (isNameStartChar(c)) {
44532
+ this.unget();
44533
+ this.state = S_ATTRIB_NAME;
44534
+ } else {
44535
+ this.fail("disallowed character in attribute name.");
44536
+ this.state = S_ATTRIB;
44537
+ }
44538
+ }
44539
+ }
44540
+ sAttribValue() {
44541
+ const c = this.getCodeNorm();
44542
+ if (isQuote(c)) {
44543
+ this.q = c;
44544
+ this.state = S_ATTRIB_VALUE_QUOTED;
44545
+ } else if (!isS(c)) {
44546
+ this.fail("unquoted attribute value.");
44547
+ this.state = S_ATTRIB_VALUE_UNQUOTED;
44548
+ this.unget();
44549
+ }
44550
+ }
44551
+ sAttribValueQuoted() {
44552
+ const { q, chunk } = this;
44553
+ let { i: start } = this;
44554
+ while (true) switch (this.getCode()) {
44555
+ case q:
44556
+ this.pushAttrib(this.name, this.text + chunk.slice(start, this.prevI));
44557
+ this.name = this.text = "";
44558
+ this.q = null;
44559
+ this.state = S_ATTRIB_VALUE_CLOSED;
44560
+ return;
44561
+ case AMP:
44562
+ this.text += chunk.slice(start, this.prevI);
44563
+ this.state = S_ENTITY;
44564
+ this.entityReturnState = S_ATTRIB_VALUE_QUOTED;
44565
+ return;
44566
+ case NL:
44567
+ case NL_LIKE:
44568
+ case TAB:
44569
+ this.text += `${chunk.slice(start, this.prevI)} `;
44570
+ start = this.i;
44571
+ break;
44572
+ case LESS:
44573
+ this.text += chunk.slice(start, this.prevI);
44574
+ this.fail("disallowed character.");
44575
+ return;
44576
+ case EOC:
44577
+ this.text += chunk.slice(start);
44578
+ return;
44579
+ }
44580
+ }
44581
+ sAttribValueClosed() {
44582
+ const c = this.getCodeNorm();
44583
+ if (isS(c)) this.state = S_ATTRIB;
44584
+ else if (c === GREATER) this.openTag();
44585
+ else if (c === FORWARD_SLASH) this.state = S_OPEN_TAG_SLASH;
44586
+ else if (isNameStartChar(c)) {
44587
+ this.fail("no whitespace between attributes.");
44588
+ this.unget();
44589
+ this.state = S_ATTRIB_NAME;
44590
+ } else this.fail("disallowed character in attribute name.");
44591
+ }
44592
+ sAttribValueUnquoted() {
44593
+ const c = this.captureTo(ATTRIB_VALUE_UNQUOTED_TERMINATOR);
44594
+ switch (c) {
44595
+ case AMP:
44596
+ this.state = S_ENTITY;
44597
+ this.entityReturnState = S_ATTRIB_VALUE_UNQUOTED;
44598
+ break;
44599
+ case LESS:
44600
+ this.fail("disallowed character.");
44601
+ break;
44602
+ case EOC: break;
44603
+ default:
44604
+ if (this.text.includes("]]>")) this.fail("the string \"]]>\" is disallowed in char data.");
44605
+ this.pushAttrib(this.name, this.text);
44606
+ this.name = this.text = "";
44607
+ if (c === GREATER) this.openTag();
44608
+ else this.state = S_ATTRIB;
44609
+ }
44610
+ }
44611
+ sCloseTag() {
44612
+ const c = this.captureNameChars();
44613
+ if (c === GREATER) this.closeTag();
44614
+ else if (isS(c)) this.state = S_CLOSE_TAG_SAW_WHITE;
44615
+ else if (c !== EOC) this.fail("disallowed character in closing tag.");
44616
+ }
44617
+ sCloseTagSawWhite() {
44618
+ switch (this.skipSpaces()) {
44619
+ case GREATER:
44620
+ this.closeTag();
44621
+ break;
44622
+ case EOC: break;
44623
+ default: this.fail("disallowed character in closing tag.");
44624
+ }
44625
+ }
44626
+ handleTextInRoot() {
44627
+ let { i: start, forbiddenState } = this;
44628
+ const { chunk, textHandler: handler } = this;
44629
+ scanLoop: while (true) switch (this.getCode()) {
44630
+ case LESS:
44631
+ this.state = S_OPEN_WAKA;
44632
+ if (handler !== void 0) {
44633
+ const { text } = this;
44634
+ const slice = chunk.slice(start, this.prevI);
44635
+ if (text.length !== 0) {
44636
+ handler(text + slice);
44637
+ this.text = "";
44638
+ } else if (slice.length !== 0) handler(slice);
44639
+ }
44640
+ forbiddenState = FORBIDDEN_START;
44641
+ break scanLoop;
44642
+ case AMP:
44643
+ this.state = S_ENTITY;
44644
+ this.entityReturnState = S_TEXT;
44645
+ if (handler !== void 0) this.text += chunk.slice(start, this.prevI);
44646
+ forbiddenState = FORBIDDEN_START;
44647
+ break scanLoop;
44648
+ case CLOSE_BRACKET:
44649
+ switch (forbiddenState) {
44650
+ case FORBIDDEN_START:
44651
+ forbiddenState = FORBIDDEN_BRACKET;
44652
+ break;
44653
+ case FORBIDDEN_BRACKET:
44654
+ forbiddenState = FORBIDDEN_BRACKET_BRACKET;
44655
+ break;
44656
+ case FORBIDDEN_BRACKET_BRACKET: break;
44657
+ default: throw new Error("impossible state");
44658
+ }
44659
+ break;
44660
+ case GREATER:
44661
+ if (forbiddenState === FORBIDDEN_BRACKET_BRACKET) this.fail("the string \"]]>\" is disallowed in char data.");
44662
+ forbiddenState = FORBIDDEN_START;
44663
+ break;
44664
+ case NL_LIKE:
44665
+ if (handler !== void 0) this.text += `${chunk.slice(start, this.prevI)}\n`;
44666
+ start = this.i;
44667
+ forbiddenState = FORBIDDEN_START;
44668
+ break;
44669
+ case EOC:
44670
+ if (handler !== void 0) this.text += chunk.slice(start);
44671
+ break scanLoop;
44672
+ default: forbiddenState = FORBIDDEN_START;
44673
+ }
44674
+ this.forbiddenState = forbiddenState;
44675
+ }
44676
+ handleTextOutsideRoot() {
44677
+ let { i: start } = this;
44678
+ const { chunk, textHandler: handler } = this;
44679
+ let nonSpace = false;
44680
+ outRootLoop: while (true) {
44681
+ const code = this.getCode();
44682
+ switch (code) {
44683
+ case LESS:
44684
+ this.state = S_OPEN_WAKA;
44685
+ if (handler !== void 0) {
44686
+ const { text } = this;
44687
+ const slice = chunk.slice(start, this.prevI);
44688
+ if (text.length !== 0) {
44689
+ handler(text + slice);
44690
+ this.text = "";
44691
+ } else if (slice.length !== 0) handler(slice);
44692
+ }
44693
+ break outRootLoop;
44694
+ case AMP:
44695
+ this.state = S_ENTITY;
44696
+ this.entityReturnState = S_TEXT;
44697
+ if (handler !== void 0) this.text += chunk.slice(start, this.prevI);
44698
+ nonSpace = true;
44699
+ break outRootLoop;
44700
+ case NL_LIKE:
44701
+ if (handler !== void 0) this.text += `${chunk.slice(start, this.prevI)}\n`;
44702
+ start = this.i;
44703
+ break;
44704
+ case EOC:
44705
+ if (handler !== void 0) this.text += chunk.slice(start);
44706
+ break outRootLoop;
44707
+ default: if (!isS(code)) nonSpace = true;
44708
+ }
44709
+ }
44710
+ if (!nonSpace) return;
44711
+ if (!this.sawRoot && !this.reportedTextBeforeRoot) {
44712
+ this.fail("text data outside of root node.");
44713
+ this.reportedTextBeforeRoot = true;
44714
+ }
44715
+ if (this.closedRoot && !this.reportedTextAfterRoot) {
44716
+ this.fail("text data outside of root node.");
44717
+ this.reportedTextAfterRoot = true;
44718
+ }
44719
+ }
44720
+ pushAttribNS(name, value) {
44721
+ var _a;
44722
+ const { prefix, local } = this.qname(name);
44723
+ const attr = {
44724
+ name,
44725
+ prefix,
44726
+ local,
44727
+ value
44728
+ };
44729
+ this.attribList.push(attr);
44730
+ (_a = this.attributeHandler) === null || _a === void 0 || _a.call(this, attr);
44731
+ if (prefix === "xmlns") {
44732
+ const trimmed = value.trim();
44733
+ if (this.currentXMLVersion === "1.0" && trimmed === "") this.fail("invalid attempt to undefine prefix in XML 1.0");
44734
+ this.topNS[local] = trimmed;
44735
+ nsPairCheck(this, local, trimmed);
44736
+ } else if (name === "xmlns") {
44737
+ const trimmed = value.trim();
44738
+ this.topNS[""] = trimmed;
44739
+ nsPairCheck(this, "", trimmed);
44740
+ }
44741
+ }
44742
+ pushAttribPlain(name, value) {
44743
+ var _a;
44744
+ const attr = {
44745
+ name,
44746
+ value
44747
+ };
44748
+ this.attribList.push(attr);
44749
+ (_a = this.attributeHandler) === null || _a === void 0 || _a.call(this, attr);
44750
+ }
44751
+ /**
44752
+ * End parsing. This performs final well-formedness checks and resets the
44753
+ * parser to a clean state.
44754
+ *
44755
+ * @returns this
44756
+ */
44757
+ end() {
44758
+ var _a, _b;
44759
+ if (!this.sawRoot) this.fail("document must contain a root element.");
44760
+ const { tags } = this;
44761
+ while (tags.length > 0) {
44762
+ const tag = tags.pop();
44763
+ this.fail(`unclosed tag: ${tag.name}`);
44764
+ }
44765
+ if (this.state !== S_BEGIN && this.state !== S_TEXT) this.fail("unexpected end.");
44766
+ const { text } = this;
44767
+ if (text.length !== 0) {
44768
+ (_a = this.textHandler) === null || _a === void 0 || _a.call(this, text);
44769
+ this.text = "";
44770
+ }
44771
+ this._closed = true;
44772
+ (_b = this.endHandler) === null || _b === void 0 || _b.call(this);
44773
+ this._init();
44774
+ return this;
44775
+ }
44776
+ /**
44777
+ * Resolve a namespace prefix.
44778
+ *
44779
+ * @param prefix The prefix to resolve.
44780
+ *
44781
+ * @returns The namespace URI or ``undefined`` if the prefix is not defined.
44782
+ */
44783
+ resolve(prefix) {
44784
+ var _a, _b;
44785
+ let uri = this.topNS[prefix];
44786
+ if (uri !== void 0) return uri;
44787
+ const { tags } = this;
44788
+ for (let index = tags.length - 1; index >= 0; index--) {
44789
+ uri = tags[index].ns[prefix];
44790
+ if (uri !== void 0) return uri;
44791
+ }
44792
+ uri = this.ns[prefix];
44793
+ if (uri !== void 0) return uri;
44794
+ return (_b = (_a = this.opt).resolvePrefix) === null || _b === void 0 ? void 0 : _b.call(_a, prefix);
44795
+ }
44796
+ /**
44797
+ * Parse a qname into its prefix and local name parts.
44798
+ *
44799
+ * @param name The name to parse
44800
+ *
44801
+ * @returns
44802
+ */
44803
+ qname(name) {
44804
+ const colon = name.indexOf(":");
44805
+ if (colon === -1) return {
44806
+ prefix: "",
44807
+ local: name
44808
+ };
44809
+ const local = name.slice(colon + 1);
44810
+ const prefix = name.slice(0, colon);
44811
+ if (prefix === "" || local === "" || local.includes(":")) this.fail(`malformed name: ${name}.`);
44812
+ return {
44813
+ prefix,
44814
+ local
44815
+ };
44816
+ }
44817
+ processAttribsNS() {
44818
+ var _a;
44819
+ const { attribList } = this;
44820
+ const tag = this.tag;
44821
+ {
44822
+ const { prefix, local } = this.qname(tag.name);
44823
+ tag.prefix = prefix;
44824
+ tag.local = local;
44825
+ const uri = tag.uri = (_a = this.resolve(prefix)) !== null && _a !== void 0 ? _a : "";
44826
+ if (prefix !== "") {
44827
+ if (prefix === "xmlns") this.fail("tags may not have \"xmlns\" as prefix.");
44828
+ if (uri === "") {
44829
+ this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
44830
+ tag.uri = prefix;
44831
+ }
44832
+ }
44833
+ }
44834
+ if (attribList.length === 0) return;
44835
+ const { attributes } = tag;
44836
+ const seen = /* @__PURE__ */ new Set();
44837
+ for (const attr of attribList) {
44838
+ const { name, prefix, local } = attr;
44839
+ let uri;
44840
+ let eqname;
44841
+ if (prefix === "") {
44842
+ uri = name === "xmlns" ? XMLNS_NAMESPACE : "";
44843
+ eqname = name;
44844
+ } else {
44845
+ uri = this.resolve(prefix);
44846
+ if (uri === void 0) {
44847
+ this.fail(`unbound namespace prefix: ${JSON.stringify(prefix)}.`);
44848
+ uri = prefix;
44849
+ }
44850
+ eqname = `{${uri}}${local}`;
44851
+ }
44852
+ if (seen.has(eqname)) this.fail(`duplicate attribute: ${eqname}.`);
44853
+ seen.add(eqname);
44854
+ attr.uri = uri;
44855
+ attributes[name] = attr;
44856
+ }
44857
+ this.attribList = [];
44858
+ }
44859
+ processAttribsPlain() {
44860
+ const { attribList } = this;
44861
+ const attributes = this.tag.attributes;
44862
+ for (const { name, value } of attribList) {
44863
+ if (attributes[name] !== void 0) this.fail(`duplicate attribute: ${name}.`);
44864
+ attributes[name] = value;
44865
+ }
44866
+ this.attribList = [];
44867
+ }
44868
+ /**
44869
+ * Handle a complete open tag. This parser code calls this once it has seen
44870
+ * the whole tag. This method checks for well-formeness and then emits
44871
+ * ``onopentag``.
44872
+ */
44873
+ openTag() {
44874
+ var _a;
44875
+ this.processAttribs();
44876
+ const { tags } = this;
44877
+ const tag = this.tag;
44878
+ tag.isSelfClosing = false;
44879
+ (_a = this.openTagHandler) === null || _a === void 0 || _a.call(this, tag);
44880
+ tags.push(tag);
44881
+ this.state = S_TEXT;
44882
+ this.name = "";
44883
+ }
44884
+ /**
44885
+ * Handle a complete self-closing tag. This parser code calls this once it has
44886
+ * seen the whole tag. This method checks for well-formeness and then emits
44887
+ * ``onopentag`` and ``onclosetag``.
44888
+ */
44889
+ openSelfClosingTag() {
44890
+ var _a, _b, _c;
44891
+ this.processAttribs();
44892
+ const { tags } = this;
44893
+ const tag = this.tag;
44894
+ tag.isSelfClosing = true;
44895
+ (_a = this.openTagHandler) === null || _a === void 0 || _a.call(this, tag);
44896
+ (_b = this.closeTagHandler) === null || _b === void 0 || _b.call(this, tag);
44897
+ if ((this.tag = (_c = tags[tags.length - 1]) !== null && _c !== void 0 ? _c : null) === null) this.closedRoot = true;
44898
+ this.state = S_TEXT;
44899
+ this.name = "";
44900
+ }
44901
+ /**
44902
+ * Handle a complete close tag. This parser code calls this once it has seen
44903
+ * the whole tag. This method checks for well-formeness and then emits
44904
+ * ``onclosetag``.
44905
+ */
44906
+ closeTag() {
44907
+ const { tags, name } = this;
44908
+ this.state = S_TEXT;
44909
+ this.name = "";
44910
+ if (name === "") {
44911
+ this.fail("weird empty close tag.");
44912
+ this.text += "</>";
44913
+ return;
44914
+ }
44915
+ const handler = this.closeTagHandler;
44916
+ let l = tags.length;
44917
+ while (l-- > 0) {
44918
+ const tag = this.tag = tags.pop();
44919
+ this.topNS = tag.ns;
44920
+ handler === null || handler === void 0 || handler(tag);
44921
+ if (tag.name === name) break;
44922
+ this.fail("unexpected close tag.");
44923
+ }
44924
+ if (l === 0) this.closedRoot = true;
44925
+ else if (l < 0) {
44926
+ this.fail(`unmatched closing tag: ${name}.`);
44927
+ this.text += `</${name}>`;
44928
+ }
44929
+ }
44930
+ /**
44931
+ * Resolves an entity. Makes any necessary well-formedness checks.
44932
+ *
44933
+ * @param entity The entity to resolve.
44934
+ *
44935
+ * @returns The parsed entity.
44936
+ */
44937
+ parseEntity(entity) {
44938
+ if (entity[0] !== "#") {
44939
+ const defined = this.ENTITIES[entity];
44940
+ if (defined !== void 0) return defined;
44941
+ this.fail(this.isName(entity) ? "undefined entity." : "disallowed character in entity name.");
44942
+ return `&${entity};`;
44943
+ }
44944
+ let num = NaN;
44945
+ if (entity[1] === "x" && /^#x[0-9a-f]+$/i.test(entity)) num = parseInt(entity.slice(2), 16);
44946
+ else if (/^#[0-9]+$/.test(entity)) num = parseInt(entity.slice(1), 10);
44947
+ if (!this.isChar(num)) {
44948
+ this.fail("malformed character entity.");
44949
+ return `&${entity};`;
44950
+ }
44951
+ return String.fromCodePoint(num);
44952
+ }
44953
+ };
44954
+ exports.SaxesParser = SaxesParser;
44955
+ })))();
44956
+ var ImageFormatError = class extends Error {
44957
+ status;
44958
+ constructor(status) {
44959
+ super(status);
44960
+ this.status = status;
44961
+ }
44962
+ };
44963
+ const refuse = (status = "unsupported") => {
44964
+ throw new ImageFormatError(status);
44965
+ };
44966
+ const size = (width, height) => {
44967
+ if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) refuse();
44968
+ width = Math.ceil(width);
44969
+ height = Math.ceil(height);
44970
+ if (width > 16384 || height > 16384 || width * height > 4e7) refuse("too-large");
44971
+ return {
44972
+ width: Math.ceil(width),
44973
+ height: Math.ceil(height)
44974
+ };
44975
+ };
44976
+ const ascii = (b, at, n) => String.fromCharCode(...b.subarray(at, at + n));
44977
+ const fragment = (value) => /^#[A-Za-z_][\w.:-]*$/u.test(value) ? value.slice(1) : refuse();
44978
+ const SVG = "http://www.w3.org/2000/svg";
44979
+ const XLINK = "http://www.w3.org/1999/xlink";
44980
+ const XMLNS = "http://www.w3.org/2000/xmlns/";
44981
+ const elements = new Set("svg g marker path rect circle ellipse line polyline polygon text tspan defs linearGradient radialGradient stop clipPath mask pattern use symbol title desc metadata style".split(" "));
44982
+ const properties = new Set("fill fill-opacity fill-rule stroke stroke-width stroke-opacity stroke-linecap stroke-linejoin stroke-miterlimit stroke-dasharray stroke-dashoffset opacity color font font-family font-size font-style font-weight font-variant text-anchor dominant-baseline alignment-baseline baseline-shift letter-spacing word-spacing text-decoration white-space display visibility clip-path clip-rule mask marker-start marker-mid marker-end paint-order vector-effect shape-rendering text-rendering stop-color stop-opacity transform transform-origin".split(" "));
44983
+ const functions = new Set("rgb rgba hsl hsla hwb lab lch oklab oklch color color-mix calc min max clamp var translate translateX translateY scale scaleX scaleY rotate skewX skewY matrix".toLowerCase().split(" "));
44984
+ function svgFormat(bytes) {
44985
+ if (bytes.length > 1048576) refuse("too-large");
44986
+ let source;
44987
+ try {
44988
+ source = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
44989
+ } catch {
44990
+ return refuse();
44991
+ }
44992
+ const nodes = [];
44993
+ const stack = [];
44994
+ const ids = /* @__PURE__ */ new Map();
44995
+ const stylesheetRefs = [];
44996
+ let dimensions;
44997
+ let cssBytes = 0, cssNodes = 0;
44998
+ let style = false;
44999
+ let css = "";
45000
+ const validateCss = (value, context, refs) => {
45001
+ cssBytes += value.length;
45002
+ if (cssBytes > 65536) refuse("too-large");
45003
+ if (value.includes("\\")) refuse();
45004
+ const ast = parse(value, {
45005
+ context,
45006
+ onParseError: () => refuse()
45007
+ });
45008
+ walk(ast, (node) => {
45009
+ if (++cssNodes > 1e4) refuse("too-large");
45010
+ if (node.type === "Atrule" || node.type === "Raw") refuse();
45011
+ if (node.type === "Url") refs.push(fragment(node.value));
45012
+ if (node.type === "Declaration" && !properties.has(node.property.toLowerCase()) && !/^--[\w-]+$/u.test(node.property)) refuse();
45013
+ if (node.type === "Function" && !functions.has(node.name.toLowerCase())) refuse();
45014
+ });
45015
+ };
45016
+ const parser = new import_saxes.SaxesParser({ xmlns: true });
45017
+ parser.on("error", () => refuse());
45018
+ parser.on("doctype", () => refuse());
45019
+ parser.on("processinginstruction", () => refuse());
45020
+ parser.on("opentag", (tag) => {
45021
+ if (style) refuse();
45022
+ if (nodes.length >= 1e4 || stack.length >= 64) refuse("too-large");
45023
+ if (tag.uri !== SVG || !elements.has(tag.local)) refuse();
45024
+ if (!nodes.length && tag.local !== "svg") refuse();
45025
+ const index = nodes.length;
45026
+ const current = {
45027
+ children: [],
45028
+ refs: []
45029
+ };
45030
+ nodes.push(current);
45031
+ if (stack.length) nodes[stack.at(-1)].children.push(index);
45032
+ stack.push(index);
45033
+ const attrs = {};
45034
+ for (const attribute of Object.values(tag.attributes)) {
45035
+ const name = attribute.local;
45036
+ const value = attribute.value;
45037
+ if (value.length > 65536) refuse("too-large");
45038
+ if (attribute.uri === XMLNS) {
45039
+ if (![SVG, XLINK].includes(value)) refuse();
45040
+ continue;
45041
+ }
45042
+ if (/^on/iu.test(name) || attribute.name === "xml:base" || name === "src" || name === "filter") refuse();
45043
+ if (attribute.uri && attribute.uri !== XLINK && attribute.uri !== "http://www.w3.org/XML/1998/namespace") refuse();
45044
+ if (name === "href") current.refs.push(fragment(value));
45045
+ else if (name === "style") validateCss(value, "declarationList", current.refs);
45046
+ else if (properties.has(name)) validateCss(value, "value", current.refs);
45047
+ else if (/url\s*\(|\\/iu.test(value)) refuse();
45048
+ if (name === "id") {
45049
+ if (!/^[A-Za-z_][\w.:-]*$/u.test(value) || ids.has(value)) refuse();
45050
+ ids.set(value, index);
45051
+ }
45052
+ attrs[name] = value;
45053
+ }
45054
+ if (index === 0) {
45055
+ const box = attrs["viewBox"]?.trim().split(/[\s,]+/u).map(Number);
45056
+ if (box && (box.length !== 4 || box.some((n) => !Number.isFinite(n)) || box[2] <= 0 || box[3] <= 0)) refuse();
45057
+ const length = (value) => {
45058
+ if (!value || /^\d+(?:\.\d+)?%$/u.test(value)) return void 0;
45059
+ const match = /^(\d+(?:\.\d+)?|\.\d+)(px|pt|pc|in|cm|mm)?$/u.exec(value);
45060
+ if (!match) return refuse();
45061
+ return Number(match[1]) * ({
45062
+ px: 1,
45063
+ pt: 96 / 72,
45064
+ pc: 16,
45065
+ in: 96,
45066
+ cm: 96 / 2.54,
45067
+ mm: 96 / 25.4
45068
+ }[match[2] ?? "px"] ?? 1);
45069
+ };
45070
+ let width = length(attrs["width"]), height = length(attrs["height"]);
45071
+ if (width !== void 0 && height === void 0 && box) height = width * box[3] / box[2];
45072
+ if (height !== void 0 && width === void 0 && box) width = height * box[2] / box[3];
45073
+ dimensions = size(width ?? box?.[2] ?? 300, height ?? box?.[3] ?? 150);
45074
+ }
45075
+ if (tag.local === "style") {
45076
+ style = true;
45077
+ css = "";
45078
+ }
45079
+ });
45080
+ const text = (value) => {
45081
+ if (style) {
45082
+ css += value;
45083
+ if (css.length > 65536) refuse("too-large");
45084
+ }
45085
+ };
45086
+ parser.on("text", text);
45087
+ parser.on("cdata", text);
45088
+ parser.on("closetag", (tag) => {
45089
+ if (tag.local === "style") {
45090
+ validateCss(css, "stylesheet", stylesheetRefs);
45091
+ style = false;
45092
+ }
45093
+ stack.pop();
45094
+ });
45095
+ try {
45096
+ parser.write(source).close();
45097
+ } catch (error) {
45098
+ if (error instanceof ImageFormatError) throw error;
45099
+ return refuse();
45100
+ }
45101
+ if (!dimensions || stack.length || !nodes.length) return refuse();
45102
+ const memo = /* @__PURE__ */ new Map();
45103
+ const expanded = (index, visiting) => {
45104
+ if (visiting.has(index)) return refuse();
45105
+ if (visiting.size >= 64) return refuse("too-large");
45106
+ const known = memo.get(index);
45107
+ if (known !== void 0) return known;
45108
+ visiting.add(index);
45109
+ const node = nodes[index];
45110
+ let cost = 1;
45111
+ for (const child of node.children) cost += expanded(child, visiting);
45112
+ for (const reference of node.refs) {
45113
+ const target = ids.get(reference) ?? refuse();
45114
+ cost += expanded(target, visiting);
45115
+ if (cost > 2e4) refuse("too-large");
45116
+ }
45117
+ visiting.delete(index);
45118
+ if (cost > 2e4) refuse("too-large");
45119
+ memo.set(index, cost);
45120
+ return cost;
45121
+ };
45122
+ let expandedNodes = expanded(0, /* @__PURE__ */ new Set());
45123
+ for (const reference of stylesheetRefs) {
45124
+ const target = ids.get(reference) ?? refuse();
45125
+ expandedNodes += expanded(target, /* @__PURE__ */ new Set()) * nodes.length;
45126
+ if (expandedNodes > 2e4) refuse("too-large");
45127
+ }
45128
+ return dimensions;
45129
+ }
45130
+ function inspectImage(bytes) {
45131
+ if (bytes.length > 26214400) return refuse("too-large");
45132
+ const b = bytes, n = b.length;
45133
+ const view = new DataView(b.buffer, b.byteOffset, b.byteLength);
45134
+ const format = (mime, extension, width, height) => ({
45135
+ mime,
45136
+ extension,
45137
+ ...size(width, height)
45138
+ });
45139
+ if (n >= 33 && ascii(b, 0, 8) === "‰PNG\r\n\n" && view.getUint32(8) === 13 && ascii(b, 12, 4) === "IHDR") return format("image/png", "png", view.getUint32(16), view.getUint32(20));
45140
+ if (n >= 4 && b[0] === 255 && b[1] === 216) {
45141
+ if (b[n - 2] !== 255 || b[n - 1] !== 217) return refuse();
45142
+ let at = 2, dimensions;
45143
+ while (at + 3 < n) {
45144
+ if (b[at++] !== 255) return refuse();
45145
+ while (at < n && b[at] === 255) at++;
45146
+ if (at + 2 >= n) return refuse();
45147
+ const marker = b[at++];
45148
+ if (marker === 0 || marker === 216 || marker === 217 || marker >= 208 && marker <= 215) return refuse();
45149
+ const length = view.getUint16(at);
45150
+ if (length < 2 || at + length > n - 2) return refuse();
45151
+ if (marker === 218) {
45152
+ const components = b[at + 2] ?? 0;
45153
+ if (components < 1 || components > 4 || length !== 6 + 2 * components || at + length >= n - 2) return refuse();
45154
+ return dimensions ?? refuse();
45155
+ }
45156
+ if (marker >= 192 && marker <= 207 && ![
45157
+ 196,
45158
+ 200,
45159
+ 204
45160
+ ].includes(marker)) {
45161
+ const components = b[at + 7] ?? 0;
45162
+ if (components < 1 || components > 4 || length !== 8 + 3 * components) return refuse();
45163
+ dimensions = format("image/jpeg", "jpg", view.getUint16(at + 5), view.getUint16(at + 3));
45164
+ }
45165
+ at += length;
45166
+ }
45167
+ return refuse();
45168
+ }
45169
+ if (n >= 14 && ["GIF87a", "GIF89a"].includes(ascii(b, 0, 6))) {
45170
+ const width = view.getUint16(6, true), height = view.getUint16(8, true);
45171
+ const result = format("image/gif", "gif", width, height);
45172
+ let at = 13 + (b[10] & 128 ? 3 * (1 << (b[10] & 7) + 1) : 0), frames = 0, pixels = 0;
45173
+ const blocks = () => {
45174
+ for (;;) {
45175
+ if (at >= n) return refuse();
45176
+ const length = b[at++];
45177
+ if (!length) return;
45178
+ at += length;
45179
+ if (at > n) return refuse();
45180
+ }
45181
+ };
45182
+ while (at < n) {
45183
+ const marker = b[at++];
45184
+ if (marker === 59) return frames && at === n ? result : refuse();
45185
+ if (marker === 33) {
45186
+ at++;
45187
+ blocks();
45188
+ continue;
45189
+ }
45190
+ if (marker !== 44 || at + 9 >= n) return refuse();
45191
+ const w = view.getUint16(at + 4, true), h = view.getUint16(at + 6, true);
45192
+ size(w, h);
45193
+ pixels += width * height;
45194
+ if (++frames > 256 || pixels > 4e7) return refuse("too-large");
45195
+ if (view.getUint16(at, true) + w > width || view.getUint16(at + 2, true) + h > height) return refuse();
45196
+ const packed = b[at + 8];
45197
+ at += 9;
45198
+ if (packed & 128) at += 3 * (1 << (packed & 7) + 1);
45199
+ const code = b[at++];
45200
+ if (code < 2 || code > 8) return refuse();
45201
+ blocks();
45202
+ }
45203
+ return refuse();
45204
+ }
45205
+ if (n >= 20 && ascii(b, 0, 4) === "RIFF" && ascii(b, 8, 4) === "WEBP") {
45206
+ if (view.getUint32(4, true) + 8 !== n) return refuse();
45207
+ let result, frames = 0, pixels = 0, image = false;
45208
+ const u24 = (at) => b[at] | b[at + 1] << 8 | b[at + 2] << 16;
45209
+ const payload = (tag, start, length) => {
45210
+ if (tag === "VP8 ") {
45211
+ if (length < 10 || ascii(b, start + 3, 3) !== "*") return refuse();
45212
+ return size(view.getUint16(start + 6, true) & 16383, view.getUint16(start + 8, true) & 16383);
45213
+ }
45214
+ if (tag === "VP8L") {
45215
+ if (length < 5 || b[start] !== 47) return refuse();
45216
+ const bits = view.getUint32(start + 1, true);
45217
+ return size(1 + (bits & 16383), 1 + (bits >>> 14 & 16383));
45218
+ }
45219
+ };
45220
+ for (let at = 12; at < n;) {
45221
+ if (at + 8 > n) return refuse();
45222
+ const tag = ascii(b, at, 4), length = view.getUint32(at + 4, true), start = at + 8;
45223
+ if (start + length > n) return refuse();
45224
+ if (tag === "VP8X") {
45225
+ if (length !== 10 || at !== 12) return refuse();
45226
+ result = format("image/webp", "webp", u24(start + 4) + 1, u24(start + 7) + 1);
45227
+ }
45228
+ const frame = payload(tag, start, length);
45229
+ if (frame) {
45230
+ result ??= format("image/webp", "webp", frame.width, frame.height);
45231
+ if (frame.width > result.width || frame.height > result.height) return refuse();
45232
+ image = true;
45233
+ }
45234
+ if (tag === "ANMF") {
45235
+ if (length < 24 || !result) return refuse();
45236
+ const w = u24(start + 6) + 1, h = u24(start + 9) + 1;
45237
+ size(w, h);
45238
+ pixels += result.width * result.height;
45239
+ if (++frames > 256 || pixels > 4e7) return refuse("too-large");
45240
+ if (u24(start) * 2 + w > result.width || u24(start + 3) * 2 + h > result.height) return refuse();
45241
+ let encoded = false;
45242
+ for (let part = start + 16; part < start + length;) {
45243
+ if (part + 8 > start + length) return refuse();
45244
+ const count = view.getUint32(part + 4, true);
45245
+ if (part + 8 + count > start + length) return refuse();
45246
+ const inner = payload(ascii(b, part, 4), part + 8, count);
45247
+ if (inner) {
45248
+ if (inner.width !== w || inner.height !== h) return refuse();
45249
+ encoded = true;
45250
+ }
45251
+ part += 8 + count + (count & 1);
45252
+ if (part > start + length) return refuse();
45253
+ }
45254
+ if (!encoded) return refuse();
45255
+ image = true;
45256
+ }
45257
+ at = start + length + (length & 1);
45258
+ if (at > n) return refuse();
45259
+ }
45260
+ return image && result ? result : refuse();
45261
+ }
45262
+ if (n && new TextDecoder().decode(b.subarray(0, Math.min(n, 512))).trimStart().startsWith("<")) return {
45263
+ mime: "image/svg+xml",
45264
+ extension: "svg",
45265
+ ...svgFormat(bytes)
45266
+ };
45267
+ return refuse();
45268
+ }
45269
+ const isMemoryImagePath = (path) => /\.(?:png|jpe?g|gif|webp|svg)$/iu.test(path);
45270
+ //#endregion
45271
+ //#region packages/core/src/memory/jail.ts
45272
+ var MemoryPathError = class extends Error {
45273
+ constructor(message) {
45274
+ super(message);
45275
+ this.name = "MemoryPathError";
45276
+ }
45277
+ };
45278
+ function toMemoryRelativePath(input) {
45279
+ if (typeof input !== "string" || input.trim().length === 0) throw new MemoryPathError("memory path must be a non-empty string");
45280
+ if (input.includes("\0")) throw new MemoryPathError("memory path must not contain NUL bytes");
45281
+ const slashed = input.replaceAll("\\", "/");
45282
+ if (slashed.startsWith("/") || /^[A-Za-z]:\//.test(slashed)) throw new MemoryPathError(`memory path must be relative: ${input}`);
45283
+ const segments = [];
45284
+ for (const segment of slashed.split("/")) {
45285
+ if (segment === "" || segment === ".") continue;
45286
+ if (segment === "..") throw new MemoryPathError(`memory path escapes the memory directory: ${input}`);
45287
+ if (segment.toLowerCase() === ".git") throw new MemoryPathError(`memory path is reserved: ${input}`);
45288
+ segments.push(segment);
45289
+ }
45290
+ if (segments.length === 0) throw new MemoryPathError(`memory path must name a file: ${input}`);
45291
+ return segments.join("/");
45292
+ }
45293
+ function toMemoryWritePath(input) {
45294
+ const relativePath = toMemoryRelativePath(input);
45295
+ const segments = relativePath.split("/");
45296
+ if (!(segments[segments.length - 1] ?? "").toLowerCase().endsWith(".md")) throw new MemoryPathError(`memory write path must end with .md: ${input}`);
45297
+ for (const segment of segments.slice(0, -1)) if (segment.startsWith(".")) throw new MemoryPathError(`memory write path must not contain dot-directories: ${input}`);
45298
+ return relativePath;
45299
+ }
45300
+ function resolveMemoryPath(root, input) {
45301
+ const relativePath = toMemoryRelativePath(input);
45302
+ const realRoot = realpathSync(root);
45303
+ const target = join(realRoot, relativePath);
45304
+ let probe = target;
45305
+ while (!existsSync(probe)) {
45306
+ const parent = dirname(probe);
45307
+ if (parent === probe) break;
45308
+ probe = parent;
45309
+ }
45310
+ const realProbe = realpathSync(probe);
45311
+ const fromRoot = relative(realRoot, realProbe);
45312
+ if (fromRoot.startsWith("..") || isAbsolute(fromRoot)) throw new MemoryPathError(`memory path escapes the memory directory through a link: ${input}`);
45313
+ return target;
45314
+ }
45315
+ //#endregion
45316
+ //#region packages/core/src/memory/image.ts
45317
+ const MAX_MEMORY_IMAGE_BYTES = 26214400;
45318
+ var MemoryImageError = class extends Error {
45319
+ code;
45320
+ constructor(code, message) {
45321
+ super(message);
45322
+ this.code = code;
45323
+ }
45324
+ };
45325
+ function readMemoryBytes(root, input, source, git, maxBytes = MAX_MEMORY_IMAGE_BYTES) {
45326
+ const path = toMemoryRelativePath(input);
45327
+ const fail = (status) => ({ status });
45328
+ let bytes;
45329
+ if (source === "worktree") {
45330
+ const target = resolveMemoryPath(root, path);
45331
+ let fd;
45332
+ try {
45333
+ fd = openSync(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0) | (constants.O_NONBLOCK ?? 0));
45334
+ } catch (error) {
45335
+ if ([
45336
+ "ENOENT",
45337
+ "ENOTDIR",
45338
+ "ELOOP"
45339
+ ].includes(error.code ?? "")) return fail("missing");
45340
+ throw error;
45341
+ }
45342
+ try {
45343
+ const realRoot = realpathSync(root);
45344
+ const current = realpathSync(resolveMemoryPath(root, path));
45345
+ toMemoryRelativePath(relative(realRoot, current));
45346
+ const before = fstatSync(fd);
45347
+ const latest = statSync(current);
45348
+ if (!before.isFile() || before.dev !== latest.dev || before.ino !== latest.ino) return fail("stale");
45349
+ if (before.size > maxBytes) return fail("too-large");
45350
+ bytes = Buffer.alloc(before.size + 1);
45351
+ let count = 0;
45352
+ while (count < bytes.length) {
45353
+ const read = readSync(fd, bytes, count, bytes.length - count, null);
45354
+ if (read === 0) break;
45355
+ count += read;
45356
+ }
45357
+ const after = fstatSync(fd);
45358
+ const finalPath = realpathSync(resolveMemoryPath(root, path));
45359
+ const final = statSync(finalPath);
45360
+ if (count > maxBytes) return fail("too-large");
45361
+ if (count !== before.size || after.size !== before.size || after.mtimeMs !== before.mtimeMs || after.ctimeMs !== before.ctimeMs || finalPath !== current || final.ino !== before.ino || final.dev !== before.dev) return fail("stale");
45362
+ bytes = bytes.subarray(0, count);
45363
+ } finally {
45364
+ closeSync(fd);
45365
+ }
45366
+ } else {
45367
+ if (source !== "index") {
45368
+ if (!/^[0-9a-f]{40}$/u.test(source)) throw new MemoryImageError("memory-unknown-commit", "Invalid image revision");
45369
+ if (git(root, [
45370
+ "cat-file",
45371
+ "-t",
45372
+ source
45373
+ ]).toString().trim() !== "commit") throw new MemoryImageError("memory-unknown-commit", "Unknown image commit");
45374
+ const branches = git(root, [
45375
+ "branch",
45376
+ "--contains",
45377
+ source,
45378
+ "--format=%(refname)"
45379
+ ]).toString().trim();
45380
+ let reachable = false;
45381
+ try {
45382
+ git(root, [
45383
+ "merge-base",
45384
+ "--is-ancestor",
45385
+ source,
45386
+ "HEAD"
45387
+ ]);
45388
+ reachable = true;
45389
+ } catch {}
45390
+ if (!reachable && !branches) throw new MemoryImageError("memory-unknown-commit", "Image commit is not reachable");
45391
+ }
45392
+ const listing = source === "index" ? git(root, [
45393
+ "--literal-pathspecs",
45394
+ "ls-files",
45395
+ "--stage",
45396
+ "-z",
45397
+ "--",
45398
+ path
45399
+ ]).toString() : git(root, [
45400
+ "--literal-pathspecs",
45401
+ "ls-tree",
45402
+ "-z",
45403
+ source,
45404
+ "--",
45405
+ path
45406
+ ]).toString();
45407
+ const entries = listing.split("\0").filter(Boolean);
45408
+ if (entries.length === 0) return fail("missing");
45409
+ if (entries.length !== 1) return fail("stale");
45410
+ const entry = entries[0];
45411
+ const tab = entry.indexOf(" ");
45412
+ const metadata = entry.slice(0, tab).split(" ");
45413
+ if (entry.slice(tab + 1) !== path || !["100644", "100755"].includes(metadata[0] ?? "")) return fail("unsupported");
45414
+ const oid = source === "index" ? metadata[1] : metadata[2];
45415
+ if (source === "index" && metadata[2] !== "0") return fail("stale");
45416
+ if (!oid || !/^[0-9a-f]{40}$/u.test(oid)) return fail("unsupported");
45417
+ const size = Number(git(root, [
45418
+ "cat-file",
45419
+ "-s",
45420
+ oid
45421
+ ]).toString());
45422
+ if (!Number.isSafeInteger(size) || size < 0 || size > maxBytes) return fail("too-large");
45423
+ bytes = git(root, [
45424
+ "cat-file",
45425
+ "blob",
45426
+ oid
45427
+ ], maxBytes + 1);
45428
+ if (source === "index" && git(root, [
45429
+ "--literal-pathspecs",
45430
+ "ls-files",
45431
+ "--stage",
45432
+ "-z",
45433
+ "--",
45434
+ path
45435
+ ]).toString() !== listing) return fail("stale");
45436
+ }
45437
+ return {
45438
+ status: "ready",
45439
+ bytes
45440
+ };
45441
+ }
45442
+ function readMemoryImage(root, input, source, git) {
45443
+ const fail = (status) => ({ image: {
45444
+ source,
45445
+ status
45446
+ } });
45447
+ const result = readMemoryBytes(root, input, source, git);
45448
+ const bytes = result.bytes;
45449
+ if (result.status !== "ready" || bytes === void 0) return fail(result.status);
45450
+ try {
45451
+ const format = inspectImage(bytes);
45452
+ return {
45453
+ image: {
45454
+ source,
45455
+ status: "ready",
45456
+ mime: format.mime,
45457
+ revision: createHash("sha256").update(bytes).digest("hex"),
45458
+ size: bytes.length,
45459
+ width: format.width,
45460
+ height: format.height
45461
+ },
45462
+ bytes
45463
+ };
45464
+ } catch (error) {
45465
+ if (error instanceof ImageFormatError) return fail(error.status);
45466
+ throw error;
45467
+ }
45468
+ }
45469
+ //#endregion
45470
+ //#region packages/core/src/memory/markdown.ts
45471
+ const MAX_MEMORY_MARKDOWN_BYTES = 4194304;
45472
+ const isMemoryMarkdown = (path) => /\.(?:md|markdown)$/iu.test(path);
45473
+ function readMemoryMarkdown(root, path, source, git, maxBytes = MAX_MEMORY_MARKDOWN_BYTES) {
45474
+ if (!isMemoryMarkdown(path)) return {
45475
+ source,
45476
+ status: "unsupported",
45477
+ body: ""
45478
+ };
45479
+ const { bytes, status } = readMemoryBytes(root, path, source, git, maxBytes);
45480
+ if (bytes === void 0) return {
45481
+ source,
45482
+ status,
45483
+ body: ""
45484
+ };
45485
+ try {
45486
+ if (bytes.includes(0)) return {
45487
+ source,
45488
+ status: "unsupported",
45489
+ body: ""
45490
+ };
45491
+ return {
45492
+ source,
45493
+ status: "ready",
45494
+ revision: createHash("sha256").update(bytes).digest("hex"),
45495
+ body: new TextDecoder("utf-8", { fatal: true }).decode(bytes)
45496
+ };
45497
+ } catch {
45498
+ return {
45499
+ source,
45500
+ status: "unsupported",
45501
+ body: ""
45502
+ };
45503
+ }
45504
+ }
45505
+ function memoryMarkdownImagePath(document, reference) {
45506
+ const invalid = () => {
45507
+ throw new MemoryImageError("memory-image-invalid", "Image reference must stay inside Memory");
45508
+ };
45509
+ if (!reference || /[\\\u0000-\u001f\u007f]/u.test(reference) || reference.startsWith("//")) invalid();
45510
+ let decoded;
45511
+ try {
45512
+ decoded = decodeURIComponent(reference.split(/[?#]/u)[0]);
45513
+ } catch {
45514
+ return invalid();
45515
+ }
45516
+ if (!decoded || /[\\:\u0000-\u001f\u007f]/u.test(decoded) || decoded.startsWith("//")) invalid();
45517
+ const segments = decoded.startsWith("/") ? [] : posix.dirname(toMemoryRelativePath(document)).split("/").filter((p) => p !== ".");
45518
+ for (const part of decoded.split("/")) {
45519
+ if (!part || part === ".") continue;
45520
+ if (part.toLowerCase() === ".git") invalid();
45521
+ if (part === "..") {
45522
+ if (segments.length === 0) invalid();
45523
+ segments.pop();
45524
+ } else segments.push(part);
45525
+ }
45526
+ return toMemoryRelativePath(segments.join("/"));
45527
+ }
45528
+ //#endregion
43066
45529
  //#region packages/core/src/memory/front-matter.ts
43067
45530
  function firstNonEmptyLine(text) {
43068
45531
  for (const line of text.split("\n")) {
@@ -43369,51 +45832,6 @@ function seedStandingFiles(root, options) {
43369
45832
  return written;
43370
45833
  }
43371
45834
  //#endregion
43372
- //#region packages/core/src/memory/jail.ts
43373
- var MemoryPathError = class extends Error {
43374
- constructor(message) {
43375
- super(message);
43376
- this.name = "MemoryPathError";
43377
- }
43378
- };
43379
- function toMemoryRelativePath(input) {
43380
- if (typeof input !== "string" || input.trim().length === 0) throw new MemoryPathError("memory path must be a non-empty string");
43381
- if (input.includes("\0")) throw new MemoryPathError("memory path must not contain NUL bytes");
43382
- const slashed = input.replaceAll("\\", "/");
43383
- if (slashed.startsWith("/") || /^[A-Za-z]:\//.test(slashed)) throw new MemoryPathError(`memory path must be relative: ${input}`);
43384
- const segments = [];
43385
- for (const segment of slashed.split("/")) {
43386
- if (segment === "" || segment === ".") continue;
43387
- if (segment === "..") throw new MemoryPathError(`memory path escapes the memory directory: ${input}`);
43388
- if (segment.toLowerCase() === ".git") throw new MemoryPathError(`memory path is reserved: ${input}`);
43389
- segments.push(segment);
43390
- }
43391
- if (segments.length === 0) throw new MemoryPathError(`memory path must name a file: ${input}`);
43392
- return segments.join("/");
43393
- }
43394
- function toMemoryWritePath(input) {
43395
- const relativePath = toMemoryRelativePath(input);
43396
- const segments = relativePath.split("/");
43397
- if (!(segments[segments.length - 1] ?? "").toLowerCase().endsWith(".md")) throw new MemoryPathError(`memory write path must end with .md: ${input}`);
43398
- for (const segment of segments.slice(0, -1)) if (segment.startsWith(".")) throw new MemoryPathError(`memory write path must not contain dot-directories: ${input}`);
43399
- return relativePath;
43400
- }
43401
- function resolveMemoryPath(root, input) {
43402
- const relativePath = toMemoryRelativePath(input);
43403
- const realRoot = realpathSync(root);
43404
- const target = join(realRoot, relativePath);
43405
- let probe = target;
43406
- while (!existsSync(probe)) {
43407
- const parent = dirname(probe);
43408
- if (parent === probe) break;
43409
- probe = parent;
43410
- }
43411
- const realProbe = realpathSync(probe);
43412
- const fromRoot = relative(realRoot, realProbe);
43413
- if (fromRoot.startsWith("..") || isAbsolute(fromRoot)) throw new MemoryPathError(`memory path escapes the memory directory through a link: ${input}`);
43414
- return target;
43415
- }
43416
- //#endregion
43417
45835
  //#region packages/core/src/memory/recovery.ts
43418
45836
  const SHA$1 = /^[0-9a-f]{40}$/u;
43419
45837
  const MAX_GIT_OUTPUT = 4194304;
@@ -44616,11 +47034,45 @@ function createMemoryAcceptance(options) {
44616
47034
  standing: standingUsage(root, registry.get(botSlug)?.standingLimits ?? DEFAULT_STANDING_LIMITS)
44617
47035
  };
44618
47036
  },
47037
+ markdownImageFile(botSlug, path, source, revision, reference) {
47038
+ const root = graphRepository(botSlug);
47039
+ const document = readMemoryMarkdown(root, path, source, run$1);
47040
+ if (document.status !== "ready") throw new MemoryImageError(`memory-image-${document.status}`, "Markdown is unavailable");
47041
+ if (document.revision !== revision) throw new MemoryImageError("memory-image-stale", "Markdown changed; refresh the view");
47042
+ const { image, bytes } = readMemoryImage(root, memoryMarkdownImagePath(path, reference), source, run$1);
47043
+ if (image.status !== "ready" || bytes === void 0) throw new MemoryImageError(`memory-image-${image.status}`, "Image is unavailable or cannot be previewed");
47044
+ if (readMemoryMarkdown(root, path, source, run$1).revision !== revision) throw new MemoryImageError("memory-image-stale", "Markdown changed; refresh the view");
47045
+ return bytes;
47046
+ },
47047
+ imageFile(botSlug, path, source, revision) {
47048
+ if (!/^[0-9a-f]{64}$/u.test(revision)) throw new MemoryImageError("memory-image-invalid", "Invalid image content revision");
47049
+ const { image, bytes } = readMemoryImage(graphRepository(botSlug), path, source, run$1);
47050
+ if (image.status !== "ready" || bytes === void 0) throw new MemoryImageError(`memory-image-${image.status}`, "Image is unavailable or cannot be previewed");
47051
+ if (image.revision !== revision) throw new MemoryImageError("memory-image-stale", "Image changed; refresh the view");
47052
+ return bytes;
47053
+ },
44619
47054
  readAccepted(botSlug, path) {
44620
47055
  const { root } = readRepository(botSlug);
44621
47056
  const relative = toMemoryRelativePath(path);
44622
47057
  const target = resolveMemoryPath(root, relative);
44623
47058
  if (!existsSync(target) || !statSync(target).isFile()) return void 0;
47059
+ if (isMemoryMarkdown(relative)) {
47060
+ const markdown = readMemoryMarkdown(root, relative, "worktree", run$1);
47061
+ return {
47062
+ path: relative,
47063
+ body: markdown.body,
47064
+ head: head(root),
47065
+ markdown,
47066
+ ...markdown.status === "ready" ? {} : { binary: true }
47067
+ };
47068
+ }
47069
+ if (isMemoryImagePath(relative)) return {
47070
+ path: relative,
47071
+ body: "",
47072
+ head: head(root),
47073
+ binary: true,
47074
+ image: readMemoryImage(root, relative, "worktree", run$1).image
47075
+ };
44624
47076
  if (statSync(target).size > MAX_DIFF_BYTES) return {
44625
47077
  path: relative,
44626
47078
  body: "",
@@ -44767,10 +47219,28 @@ function createMemoryAcceptance(options) {
44767
47219
  ...range
44768
47220
  ]).toString("utf8").split("\0").filter(Boolean);
44769
47221
  const files = [];
44770
- for (let index = 0; index < nameStatus.length; index += 2) files.push({
44771
- status: nameStatus[index] ?? "",
44772
- path: nameStatus[index + 1] ?? ""
44773
- });
47222
+ let markdownBudget = MAX_MEMORY_MARKDOWN_BYTES;
47223
+ const document = (path, source) => {
47224
+ const result = readMemoryMarkdown(root, path, source, run$1, markdownBudget);
47225
+ markdownBudget -= Buffer.byteLength(result.body, "utf8");
47226
+ return result;
47227
+ };
47228
+ for (let index = 0; index < nameStatus.length; index += 2) {
47229
+ const status = nameStatus[index] ?? "";
47230
+ const path = nameStatus[index + 1] ?? "";
47231
+ files.push({
47232
+ status,
47233
+ path,
47234
+ ...isMemoryMarkdown(path) ? { markdown: {
47235
+ ...status === "A" || firstParent === void 0 ? {} : { before: document(path, firstParent) },
47236
+ ...status === "D" ? {} : { after: document(path, sha) }
47237
+ } } : {},
47238
+ ...isMemoryImagePath(path) ? { images: {
47239
+ ...status === "A" || firstParent === void 0 ? {} : { before: readMemoryImage(root, path, firstParent, run$1).image },
47240
+ ...status === "D" ? {} : { after: readMemoryImage(root, path, sha, run$1).image }
47241
+ } } : {}
47242
+ });
47243
+ }
44774
47244
  return {
44775
47245
  sha,
44776
47246
  subject: output(root, [
@@ -44817,20 +47287,45 @@ function createMemoryAcceptance(options) {
44817
47287
  status: phases.some((entry) => entry.kind === "untracked" || entry.status === "A") ? "A" : phases.some((entry) => entry.status === "D") ? "D" : "M"
44818
47288
  } : phases.find((entry) => entry.kind === kind);
44819
47289
  if (change === void 0) throw new MemoryAcceptError("memory-invalid", "Memory working change no longer exists");
47290
+ const comparisonHead = head(root);
47291
+ const markdown = isMemoryMarkdown(relative) ? {
47292
+ ...change.status === "A" || kind === "untracked" ? {} : { before: readMemoryMarkdown(root, relative, kind === "unstaged" ? "index" : comparisonHead, run$1) },
47293
+ ...change.status === "D" ? {} : { after: readMemoryMarkdown(root, relative, kind === "staged" ? "index" : "worktree", run$1) }
47294
+ } : void 0;
47295
+ if (isMemoryImagePath(relative)) {
47296
+ const oldSource = kind === "unstaged" ? "index" : head(root);
47297
+ const newSource = kind === "staged" ? "index" : "worktree";
47298
+ return {
47299
+ ...change,
47300
+ diff: "",
47301
+ binary: true,
47302
+ images: {
47303
+ ...change.status === "A" || kind === "untracked" ? {} : { before: readMemoryImage(root, relative, oldSource, run$1).image },
47304
+ ...change.status === "D" ? {} : { after: readMemoryImage(root, relative, newSource, run$1).image }
47305
+ }
47306
+ };
47307
+ }
44820
47308
  if (kind !== "untracked" && !(kind === "current" && phases[0]?.kind === "untracked")) {
44821
47309
  const diff = output(root, [
44822
47310
  "diff",
44823
47311
  "--no-ext-diff",
44824
47312
  "--no-textconv",
44825
47313
  "--no-renames",
44826
- ...kind === "staged" ? ["--cached", "HEAD"] : kind === "current" ? ["HEAD"] : [],
47314
+ ...kind === "staged" ? ["--cached", comparisonHead] : kind === "current" ? [comparisonHead] : [],
44827
47315
  "--",
44828
47316
  relative
44829
47317
  ]);
47318
+ if (markdown !== void 0) {
47319
+ if (head(root) !== comparisonHead || Object.values(markdown).some((document) => {
47320
+ const next = readMemoryMarkdown(root, relative, document.source, run$1);
47321
+ return next.revision !== document.revision || next.status !== document.status;
47322
+ })) throw new MemoryImageError("memory-image-stale", "Markdown changed; refresh the view");
47323
+ }
44830
47324
  return {
44831
47325
  ...change,
44832
47326
  diff,
44833
- binary: /^Binary files .+ differ$/mu.test(diff)
47327
+ binary: /^Binary files .+ differ$/mu.test(diff),
47328
+ ...markdown === void 0 ? {} : { markdown }
44834
47329
  };
44835
47330
  }
44836
47331
  const target = resolveMemoryPath(root, relative);
@@ -44870,7 +47365,8 @@ function createMemoryAcceptance(options) {
44870
47365
  return {
44871
47366
  ...change,
44872
47367
  diff,
44873
- binary: false
47368
+ binary: false,
47369
+ ...markdown === void 0 ? {} : { markdown }
44874
47370
  };
44875
47371
  },
44876
47372
  recoveryHistory(botSlug) {
@@ -45625,6 +48121,8 @@ function createMemoryService(options) {
45625
48121
  abortTurn: (botSlug, sessionId, preserveObservation) => requireAcceptance().abortTurn(botSlug, sessionId, preserveObservation),
45626
48122
  snapshot: (botSlug) => requireAcceptance().snapshot(botSlug),
45627
48123
  readAccepted: (botSlug, path) => requireAcceptance().readAccepted(botSlug, path),
48124
+ markdownImageFile: (botSlug, path, source, revision, reference) => requireAcceptance().markdownImageFile(botSlug, path, source, revision, reference),
48125
+ imageFile: (botSlug, path, source, revision) => requireAcceptance().imageFile(botSlug, path, source, revision),
45628
48126
  history: (botSlug, limit) => requireAcceptance().history(botSlug, limit),
45629
48127
  diff: (botSlug, sha) => requireAcceptance().diff(botSlug, sha),
45630
48128
  gitGraph: (botSlug, offset) => requireAcceptance().gitGraph(botSlug, offset),
@@ -51446,6 +53944,32 @@ function createPersonaBotRegistry(options) {
51446
53944
  };
51447
53945
  }
51448
53946
  //#endregion
53947
+ //#region packages/core/src/channels/live-frames.ts
53948
+ function parseLiveFrame(block) {
53949
+ let event = "message";
53950
+ let id;
53951
+ const data = [];
53952
+ for (const line of block.split("\n")) {
53953
+ if (line.length === 0 || line.startsWith(":")) continue;
53954
+ const colon = line.indexOf(":");
53955
+ const field = colon < 0 ? line : line.slice(0, colon);
53956
+ const rest = colon < 0 ? "" : line.slice(colon + 1);
53957
+ const value = rest.startsWith(" ") ? rest.slice(1) : rest;
53958
+ if (field === "event") event = value;
53959
+ else if (field === "data") data.push(value);
53960
+ else if (field === "id") id = value;
53961
+ }
53962
+ if (data.length === 0) return void 0;
53963
+ return id === void 0 ? {
53964
+ event,
53965
+ data: data.join("\n")
53966
+ } : {
53967
+ event,
53968
+ data: data.join("\n"),
53969
+ id
53970
+ };
53971
+ }
53972
+ //#endregion
51449
53973
  //#region packages/core/src/bots/cli-live-error.ts
51450
53974
  var CliLiveError = class extends Error {
51451
53975
  code;
@@ -51461,10 +53985,64 @@ var CliLiveError = class extends Error {
51461
53985
  }
51462
53986
  };
51463
53987
  //#endregion
53988
+ //#region packages/core/src/bots/cli-inbox-watch.ts
53989
+ async function watchInbox(stream, read, seconds) {
53990
+ const response = await stream("/api/botharness/stream?scope=roster");
53991
+ if (!response.body || !response.headers.get("content-type")?.includes("text/event-stream")) throw new CliLiveError("host-query-unsupported", "The Host did not open the inbox event stream.");
53992
+ const reader = response.body.getReader();
53993
+ let elapsed = false;
53994
+ let invalidations = 0;
53995
+ let failure;
53996
+ const timer = setTimeout(() => {
53997
+ elapsed = true;
53998
+ reader.cancel().catch(() => {});
53999
+ }, seconds * 1e3);
54000
+ const consuming = (async () => {
54001
+ const decoder = new TextDecoder();
54002
+ let buffer = "";
54003
+ for (;;) {
54004
+ const { value, done } = await reader.read();
54005
+ if (done) {
54006
+ if (!elapsed) throw new CliLiveError("host-unreachable", "The inbox event stream ended before the observation completed.");
54007
+ return;
54008
+ }
54009
+ buffer += decoder.decode(value, { stream: true }).replace(/\r/g, "");
54010
+ let end;
54011
+ while ((end = buffer.indexOf("\n\n")) !== -1) {
54012
+ const frame = parseLiveFrame(buffer.slice(0, end));
54013
+ buffer = buffer.slice(end + 2);
54014
+ if (frame?.event === "human-attention/changed") invalidations++;
54015
+ }
54016
+ if (buffer.length > 1048576) throw new CliLiveError("host-query-unsupported", "The inbox event frame exceeds the supported size.");
54017
+ }
54018
+ })().catch((error) => {
54019
+ failure = error;
54020
+ });
54021
+ try {
54022
+ const initial = await read();
54023
+ await consuming;
54024
+ if (failure) throw failure;
54025
+ return {
54026
+ seconds,
54027
+ invalidations,
54028
+ initial,
54029
+ current: await read()
54030
+ };
54031
+ } finally {
54032
+ clearTimeout(timer);
54033
+ elapsed = true;
54034
+ await reader.cancel().catch(() => {});
54035
+ await consuming;
54036
+ reader.releaseLock();
54037
+ }
54038
+ }
54039
+ //#endregion
51464
54040
  //#region packages/core/src/bots/cli-inbox.ts
51465
54041
  const INBOX_OPTIONS = {
51466
54042
  category: { type: "string" },
54043
+ "watch-seconds": { type: "string" },
51467
54044
  channel: { type: "string" },
54045
+ request: { type: "string" },
51468
54046
  sort: { type: "string" },
51469
54047
  search: { type: "string" },
51470
54048
  unread: { type: "boolean" },
@@ -51482,6 +54060,14 @@ const INBOX_OPTIONS = {
51482
54060
  snoozed: { type: "boolean" }
51483
54061
  };
51484
54062
  const INBOX_COMMANDS = [
54063
+ {
54064
+ command: "grant-request-approve",
54065
+ description: "approve persistent read/write for one workspace request (needs --confirm)"
54066
+ },
54067
+ {
54068
+ command: "inbox-watch",
54069
+ description: "observe live inbox changes for a bounded time and return one JSON snapshot"
54070
+ },
51485
54071
  {
51486
54072
  command: "inbox",
51487
54073
  description: "list Human Inbox items by category, Bot or Channel"
@@ -51555,30 +54141,41 @@ const CATEGORIES = [
51555
54141
  "replies",
51556
54142
  "handled"
51557
54143
  ];
51558
- function usage$17(message) {
54144
+ function usage$18(message) {
51559
54145
  throw new CliLiveError("usage", message);
51560
54146
  }
51561
54147
  function isInboxCommand(command) {
51562
54148
  return INBOX_COMMANDS.some((entry) => entry.command === command) || INBOX_HOST_COMMANDS.some((entry) => entry === command);
51563
54149
  }
51564
54150
  function positionals(command, rest, count, name) {
51565
- if (rest.length !== count || rest.some((value) => !value.trim())) usage$17(count === 0 ? `${command} takes no positional arguments.` : `${command} needs ${name}.`);
54151
+ if (rest.length !== count || rest.some((value) => !value.trim())) usage$18(count === 0 ? `${command} takes no positional arguments.` : `${command} needs ${name}.`);
51566
54152
  return rest.map((value) => value.trim());
51567
54153
  }
51568
54154
  function required$4(value, flag, command) {
51569
54155
  const next = value?.trim();
51570
- if (!next) usage$17(`${command} requires --${flag}.`);
54156
+ if (!next) usage$18(`${command} requires --${flag}.`);
51571
54157
  return next;
51572
54158
  }
51573
54159
  function toggle(command, on, off, flags) {
51574
- if (on === true === (off === true)) usage$17(`${command} needs --${flags[0]} or --${flags[1]}, not both or neither.`);
54160
+ if (on === true === (off === true)) usage$18(`${command} needs --${flags[0]} or --${flags[1]}, not both or neither.`);
51575
54161
  return on === true;
51576
54162
  }
51577
54163
  function confirmed(command, values) {
51578
- if (values.confirm !== true) usage$17(`${command} is destructive; repeat it with --confirm, as the Web UI asks you to.`);
54164
+ if (values.confirm !== true) usage$18(`${command} is destructive; repeat it with --confirm, as the Web UI asks you to.`);
51579
54165
  }
51580
54166
  async function runInboxCommand(command, rest, values, connect) {
51581
- const call = prepare(command, rest, values);
54167
+ const call = prepare(command === "inbox-watch" ? "inbox" : command, rest, values);
54168
+ if (command === "inbox-watch") {
54169
+ const seconds = Number(values["watch-seconds"] ?? 10);
54170
+ if (!Number.isInteger(seconds) || seconds < 1 || seconds > 60) usage$18("--watch-seconds must be 1–60.");
54171
+ const host = await connect();
54172
+ if (!host.stream) throw new CliLiveError("host-query-unsupported", "This connection cannot watch live inbox changes.");
54173
+ return watchInbox(host.stream, async () => {
54174
+ const result = await host.rpc(call.method, call.args);
54175
+ if (call.args["queryVersion"] === 1 && result["queryVersion"] !== 1) throw new CliLiveError("host-query-unsupported", "Update the Host to use Activity query filters.");
54176
+ return result;
54177
+ }, seconds);
54178
+ }
51582
54179
  const { rpc } = await connect();
51583
54180
  const result = await rpc(call.method, call.args);
51584
54181
  if (call.args["queryVersion"] === 1 && result["queryVersion"] !== 1) throw new CliLiveError("host-query-unsupported", "Update the Host to use Activity search, unread filtering and mention ordering.");
@@ -51594,12 +54191,12 @@ function prepare(command, rest, values) {
51594
54191
  switch (command) {
51595
54192
  case "inbox": {
51596
54193
  positionals(command, rest, 0, "");
51597
- if (values.category !== void 0 && !CATEGORIES.includes(values.category)) usage$17(`--category must be one of ${CATEGORIES.join(", ")}.`);
51598
- if (values.sort !== void 0 && values.sort !== "newest" && values.sort !== "oldest" && !(values.sort === "mentions-first" && values.category === "replies")) usage$17("--sort must be newest, oldest, or mentions-first with --category replies.");
51599
- if (values.search !== void 0 && values.search.length > 200) usage$17("--search must be at most 200 characters.");
51600
- if (values.kind !== void 0 && values.kind !== "auto-rejection") usage$17("--kind must be auto-rejection.");
54194
+ if (values.category !== void 0 && !CATEGORIES.includes(values.category)) usage$18(`--category must be one of ${CATEGORIES.join(", ")}.`);
54195
+ if (values.sort !== void 0 && values.sort !== "newest" && values.sort !== "oldest" && !(values.sort === "mentions-first" && values.category === "replies")) usage$18("--sort must be newest, oldest, or mentions-first with --category replies.");
54196
+ if (values.search !== void 0 && values.search.length > 200) usage$18("--search must be at most 200 characters.");
54197
+ if (values.kind !== void 0 && values.kind !== "auto-rejection") usage$18("--kind must be auto-rejection.");
51601
54198
  const limit = values.limit === void 0 ? void 0 : Number(values.limit);
51602
- if (limit !== void 0 && (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)) usage$17("--limit must be 1–100.");
54199
+ if (limit !== void 0 && (!Number.isSafeInteger(limit) || limit < 1 || limit > 100)) usage$18("--limit must be 1–100.");
51603
54200
  return {
51604
54201
  method: "humanAttention",
51605
54202
  args: {
@@ -51619,7 +54216,7 @@ function prepare(command, rest, values) {
51619
54216
  }
51620
54217
  case "inbox-allow-once": {
51621
54218
  const [itemId] = positionals(command, rest, 1, "exactly one auto-rejection item id");
51622
- if (!itemId.startsWith("autoreject:")) usage$17("inbox-allow-once takes an auto-rejection item id (autoreject:…).");
54219
+ if (!itemId.startsWith("autoreject:")) usage$18("inbox-allow-once takes an auto-rejection item id (autoreject:…).");
51623
54220
  return {
51624
54221
  method: "toolAutoRejectionOverride",
51625
54222
  args: { itemId }
@@ -51629,7 +54226,7 @@ function prepare(command, rest, values) {
51629
54226
  positionals(command, rest, 0, "");
51630
54227
  return {
51631
54228
  method: "humanAttentionStatus",
51632
- args: {}
54229
+ args: { messageCounts: true }
51633
54230
  };
51634
54231
  case "inbox-dismiss": {
51635
54232
  const [itemId] = positionals(command, rest, 1, "exactly one inbox item id");
@@ -51643,11 +54240,11 @@ function prepare(command, rest, values) {
51643
54240
  }
51644
54241
  case "inbox-snooze": {
51645
54242
  const [itemId] = positionals(command, rest, 1, "exactly one inbox item id");
51646
- if (values.until !== void 0 === (values.clear === true)) usage$17("inbox-snooze needs --until <ISO time> or --clear, not both or neither.");
54243
+ if (values.until !== void 0 === (values.clear === true)) usage$18("inbox-snooze needs --until <ISO time> or --clear, not both or neither.");
51647
54244
  let until = null;
51648
54245
  if (values.until !== void 0) {
51649
54246
  const at = Date.parse(values.until.trim());
51650
- if (Number.isNaN(at)) usage$17("--until must be an ISO time such as 2026-10-15T09:00:00Z.");
54247
+ if (Number.isNaN(at)) usage$18("--until must be an ISO time such as 2026-10-15T09:00:00Z.");
51651
54248
  until = new Date(at).toISOString();
51652
54249
  }
51653
54250
  return {
@@ -51686,9 +54283,9 @@ function prepare(command, rest, values) {
51686
54283
  }
51687
54284
  case "channel-assign": {
51688
54285
  const [channelId] = positionals(command, rest, 1, "exactly one channel id");
51689
- if (values.section !== void 0 === (values.unsectioned === true)) usage$17("channel-assign needs --section <id> or --unsectioned, not both or neither.");
54286
+ if (values.section !== void 0 === (values.unsectioned === true)) usage$18("channel-assign needs --section <id> or --unsectioned, not both or neither.");
51690
54287
  const index = values.index === void 0 ? void 0 : Number(values.index);
51691
- if (index !== void 0 && (!Number.isSafeInteger(index) || index < 0)) usage$17("--index must be a nonnegative integer.");
54288
+ if (index !== void 0 && (!Number.isSafeInteger(index) || index < 0)) usage$18("--index must be a nonnegative integer.");
51692
54289
  return {
51693
54290
  method: "channelAssign",
51694
54291
  args: {
@@ -51753,6 +54350,20 @@ function prepare(command, rest, values) {
51753
54350
  }
51754
54351
  };
51755
54352
  }
54353
+ case "grant-request-approve": {
54354
+ const [slug] = positionals(command, rest, 1, "exactly one bot id");
54355
+ confirmed(command, values);
54356
+ return {
54357
+ method: "grantRequestApprove",
54358
+ args: {
54359
+ slug,
54360
+ channelId: required$4(values.channel, "channel", command),
54361
+ requestMessageId: required$4(values.request, "request", command),
54362
+ workspaceId: required$4(values.workspace, "workspace", command),
54363
+ acknowledgeReadWrite: true
54364
+ }
54365
+ };
54366
+ }
51756
54367
  case "grant-write-set": {
51757
54368
  const [slug] = positionals(command, rest, 1, "exactly one bot id");
51758
54369
  return {
@@ -51787,10 +54398,274 @@ function prepare(command, rest, values) {
51787
54398
  }
51788
54399
  };
51789
54400
  }
51790
- default: usage$17(`Unsupported inbox command ${command}.`);
54401
+ default: usage$18(`Unsupported inbox command ${command}.`);
51791
54402
  }
51792
54403
  }
51793
54404
  //#endregion
54405
+ //#region packages/core/src/bots/cli-window-zoom.ts
54406
+ const WINDOW_ZOOM_COMMANDS = [
54407
+ {
54408
+ command: "window-zoom-clients",
54409
+ description: "list active desktop window targets"
54410
+ },
54411
+ {
54412
+ command: "window-zoom-get",
54413
+ description: "read zoom from an explicit --client-id"
54414
+ },
54415
+ {
54416
+ command: "window-zoom-set",
54417
+ description: "set --zoom-level (-8..8), optionally --zoom-default, on an explicit Client"
54418
+ },
54419
+ {
54420
+ command: "window-zoom-reset",
54421
+ description: "restore the explicit Client window to its saved default zoom"
54422
+ }
54423
+ ];
54424
+ const WINDOW_ZOOM_OPTIONS = {
54425
+ "client-id": { type: "string" },
54426
+ "zoom-level": { type: "string" },
54427
+ "zoom-default": { type: "boolean" }
54428
+ };
54429
+ async function runWindowZoomCommand(command, rest, values, connect) {
54430
+ const list = command === "window-zoom-clients";
54431
+ const write = command === "window-zoom-set" || command === "window-zoom-reset";
54432
+ if (rest.length || (list ? !!values["client-id"] : !values["client-id"])) throw new CliLiveError("usage", "Select exactly one --client-id from window-zoom-clients.");
54433
+ if (write ? !values["expected-revision"] : !!values["expected-revision"]) throw new CliLiveError("usage", "Writes require --expected-revision from window-zoom-get.");
54434
+ let operation;
54435
+ if (command === "window-zoom-set") {
54436
+ const raw = values["zoom-level"];
54437
+ if (raw === void 0 || !/^-?[0-8]$/.test(raw)) throw new CliLiveError("usage", "Specify integer --zoom-level from -8 to 8.");
54438
+ operation = {
54439
+ type: values["zoom-default"] ? "default" : "set",
54440
+ level: Number(raw)
54441
+ };
54442
+ } else {
54443
+ if (values["zoom-level"] !== void 0 || values["zoom-default"]) throw new CliLiveError("usage", "Zoom level/default options require window-zoom-set.");
54444
+ if (command === "window-zoom-reset") operation = { type: "reset" };
54445
+ }
54446
+ const result = await (await connect()).http("/api/botharness/window-zoom-control", list ? void 0 : {
54447
+ action: "request",
54448
+ clientId: values["client-id"],
54449
+ ...write ? {
54450
+ operation,
54451
+ expectedRevision: values["expected-revision"]
54452
+ } : {}
54453
+ });
54454
+ return JSON.parse(new TextDecoder().decode(result.bytes));
54455
+ }
54456
+ //#endregion
54457
+ //#region packages/core/src/bots/cli-wallpaper.ts
54458
+ const WALLPAPER_COMMANDS = [
54459
+ {
54460
+ command: "wallpaper-get",
54461
+ description: "read the explicit Client local wallpaper metadata and revision"
54462
+ },
54463
+ {
54464
+ command: "wallpaper-import",
54465
+ description: "read --file on this CLI machine and import image/video media to --client-id with --expected-revision"
54466
+ },
54467
+ {
54468
+ command: "wallpaper-crop",
54469
+ description: "save {x,y,zoom} from --patch-stdin on --client-id with --expected-revision"
54470
+ },
54471
+ {
54472
+ command: "wallpaper-remove",
54473
+ description: "delete the shown wallpaper, or --wallpaper-item, from the library with --expected-revision"
54474
+ },
54475
+ {
54476
+ command: "wallpaper-select",
54477
+ description: "show library --wallpaper-item <id>, or none, on --client-id with --expected-revision"
54478
+ },
54479
+ {
54480
+ command: "wallpaper-rotation",
54481
+ description: "set {interval,shuffle} from --patch-stdin; interval is 0 or 60000/300000/900000/1800000/3600000 ms"
54482
+ }
54483
+ ];
54484
+ const WALLPAPER_OPTIONS = { "wallpaper-item": { type: "string" } };
54485
+ async function runWallpaperCommand(command, rest, values, io, connect) {
54486
+ if (rest.length || !values["client-id"]) throw new CliLiveError("usage", "Wallpaper commands require exactly one --client-id.");
54487
+ if (command !== "wallpaper-get" && !values["expected-revision"]) throw new CliLiveError("usage", "Read wallpaper-get and supply its --expected-revision.");
54488
+ if (command === "wallpaper-get" && (values["expected-revision"] || values.file || values["patch-stdin"])) throw new CliLiveError("usage", "wallpaper-get takes no write options.");
54489
+ if (values.file && command !== "wallpaper-import") throw new CliLiveError("usage", "--file requires wallpaper-import.");
54490
+ if (values["patch-stdin"] && ![
54491
+ "wallpaper-import",
54492
+ "wallpaper-crop",
54493
+ "wallpaper-rotation"
54494
+ ].includes(command)) throw new CliLiveError("usage", "--patch-stdin requires wallpaper-import, wallpaper-crop or wallpaper-rotation.");
54495
+ const item = values["wallpaper-item"];
54496
+ if (item !== void 0 && ![
54497
+ "wallpaper-crop",
54498
+ "wallpaper-remove",
54499
+ "wallpaper-select"
54500
+ ].includes(command)) throw new CliLiveError("usage", "--wallpaper-item requires wallpaper-crop, wallpaper-remove or wallpaper-select.");
54501
+ if (command === "wallpaper-select" && !item) throw new CliLiveError("usage", "wallpaper-select requires --wallpaper-item <id> from wallpaper-get, or none.");
54502
+ let crop;
54503
+ if (values["patch-stdin"]) try {
54504
+ crop = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
54505
+ } catch {
54506
+ throw new CliLiveError("usage", "Invalid crop JSON.");
54507
+ }
54508
+ if (command === "wallpaper-rotation") {
54509
+ const rotation = crop;
54510
+ if (!rotation || typeof rotation !== "object" || Array.isArray(rotation) || !Object.keys(rotation).length || Object.keys(rotation).some((key) => !["interval", "shuffle"].includes(key))) throw new CliLiveError("usage", "wallpaper-rotation requires --patch-stdin with interval and/or shuffle.");
54511
+ }
54512
+ if (command === "wallpaper-crop" && crop === void 0) throw new CliLiveError("usage", "wallpaper-crop requires --patch-stdin.");
54513
+ let bytes;
54514
+ if (command === "wallpaper-import") {
54515
+ if (!values.file) throw new CliLiveError("usage", "wallpaper-import requires --file on this CLI machine.");
54516
+ try {
54517
+ const path = resolve(values.file);
54518
+ const stat = statSync(path);
54519
+ if (!stat.isFile() || stat.size < 1 || stat.size > 104857600) throw new CliLiveError("wallpaper-size-invalid", "Media must be nonempty: images up to 20 MB and videos up to 100 MB; the Client verifies decoding.");
54520
+ bytes = readFileSync(path);
54521
+ if (bytes.length !== stat.size) throw new CliLiveError("wallpaper-file-changed", "The input file changed while reading it.");
54522
+ } catch (error) {
54523
+ if (error instanceof CliLiveError) throw error;
54524
+ throw new CliLiveError("wallpaper-file-unavailable", "Cannot read the input media on this CLI machine.");
54525
+ }
54526
+ }
54527
+ const host = await connect();
54528
+ const request = async (wallpaper) => {
54529
+ for (let attempt = 0;; attempt++) try {
54530
+ const reply = await host.http("/api/botharness/appearance-control", {
54531
+ action: "request",
54532
+ clientId: values["client-id"],
54533
+ ...values["expected-revision"] ? { expectedRevision: values["expected-revision"] } : {},
54534
+ wallpaper
54535
+ });
54536
+ return JSON.parse(new TextDecoder().decode(reply.bytes));
54537
+ } catch (error) {
54538
+ if (!(error instanceof CliLiveError) || error.code !== "appearance-client-unavailable" || attempt >= 20) throw error;
54539
+ await new Promise((resolve) => setTimeout(resolve, 50));
54540
+ }
54541
+ };
54542
+ if (command === "wallpaper-get") return request({ action: "read" });
54543
+ const target = item === void 0 ? {} : { item };
54544
+ if (command === "wallpaper-remove") return request({
54545
+ action: "remove",
54546
+ ...target
54547
+ });
54548
+ if (command === "wallpaper-crop") return request({
54549
+ action: "crop",
54550
+ crop,
54551
+ ...target
54552
+ });
54553
+ if (command === "wallpaper-select") return request({
54554
+ action: "select",
54555
+ ...item === "none" ? {} : target
54556
+ });
54557
+ if (command === "wallpaper-rotation") return request({
54558
+ action: "rotation",
54559
+ ...crop
54560
+ });
54561
+ const begin = await request({
54562
+ action: "begin",
54563
+ size: bytes.length
54564
+ });
54565
+ if (typeof begin.uploadId !== "string") throw new CliLiveError("host-protocol-error", "Client returned no upload receipt.");
54566
+ try {
54567
+ for (let offset = 0; offset < bytes.length; offset += 196608) {
54568
+ const chunk = bytes.subarray(offset, offset + 196608);
54569
+ if ((await request({
54570
+ action: "append",
54571
+ uploadId: begin.uploadId,
54572
+ offset,
54573
+ data: chunk.toString("base64")
54574
+ })).offset !== offset + chunk.length) throw new CliLiveError("host-protocol-error", "Client acknowledged a different upload offset.");
54575
+ }
54576
+ return await request({
54577
+ action: "commit",
54578
+ uploadId: begin.uploadId,
54579
+ ...crop === void 0 ? {} : { crop }
54580
+ });
54581
+ } catch (error) {
54582
+ await request({
54583
+ action: "cancel",
54584
+ uploadId: begin.uploadId
54585
+ }).catch(() => {});
54586
+ throw error;
54587
+ }
54588
+ }
54589
+ //#endregion
54590
+ //#region packages/core/src/bots/cli-appearance.ts
54591
+ const APPEARANCE_COMMANDS = [
54592
+ ...WALLPAPER_COMMANDS,
54593
+ {
54594
+ command: "appearance-clear-panels",
54595
+ description: "clear only --mode light/dark Panel overrides on an explicit Client with --expected-revision"
54596
+ },
54597
+ {
54598
+ command: "appearance-reset",
54599
+ description: "reset both modes and wallpaper on --client-id with --confirm-reset and both expected revisions"
54600
+ },
54601
+ {
54602
+ command: "appearance-targets",
54603
+ description: "list functional Panel appearance targets on an explicit --client-id"
54604
+ },
54605
+ {
54606
+ command: "appearance-clients",
54607
+ description: "list online Client targets for device-local DeepSeekBot appearance"
54608
+ },
54609
+ {
54610
+ command: "appearance-get",
54611
+ description: "read device-local appearance from an explicit --client-id"
54612
+ },
54613
+ {
54614
+ command: "appearance-set",
54615
+ description: "write --patch-stdin to an explicit --client-id with --expected-revision"
54616
+ }
54617
+ ];
54618
+ const APPEARANCE_OPTIONS = {
54619
+ ...WALLPAPER_OPTIONS,
54620
+ "client-id": { type: "string" },
54621
+ "confirm-reset": { type: "boolean" },
54622
+ "expected-wallpaper-revision": { type: "string" }
54623
+ };
54624
+ async function runAppearanceCommand(command, rest, values, io, connect) {
54625
+ if (command.startsWith("wallpaper-")) return runWallpaperCommand(command, rest, values, io, connect);
54626
+ if (rest.length || command !== "appearance-clients" && !values["client-id"]) throw new CliLiveError("usage", "Specify exactly one --client-id from appearance-clients.");
54627
+ if (command === "appearance-clients" && values["client-id"]) throw new CliLiveError("usage", "appearance-clients does not take a target.");
54628
+ if (command !== "appearance-reset" && (values["confirm-reset"] || values["expected-wallpaper-revision"])) throw new CliLiveError("usage", "Reset confirmation and wallpaper revision require appearance-reset.");
54629
+ let recovery;
54630
+ let patch;
54631
+ if (command === "appearance-reset") {
54632
+ if (!values["confirm-reset"] || !values["expected-revision"] || !values["expected-wallpaper-revision"] || values["patch-stdin"] || values.mode || values.file) throw new CliLiveError("usage", "appearance-reset requires --confirm-reset, --expected-revision and --expected-wallpaper-revision from the selected Client.");
54633
+ recovery = {
54634
+ action: "reset-all",
54635
+ confirmed: true,
54636
+ wallpaperRevision: values["expected-wallpaper-revision"]
54637
+ };
54638
+ } else if (command === "appearance-clear-panels") {
54639
+ if (!values["expected-revision"] || !["light", "dark"].includes(values.mode ?? "") || values["patch-stdin"] || values.file) throw new CliLiveError("usage", "appearance-clear-panels requires --mode light/dark and --expected-revision.");
54640
+ patch = {
54641
+ mode: values.mode,
54642
+ clearPanels: true
54643
+ };
54644
+ }
54645
+ if (command === "appearance-set") {
54646
+ if (!values["patch-stdin"] || !values["expected-revision"]) throw new CliLiveError("usage", "appearance-set needs --patch-stdin and --expected-revision from appearance-get.");
54647
+ try {
54648
+ patch = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
54649
+ } catch {
54650
+ throw new CliLiveError("usage", "Invalid appearance JSON on stdin.");
54651
+ }
54652
+ if (typeof patch !== "object" || patch === null || Array.isArray(patch)) throw new CliLiveError("usage", "Appearance patch must be an object.");
54653
+ } else if (!["appearance-clear-panels", "appearance-reset"].includes(command) && (values["patch-stdin"] || values["expected-revision"])) throw new CliLiveError("usage", "Write options require appearance-set.");
54654
+ const response = await (await connect()).http("/api/botharness/appearance-control", command === "appearance-clients" ? void 0 : {
54655
+ action: "request",
54656
+ clientId: values["client-id"],
54657
+ ...patch === void 0 ? {} : {
54658
+ patch,
54659
+ expectedRevision: values["expected-revision"]
54660
+ },
54661
+ ...recovery === void 0 ? {} : {
54662
+ recovery,
54663
+ expectedRevision: values["expected-revision"]
54664
+ }
54665
+ });
54666
+ return JSON.parse(new TextDecoder().decode(response.bytes));
54667
+ }
54668
+ //#endregion
51794
54669
  //#region packages/core/src/cloud/management.ts
51795
54670
  function parseCloudManagement(value) {
51796
54671
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new ClientError("INVALID_CLOUD_INPUT");
@@ -51910,22 +54785,22 @@ const BOT_TOOL_COMMANDS = [{
51910
54785
  command: "bot-tool",
51911
54786
  description: "run one Harness Bot tool as a Bot directly, without the model (args JSON from stdin)"
51912
54787
  }];
51913
- function usage$16(message) {
54788
+ function usage$17(message) {
51914
54789
  throw new CliLiveError("usage", message);
51915
54790
  }
51916
54791
  async function runBotToolCommand(command, rest, values, io, connect) {
51917
54792
  if (command === "bot-tools") {
51918
- if (rest.length !== 0) usage$16("bot-tools takes no positional arguments.");
54793
+ if (rest.length !== 0) usage$17("bot-tools takes no positional arguments.");
51919
54794
  return (await connect()).rpc("botTools", {});
51920
54795
  }
51921
- if (rest.length !== 2 || rest.some((value) => !value.trim())) usage$16("bot-tool needs a bot id and a tool name.");
54796
+ if (rest.length !== 2 || rest.some((value) => !value.trim())) usage$17("bot-tool needs a bot id and a tool name.");
51922
54797
  let args = {};
51923
54798
  if (values["args-stdin"] === true) try {
51924
54799
  const parsed = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
51925
54800
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("not an object");
51926
54801
  args = parsed;
51927
54802
  } catch {
51928
- usage$16("--args-stdin must be a JSON object of tool arguments.");
54803
+ usage$17("--args-stdin must be a JSON object of tool arguments.");
51929
54804
  }
51930
54805
  return (await connect()).rpc("botToolRun", {
51931
54806
  slug: rest[0].trim(),
@@ -52082,11 +54957,11 @@ const DIRECTIONS = /* @__PURE__ */ new Set([
52082
54957
  "around"
52083
54958
  ]);
52084
54959
  const MAX_AVATAR_BYTES = 98304;
52085
- function usage$15(message) {
54960
+ function usage$16(message) {
52086
54961
  throw new CliLiveError("usage", message);
52087
54962
  }
52088
54963
  function channelOperationKey(value) {
52089
- if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/u.test(value)) usage$15("--operation-key must be 8–128 letters, digits, dots, underscores, colons or hyphens, starting with a letter or digit.");
54964
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{7,127}$/u.test(value)) usage$16("--operation-key must be 8–128 letters, digits, dots, underscores, colons or hyphens, starting with a letter or digit.");
52090
54965
  return value;
52091
54966
  }
52092
54967
  function isChannelCommand(command) {
@@ -52095,12 +54970,12 @@ function isChannelCommand(command) {
52095
54970
  function integer$1(value, flag, min, max) {
52096
54971
  if (value === void 0) return void 0;
52097
54972
  const parsed = Number(value);
52098
- if (!/^\d+$/u.test(value.trim()) || !Number.isSafeInteger(parsed) || parsed < min || parsed > max) usage$15(`${flag} must be an integer from ${String(min)} to ${String(max)}.`);
54973
+ if (!/^\d+$/u.test(value.trim()) || !Number.isSafeInteger(parsed) || parsed < min || parsed > max) usage$16(`${flag} must be an integer from ${String(min)} to ${String(max)}.`);
52099
54974
  return parsed;
52100
54975
  }
52101
54976
  function required$3(value, flag) {
52102
54977
  const trimmed = value?.trim();
52103
- if (!trimmed) usage$15(`${flag} is required.`);
54978
+ if (!trimmed) usage$16(`${flag} is required.`);
52104
54979
  return trimmed;
52105
54980
  }
52106
54981
  function channelAvatarDataUrl(path) {
@@ -52108,9 +54983,9 @@ function channelAvatarDataUrl(path) {
52108
54983
  try {
52109
54984
  bytes = readFileSync(path);
52110
54985
  } catch {
52111
- usage$15("Cannot read --avatar-file.");
54986
+ usage$16("Cannot read --avatar-file.");
52112
54987
  }
52113
- if (bytes.length === 0 || bytes.length > MAX_AVATAR_BYTES) usage$15(`--avatar-file must be 1 to ${String(MAX_AVATAR_BYTES)} bytes.`);
54988
+ if (bytes.length === 0 || bytes.length > MAX_AVATAR_BYTES) usage$16(`--avatar-file must be 1 to ${String(MAX_AVATAR_BYTES)} bytes.`);
52114
54989
  return `data:image/${bytes.subarray(0, 8).equals(Buffer.from([
52115
54990
  137,
52116
54991
  80,
@@ -52120,26 +54995,26 @@ function channelAvatarDataUrl(path) {
52120
54995
  10,
52121
54996
  26,
52122
54997
  10
52123
- ])) ? "png" : bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255 ? "jpeg" : bytes.toString("ascii", 0, 4) === "RIFF" && bytes.toString("ascii", 8, 12) === "WEBP" ? "webp" : usage$15("--avatar-file must be a PNG, JPEG or WebP image.")};base64,${bytes.toString("base64")}`;
54998
+ ])) ? "png" : bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255 ? "jpeg" : bytes.toString("ascii", 0, 4) === "RIFF" && bytes.toString("ascii", 8, 12) === "WEBP" ? "webp" : usage$16("--avatar-file must be a PNG, JPEG or WebP image.")};base64,${bytes.toString("base64")}`;
52124
54999
  }
52125
55000
  async function purgeToken(io) {
52126
55001
  let input;
52127
55002
  try {
52128
55003
  input = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
52129
55004
  } catch {
52130
- usage$15("Confirmation stdin must be JSON with the token from channel-purge-preview.");
55005
+ usage$16("Confirmation stdin must be JSON with the token from channel-purge-preview.");
52131
55006
  }
52132
- if (typeof input !== "object" || input === null || !("token" in input) || typeof input.token !== "string" || !input.token.trim() || input.token.length > 512) usage$15("Confirmation stdin must contain the token string from channel-purge-preview.");
55007
+ if (typeof input !== "object" || input === null || !("token" in input) || typeof input.token !== "string" || !input.token.trim() || input.token.length > 512) usage$16("Confirmation stdin must contain the token string from channel-purge-preview.");
52133
55008
  return input.token;
52134
55009
  }
52135
55010
  async function runChannelCommand(command, rest, input, io, connect) {
52136
55011
  const values = input;
52137
55012
  const noTarget = command === "channel-history" || command === "channel-mark-all-read" || command === "channel-unread";
52138
- if (rest.length !== (noTarget ? 0 : 1)) usage$15(`${command} ${noTarget ? "takes no positional arguments" : "needs exactly one Channel ID"}.`);
55013
+ if (rest.length !== (noTarget ? 0 : 1)) usage$16(`${command} ${noTarget ? "takes no positional arguments" : "needs exactly one Channel ID"}.`);
52139
55014
  const channelId = rest[0]?.trim() ?? "";
52140
- if (!noTarget && !channelId) usage$15(`${command} requires a nonempty Channel ID.`);
55015
+ if (!noTarget && !channelId) usage$16(`${command} requires a nonempty Channel ID.`);
52141
55016
  const seconds = values.timeout === void 0 ? 120 : Number(values.timeout);
52142
- if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 600) usage$15("--timeout must be between 0 and 600 seconds.");
55017
+ if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 600) usage$16("--timeout must be between 0 and 600 seconds.");
52143
55018
  let args = { channelId };
52144
55019
  let method;
52145
55020
  switch (command) {
@@ -52149,7 +55024,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52149
55024
  case "channel-media-target":
52150
55025
  case "channel-media-download":
52151
55026
  method = "channelMediaTarget";
52152
- if (values["source-event"]?.length !== 1) usage$15("--source-event must identify exactly one Source Event.");
55027
+ if (values["source-event"]?.length !== 1) usage$16("--source-event must identify exactly one Source Event.");
52153
55028
  args.sourceEventId = required$3(values["source-event"][0], "--source-event");
52154
55029
  args.attachmentId = required$3(values.attachment, "--attachment");
52155
55030
  if (command === "channel-media-download") required$3(values.out, "--out");
@@ -52160,7 +55035,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52160
55035
  break;
52161
55036
  case "group-avatar-set":
52162
55037
  method = "channelGroupAvatarSet";
52163
- if (values["avatar-file"] === void 0 === (values.clear !== true)) usage$15("group-avatar-set needs exactly one of --avatar-file <path> or --clear.");
55038
+ if (values["avatar-file"] === void 0 === (values.clear !== true)) usage$16("group-avatar-set needs exactly one of --avatar-file <path> or --clear.");
52164
55039
  args.avatar = values.clear === true ? null : channelAvatarDataUrl(values["avatar-file"]);
52165
55040
  break;
52166
55041
  case "group-invite":
@@ -52175,7 +55050,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52175
55050
  break;
52176
55051
  case "group-join-decide":
52177
55052
  method = "channelGroupJoinDecide";
52178
- if (values.accept === values.decline) usage$15("group-join-decide needs exactly one of --accept or --decline.");
55053
+ if (values.accept === values.decline) usage$16("group-join-decide needs exactly one of --accept or --decline.");
52179
55054
  args.requestId = required$3(values.request, "--request");
52180
55055
  args.accept = values.accept === true;
52181
55056
  break;
@@ -52185,7 +55060,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52185
55060
  break;
52186
55061
  case "group-send-review":
52187
55062
  method = "channelGroupSendReview";
52188
- if (values.accept && values.off) usage$15("Choose --accept or --off");
55063
+ if (values.accept && values.off) usage$16("Choose --accept or --off");
52189
55064
  if (values.accept || values.off) args.enabled = values.accept === true;
52190
55065
  break;
52191
55066
  case "group-wake-policies":
@@ -52194,7 +55069,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52194
55069
  case "group-wake-set": {
52195
55070
  method = "channelGroupWakeSet";
52196
55071
  const mode = values.mode ?? (values.inherit === true ? "digest" : void 0);
52197
- if (mode === void 0 || !WAKE_MODES.has(mode)) usage$15("--mode must be all, mentions, digest or silent, unless --inherit resets it.");
55072
+ if (mode === void 0 || !WAKE_MODES.has(mode)) usage$16("--mode must be all, mentions, digest or silent, unless --inherit resets it.");
52198
55073
  args = {
52199
55074
  channelId,
52200
55075
  botSlug: required$3(values.bot, "--bot"),
@@ -52207,7 +55082,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52207
55082
  }
52208
55083
  case "group-delete":
52209
55084
  method = "channelGroupDelete";
52210
- if (values.confirm !== true) usage$15("Deleting a group removes it for every member. Pass --confirm to delete it.");
55085
+ if (values.confirm !== true) usage$16("Deleting a group removes it for every member. Pass --confirm to delete it.");
52211
55086
  break;
52212
55087
  case "channel-history":
52213
55088
  method = "channelHistory";
@@ -52215,7 +55090,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52215
55090
  break;
52216
55091
  case "channel-history-sources":
52217
55092
  method = "channelHistorySources";
52218
- if (values.before !== void 0 && !/^\d+$/u.test(values.before)) usage$15("--before must be the numeric cursor from the previous page.");
55093
+ if (values.before !== void 0 && !/^\d+$/u.test(values.before)) usage$16("--before must be the numeric cursor from the previous page.");
52219
55094
  if (values.before !== void 0) args.before = values.before;
52220
55095
  break;
52221
55096
  case "channel-journal": {
@@ -52233,8 +55108,8 @@ async function runChannelCommand(command, rest, input, io, connect) {
52233
55108
  }
52234
55109
  case "channel-timeline": {
52235
55110
  method = "channelTimeline";
52236
- if (values.direction !== void 0 && !DIRECTIONS.has(values.direction)) usage$15("--direction must be older, newer or around.");
52237
- if (values.direction === "around" && !values.around?.trim()) usage$15("--direction around needs --around <message-id>.");
55111
+ if (values.direction !== void 0 && !DIRECTIONS.has(values.direction)) usage$16("--direction must be older, newer or around.");
55112
+ if (values.direction === "around" && !values.around?.trim()) usage$16("--direction around needs --around <message-id>.");
52238
55113
  const limit = integer$1(values.limit, "--limit", 1, 200);
52239
55114
  const olderLimit = integer$1(values["older-limit"], "--older-limit", 0, 200);
52240
55115
  const newerLimit = integer$1(values["newer-limit"], "--newer-limit", 0, 200);
@@ -52291,11 +55166,11 @@ async function runChannelCommand(command, rest, input, io, connect) {
52291
55166
  case "channel-purge-confirm": {
52292
55167
  method = command === "channel-purge-preview" ? "channelPurgePreview" : "channelPurgeConfirm";
52293
55168
  const sourceEventIds = (values["source-event"] ?? []).map((id) => id.trim()).filter(Boolean);
52294
- if (sourceEventIds.length === 0 || sourceEventIds.length > 100) usage$15(`${command} needs 1 to 100 --source-event <id> flags.`);
55169
+ if (sourceEventIds.length === 0 || sourceEventIds.length > 100) usage$16(`${command} needs 1 to 100 --source-event <id> flags.`);
52295
55170
  args.sourceEventIds = [...new Set(sourceEventIds)];
52296
55171
  if (command === "channel-purge-confirm") {
52297
- if (values.confirm !== true) usage$15("Purging permanently removes these Source Events and their content. Pass --confirm.");
52298
- if (values["confirmation-stdin"] !== true) usage$15("channel-purge-confirm reads the preview token with --confirmation-stdin.");
55172
+ if (values.confirm !== true) usage$16("Purging permanently removes these Source Events and their content. Pass --confirm.");
55173
+ if (values["confirmation-stdin"] !== true) usage$16("channel-purge-confirm reads the preview token with --confirmation-stdin.");
52299
55174
  args.token = await purgeToken(io);
52300
55175
  }
52301
55176
  break;
@@ -52303,7 +55178,7 @@ async function runChannelCommand(command, rest, input, io, connect) {
52303
55178
  }
52304
55179
  if (values["expected-channel"] !== void 0 && command !== "group-invite") {
52305
55180
  const fingerprint = required$3(values["expected-channel"], "--expected-channel");
52306
- if (!/^[a-f0-9]{64}$/u.test(fingerprint)) usage$15("--expected-channel must be the observed Channel fingerprint.");
55181
+ if (!/^[a-f0-9]{64}$/u.test(fingerprint)) usage$16("--expected-channel must be the observed Channel fingerprint.");
52307
55182
  args.expectedChannel = fingerprint;
52308
55183
  }
52309
55184
  const host = await connect(values, io, AbortSignal.timeout(Math.ceil(seconds * 1e3)));
@@ -52429,7 +55304,7 @@ const CONFIRMED = [
52429
55304
  function isBrowserComputerCommand(command) {
52430
55305
  return BROWSER_COMPUTER_COMMANDS.some((entry) => entry.command === command);
52431
55306
  }
52432
- function usage$14(message) {
55307
+ function usage$15(message) {
52433
55308
  throw new CliLiveError("usage", message);
52434
55309
  }
52435
55310
  const absolute = (value) => value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value);
@@ -52514,34 +55389,34 @@ function probeSignaling(socket, deadlineMs = PROBE_DEADLINE_MS) {
52514
55389
  function count$1(value, flag, max) {
52515
55390
  if (value === void 0) return void 0;
52516
55391
  const parsed = Number(value);
52517
- if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > max) usage$14(`${flag} must be an integer from 0 to ${String(max)}.`);
55392
+ if (!Number.isSafeInteger(parsed) || parsed < 0 || parsed > max) usage$15(`${flag} must be an integer from 0 to ${String(max)}.`);
52518
55393
  return parsed;
52519
55394
  }
52520
55395
  async function runBrowserComputerCommand(command, rest, values, io, connect) {
52521
55396
  const positionals = BOT_COMMANDS.includes(command) || FILE_COMMANDS.includes(command) ? 1 : 0;
52522
- if (rest.length !== positionals || rest.some((value) => !value.trim())) usage$14(positionals === 0 ? `${command} takes no positional arguments.` : FILE_COMMANDS.includes(command) ? `${command} needs exactly one ${command === "computer-upload" ? "local file" : "archive name"}.` : `${command} needs exactly one bot id.`);
55397
+ if (rest.length !== positionals || rest.some((value) => !value.trim())) usage$15(positionals === 0 ? `${command} takes no positional arguments.` : FILE_COMMANDS.includes(command) ? `${command} needs exactly one ${command === "computer-upload" ? "local file" : "archive name"}.` : `${command} needs exactly one bot id.`);
52523
55398
  const target = rest[0]?.trim() ?? "";
52524
- if (CONFIRMED.includes(command) && values.confirm !== true) usage$14(command === "computer-import" ? "computer-import replaces Container Computer data with the archive. Pass --confirm." : `${command} installs system packages on the Host. Pass --confirm.`);
52525
- if (values.out !== void 0 && !absolute(values.out)) usage$14("--out must be an absolute file path.");
52526
- if (values.dir !== void 0 && !absolute(values.dir)) usage$14("--dir must be an absolute folder.");
55399
+ if (CONFIRMED.includes(command) && values.confirm !== true) usage$15(command === "computer-import" ? "computer-import replaces Container Computer data with the archive. Pass --confirm." : `${command} installs system packages on the Host. Pass --confirm.`);
55400
+ if (values.out !== void 0 && !absolute(values.out)) usage$15("--out must be an absolute file path.");
55401
+ if (values.dir !== void 0 && !absolute(values.dir)) usage$15("--dir must be an absolute folder.");
52527
55402
  const viewer = values.viewer?.trim() ?? "";
52528
- if (command === "browser-webrtc" && !/^[a-f0-9]{24}$/u.test(viewer)) usage$14("browser-webrtc needs --viewer <id>, the id in the Container Browser viewer path /botharness-browser/viewer/<id>/.");
52529
- if (command === "browser-profile-set" && !values.profile?.trim()) usage$14("browser-profile-set requires --profile <name> or --profile default.");
55403
+ if (command === "browser-webrtc" && !/^[a-f0-9]{24}$/u.test(viewer)) usage$15("browser-webrtc needs --viewer <id>, the id in the Container Browser viewer path /botharness-browser/viewer/<id>/.");
55404
+ if (command === "browser-profile-set" && !values.profile?.trim()) usage$15("browser-profile-set requires --profile <name> or --profile default.");
52530
55405
  const packages = (values.package ?? []).map((name) => name.trim()).filter(Boolean);
52531
- if (command === "browser-install-packages" && packages.length === 0) usage$14("browser-install-packages needs --package for each library the Browser reported.");
52532
- if (command === "computer-import" && !archiveName(target)) usage$14("computer-import needs an archive name from computer-exports, such as computer.tar.");
55406
+ if (command === "browser-install-packages" && packages.length === 0) usage$15("browser-install-packages needs --package for each library the Browser reported.");
55407
+ if (command === "computer-import" && !archiveName(target)) usage$15("computer-import needs an archive name from computer-exports, such as computer.tar.");
52533
55408
  let upload;
52534
55409
  if (command === "computer-upload") {
52535
- if (!absolute(target)) usage$14("computer-upload needs an absolute local file path.");
55410
+ if (!absolute(target)) usage$15("computer-upload needs an absolute local file path.");
52536
55411
  const name = values.name?.trim() || basename(target);
52537
- if (!archiveName(name)) usage$14("The uploaded archive name must end in .tar, such as computer.tar.");
55412
+ if (!archiveName(name)) usage$15("The uploaded archive name must end in .tar, such as computer.tar.");
52538
55413
  let bytes;
52539
55414
  try {
52540
55415
  const info = statSync(target);
52541
55416
  if (!info.isFile()) throw new Error("not a file");
52542
55417
  bytes = info.size;
52543
55418
  } catch {
52544
- usage$14(`Cannot read ${target}.`);
55419
+ usage$15(`Cannot read ${target}.`);
52545
55420
  }
52546
55421
  upload = {
52547
55422
  path: target,
@@ -52551,9 +55426,9 @@ async function runBrowserComputerCommand(command, rest, values, io, connect) {
52551
55426
  }
52552
55427
  let token = "";
52553
55428
  if (command === "browser-takeover-recording") {
52554
- if (values["token-stdin"] !== true) usage$14("browser-takeover-recording requires --token-stdin.");
55429
+ if (values["token-stdin"] !== true) usage$15("browser-takeover-recording requires --token-stdin.");
52555
55430
  token = (await (io.readStdin?.() ?? Promise.resolve(""))).trim();
52556
- if (!/^[A-Za-z0-9_-]{1,128}$/u.test(token)) usage$14("stdin must hold the takeover token from the takeover link.");
55431
+ if (!/^[A-Za-z0-9_-]{1,128}$/u.test(token)) usage$15("stdin must hold the takeover token from the takeover link.");
52557
55432
  }
52558
55433
  const since = count$1(values.since, "--since", Number.MAX_SAFE_INTEGER);
52559
55434
  const limit = count$1(values.limit, "--limit", 1e3);
@@ -52745,7 +55620,7 @@ const states = [
52745
55620
  "failed"
52746
55621
  ];
52747
55622
  const record$5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
52748
- function usage$13(message) {
55623
+ function usage$14(message) {
52749
55624
  throw new CliLiveError("usage", message);
52750
55625
  }
52751
55626
  function invalidResponse() {
@@ -52759,36 +55634,36 @@ async function prepareImAuthorization(command, rest, values, io) {
52759
55634
  "im-credentials",
52760
55635
  "im-verify"
52761
55636
  ].includes(command)) throw new CliLiveError("secret-in-argv", "IM应用授权 inputs must arrive through stdin.");
52762
- usage$13(`${command} requires ${count} positional arguments.`);
55637
+ usage$14(`${command} requires ${count} positional arguments.`);
52763
55638
  }
52764
55639
  const target = rest[0]?.trim() ?? "";
52765
55640
  if (command === "im-authorize") {
52766
- if (!["feishu", "weixin"].includes(target)) usage$13("Choose feishu or weixin.");
52767
- } else if (count === 1 && !/^[A-Za-z0-9_-]{1,128}$/u.test(target)) usage$13("Use the attemptId returned by im-authorize.");
52768
- if (values["credentials-stdin"] && command !== "im-credentials") usage$13("--credentials-stdin is only valid for im-credentials.");
52769
- if (values["verification-stdin"] && command !== "im-verify") usage$13("--verification-stdin is only valid for im-verify.");
52770
- if (values.wait && command !== "pairing-status") usage$13("--wait is only valid for pairing-status.");
55641
+ if (!["feishu", "weixin"].includes(target)) usage$14("Choose feishu or weixin.");
55642
+ } else if (count === 1 && !/^[A-Za-z0-9_-]{1,128}$/u.test(target)) usage$14("Use the attemptId returned by im-authorize.");
55643
+ if (values["credentials-stdin"] && command !== "im-credentials") usage$14("--credentials-stdin is only valid for im-credentials.");
55644
+ if (values["verification-stdin"] && command !== "im-verify") usage$14("--verification-stdin is only valid for im-verify.");
55645
+ if (values.wait && command !== "pairing-status") usage$14("--wait is only valid for pairing-status.");
52771
55646
  const operation = {
52772
55647
  command,
52773
55648
  target,
52774
55649
  wait: values.wait === true
52775
55650
  };
52776
55651
  if (command === "im-credentials") {
52777
- if (!values["credentials-stdin"]) usage$13("im-credentials requires --credentials-stdin.");
55652
+ if (!values["credentials-stdin"]) usage$14("im-credentials requires --credentials-stdin.");
52778
55653
  const input = await (io.readStdin?.() ?? Promise.resolve(""));
52779
55654
  let credentials;
52780
55655
  try {
52781
- if (input.length > 16384) usage$13("IM credential JSON is too large.");
55656
+ if (input.length > 16384) usage$14("IM credential JSON is too large.");
52782
55657
  credentials = record$5(JSON.parse(input));
52783
55658
  } catch {
52784
- usage$13("IM credentials require JSON from stdin.");
55659
+ usage$14("IM credentials require JSON from stdin.");
52785
55660
  }
52786
55661
  const { appId, appSecret, domain } = credentials;
52787
55662
  if (Object.keys(credentials).some((key) => ![
52788
55663
  "appId",
52789
55664
  "appSecret",
52790
55665
  "domain"
52791
- ].includes(key)) || typeof appId !== "string" || !/^cli_[A-Za-z0-9_-]+$/u.test(appId) || typeof appSecret !== "string" || !appSecret.trim() || appSecret.length > 4096 || domain !== "lark" && domain !== "feishu") usage$13("Credential JSON requires appId, appSecret and domain (lark or feishu).");
55666
+ ].includes(key)) || typeof appId !== "string" || !/^cli_[A-Za-z0-9_-]+$/u.test(appId) || typeof appSecret !== "string" || !appSecret.trim() || appSecret.length > 4096 || domain !== "lark" && domain !== "feishu") usage$14("Credential JSON requires appId, appSecret and domain (lark or feishu).");
52792
55667
  operation.credentials = {
52793
55668
  appId,
52794
55669
  appSecret,
@@ -52796,9 +55671,9 @@ async function prepareImAuthorization(command, rest, values, io) {
52796
55671
  };
52797
55672
  }
52798
55673
  if (command === "im-verify") {
52799
- if (!values["verification-stdin"]) usage$13("im-verify requires --verification-stdin.");
55674
+ if (!values["verification-stdin"]) usage$14("im-verify requires --verification-stdin.");
52800
55675
  const verifyCode = (await (io.readStdin?.() ?? Promise.resolve(""))).trim();
52801
- if (!/^\d{4,8}$/u.test(verifyCode)) usage$13("Verification stdin must contain 4–8 digits.");
55676
+ if (!/^\d{4,8}$/u.test(verifyCode)) usage$14("Verification stdin must contain 4–8 digits.");
52802
55677
  operation.verifyCode = verifyCode;
52803
55678
  }
52804
55679
  return operation;
@@ -52867,7 +55742,7 @@ async function runImAuthorization(operation, rpc, signal) {
52867
55742
  "im-cancel": "setup.cancel",
52868
55743
  "pairing-status": "setup.poll"
52869
55744
  }[operation.command];
52870
- if (!method) usage$13("Unknown IM应用授权 command.");
55745
+ if (!method) usage$14("Unknown IM应用授权 command.");
52871
55746
  const start = operation.command === "im-authorize";
52872
55747
  const payload = start ? { channel: operation.target } : {
52873
55748
  attemptId: operation.target,
@@ -53074,7 +55949,7 @@ const BODY_COMMANDS = /* @__PURE__ */ new Set([
53074
55949
  "messaging-post-status",
53075
55950
  "messaging-send"
53076
55951
  ]);
53077
- function usage$12(message) {
55952
+ function usage$13(message) {
53078
55953
  throw new CliLiveError("usage", message);
53079
55954
  }
53080
55955
  function record$4(value) {
@@ -53085,12 +55960,12 @@ function list(value) {
53085
55960
  }
53086
55961
  function uuid(value, flag) {
53087
55962
  const trimmed = value?.trim() ?? "";
53088
- if (!UUID.test(trimmed)) usage$12(`${flag} must be a UUID.`);
55963
+ if (!UUID.test(trimmed)) usage$13(`${flag} must be a UUID.`);
53089
55964
  return trimmed;
53090
55965
  }
53091
55966
  function required$2(value, flag) {
53092
55967
  const trimmed = value?.trim() ?? "";
53093
- if (!trimmed) usage$12(`${flag} is required.`);
55968
+ if (!trimmed) usage$13(`${flag} is required.`);
53094
55969
  return trimmed;
53095
55970
  }
53096
55971
  function destructive(input, command) {
@@ -53102,37 +55977,37 @@ function destructive(input, command) {
53102
55977
  }
53103
55978
  async function prepareMessaging(command, rest, values, io) {
53104
55979
  const what = command === "messaging-defaults" || command === "messaging-defaults-set" ? "a platform" : command === "messaging-targets" ? "an IM app ref" : command.startsWith("channel-") ? "a Channel id" : "a Bot id";
53105
- if (rest.length !== 1 || !rest[0]?.trim()) usage$12(`${command} needs exactly one target: ${what}.`);
55980
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$13(`${command} needs exactly one target: ${what}.`);
53106
55981
  const target = rest[0].trim();
53107
- if (what === "a platform" && !PLATFORMS.includes(target)) usage$12(`Choose one of ${PLATFORMS.join(", ")}.`);
55982
+ if (what === "a platform" && !PLATFORMS.includes(target)) usage$13(`Choose one of ${PLATFORMS.join(", ")}.`);
53108
55983
  const operation = {
53109
55984
  command,
53110
55985
  target,
53111
55986
  values
53112
55987
  };
53113
55988
  if (STDIN_COMMANDS.has(command)) {
53114
- if (values["input-stdin"] !== true) usage$12(`${command} requires --input-stdin.`);
55989
+ if (values["input-stdin"] !== true) usage$13(`${command} requires --input-stdin.`);
53115
55990
  const raw = await (io.readStdin?.() ?? Promise.resolve(""));
53116
55991
  let parsed;
53117
55992
  try {
53118
55993
  if (raw.length > 65536) throw new Error("too large");
53119
55994
  parsed = JSON.parse(raw);
53120
55995
  } catch {
53121
- usage$12("--input-stdin must be one JSON object of at most 64 KiB.");
55996
+ usage$13("--input-stdin must be one JSON object of at most 64 KiB.");
53122
55997
  }
53123
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) usage$12("--input-stdin must be one JSON object of at most 64 KiB.");
55998
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) usage$13("--input-stdin must be one JSON object of at most 64 KiB.");
53124
55999
  operation.input = parsed;
53125
- if (destructive(operation.input, command) && values.confirm !== true) usage$12(`This ${String(operation.input["kind"])} change needs --confirm.`);
53126
- } else if (values["input-stdin"] === true) usage$12(`--input-stdin is not valid for ${command}.`);
56000
+ if (destructive(operation.input, command) && values.confirm !== true) usage$13(`This ${String(operation.input["kind"])} change needs --confirm.`);
56001
+ } else if (values["input-stdin"] === true) usage$13(`--input-stdin is not valid for ${command}.`);
53127
56002
  if (BODY_COMMANDS.has(command)) {
53128
- if (values.body !== void 0 === (values["body-stdin"] === true)) usage$12(`${command} requires exactly one of --body or --body-stdin.`);
56003
+ if (values.body !== void 0 === (values["body-stdin"] === true)) usage$13(`${command} requires exactly one of --body or --body-stdin.`);
53129
56004
  const text = values["body-stdin"] ? await (io.readStdin?.() ?? Promise.resolve("")) : values.body;
53130
- if (!text?.trim()) usage$12(`${command} requires a nonempty message.`);
53131
- if (text.length > 4e3) usage$12("Messages are limited to 4000 characters.");
56005
+ if (!text?.trim()) usage$13(`${command} requires a nonempty message.`);
56006
+ if (text.length > 4e3) usage$13("Messages are limited to 4000 characters.");
53132
56007
  operation.text = text;
53133
56008
  }
53134
56009
  const requestId = values["request-id"];
53135
- if (requestId !== void 0 && !/^[A-Za-z0-9_:.-]{8,128}$/u.test(requestId)) usage$12("--request-id must be 8–128 letters, digits, _ : . or -.");
56010
+ if (requestId !== void 0 && !/^[A-Za-z0-9_:.-]{8,128}$/u.test(requestId)) usage$13("--request-id must be 8–128 letters, digits, _ : . or -.");
53136
56011
  switch (command) {
53137
56012
  case "messaging-targets":
53138
56013
  case "messaging-defaults":
@@ -53152,12 +56027,12 @@ async function prepareMessaging(command, rest, values, io) {
53152
56027
  break;
53153
56028
  case "messaging-revoke":
53154
56029
  uuid(values.grant, "--grant");
53155
- if (values.confirm !== true) usage$12("Revoking stops the Bot from messaging this conversation. Pass --confirm.");
56030
+ if (values.confirm !== true) usage$13("Revoking stops the Bot from messaging this conversation. Pass --confirm.");
53156
56031
  break;
53157
56032
  case "messaging-receive":
53158
56033
  case "failure-alerts-set":
53159
56034
  if (command === "messaging-receive") uuid(values.grant, "--grant");
53160
- if (values.enabled === values.disabled) usage$12(`${command} needs exactly one of --enabled or --disabled.`);
56035
+ if (values.enabled === values.disabled) usage$13(`${command} needs exactly one of --enabled or --disabled.`);
53161
56036
  break;
53162
56037
  case "messaging-channel-target":
53163
56038
  uuid(values.grant, "--grant");
@@ -53178,12 +56053,12 @@ async function prepareMessaging(command, rest, values, io) {
53178
56053
  case "messaging-post-status":
53179
56054
  uuid(values.binding, "--binding");
53180
56055
  required$2(values.conversation, "--conversation");
53181
- if (command === "messaging-post-status" && requestId === void 0) usage$12("messaging-post-status requires the --request-id of the post.");
56056
+ if (command === "messaging-post-status" && requestId === void 0) usage$13("messaging-post-status requires the --request-id of the post.");
53182
56057
  break;
53183
56058
  case "messaging-post-limit": {
53184
56059
  uuid(values.binding, "--binding");
53185
56060
  const limit = values.limit?.trim();
53186
- if (limit !== "none" && !(Number.isSafeInteger(Number(limit)) && Number(limit) >= 1 && Number(limit) <= 1e4)) usage$12("--limit must be 1–10000, or none to clear it.");
56061
+ if (limit !== "none" && !(Number.isSafeInteger(Number(limit)) && Number(limit) >= 1 && Number(limit) <= 1e4)) usage$13("--limit must be 1–10000, or none to clear it.");
53187
56062
  break;
53188
56063
  }
53189
56064
  case "approval-route":
@@ -53504,38 +56379,38 @@ const NO_TARGET = /* @__PURE__ */ new Set([
53504
56379
  "channel-activity-today"
53505
56380
  ]);
53506
56381
  const DAY = /^\d{4}-\d{2}-\d{2}$/u;
53507
- function usage$11(message) {
56382
+ function usage$12(message) {
53508
56383
  throw new CliLiveError("usage", message);
53509
56384
  }
53510
56385
  function revision$1(value) {
53511
56386
  if (value === void 0) return void 0;
53512
56387
  const parsed = Number(value);
53513
- if (!/^\d+$/u.test(value) || !Number.isSafeInteger(parsed)) usage$11("--expected-revision must be a nonnegative integer.");
56388
+ if (!/^\d+$/u.test(value) || !Number.isSafeInteger(parsed)) usage$12("--expected-revision must be a nonnegative integer.");
53514
56389
  return parsed;
53515
56390
  }
53516
56391
  function cursor(value) {
53517
56392
  if (value === void 0) return void 0;
53518
- if (value.length === 0 || value.length > 255) usage$11("--after must be 1–255 characters.");
56393
+ if (value.length === 0 || value.length > 255) usage$12("--after must be 1–255 characters.");
53519
56394
  return value;
53520
56395
  }
53521
56396
  function day(value, flag) {
53522
56397
  if (value === void 0) return void 0;
53523
- if (!DAY.test(value)) usage$11(`--${flag} must be a YYYY-MM-DD day.`);
56398
+ if (!DAY.test(value)) usage$12(`--${flag} must be a YYYY-MM-DD day.`);
53524
56399
  return value;
53525
56400
  }
53526
56401
  async function planInput$1(io, values, keys, required) {
53527
- if (!values["plan-stdin"]) usage$11("This command reads its plan JSON with --plan-stdin.");
56402
+ if (!values["plan-stdin"]) usage$12("This command reads its plan JSON with --plan-stdin.");
53528
56403
  let input;
53529
56404
  try {
53530
56405
  input = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
53531
56406
  } catch {
53532
- usage$11("Plan stdin must be one JSON object.");
56407
+ usage$12("Plan stdin must be one JSON object.");
53533
56408
  }
53534
- if (typeof input !== "object" || input === null || Array.isArray(input)) usage$11("Plan stdin must be one JSON object.");
56409
+ if (typeof input !== "object" || input === null || Array.isArray(input)) usage$12("Plan stdin must be one JSON object.");
53535
56410
  const plan = input;
53536
- if (Object.keys(plan).filter((key) => !keys.includes(key)).length > 0) usage$11(`Plan stdin accepts only ${keys.join(", ")}.`);
56411
+ if (Object.keys(plan).filter((key) => !keys.includes(key)).length > 0) usage$12(`Plan stdin accepts only ${keys.join(", ")}.`);
53537
56412
  const missing = required.filter((key) => plan[key] === void 0);
53538
- if (missing.length > 0) usage$11(`Plan stdin requires ${missing.join(", ")}.`);
56413
+ if (missing.length > 0) usage$12(`Plan stdin requires ${missing.join(", ")}.`);
53539
56414
  return plan;
53540
56415
  }
53541
56416
  function routeOverride(values, prefix, current) {
@@ -53546,7 +56421,7 @@ function routeOverride(values, prefix, current) {
53546
56421
  ["provider", provider],
53547
56422
  ["model", model],
53548
56423
  ["effort", effort]
53549
- ]) if (value === "") usage$11(`--${prefix}-${flag} must not be empty.`);
56424
+ ]) if (value === "") usage$12(`--${prefix}-${flag} must not be empty.`);
53550
56425
  const next = {
53551
56426
  provider: provider ?? current.provider,
53552
56427
  model: model ?? current.model
@@ -53563,12 +56438,12 @@ function isModelsUsageCommand(command) {
53563
56438
  }
53564
56439
  async function runModelsUsage(command, rest, values, io, connect) {
53565
56440
  const noTarget = NO_TARGET.has(command);
53566
- if (rest.length !== (noTarget ? 0 : 1)) usage$11(`${command} ${noTarget ? "takes no positional arguments" : "needs exactly one target id"}.`);
56441
+ if (rest.length !== (noTarget ? 0 : 1)) usage$12(`${command} ${noTarget ? "takes no positional arguments" : "needs exactly one target id"}.`);
53567
56442
  const target = rest[0]?.trim() ?? "";
53568
- if (!noTarget && !target) usage$11(`${command} requires a nonempty target id.`);
56443
+ if (!noTarget && !target) usage$12(`${command} requires a nonempty target id.`);
53569
56444
  const expected = revision$1(values["expected-revision"]);
53570
56445
  if (command === "home-model-set") {
53571
- if (!values.provider || !values.model) usage$11("home-model-set requires --provider and --model.");
56446
+ if (!values.provider || !values.model) usage$12("home-model-set requires --provider and --model.");
53572
56447
  const rpc = await connect();
53573
56448
  const expectedDefaultRevision = expected ?? (await rpc("modelCatalog", {})).defaultRevision;
53574
56449
  if (!Number.isSafeInteger(expectedDefaultRevision) || Number(expectedDefaultRevision) < 0) throw new CliLiveError("settings-unavailable", "The Host does not expose its native default model revision.");
@@ -53592,7 +56467,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53592
56467
  }
53593
56468
  if (command === "overview-usage") {
53594
56469
  const period = values.period ?? "today";
53595
- if (!isUsageOverviewPeriod(period)) usage$11(`--period must be one of ${usageOverviewPeriods.join(", ")}.`);
56470
+ if (!isUsageOverviewPeriod(period)) usage$12(`--period must be one of ${usageOverviewPeriods.join(", ")}.`);
53596
56471
  const after = cursor(values.after);
53597
56472
  return (await connect())("overviewUsage", {
53598
56473
  period,
@@ -53604,7 +56479,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53604
56479
  if (command === "bot-activity-history") {
53605
56480
  const before = day(values.before, "before");
53606
56481
  const weeks = values.weeks === void 0 ? void 0 : Number(values.weeks);
53607
- if (weeks !== void 0 && (!Number.isInteger(weeks) || weeks < 1 || weeks > 104)) usage$11("--weeks must be an integer from 1 to 104.");
56482
+ if (weeks !== void 0 && (!Number.isInteger(weeks) || weeks < 1 || weeks > 104)) usage$12("--weeks must be an integer from 1 to 104.");
53608
56483
  return (await connect())("profileActivity", {
53609
56484
  channelId: dmChannelId(target),
53610
56485
  ...before === void 0 ? {} : { before },
@@ -53614,7 +56489,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53614
56489
  if (command === "bot-usage") {
53615
56490
  const start = day(values.start, "start");
53616
56491
  const end = day(values.end, "end");
53617
- if (start === void 0 || end === void 0) usage$11("bot-usage requires --start and --end.");
56492
+ if (start === void 0 || end === void 0) usage$12("bot-usage requires --start and --end.");
53618
56493
  const filter = {
53619
56494
  start,
53620
56495
  end,
@@ -53631,7 +56506,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53631
56506
  const provider = values["orchestrator-provider"]?.trim();
53632
56507
  const model = values["orchestrator-model"]?.trim();
53633
56508
  const effort = values["orchestrator-effort"]?.trim();
53634
- if (!provider || !model) usage$11("--orchestrator-provider and --orchestrator-model are required.");
56509
+ if (!provider || !model) usage$12("--orchestrator-provider and --orchestrator-model are required.");
53635
56510
  const rpc = await connect();
53636
56511
  return rpc("modelPlanCustomize", {
53637
56512
  slug: target,
@@ -53668,7 +56543,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53668
56543
  }
53669
56544
  if (command === "model-preset-update") {
53670
56545
  const name = values.name?.trim();
53671
- if (values.name !== void 0 && !name) usage$11("--name must not be empty.");
56546
+ if (values.name !== void 0 && !name) usage$12("--name must not be empty.");
53672
56547
  const plan = values["plan-stdin"] ? await planInput$1(io, values, ["assignmentModels"], ["assignmentModels"]) : {};
53673
56548
  const rpc = await connect();
53674
56549
  const { presets } = await rpc("modelPresets", {});
@@ -53683,7 +56558,7 @@ async function runModelsUsage(command, rest, values, io, connect) {
53683
56558
  ...plan
53684
56559
  });
53685
56560
  }
53686
- return usage$11(`Unsupported models or usage command ${command}.`);
56561
+ return usage$12(`Unsupported models or usage command ${command}.`);
53687
56562
  }
53688
56563
  //#endregion
53689
56564
  //#region packages/core/src/marketplace/altcha.ts
@@ -53822,7 +56697,7 @@ const HOST_ADMIN_COMMANDS = [
53822
56697
  }
53823
56698
  ];
53824
56699
  const MAX_REPORT_REASON_LENGTH = 500;
53825
- function usage$10(message) {
56700
+ function usage$11(message) {
53826
56701
  throw new CliLiveError("usage", message);
53827
56702
  }
53828
56703
  function record$2(value) {
@@ -53857,26 +56732,26 @@ const POSITIONAL_NAMES = {
53857
56732
  };
53858
56733
  function validate(command, rest, values) {
53859
56734
  const expected = POSITIONALS$2[command];
53860
- if (rest.length !== expected || rest.some((value) => !value.trim())) usage$10(expected === 0 ? `${command} takes no positional arguments.` : `${command} needs ${POSITIONAL_NAMES[expected]}.`);
53861
- if (values.sort !== void 0 && (command !== "marketplace-list" || values.sort !== "updated" && values.sort !== "stars")) usage$10("--sort must be updated or stars, on marketplace-list.");
56735
+ if (rest.length !== expected || rest.some((value) => !value.trim())) usage$11(expected === 0 ? `${command} takes no positional arguments.` : `${command} needs ${POSITIONAL_NAMES[expected]}.`);
56736
+ if (values.sort !== void 0 && (command !== "marketplace-list" || values.sort !== "updated" && values.sort !== "stars")) usage$11("--sort must be updated or stars, on marketplace-list.");
53862
56737
  if (command === "marketplace-report" && values.reason !== void 0) {
53863
- if (values.reason.trim().length > MAX_REPORT_REASON_LENGTH) usage$10(`--reason must be at most ${String(MAX_REPORT_REASON_LENGTH)} characters.`);
56738
+ if (values.reason.trim().length > MAX_REPORT_REASON_LENGTH) usage$11(`--reason must be at most ${String(MAX_REPORT_REASON_LENGTH)} characters.`);
53864
56739
  }
53865
- if ((command === "release-install" || command === "release-restart") && values.confirm !== true) usage$10(command === "release-install" ? "release-install replaces the installed DeepSeekBot. Pass --confirm to install." : "release-restart stops every running Bot turn on this Host. Pass --confirm to restart.");
53866
- if (command === "telemetry-set" && values.enabled === values.disabled) usage$10("telemetry-set needs exactly one of --enabled or --disabled.");
56740
+ if ((command === "release-install" || command === "release-restart") && values.confirm !== true) usage$11(command === "release-install" ? "release-install replaces the installed DeepSeekBot. Pass --confirm to install." : "release-restart stops every running Bot turn on this Host. Pass --confirm to restart.");
56741
+ if (command === "telemetry-set" && values.enabled === values.disabled) usage$11("telemetry-set needs exactly one of --enabled or --disabled.");
53867
56742
  if (command !== "pairing-review") return void 0;
53868
56743
  const kind = values.decision;
53869
- if (kind !== "approve" && kind !== "reject" && kind !== "revoke") usage$10("--decision must be approve, reject or revoke.");
56744
+ if (kind !== "approve" && kind !== "reject" && kind !== "revoke") usage$11("--decision must be approve, reject or revoke.");
53870
56745
  const roles = (values.role ?? []).map((role) => role.trim()).filter(Boolean);
53871
56746
  const capabilities = (values.capability ?? []).map((capability) => capability.trim());
53872
- for (const capability of capabilities) if (!pairingCapabilities.includes(capability)) usage$10(`--capability must be one of ${pairingCapabilities.join(", ")}.`);
56747
+ for (const capability of capabilities) if (!pairingCapabilities.includes(capability)) usage$11(`--capability must be one of ${pairingCapabilities.join(", ")}.`);
53873
56748
  if (kind !== "approve") {
53874
- if (roles.length > 0 || capabilities.length > 0) usage$10("--role and --capability only apply to --decision approve.");
53875
- if (kind === "revoke" && values.confirm !== true) usage$10("Revoking ends this person’s access through the Bot. Pass --confirm to revoke.");
56749
+ if (roles.length > 0 || capabilities.length > 0) usage$11("--role and --capability only apply to --decision approve.");
56750
+ if (kind === "revoke" && values.confirm !== true) usage$11("Revoking ends this person’s access through the Bot. Pass --confirm to revoke.");
53876
56751
  return { kind };
53877
56752
  }
53878
- if (roles.length > 1) usage$10("pairing-review takes at most one --role.");
53879
- if (roles.length === 1 === capabilities.length > 0) usage$10("Approve needs exactly one of --role <role-id> or --capability <capability> ...");
56753
+ if (roles.length > 1) usage$11("pairing-review takes at most one --role.");
56754
+ if (roles.length === 1 === capabilities.length > 0) usage$11("Approve needs exactly one of --role <role-id> or --capability <capability> ...");
53880
56755
  return roles.length === 1 ? {
53881
56756
  kind,
53882
56757
  roleId: roles[0]
@@ -53935,7 +56810,7 @@ async function runHostAdminCommand(command, rest, values, _io, host) {
53935
56810
  "continue",
53936
56811
  "restart",
53937
56812
  "finish"
53938
- ].includes(values.action)) usage$10("Invalid onboarding action.");
56813
+ ].includes(values.action)) usage$11("Invalid onboarding action.");
53939
56814
  return rpc("onboarding", values.action === void 0 ? {} : { action: values.action });
53940
56815
  case "tob-home": return rpc("tobHome", {});
53941
56816
  case "marketplace-list": return rpc("marketplaceList", { query: {
@@ -54098,14 +56973,14 @@ function scheduleToggleFromFlags(values, on, off, fail) {
54098
56973
  if (isOn) return true;
54099
56974
  if (isOff) return false;
54100
56975
  }
54101
- function usage$9(message) {
56976
+ function usage$10(message) {
54102
56977
  return new CliLiveError("usage", message);
54103
56978
  }
54104
56979
  function prepareScheduleCommand(command, rest, values) {
54105
56980
  if (command === "schedule-preview") {
54106
- if (rest.length > 0) throw usage$9("schedule-preview takes no bot id.");
54107
- const trigger = scheduleTriggerFromFlags(values, usage$9);
54108
- if (trigger === void 0) throw usage$9("schedule-preview needs a trigger flag.");
56981
+ if (rest.length > 0) throw usage$10("schedule-preview takes no bot id.");
56982
+ const trigger = scheduleTriggerFromFlags(values, usage$10);
56983
+ if (trigger === void 0) throw usage$10("schedule-preview needs a trigger flag.");
54109
56984
  return {
54110
56985
  method: "schedulePreview",
54111
56986
  args: { trigger },
@@ -54113,7 +56988,7 @@ function prepareScheduleCommand(command, rest, values) {
54113
56988
  };
54114
56989
  }
54115
56990
  const slug = rest.length === 1 ? rest[0].trim() : "";
54116
- if (slug.length === 0) throw usage$9(`${command} needs exactly one bot id.`);
56991
+ if (slug.length === 0) throw usage$10(`${command} needs exactly one bot id.`);
54117
56992
  if (command === "schedules") return {
54118
56993
  method: "scheduleList",
54119
56994
  args: { slug }
@@ -54121,11 +56996,11 @@ function prepareScheduleCommand(command, rest, values) {
54121
56996
  if (command === "schedule-create") {
54122
56997
  const title = trimmed$1(values.title);
54123
56998
  const prompt = trimmed$1(values.prompt);
54124
- if (title === void 0 || prompt === void 0) throw usage$9("--title and --prompt are required for schedule-create.");
54125
- const trigger = scheduleTriggerFromFlags(values, usage$9);
54126
- if (trigger === void 0) throw usage$9("schedule-create needs a trigger flag.");
54127
- const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$9);
54128
- const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$9);
56999
+ if (title === void 0 || prompt === void 0) throw usage$10("--title and --prompt are required for schedule-create.");
57000
+ const trigger = scheduleTriggerFromFlags(values, usage$10);
57001
+ if (trigger === void 0) throw usage$10("schedule-create needs a trigger flag.");
57002
+ const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$10);
57003
+ const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$10);
54129
57004
  return {
54130
57005
  method: "scheduleCreate",
54131
57006
  args: {
@@ -54141,13 +57016,13 @@ function prepareScheduleCommand(command, rest, values) {
54141
57016
  };
54142
57017
  }
54143
57018
  const id = trimmed$1(values.sid);
54144
- if (id === void 0) throw usage$9(`--sid is required for ${command}.`);
57019
+ if (id === void 0) throw usage$10(`--sid is required for ${command}.`);
54145
57020
  if (command === "schedule-update") {
54146
57021
  const title = trimmed$1(values.title);
54147
57022
  const prompt = trimmed$1(values.prompt);
54148
- const trigger = scheduleTriggerFromFlags(values, usage$9);
54149
- const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$9);
54150
- const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$9);
57023
+ const trigger = scheduleTriggerFromFlags(values, usage$10);
57024
+ const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$10);
57025
+ const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$10);
54151
57026
  const change = {
54152
57027
  ...title === void 0 ? {} : { title },
54153
57028
  ...prompt === void 0 ? {} : { prompt },
@@ -54155,7 +57030,7 @@ function prepareScheduleCommand(command, rest, values) {
54155
57030
  ...enabled === void 0 ? {} : { enabled },
54156
57031
  ...locked === void 0 ? {} : { locked }
54157
57032
  };
54158
- if (Object.keys(change).length === 0) throw usage$9("schedule-update needs at least one change flag.");
57033
+ if (Object.keys(change).length === 0) throw usage$10("schedule-update needs at least one change flag.");
54159
57034
  return {
54160
57035
  method: "scheduleUpdate",
54161
57036
  args: {
@@ -54166,7 +57041,7 @@ function prepareScheduleCommand(command, rest, values) {
54166
57041
  };
54167
57042
  }
54168
57043
  if (command === "schedule-delete") {
54169
- if (values.confirm !== true) throw usage$9("schedule-delete removes the schedule and its history. Pass --confirm.");
57044
+ if (values.confirm !== true) throw usage$10("schedule-delete removes the schedule and its history. Pass --confirm.");
54170
57045
  return {
54171
57046
  method: "scheduleDelete",
54172
57047
  args: {
@@ -54330,14 +57205,14 @@ const SOURCE_CLASSES = /* @__PURE__ */ new Set([
54330
57205
  "bot-dm",
54331
57206
  "group-mention"
54332
57207
  ]);
54333
- function usage$8(message) {
57208
+ function usage$9(message) {
54334
57209
  throw new CliLiveError("usage", message);
54335
57210
  }
54336
57211
  function isProfileCommand(command) {
54337
57212
  return PROFILE_COMMANDS.some((entry) => entry.command === command) || PROFILE_ONLINE_COMMANDS.some((entry) => entry === command);
54338
57213
  }
54339
57214
  function readBytes(path, flag = "--file") {
54340
- if (!path?.trim()) usage$8(`${flag} <path> is required.`);
57215
+ if (!path?.trim()) usage$9(`${flag} <path> is required.`);
54341
57216
  try {
54342
57217
  return readFileSync(path);
54343
57218
  } catch {
@@ -54355,27 +57230,27 @@ function imageDataUrl(bytes) {
54355
57230
  26,
54356
57231
  10
54357
57232
  ])) ? "png" : bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255 ? "jpeg" : bytes.toString("ascii", 0, 4) === "RIFF" && bytes.toString("ascii", 8, 12) === "WEBP" ? "webp" : void 0;
54358
- if (type === void 0) usage$8("--file must be a PNG, JPEG or WebP image.");
57233
+ if (type === void 0) usage$9("--file must be a PNG, JPEG or WebP image.");
54359
57234
  return `data:image/${type};base64,${bytes.toString("base64")}`;
54360
57235
  }
54361
57236
  async function stdinJson(io, flag) {
54362
57237
  try {
54363
57238
  return JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
54364
57239
  } catch {
54365
- usage$8(`${flag} must be one JSON document.`);
57240
+ usage$9(`${flag} must be one JSON document.`);
54366
57241
  }
54367
57242
  }
54368
57243
  function count(value, flag, min = 0) {
54369
57244
  const parsed = Number(value);
54370
- if (value === void 0 || value.trim() === "" || !Number.isSafeInteger(parsed) || parsed < min) usage$8(`${flag} must be a whole number of at least ${String(min)}.`);
57245
+ if (value === void 0 || value.trim() === "" || !Number.isSafeInteger(parsed) || parsed < min) usage$9(`${flag} must be a whole number of at least ${String(min)}.`);
54371
57246
  return parsed;
54372
57247
  }
54373
57248
  function oneBot(command, rest) {
54374
- if (rest.length !== 1 || !rest[0]?.trim()) usage$8(`${command} needs exactly one bot id.`);
57249
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$9(`${command} needs exactly one bot id.`);
54375
57250
  return rest[0].trim();
54376
57251
  }
54377
57252
  function noArguments(command, rest) {
54378
- if (rest.length > 0) usage$8(`${command} takes no positional arguments.`);
57253
+ if (rest.length > 0) usage$9(`${command} takes no positional arguments.`);
54379
57254
  }
54380
57255
  function ids(rest) {
54381
57256
  return rest.map((id) => id.trim()).filter((id) => id.length > 0);
@@ -54384,7 +57259,7 @@ async function profileCall(command, rest, values, io) {
54384
57259
  switch (command) {
54385
57260
  case "bot-avatar-set": {
54386
57261
  const channelId = dmChannelId(oneBot(command, rest));
54387
- if (values.file !== void 0 === (values.clear === true)) usage$8("bot-avatar-set needs exactly one of --file or --clear.");
57262
+ if (values.file !== void 0 === (values.clear === true)) usage$9("bot-avatar-set needs exactly one of --file or --clear.");
54388
57263
  return ["botAvatarSet", {
54389
57264
  channelId,
54390
57265
  avatar: values.clear ? null : imageDataUrl(readBytes(values.file))
@@ -54396,7 +57271,7 @@ async function profileCall(command, rest, values, io) {
54396
57271
  values.file !== void 0,
54397
57272
  values["recipe-stdin"] === true,
54398
57273
  values.clear
54399
- ].filter(Boolean).length !== 1) usage$8("bot-banner-set needs exactly one of --file, --recipe-stdin or --clear.");
57274
+ ].filter(Boolean).length !== 1) usage$9("bot-banner-set needs exactly one of --file, --recipe-stdin or --clear.");
54400
57275
  return ["botBannerSet", {
54401
57276
  channelId,
54402
57277
  banner: values.clear ? null : values["recipe-stdin"] ? { recipe: await stdinJson(io, "--recipe-stdin") } : { image: `data:image/png;base64,${readBytes(values.file).toString("base64")}` }
@@ -54404,7 +57279,7 @@ async function profileCall(command, rest, values, io) {
54404
57279
  }
54405
57280
  case "bot-appearance-set": {
54406
57281
  const channelId = dmChannelId(oneBot(command, rest));
54407
- if (values["recipe-stdin"] !== true) usage$8("bot-appearance-set requires --recipe-stdin.");
57282
+ if (values["recipe-stdin"] !== true) usage$9("bot-appearance-set requires --recipe-stdin.");
54408
57283
  return ["botAppearanceSet", {
54409
57284
  channelId,
54410
57285
  recipe: await stdinJson(io, "--recipe-stdin")
@@ -54412,8 +57287,8 @@ async function profileCall(command, rest, values, io) {
54412
57287
  }
54413
57288
  case "bot-primary-color-set": {
54414
57289
  const channelId = dmChannelId(oneBot(command, rest));
54415
- if (values.color !== void 0 === (values.automatic === true)) usage$8("bot-primary-color-set needs exactly one of --color or --automatic.");
54416
- if (values.color !== void 0 && !/^#[0-9a-f]{6}$/iu.test(values.color)) usage$8("--color must be #rrggbb.");
57290
+ if (values.color !== void 0 === (values.automatic === true)) usage$9("bot-primary-color-set needs exactly one of --color or --automatic.");
57291
+ if (values.color !== void 0 && !/^#[0-9a-f]{6}$/iu.test(values.color)) usage$9("--color must be #rrggbb.");
54417
57292
  return ["botPrimaryColorSet", {
54418
57293
  channelId,
54419
57294
  primaryColor: values.automatic ? { mode: "automatic" } : {
@@ -54427,13 +57302,13 @@ async function profileCall(command, rest, values, io) {
54427
57302
  case "bot-source-policy-reset": {
54428
57303
  const slug = oneBot(command, rest);
54429
57304
  const sourceClass = values["source-class"] ?? "";
54430
- if (!SOURCE_CLASSES.has(sourceClass)) usage$8("--source-class must be assignment-report, group-ordinary, human-dm, bot-dm or group-mention.");
57305
+ if (!SOURCE_CLASSES.has(sourceClass)) usage$9("--source-class must be assignment-report, group-ordinary, human-dm, bot-dm or group-mention.");
54431
57306
  if (command === "bot-source-policy-reset") return ["botSourcePolicyReset", {
54432
57307
  slug,
54433
57308
  sourceClass
54434
57309
  }];
54435
57310
  if (IMMEDIATE_CLASSES.has(sourceClass)) {
54436
- if (values.delivery !== "steer" && values.delivery !== "turn") usage$8(`${sourceClass} needs --delivery steer or turn.`);
57311
+ if (values.delivery !== "steer" && values.delivery !== "turn") usage$9(`${sourceClass} needs --delivery steer or turn.`);
54437
57312
  return ["botSourcePolicySet", {
54438
57313
  slug,
54439
57314
  sourceClass,
@@ -54447,7 +57322,7 @@ async function profileCall(command, rest, values, io) {
54447
57322
  "digest",
54448
57323
  "mentions",
54449
57324
  "silent"
54450
- ].includes(values.wake ?? "")) usage$8("group-ordinary needs --wake immediate, digest, mentions or silent.");
57325
+ ].includes(values.wake ?? "")) usage$9("group-ordinary needs --wake immediate, digest, mentions or silent.");
54451
57326
  return ["botSourcePolicySet", {
54452
57327
  slug,
54453
57328
  sourceClass,
@@ -54456,7 +57331,7 @@ async function profileCall(command, rest, values, io) {
54456
57331
  digestIntervalSeconds: count(values["digest-interval"], "--digest-interval", 1)
54457
57332
  }];
54458
57333
  }
54459
- if (values.wake !== "conditional" && values.wake !== "immediate") usage$8("assignment-report needs --wake conditional or immediate.");
57334
+ if (values.wake !== "conditional" && values.wake !== "immediate") usage$9("assignment-report needs --wake conditional or immediate.");
54460
57335
  return ["botSourcePolicySet", {
54461
57336
  slug,
54462
57337
  sourceClass,
@@ -54470,7 +57345,7 @@ async function profileCall(command, rest, values, io) {
54470
57345
  }];
54471
57346
  case "developer-mode-set":
54472
57347
  noArguments(command, rest);
54473
- if (values.enabled === values.disabled) usage$8("developer-mode-set needs exactly one of --enabled or --disabled.");
57348
+ if (values.enabled === values.disabled) usage$9("developer-mode-set needs exactly one of --enabled or --disabled.");
54474
57349
  return ["developerModeSet", { enabled: values.enabled === true }];
54475
57350
  case "roster":
54476
57351
  noArguments(command, rest);
@@ -54482,9 +57357,9 @@ async function profileCall(command, rest, values, io) {
54482
57357
  "unpin",
54483
57358
  "hide",
54484
57359
  "move"
54485
- ].includes(action ?? "")) usage$8("roster-batch needs an action: pin, unpin, hide or move.");
54486
- if (ids(channelIds).length === 0) usage$8("roster-batch needs at least one channel id.");
54487
- if (action !== "move" && values.section !== void 0) usage$8("--section is only valid for roster-batch move.");
57360
+ ].includes(action ?? "")) usage$9("roster-batch needs an action: pin, unpin, hide or move.");
57361
+ if (ids(channelIds).length === 0) usage$9("roster-batch needs at least one channel id.");
57362
+ if (action !== "move" && values.section !== void 0) usage$9("--section is only valid for roster-batch move.");
54488
57363
  return ["rosterBatch", {
54489
57364
  action,
54490
57365
  channelIds: ids(channelIds),
@@ -54494,27 +57369,27 @@ async function profileCall(command, rest, values, io) {
54494
57369
  case "roster-pins-set": return ["pinsSet", { pins: ids(rest) }];
54495
57370
  case "roster-hidden-set": return ["hiddenSet", { hidden: ids(rest) }];
54496
57371
  case "roster-section-create":
54497
- if (rest.length !== 1 || !rest[0]?.trim()) usage$8("roster-section-create needs one name.");
57372
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$9("roster-section-create needs one name.");
54498
57373
  return ["sectionCreate", { name: rest[0].trim() }];
54499
57374
  case "roster-section-rename":
54500
- if (rest.length !== 1 || !rest[0]?.trim()) usage$8("roster-section-rename needs exactly one section id.");
54501
- if (!values.name?.trim()) usage$8("roster-section-rename requires --name <text>.");
57375
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$9("roster-section-rename needs exactly one section id.");
57376
+ if (!values.name?.trim()) usage$9("roster-section-rename requires --name <text>.");
54502
57377
  return ["sectionRename", {
54503
57378
  sectionId: rest[0].trim(),
54504
57379
  name: values.name.trim()
54505
57380
  }];
54506
57381
  case "roster-section-remove":
54507
- if (rest.length !== 1 || !rest[0]?.trim()) usage$8("roster-section-remove needs exactly one section id.");
54508
- if (values.confirm !== true) usage$8("roster-section-remove requires --confirm; its Channels move to the top level.");
57382
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$9("roster-section-remove needs exactly one section id.");
57383
+ if (values.confirm !== true) usage$9("roster-section-remove requires --confirm; its Channels move to the top level.");
54509
57384
  return ["sectionRemove", { sectionId: rest[0].trim() }];
54510
57385
  case "roster-section-reorder":
54511
- if (ids(rest).length === 0) usage$8("roster-section-reorder needs the section ids in order.");
57386
+ if (ids(rest).length === 0) usage$9("roster-section-reorder needs the section ids in order.");
54512
57387
  return ["sectionReorder", { order: ids(rest) }];
54513
57388
  case "roster-top-reorder":
54514
- if (ids(rest).length === 0) usage$8("roster-top-reorder needs section:<id> and channel:<id> entries in order.");
57389
+ if (ids(rest).length === 0) usage$9("roster-top-reorder needs section:<id> and channel:<id> entries in order.");
54515
57390
  return ["topReorder", { order: ids(rest).map((entry) => {
54516
57391
  const match = /^(section|channel):(.+)$/u.exec(entry);
54517
- if (match === null) usage$8(`roster-top-reorder entry ${entry} must be section:<id> or channel:<id>.`);
57392
+ if (match === null) usage$9(`roster-top-reorder entry ${entry} must be section:<id> or channel:<id>.`);
54518
57393
  return {
54519
57394
  kind: match[1],
54520
57395
  id: match[2]
@@ -54526,13 +57401,13 @@ async function profileCall(command, rest, values, io) {
54526
57401
  case "human-name-set": {
54527
57402
  noArguments(command, rest);
54528
57403
  const name = values.name?.trim();
54529
- if ((name === void 0 || name === "") === (values.clear !== true)) usage$8("human-name-set needs --name or --clear, not both or neither.");
57404
+ if ((name === void 0 || name === "") === (values.clear !== true)) usage$9("human-name-set needs --name or --clear, not both or neither.");
54530
57405
  return ["humanNameSet", { displayName: values.clear ? null : name }];
54531
57406
  }
54532
57407
  case "channel-human-name-set": {
54533
- if (rest.length !== 1 || !rest[0]?.trim()) usage$8("channel-human-name-set needs exactly one channel id.");
57408
+ if (rest.length !== 1 || !rest[0]?.trim()) usage$9("channel-human-name-set needs exactly one channel id.");
54534
57409
  const nickname = values.nickname?.trim();
54535
- if ((nickname === void 0 || nickname === "") === (values.clear !== true)) usage$8("channel-human-name-set needs --nickname or --clear, not both or neither.");
57410
+ if ((nickname === void 0 || nickname === "") === (values.clear !== true)) usage$9("channel-human-name-set needs --nickname or --clear, not both or neither.");
54536
57411
  return ["channelHumanNameSet", {
54537
57412
  channelId: rest[0].trim(),
54538
57413
  nickname: values.clear ? null : nickname
@@ -54543,7 +57418,7 @@ async function profileCall(command, rest, values, io) {
54543
57418
  return ["partLibraryList", {}];
54544
57419
  case "part-library-add":
54545
57420
  noArguments(command, rest);
54546
- if (values["part-stdin"] !== true) usage$8("part-library-add requires --part-stdin.");
57421
+ if (values["part-stdin"] !== true) usage$9("part-library-add requires --part-stdin.");
54547
57422
  return ["partLibraryAdd", {
54548
57423
  part: await stdinJson(io, "--part-stdin"),
54549
57424
  name: values.name ?? "",
@@ -54554,7 +57429,7 @@ async function profileCall(command, rest, values, io) {
54554
57429
  return ["partLibraryImport", { data: readBytes(values.file).toString("base64") }];
54555
57430
  case "part-library-import-image":
54556
57431
  noArguments(command, rest);
54557
- if (!values.slot?.trim()) usage$8("part-library-import-image requires --slot <slot>.");
57432
+ if (!values.slot?.trim()) usage$9("part-library-import-image requires --slot <slot>.");
54558
57433
  return ["partLibraryImportImage", {
54559
57434
  data: readBytes(values.file).toString("base64"),
54560
57435
  slot: values.slot.trim(),
@@ -54564,12 +57439,12 @@ async function profileCall(command, rest, values, io) {
54564
57439
  case "part-library-export": {
54565
57440
  noArguments(command, rest);
54566
57441
  const out = values.out ?? "";
54567
- if (!out.startsWith("/") && !/^[A-Za-z]:[\\/]/u.test(out)) usage$8("part-library-export requires --out <absolute-file>.");
54568
- if (values["part-id"] !== void 0 && values["part-stdin"] === true) usage$8("part-library-export takes --part-id or --part-stdin, not both.");
57442
+ if (!out.startsWith("/") && !/^[A-Za-z]:[\\/]/u.test(out)) usage$9("part-library-export requires --out <absolute-file>.");
57443
+ if (values["part-id"] !== void 0 && values["part-stdin"] === true) usage$9("part-library-export takes --part-id or --part-stdin, not both.");
54569
57444
  if (values["part-stdin"] === true) return ["partLibraryExport", { part: await stdinJson(io, "--part-stdin") }];
54570
57445
  return ["partLibraryExport", values["part-id"] === void 0 ? {} : { id: values["part-id"].trim() }];
54571
57446
  }
54572
- default: usage$8(`Unknown profile command ${command}.`);
57447
+ default: usage$9(`Unknown profile command ${command}.`);
54573
57448
  }
54574
57449
  }
54575
57450
  async function runProfileCommand(command, rest, values, io, connect) {
@@ -54621,7 +57496,7 @@ const TODO_COMMANDS = [
54621
57496
  function isTodoCommand(command) {
54622
57497
  return TODO_COMMANDS.some((entry) => entry.command === command);
54623
57498
  }
54624
- function usage$7(message) {
57499
+ function usage$8(message) {
54625
57500
  throw new CliLiveError("usage", message);
54626
57501
  }
54627
57502
  const POSITIONALS$1 = {
@@ -54634,18 +57509,18 @@ const POSITIONALS$1 = {
54634
57509
  };
54635
57510
  async function runTodoCommand(command, rest, values, io, connect) {
54636
57511
  const count = POSITIONALS$1[command];
54637
- if (rest.length !== count || rest.some((value) => !value.trim())) usage$7(count === 0 ? `${command} takes no positional arguments.` : command === "todo-tool" ? "todo-tool needs a bot id and a tool name." : `${command} needs exactly one to-do id.`);
57512
+ if (rest.length !== count || rest.some((value) => !value.trim())) usage$8(count === 0 ? `${command} takes no positional arguments.` : command === "todo-tool" ? "todo-tool needs a bot id and a tool name." : `${command} needs exactly one to-do id.`);
54638
57513
  const title = values.title?.trim();
54639
- if (command === "todo-add" && !title) usage$7("todo-add needs --title <text>.");
54640
- if (values.done === true && values["not-done"] === true) usage$7("Pass at most one of --done and --not-done.");
54641
- if (command === "todo-update" && title === void 0 && !values.done && !values["not-done"]) usage$7("todo-update needs --title, --done or --not-done.");
57514
+ if (command === "todo-add" && !title) usage$8("todo-add needs --title <text>.");
57515
+ if (values.done === true && values["not-done"] === true) usage$8("Pass at most one of --done and --not-done.");
57516
+ if (command === "todo-update" && title === void 0 && !values.done && !values["not-done"]) usage$8("todo-update needs --title, --done or --not-done.");
54642
57517
  let args = {};
54643
57518
  if (command === "todo-tool" && values["args-stdin"] === true) try {
54644
57519
  const parsed = JSON.parse(await (io.readStdin?.() ?? Promise.resolve("")));
54645
57520
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) throw new Error("not an object");
54646
57521
  args = parsed;
54647
57522
  } catch {
54648
- usage$7("--args-stdin must be a JSON object of tool arguments.");
57523
+ usage$8("--args-stdin must be a JSON object of tool arguments.");
54649
57524
  }
54650
57525
  const { http } = await connect();
54651
57526
  const json = async (path, body) => {
@@ -54715,7 +57590,7 @@ const SUBCOMMANDS = [
54715
57590
  function isApprovalTemplateCommand(command) {
54716
57591
  return APPROVAL_TEMPLATE_COMMANDS.some((entry) => entry.command === command);
54717
57592
  }
54718
- function usage$6(message) {
57593
+ function usage$7(message) {
54719
57594
  throw new CliLiveError("usage", message);
54720
57595
  }
54721
57596
  const POSITIONALS = {
@@ -54726,14 +57601,14 @@ const POSITIONALS = {
54726
57601
  delete: 1
54727
57602
  };
54728
57603
  async function templateText(values, io) {
54729
- if (values.file !== void 0 && values["text-stdin"] === true) usage$6("Give the template text with --file or --text-stdin, not both.");
57604
+ if (values.file !== void 0 && values["text-stdin"] === true) usage$7("Give the template text with --file or --text-stdin, not both.");
54730
57605
  if (values.file !== void 0) try {
54731
57606
  return readFileSync(values.file, "utf8");
54732
57607
  } catch {
54733
57608
  throw new CliLiveError("invalid-input", `Cannot read ${values.file}.`);
54734
57609
  }
54735
57610
  if (values["text-stdin"] === true) return io.readStdin?.() ?? Promise.resolve("");
54736
- return usage$6("Give the template Markdown with --file <path> or --text-stdin.");
57611
+ return usage$7("Give the template Markdown with --file <path> or --text-stdin.");
54737
57612
  }
54738
57613
  function normalize(command, rest) {
54739
57614
  if (command === "approval-templates") return {
@@ -54745,7 +57620,7 @@ function normalize(command, rest) {
54745
57620
  args: rest
54746
57621
  };
54747
57622
  const [subcommand, ...args] = rest;
54748
- if (!SUBCOMMANDS.includes(subcommand)) usage$6("approval-template needs one of: " + SUBCOMMANDS.join(", ") + ".");
57623
+ if (!SUBCOMMANDS.includes(subcommand)) usage$7("approval-template needs one of: " + SUBCOMMANDS.join(", ") + ".");
54749
57624
  return {
54750
57625
  subcommand,
54751
57626
  args
@@ -54753,7 +57628,7 @@ function normalize(command, rest) {
54753
57628
  }
54754
57629
  async function runApprovalTemplateCommand(command, rest, values, io, connect) {
54755
57630
  if (command === "approval-template-set") {
54756
- if (rest.length !== 2 || rest.some((value) => !value.trim())) usage$6("approval-template-set needs a bot id and a template name (or off).");
57631
+ if (rest.length !== 2 || rest.some((value) => !value.trim())) usage$7("approval-template-set needs a bot id and a template name (or off).");
54757
57632
  const rpc = await connect();
54758
57633
  const template = rest[1].trim();
54759
57634
  return rpc("botApprovalTemplateSet", {
@@ -54762,11 +57637,11 @@ async function runApprovalTemplateCommand(command, rest, values, io, connect) {
54762
57637
  });
54763
57638
  }
54764
57639
  const { subcommand, args } = normalize(command, rest);
54765
- if (args.length !== POSITIONALS[subcommand] || args.some((value) => !value.trim())) usage$6(subcommand === "list" ? "approval-template list takes no positional arguments." : `approval-template ${subcommand} needs exactly one template name.`);
57640
+ if (args.length !== POSITIONALS[subcommand] || args.some((value) => !value.trim())) usage$7(subcommand === "list" ? "approval-template list takes no positional arguments." : `approval-template ${subcommand} needs exactly one template name.`);
54766
57641
  const name = args[0]?.trim() ?? "";
54767
57642
  if (subcommand === "create") {
54768
57643
  const from = values.from?.trim();
54769
- if (from !== void 0 && (values.file !== void 0 || values["text-stdin"] === true)) usage$6("approval-template create takes --from, or the text with --file or --text-stdin.");
57644
+ if (from !== void 0 && (values.file !== void 0 || values["text-stdin"] === true)) usage$7("approval-template create takes --from, or the text with --file or --text-stdin.");
54770
57645
  const text = from === void 0 ? await templateText(values, io) : void 0;
54771
57646
  return (await connect())("approvalTemplateCreate", {
54772
57647
  name,
@@ -54810,19 +57685,19 @@ const APPROVAL_REVIEWER_COMMANDS = [{
54810
57685
  function isApprovalReviewerCommand(command) {
54811
57686
  return APPROVAL_REVIEWER_COMMANDS.some((entry) => entry.command === command);
54812
57687
  }
54813
- function usage$5(message) {
57688
+ function usage$6(message) {
54814
57689
  throw new CliLiveError("usage", message);
54815
57690
  }
54816
57691
  function modelArgument(value, effort) {
54817
57692
  if (value === "bot") {
54818
- if (effort !== void 0) usage$5("--effort applies only to a named model, not `bot`.");
57693
+ if (effort !== void 0) usage$6("--effort applies only to a named model, not `bot`.");
54819
57694
  return null;
54820
57695
  }
54821
57696
  const slash = value.indexOf("/");
54822
57697
  const provider = slash < 0 ? "" : value.slice(0, slash).trim();
54823
57698
  const model = slash < 0 ? "" : value.slice(slash + 1).trim();
54824
- if (!provider || !model) usage$5("approval-reviewer-model-set needs <provider>/<model> (for example deepseek/<model>) or bot.");
54825
- if (effort !== void 0 && !effort.trim()) usage$5("--effort must not be empty.");
57699
+ if (!provider || !model) usage$6("approval-reviewer-model-set needs <provider>/<model> (for example deepseek/<model>) or bot.");
57700
+ if (effort !== void 0 && !effort.trim()) usage$6("--effort must not be empty.");
54826
57701
  return {
54827
57702
  provider,
54828
57703
  model,
@@ -54831,16 +57706,71 @@ function modelArgument(value, effort) {
54831
57706
  }
54832
57707
  async function runApprovalReviewerCommand(command, rest, values, connect) {
54833
57708
  if (command === "approval-reviewer-model") {
54834
- if (rest.length !== 0 || values.effort !== void 0) usage$5("approval-reviewer-model takes no arguments.");
57709
+ if (rest.length !== 0 || values.effort !== void 0) usage$6("approval-reviewer-model takes no arguments.");
54835
57710
  return (await connect())("approvalReviewerModel", {});
54836
57711
  }
54837
- if (rest.length !== 1 || !rest[0].trim()) usage$5("approval-reviewer-model-set needs exactly one <provider>/<model>, or bot.");
57712
+ if (rest.length !== 1 || !rest[0].trim()) usage$6("approval-reviewer-model-set needs exactly one <provider>/<model>, or bot.");
54838
57713
  const model = modelArgument(rest[0].trim(), values.effort);
54839
57714
  return (await connect())("approvalReviewerModelSet", { model });
54840
57715
  }
54841
57716
  //#endregion
57717
+ //#region packages/core/src/runtime/idle-compaction-settings.ts
57718
+ const MAX_CACHE_LIFETIME_SECONDS = 604800;
57719
+ //#endregion
57720
+ //#region packages/core/src/bots/cli-idle-compaction.ts
57721
+ const IDLE_COMPACTION_COMMANDS = [
57722
+ {
57723
+ command: "idle-compaction",
57724
+ description: "show whether idle Orchestrator Sessions are compacted while their prompt cache is warm, and each route’s cache lifetime"
57725
+ },
57726
+ {
57727
+ command: "idle-compaction-set",
57728
+ description: "turn idle compaction on or off for every Bot (on | off)"
57729
+ },
57730
+ {
57731
+ command: "idle-compaction-cache-set",
57732
+ description: "set one route’s prompt-cache lifetime in seconds (<provider>/<model> <seconds>), or `auto` to resolve it again"
57733
+ }
57734
+ ];
57735
+ function isIdleCompactionCommand(command) {
57736
+ return IDLE_COMPACTION_COMMANDS.some((entry) => entry.command === command);
57737
+ }
57738
+ function usage$5(message) {
57739
+ throw new CliLiveError("usage", message);
57740
+ }
57741
+ async function runIdleCompactionCommand(command, rest, connect) {
57742
+ if (command === "idle-compaction") {
57743
+ if (rest.length !== 0) usage$5("idle-compaction takes no arguments.");
57744
+ return (await connect())("idleCompaction", {});
57745
+ }
57746
+ if (command === "idle-compaction-set") {
57747
+ const value = rest.length === 1 ? rest[0].trim() : "";
57748
+ if (value !== "on" && value !== "off") usage$5("idle-compaction-set needs exactly on or off.");
57749
+ return (await connect())("idleCompactionSet", { enabled: value === "on" });
57750
+ }
57751
+ if (rest.length !== 2) usage$5("idle-compaction-cache-set needs <provider>/<model> and <seconds> or auto.");
57752
+ const route = rest[0].trim();
57753
+ const slash = route.indexOf("/");
57754
+ const provider = slash < 0 ? "" : route.slice(0, slash).trim();
57755
+ const model = slash < 0 ? "" : route.slice(slash + 1).trim();
57756
+ if (!provider || !model) usage$5("idle-compaction-cache-set needs <provider>/<model>, for example deepseek/<model>.");
57757
+ const value = rest[1].trim();
57758
+ let seconds = null;
57759
+ if (value !== "auto") {
57760
+ if (!/^\d+$/u.test(value) || Number(value) > 604800) usage$5(`idle-compaction-cache-set needs whole seconds from 0 to ${MAX_CACHE_LIFETIME_SECONDS}, or auto.`);
57761
+ seconds = Number(value);
57762
+ }
57763
+ return (await connect())("idleCompactionCacheLifetimeSet", {
57764
+ provider,
57765
+ model,
57766
+ seconds
57767
+ });
57768
+ }
57769
+ //#endregion
54842
57770
  //#region packages/core/src/bots/cli-live.ts
54843
57771
  const LIVE_OPTIONS = {
57772
+ ...WINDOW_ZOOM_OPTIONS,
57773
+ ...APPEARANCE_OPTIONS,
54844
57774
  ...IM_OPTIONS,
54845
57775
  ...MESSAGING_OPTIONS,
54846
57776
  ...MODELS_USAGE_OPTIONS,
@@ -54855,6 +57785,9 @@ const LIVE_OPTIONS = {
54855
57785
  ...APPROVAL_REVIEWER_OPTIONS,
54856
57786
  host: { type: "string" },
54857
57787
  "token-file": { type: "string" },
57788
+ "image-source": { type: "string" },
57789
+ "image-revision": { type: "string" },
57790
+ "image-reference": { type: "string" },
54858
57791
  timeout: { type: "string" },
54859
57792
  "message-id": { type: "string" },
54860
57793
  outcome: { type: "string" },
@@ -54934,6 +57867,7 @@ const CONTROL_COMMANDS = [
54934
57867
  "group-create"
54935
57868
  ];
54936
57869
  const LIVE_COMMANDS = [
57870
+ ...WINDOW_ZOOM_COMMANDS,
54937
57871
  ...IM_COMMANDS,
54938
57872
  ...MESSAGING_COMMANDS,
54939
57873
  {
@@ -54947,6 +57881,7 @@ const LIVE_COMMANDS = [
54947
57881
  ...MODELS_USAGE_COMMANDS,
54948
57882
  ...CHANNEL_COMMANDS,
54949
57883
  ...HOST_ADMIN_COMMANDS,
57884
+ ...APPEARANCE_COMMANDS,
54950
57885
  ...INBOX_COMMANDS,
54951
57886
  ...BROWSER_COMPUTER_COMMANDS,
54952
57887
  ...PROFILE_COMMANDS,
@@ -54954,6 +57889,7 @@ const LIVE_COMMANDS = [
54954
57889
  ...TODO_COMMANDS,
54955
57890
  ...APPROVAL_TEMPLATE_COMMANDS,
54956
57891
  ...APPROVAL_REVIEWER_COMMANDS,
57892
+ ...IDLE_COMPACTION_COMMANDS,
54957
57893
  {
54958
57894
  command: "send",
54959
57895
  description: "send a Human DM and collect its committed Bot reply from a live Host"
@@ -55134,6 +58070,10 @@ const LIVE_COMMANDS = [
55134
58070
  command: "browser-tool",
55135
58071
  description: "run one Browser tool directly for a Bot, without the model (args JSON from stdin)"
55136
58072
  },
58073
+ {
58074
+ command: "memory-image",
58075
+ description: "export version-bound Memory image bytes (--path --image-source --image-revision [--image-reference] --out)"
58076
+ },
55137
58077
  {
55138
58078
  command: "memory-file-target",
55139
58079
  description: "resolve a memory file path for a Bot"
@@ -55408,6 +58348,7 @@ async function runLiveCli(command, rest, values, io) {
55408
58348
  if (isModelsUsageCommand(command)) return runModelsUsage(command, rest, values, io, async () => {
55409
58349
  return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc;
55410
58350
  });
58351
+ if (WINDOW_ZOOM_COMMANDS.some((entry) => entry.command === command)) return runWindowZoomCommand(command, rest, values, () => connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout))));
55411
58352
  if (command === "cloud-work") {
55412
58353
  const input = await prepareCloudWork(rest, values, io);
55413
58354
  return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc("cloudWork", input);
@@ -55420,12 +58361,16 @@ async function runLiveCli(command, rest, values, io) {
55420
58361
  if (isInboxCommand(command)) return runInboxCommand(command, rest, values, () => connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout))));
55421
58362
  if (isScheduleCommand(command)) return runScheduleCommand(prepareScheduleCommand(command, rest, values), (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc);
55422
58363
  if (isBrowserComputerCommand(command)) return runBrowserComputerCommand(command, rest, values, io, () => connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout))));
58364
+ if (APPEARANCE_COMMANDS.some((entry) => entry.command === command)) return runAppearanceCommand(command, rest, values, io, () => connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout))));
55423
58365
  if (isProfileCommand(command)) return runProfileCommand(command, rest, values, io, async () => {
55424
58366
  return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc;
55425
58367
  });
55426
58368
  if (isApprovalReviewerCommand(command)) return runApprovalReviewerCommand(command, rest, values, async () => {
55427
58369
  return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc;
55428
58370
  });
58371
+ if (isIdleCompactionCommand(command)) return runIdleCompactionCommand(command, rest, async () => {
58372
+ return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc;
58373
+ });
55429
58374
  if (isApprovalTemplateCommand(command)) return runApprovalTemplateCommand(command, rest, values, io, async () => {
55430
58375
  return (await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)))).rpc;
55431
58376
  });
@@ -55497,7 +58442,7 @@ async function runLiveCli(command, rest, values, io) {
55497
58442
  if (!body?.trim()) usage$4("send requires a nonempty message.");
55498
58443
  if (messageId !== void 0 && !/^human-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(messageId)) usage$4("--message-id must be human- followed by a UUID.");
55499
58444
  }
55500
- if (command === "tool-approval-decide" && values.outcome !== "allowed-once" && values.outcome !== "allowed-always-kind" && values.outcome !== "rejected") usage$4("--outcome must be allowed-once, allowed-always-kind or rejected.");
58445
+ if (command === "tool-approval-decide" && values.outcome !== "allowed-once" && values.outcome !== "allowed-always-tool" && values.outcome !== "allowed-always-kind" && values.outcome !== "rejected") usage$4("--outcome must be allowed-once, allowed-always-tool, allowed-always-kind or rejected.");
55501
58446
  if (command === "user-question-answer") {
55502
58447
  if (!values["answer-stdin"]) usage$4("user-question-answer requires --answer-stdin.");
55503
58448
  try {
@@ -55991,6 +58936,7 @@ async function runDeviceCommand(command, rest, values, io) {
55991
58936
  const MEMORY_COMMANDS = /* @__PURE__ */ new Set([
55992
58937
  "memory-snapshot",
55993
58938
  "memory-file",
58939
+ "memory-image",
55994
58940
  "memory-history",
55995
58941
  "memory-diff",
55996
58942
  "memory-save",
@@ -56034,6 +58980,40 @@ async function runMemoryCommand(command, rest, values, io) {
56034
58980
  case "memory-snapshot":
56035
58981
  [method, args] = ["memorySnapshot", { channelId }];
56036
58982
  break;
58983
+ case "memory-image": {
58984
+ const path = required("path", "path <file>");
58985
+ const source = required("image-source", "image-source worktree|index|<commit>");
58986
+ const revision = required("image-revision", "image-revision <sha256>");
58987
+ const out = required("out", "out <absolute file>");
58988
+ if (!isAbsolute(out)) usage$4("--out must be an absolute path.");
58989
+ const host = await connectLiveHost(values, io, AbortSignal.timeout(timeoutMs(values.timeout)));
58990
+ const reference = values["image-reference"];
58991
+ const { bytes, response } = await host.http("/api/botharness/memory/image?" + new URLSearchParams({
58992
+ slug,
58993
+ path,
58994
+ source,
58995
+ revision,
58996
+ ...reference === void 0 ? {} : { reference }
58997
+ }));
58998
+ const mime = response.headers.get("content-type");
58999
+ if (![
59000
+ "image/png",
59001
+ "image/jpeg",
59002
+ "image/gif",
59003
+ "image/webp",
59004
+ "image/svg+xml"
59005
+ ].includes(mime ?? "")) throw new CliLiveError("host-protocol-error", "Expected a supported Memory image");
59006
+ writeFileSync(out, bytes, { flag: "wx" });
59007
+ return {
59008
+ path,
59009
+ source,
59010
+ revision,
59011
+ ...reference === void 0 ? {} : { reference },
59012
+ mime,
59013
+ bytes: bytes.length,
59014
+ out
59015
+ };
59016
+ }
56037
59017
  case "memory-file":
56038
59018
  [method, args] = ["memoryFile", {
56039
59019
  channelId,
@@ -56908,9 +59888,9 @@ async function runAgentCli(command, rest, values, io) {
56908
59888
  });
56909
59889
  }
56910
59890
  }
56911
- const seconds = values["timeout"] === void 0 ? 120 : Number(values["timeout"]);
56912
- if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 600) refuse("usage", "--timeout must be between 0 and 600 seconds.");
56913
59891
  const write = managed?.write ?? operation === "settings-set";
59892
+ const seconds = values["timeout"] === void 0 ? write ? 600 : 120 : Number(values["timeout"]);
59893
+ if (!Number.isFinite(seconds) || seconds <= 0 || seconds > 600) refuse("usage", "--timeout must be between 0 and 600 seconds.");
56914
59894
  let response;
56915
59895
  let body;
56916
59896
  try {
@@ -56978,6 +59958,10 @@ const LIFECYCLE_COMMANDS = [
56978
59958
  command: "bot-new-session",
56979
59959
  description: "retire an idle Bot's Orchestrator Session; the next message starts a fresh one"
56980
59960
  },
59961
+ {
59962
+ command: "bot-compact",
59963
+ description: "compact an idle Bot's Orchestrator Session now through DSH /compact; refuses while it works"
59964
+ },
56981
59965
  {
56982
59966
  command: "bot-delete-preview",
56983
59967
  description: "inspect the current PersonaBot deletion scope and confirmation token"
@@ -57089,6 +60073,7 @@ async function runOnlineManagement(command, rest, values, io, create, bundle) {
57089
60073
  }
57090
60074
  if (command === "model-plan") return rpc("modelPlan", { slug });
57091
60075
  if (command === "bot-new-session") return rpc("botNewSession", { slug });
60076
+ if (command === "bot-compact") return rpc("botCompact", { slug });
57092
60077
  if (command === "bot-delete-preview") return rpc("deletionPreview", { slug });
57093
60078
  if (command === "bot-delete-memory-folder") return rpc("deletionMemoryFolder", { slug });
57094
60079
  if (command === "bot-delete-confirm") return rpc("deletionConfirm", {