@craftsamo/telegram-tools 0.1.0 → 0.3.0
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/.antigravity-plugin/plugin.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -1
- package/README.md +69 -22
- package/dist/cli.js +961 -865
- package/dist/mcp.js +463 -351
- package/dist/opencode.js +531 -398
- package/package.json +1 -1
- package/plugin.yaml +7 -4
- package/src/hermes/telegram_tools_hermes/approval.py +18 -14
- package/src/hermes/telegram_tools_hermes/plugin.py +3 -3
- package/src/hermes/telegram_tools_hermes/project.py +6 -0
- package/src/hermes/telegram_tools_hermes/settings.py +61 -63
- package/src/hermes/telegram_tools_hermes/tools.py +10 -3
package/dist/opencode.js
CHANGED
|
@@ -25,6 +25,21 @@ var PROJECT = {
|
|
|
25
25
|
toolsets: ["account", "chats", "sync", "files", "sends", "actions"],
|
|
26
26
|
/** The toolsets on when a setting names none. */
|
|
27
27
|
defaultToolsets: ["account", "chats", "sync", "sends"],
|
|
28
|
+
/** The package's own settings, which the tools themselves read: each snake_case name and its type, with bounds when it needs them. */
|
|
29
|
+
options: {
|
|
30
|
+
/** Where every account's state lives. */
|
|
31
|
+
state_dir: "path",
|
|
32
|
+
/** Where received files are saved. */
|
|
33
|
+
download_dir: "path",
|
|
34
|
+
/** The largest received file a call may download, in megabytes. */
|
|
35
|
+
download_max_mb: { type: "number", integer: true, min: 1, max: 2e3 },
|
|
36
|
+
/** The directories files may be sent from, besides the working directory. */
|
|
37
|
+
send_dirs: "paths",
|
|
38
|
+
/** Whether messages that disappear are kept; read by the sync service's commands. */
|
|
39
|
+
keep_disappearing: "boolean",
|
|
40
|
+
/** Whether channels are listed and their messages received; read by the sync service's commands. */
|
|
41
|
+
channels: "boolean"
|
|
42
|
+
},
|
|
28
43
|
/** The environment variables the tools read besides the settings, which Codex forwards to the server after them. */
|
|
29
44
|
toolVariables: []
|
|
30
45
|
};
|
|
@@ -5099,7 +5114,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5099
5114
|
var NONE = 0;
|
|
5100
5115
|
var ASSUMED = 1;
|
|
5101
5116
|
var PROVEN = 2;
|
|
5102
|
-
function isRecursive(inst, stack,
|
|
5117
|
+
function isRecursive(inst, stack, resolve6) {
|
|
5103
5118
|
const cached2 = recursive.get(inst);
|
|
5104
5119
|
if (cached2 !== void 0)
|
|
5105
5120
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5109,7 +5124,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5109
5124
|
let result = NONE;
|
|
5110
5125
|
const check2 = (child) => {
|
|
5111
5126
|
if (result !== PROVEN && child?._zod) {
|
|
5112
|
-
const answer = isRecursive(child, stack,
|
|
5127
|
+
const answer = isRecursive(child, stack, resolve6);
|
|
5113
5128
|
if (answer > result)
|
|
5114
5129
|
result = answer;
|
|
5115
5130
|
}
|
|
@@ -5120,7 +5135,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5120
5135
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5121
5136
|
if (spread && !desc.enumerable)
|
|
5122
5137
|
continue;
|
|
5123
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5138
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve6) : NONE;
|
|
5124
5139
|
if (child > answer)
|
|
5125
5140
|
answer = child;
|
|
5126
5141
|
}
|
|
@@ -5184,7 +5199,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
5184
5199
|
break;
|
|
5185
5200
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5186
5201
|
case "lazy": {
|
|
5187
|
-
const inner = def._cachedInner ?? (
|
|
5202
|
+
const inner = def._cachedInner ?? (resolve6 ? inst._zod.innerType : void 0);
|
|
5188
5203
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5189
5204
|
break;
|
|
5190
5205
|
}
|
|
@@ -9382,8 +9397,8 @@ function ko_default() {
|
|
|
9382
9397
|
}
|
|
9383
9398
|
|
|
9384
9399
|
// node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/lt.js
|
|
9385
|
-
var capitalizeFirstCharacter = (
|
|
9386
|
-
return
|
|
9400
|
+
var capitalizeFirstCharacter = (text2) => {
|
|
9401
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
9387
9402
|
};
|
|
9388
9403
|
function getUnitTypeFromNumber(number4) {
|
|
9389
9404
|
const abs = Math.abs(number4);
|
|
@@ -19788,8 +19803,8 @@ function quoteBadLabel(value) {
|
|
|
19788
19803
|
const truncated = value.length > MAX_BAD_LABEL_PREVIEW ? `${value.slice(0, MAX_BAD_LABEL_PREVIEW)}\u2026` : value;
|
|
19789
19804
|
return JSON.stringify(truncated);
|
|
19790
19805
|
}
|
|
19791
|
-
function isLabel(
|
|
19792
|
-
return typeof
|
|
19806
|
+
function isLabel(text2) {
|
|
19807
|
+
return typeof text2 === "string" && LABEL_PATTERN.test(text2);
|
|
19793
19808
|
}
|
|
19794
19809
|
function checkLabel(label) {
|
|
19795
19810
|
if (!isLabel(label)) {
|
|
@@ -20008,6 +20023,7 @@ function lockHolder(path) {
|
|
|
20008
20023
|
}
|
|
20009
20024
|
|
|
20010
20025
|
// src/core/time.ts
|
|
20026
|
+
var MS_PER_S = 1e3;
|
|
20011
20027
|
var MS_PER_MINUTE = 6e4;
|
|
20012
20028
|
var MINUTES_PER_HOUR = 60;
|
|
20013
20029
|
var localOffsetMinutes = (ms) => -new Date(ms).getTimezoneOffset();
|
|
@@ -20027,10 +20043,10 @@ var MILLISECOND_DIGITS = 3;
|
|
|
20027
20043
|
var MIN_YEAR = 1e3;
|
|
20028
20044
|
var MAX_HOUR = 23;
|
|
20029
20045
|
var MAX_MINUTE = 59;
|
|
20030
|
-
function badTime(
|
|
20046
|
+
function badTime(text2, name) {
|
|
20031
20047
|
return new ToolError(
|
|
20032
20048
|
"invalid_argument",
|
|
20033
|
-
`${name} is not a time: ${JSON.stringify(
|
|
20049
|
+
`${name} is not a time: ${JSON.stringify(text2)}. Use RFC 3339 with an offset (2026-11-07T14:03:12+09:00), or a date or time without one (2026-11-07, 2026-11-07T14:03), which reads as local time.`
|
|
20034
20050
|
);
|
|
20035
20051
|
}
|
|
20036
20052
|
function isCalendarDay(year, month, day) {
|
|
@@ -20038,21 +20054,21 @@ function isCalendarDay(year, month, day) {
|
|
|
20038
20054
|
date5.setUTCFullYear(year, month - 1, day);
|
|
20039
20055
|
return date5.getUTCFullYear() === year && date5.getUTCMonth() === month - 1 && date5.getUTCDate() === day;
|
|
20040
20056
|
}
|
|
20041
|
-
function parseTimeArgument(
|
|
20042
|
-
const match = TIME_PATTERN.exec(
|
|
20043
|
-
if (!match) throw badTime(
|
|
20057
|
+
function parseTimeArgument(text2, name) {
|
|
20058
|
+
const match = TIME_PATTERN.exec(text2.trim());
|
|
20059
|
+
if (!match) throw badTime(text2, name);
|
|
20044
20060
|
const [, year, month, day, hour = "0", minute = "0", second = "0", fraction = "", zulu, sign, offsetHour, offsetMin] = match;
|
|
20045
20061
|
const [y, mon, d, h, mi, s] = [year, month, day, hour, minute, second].map(Number);
|
|
20046
20062
|
const ms = Number(fraction.padEnd(MILLISECOND_DIGITS, "0").slice(0, MILLISECOND_DIGITS));
|
|
20047
20063
|
if (y < MIN_YEAR || !isCalendarDay(y, mon, d) || h > MAX_HOUR || mi > MAX_MINUTE || s > MAX_MINUTE) {
|
|
20048
|
-
throw badTime(
|
|
20064
|
+
throw badTime(text2, name);
|
|
20049
20065
|
}
|
|
20050
20066
|
if (sign === void 0 && zulu === void 0) return new Date(y, mon - 1, d, h, mi, s, ms).getTime();
|
|
20051
20067
|
const wall = Date.UTC(y, mon - 1, d, h, mi, s, ms);
|
|
20052
20068
|
if (zulu) return wall;
|
|
20053
20069
|
const offsetH = Number(offsetHour);
|
|
20054
20070
|
const offsetM = Number(offsetMin);
|
|
20055
|
-
if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(
|
|
20071
|
+
if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(text2, name);
|
|
20056
20072
|
const offset = (offsetH * MINUTES_PER_HOUR + offsetM) * MS_PER_MINUTE;
|
|
20057
20073
|
return sign === "-" ? wall + offset : wall - offset;
|
|
20058
20074
|
}
|
|
@@ -20387,23 +20403,23 @@ function encodeCursor(value) {
|
|
|
20387
20403
|
function notACursor(name) {
|
|
20388
20404
|
return new ToolError("invalid_argument", `${name} is not a cursor this tool returned.`);
|
|
20389
20405
|
}
|
|
20390
|
-
function decodeCursor(
|
|
20391
|
-
const bytes = Buffer3.from(
|
|
20392
|
-
if (bytes.toString("base64url") !==
|
|
20406
|
+
function decodeCursor(text2, name) {
|
|
20407
|
+
const bytes = Buffer3.from(text2, "base64url");
|
|
20408
|
+
if (bytes.toString("base64url") !== text2) throw notACursor(name);
|
|
20393
20409
|
try {
|
|
20394
20410
|
return JSON.parse(bytes.toString("utf8"));
|
|
20395
20411
|
} catch {
|
|
20396
20412
|
throw notACursor(name);
|
|
20397
20413
|
}
|
|
20398
20414
|
}
|
|
20399
|
-
function readCursor(
|
|
20400
|
-
const parsed = schema.safeParse(decodeCursor(
|
|
20415
|
+
function readCursor(text2, name, schema) {
|
|
20416
|
+
const parsed = schema.safeParse(decodeCursor(text2, name));
|
|
20401
20417
|
if (!parsed.success) throw notACursor(name);
|
|
20402
20418
|
return parsed.data;
|
|
20403
20419
|
}
|
|
20404
20420
|
var HIGH_SURROGATE = /[\uD800-\uDBFF]$/;
|
|
20405
|
-
function cutText(
|
|
20406
|
-
return
|
|
20421
|
+
function cutText(text2, keep) {
|
|
20422
|
+
return text2.length <= keep ? text2 : text2.slice(0, keep).replace(HIGH_SURROGATE, "");
|
|
20407
20423
|
}
|
|
20408
20424
|
function jsonLength(value) {
|
|
20409
20425
|
return JSON.stringify(value).length;
|
|
@@ -20493,15 +20509,15 @@ var ERROR_CODES = {
|
|
|
20493
20509
|
function isErrorCode(value) {
|
|
20494
20510
|
return typeof value === "string" && Object.hasOwn(ERROR_CODES, value);
|
|
20495
20511
|
}
|
|
20496
|
-
function maskPhoneNumbers(
|
|
20497
|
-
return
|
|
20512
|
+
function maskPhoneNumbers(text2) {
|
|
20513
|
+
return text2.replace(PHONE_NUMBER, "[number]");
|
|
20498
20514
|
}
|
|
20499
20515
|
function cut(message) {
|
|
20500
20516
|
return maskPhoneNumbers(message).trim().slice(0, MAX_DETAIL_LENGTH);
|
|
20501
20517
|
}
|
|
20502
20518
|
function detail(message) {
|
|
20503
|
-
const
|
|
20504
|
-
return
|
|
20519
|
+
const text2 = cut(message);
|
|
20520
|
+
return text2 ? `: ${text2}` : "";
|
|
20505
20521
|
}
|
|
20506
20522
|
function afterWriteError(method, effect, reason) {
|
|
20507
20523
|
return effect === "write" ? new ToolError("uncertain", `${method} may have taken effect (${reason}). ${UNCERTAIN_ADVICE}`) : new ToolError("upstream_error", `${method} failed (${reason}).`);
|
|
@@ -20622,7 +20638,7 @@ function abortError(signal) {
|
|
|
20622
20638
|
}
|
|
20623
20639
|
function exec(argv, options) {
|
|
20624
20640
|
const { signal } = options;
|
|
20625
|
-
return new Promise((
|
|
20641
|
+
return new Promise((resolve6, reject) => {
|
|
20626
20642
|
if (signal?.aborted) {
|
|
20627
20643
|
reject(abortError(signal));
|
|
20628
20644
|
return;
|
|
@@ -20681,7 +20697,7 @@ function exec(argv, options) {
|
|
|
20681
20697
|
}
|
|
20682
20698
|
const finish = () => settle2(() => {
|
|
20683
20699
|
const { code, killedBy } = exitedWith ?? { code: null, killedBy: null };
|
|
20684
|
-
|
|
20700
|
+
resolve6({
|
|
20685
20701
|
code: code ?? -1,
|
|
20686
20702
|
stdout,
|
|
20687
20703
|
stderr,
|
|
@@ -20775,19 +20791,19 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
20775
20791
|
socket.on("error", (error62) => {
|
|
20776
20792
|
this.endReason ??= `the connection to the service broke${error62.code ? ` (${error62.code})` : ""}`;
|
|
20777
20793
|
});
|
|
20778
|
-
this.closed = new Promise((
|
|
20794
|
+
this.closed = new Promise((resolve6) => {
|
|
20779
20795
|
socket.once("close", () => {
|
|
20780
20796
|
this.endReason ??= "the service closed the connection";
|
|
20781
20797
|
const lost = { lost: this.endReason };
|
|
20782
20798
|
for (const settle2 of [...this.pending.values()]) settle2(lost);
|
|
20783
|
-
|
|
20799
|
+
resolve6();
|
|
20784
20800
|
});
|
|
20785
20801
|
});
|
|
20786
20802
|
}
|
|
20787
20803
|
/** Connects to the service's socket; rejects as `upstream_error` when nothing is listening there. */
|
|
20788
20804
|
static connect(socketPath, options = {}) {
|
|
20789
20805
|
const { timeoutMs = DEFAULT_CONNECT_TIMEOUT_MS, signal, maxLineLength = DEFAULT_MAX_LINE_LENGTH } = options;
|
|
20790
|
-
return new Promise((
|
|
20806
|
+
return new Promise((resolve6, reject) => {
|
|
20791
20807
|
if (signal?.aborted) {
|
|
20792
20808
|
reject(abortError(signal));
|
|
20793
20809
|
return;
|
|
@@ -20809,7 +20825,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
20809
20825
|
};
|
|
20810
20826
|
const onConnect = () => {
|
|
20811
20827
|
detach();
|
|
20812
|
-
|
|
20828
|
+
resolve6(new _ServiceConnection(socket, maxLineLength));
|
|
20813
20829
|
};
|
|
20814
20830
|
const onFailure = () => stop(new ToolError("upstream_error", NOT_RUNNING_MESSAGE));
|
|
20815
20831
|
const onAbort = () => stop(abortError(signal));
|
|
@@ -20832,7 +20848,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
20832
20848
|
*/
|
|
20833
20849
|
call(method, params, options) {
|
|
20834
20850
|
const { effect, timeoutMs = DEFAULT_CALL_TIMEOUT_MS, signal } = options;
|
|
20835
|
-
return new Promise((
|
|
20851
|
+
return new Promise((resolve6, reject) => {
|
|
20836
20852
|
if (signal?.aborted) {
|
|
20837
20853
|
reject(abortError(signal));
|
|
20838
20854
|
return;
|
|
@@ -20861,7 +20877,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
20861
20877
|
clearTimeout(timer);
|
|
20862
20878
|
signal?.removeEventListener("abort", onAbort);
|
|
20863
20879
|
try {
|
|
20864
|
-
|
|
20880
|
+
resolve6(produce());
|
|
20865
20881
|
} catch (error62) {
|
|
20866
20882
|
reject(error62);
|
|
20867
20883
|
}
|
|
@@ -20934,7 +20950,6 @@ async function callService(socketPath, method, params, options) {
|
|
|
20934
20950
|
// src/core/chat/live.ts
|
|
20935
20951
|
var REFRESH_TIMEOUT_MS = 12e4;
|
|
20936
20952
|
var FETCH_TIMEOUT_MS = 18e4;
|
|
20937
|
-
var MS_PER_S = 1e3;
|
|
20938
20953
|
function requestHistory(socket, params, signal) {
|
|
20939
20954
|
return callService(socket, SERVICE_REQUESTS.history, params, { effect: "read", signal });
|
|
20940
20955
|
}
|
|
@@ -21062,113 +21077,6 @@ var messageEntry = external_exports.object({
|
|
|
21062
21077
|
private_note: external_exports.string().optional()
|
|
21063
21078
|
});
|
|
21064
21079
|
|
|
21065
|
-
// src/core/chat/schema.ts
|
|
21066
|
-
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
21067
|
-
var GENERAL_TOPIC2 = 1;
|
|
21068
|
-
var LIMITS = {
|
|
21069
|
-
list: { default: 30, max: 200 },
|
|
21070
|
-
view: { default: 50, max: 300 },
|
|
21071
|
-
topics: { default: 30, max: TOPICS_LIMIT },
|
|
21072
|
-
search: { default: 30, max: 200 }
|
|
21073
|
-
};
|
|
21074
|
-
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
21075
|
-
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
21076
|
-
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
21077
|
-
var input3 = external_exports.object({
|
|
21078
|
-
method: external_exports.enum(METHODS).describe(
|
|
21079
|
-
"`list` finds chats; `view` reads the newest messages of one chat between two times, oldest first; `topics` lists the topics of a forum chat; `search` finds messages in the mirror by words; `around` reads the messages around one; `fetch` adds older history of a mirrored chat to the mirror."
|
|
21080
|
-
),
|
|
21081
|
-
account: accountArgument,
|
|
21082
|
-
query: external_exports.string().optional().describe(
|
|
21083
|
-
"list: only chats whose name or username holds this text; a leading @ is ignored. search (required): the words to look for, all of which a message must hold in its text, caption or file name, in any order. Both ignore case and letter width."
|
|
21084
|
-
),
|
|
21085
|
-
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
21086
|
-
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
21087
|
-
refresh: external_exports.boolean().optional().describe(
|
|
21088
|
-
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
21089
|
-
),
|
|
21090
|
-
chat: external_exports.string().optional().describe(
|
|
21091
|
-
"view, topics, around, fetch (required) and search (optional, to search one chat): the chat id, from `list`, such as 123456789 or -1001234567890. A name, username or phone number is not a chat."
|
|
21092
|
-
),
|
|
21093
|
-
topic: external_exports.number().int().positive().optional().describe(
|
|
21094
|
-
`view, around: only messages of this topic of a forum chat (ids from \`topics\`); the General topic is ${GENERAL_TOPIC2}. Refused for a chat without topics.`
|
|
21095
|
-
),
|
|
21096
|
-
after: external_exports.string().optional().describe(
|
|
21097
|
-
"view, search: only messages after this time (exclusive): RFC 3339 with an offset, or a date or time without one, read as local time, such as 2026-11-07 or 2026-11-07T14:03."
|
|
21098
|
-
),
|
|
21099
|
-
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
21100
|
-
limit: external_exports.number().int().optional().describe(
|
|
21101
|
-
`How many to return. list: default ${LIMITS.list.default}, at most ${LIMITS.list.max}. view: default ${LIMITS.view.default}, at most ${LIMITS.view.max} (${HISTORY_LIMIT} for a chat read live). topics: default ${LIMITS.topics.default}, at most ${LIMITS.topics.max}. search: default ${LIMITS.search.default}, at most ${LIMITS.search.max}. A larger value is lowered to the most; a result may hold fewer to stay a size a model can read.`
|
|
21102
|
-
),
|
|
21103
|
-
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
21104
|
-
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
21105
|
-
before_count: external_exports.number().int().optional().describe(
|
|
21106
|
-
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21107
|
-
),
|
|
21108
|
-
after_count: external_exports.number().int().optional().describe(
|
|
21109
|
-
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21110
|
-
),
|
|
21111
|
-
pages: external_exports.number().int().optional().describe(
|
|
21112
|
-
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
21113
|
-
)
|
|
21114
|
-
});
|
|
21115
|
-
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
21116
|
-
var chatEntry2 = external_exports.object({
|
|
21117
|
-
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
21118
|
-
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
21119
|
-
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
21120
|
-
name_cut: nameCut,
|
|
21121
|
-
username: external_exports.string().optional(),
|
|
21122
|
-
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
21123
|
-
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
21124
|
-
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
21125
|
-
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
21126
|
-
archived: external_exports.literal(true).optional(),
|
|
21127
|
-
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
21128
|
-
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
21129
|
-
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
21130
|
-
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
21131
|
-
});
|
|
21132
|
-
var topicEntry = external_exports.object({
|
|
21133
|
-
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC2} is the General topic.`),
|
|
21134
|
-
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
21135
|
-
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
21136
|
-
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
21137
|
-
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
21138
|
-
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
21139
|
-
});
|
|
21140
|
-
var output3 = external_exports.object({
|
|
21141
|
-
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
21142
|
-
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
21143
|
-
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
21144
|
-
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
21145
|
-
live: external_exports.literal(true).optional().describe(
|
|
21146
|
-
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
21147
|
-
),
|
|
21148
|
-
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
21149
|
-
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
21150
|
-
trimmed_before: external_exports.number().int().optional().describe(
|
|
21151
|
-
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
21152
|
-
),
|
|
21153
|
-
trimmed_after: external_exports.number().int().optional().describe(
|
|
21154
|
-
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
21155
|
-
),
|
|
21156
|
-
scanned_to: localTimeSchema.optional().describe(
|
|
21157
|
-
"search: set when the search stopped before the end of the history it covers: the time of the oldest message looked at, in local time with offset. `next` continues from there."
|
|
21158
|
-
),
|
|
21159
|
-
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
21160
|
-
fetched: external_exports.object({
|
|
21161
|
-
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
21162
|
-
pages: external_exports.number().int().describe("How many pages were read."),
|
|
21163
|
-
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
21164
|
-
oldest_at: localTimeSchema.nullable().describe(
|
|
21165
|
-
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
21166
|
-
)
|
|
21167
|
-
}).optional().describe("fetch: what the history fetch stored."),
|
|
21168
|
-
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
21169
|
-
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
21170
|
-
});
|
|
21171
|
-
|
|
21172
21080
|
// src/core/chat/message-rows.ts
|
|
21173
21081
|
var MESSAGE_COLUMNS = "chat, id, topic, ts, from_me, sender, sender_name, kind, body, entities, media, action, reply, forward, grouped, reactions, edited, expires, view_once, self_destruct";
|
|
21174
21082
|
function liveMessages(now) {
|
|
@@ -21176,7 +21084,7 @@ function liveMessages(now) {
|
|
|
21176
21084
|
}
|
|
21177
21085
|
function inTopic(topic) {
|
|
21178
21086
|
return {
|
|
21179
|
-
condition: topic ===
|
|
21087
|
+
condition: topic === GENERAL_TOPIC ? "(topic IS NULL OR topic = ?)" : "topic = ?",
|
|
21180
21088
|
params: [topic]
|
|
21181
21089
|
};
|
|
21182
21090
|
}
|
|
@@ -21289,10 +21197,10 @@ function replyTo(parsed, related) {
|
|
|
21289
21197
|
if (reply.chat !== void 0) entry2.chat = reply.chat;
|
|
21290
21198
|
if (reply.topic !== void 0) entry2.topic = reply.topic;
|
|
21291
21199
|
if (reply.quote !== void 0) entry2.quote = reply.quote;
|
|
21292
|
-
const
|
|
21293
|
-
if (
|
|
21294
|
-
entry2.text = cutText(
|
|
21295
|
-
if (entry2.text.length <
|
|
21200
|
+
const text2 = repliedText(parsed, related)?.text;
|
|
21201
|
+
if (text2 !== void 0) {
|
|
21202
|
+
entry2.text = cutText(text2, REPLY_TEXT_LENGTH);
|
|
21203
|
+
if (entry2.text.length < text2.length) entry2.text_cut = true;
|
|
21296
21204
|
}
|
|
21297
21205
|
return entry2;
|
|
21298
21206
|
}
|
|
@@ -21361,25 +21269,25 @@ function texts(entry2) {
|
|
|
21361
21269
|
];
|
|
21362
21270
|
}
|
|
21363
21271
|
function messageTextLength(entry2) {
|
|
21364
|
-
return texts(entry2).reduce((total,
|
|
21272
|
+
return texts(entry2).reduce((total, text2) => total + text2.length, 0);
|
|
21365
21273
|
}
|
|
21366
21274
|
function cutMessage(entry2, keep) {
|
|
21367
21275
|
let room = keep;
|
|
21368
21276
|
let cut3 = false;
|
|
21369
|
-
const take = (
|
|
21370
|
-
const kept = cutText(
|
|
21371
|
-
room = Math.max(0, room -
|
|
21372
|
-
if (kept.length <
|
|
21277
|
+
const take = (text2) => {
|
|
21278
|
+
const kept = cutText(text2, room);
|
|
21279
|
+
room = Math.max(0, room - text2.length);
|
|
21280
|
+
if (kept.length < text2.length) cut3 = true;
|
|
21373
21281
|
return kept;
|
|
21374
21282
|
};
|
|
21375
21283
|
const cutEntry = { ...entry2 };
|
|
21376
21284
|
if (entry2.text !== void 0) cutEntry.text = take(entry2.text);
|
|
21377
21285
|
if (entry2.reply_to) {
|
|
21378
|
-
const { quote, text } = entry2.reply_to;
|
|
21286
|
+
const { quote, text: text2 } = entry2.reply_to;
|
|
21379
21287
|
cutEntry.reply_to = {
|
|
21380
21288
|
...entry2.reply_to,
|
|
21381
21289
|
...quote === void 0 ? {} : { quote: take(quote) },
|
|
21382
|
-
...
|
|
21290
|
+
...text2 === void 0 ? {} : { text: take(text2) }
|
|
21383
21291
|
};
|
|
21384
21292
|
}
|
|
21385
21293
|
if (entry2.earlier_versions)
|
|
@@ -21401,6 +21309,112 @@ var cuttableMessage = {
|
|
|
21401
21309
|
drop: dropMetadata
|
|
21402
21310
|
};
|
|
21403
21311
|
|
|
21312
|
+
// src/core/chat/schema.ts
|
|
21313
|
+
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
21314
|
+
var LIMITS = {
|
|
21315
|
+
list: { default: 30, max: 200 },
|
|
21316
|
+
view: { default: 50, max: 300 },
|
|
21317
|
+
topics: { default: 30, max: TOPICS_LIMIT },
|
|
21318
|
+
search: { default: 30, max: 200 }
|
|
21319
|
+
};
|
|
21320
|
+
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
21321
|
+
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
21322
|
+
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
21323
|
+
var input3 = external_exports.object({
|
|
21324
|
+
method: external_exports.enum(METHODS).describe(
|
|
21325
|
+
"`list` finds chats; `view` reads the newest messages of one chat between two times, oldest first; `topics` lists the topics of a forum chat; `search` finds messages in the mirror by words; `around` reads the messages around one; `fetch` adds older history of a mirrored chat to the mirror."
|
|
21326
|
+
),
|
|
21327
|
+
account: accountArgument,
|
|
21328
|
+
query: external_exports.string().optional().describe(
|
|
21329
|
+
"list: only chats whose name or username holds this text; a leading @ is ignored. search (required): the words to look for, all of which a message must hold in its text, caption or file name, in any order. Both ignore case and letter width."
|
|
21330
|
+
),
|
|
21331
|
+
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
21332
|
+
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
21333
|
+
refresh: external_exports.boolean().optional().describe(
|
|
21334
|
+
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
21335
|
+
),
|
|
21336
|
+
chat: external_exports.string().optional().describe(
|
|
21337
|
+
"view, topics, around, fetch (required) and search (optional, to search one chat): the chat id, from `list`, such as 123456789 or -1001234567890. A name, username or phone number is not a chat."
|
|
21338
|
+
),
|
|
21339
|
+
topic: external_exports.number().int().positive().optional().describe(
|
|
21340
|
+
`view, around: only messages of this topic of a forum chat (ids from \`topics\`); the General topic is ${GENERAL_TOPIC}. Refused for a chat without topics.`
|
|
21341
|
+
),
|
|
21342
|
+
after: external_exports.string().optional().describe(
|
|
21343
|
+
"view, search: only messages after this time (exclusive): RFC 3339 with an offset, or a date or time without one, read as local time, such as 2026-11-07 or 2026-11-07T14:03."
|
|
21344
|
+
),
|
|
21345
|
+
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
21346
|
+
limit: external_exports.number().int().optional().describe(
|
|
21347
|
+
`How many to return. list: default ${LIMITS.list.default}, at most ${LIMITS.list.max}. view: default ${LIMITS.view.default}, at most ${LIMITS.view.max} (${HISTORY_LIMIT} for a chat read live). topics: default ${LIMITS.topics.default}, at most ${LIMITS.topics.max}. search: default ${LIMITS.search.default}, at most ${LIMITS.search.max}. A larger value is lowered to the most; a result may hold fewer to stay a size a model can read.`
|
|
21348
|
+
),
|
|
21349
|
+
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
21350
|
+
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
21351
|
+
before_count: external_exports.number().int().optional().describe(
|
|
21352
|
+
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21353
|
+
),
|
|
21354
|
+
after_count: external_exports.number().int().optional().describe(
|
|
21355
|
+
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
21356
|
+
),
|
|
21357
|
+
pages: external_exports.number().int().optional().describe(
|
|
21358
|
+
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
21359
|
+
)
|
|
21360
|
+
});
|
|
21361
|
+
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
21362
|
+
var chatEntry2 = external_exports.object({
|
|
21363
|
+
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
21364
|
+
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
21365
|
+
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
21366
|
+
name_cut: nameCut,
|
|
21367
|
+
username: external_exports.string().optional(),
|
|
21368
|
+
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
21369
|
+
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
21370
|
+
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
21371
|
+
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
21372
|
+
archived: external_exports.literal(true).optional(),
|
|
21373
|
+
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
21374
|
+
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
21375
|
+
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
21376
|
+
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
21377
|
+
});
|
|
21378
|
+
var topicEntry = external_exports.object({
|
|
21379
|
+
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC} is the General topic.`),
|
|
21380
|
+
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
21381
|
+
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
21382
|
+
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
21383
|
+
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
21384
|
+
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
21385
|
+
});
|
|
21386
|
+
var output3 = external_exports.object({
|
|
21387
|
+
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
21388
|
+
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
21389
|
+
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
21390
|
+
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
21391
|
+
live: external_exports.literal(true).optional().describe(
|
|
21392
|
+
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
21393
|
+
),
|
|
21394
|
+
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
21395
|
+
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
21396
|
+
trimmed_before: external_exports.number().int().optional().describe(
|
|
21397
|
+
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
21398
|
+
),
|
|
21399
|
+
trimmed_after: external_exports.number().int().optional().describe(
|
|
21400
|
+
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
21401
|
+
),
|
|
21402
|
+
scanned_to: localTimeSchema.optional().describe(
|
|
21403
|
+
"search: set when the search stopped before the end of the history it covers: the time of the oldest message looked at, in local time with offset. `next` continues from there."
|
|
21404
|
+
),
|
|
21405
|
+
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
21406
|
+
fetched: external_exports.object({
|
|
21407
|
+
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
21408
|
+
pages: external_exports.number().int().describe("How many pages were read."),
|
|
21409
|
+
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
21410
|
+
oldest_at: localTimeSchema.nullable().describe(
|
|
21411
|
+
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
21412
|
+
)
|
|
21413
|
+
}).optional().describe("fetch: what the history fetch stored."),
|
|
21414
|
+
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
21415
|
+
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
21416
|
+
});
|
|
21417
|
+
|
|
21404
21418
|
// src/core/chat/around.ts
|
|
21405
21419
|
var TRIMMED_RESERVE = 100;
|
|
21406
21420
|
var NO_MESSAGE = "No message with this id in this chat.";
|
|
@@ -21522,8 +21536,8 @@ function fetchResult(read, stored) {
|
|
|
21522
21536
|
}
|
|
21523
21537
|
|
|
21524
21538
|
// src/core/fold.ts
|
|
21525
|
-
function foldCase(
|
|
21526
|
-
return
|
|
21539
|
+
function foldCase(text2) {
|
|
21540
|
+
return text2.normalize("NFKC").toUpperCase().toLowerCase().replace(/ς/g, "\u03C3");
|
|
21527
21541
|
}
|
|
21528
21542
|
|
|
21529
21543
|
// src/core/chat/filter.ts
|
|
@@ -21603,7 +21617,7 @@ function listChats(mirror, args, now) {
|
|
|
21603
21617
|
return result;
|
|
21604
21618
|
}
|
|
21605
21619
|
|
|
21606
|
-
// src/core/
|
|
21620
|
+
// src/core/open.ts
|
|
21607
21621
|
async function pickPaths(ctx, account2) {
|
|
21608
21622
|
if (!ctx.stateDir) throw new ToolError("internal_error", "The entry point did not supply a state directory.");
|
|
21609
21623
|
return pickLabel(ctx.stateDir, account2);
|
|
@@ -21662,8 +21676,8 @@ function foldedFileName(media) {
|
|
|
21662
21676
|
return isRecord(info) && typeof info.name === "string" ? foldCase(info.name) : void 0;
|
|
21663
21677
|
}
|
|
21664
21678
|
function matchesAllWords(row, words2) {
|
|
21665
|
-
const
|
|
21666
|
-
const unmatched = words2.filter((word) => !
|
|
21679
|
+
const text2 = foldCase(row.body ?? "");
|
|
21680
|
+
const unmatched = words2.filter((word) => !text2.includes(word));
|
|
21667
21681
|
if (unmatched.length === 0) return true;
|
|
21668
21682
|
const name = row.media === null ? void 0 : foldedFileName(row.media);
|
|
21669
21683
|
return name !== void 0 && unmatched.every((word) => name.includes(word));
|
|
@@ -22023,6 +22037,56 @@ var CHAT_FACT_TRANSLATIONS = {
|
|
|
22023
22037
|
}
|
|
22024
22038
|
};
|
|
22025
22039
|
|
|
22040
|
+
// src/core/chat/media-facts.ts
|
|
22041
|
+
var MEDIA_KIND_WORDS = {
|
|
22042
|
+
photo: "Photo",
|
|
22043
|
+
document: "Document",
|
|
22044
|
+
audio: "Audio",
|
|
22045
|
+
voice: "Voice message",
|
|
22046
|
+
video: "Video",
|
|
22047
|
+
sticker: "Sticker",
|
|
22048
|
+
dice: "Dice",
|
|
22049
|
+
contact: "Contact",
|
|
22050
|
+
venue: "Venue",
|
|
22051
|
+
geo: "Location",
|
|
22052
|
+
geo_live: "Live location",
|
|
22053
|
+
game: "Game",
|
|
22054
|
+
invoice: "Invoice",
|
|
22055
|
+
webpage: "Link preview",
|
|
22056
|
+
poll: "Poll",
|
|
22057
|
+
todo: "Checklist",
|
|
22058
|
+
story: "Story",
|
|
22059
|
+
paid: "Paid media",
|
|
22060
|
+
unsupported: "Unsupported media"
|
|
22061
|
+
};
|
|
22062
|
+
function mediaKindValue(type) {
|
|
22063
|
+
return Object.hasOwn(MEDIA_KIND_WORDS, type) ? { text: MEDIA_KIND_WORDS[type] } : type;
|
|
22064
|
+
}
|
|
22065
|
+
var MEDIA_FACT_TRANSLATIONS = {
|
|
22066
|
+
ja: {
|
|
22067
|
+
Media: "\u30E1\u30C7\u30A3\u30A2",
|
|
22068
|
+
Photo: "\u5199\u771F",
|
|
22069
|
+
Document: "\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
22070
|
+
Audio: "\u97F3\u58F0",
|
|
22071
|
+
"Voice message": "\u30DC\u30A4\u30B9\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
22072
|
+
Video: "\u52D5\u753B",
|
|
22073
|
+
Sticker: "\u30B9\u30BF\u30F3\u30D7",
|
|
22074
|
+
Dice: "\u30B5\u30A4\u30B3\u30ED",
|
|
22075
|
+
Contact: "\u9023\u7D61\u5148",
|
|
22076
|
+
Venue: "\u5834\u6240",
|
|
22077
|
+
Location: "\u4F4D\u7F6E\u60C5\u5831",
|
|
22078
|
+
"Live location": "\u30E9\u30A4\u30D6\u4F4D\u7F6E\u60C5\u5831",
|
|
22079
|
+
Game: "\u30B2\u30FC\u30E0",
|
|
22080
|
+
Invoice: "\u8ACB\u6C42\u66F8",
|
|
22081
|
+
"Link preview": "\u30EA\u30F3\u30AF\u306E\u30D7\u30EC\u30D3\u30E5\u30FC",
|
|
22082
|
+
Poll: "\u6295\u7968",
|
|
22083
|
+
Checklist: "\u30C1\u30A7\u30C3\u30AF\u30EA\u30B9\u30C8",
|
|
22084
|
+
Story: "\u30B9\u30C8\u30FC\u30EA\u30FC",
|
|
22085
|
+
"Paid media": "\u6709\u6599\u30E1\u30C7\u30A3\u30A2",
|
|
22086
|
+
"Unsupported media": "\u672A\u5BFE\u5FDC\u306E\u30E1\u30C7\u30A3\u30A2"
|
|
22087
|
+
}
|
|
22088
|
+
};
|
|
22089
|
+
|
|
22026
22090
|
// src/core/facts.ts
|
|
22027
22091
|
function sizeFact(bytes) {
|
|
22028
22092
|
return { label: "Size", value: { text: bytes === 1 ? "{bytes} byte" : "{bytes} bytes", values: { bytes } } };
|
|
@@ -22257,11 +22321,11 @@ var ANIMATED_STICKER = "an animated sticker (.tgs), which cannot be inspected";
|
|
|
22257
22321
|
function unreadableArchive(label) {
|
|
22258
22322
|
return `an archive that cannot be inspected (${label})`;
|
|
22259
22323
|
}
|
|
22260
|
-
function words(
|
|
22261
|
-
return
|
|
22324
|
+
function words(text2) {
|
|
22325
|
+
return text2.split(/\s+/).filter((word) => word !== "");
|
|
22262
22326
|
}
|
|
22263
|
-
function ascii(
|
|
22264
|
-
return Array.from(
|
|
22327
|
+
function ascii(text2) {
|
|
22328
|
+
return Array.from(text2, (character) => character.charCodeAt(0));
|
|
22265
22329
|
}
|
|
22266
22330
|
function at(offset, bytes) {
|
|
22267
22331
|
return { offset, bytes };
|
|
@@ -22519,9 +22583,9 @@ function parseHeader(block) {
|
|
|
22519
22583
|
}
|
|
22520
22584
|
return { path, size: parseNumber(block.subarray(SIZE_START, SIZE_END)), type: block[TYPE_OFFSET] };
|
|
22521
22585
|
}
|
|
22522
|
-
function parseDecimal(
|
|
22523
|
-
if (!/^[0-9]{1,15}$/.test(
|
|
22524
|
-
return Number(
|
|
22586
|
+
function parseDecimal(text2) {
|
|
22587
|
+
if (!/^[0-9]{1,15}$/.test(text2)) return void 0;
|
|
22588
|
+
return Number(text2);
|
|
22525
22589
|
}
|
|
22526
22590
|
function parsePaxRecords(data, maxRecords = Infinity) {
|
|
22527
22591
|
const records = [];
|
|
@@ -22711,8 +22775,8 @@ var EXTENSIONS = {
|
|
|
22711
22775
|
};
|
|
22712
22776
|
var KIND_PATTERN = /^[a-z]{1,16}$/;
|
|
22713
22777
|
var UNKNOWN_KIND = "file";
|
|
22714
|
-
function byteLength(
|
|
22715
|
-
return Buffer5.byteLength(
|
|
22778
|
+
function byteLength(text2) {
|
|
22779
|
+
return Buffer5.byteLength(text2);
|
|
22716
22780
|
}
|
|
22717
22781
|
function extensionOf2(type) {
|
|
22718
22782
|
return type == null ? "" : EXTENSIONS[type.split(";")[0].trim().toLowerCase()] ?? "";
|
|
@@ -22981,8 +23045,8 @@ function fitListings(result) {
|
|
|
22981
23045
|
var MAX_NAME_CHARACTERS = 255;
|
|
22982
23046
|
var CUT_MARK = "\u2026";
|
|
22983
23047
|
var HIDDEN_CHARACTERS = /[\u0000-\u001F\u007F-\u009F\u00AD\u034F\u061C\u115F\u1160\u17B4\u17B5\u180B-\u180F\u200B-\u200F\u2028-\u202E\u2060-\u206F\u3164\uFE00-\uFE0D\uFEFF\uFFA0\uFFF9-\uFFFC\u{1D173}-\u{1D17A}\u{E0000}-\u{E007F}]/gu;
|
|
22984
|
-
function cleanName(
|
|
22985
|
-
const cleaned =
|
|
23048
|
+
function cleanName(text2) {
|
|
23049
|
+
const cleaned = text2.normalize("NFC").replace(HIDDEN_CHARACTERS, "?");
|
|
22986
23050
|
const characters = Array.from(cleaned);
|
|
22987
23051
|
if (characters.length <= MAX_NAME_CHARACTERS) return cleaned;
|
|
22988
23052
|
return characters.slice(0, MAX_NAME_CHARACTERS - CUT_MARK.length).join("") + CUT_MARK;
|
|
@@ -23155,9 +23219,9 @@ function decodeUtf8Lossy(bytes) {
|
|
|
23155
23219
|
return LOSSY_UTF8.decode(bytes);
|
|
23156
23220
|
}
|
|
23157
23221
|
function decodeCp437(bytes) {
|
|
23158
|
-
let
|
|
23159
|
-
for (const byte of bytes)
|
|
23160
|
-
return
|
|
23222
|
+
let text2 = "";
|
|
23223
|
+
for (const byte of bytes) text2 += byte < ASCII_END ? String.fromCharCode(byte) : CP437_HIGH[byte - ASCII_END];
|
|
23224
|
+
return text2;
|
|
23161
23225
|
}
|
|
23162
23226
|
|
|
23163
23227
|
// src/core/archive/tar.ts
|
|
@@ -23977,14 +24041,6 @@ function namesOf(file2, id) {
|
|
|
23977
24041
|
const name = safeFileName(file2.name, { kind: file2.kind, id, type: file2.type });
|
|
23978
24042
|
return { name, shown: file2.name === null ? file2.kind : name };
|
|
23979
24043
|
}
|
|
23980
|
-
var FILE_KIND_WORDS = {
|
|
23981
|
-
photo: "Photo",
|
|
23982
|
-
document: "Document",
|
|
23983
|
-
audio: "Audio",
|
|
23984
|
-
voice: "Voice message",
|
|
23985
|
-
video: "Video",
|
|
23986
|
-
sticker: "Sticker"
|
|
23987
|
-
};
|
|
23988
24044
|
function saveHeadline(file2, chat) {
|
|
23989
24045
|
if (file2 !== void 0 && chat !== null) return { text: "About to save {file} from {chat}", values: { file: file2, chat } };
|
|
23990
24046
|
if (chat !== null) return { text: "About to save a file from {chat}", values: { chat } };
|
|
@@ -23992,9 +24048,8 @@ function saveHeadline(file2, chat) {
|
|
|
23992
24048
|
return void 0;
|
|
23993
24049
|
}
|
|
23994
24050
|
function fileFacts(media, unpack) {
|
|
23995
|
-
const kind = media && Object.hasOwn(FILE_KIND_WORDS, media.type) ? FILE_KIND_WORDS[media.type] : void 0;
|
|
23996
24051
|
return [
|
|
23997
|
-
...media ? [{ label: "File", value:
|
|
24052
|
+
...media ? [{ label: "File", value: mediaKindValue(media.type) }] : [],
|
|
23998
24053
|
...unpack ? [{ label: "Unpack", value: { text: "Yes" } }] : [],
|
|
23999
24054
|
...media?.size !== void 0 && Number.isSafeInteger(media.size) && media.size > 0 ? [sizeFact(media.size)] : []
|
|
24000
24055
|
];
|
|
@@ -24225,14 +24280,14 @@ function storedReactions(json2) {
|
|
|
24225
24280
|
function ownReaction(reactions) {
|
|
24226
24281
|
return reactions.find((reaction2) => reaction2.mine)?.emoji;
|
|
24227
24282
|
}
|
|
24228
|
-
function checkEditable({ kind, body, captioned },
|
|
24283
|
+
function checkEditable({ kind, body, captioned }, text2) {
|
|
24229
24284
|
if (kind === "service" || body === null && !captioned) {
|
|
24230
24285
|
throw new ToolError("invalid_argument", "This message has no text or caption to edit; nothing was edited.");
|
|
24231
24286
|
}
|
|
24232
|
-
if (body ===
|
|
24287
|
+
if (body === text2) {
|
|
24233
24288
|
throw new ToolError("invalid_argument", "The text is the same as the message's; nothing to edit.");
|
|
24234
24289
|
}
|
|
24235
|
-
if (captioned &&
|
|
24290
|
+
if (captioned && text2.length > CAPTION_MAX_UNITS) {
|
|
24236
24291
|
throw new ToolError(
|
|
24237
24292
|
"invalid_argument",
|
|
24238
24293
|
`A caption must be at most ${CAPTION_MAX_UNITS} characters; nothing was edited.`
|
|
@@ -24241,8 +24296,8 @@ function checkEditable({ kind, body, captioned }, text) {
|
|
|
24241
24296
|
}
|
|
24242
24297
|
|
|
24243
24298
|
// src/core/message/arguments.ts
|
|
24244
|
-
function checkedText(
|
|
24245
|
-
const trimmed =
|
|
24299
|
+
function checkedText(text2) {
|
|
24300
|
+
const trimmed = text2.trim();
|
|
24246
24301
|
if (trimmed === "") throw new ToolError("invalid_argument", "text is blank; give the text to send.");
|
|
24247
24302
|
if (trimmed.length > TEXT_MAX_UNITS) {
|
|
24248
24303
|
throw new ToolError(
|
|
@@ -24300,8 +24355,8 @@ var Window = class {
|
|
|
24300
24355
|
get tail() {
|
|
24301
24356
|
return this.#tail;
|
|
24302
24357
|
}
|
|
24303
|
-
sees(
|
|
24304
|
-
const all = this.#tail +
|
|
24358
|
+
sees(text2) {
|
|
24359
|
+
const all = this.#tail + text2;
|
|
24305
24360
|
this.#tail = all.slice(-TAIL_LENGTH);
|
|
24306
24361
|
return MARKER.test(all);
|
|
24307
24362
|
}
|
|
@@ -24311,13 +24366,13 @@ var PrivateKeyScan = class {
|
|
|
24311
24366
|
#withoutNuls;
|
|
24312
24367
|
/** Feeds the next chunk; whether a marker starts anywhere in the bytes so far. */
|
|
24313
24368
|
sees(chunk) {
|
|
24314
|
-
const
|
|
24369
|
+
const text2 = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength).toString("latin1");
|
|
24315
24370
|
const before = this.#plain.tail;
|
|
24316
|
-
const plain2 = this.#plain.sees(
|
|
24317
|
-
if (this.#withoutNuls === void 0 &&
|
|
24371
|
+
const plain2 = this.#plain.sees(text2);
|
|
24372
|
+
if (this.#withoutNuls === void 0 && text2.includes(NUL)) {
|
|
24318
24373
|
this.#withoutNuls = new Window(before);
|
|
24319
24374
|
}
|
|
24320
|
-
const stripped = this.#withoutNuls?.sees(
|
|
24375
|
+
const stripped = this.#withoutNuls?.sees(text2.replaceAll(NUL, "")) ?? false;
|
|
24321
24376
|
return plain2 || stripped;
|
|
24322
24377
|
}
|
|
24323
24378
|
};
|
|
@@ -24509,9 +24564,8 @@ async function checkArchive(path, format, limits, signal) {
|
|
|
24509
24564
|
}
|
|
24510
24565
|
|
|
24511
24566
|
// src/core/outgoing/limits.ts
|
|
24512
|
-
var BYTES_PER_MB2 = 1024 * 1024;
|
|
24513
24567
|
var MAX_FILES = 10;
|
|
24514
|
-
var MAX_TOTAL_BYTES = 100 *
|
|
24568
|
+
var MAX_TOTAL_BYTES = 100 * BYTES_PER_MB;
|
|
24515
24569
|
|
|
24516
24570
|
// src/core/file/send/constants.ts
|
|
24517
24571
|
var SEND_FILES_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -24944,12 +24998,12 @@ var DUPLICATE_NOTE = "An earlier delivery of this same call had already gone out
|
|
|
24944
24998
|
var DUPLICATE_UNKNOWN_ID_NOTE = `${DUPLICATE_NOTE} Its id is not known yet; \`telegram_chat_read\` shows it once the service receives it.`;
|
|
24945
24999
|
|
|
24946
25000
|
// src/core/message/uncertain.ts
|
|
24947
|
-
function sentLike(paths, chat,
|
|
25001
|
+
function sentLike(paths, chat, text2, startedAt) {
|
|
24948
25002
|
const rows = readMirror(
|
|
24949
25003
|
paths,
|
|
24950
25004
|
(mirror) => mirror.prepare(
|
|
24951
25005
|
"SELECT id, ts FROM messages WHERE chat = ? AND from_me = 1 AND body = ? AND ts >= ? ORDER BY ts DESC, id DESC LIMIT ?"
|
|
24952
|
-
).all(chat,
|
|
25006
|
+
).all(chat, text2, startedAt - SENT_LOOKBACK_MS, MAX_SENT_LIKE)
|
|
24953
25007
|
);
|
|
24954
25008
|
return rows.map(({ id, ts }) => ({ id, time: formatLocalTime(ts) }));
|
|
24955
25009
|
}
|
|
@@ -24969,8 +25023,8 @@ function withFound(error62, find, describe3) {
|
|
|
24969
25023
|
details: { ...error62.details, sent_like_this: found }
|
|
24970
25024
|
});
|
|
24971
25025
|
}
|
|
24972
|
-
function withSentLike(error62, paths, chat,
|
|
24973
|
-
return withFound(error62, () => sentLike(paths, chat,
|
|
25026
|
+
function withSentLike(error62, paths, chat, text2, startedAt) {
|
|
25027
|
+
return withFound(error62, () => sentLike(paths, chat, text2, startedAt), sentence);
|
|
24974
25028
|
}
|
|
24975
25029
|
|
|
24976
25030
|
// src/core/file/send/uncertain.ts
|
|
@@ -25107,17 +25161,17 @@ var MAX_HEADLINE_VALUES = 8;
|
|
|
25107
25161
|
var MAX_HEADLINE_VALUE_LENGTH = 80;
|
|
25108
25162
|
var MAX_PINS = 16;
|
|
25109
25163
|
var HEADLINE_PLACEHOLDER = /\{([A-Za-z_][A-Za-z0-9_]*)\}/;
|
|
25110
|
-
function cut2(
|
|
25111
|
-
const points = Array.from(
|
|
25112
|
-
return points.length > limit ? `${points.slice(0, limit - 1).join("")}\u2026` :
|
|
25164
|
+
function cut2(text2, limit) {
|
|
25165
|
+
const points = Array.from(text2);
|
|
25166
|
+
return points.length > limit ? `${points.slice(0, limit - 1).join("")}\u2026` : text2;
|
|
25113
25167
|
}
|
|
25114
|
-
function omittedBy(
|
|
25115
|
-
const length = Array.from(
|
|
25168
|
+
function omittedBy(text2, limit) {
|
|
25169
|
+
const length = Array.from(text2).length;
|
|
25116
25170
|
return length > limit ? length - (limit - 1) : 0;
|
|
25117
25171
|
}
|
|
25118
|
-
function templatePlaceholders(
|
|
25172
|
+
function templatePlaceholders(text2) {
|
|
25119
25173
|
const names = /* @__PURE__ */ new Set();
|
|
25120
|
-
const parts =
|
|
25174
|
+
const parts = text2.split(HEADLINE_PLACEHOLDER);
|
|
25121
25175
|
for (const [index, part] of parts.entries()) {
|
|
25122
25176
|
if (index % 2 === 1) names.add(part);
|
|
25123
25177
|
else if (/[{}]/.test(part)) return void 0;
|
|
@@ -25135,10 +25189,10 @@ function valueEntries(values) {
|
|
|
25135
25189
|
const entries = Object.entries(values);
|
|
25136
25190
|
return entries.length > MAX_HEADLINE_VALUES ? void 0 : entries;
|
|
25137
25191
|
}
|
|
25138
|
-
function isTemplate(
|
|
25139
|
-
if (
|
|
25192
|
+
function isTemplate(text2, limit, entries) {
|
|
25193
|
+
if (text2.trim() === "" || Array.from(text2).length > limit) return false;
|
|
25140
25194
|
const given = new Set(entries.map(([name]) => name));
|
|
25141
|
-
const placeholders2 = templatePlaceholders(
|
|
25195
|
+
const placeholders2 = templatePlaceholders(text2);
|
|
25142
25196
|
return placeholders2 !== void 0 && [...placeholders2].every((name) => given.has(name));
|
|
25143
25197
|
}
|
|
25144
25198
|
function isTemplateValue(value) {
|
|
@@ -25154,15 +25208,15 @@ function isFact(fact) {
|
|
|
25154
25208
|
}
|
|
25155
25209
|
function cutValue(value) {
|
|
25156
25210
|
if (typeof value === "string") return cut2(value, MAX_VALUE_LENGTH);
|
|
25157
|
-
const { text, values } = value;
|
|
25158
|
-
if (values === void 0) return { text };
|
|
25211
|
+
const { text: text2, values } = value;
|
|
25212
|
+
if (values === void 0) return { text: text2 };
|
|
25159
25213
|
const cutValues = Object.entries(values).map(
|
|
25160
25214
|
([name, entry2]) => [name, typeof entry2 === "string" ? cut2(entry2, MAX_VALUE_LENGTH) : entry2]
|
|
25161
25215
|
);
|
|
25162
|
-
return { text, values: Object.fromEntries(cutValues) };
|
|
25216
|
+
return { text: text2, values: Object.fromEntries(cutValues) };
|
|
25163
25217
|
}
|
|
25164
|
-
function isText2(
|
|
25165
|
-
return isRecord2(
|
|
25218
|
+
function isText2(text2) {
|
|
25219
|
+
return isRecord2(text2) && typeof text2.label === "string" && text2.label.trim() !== "" && typeof text2.body === "string";
|
|
25166
25220
|
}
|
|
25167
25221
|
function pinsOf(pins) {
|
|
25168
25222
|
if (pins === void 0) return {};
|
|
@@ -25176,32 +25230,32 @@ function pinsOf(pins) {
|
|
|
25176
25230
|
}
|
|
25177
25231
|
function copyValue(value) {
|
|
25178
25232
|
if (typeof value === "string") return value;
|
|
25179
|
-
const { text, values } = value;
|
|
25180
|
-
return values === void 0 ? { text } : { text, values: { ...values } };
|
|
25233
|
+
const { text: text2, values } = value;
|
|
25234
|
+
return values === void 0 ? { text: text2 } : { text: text2, values: { ...values } };
|
|
25181
25235
|
}
|
|
25182
25236
|
function headlineOf(headline) {
|
|
25183
25237
|
if (!isRecord2(headline) || typeof headline.text !== "string") return void 0;
|
|
25184
|
-
const { text, values } = headline;
|
|
25238
|
+
const { text: text2, values } = headline;
|
|
25185
25239
|
const entries = valueEntries(values);
|
|
25186
|
-
if (entries === void 0 || !isTemplate(
|
|
25240
|
+
if (entries === void 0 || !isTemplate(text2, MAX_HEADLINE_LENGTH, entries)) return void 0;
|
|
25187
25241
|
if (!entries.every((entry2) => typeof entry2[1] === "string")) return void 0;
|
|
25188
|
-
return values === void 0 ? { text } : { text, values: Object.fromEntries(entries) };
|
|
25242
|
+
return values === void 0 ? { text: text2 } : { text: text2, values: Object.fromEntries(entries) };
|
|
25189
25243
|
}
|
|
25190
|
-
function cutHeadline({ text, values }) {
|
|
25191
|
-
if (values === void 0) return { text };
|
|
25244
|
+
function cutHeadline({ text: text2, values }) {
|
|
25245
|
+
if (values === void 0) return { text: text2 };
|
|
25192
25246
|
const cutValues = Object.entries(values).map(
|
|
25193
25247
|
([name, value]) => [name, cut2(value, MAX_HEADLINE_VALUE_LENGTH)]
|
|
25194
25248
|
);
|
|
25195
|
-
return { text, values: Object.fromEntries(cutValues) };
|
|
25249
|
+
return { text: text2, values: Object.fromEntries(cutValues) };
|
|
25196
25250
|
}
|
|
25197
|
-
function cutDescription({ headline, facts, text, pins }) {
|
|
25251
|
+
function cutDescription({ headline, facts, text: text2, pins }) {
|
|
25198
25252
|
return {
|
|
25199
25253
|
...headline && { headline: cutHeadline(headline) },
|
|
25200
25254
|
facts: facts.slice(0, MAX_FACTS).map(({ label, value }) => ({
|
|
25201
25255
|
label: cut2(label, MAX_LABEL_LENGTH),
|
|
25202
25256
|
value: cutValue(value)
|
|
25203
25257
|
})),
|
|
25204
|
-
...
|
|
25258
|
+
...text2 && { text: { label: cut2(text2.label, MAX_TEXT_LABEL_LENGTH), body: cut2(text2.body, MAX_TEXT_LENGTH) } },
|
|
25205
25259
|
...pins && { pins }
|
|
25206
25260
|
};
|
|
25207
25261
|
}
|
|
@@ -25225,47 +25279,54 @@ async function wholeCallDescription(spec, args, ctx) {
|
|
|
25225
25279
|
if (kept === void 0) return void 0;
|
|
25226
25280
|
const facts = entries.map(({ label, value }) => ({ label, value: copyValue(value) }));
|
|
25227
25281
|
const headline = answer.headline === void 0 ? void 0 : headlineOf(answer.headline);
|
|
25228
|
-
const
|
|
25229
|
-
if (headline === void 0 && facts.length === 0 &&
|
|
25230
|
-
return { ...headline && { headline }, facts, ...
|
|
25282
|
+
const text2 = answer.text === void 0 || answer.text.body === "" ? void 0 : { label: answer.text.label, body: answer.text.body };
|
|
25283
|
+
if (headline === void 0 && facts.length === 0 && text2 === void 0) return void 0;
|
|
25284
|
+
return { ...headline && { headline }, facts, ...text2 && { text: text2 }, ...kept };
|
|
25231
25285
|
}
|
|
25232
25286
|
|
|
25233
25287
|
// src/core/message/action-describe.ts
|
|
25234
25288
|
var EDIT_HEADLINES = {
|
|
25235
25289
|
named: "About to edit message {id} in {chat}",
|
|
25236
|
-
saved: "About to edit message {id} in Saved Messages"
|
|
25290
|
+
saved: "About to edit message {id} in Saved Messages",
|
|
25291
|
+
bare: "About to edit message {id}"
|
|
25237
25292
|
};
|
|
25238
25293
|
var DELETE_HEADLINES = {
|
|
25239
|
-
named: "About to delete message {id} from {chat}",
|
|
25240
|
-
saved: "About to delete message {id} from Saved Messages"
|
|
25294
|
+
named: "About to delete message {id} from {chat} for everyone",
|
|
25295
|
+
saved: "About to delete message {id} from Saved Messages",
|
|
25296
|
+
bare: "About to delete message {id} for everyone"
|
|
25241
25297
|
};
|
|
25242
25298
|
var REACT_HEADLINES = {
|
|
25243
25299
|
named: "About to react {emoji} to message {id} in {chat}",
|
|
25244
|
-
saved: "About to react {emoji} to message {id} in Saved Messages"
|
|
25300
|
+
saved: "About to react {emoji} to message {id} in Saved Messages",
|
|
25301
|
+
bare: "About to react {emoji} to message {id}"
|
|
25245
25302
|
};
|
|
25246
25303
|
var UNREACT_HEADLINES = {
|
|
25247
25304
|
named: "About to remove your reaction from message {id} in {chat}",
|
|
25248
|
-
saved: "About to remove your reaction from message {id} in Saved Messages"
|
|
25305
|
+
saved: "About to remove your reaction from message {id} in Saved Messages",
|
|
25306
|
+
bare: "About to remove your reaction from message {id}"
|
|
25249
25307
|
};
|
|
25250
25308
|
var PIN_HEADLINES = {
|
|
25251
25309
|
named: "About to pin message {id} in {chat}",
|
|
25252
|
-
saved: "About to pin message {id} in Saved Messages"
|
|
25310
|
+
saved: "About to pin message {id} in Saved Messages",
|
|
25311
|
+
bare: "About to pin message {id}"
|
|
25253
25312
|
};
|
|
25254
25313
|
var UNPIN_HEADLINES = {
|
|
25255
25314
|
named: "About to unpin message {id} in {chat}",
|
|
25256
|
-
saved: "About to unpin message {id} in Saved Messages"
|
|
25315
|
+
saved: "About to unpin message {id} in Saved Messages",
|
|
25316
|
+
bare: "About to unpin message {id}"
|
|
25257
25317
|
};
|
|
25258
25318
|
var MARK_READ_HEADLINES = {
|
|
25259
25319
|
named: "About to mark {chat} read up to message {id}",
|
|
25260
|
-
saved: "About to mark Saved Messages read up to message {id}"
|
|
25320
|
+
saved: "About to mark Saved Messages read up to message {id}",
|
|
25321
|
+
bare: "About to mark messages read up to message {id}"
|
|
25261
25322
|
};
|
|
25262
25323
|
function actionHeadline(headlines, { kind, name }, id, values) {
|
|
25263
25324
|
if (kind === "self") return { text: headlines.saved, values: { id: String(id), ...values } };
|
|
25264
|
-
return name === null ?
|
|
25325
|
+
return name === null ? { text: headlines.bare, values: { id: String(id), ...values } } : { text: headlines.named, values: { id: String(id), chat: name, ...values } };
|
|
25265
25326
|
}
|
|
25266
25327
|
function currentFacts({ body, media }) {
|
|
25267
|
-
|
|
25268
|
-
return
|
|
25328
|
+
if (body) return [{ label: "Current", value: cut2(body, MAX_VALUE_LENGTH) }];
|
|
25329
|
+
return media ? [{ label: "Media", value: mediaKindValue(media.type) }] : [];
|
|
25269
25330
|
}
|
|
25270
25331
|
function describeAction(headlines, chat, id, message, extras = {}) {
|
|
25271
25332
|
const headline = actionHeadline(headlines, chat, id, extras.values ?? {});
|
|
@@ -25501,7 +25562,7 @@ var telegramMessageDelete = defineTool({
|
|
|
25501
25562
|
"A result means Telegram deleted the message for everyone. `already` means it was gone before this call.",
|
|
25502
25563
|
"A failure `uncertain` means the delete may have gone through: check the chat in Telegram and never ask for it again without the user checking."
|
|
25503
25564
|
].join(" "),
|
|
25504
|
-
intent: "About to delete a message",
|
|
25565
|
+
intent: "About to delete a message for everyone",
|
|
25505
25566
|
toolset: "actions",
|
|
25506
25567
|
class: "administrative",
|
|
25507
25568
|
input: deleteInput,
|
|
@@ -25533,10 +25594,10 @@ var telegramMessageDelete = defineTool({
|
|
|
25533
25594
|
});
|
|
25534
25595
|
|
|
25535
25596
|
// src/core/message/edit-prepare.ts
|
|
25536
|
-
function prepareEdit(mirror, chatId, id,
|
|
25597
|
+
function prepareEdit(mirror, chatId, id, text2) {
|
|
25537
25598
|
const { chat, message } = findOwnMessage(mirror, chatId, id, "edit");
|
|
25538
25599
|
if (!message) throw deletedMessage();
|
|
25539
|
-
checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) },
|
|
25600
|
+
checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) }, text2);
|
|
25540
25601
|
return { chat, message };
|
|
25541
25602
|
}
|
|
25542
25603
|
|
|
@@ -25559,22 +25620,22 @@ var telegramMessageEdit = defineTool({
|
|
|
25559
25620
|
input: editInput,
|
|
25560
25621
|
output: editOutput,
|
|
25561
25622
|
async describe(args, ctx) {
|
|
25562
|
-
const
|
|
25623
|
+
const text2 = checkedText(args.text);
|
|
25563
25624
|
const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
|
|
25564
25625
|
const paths = await pickPaths(ctx, args.account);
|
|
25565
|
-
const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id,
|
|
25626
|
+
const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text2));
|
|
25566
25627
|
return {
|
|
25567
25628
|
...describeAction(EDIT_HEADLINES, target.chat, args.id, target.message),
|
|
25568
|
-
text: { label: "New text", body:
|
|
25629
|
+
text: { label: "New text", body: text2 }
|
|
25569
25630
|
};
|
|
25570
25631
|
},
|
|
25571
25632
|
targets: (args, ctx) => actionTargets(MESSAGE_EDIT_TOOL_ID, args, ctx),
|
|
25572
25633
|
async execute(args, ctx) {
|
|
25573
25634
|
const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
|
|
25574
|
-
const
|
|
25635
|
+
const text2 = checkedText(args.text);
|
|
25575
25636
|
const paths = await pickPaths(ctx, args.account);
|
|
25576
|
-
readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id,
|
|
25577
|
-
const params = { chat, id: args.id, text };
|
|
25637
|
+
readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text2));
|
|
25638
|
+
const params = { chat, id: args.id, text: text2 };
|
|
25578
25639
|
const edited = await callService(paths.socket, SERVICE_REQUESTS.edit, params, {
|
|
25579
25640
|
effect: "write",
|
|
25580
25641
|
signal: ctx.signal,
|
|
@@ -25770,7 +25831,7 @@ var telegramMessageSend = defineTool({
|
|
|
25770
25831
|
input: input5,
|
|
25771
25832
|
output: output5,
|
|
25772
25833
|
async describe(args, ctx) {
|
|
25773
|
-
const
|
|
25834
|
+
const text2 = checkedText(args.text);
|
|
25774
25835
|
const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
|
|
25775
25836
|
const paths = await pickPaths(ctx, args.account);
|
|
25776
25837
|
const { row, title } = readMirror(paths, (mirror) => {
|
|
@@ -25782,17 +25843,17 @@ var telegramMessageSend = defineTool({
|
|
|
25782
25843
|
headline: { text: "About to send a message to {chat}", values: { chat: row.name } }
|
|
25783
25844
|
},
|
|
25784
25845
|
facts: [chatFact(row.kind), ...topicFacts(args.topic, title), ...replyFacts(args.reply_to)],
|
|
25785
|
-
text: { label: "Message text", body:
|
|
25846
|
+
text: { label: "Message text", body: text2 }
|
|
25786
25847
|
};
|
|
25787
25848
|
},
|
|
25788
25849
|
targets: (args, ctx) => chatTargets(MESSAGE_SEND_TOOL_ID, args, ctx),
|
|
25789
25850
|
async execute(args, ctx) {
|
|
25790
25851
|
const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
|
|
25791
|
-
const
|
|
25852
|
+
const text2 = checkedText(args.text);
|
|
25792
25853
|
const paths = await pickPaths(ctx, args.account);
|
|
25793
25854
|
const params = {
|
|
25794
25855
|
chat,
|
|
25795
|
-
text,
|
|
25856
|
+
text: text2,
|
|
25796
25857
|
...args.topic !== void 0 && { topic: args.topic },
|
|
25797
25858
|
...args.reply_to !== void 0 && { reply_to: args.reply_to }
|
|
25798
25859
|
};
|
|
@@ -25805,7 +25866,7 @@ var telegramMessageSend = defineTool({
|
|
|
25805
25866
|
});
|
|
25806
25867
|
return sendResult(chat, sent);
|
|
25807
25868
|
} catch (error62) {
|
|
25808
|
-
throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat,
|
|
25869
|
+
throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat, text2, startedAt) : error62;
|
|
25809
25870
|
}
|
|
25810
25871
|
}
|
|
25811
25872
|
});
|
|
@@ -26106,12 +26167,6 @@ var FILE_TRANSLATIONS = {
|
|
|
26106
26167
|
"About to save a file from {chat}": "{chat} \u306E\u30D5\u30A1\u30A4\u30EB\u3092\u4FDD\u5B58\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26107
26168
|
"About to save {file}": "{file} \u3092\u4FDD\u5B58\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26108
26169
|
File: "\u30D5\u30A1\u30A4\u30EB",
|
|
26109
|
-
Photo: "\u5199\u771F",
|
|
26110
|
-
Document: "\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8",
|
|
26111
|
-
Audio: "\u97F3\u58F0",
|
|
26112
|
-
"Voice message": "\u30DC\u30A4\u30B9\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
26113
|
-
Video: "\u52D5\u753B",
|
|
26114
|
-
Sticker: "\u30B9\u30BF\u30F3\u30D7",
|
|
26115
26170
|
Unpack: "\u5C55\u958B",
|
|
26116
26171
|
Yes: "\u3059\u308B"
|
|
26117
26172
|
}
|
|
@@ -26126,24 +26181,31 @@ var ACTION_TRANSLATIONS = {
|
|
|
26126
26181
|
"Pin or unpin a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30D4\u30F3\u7559\u3081\u3059\u308B\u30FB\u89E3\u9664\u3059\u308B",
|
|
26127
26182
|
"Mark a chat read": "\u30C1\u30E3\u30C3\u30C8\u3092\u65E2\u8AAD\u306B\u3059\u308B",
|
|
26128
26183
|
"About to edit a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26129
|
-
"About to delete a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26184
|
+
"About to delete a message for everyone": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26130
26185
|
"About to change a reaction": "\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26131
26186
|
"About to pin or unpin a message": "\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u30D4\u30F3\u7559\u3081\u3092\u5909\u66F4\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26132
26187
|
"About to mark messages read": "\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26133
26188
|
"About to edit message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26134
|
-
"About to edit message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26135
|
-
"About to
|
|
26136
|
-
"About to delete message {id} from
|
|
26189
|
+
"About to edit message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26190
|
+
"About to edit message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u7DE8\u96C6\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26191
|
+
"About to delete message {id} from {chat} for everyone": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26192
|
+
"About to delete message {id} from Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26193
|
+
"About to delete message {id} for everyone": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u5168\u54E1\u5206\u524A\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26137
26194
|
"About to react {emoji} to message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26138
|
-
"About to react {emoji} to message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26195
|
+
"About to react {emoji} to message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26196
|
+
"About to react {emoji} to message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306B {emoji} \u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26139
26197
|
"About to remove your reaction from message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26140
|
-
"About to remove your reaction from message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26198
|
+
"About to remove your reaction from message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26199
|
+
"About to remove your reaction from message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u304B\u3089\u81EA\u5206\u306E\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3\u3092\u5916\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26141
26200
|
"About to pin message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26142
|
-
"About to pin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26201
|
+
"About to pin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26202
|
+
"About to pin message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u3092\u30D4\u30F3\u7559\u3081\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26143
26203
|
"About to unpin message {id} in {chat}": "{chat} \u306E\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26144
|
-
"About to unpin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\
|
|
26204
|
+
"About to unpin message {id} in Saved Messages": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u306B\u3042\u308B\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26205
|
+
"About to unpin message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u306E\u30D4\u30F3\u7559\u3081\u3092\u89E3\u9664\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26145
26206
|
"About to mark {chat} read up to message {id}": "{chat} \u3092\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26146
26207
|
"About to mark Saved Messages read up to message {id}": "\u4FDD\u5B58\u6E08\u307F\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26208
|
+
"About to mark messages read up to message {id}": "\u30E1\u30C3\u30BB\u30FC\u30B8 {id} \u307E\u3067\u65E2\u8AAD\u306B\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059",
|
|
26147
26209
|
Message: "\u30E1\u30C3\u30BB\u30FC\u30B8",
|
|
26148
26210
|
Current: "\u73FE\u5728\u306E\u5185\u5BB9",
|
|
26149
26211
|
Replaces: "\u7F6E\u304D\u63DB\u3048\u308B\u30EA\u30A2\u30AF\u30B7\u30E7\u30F3",
|
|
@@ -26187,6 +26249,7 @@ var SYNC_TRANSLATIONS = {
|
|
|
26187
26249
|
var ALL_TRANSLATIONS = mergeTranslations(
|
|
26188
26250
|
FACT_TRANSLATIONS,
|
|
26189
26251
|
CHAT_FACT_TRANSLATIONS,
|
|
26252
|
+
MEDIA_FACT_TRANSLATIONS,
|
|
26190
26253
|
MESSAGE_TRANSLATIONS,
|
|
26191
26254
|
ACTION_TRANSLATIONS,
|
|
26192
26255
|
FILE_TRANSLATIONS,
|
|
@@ -26209,9 +26272,9 @@ function mark(character) {
|
|
|
26209
26272
|
const hex3 = character.codePointAt(0).toString(16).toUpperCase();
|
|
26210
26273
|
return `<U+${hex3.padStart(MARK_DIGITS, "0")}>`;
|
|
26211
26274
|
}
|
|
26212
|
-
function visible(
|
|
26213
|
-
if (options.keepNewlines) return
|
|
26214
|
-
return
|
|
26275
|
+
function visible(text2, options = {}) {
|
|
26276
|
+
if (options.keepNewlines) return text2.replace(/\r\n/g, "\n").replace(HIDDEN_EXCEPT_NEWLINE, mark);
|
|
26277
|
+
return text2.replace(HIDDEN_ALL, mark);
|
|
26215
26278
|
}
|
|
26216
26279
|
|
|
26217
26280
|
// src/entry/words.ts
|
|
@@ -26257,12 +26320,12 @@ var omittedOf = (count) => count > 0 ? { omitted: count } : {};
|
|
|
26257
26320
|
function quoted(value) {
|
|
26258
26321
|
return `"${visible(value).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
26259
26322
|
}
|
|
26260
|
-
function filled(
|
|
26261
|
-
return
|
|
26323
|
+
function filled(text2, literal2, slot) {
|
|
26324
|
+
return text2.split(HEADLINE_PLACEHOLDER).map((part, index) => index % 2 === 0 ? literal2(part) : slot(part)).join("");
|
|
26262
26325
|
}
|
|
26263
|
-
function renderedHeadline({ text, values = {} }) {
|
|
26326
|
+
function renderedHeadline({ text: text2, values = {} }) {
|
|
26264
26327
|
return filled(
|
|
26265
|
-
|
|
26328
|
+
text2,
|
|
26266
26329
|
(part) => visible(part),
|
|
26267
26330
|
(name) => quoted(values[name] ?? "")
|
|
26268
26331
|
);
|
|
@@ -26276,7 +26339,7 @@ function renderedValue(value, t) {
|
|
|
26276
26339
|
return { value: visible(cut2(whole, MAX_VALUE_LENGTH)), ...omittedOf(omittedBy(whole, MAX_VALUE_LENGTH)) };
|
|
26277
26340
|
}
|
|
26278
26341
|
function shownDescription(description, t) {
|
|
26279
|
-
const { headline, facts, text } = cutDescription(description);
|
|
26342
|
+
const { headline, facts, text: text2 } = cutDescription(description);
|
|
26280
26343
|
const wholeBody = description.text?.body ?? "";
|
|
26281
26344
|
const dropped = description.facts.length - facts.length;
|
|
26282
26345
|
return {
|
|
@@ -26286,9 +26349,9 @@ function shownDescription(description, t) {
|
|
|
26286
26349
|
...renderedValue(description.facts[index].value, t)
|
|
26287
26350
|
})),
|
|
26288
26351
|
...dropped > 0 && { dropped },
|
|
26289
|
-
...
|
|
26352
|
+
...text2 && {
|
|
26290
26353
|
text: {
|
|
26291
|
-
label: visible(t.word(
|
|
26354
|
+
label: visible(t.word(text2.label, MAX_TEXT_LABEL_LENGTH)),
|
|
26292
26355
|
body: visible(cut2(wholeBody, MAX_TEXT_LENGTH), { keepNewlines: true }),
|
|
26293
26356
|
...omittedOf(omittedBy(wholeBody, MAX_TEXT_LENGTH))
|
|
26294
26357
|
}
|
|
@@ -26302,9 +26365,9 @@ async function timedCallDescription(spec, args, ctx, timeoutMs = DESCRIBE_TIMEOU
|
|
|
26302
26365
|
let timer;
|
|
26303
26366
|
let onAbort;
|
|
26304
26367
|
try {
|
|
26305
|
-
const timedOut = new Promise((
|
|
26368
|
+
const timedOut = new Promise((resolve6) => {
|
|
26306
26369
|
timer = setTimeout(() => {
|
|
26307
|
-
|
|
26370
|
+
resolve6(void 0);
|
|
26308
26371
|
controller.abort();
|
|
26309
26372
|
}, timeoutMs);
|
|
26310
26373
|
});
|
|
@@ -26380,76 +26443,70 @@ ${JSON.stringify(error62.details)}` : ""}`;
|
|
|
26380
26443
|
var PROJECT_PROFILE = {
|
|
26381
26444
|
name: PROJECT.name,
|
|
26382
26445
|
envPrefix: PROJECT.envPrefix,
|
|
26383
|
-
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets }
|
|
26446
|
+
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets },
|
|
26447
|
+
options: PROJECT.options
|
|
26384
26448
|
};
|
|
26385
26449
|
|
|
26386
|
-
// src/entry/
|
|
26387
|
-
import {
|
|
26450
|
+
// src/entry/settings.ts
|
|
26451
|
+
import { homedir as homedir3 } from "node:os";
|
|
26452
|
+
import { isAbsolute as isAbsolute6, join as join10, resolve as resolvePath, sep as sep4 } from "node:path";
|
|
26388
26453
|
|
|
26389
26454
|
// src/entry/directory.ts
|
|
26390
26455
|
import { homedir as homedir2 } from "node:os";
|
|
26391
|
-
import { isAbsolute as isAbsolute5,
|
|
26456
|
+
import { isAbsolute as isAbsolute5, resolve as resolve4 } from "node:path";
|
|
26457
|
+
var DOWNLOADS_DIR = "Downloads";
|
|
26458
|
+
var DEFAULT_DOWNLOAD_MAX_MB = 100;
|
|
26392
26459
|
function homeDir(env) {
|
|
26393
26460
|
const envHome = env.HOME;
|
|
26394
26461
|
if (envHome && isAbsolute5(envHome)) return envHome;
|
|
26395
26462
|
return homedir2();
|
|
26396
26463
|
}
|
|
26397
|
-
function
|
|
26398
|
-
const
|
|
26399
|
-
|
|
26400
|
-
if (!text || !isAbsolute5(expanded)) {
|
|
26401
|
-
throw new ToolError("invalid_argument", `${given.source} must be an absolute path.`);
|
|
26402
|
-
}
|
|
26403
|
-
return resolve4(expanded);
|
|
26404
|
-
}
|
|
26405
|
-
|
|
26406
|
-
// src/entry/download-dir.ts
|
|
26407
|
-
var DOWNLOADS_DIR = "Downloads";
|
|
26408
|
-
function resolveDownloadDir(given, env, profile) {
|
|
26409
|
-
const home = homeDir(env);
|
|
26410
|
-
return given !== void 0 ? resolveGivenDirectory(given, home) : resolve5(home, DOWNLOADS_DIR, profile.name);
|
|
26464
|
+
function defaultStateDir(name, env, home) {
|
|
26465
|
+
const xdg = env.XDG_STATE_HOME;
|
|
26466
|
+
return xdg && isAbsolute5(xdg) ? resolve4(xdg, name) : resolve4(home, ".local", "state", name);
|
|
26411
26467
|
}
|
|
26412
|
-
|
|
26413
|
-
|
|
26414
|
-
function resolveSendDirs(given, env) {
|
|
26415
|
-
const home = homeDir(env);
|
|
26416
|
-
return given.map((directory) => resolveGivenDirectory(directory, home));
|
|
26468
|
+
function text(value) {
|
|
26469
|
+
return typeof value === "string" ? value : void 0;
|
|
26417
26470
|
}
|
|
26418
|
-
|
|
26419
|
-
// src/entry/state-dir.ts
|
|
26420
|
-
import { isAbsolute as isAbsolute6, resolve as resolve6 } from "node:path";
|
|
26421
|
-
function resolveStateDir(given, env, profile) {
|
|
26471
|
+
function resolveDirectorySettings(options, env, profile) {
|
|
26422
26472
|
const home = homeDir(env);
|
|
26423
|
-
|
|
26424
|
-
const
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26473
|
+
const maxMb = options.download_max_mb;
|
|
26474
|
+
const sendDirs = options.send_dirs;
|
|
26475
|
+
return {
|
|
26476
|
+
state_dir: text(options.state_dir) ?? defaultStateDir(profile.name, env, home),
|
|
26477
|
+
download_dir: text(options.download_dir) ?? resolve4(home, DOWNLOADS_DIR, profile.name),
|
|
26478
|
+
download_max_mb: typeof maxMb === "number" ? maxMb : DEFAULT_DOWNLOAD_MAX_MB,
|
|
26479
|
+
send_dirs: Array.isArray(sendDirs) ? [...sendDirs] : []
|
|
26480
|
+
};
|
|
26429
26481
|
}
|
|
26430
26482
|
|
|
26431
26483
|
// src/entry/settings.ts
|
|
26432
26484
|
var ALL_TOOLSETS = "all";
|
|
26433
26485
|
var TRUE_VALUES = ["1", "true"];
|
|
26434
26486
|
var FALSE_VALUES = ["0", "false"];
|
|
26435
|
-
var DEFAULT_DOWNLOAD_MAX_MB = 100;
|
|
26436
|
-
var MAX_DOWNLOAD_MB = 2e3;
|
|
26437
26487
|
var OPTIONS = {
|
|
26438
26488
|
toolsets: { flag: "--toolsets", envSuffix: "TOOLSETS" },
|
|
26439
26489
|
read_only: { flag: "--read-only", envSuffix: "READ_ONLY", boolean: true },
|
|
26440
26490
|
tools: { flag: "--tools", envSuffix: "TOOLS" },
|
|
26441
26491
|
exclude_tools: { flag: "--exclude-tools", envSuffix: "EXCLUDE_TOOLS" },
|
|
26442
|
-
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
26443
|
-
state_dir: { flag: "--state-dir", envSuffix: "STATE_DIR" },
|
|
26444
|
-
download_dir: { flag: "--download-dir", envSuffix: "DOWNLOAD_DIR" },
|
|
26445
|
-
download_max_mb: { flag: "--download-max-mb", envSuffix: "DOWNLOAD_MAX_MB" },
|
|
26446
|
-
send_dirs: { flag: "--send-dirs", envSuffix: "SEND_DIRS" },
|
|
26447
|
-
keep_disappearing: { flag: "--keep-disappearing", envSuffix: "KEEP_DISAPPEARING", boolean: true },
|
|
26448
|
-
channels: { flag: "--channels", envSuffix: "CHANNELS", boolean: true }
|
|
26492
|
+
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
26449
26493
|
};
|
|
26450
|
-
|
|
26494
|
+
function profileOptions(profile) {
|
|
26495
|
+
return profile.options ?? {};
|
|
26496
|
+
}
|
|
26497
|
+
function settingOptions(profile) {
|
|
26498
|
+
const toolOptions = Object.entries(profileOptions(profile)).map(([name, spec]) => [
|
|
26499
|
+
name,
|
|
26500
|
+
{
|
|
26501
|
+
flag: `--${name.replace(/_/g, "-")}`,
|
|
26502
|
+
envSuffix: name.toUpperCase(),
|
|
26503
|
+
...optionType(spec) === "boolean" && { boolean: true }
|
|
26504
|
+
}
|
|
26505
|
+
]);
|
|
26506
|
+
return { ...OPTIONS, ...Object.fromEntries(toolOptions) };
|
|
26507
|
+
}
|
|
26451
26508
|
function envName(name, profile) {
|
|
26452
|
-
return `${profile.envPrefix}_${
|
|
26509
|
+
return `${profile.envPrefix}_${settingOptions(profile)[name].envSuffix}`;
|
|
26453
26510
|
}
|
|
26454
26511
|
function splitList(value) {
|
|
26455
26512
|
return value.split(",").map((item) => item.trim()).filter((item) => item !== "");
|
|
@@ -26464,43 +26521,87 @@ function checkToolsets(names, source, toolsets) {
|
|
|
26464
26521
|
return names.length ? names : void 0;
|
|
26465
26522
|
}
|
|
26466
26523
|
function parseBoolean(value, source) {
|
|
26467
|
-
const
|
|
26468
|
-
if (TRUE_VALUES.includes(
|
|
26469
|
-
if (FALSE_VALUES.includes(
|
|
26524
|
+
const text2 = value.trim().toLowerCase();
|
|
26525
|
+
if (TRUE_VALUES.includes(text2)) return true;
|
|
26526
|
+
if (FALSE_VALUES.includes(text2)) return false;
|
|
26470
26527
|
throw new ToolError(
|
|
26471
26528
|
"invalid_argument",
|
|
26472
26529
|
`Unknown value "${value}" in ${source}; use one of ${[...TRUE_VALUES, ...FALSE_VALUES].join(", ")}.`
|
|
26473
26530
|
);
|
|
26474
26531
|
}
|
|
26475
|
-
function
|
|
26476
|
-
|
|
26477
|
-
|
|
26478
|
-
|
|
26479
|
-
|
|
26480
|
-
throw new ToolError("invalid_argument", `${source} must be an integer from 1 to ${MAX_DOWNLOAD_MB}.`);
|
|
26532
|
+
function parseNumber2(value, source) {
|
|
26533
|
+
const trimmed = value.trim();
|
|
26534
|
+
const parsed = trimmed === "" ? Number.NaN : Number(trimmed);
|
|
26535
|
+
if (!Number.isFinite(parsed)) {
|
|
26536
|
+
throw new ToolError("invalid_argument", `Unknown number "${value}" in ${source}; use a finite number.`);
|
|
26481
26537
|
}
|
|
26482
|
-
return
|
|
26538
|
+
return parsed;
|
|
26483
26539
|
}
|
|
26484
|
-
function
|
|
26485
|
-
const
|
|
26486
|
-
|
|
26540
|
+
function absolutePath(text2, source, env) {
|
|
26541
|
+
const home = env.HOME !== void 0 && isAbsolute6(env.HOME) ? env.HOME : homedir3();
|
|
26542
|
+
const expanded = text2 === "~" || text2.startsWith("~/") || text2.startsWith(`~${sep4}`) ? join10(home, text2.slice(1)) : text2;
|
|
26543
|
+
if (!isAbsolute6(expanded)) throw new ToolError("invalid_argument", `${source} must be an absolute path.`);
|
|
26544
|
+
return resolvePath(expanded);
|
|
26545
|
+
}
|
|
26546
|
+
function absolutePaths(items, source, env) {
|
|
26547
|
+
return items.length > 0 ? items.map((item) => absolutePath(item, source, env)) : void 0;
|
|
26487
26548
|
}
|
|
26488
26549
|
function envText(name, env, profile) {
|
|
26489
26550
|
const variable = envName(name, profile);
|
|
26490
|
-
const
|
|
26491
|
-
return
|
|
26492
|
-
}
|
|
26493
|
-
|
|
26494
|
-
"
|
|
26495
|
-
|
|
26496
|
-
|
|
26497
|
-
"
|
|
26498
|
-
|
|
26499
|
-
|
|
26500
|
-
"
|
|
26501
|
-
"
|
|
26502
|
-
|
|
26503
|
-
|
|
26551
|
+
const text2 = env[variable];
|
|
26552
|
+
return text2 === void 0 || text2.trim() === "" ? void 0 : { text: text2, source: variable };
|
|
26553
|
+
}
|
|
26554
|
+
function optionType(spec) {
|
|
26555
|
+
return typeof spec === "string" ? spec : spec.type;
|
|
26556
|
+
}
|
|
26557
|
+
function itemCount(count) {
|
|
26558
|
+
return count === 1 ? "1 item" : `${count} items`;
|
|
26559
|
+
}
|
|
26560
|
+
function numberBoundsError({ integer: integer2, min, max }, source) {
|
|
26561
|
+
const range = min !== void 0 && max !== void 0 ? ` from ${min} to ${max}` : min !== void 0 ? ` of at least ${min}` : max !== void 0 ? ` of at most ${max}` : "";
|
|
26562
|
+
return new ToolError("invalid_argument", `${source} must be ${integer2 ? "a whole number" : "a number"}${range}.`);
|
|
26563
|
+
}
|
|
26564
|
+
function countBoundsError({ min, max }, source) {
|
|
26565
|
+
const range = min !== void 0 && max !== void 0 ? `from ${min} to ${max} items` : min !== void 0 ? `at least ${itemCount(min)}` : `at most ${itemCount(max)}`;
|
|
26566
|
+
return new ToolError("invalid_argument", `${source} must list ${range}.`);
|
|
26567
|
+
}
|
|
26568
|
+
function withinBounds(spec, value, source) {
|
|
26569
|
+
if (value === void 0 || typeof spec === "string") return value;
|
|
26570
|
+
const bounds = spec;
|
|
26571
|
+
const { integer: integer2, min, max } = bounds;
|
|
26572
|
+
if (typeof value === "number") {
|
|
26573
|
+
if (integer2 && !Number.isInteger(value) || min !== void 0 && value < min || max !== void 0 && value > max) {
|
|
26574
|
+
throw numberBoundsError(bounds, source);
|
|
26575
|
+
}
|
|
26576
|
+
} else if (typeof value === "object" && (min !== void 0 && value.length < min || max !== void 0 && value.length > max)) {
|
|
26577
|
+
throw countBoundsError(bounds, source);
|
|
26578
|
+
}
|
|
26579
|
+
return value;
|
|
26580
|
+
}
|
|
26581
|
+
function parseOptionText(spec, given, env) {
|
|
26582
|
+
return withinBounds(spec, parseTypedText(optionType(spec), given, env), given.source);
|
|
26583
|
+
}
|
|
26584
|
+
function parseTypedText(kind, given, env) {
|
|
26585
|
+
switch (kind) {
|
|
26586
|
+
case "text":
|
|
26587
|
+
return nonBlank(given.text);
|
|
26588
|
+
case "boolean":
|
|
26589
|
+
return parseBoolean(given.text, given.source);
|
|
26590
|
+
case "number":
|
|
26591
|
+
return parseNumber2(given.text, given.source);
|
|
26592
|
+
case "list": {
|
|
26593
|
+
const items = splitList(given.text);
|
|
26594
|
+
return items.length > 0 ? items : void 0;
|
|
26595
|
+
}
|
|
26596
|
+
case "path": {
|
|
26597
|
+
const text2 = nonBlank(given.text);
|
|
26598
|
+
return text2 === void 0 ? void 0 : absolutePath(text2, given.source, env);
|
|
26599
|
+
}
|
|
26600
|
+
case "paths":
|
|
26601
|
+
return absolutePaths(splitList(given.text), given.source, env);
|
|
26602
|
+
}
|
|
26603
|
+
}
|
|
26604
|
+
var TOOL_OPTION_NAMES = ["toolsets", "read_only", "tools", "exclude_tools"];
|
|
26504
26605
|
function stringList(value) {
|
|
26505
26606
|
return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
|
|
26506
26607
|
}
|
|
@@ -26508,15 +26609,6 @@ var optionSource = (name) => `Option "${name}"`;
|
|
|
26508
26609
|
function optionError(name, expected) {
|
|
26509
26610
|
return new ToolError("invalid_argument", `${optionSource(name)} must be ${expected}.`);
|
|
26510
26611
|
}
|
|
26511
|
-
function directoryOption(name, value) {
|
|
26512
|
-
if (typeof value !== "string") throw optionError(name, "an absolute path");
|
|
26513
|
-
return value;
|
|
26514
|
-
}
|
|
26515
|
-
function sendDirsOption(value) {
|
|
26516
|
-
const list2 = stringList(value);
|
|
26517
|
-
if (!list2) throw optionError("send_dirs", "a list of absolute paths");
|
|
26518
|
-
return list2.map((text) => ({ text, source: optionSource("send_dirs") }));
|
|
26519
|
-
}
|
|
26520
26612
|
function toolsetsOption(value, toolsets) {
|
|
26521
26613
|
if (value === ALL_TOOLSETS) return ALL_TOOLSETS;
|
|
26522
26614
|
const names = stringList(value);
|
|
@@ -26537,12 +26629,14 @@ function listOption(name) {
|
|
|
26537
26629
|
};
|
|
26538
26630
|
}
|
|
26539
26631
|
var LANGUAGE_OPTION = "language";
|
|
26540
|
-
|
|
26632
|
+
function pluginOptionNames(profile) {
|
|
26633
|
+
return [...TOOL_OPTION_NAMES, LANGUAGE_OPTION, ...Object.keys(profileOptions(profile))];
|
|
26634
|
+
}
|
|
26541
26635
|
function languageVariable(profile = PROJECT_PROFILE) {
|
|
26542
26636
|
return `${profile.envPrefix}_LANGUAGE`;
|
|
26543
26637
|
}
|
|
26544
|
-
function nonBlank(
|
|
26545
|
-
const trimmed =
|
|
26638
|
+
function nonBlank(text2) {
|
|
26639
|
+
const trimmed = text2?.trim();
|
|
26546
26640
|
return trimmed === "" ? void 0 : trimmed;
|
|
26547
26641
|
}
|
|
26548
26642
|
function promptLanguage(flag, env, harness, profile = PROJECT_PROFILE) {
|
|
@@ -26552,42 +26646,80 @@ function languageOption(value) {
|
|
|
26552
26646
|
if (typeof value !== "string") throw optionError(LANGUAGE_OPTION, 'a language tag such as "ja"');
|
|
26553
26647
|
return nonBlank(value);
|
|
26554
26648
|
}
|
|
26649
|
+
function toolOption(name, spec, value, env) {
|
|
26650
|
+
return withinBounds(spec, toolOptionOfType(name, optionType(spec), value, env), `Option "${name}"`);
|
|
26651
|
+
}
|
|
26652
|
+
function toolOptionOfType(name, kind, value, env) {
|
|
26653
|
+
switch (kind) {
|
|
26654
|
+
case "text":
|
|
26655
|
+
if (typeof value !== "string") throw optionError(name, "text");
|
|
26656
|
+
return nonBlank(value);
|
|
26657
|
+
case "boolean":
|
|
26658
|
+
if (typeof value !== "boolean") throw optionError(name, "true or false");
|
|
26659
|
+
return value;
|
|
26660
|
+
case "number":
|
|
26661
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw optionError(name, "a finite number");
|
|
26662
|
+
return value;
|
|
26663
|
+
case "list": {
|
|
26664
|
+
const list2 = stringList(value);
|
|
26665
|
+
if (!list2) throw optionError(name, "a list of strings");
|
|
26666
|
+
const items = list2.map((item) => item.trim()).filter((item) => item !== "");
|
|
26667
|
+
return items.length > 0 ? items : void 0;
|
|
26668
|
+
}
|
|
26669
|
+
case "path": {
|
|
26670
|
+
if (typeof value !== "string") throw optionError(name, "an absolute path");
|
|
26671
|
+
const text2 = nonBlank(value);
|
|
26672
|
+
return text2 === void 0 ? void 0 : absolutePath(text2, `Option "${name}"`, env);
|
|
26673
|
+
}
|
|
26674
|
+
case "paths": {
|
|
26675
|
+
const list2 = stringList(value);
|
|
26676
|
+
if (!list2) throw optionError(name, "a list of absolute paths");
|
|
26677
|
+
return absolutePaths(
|
|
26678
|
+
list2.flatMap((item) => nonBlank(item) ?? []),
|
|
26679
|
+
`Option "${name}"`,
|
|
26680
|
+
env
|
|
26681
|
+
);
|
|
26682
|
+
}
|
|
26683
|
+
}
|
|
26684
|
+
}
|
|
26555
26685
|
function settingsFromOptions(options, env, profile = PROJECT_PROFILE) {
|
|
26556
26686
|
const given = options ?? {};
|
|
26557
|
-
const
|
|
26687
|
+
const names = pluginOptionNames(profile);
|
|
26688
|
+
const unknown2 = Object.keys(given).find((name) => !names.includes(name));
|
|
26558
26689
|
if (unknown2 !== void 0) {
|
|
26559
|
-
throw new ToolError(
|
|
26560
|
-
"invalid_argument",
|
|
26561
|
-
`Unknown option "${unknown2}"; use one of ${PLUGIN_OPTION_NAMES.join(", ")}.`
|
|
26562
|
-
);
|
|
26690
|
+
throw new ToolError("invalid_argument", `Unknown option "${unknown2}"; use one of ${names.join(", ")}.`);
|
|
26563
26691
|
}
|
|
26564
|
-
const
|
|
26692
|
+
const resolve6 = (name, fromOption, fromText) => {
|
|
26565
26693
|
if (given[name] !== void 0) return fromOption(given[name]);
|
|
26566
|
-
const
|
|
26567
|
-
return
|
|
26568
|
-
};
|
|
26569
|
-
const
|
|
26694
|
+
const text2 = envText(name, env, profile);
|
|
26695
|
+
return text2 !== void 0 ? fromText(text2) : void 0;
|
|
26696
|
+
};
|
|
26697
|
+
const parsedOptions = {};
|
|
26698
|
+
for (const [name, spec] of Object.entries(profileOptions(profile))) {
|
|
26699
|
+
let parsed;
|
|
26700
|
+
if (given[name] !== void 0) {
|
|
26701
|
+
parsed = toolOption(name, spec, given[name], env);
|
|
26702
|
+
} else {
|
|
26703
|
+
const fromEnv = envText(name, env, profile);
|
|
26704
|
+
if (fromEnv !== void 0) parsed = parseOptionText(spec, fromEnv, env);
|
|
26705
|
+
}
|
|
26706
|
+
if (parsed !== void 0) parsedOptions[name] = parsed;
|
|
26707
|
+
}
|
|
26570
26708
|
const settings = {
|
|
26571
|
-
|
|
26572
|
-
|
|
26573
|
-
download_dir: resolveDownloadDir(directoryText("download_dir"), env, profile),
|
|
26574
|
-
download_max_mb: resolve8("download_max_mb", (value) => downloadMaxMb(value, optionSource("download_max_mb")), downloadMaxMbText) ?? DEFAULT_DOWNLOAD_MAX_MB
|
|
26709
|
+
options: parsedOptions,
|
|
26710
|
+
...resolveDirectorySettings(parsedOptions, env, profile)
|
|
26575
26711
|
};
|
|
26576
|
-
const toolsets =
|
|
26712
|
+
const toolsets = resolve6(
|
|
26577
26713
|
"toolsets",
|
|
26578
26714
|
(value) => toolsetsOption(value, profile.toolsets),
|
|
26579
|
-
({ text, source }) => checkToolsets(splitList(
|
|
26715
|
+
({ text: text2, source }) => checkToolsets(splitList(text2), source, profile.toolsets)
|
|
26580
26716
|
);
|
|
26581
26717
|
if (toolsets !== void 0) settings.toolsets = toolsets;
|
|
26582
|
-
const readOnly =
|
|
26718
|
+
const readOnly = resolve6("read_only", booleanOption("read_only"), ({ text: text2, source }) => parseBoolean(text2, source));
|
|
26583
26719
|
if (readOnly !== void 0) settings.read_only = readOnly;
|
|
26584
|
-
|
|
26585
|
-
const given2 = resolve8(name, booleanOption(name), ({ text, source }) => parseBoolean(text, source));
|
|
26586
|
-
if (given2 !== void 0) settings[name] = given2;
|
|
26587
|
-
}
|
|
26588
|
-
const tools = resolve8("tools", listOption("tools"), ({ text }) => splitList(text));
|
|
26720
|
+
const tools = resolve6("tools", listOption("tools"), ({ text: text2 }) => splitList(text2));
|
|
26589
26721
|
if (tools !== void 0) settings.tools = tools;
|
|
26590
|
-
const excluded =
|
|
26722
|
+
const excluded = resolve6("exclude_tools", listOption("exclude_tools"), ({ text: text2 }) => splitList(text2));
|
|
26591
26723
|
if (excluded !== void 0) settings.exclude_tools = excluded;
|
|
26592
26724
|
const language = given[LANGUAGE_OPTION] !== void 0 ? languageOption(given[LANGUAGE_OPTION]) : promptLanguage(void 0, env, void 0, profile);
|
|
26593
26725
|
if (language !== void 0) settings.language = language;
|
|
@@ -26618,7 +26750,8 @@ function selectedTools(specs, options, deps) {
|
|
|
26618
26750
|
downloadMaxMb: settings.download_max_mb,
|
|
26619
26751
|
sendDirs: settings.send_dirs,
|
|
26620
26752
|
programName: PROJECT.name,
|
|
26621
|
-
translator: promptTranslator(deps.translations ?? {}, settings.language)
|
|
26753
|
+
translator: promptTranslator(deps.translations ?? {}, settings.language),
|
|
26754
|
+
options: settings.options
|
|
26622
26755
|
};
|
|
26623
26756
|
}
|
|
26624
26757
|
async function runTool(spec, args, ctx, pin) {
|
|
@@ -26641,8 +26774,8 @@ function describeArguments(spec) {
|
|
|
26641
26774
|
const { properties = {}, required: required2 = [] } = inputJsonSchema(spec);
|
|
26642
26775
|
const lines = Object.entries(properties).map(([name, property]) => {
|
|
26643
26776
|
const kind = required2.includes(name) ? typeName(property) : `${typeName(property)}, optional`;
|
|
26644
|
-
const
|
|
26645
|
-
return `- ${name} (${kind})${
|
|
26777
|
+
const text2 = property.description?.replace(/\s+/g, " ").trim();
|
|
26778
|
+
return `- ${name} (${kind})${text2 ? `: ${text2}` : ""}`;
|
|
26646
26779
|
});
|
|
26647
26780
|
return lines.length > 0 ? `
|
|
26648
26781
|
|
|
@@ -26686,7 +26819,7 @@ function createV1Server(specs, deps = {}) {
|
|
|
26686
26819
|
|
|
26687
26820
|
// src/opencode/skills.ts
|
|
26688
26821
|
import { readFile, readdir as readdir3 } from "node:fs/promises";
|
|
26689
|
-
import { join as join11, resolve as
|
|
26822
|
+
import { join as join11, resolve as resolve5 } from "node:path";
|
|
26690
26823
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
26691
26824
|
var SKILL_FILE = "SKILL.md";
|
|
26692
26825
|
var FRONTMATTER = /^---[ \t]*\r?\n([\s\S]*?\r?\n)?---[ \t]*(?:\r?\n|$)/;
|
|
@@ -26713,8 +26846,8 @@ function unquote(value) {
|
|
|
26713
26846
|
function scalar(raw) {
|
|
26714
26847
|
if (raw === "" || UNSUPPORTED_VALUE_START.test(raw)) return void 0;
|
|
26715
26848
|
if (raw.startsWith('"') || raw.startsWith("'")) return unquote(raw);
|
|
26716
|
-
const
|
|
26717
|
-
return
|
|
26849
|
+
const text2 = raw.replace(TRAILING_COMMENT, "").trim();
|
|
26850
|
+
return text2 === "" ? void 0 : text2;
|
|
26718
26851
|
}
|
|
26719
26852
|
function readToolset(line, indent) {
|
|
26720
26853
|
if (!line.startsWith(indent)) return void 0;
|
|
@@ -26749,8 +26882,8 @@ function readFrontmatter(block) {
|
|
|
26749
26882
|
}
|
|
26750
26883
|
return found;
|
|
26751
26884
|
}
|
|
26752
|
-
function parseSkill(directory,
|
|
26753
|
-
const match = FRONTMATTER.exec(
|
|
26885
|
+
function parseSkill(directory, text2, path) {
|
|
26886
|
+
const match = FRONTMATTER.exec(text2);
|
|
26754
26887
|
const { name, description, toolset } = match ? readFrontmatter(match[1] ?? "") : {};
|
|
26755
26888
|
const id = name ?? directory;
|
|
26756
26889
|
return {
|
|
@@ -26759,7 +26892,7 @@ function parseSkill(directory, text, path) {
|
|
|
26759
26892
|
name: id,
|
|
26760
26893
|
...description !== void 0 && { description },
|
|
26761
26894
|
path,
|
|
26762
|
-
content: match ?
|
|
26895
|
+
content: match ? text2.slice(match[0].length) : text2
|
|
26763
26896
|
},
|
|
26764
26897
|
...toolset !== void 0 && { toolset }
|
|
26765
26898
|
};
|
|
@@ -26777,7 +26910,7 @@ async function readSkillFile(path) {
|
|
|
26777
26910
|
}
|
|
26778
26911
|
}
|
|
26779
26912
|
async function readSkills(dir) {
|
|
26780
|
-
const root =
|
|
26913
|
+
const root = resolve5(typeof dir === "string" ? dir : fileURLToPath2(dir));
|
|
26781
26914
|
let entries;
|
|
26782
26915
|
try {
|
|
26783
26916
|
entries = (await readdir3(root, { withFileTypes: true })).filter((entry2) => !entry2.isFile()).map((entry2) => entry2.name);
|
|
@@ -26788,9 +26921,9 @@ async function readSkills(dir) {
|
|
|
26788
26921
|
const skills = /* @__PURE__ */ new Map();
|
|
26789
26922
|
for (const directory of entries.sort()) {
|
|
26790
26923
|
const path = join11(root, directory, SKILL_FILE);
|
|
26791
|
-
const
|
|
26792
|
-
if (
|
|
26793
|
-
const found = parseSkill(directory,
|
|
26924
|
+
const text2 = await readSkillFile(path);
|
|
26925
|
+
if (text2 === void 0) continue;
|
|
26926
|
+
const found = parseSkill(directory, text2, path);
|
|
26794
26927
|
if (!skills.has(found.skill.id)) skills.set(found.skill.id, found);
|
|
26795
26928
|
}
|
|
26796
26929
|
return [...skills.values()];
|