@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/CHANGELOG.md +51 -1
- package/CHANGELOG.zh.md +51 -1
- package/cli/index.mjs +3241 -256
- package/dist/index.d.mts +199 -41
- package/dist/index.mjs +4818 -329
- package/package.json +3 -1
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$
|
|
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$
|
|
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
|
-
|
|
44771
|
-
|
|
44772
|
-
path
|
|
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",
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
51598
|
-
if (values.sort !== void 0 && values.sort !== "newest" && values.sort !== "oldest" && !(values.sort === "mentions-first" && values.category === "replies")) usage$
|
|
51599
|
-
if (values.search !== void 0 && values.search.length > 200) usage$
|
|
51600
|
-
if (values.kind !== void 0 && values.kind !== "auto-rejection") usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54986
|
+
usage$16("Cannot read --avatar-file.");
|
|
52112
54987
|
}
|
|
52113
|
-
if (bytes.length === 0 || bytes.length > MAX_AVATAR_BYTES) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
52237
|
-
if (values.direction === "around" && !values.around?.trim()) usage$
|
|
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$
|
|
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$
|
|
52298
|
-
if (values["confirmation-stdin"] !== true) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
52525
|
-
if (values.out !== void 0 && !absolute(values.out)) usage$
|
|
52526
|
-
if (values.dir !== void 0 && !absolute(values.dir)) usage$
|
|
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$
|
|
52529
|
-
if (command === "browser-profile-set" && !values.profile?.trim()) usage$
|
|
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$
|
|
52532
|
-
if (command === "computer-import" && !archiveName(target)) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
52767
|
-
} else if (count === 1 && !/^[A-Za-z0-9_-]{1,128}$/u.test(target)) usage$
|
|
52768
|
-
if (values["credentials-stdin"] && command !== "im-credentials") usage$
|
|
52769
|
-
if (values["verification-stdin"] && command !== "im-verify") usage$
|
|
52770
|
-
if (values.wait && command !== "pairing-status") usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
53126
|
-
} else if (values["input-stdin"] === true) usage$
|
|
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$
|
|
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$
|
|
53131
|
-
if (text.length > 4e3) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
56407
|
+
usage$12("Plan stdin must be one JSON object.");
|
|
53533
56408
|
}
|
|
53534
|
-
if (typeof input !== "object" || input === null || Array.isArray(input)) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
53861
|
-
if (values.sort !== void 0 && (command !== "marketplace-list" || values.sort !== "updated" && values.sort !== "stars")) usage$
|
|
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$
|
|
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$
|
|
53866
|
-
if (command === "telemetry-set" && values.enabled === values.disabled) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
53875
|
-
if (kind === "revoke" && values.confirm !== true) usage$
|
|
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$
|
|
53879
|
-
if (roles.length === 1 === capabilities.length > 0) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
54107
|
-
const trigger = scheduleTriggerFromFlags(values, usage$
|
|
54108
|
-
if (trigger === void 0) throw usage$
|
|
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$
|
|
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$
|
|
54125
|
-
const trigger = scheduleTriggerFromFlags(values, usage$
|
|
54126
|
-
if (trigger === void 0) throw usage$
|
|
54127
|
-
const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$
|
|
54128
|
-
const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$
|
|
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$
|
|
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$
|
|
54149
|
-
const enabled = scheduleToggleFromFlags(values, "enabled", "disabled", usage$
|
|
54150
|
-
const locked = scheduleToggleFromFlags(values, "locked", "unlocked", usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54416
|
-
if (values.color !== void 0 && !/^#[0-9a-f]{6}$/iu.test(values.color)) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54486
|
-
if (ids(channelIds).length === 0) usage$
|
|
54487
|
-
if (action !== "move" && values.section !== void 0) usage$
|
|
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$
|
|
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$
|
|
54501
|
-
if (!values.name?.trim()) usage$
|
|
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$
|
|
54508
|
-
if (values.confirm !== true) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54568
|
-
if (values["part-id"] !== void 0 && values["part-stdin"] === true) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54640
|
-
if (values.done === true && values["not-done"] === true) usage$
|
|
54641
|
-
if (command === "todo-update" && title === void 0 && !values.done && !values["not-done"]) usage$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
54825
|
-
if (effort !== void 0 && !effort.trim()) usage$
|
|
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$
|
|
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$
|
|
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", {
|