@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/mcp.js
CHANGED
|
@@ -2984,7 +2984,7 @@ var require_compile = __commonJS({
|
|
|
2984
2984
|
const schOrFunc = root.refs[ref];
|
|
2985
2985
|
if (schOrFunc)
|
|
2986
2986
|
return schOrFunc;
|
|
2987
|
-
let _sch =
|
|
2987
|
+
let _sch = resolve5.call(this, root, ref);
|
|
2988
2988
|
if (_sch === void 0) {
|
|
2989
2989
|
const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
|
|
2990
2990
|
const { schemaId } = this.opts;
|
|
@@ -3011,7 +3011,7 @@ var require_compile = __commonJS({
|
|
|
3011
3011
|
function sameSchemaEnv(s1, s2) {
|
|
3012
3012
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3013
3013
|
}
|
|
3014
|
-
function
|
|
3014
|
+
function resolve5(root, ref) {
|
|
3015
3015
|
let sch;
|
|
3016
3016
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3017
3017
|
ref = sch;
|
|
@@ -3875,7 +3875,7 @@ var require_fast_uri = __commonJS({
|
|
|
3875
3875
|
}
|
|
3876
3876
|
return uri;
|
|
3877
3877
|
}
|
|
3878
|
-
function
|
|
3878
|
+
function resolve5(baseURI, relativeURI, options) {
|
|
3879
3879
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3880
3880
|
const {
|
|
3881
3881
|
parsed: baseParsed,
|
|
@@ -4266,7 +4266,7 @@ var require_fast_uri = __commonJS({
|
|
|
4266
4266
|
var fastUri = {
|
|
4267
4267
|
SCHEMES,
|
|
4268
4268
|
normalize,
|
|
4269
|
-
resolve:
|
|
4269
|
+
resolve: resolve5,
|
|
4270
4270
|
resolveComponent,
|
|
4271
4271
|
equal,
|
|
4272
4272
|
serialize,
|
|
@@ -4681,7 +4681,7 @@ var require_core = __commonJS({
|
|
|
4681
4681
|
errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
|
|
4682
4682
|
if (!errors || errors.length === 0)
|
|
4683
4683
|
return "No errors";
|
|
4684
|
-
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((
|
|
4684
|
+
return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
|
|
4685
4685
|
}
|
|
4686
4686
|
$dataMetaSchema(metaSchema, keywordsJsonPointers) {
|
|
4687
4687
|
const rules = this.RULES.all;
|
|
@@ -12325,7 +12325,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
12325
12325
|
var NONE = 0;
|
|
12326
12326
|
var ASSUMED = 1;
|
|
12327
12327
|
var PROVEN = 2;
|
|
12328
|
-
function isRecursive(inst, stack,
|
|
12328
|
+
function isRecursive(inst, stack, resolve5) {
|
|
12329
12329
|
const cached2 = recursive.get(inst);
|
|
12330
12330
|
if (cached2 !== void 0)
|
|
12331
12331
|
return cached2 ? PROVEN : NONE;
|
|
@@ -12335,7 +12335,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
12335
12335
|
let result = NONE;
|
|
12336
12336
|
const check2 = (child) => {
|
|
12337
12337
|
if (result !== PROVEN && child?._zod) {
|
|
12338
|
-
const answer = isRecursive(child, stack,
|
|
12338
|
+
const answer = isRecursive(child, stack, resolve5);
|
|
12339
12339
|
if (answer > result)
|
|
12340
12340
|
result = answer;
|
|
12341
12341
|
}
|
|
@@ -12346,7 +12346,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
12346
12346
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
12347
12347
|
if (spread && !desc.enumerable)
|
|
12348
12348
|
continue;
|
|
12349
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
12349
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve5) : NONE;
|
|
12350
12350
|
if (child > answer)
|
|
12351
12351
|
answer = child;
|
|
12352
12352
|
}
|
|
@@ -12410,7 +12410,7 @@ function isRecursive(inst, stack, resolve7) {
|
|
|
12410
12410
|
break;
|
|
12411
12411
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
12412
12412
|
case "lazy": {
|
|
12413
|
-
const inner = def._cachedInner ?? (
|
|
12413
|
+
const inner = def._cachedInner ?? (resolve5 ? inst._zod.innerType : void 0);
|
|
12414
12414
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
12415
12415
|
break;
|
|
12416
12416
|
}
|
|
@@ -16608,8 +16608,8 @@ function ko_default() {
|
|
|
16608
16608
|
}
|
|
16609
16609
|
|
|
16610
16610
|
// node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/locales/lt.js
|
|
16611
|
-
var capitalizeFirstCharacter = (
|
|
16612
|
-
return
|
|
16611
|
+
var capitalizeFirstCharacter = (text2) => {
|
|
16612
|
+
return text2.charAt(0).toUpperCase() + text2.slice(1);
|
|
16613
16613
|
};
|
|
16614
16614
|
function getUnitTypeFromNumber(number4) {
|
|
16615
16615
|
const abs = Math.abs(number4);
|
|
@@ -28587,12 +28587,12 @@ var StdioServerTransport = class {
|
|
|
28587
28587
|
this.onclose?.();
|
|
28588
28588
|
}
|
|
28589
28589
|
send(message) {
|
|
28590
|
-
return new Promise((
|
|
28590
|
+
return new Promise((resolve5) => {
|
|
28591
28591
|
const json2 = serializeMessage(message);
|
|
28592
28592
|
if (this._stdout.write(json2)) {
|
|
28593
|
-
|
|
28593
|
+
resolve5();
|
|
28594
28594
|
} else {
|
|
28595
|
-
this._stdout.once("drain",
|
|
28595
|
+
this._stdout.once("drain", resolve5);
|
|
28596
28596
|
}
|
|
28597
28597
|
});
|
|
28598
28598
|
}
|
|
@@ -28639,7 +28639,7 @@ function abortError(signal) {
|
|
|
28639
28639
|
}
|
|
28640
28640
|
function exec(argv, options) {
|
|
28641
28641
|
const { signal } = options;
|
|
28642
|
-
return new Promise((
|
|
28642
|
+
return new Promise((resolve5, reject) => {
|
|
28643
28643
|
if (signal?.aborted) {
|
|
28644
28644
|
reject(abortError(signal));
|
|
28645
28645
|
return;
|
|
@@ -28698,7 +28698,7 @@ function exec(argv, options) {
|
|
|
28698
28698
|
}
|
|
28699
28699
|
const finish = () => settle2(() => {
|
|
28700
28700
|
const { code, killedBy } = exitedWith ?? { code: null, killedBy: null };
|
|
28701
|
-
|
|
28701
|
+
resolve5({
|
|
28702
28702
|
code: code ?? -1,
|
|
28703
28703
|
stdout,
|
|
28704
28704
|
stderr,
|
|
@@ -28872,9 +28872,9 @@ var StepErrors = class {
|
|
|
28872
28872
|
|
|
28873
28873
|
// src/core/describe.ts
|
|
28874
28874
|
var MAX_VALUE_LENGTH = 200;
|
|
28875
|
-
function cut(
|
|
28876
|
-
const points = Array.from(
|
|
28877
|
-
return points.length > limit ? `${points.slice(0, limit - 1).join("")}\u2026` :
|
|
28875
|
+
function cut(text2, limit) {
|
|
28876
|
+
const points = Array.from(text2);
|
|
28877
|
+
return points.length > limit ? `${points.slice(0, limit - 1).join("")}\u2026` : text2;
|
|
28878
28878
|
}
|
|
28879
28879
|
|
|
28880
28880
|
// src/core/facts.ts
|
|
@@ -28889,6 +28889,10 @@ function packageRoot(bundleUrl) {
|
|
|
28889
28889
|
return dirname(dirname(fileURLToPath(bundleUrl)));
|
|
28890
28890
|
}
|
|
28891
28891
|
|
|
28892
|
+
// src/entry/settings.ts
|
|
28893
|
+
import { homedir as homedir2 } from "node:os";
|
|
28894
|
+
import { isAbsolute as isAbsolute3, join, resolve as resolvePath, sep as sep2 } from "node:path";
|
|
28895
|
+
|
|
28892
28896
|
// src/project.ts
|
|
28893
28897
|
var PROJECT = {
|
|
28894
28898
|
/** The plugin, MCP server and program name. */
|
|
@@ -28903,89 +28907,94 @@ var PROJECT = {
|
|
|
28903
28907
|
toolsets: ["account", "chats", "sync", "files", "sends", "actions"],
|
|
28904
28908
|
/** The toolsets on when a setting names none. */
|
|
28905
28909
|
defaultToolsets: ["account", "chats", "sync", "sends"],
|
|
28910
|
+
/** The package's own settings, which the tools themselves read: each snake_case name and its type, with bounds when it needs them. */
|
|
28911
|
+
options: {
|
|
28912
|
+
/** Where every account's state lives. */
|
|
28913
|
+
state_dir: "path",
|
|
28914
|
+
/** Where received files are saved. */
|
|
28915
|
+
download_dir: "path",
|
|
28916
|
+
/** The largest received file a call may download, in megabytes. */
|
|
28917
|
+
download_max_mb: { type: "number", integer: true, min: 1, max: 2e3 },
|
|
28918
|
+
/** The directories files may be sent from, besides the working directory. */
|
|
28919
|
+
send_dirs: "paths",
|
|
28920
|
+
/** Whether messages that disappear are kept; read by the sync service's commands. */
|
|
28921
|
+
keep_disappearing: "boolean",
|
|
28922
|
+
/** Whether channels are listed and their messages received; read by the sync service's commands. */
|
|
28923
|
+
channels: "boolean"
|
|
28924
|
+
},
|
|
28906
28925
|
/** The environment variables the tools read besides the settings, which Codex forwards to the server after them. */
|
|
28907
28926
|
toolVariables: []
|
|
28908
28927
|
};
|
|
28909
28928
|
|
|
28910
|
-
// src/entry/download-dir.ts
|
|
28911
|
-
import { resolve as resolve2 } from "node:path";
|
|
28912
|
-
|
|
28913
28929
|
// src/entry/directory.ts
|
|
28914
28930
|
import { homedir } from "node:os";
|
|
28915
|
-
import { isAbsolute as isAbsolute2,
|
|
28931
|
+
import { isAbsolute as isAbsolute2, resolve } from "node:path";
|
|
28932
|
+
var DOWNLOADS_DIR = "Downloads";
|
|
28933
|
+
var DEFAULT_DOWNLOAD_MAX_MB = 100;
|
|
28916
28934
|
function homeDir(env) {
|
|
28917
28935
|
const envHome = env.HOME;
|
|
28918
28936
|
if (envHome && isAbsolute2(envHome)) return envHome;
|
|
28919
28937
|
return homedir();
|
|
28920
28938
|
}
|
|
28921
|
-
function
|
|
28922
|
-
const
|
|
28923
|
-
|
|
28924
|
-
if (!text || !isAbsolute2(expanded)) {
|
|
28925
|
-
throw new ToolError("invalid_argument", `${given.source} must be an absolute path.`);
|
|
28926
|
-
}
|
|
28927
|
-
return resolve(expanded);
|
|
28939
|
+
function defaultStateDir(name, env, home) {
|
|
28940
|
+
const xdg = env.XDG_STATE_HOME;
|
|
28941
|
+
return xdg && isAbsolute2(xdg) ? resolve(xdg, name) : resolve(home, ".local", "state", name);
|
|
28928
28942
|
}
|
|
28929
|
-
|
|
28930
|
-
|
|
28931
|
-
|
|
28932
|
-
function
|
|
28943
|
+
function text(value) {
|
|
28944
|
+
return typeof value === "string" ? value : void 0;
|
|
28945
|
+
}
|
|
28946
|
+
function resolveDirectorySettings(options, env, profile) {
|
|
28933
28947
|
const home = homeDir(env);
|
|
28934
|
-
|
|
28948
|
+
const maxMb = options.download_max_mb;
|
|
28949
|
+
const sendDirs = options.send_dirs;
|
|
28950
|
+
return {
|
|
28951
|
+
state_dir: text(options.state_dir) ?? defaultStateDir(profile.name, env, home),
|
|
28952
|
+
download_dir: text(options.download_dir) ?? resolve(home, DOWNLOADS_DIR, profile.name),
|
|
28953
|
+
download_max_mb: typeof maxMb === "number" ? maxMb : DEFAULT_DOWNLOAD_MAX_MB,
|
|
28954
|
+
send_dirs: Array.isArray(sendDirs) ? [...sendDirs] : []
|
|
28955
|
+
};
|
|
28935
28956
|
}
|
|
28936
28957
|
|
|
28937
28958
|
// src/entry/profile.ts
|
|
28938
28959
|
var PROJECT_PROFILE = {
|
|
28939
28960
|
name: PROJECT.name,
|
|
28940
28961
|
envPrefix: PROJECT.envPrefix,
|
|
28941
|
-
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets }
|
|
28962
|
+
toolsets: { names: PROJECT.toolsets, defaults: PROJECT.defaultToolsets },
|
|
28963
|
+
options: PROJECT.options
|
|
28942
28964
|
};
|
|
28943
28965
|
|
|
28944
|
-
// src/entry/send-dirs.ts
|
|
28945
|
-
function resolveSendDirs(given, env) {
|
|
28946
|
-
const home = homeDir(env);
|
|
28947
|
-
return given.map((directory) => resolveGivenDirectory(directory, home));
|
|
28948
|
-
}
|
|
28949
|
-
|
|
28950
|
-
// src/entry/state-dir.ts
|
|
28951
|
-
import { isAbsolute as isAbsolute3, resolve as resolve3 } from "node:path";
|
|
28952
|
-
function resolveStateDir(given, env, profile) {
|
|
28953
|
-
const home = homeDir(env);
|
|
28954
|
-
if (given !== void 0) return resolveGivenDirectory(given, home);
|
|
28955
|
-
const xdg = env.XDG_STATE_HOME;
|
|
28956
|
-
if (xdg && isAbsolute3(xdg)) {
|
|
28957
|
-
return resolve3(xdg, profile.name);
|
|
28958
|
-
}
|
|
28959
|
-
return resolve3(home, ".local", "state", profile.name);
|
|
28960
|
-
}
|
|
28961
|
-
|
|
28962
28966
|
// src/entry/settings.ts
|
|
28963
28967
|
var CONFIRM_MODES = ["harness", "elicitation"];
|
|
28964
28968
|
var ALL_TOOLSETS = "all";
|
|
28965
28969
|
var TRUE_VALUES = ["1", "true"];
|
|
28966
28970
|
var FALSE_VALUES = ["0", "false"];
|
|
28967
|
-
var DEFAULT_DOWNLOAD_MAX_MB = 100;
|
|
28968
|
-
var MAX_DOWNLOAD_MB = 2e3;
|
|
28969
28971
|
var OPTIONS = {
|
|
28970
28972
|
toolsets: { flag: "--toolsets", envSuffix: "TOOLSETS" },
|
|
28971
28973
|
read_only: { flag: "--read-only", envSuffix: "READ_ONLY", boolean: true },
|
|
28972
28974
|
tools: { flag: "--tools", envSuffix: "TOOLS" },
|
|
28973
28975
|
exclude_tools: { flag: "--exclude-tools", envSuffix: "EXCLUDE_TOOLS" },
|
|
28974
|
-
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
28975
|
-
state_dir: { flag: "--state-dir", envSuffix: "STATE_DIR" },
|
|
28976
|
-
download_dir: { flag: "--download-dir", envSuffix: "DOWNLOAD_DIR" },
|
|
28977
|
-
download_max_mb: { flag: "--download-max-mb", envSuffix: "DOWNLOAD_MAX_MB" },
|
|
28978
|
-
send_dirs: { flag: "--send-dirs", envSuffix: "SEND_DIRS" },
|
|
28979
|
-
keep_disappearing: { flag: "--keep-disappearing", envSuffix: "KEEP_DISAPPEARING", boolean: true },
|
|
28980
|
-
channels: { flag: "--channels", envSuffix: "CHANNELS", boolean: true }
|
|
28976
|
+
confirm: { flag: "--confirm", envSuffix: "CONFIRM" }
|
|
28981
28977
|
};
|
|
28982
|
-
|
|
28978
|
+
function profileOptions(profile) {
|
|
28979
|
+
return profile.options ?? {};
|
|
28980
|
+
}
|
|
28981
|
+
function settingOptions(profile) {
|
|
28982
|
+
const toolOptions = Object.entries(profileOptions(profile)).map(([name, spec]) => [
|
|
28983
|
+
name,
|
|
28984
|
+
{
|
|
28985
|
+
flag: `--${name.replace(/_/g, "-")}`,
|
|
28986
|
+
envSuffix: name.toUpperCase(),
|
|
28987
|
+
...optionType(spec) === "boolean" && { boolean: true }
|
|
28988
|
+
}
|
|
28989
|
+
]);
|
|
28990
|
+
return { ...OPTIONS, ...Object.fromEntries(toolOptions) };
|
|
28991
|
+
}
|
|
28983
28992
|
function envName(name, profile) {
|
|
28984
|
-
return `${profile.envPrefix}_${
|
|
28993
|
+
return `${profile.envPrefix}_${settingOptions(profile)[name].envSuffix}`;
|
|
28985
28994
|
}
|
|
28986
|
-
function readFlags(argv) {
|
|
28995
|
+
function readFlags(argv, profile) {
|
|
28987
28996
|
const byFlag = new Map(
|
|
28988
|
-
Object.
|
|
28997
|
+
Object.entries(settingOptions(profile)).map(([name, option]) => [option.flag, { name, ...option }])
|
|
28989
28998
|
);
|
|
28990
28999
|
const given = {};
|
|
28991
29000
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -29020,9 +29029,9 @@ function checkToolsets(names, source, toolsets) {
|
|
|
29020
29029
|
return names.length ? names : void 0;
|
|
29021
29030
|
}
|
|
29022
29031
|
function parseBoolean(value, source) {
|
|
29023
|
-
const
|
|
29024
|
-
if (TRUE_VALUES.includes(
|
|
29025
|
-
if (FALSE_VALUES.includes(
|
|
29032
|
+
const text2 = value.trim().toLowerCase();
|
|
29033
|
+
if (TRUE_VALUES.includes(text2)) return true;
|
|
29034
|
+
if (FALSE_VALUES.includes(text2)) return false;
|
|
29026
29035
|
throw new ToolError(
|
|
29027
29036
|
"invalid_argument",
|
|
29028
29037
|
`Unknown value "${value}" in ${source}; use one of ${[...TRUE_VALUES, ...FALSE_VALUES].join(", ")}.`
|
|
@@ -29038,44 +29047,106 @@ function parseConfirm(value, source) {
|
|
|
29038
29047
|
}
|
|
29039
29048
|
return mode;
|
|
29040
29049
|
}
|
|
29041
|
-
function
|
|
29042
|
-
|
|
29043
|
-
|
|
29044
|
-
|
|
29045
|
-
|
|
29046
|
-
throw new ToolError("invalid_argument", `${source} must be an integer from 1 to ${MAX_DOWNLOAD_MB}.`);
|
|
29050
|
+
function parseNumber(value, source) {
|
|
29051
|
+
const trimmed = value.trim();
|
|
29052
|
+
const parsed = trimmed === "" ? Number.NaN : Number(trimmed);
|
|
29053
|
+
if (!Number.isFinite(parsed)) {
|
|
29054
|
+
throw new ToolError("invalid_argument", `Unknown number "${value}" in ${source}; use a finite number.`);
|
|
29047
29055
|
}
|
|
29048
|
-
return
|
|
29056
|
+
return parsed;
|
|
29049
29057
|
}
|
|
29050
|
-
function
|
|
29051
|
-
const
|
|
29052
|
-
|
|
29058
|
+
function absolutePath(text2, source, env) {
|
|
29059
|
+
const home = env.HOME !== void 0 && isAbsolute3(env.HOME) ? env.HOME : homedir2();
|
|
29060
|
+
const expanded = text2 === "~" || text2.startsWith("~/") || text2.startsWith(`~${sep2}`) ? join(home, text2.slice(1)) : text2;
|
|
29061
|
+
if (!isAbsolute3(expanded)) throw new ToolError("invalid_argument", `${source} must be an absolute path.`);
|
|
29062
|
+
return resolvePath(expanded);
|
|
29053
29063
|
}
|
|
29054
|
-
function
|
|
29055
|
-
|
|
29056
|
-
const max = value("download_max_mb");
|
|
29057
|
-
return {
|
|
29058
|
-
download_dir: resolveDownloadDir(value("download_dir"), env, profile),
|
|
29059
|
-
download_max_mb: max === void 0 ? DEFAULT_DOWNLOAD_MAX_MB : downloadMaxMbText(max)
|
|
29060
|
-
};
|
|
29064
|
+
function absolutePaths(items, source, env) {
|
|
29065
|
+
return items.length > 0 ? items.map((item) => absolutePath(item, source, env)) : void 0;
|
|
29061
29066
|
}
|
|
29062
29067
|
function envText(name, env, profile) {
|
|
29063
29068
|
const variable = envName(name, profile);
|
|
29064
|
-
const
|
|
29065
|
-
return
|
|
29069
|
+
const text2 = env[variable];
|
|
29070
|
+
return text2 === void 0 || text2.trim() === "" ? void 0 : { text: text2, source: variable };
|
|
29066
29071
|
}
|
|
29067
29072
|
function flagOrEnvText(flags, name, env, profile) {
|
|
29068
29073
|
const flagged = flags[name];
|
|
29069
29074
|
return flagged !== void 0 ? { text: flagged, source: OPTIONS[name].flag } : envText(name, env, profile);
|
|
29070
29075
|
}
|
|
29076
|
+
function optionType(spec) {
|
|
29077
|
+
return typeof spec === "string" ? spec : spec.type;
|
|
29078
|
+
}
|
|
29079
|
+
function itemCount(count) {
|
|
29080
|
+
return count === 1 ? "1 item" : `${count} items`;
|
|
29081
|
+
}
|
|
29082
|
+
function numberBoundsError({ integer: integer2, min, max }, source) {
|
|
29083
|
+
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}` : "";
|
|
29084
|
+
return new ToolError("invalid_argument", `${source} must be ${integer2 ? "a whole number" : "a number"}${range}.`);
|
|
29085
|
+
}
|
|
29086
|
+
function countBoundsError({ min, max }, source) {
|
|
29087
|
+
const range = min !== void 0 && max !== void 0 ? `from ${min} to ${max} items` : min !== void 0 ? `at least ${itemCount(min)}` : `at most ${itemCount(max)}`;
|
|
29088
|
+
return new ToolError("invalid_argument", `${source} must list ${range}.`);
|
|
29089
|
+
}
|
|
29090
|
+
function withinBounds(spec, value, source) {
|
|
29091
|
+
if (value === void 0 || typeof spec === "string") return value;
|
|
29092
|
+
const bounds = spec;
|
|
29093
|
+
const { integer: integer2, min, max } = bounds;
|
|
29094
|
+
if (typeof value === "number") {
|
|
29095
|
+
if (integer2 && !Number.isInteger(value) || min !== void 0 && value < min || max !== void 0 && value > max) {
|
|
29096
|
+
throw numberBoundsError(bounds, source);
|
|
29097
|
+
}
|
|
29098
|
+
} else if (typeof value === "object" && (min !== void 0 && value.length < min || max !== void 0 && value.length > max)) {
|
|
29099
|
+
throw countBoundsError(bounds, source);
|
|
29100
|
+
}
|
|
29101
|
+
return value;
|
|
29102
|
+
}
|
|
29103
|
+
function parseOptionText(spec, given, env) {
|
|
29104
|
+
return withinBounds(spec, parseTypedText(optionType(spec), given, env), given.source);
|
|
29105
|
+
}
|
|
29106
|
+
function parseTypedText(kind, given, env) {
|
|
29107
|
+
switch (kind) {
|
|
29108
|
+
case "text":
|
|
29109
|
+
return nonBlank(given.text);
|
|
29110
|
+
case "boolean":
|
|
29111
|
+
return parseBoolean(given.text, given.source);
|
|
29112
|
+
case "number":
|
|
29113
|
+
return parseNumber(given.text, given.source);
|
|
29114
|
+
case "list": {
|
|
29115
|
+
const items = splitList(given.text);
|
|
29116
|
+
return items.length > 0 ? items : void 0;
|
|
29117
|
+
}
|
|
29118
|
+
case "path": {
|
|
29119
|
+
const text2 = nonBlank(given.text);
|
|
29120
|
+
return text2 === void 0 ? void 0 : absolutePath(text2, given.source, env);
|
|
29121
|
+
}
|
|
29122
|
+
case "paths":
|
|
29123
|
+
return absolutePaths(splitList(given.text), given.source, env);
|
|
29124
|
+
}
|
|
29125
|
+
}
|
|
29126
|
+
function optionsFrom(flags, env, profile) {
|
|
29127
|
+
const options = {};
|
|
29128
|
+
for (const [name, spec] of Object.entries(profileOptions(profile))) {
|
|
29129
|
+
if (flags[name] !== void 0) {
|
|
29130
|
+
const parsed = parseOptionText(spec, { text: flags[name], source: settingOptions(profile)[name].flag }, env);
|
|
29131
|
+
if (parsed !== void 0) options[name] = parsed;
|
|
29132
|
+
continue;
|
|
29133
|
+
}
|
|
29134
|
+
const fromEnv = envText(name, env, profile);
|
|
29135
|
+
if (fromEnv !== void 0) {
|
|
29136
|
+
const parsed = parseOptionText(spec, fromEnv, env);
|
|
29137
|
+
if (parsed !== void 0) options[name] = parsed;
|
|
29138
|
+
}
|
|
29139
|
+
}
|
|
29140
|
+
return options;
|
|
29141
|
+
}
|
|
29071
29142
|
function parseSettings(argv, env, profile = PROJECT_PROFILE) {
|
|
29072
|
-
const flags = readFlags(argv);
|
|
29143
|
+
const flags = readFlags(argv, profile);
|
|
29073
29144
|
const value = (name) => flagOrEnvText(flags, name, env, profile);
|
|
29145
|
+
const options = optionsFrom(flags, env, profile);
|
|
29074
29146
|
const settings = {
|
|
29075
29147
|
confirm: "harness",
|
|
29076
|
-
|
|
29077
|
-
...
|
|
29078
|
-
send_dirs: resolveSendDirs(listedDirectories(value("send_dirs")), env)
|
|
29148
|
+
options,
|
|
29149
|
+
...resolveDirectorySettings(options, env, profile)
|
|
29079
29150
|
};
|
|
29080
29151
|
const toolsets = value("toolsets");
|
|
29081
29152
|
if (toolsets) settings.toolsets = checkToolsets(splitList(toolsets.text), toolsets.source, profile.toolsets);
|
|
@@ -29087,25 +29158,12 @@ function parseSettings(argv, env, profile = PROJECT_PROFILE) {
|
|
|
29087
29158
|
if (excluded) settings.exclude_tools = splitList(excluded.text);
|
|
29088
29159
|
const confirm = value("confirm");
|
|
29089
29160
|
if (confirm) settings.confirm = parseConfirm(confirm.text.trim(), confirm.source);
|
|
29090
|
-
for (const name of SERVICE_OPTION_NAMES) {
|
|
29091
|
-
const given = value(name);
|
|
29092
|
-
if (given) settings[name] = parseBoolean(given.text, given.source);
|
|
29093
|
-
}
|
|
29094
29161
|
return settings;
|
|
29095
29162
|
}
|
|
29096
|
-
|
|
29097
|
-
|
|
29098
|
-
"
|
|
29099
|
-
|
|
29100
|
-
"exclude_tools",
|
|
29101
|
-
"state_dir",
|
|
29102
|
-
"download_dir",
|
|
29103
|
-
"download_max_mb",
|
|
29104
|
-
"send_dirs",
|
|
29105
|
-
...SERVICE_OPTION_NAMES
|
|
29106
|
-
];
|
|
29107
|
-
var LANGUAGE_OPTION = "language";
|
|
29108
|
-
var PLUGIN_OPTION_NAMES = [...TOOL_OPTION_NAMES, LANGUAGE_OPTION];
|
|
29163
|
+
function nonBlank(text2) {
|
|
29164
|
+
const trimmed = text2?.trim();
|
|
29165
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
29166
|
+
}
|
|
29109
29167
|
|
|
29110
29168
|
// src/core/account/read.ts
|
|
29111
29169
|
import { existsSync as existsSync2, statSync } from "node:fs";
|
|
@@ -29121,8 +29179,8 @@ function quoteBadLabel(value) {
|
|
|
29121
29179
|
const truncated = value.length > MAX_BAD_LABEL_PREVIEW ? `${value.slice(0, MAX_BAD_LABEL_PREVIEW)}\u2026` : value;
|
|
29122
29180
|
return JSON.stringify(truncated);
|
|
29123
29181
|
}
|
|
29124
|
-
function isLabel(
|
|
29125
|
-
return typeof
|
|
29182
|
+
function isLabel(text2) {
|
|
29183
|
+
return typeof text2 === "string" && LABEL_PATTERN.test(text2);
|
|
29126
29184
|
}
|
|
29127
29185
|
function checkLabel(label) {
|
|
29128
29186
|
if (!isLabel(label)) {
|
|
@@ -29341,6 +29399,7 @@ function lockHolder(path) {
|
|
|
29341
29399
|
}
|
|
29342
29400
|
|
|
29343
29401
|
// src/core/time.ts
|
|
29402
|
+
var MS_PER_S = 1e3;
|
|
29344
29403
|
var MS_PER_MINUTE = 6e4;
|
|
29345
29404
|
var MINUTES_PER_HOUR = 60;
|
|
29346
29405
|
var localOffsetMinutes = (ms) => -new Date(ms).getTimezoneOffset();
|
|
@@ -29360,10 +29419,10 @@ var MILLISECOND_DIGITS = 3;
|
|
|
29360
29419
|
var MIN_YEAR = 1e3;
|
|
29361
29420
|
var MAX_HOUR = 23;
|
|
29362
29421
|
var MAX_MINUTE = 59;
|
|
29363
|
-
function badTime(
|
|
29422
|
+
function badTime(text2, name) {
|
|
29364
29423
|
return new ToolError(
|
|
29365
29424
|
"invalid_argument",
|
|
29366
|
-
`${name} is not a time: ${JSON.stringify(
|
|
29425
|
+
`${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.`
|
|
29367
29426
|
);
|
|
29368
29427
|
}
|
|
29369
29428
|
function isCalendarDay(year, month, day) {
|
|
@@ -29371,21 +29430,21 @@ function isCalendarDay(year, month, day) {
|
|
|
29371
29430
|
date5.setUTCFullYear(year, month - 1, day);
|
|
29372
29431
|
return date5.getUTCFullYear() === year && date5.getUTCMonth() === month - 1 && date5.getUTCDate() === day;
|
|
29373
29432
|
}
|
|
29374
|
-
function parseTimeArgument(
|
|
29375
|
-
const match = TIME_PATTERN.exec(
|
|
29376
|
-
if (!match) throw badTime(
|
|
29433
|
+
function parseTimeArgument(text2, name) {
|
|
29434
|
+
const match = TIME_PATTERN.exec(text2.trim());
|
|
29435
|
+
if (!match) throw badTime(text2, name);
|
|
29377
29436
|
const [, year, month, day, hour = "0", minute = "0", second = "0", fraction = "", zulu, sign, offsetHour, offsetMin] = match;
|
|
29378
29437
|
const [y, mon, d, h, mi, s] = [year, month, day, hour, minute, second].map(Number);
|
|
29379
29438
|
const ms = Number(fraction.padEnd(MILLISECOND_DIGITS, "0").slice(0, MILLISECOND_DIGITS));
|
|
29380
29439
|
if (y < MIN_YEAR || !isCalendarDay(y, mon, d) || h > MAX_HOUR || mi > MAX_MINUTE || s > MAX_MINUTE) {
|
|
29381
|
-
throw badTime(
|
|
29440
|
+
throw badTime(text2, name);
|
|
29382
29441
|
}
|
|
29383
29442
|
if (sign === void 0 && zulu === void 0) return new Date(y, mon - 1, d, h, mi, s, ms).getTime();
|
|
29384
29443
|
const wall = Date.UTC(y, mon - 1, d, h, mi, s, ms);
|
|
29385
29444
|
if (zulu) return wall;
|
|
29386
29445
|
const offsetH = Number(offsetHour);
|
|
29387
29446
|
const offsetM = Number(offsetMin);
|
|
29388
|
-
if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(
|
|
29447
|
+
if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(text2, name);
|
|
29389
29448
|
const offset = (offsetH * MINUTES_PER_HOUR + offsetM) * MS_PER_MINUTE;
|
|
29390
29449
|
return sign === "-" ? wall + offset : wall - offset;
|
|
29391
29450
|
}
|
|
@@ -29604,23 +29663,23 @@ function encodeCursor(value) {
|
|
|
29604
29663
|
function notACursor(name) {
|
|
29605
29664
|
return new ToolError("invalid_argument", `${name} is not a cursor this tool returned.`);
|
|
29606
29665
|
}
|
|
29607
|
-
function decodeCursor(
|
|
29608
|
-
const bytes = Buffer3.from(
|
|
29609
|
-
if (bytes.toString("base64url") !==
|
|
29666
|
+
function decodeCursor(text2, name) {
|
|
29667
|
+
const bytes = Buffer3.from(text2, "base64url");
|
|
29668
|
+
if (bytes.toString("base64url") !== text2) throw notACursor(name);
|
|
29610
29669
|
try {
|
|
29611
29670
|
return JSON.parse(bytes.toString("utf8"));
|
|
29612
29671
|
} catch {
|
|
29613
29672
|
throw notACursor(name);
|
|
29614
29673
|
}
|
|
29615
29674
|
}
|
|
29616
|
-
function readCursor(
|
|
29617
|
-
const parsed = schema.safeParse(decodeCursor(
|
|
29675
|
+
function readCursor(text2, name, schema) {
|
|
29676
|
+
const parsed = schema.safeParse(decodeCursor(text2, name));
|
|
29618
29677
|
if (!parsed.success) throw notACursor(name);
|
|
29619
29678
|
return parsed.data;
|
|
29620
29679
|
}
|
|
29621
29680
|
var HIGH_SURROGATE = /[\uD800-\uDBFF]$/;
|
|
29622
|
-
function cutText(
|
|
29623
|
-
return
|
|
29681
|
+
function cutText(text2, keep) {
|
|
29682
|
+
return text2.length <= keep ? text2 : text2.slice(0, keep).replace(HIGH_SURROGATE, "");
|
|
29624
29683
|
}
|
|
29625
29684
|
function jsonLength(value) {
|
|
29626
29685
|
return JSON.stringify(value).length;
|
|
@@ -29710,15 +29769,15 @@ var ERROR_CODES = {
|
|
|
29710
29769
|
function isErrorCode(value) {
|
|
29711
29770
|
return typeof value === "string" && Object.hasOwn(ERROR_CODES, value);
|
|
29712
29771
|
}
|
|
29713
|
-
function maskPhoneNumbers(
|
|
29714
|
-
return
|
|
29772
|
+
function maskPhoneNumbers(text2) {
|
|
29773
|
+
return text2.replace(PHONE_NUMBER, "[number]");
|
|
29715
29774
|
}
|
|
29716
29775
|
function cut2(message) {
|
|
29717
29776
|
return maskPhoneNumbers(message).trim().slice(0, MAX_DETAIL_LENGTH);
|
|
29718
29777
|
}
|
|
29719
29778
|
function detail(message) {
|
|
29720
|
-
const
|
|
29721
|
-
return
|
|
29779
|
+
const text2 = cut2(message);
|
|
29780
|
+
return text2 ? `: ${text2}` : "";
|
|
29722
29781
|
}
|
|
29723
29782
|
function afterWriteError(method, effect, reason) {
|
|
29724
29783
|
return effect === "write" ? new ToolError("uncertain", `${method} may have taken effect (${reason}). ${UNCERTAIN_ADVICE}`) : new ToolError("upstream_error", `${method} failed (${reason}).`);
|
|
@@ -29896,19 +29955,19 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
29896
29955
|
socket.on("error", (error62) => {
|
|
29897
29956
|
this.endReason ??= `the connection to the service broke${error62.code ? ` (${error62.code})` : ""}`;
|
|
29898
29957
|
});
|
|
29899
|
-
this.closed = new Promise((
|
|
29958
|
+
this.closed = new Promise((resolve5) => {
|
|
29900
29959
|
socket.once("close", () => {
|
|
29901
29960
|
this.endReason ??= "the service closed the connection";
|
|
29902
29961
|
const lost = { lost: this.endReason };
|
|
29903
29962
|
for (const settle2 of [...this.pending.values()]) settle2(lost);
|
|
29904
|
-
|
|
29963
|
+
resolve5();
|
|
29905
29964
|
});
|
|
29906
29965
|
});
|
|
29907
29966
|
}
|
|
29908
29967
|
/** Connects to the service's socket; rejects as `upstream_error` when nothing is listening there. */
|
|
29909
29968
|
static connect(socketPath, options = {}) {
|
|
29910
29969
|
const { timeoutMs = DEFAULT_CONNECT_TIMEOUT_MS, signal, maxLineLength = DEFAULT_MAX_LINE_LENGTH } = options;
|
|
29911
|
-
return new Promise((
|
|
29970
|
+
return new Promise((resolve5, reject) => {
|
|
29912
29971
|
if (signal?.aborted) {
|
|
29913
29972
|
reject(abortError(signal));
|
|
29914
29973
|
return;
|
|
@@ -29930,7 +29989,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
29930
29989
|
};
|
|
29931
29990
|
const onConnect = () => {
|
|
29932
29991
|
detach();
|
|
29933
|
-
|
|
29992
|
+
resolve5(new _ServiceConnection(socket, maxLineLength));
|
|
29934
29993
|
};
|
|
29935
29994
|
const onFailure = () => stop(new ToolError("upstream_error", NOT_RUNNING_MESSAGE));
|
|
29936
29995
|
const onAbort = () => stop(abortError(signal));
|
|
@@ -29953,7 +30012,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
29953
30012
|
*/
|
|
29954
30013
|
call(method, params, options) {
|
|
29955
30014
|
const { effect, timeoutMs = DEFAULT_CALL_TIMEOUT_MS, signal } = options;
|
|
29956
|
-
return new Promise((
|
|
30015
|
+
return new Promise((resolve5, reject) => {
|
|
29957
30016
|
if (signal?.aborted) {
|
|
29958
30017
|
reject(abortError(signal));
|
|
29959
30018
|
return;
|
|
@@ -29982,7 +30041,7 @@ var ServiceConnection = class _ServiceConnection {
|
|
|
29982
30041
|
clearTimeout(timer);
|
|
29983
30042
|
signal?.removeEventListener("abort", onAbort);
|
|
29984
30043
|
try {
|
|
29985
|
-
|
|
30044
|
+
resolve5(produce());
|
|
29986
30045
|
} catch (error62) {
|
|
29987
30046
|
reject(error62);
|
|
29988
30047
|
}
|
|
@@ -30055,7 +30114,6 @@ async function callService(socketPath, method, params, options) {
|
|
|
30055
30114
|
// src/core/chat/live.ts
|
|
30056
30115
|
var REFRESH_TIMEOUT_MS = 12e4;
|
|
30057
30116
|
var FETCH_TIMEOUT_MS = 18e4;
|
|
30058
|
-
var MS_PER_S = 1e3;
|
|
30059
30117
|
function requestHistory(socket, params, signal) {
|
|
30060
30118
|
return callService(socket, SERVICE_REQUESTS.history, params, { effect: "read", signal });
|
|
30061
30119
|
}
|
|
@@ -30183,113 +30241,6 @@ var messageEntry = external_exports.object({
|
|
|
30183
30241
|
private_note: external_exports.string().optional()
|
|
30184
30242
|
});
|
|
30185
30243
|
|
|
30186
|
-
// src/core/chat/schema.ts
|
|
30187
|
-
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
30188
|
-
var GENERAL_TOPIC2 = 1;
|
|
30189
|
-
var LIMITS = {
|
|
30190
|
-
list: { default: 30, max: 200 },
|
|
30191
|
-
view: { default: 50, max: 300 },
|
|
30192
|
-
topics: { default: 30, max: TOPICS_LIMIT },
|
|
30193
|
-
search: { default: 30, max: 200 }
|
|
30194
|
-
};
|
|
30195
|
-
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
30196
|
-
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
30197
|
-
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
30198
|
-
var input3 = external_exports.object({
|
|
30199
|
-
method: external_exports.enum(METHODS).describe(
|
|
30200
|
-
"`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."
|
|
30201
|
-
),
|
|
30202
|
-
account: accountArgument,
|
|
30203
|
-
query: external_exports.string().optional().describe(
|
|
30204
|
-
"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."
|
|
30205
|
-
),
|
|
30206
|
-
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
30207
|
-
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
30208
|
-
refresh: external_exports.boolean().optional().describe(
|
|
30209
|
-
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
30210
|
-
),
|
|
30211
|
-
chat: external_exports.string().optional().describe(
|
|
30212
|
-
"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."
|
|
30213
|
-
),
|
|
30214
|
-
topic: external_exports.number().int().positive().optional().describe(
|
|
30215
|
-
`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.`
|
|
30216
|
-
),
|
|
30217
|
-
after: external_exports.string().optional().describe(
|
|
30218
|
-
"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."
|
|
30219
|
-
),
|
|
30220
|
-
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
30221
|
-
limit: external_exports.number().int().optional().describe(
|
|
30222
|
-
`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.`
|
|
30223
|
-
),
|
|
30224
|
-
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
30225
|
-
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
30226
|
-
before_count: external_exports.number().int().optional().describe(
|
|
30227
|
-
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
30228
|
-
),
|
|
30229
|
-
after_count: external_exports.number().int().optional().describe(
|
|
30230
|
-
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
30231
|
-
),
|
|
30232
|
-
pages: external_exports.number().int().optional().describe(
|
|
30233
|
-
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
30234
|
-
)
|
|
30235
|
-
});
|
|
30236
|
-
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
30237
|
-
var chatEntry2 = external_exports.object({
|
|
30238
|
-
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
30239
|
-
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
30240
|
-
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
30241
|
-
name_cut: nameCut,
|
|
30242
|
-
username: external_exports.string().optional(),
|
|
30243
|
-
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
30244
|
-
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
30245
|
-
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
30246
|
-
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
30247
|
-
archived: external_exports.literal(true).optional(),
|
|
30248
|
-
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
30249
|
-
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
30250
|
-
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
30251
|
-
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
30252
|
-
});
|
|
30253
|
-
var topicEntry = external_exports.object({
|
|
30254
|
-
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC2} is the General topic.`),
|
|
30255
|
-
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
30256
|
-
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
30257
|
-
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
30258
|
-
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
30259
|
-
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
30260
|
-
});
|
|
30261
|
-
var output3 = external_exports.object({
|
|
30262
|
-
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
30263
|
-
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
30264
|
-
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
30265
|
-
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
30266
|
-
live: external_exports.literal(true).optional().describe(
|
|
30267
|
-
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
30268
|
-
),
|
|
30269
|
-
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
30270
|
-
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
30271
|
-
trimmed_before: external_exports.number().int().optional().describe(
|
|
30272
|
-
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
30273
|
-
),
|
|
30274
|
-
trimmed_after: external_exports.number().int().optional().describe(
|
|
30275
|
-
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
30276
|
-
),
|
|
30277
|
-
scanned_to: localTimeSchema.optional().describe(
|
|
30278
|
-
"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."
|
|
30279
|
-
),
|
|
30280
|
-
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
30281
|
-
fetched: external_exports.object({
|
|
30282
|
-
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
30283
|
-
pages: external_exports.number().int().describe("How many pages were read."),
|
|
30284
|
-
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
30285
|
-
oldest_at: localTimeSchema.nullable().describe(
|
|
30286
|
-
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
30287
|
-
)
|
|
30288
|
-
}).optional().describe("fetch: what the history fetch stored."),
|
|
30289
|
-
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
30290
|
-
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
30291
|
-
});
|
|
30292
|
-
|
|
30293
30244
|
// src/core/chat/message-rows.ts
|
|
30294
30245
|
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";
|
|
30295
30246
|
function liveMessages(now) {
|
|
@@ -30297,7 +30248,7 @@ function liveMessages(now) {
|
|
|
30297
30248
|
}
|
|
30298
30249
|
function inTopic(topic) {
|
|
30299
30250
|
return {
|
|
30300
|
-
condition: topic ===
|
|
30251
|
+
condition: topic === GENERAL_TOPIC ? "(topic IS NULL OR topic = ?)" : "topic = ?",
|
|
30301
30252
|
params: [topic]
|
|
30302
30253
|
};
|
|
30303
30254
|
}
|
|
@@ -30410,10 +30361,10 @@ function replyTo(parsed, related) {
|
|
|
30410
30361
|
if (reply.chat !== void 0) entry2.chat = reply.chat;
|
|
30411
30362
|
if (reply.topic !== void 0) entry2.topic = reply.topic;
|
|
30412
30363
|
if (reply.quote !== void 0) entry2.quote = reply.quote;
|
|
30413
|
-
const
|
|
30414
|
-
if (
|
|
30415
|
-
entry2.text = cutText(
|
|
30416
|
-
if (entry2.text.length <
|
|
30364
|
+
const text2 = repliedText(parsed, related)?.text;
|
|
30365
|
+
if (text2 !== void 0) {
|
|
30366
|
+
entry2.text = cutText(text2, REPLY_TEXT_LENGTH);
|
|
30367
|
+
if (entry2.text.length < text2.length) entry2.text_cut = true;
|
|
30417
30368
|
}
|
|
30418
30369
|
return entry2;
|
|
30419
30370
|
}
|
|
@@ -30482,25 +30433,25 @@ function texts(entry2) {
|
|
|
30482
30433
|
];
|
|
30483
30434
|
}
|
|
30484
30435
|
function messageTextLength(entry2) {
|
|
30485
|
-
return texts(entry2).reduce((total,
|
|
30436
|
+
return texts(entry2).reduce((total, text2) => total + text2.length, 0);
|
|
30486
30437
|
}
|
|
30487
30438
|
function cutMessage(entry2, keep) {
|
|
30488
30439
|
let room = keep;
|
|
30489
30440
|
let cut3 = false;
|
|
30490
|
-
const take = (
|
|
30491
|
-
const kept = cutText(
|
|
30492
|
-
room = Math.max(0, room -
|
|
30493
|
-
if (kept.length <
|
|
30441
|
+
const take = (text2) => {
|
|
30442
|
+
const kept = cutText(text2, room);
|
|
30443
|
+
room = Math.max(0, room - text2.length);
|
|
30444
|
+
if (kept.length < text2.length) cut3 = true;
|
|
30494
30445
|
return kept;
|
|
30495
30446
|
};
|
|
30496
30447
|
const cutEntry = { ...entry2 };
|
|
30497
30448
|
if (entry2.text !== void 0) cutEntry.text = take(entry2.text);
|
|
30498
30449
|
if (entry2.reply_to) {
|
|
30499
|
-
const { quote, text } = entry2.reply_to;
|
|
30450
|
+
const { quote, text: text2 } = entry2.reply_to;
|
|
30500
30451
|
cutEntry.reply_to = {
|
|
30501
30452
|
...entry2.reply_to,
|
|
30502
30453
|
...quote === void 0 ? {} : { quote: take(quote) },
|
|
30503
|
-
...
|
|
30454
|
+
...text2 === void 0 ? {} : { text: take(text2) }
|
|
30504
30455
|
};
|
|
30505
30456
|
}
|
|
30506
30457
|
if (entry2.earlier_versions)
|
|
@@ -30522,6 +30473,112 @@ var cuttableMessage = {
|
|
|
30522
30473
|
drop: dropMetadata
|
|
30523
30474
|
};
|
|
30524
30475
|
|
|
30476
|
+
// src/core/chat/schema.ts
|
|
30477
|
+
var METHODS = ["list", "view", "topics", "search", "around", "fetch"];
|
|
30478
|
+
var LIMITS = {
|
|
30479
|
+
list: { default: 30, max: 200 },
|
|
30480
|
+
view: { default: 50, max: 300 },
|
|
30481
|
+
topics: { default: 30, max: TOPICS_LIMIT },
|
|
30482
|
+
search: { default: 30, max: 200 }
|
|
30483
|
+
};
|
|
30484
|
+
var AROUND_COUNT = { default: 5, max: AROUND_LIMIT };
|
|
30485
|
+
var FETCH_PAGES = { default: 1, max: FETCH_PAGE_LIMIT };
|
|
30486
|
+
var accountArgument = external_exports.string().optional().describe("The account label; may be left out when only one account is logged in.");
|
|
30487
|
+
var input3 = external_exports.object({
|
|
30488
|
+
method: external_exports.enum(METHODS).describe(
|
|
30489
|
+
"`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."
|
|
30490
|
+
),
|
|
30491
|
+
account: accountArgument,
|
|
30492
|
+
query: external_exports.string().optional().describe(
|
|
30493
|
+
"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."
|
|
30494
|
+
),
|
|
30495
|
+
unread: external_exports.boolean().optional().describe("list: only chats with unread messages."),
|
|
30496
|
+
last: external_exports.boolean().optional().describe("list: add each chat's newest mirrored message as `last_message`."),
|
|
30497
|
+
refresh: external_exports.boolean().optional().describe(
|
|
30498
|
+
"list: first take the chat list from Telegram (needs the sync service), then read it, and report when in `refreshed_at`."
|
|
30499
|
+
),
|
|
30500
|
+
chat: external_exports.string().optional().describe(
|
|
30501
|
+
"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."
|
|
30502
|
+
),
|
|
30503
|
+
topic: external_exports.number().int().positive().optional().describe(
|
|
30504
|
+
`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.`
|
|
30505
|
+
),
|
|
30506
|
+
after: external_exports.string().optional().describe(
|
|
30507
|
+
"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."
|
|
30508
|
+
),
|
|
30509
|
+
before: external_exports.string().optional().describe("view, search: only messages before this time (exclusive); the same forms as `after`."),
|
|
30510
|
+
limit: external_exports.number().int().optional().describe(
|
|
30511
|
+
`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.`
|
|
30512
|
+
),
|
|
30513
|
+
cursor: external_exports.string().optional().describe("The `next` of the previous result, to continue where it stopped."),
|
|
30514
|
+
id: external_exports.number().int().positive().optional().describe("around (required): the id of the message to read around."),
|
|
30515
|
+
before_count: external_exports.number().int().optional().describe(
|
|
30516
|
+
`around: how many older messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
30517
|
+
),
|
|
30518
|
+
after_count: external_exports.number().int().optional().describe(
|
|
30519
|
+
`around: how many newer messages to return, default ${AROUND_COUNT.default}, at most ${AROUND_COUNT.max}; 0 asks for none.`
|
|
30520
|
+
),
|
|
30521
|
+
pages: external_exports.number().int().optional().describe(
|
|
30522
|
+
`fetch: how many pages of ${FETCH_PAGE_SIZE} older messages to add, default ${FETCH_PAGES.default}, at most ${FETCH_PAGES.max}.`
|
|
30523
|
+
)
|
|
30524
|
+
});
|
|
30525
|
+
var nameCut = external_exports.literal(true).optional().describe("Set when the name was longer than the most a result carries and was cut.");
|
|
30526
|
+
var chatEntry2 = external_exports.object({
|
|
30527
|
+
id: external_exports.string().describe("The chat id: Telegram's signed id as text, such as `123456789` or `-1001234567890`."),
|
|
30528
|
+
kind: external_exports.enum(CHAT_KINDS).describe("`self` is Saved Messages."),
|
|
30529
|
+
name: external_exports.string().nullable().describe("The person's or chat's name; null when none is known."),
|
|
30530
|
+
name_cut: nameCut,
|
|
30531
|
+
username: external_exports.string().optional(),
|
|
30532
|
+
mirrored: external_exports.boolean().describe("Whether the mirror keeps this chat's messages."),
|
|
30533
|
+
unread: external_exports.number().int().describe("Incoming messages not read yet."),
|
|
30534
|
+
last_activity_at: localTimeSchema.nullable().describe("The latest message's time, in local time with offset; null when none is known."),
|
|
30535
|
+
forum: external_exports.literal(true).optional().describe("Set for a supergroup with topics."),
|
|
30536
|
+
archived: external_exports.literal(true).optional(),
|
|
30537
|
+
left: external_exports.literal(true).optional().describe("Set for a group or channel the user has left or been removed from."),
|
|
30538
|
+
can_send: external_exports.literal(false).optional().describe("Set when the user is known not to be able to write here."),
|
|
30539
|
+
auto_delete_seconds: external_exports.number().int().optional().describe("The chat's auto-delete period, when on."),
|
|
30540
|
+
last_message: messageEntry.nullable().optional().describe("With `last`: the newest mirrored message of the chat, or null when none is mirrored.")
|
|
30541
|
+
});
|
|
30542
|
+
var topicEntry = external_exports.object({
|
|
30543
|
+
id: external_exports.number().int().describe(`The topic id, to pass as \`topic\` to \`view\`; ${GENERAL_TOPIC} is the General topic.`),
|
|
30544
|
+
title: external_exports.string().nullable().describe("The topic's title; null when none is known."),
|
|
30545
|
+
closed: external_exports.literal(true).optional().describe("Set for a topic that is closed."),
|
|
30546
|
+
pinned: external_exports.literal(true).optional().describe("Set for a topic that is pinned."),
|
|
30547
|
+
unread: external_exports.number().int().describe("Messages in it not read yet."),
|
|
30548
|
+
last_activity_at: localTimeSchema.nullable().describe("The newest message's time, in local time with offset; null when none is known.")
|
|
30549
|
+
});
|
|
30550
|
+
var output3 = external_exports.object({
|
|
30551
|
+
chats: external_exports.array(chatEntry2).optional().describe("list: the chats, newest activity first."),
|
|
30552
|
+
refreshed_at: localTimeSchema.optional().describe("list with `refresh`: when the chat list was taken from Telegram, in local time with offset."),
|
|
30553
|
+
chat: chatEntry2.optional().describe("view, topics, around, fetch: the chat read."),
|
|
30554
|
+
messages: external_exports.array(messageEntry).optional().describe("view, around: the messages, oldest first. search: the hits, newest first."),
|
|
30555
|
+
live: external_exports.literal(true).optional().describe(
|
|
30556
|
+
"view, around: set when the chat is not mirrored, so the messages were read from Telegram and stored nowhere."
|
|
30557
|
+
),
|
|
30558
|
+
topics: external_exports.array(topicEntry).optional().describe("topics: the topics, most recently active first."),
|
|
30559
|
+
anchor: external_exports.number().int().optional().describe("around: the id of the message read around, among `messages`."),
|
|
30560
|
+
trimmed_before: external_exports.number().int().optional().describe(
|
|
30561
|
+
"around: how many older messages were left out, farthest first, to keep the result a size that can be read."
|
|
30562
|
+
),
|
|
30563
|
+
trimmed_after: external_exports.number().int().optional().describe(
|
|
30564
|
+
"around: how many newer messages were left out, farthest first, to keep the result a size that can be read."
|
|
30565
|
+
),
|
|
30566
|
+
scanned_to: localTimeSchema.optional().describe(
|
|
30567
|
+
"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."
|
|
30568
|
+
),
|
|
30569
|
+
scope: external_exports.string().optional().describe("search: what the search covers and what it does not."),
|
|
30570
|
+
fetched: external_exports.object({
|
|
30571
|
+
added: external_exports.number().int().describe("How many messages the mirror gained."),
|
|
30572
|
+
pages: external_exports.number().int().describe("How many pages were read."),
|
|
30573
|
+
complete: external_exports.boolean().describe("Whether Telegram has nothing older for this chat."),
|
|
30574
|
+
oldest_at: localTimeSchema.nullable().describe(
|
|
30575
|
+
"The time of the oldest message the mirror now holds of this chat, in local time with offset; null when none."
|
|
30576
|
+
)
|
|
30577
|
+
}).optional().describe("fetch: what the history fetch stored."),
|
|
30578
|
+
next: external_exports.string().optional().describe("Pass back as `cursor` to continue; absent when there is no more."),
|
|
30579
|
+
note: external_exports.string().describe("Says that what the result carries is data written by other people.")
|
|
30580
|
+
});
|
|
30581
|
+
|
|
30525
30582
|
// src/core/chat/around.ts
|
|
30526
30583
|
var TRIMMED_RESERVE = 100;
|
|
30527
30584
|
var NO_MESSAGE = "No message with this id in this chat.";
|
|
@@ -30643,8 +30700,8 @@ function fetchResult(read, stored) {
|
|
|
30643
30700
|
}
|
|
30644
30701
|
|
|
30645
30702
|
// src/core/fold.ts
|
|
30646
|
-
function foldCase(
|
|
30647
|
-
return
|
|
30703
|
+
function foldCase(text2) {
|
|
30704
|
+
return text2.normalize("NFKC").toUpperCase().toLowerCase().replace(/ς/g, "\u03C3");
|
|
30648
30705
|
}
|
|
30649
30706
|
|
|
30650
30707
|
// src/core/chat/filter.ts
|
|
@@ -30724,7 +30781,7 @@ function listChats(mirror, args, now) {
|
|
|
30724
30781
|
return result;
|
|
30725
30782
|
}
|
|
30726
30783
|
|
|
30727
|
-
// src/core/
|
|
30784
|
+
// src/core/open.ts
|
|
30728
30785
|
async function pickPaths(ctx, account2) {
|
|
30729
30786
|
if (!ctx.stateDir) throw new ToolError("internal_error", "The entry point did not supply a state directory.");
|
|
30730
30787
|
return pickLabel(ctx.stateDir, account2);
|
|
@@ -30783,8 +30840,8 @@ function foldedFileName(media) {
|
|
|
30783
30840
|
return isRecord(info) && typeof info.name === "string" ? foldCase(info.name) : void 0;
|
|
30784
30841
|
}
|
|
30785
30842
|
function matchesAllWords(row, words2) {
|
|
30786
|
-
const
|
|
30787
|
-
const unmatched = words2.filter((word) => !
|
|
30843
|
+
const text2 = foldCase(row.body ?? "");
|
|
30844
|
+
const unmatched = words2.filter((word) => !text2.includes(word));
|
|
30788
30845
|
if (unmatched.length === 0) return true;
|
|
30789
30846
|
const name = row.media === null ? void 0 : foldedFileName(row.media);
|
|
30790
30847
|
return name !== void 0 && unmatched.every((word) => name.includes(word));
|
|
@@ -31133,6 +31190,32 @@ function chatFact(kind) {
|
|
|
31133
31190
|
return { label: "Chat", value: { text: CHAT_KIND_WORDS[kind] } };
|
|
31134
31191
|
}
|
|
31135
31192
|
|
|
31193
|
+
// src/core/chat/media-facts.ts
|
|
31194
|
+
var MEDIA_KIND_WORDS = {
|
|
31195
|
+
photo: "Photo",
|
|
31196
|
+
document: "Document",
|
|
31197
|
+
audio: "Audio",
|
|
31198
|
+
voice: "Voice message",
|
|
31199
|
+
video: "Video",
|
|
31200
|
+
sticker: "Sticker",
|
|
31201
|
+
dice: "Dice",
|
|
31202
|
+
contact: "Contact",
|
|
31203
|
+
venue: "Venue",
|
|
31204
|
+
geo: "Location",
|
|
31205
|
+
geo_live: "Live location",
|
|
31206
|
+
game: "Game",
|
|
31207
|
+
invoice: "Invoice",
|
|
31208
|
+
webpage: "Link preview",
|
|
31209
|
+
poll: "Poll",
|
|
31210
|
+
todo: "Checklist",
|
|
31211
|
+
story: "Story",
|
|
31212
|
+
paid: "Paid media",
|
|
31213
|
+
unsupported: "Unsupported media"
|
|
31214
|
+
};
|
|
31215
|
+
function mediaKindValue(type) {
|
|
31216
|
+
return Object.hasOwn(MEDIA_KIND_WORDS, type) ? { text: MEDIA_KIND_WORDS[type] } : type;
|
|
31217
|
+
}
|
|
31218
|
+
|
|
31136
31219
|
// src/core/file/constants.ts
|
|
31137
31220
|
var FILE_SAVE_TOOL_ID = "telegram_file_save";
|
|
31138
31221
|
var FILE_SEND_TOOL_ID = "telegram_file_send";
|
|
@@ -31317,7 +31400,7 @@ async function openMessageFolder(downloadDir, folder) {
|
|
|
31317
31400
|
|
|
31318
31401
|
// src/core/file/incoming.ts
|
|
31319
31402
|
import { lstat as lstat4, realpath as realpath3 } from "node:fs/promises";
|
|
31320
|
-
import { dirname as dirname3, isAbsolute as isAbsolute6, resolve as
|
|
31403
|
+
import { dirname as dirname3, isAbsolute as isAbsolute6, resolve as resolve2 } from "node:path";
|
|
31321
31404
|
|
|
31322
31405
|
// src/core/file/place.ts
|
|
31323
31406
|
import { createHash as createHash3, randomBytes } from "node:crypto";
|
|
@@ -31335,11 +31418,11 @@ var ANIMATED_STICKER = "an animated sticker (.tgs), which cannot be inspected";
|
|
|
31335
31418
|
function unreadableArchive(label) {
|
|
31336
31419
|
return `an archive that cannot be inspected (${label})`;
|
|
31337
31420
|
}
|
|
31338
|
-
function words(
|
|
31339
|
-
return
|
|
31421
|
+
function words(text2) {
|
|
31422
|
+
return text2.split(/\s+/).filter((word) => word !== "");
|
|
31340
31423
|
}
|
|
31341
|
-
function ascii(
|
|
31342
|
-
return Array.from(
|
|
31424
|
+
function ascii(text2) {
|
|
31425
|
+
return Array.from(text2, (character) => character.charCodeAt(0));
|
|
31343
31426
|
}
|
|
31344
31427
|
function at(offset, bytes) {
|
|
31345
31428
|
return { offset, bytes };
|
|
@@ -31556,7 +31639,7 @@ function parseOctal(field) {
|
|
|
31556
31639
|
}
|
|
31557
31640
|
return digits > 0 ? value : void 0;
|
|
31558
31641
|
}
|
|
31559
|
-
function
|
|
31642
|
+
function parseNumber2(field) {
|
|
31560
31643
|
const first = field[0];
|
|
31561
31644
|
if (first === void 0 || (first & BASE256_FLAG) === 0) return parseOctal(field);
|
|
31562
31645
|
if (first === BASE256_NEGATIVE) return void 0;
|
|
@@ -31595,11 +31678,11 @@ function parseHeader(block) {
|
|
|
31595
31678
|
path[prefix.length] = "/".charCodeAt(0);
|
|
31596
31679
|
path.set(name, prefix.length + 1);
|
|
31597
31680
|
}
|
|
31598
|
-
return { path, size:
|
|
31681
|
+
return { path, size: parseNumber2(block.subarray(SIZE_START, SIZE_END)), type: block[TYPE_OFFSET] };
|
|
31599
31682
|
}
|
|
31600
|
-
function parseDecimal(
|
|
31601
|
-
if (!/^[0-9]{1,15}$/.test(
|
|
31602
|
-
return Number(
|
|
31683
|
+
function parseDecimal(text2) {
|
|
31684
|
+
if (!/^[0-9]{1,15}$/.test(text2)) return void 0;
|
|
31685
|
+
return Number(text2);
|
|
31603
31686
|
}
|
|
31604
31687
|
function parsePaxRecords(data, maxRecords = Infinity) {
|
|
31605
31688
|
const records = [];
|
|
@@ -31789,8 +31872,8 @@ var EXTENSIONS = {
|
|
|
31789
31872
|
};
|
|
31790
31873
|
var KIND_PATTERN = /^[a-z]{1,16}$/;
|
|
31791
31874
|
var UNKNOWN_KIND = "file";
|
|
31792
|
-
function byteLength(
|
|
31793
|
-
return Buffer5.byteLength(
|
|
31875
|
+
function byteLength(text2) {
|
|
31876
|
+
return Buffer5.byteLength(text2);
|
|
31794
31877
|
}
|
|
31795
31878
|
function extensionOf2(type) {
|
|
31796
31879
|
return type == null ? "" : EXTENSIONS[type.split(";")[0].trim().toLowerCase()] ?? "";
|
|
@@ -31958,7 +32041,7 @@ async function openDownloaded(incoming, path) {
|
|
|
31958
32041
|
}
|
|
31959
32042
|
async function discardDownload(incoming, path) {
|
|
31960
32043
|
if (!isAbsolute6(path)) return;
|
|
31961
|
-
const folder = dirname3(
|
|
32044
|
+
const folder = dirname3(resolve2(path));
|
|
31962
32045
|
if (dirname3(folder) !== incoming) return;
|
|
31963
32046
|
await discard(folder).catch(() => {
|
|
31964
32047
|
});
|
|
@@ -32059,8 +32142,8 @@ function fitListings(result) {
|
|
|
32059
32142
|
var MAX_NAME_CHARACTERS = 255;
|
|
32060
32143
|
var CUT_MARK = "\u2026";
|
|
32061
32144
|
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;
|
|
32062
|
-
function cleanName(
|
|
32063
|
-
const cleaned =
|
|
32145
|
+
function cleanName(text2) {
|
|
32146
|
+
const cleaned = text2.normalize("NFC").replace(HIDDEN_CHARACTERS, "?");
|
|
32064
32147
|
const characters = Array.from(cleaned);
|
|
32065
32148
|
if (characters.length <= MAX_NAME_CHARACTERS) return cleaned;
|
|
32066
32149
|
return characters.slice(0, MAX_NAME_CHARACTERS - CUT_MARK.length).join("") + CUT_MARK;
|
|
@@ -32233,9 +32316,9 @@ function decodeUtf8Lossy(bytes) {
|
|
|
32233
32316
|
return LOSSY_UTF8.decode(bytes);
|
|
32234
32317
|
}
|
|
32235
32318
|
function decodeCp437(bytes) {
|
|
32236
|
-
let
|
|
32237
|
-
for (const byte of bytes)
|
|
32238
|
-
return
|
|
32319
|
+
let text2 = "";
|
|
32320
|
+
for (const byte of bytes) text2 += byte < ASCII_END ? String.fromCharCode(byte) : CP437_HIGH[byte - ASCII_END];
|
|
32321
|
+
return text2;
|
|
32239
32322
|
}
|
|
32240
32323
|
|
|
32241
32324
|
// src/core/archive/tar.ts
|
|
@@ -33055,14 +33138,6 @@ function namesOf(file2, id) {
|
|
|
33055
33138
|
const name = safeFileName(file2.name, { kind: file2.kind, id, type: file2.type });
|
|
33056
33139
|
return { name, shown: file2.name === null ? file2.kind : name };
|
|
33057
33140
|
}
|
|
33058
|
-
var FILE_KIND_WORDS = {
|
|
33059
|
-
photo: "Photo",
|
|
33060
|
-
document: "Document",
|
|
33061
|
-
audio: "Audio",
|
|
33062
|
-
voice: "Voice message",
|
|
33063
|
-
video: "Video",
|
|
33064
|
-
sticker: "Sticker"
|
|
33065
|
-
};
|
|
33066
33141
|
function saveHeadline(file2, chat) {
|
|
33067
33142
|
if (file2 !== void 0 && chat !== null) return { text: "About to save {file} from {chat}", values: { file: file2, chat } };
|
|
33068
33143
|
if (chat !== null) return { text: "About to save a file from {chat}", values: { chat } };
|
|
@@ -33070,9 +33145,8 @@ function saveHeadline(file2, chat) {
|
|
|
33070
33145
|
return void 0;
|
|
33071
33146
|
}
|
|
33072
33147
|
function fileFacts(media, unpack) {
|
|
33073
|
-
const kind = media && Object.hasOwn(FILE_KIND_WORDS, media.type) ? FILE_KIND_WORDS[media.type] : void 0;
|
|
33074
33148
|
return [
|
|
33075
|
-
...media ? [{ label: "File", value:
|
|
33149
|
+
...media ? [{ label: "File", value: mediaKindValue(media.type) }] : [],
|
|
33076
33150
|
...unpack ? [{ label: "Unpack", value: { text: "Yes" } }] : [],
|
|
33077
33151
|
...media?.size !== void 0 && Number.isSafeInteger(media.size) && media.size > 0 ? [sizeFact(media.size)] : []
|
|
33078
33152
|
];
|
|
@@ -33221,7 +33295,7 @@ var telegramFileSave = createFileSave();
|
|
|
33221
33295
|
|
|
33222
33296
|
// src/core/file/send/tool.ts
|
|
33223
33297
|
import { realpath as realpath6 } from "node:fs/promises";
|
|
33224
|
-
import { join as join10, resolve as
|
|
33298
|
+
import { join as join10, resolve as resolve4 } from "node:path";
|
|
33225
33299
|
|
|
33226
33300
|
// src/core/telegram/action-checks.ts
|
|
33227
33301
|
var LINK_PREVIEW = "webpage";
|
|
@@ -33303,14 +33377,14 @@ function storedReactions(json2) {
|
|
|
33303
33377
|
function ownReaction(reactions) {
|
|
33304
33378
|
return reactions.find((reaction2) => reaction2.mine)?.emoji;
|
|
33305
33379
|
}
|
|
33306
|
-
function checkEditable({ kind, body, captioned },
|
|
33380
|
+
function checkEditable({ kind, body, captioned }, text2) {
|
|
33307
33381
|
if (kind === "service" || body === null && !captioned) {
|
|
33308
33382
|
throw new ToolError("invalid_argument", "This message has no text or caption to edit; nothing was edited.");
|
|
33309
33383
|
}
|
|
33310
|
-
if (body ===
|
|
33384
|
+
if (body === text2) {
|
|
33311
33385
|
throw new ToolError("invalid_argument", "The text is the same as the message's; nothing to edit.");
|
|
33312
33386
|
}
|
|
33313
|
-
if (captioned &&
|
|
33387
|
+
if (captioned && text2.length > CAPTION_MAX_UNITS) {
|
|
33314
33388
|
throw new ToolError(
|
|
33315
33389
|
"invalid_argument",
|
|
33316
33390
|
`A caption must be at most ${CAPTION_MAX_UNITS} characters; nothing was edited.`
|
|
@@ -33319,8 +33393,8 @@ function checkEditable({ kind, body, captioned }, text) {
|
|
|
33319
33393
|
}
|
|
33320
33394
|
|
|
33321
33395
|
// src/core/message/arguments.ts
|
|
33322
|
-
function checkedText(
|
|
33323
|
-
const trimmed =
|
|
33396
|
+
function checkedText(text2) {
|
|
33397
|
+
const trimmed = text2.trim();
|
|
33324
33398
|
if (trimmed === "") throw new ToolError("invalid_argument", "text is blank; give the text to send.");
|
|
33325
33399
|
if (trimmed.length > TEXT_MAX_UNITS) {
|
|
33326
33400
|
throw new ToolError(
|
|
@@ -33378,8 +33452,8 @@ var Window = class {
|
|
|
33378
33452
|
get tail() {
|
|
33379
33453
|
return this.#tail;
|
|
33380
33454
|
}
|
|
33381
|
-
sees(
|
|
33382
|
-
const all = this.#tail +
|
|
33455
|
+
sees(text2) {
|
|
33456
|
+
const all = this.#tail + text2;
|
|
33383
33457
|
this.#tail = all.slice(-TAIL_LENGTH);
|
|
33384
33458
|
return MARKER.test(all);
|
|
33385
33459
|
}
|
|
@@ -33389,13 +33463,13 @@ var PrivateKeyScan = class {
|
|
|
33389
33463
|
#withoutNuls;
|
|
33390
33464
|
/** Feeds the next chunk; whether a marker starts anywhere in the bytes so far. */
|
|
33391
33465
|
sees(chunk) {
|
|
33392
|
-
const
|
|
33466
|
+
const text2 = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength).toString("latin1");
|
|
33393
33467
|
const before = this.#plain.tail;
|
|
33394
|
-
const plain2 = this.#plain.sees(
|
|
33395
|
-
if (this.#withoutNuls === void 0 &&
|
|
33468
|
+
const plain2 = this.#plain.sees(text2);
|
|
33469
|
+
if (this.#withoutNuls === void 0 && text2.includes(NUL)) {
|
|
33396
33470
|
this.#withoutNuls = new Window(before);
|
|
33397
33471
|
}
|
|
33398
|
-
const stripped = this.#withoutNuls?.sees(
|
|
33472
|
+
const stripped = this.#withoutNuls?.sees(text2.replaceAll(NUL, "")) ?? false;
|
|
33399
33473
|
return plain2 || stripped;
|
|
33400
33474
|
}
|
|
33401
33475
|
};
|
|
@@ -33587,9 +33661,8 @@ async function checkArchive(path, format, limits, signal) {
|
|
|
33587
33661
|
}
|
|
33588
33662
|
|
|
33589
33663
|
// src/core/outgoing/limits.ts
|
|
33590
|
-
var BYTES_PER_MB2 = 1024 * 1024;
|
|
33591
33664
|
var MAX_FILES = 10;
|
|
33592
|
-
var MAX_TOTAL_BYTES = 100 *
|
|
33665
|
+
var MAX_TOTAL_BYTES = 100 * BYTES_PER_MB;
|
|
33593
33666
|
|
|
33594
33667
|
// src/core/file/send/constants.ts
|
|
33595
33668
|
var SEND_FILES_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -33712,7 +33785,7 @@ async function hashResolved({ shown, resolved }, budget, signal) {
|
|
|
33712
33785
|
}
|
|
33713
33786
|
|
|
33714
33787
|
// src/core/file/send/resolve-files.ts
|
|
33715
|
-
import { homedir as
|
|
33788
|
+
import { homedir as homedir3 } from "node:os";
|
|
33716
33789
|
|
|
33717
33790
|
// src/core/outgoing/roots.ts
|
|
33718
33791
|
import { realpath as realpath4 } from "node:fs/promises";
|
|
@@ -33750,7 +33823,7 @@ async function allowedRoots({ cwd, sendDirs, home, forbidden }) {
|
|
|
33750
33823
|
|
|
33751
33824
|
// src/core/outgoing/resolve.ts
|
|
33752
33825
|
import { lstat as lstat6, realpath as realpath5 } from "node:fs/promises";
|
|
33753
|
-
import { basename as basename2, resolve as
|
|
33826
|
+
import { basename as basename2, resolve as resolve3, sep as sep4 } from "node:path";
|
|
33754
33827
|
var UNRESOLVABLE = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR", "ELOOP"]);
|
|
33755
33828
|
var UNREADABLE = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
|
|
33756
33829
|
async function realPathOf(path, shown) {
|
|
@@ -33765,7 +33838,7 @@ async function realPathOf(path, shown) {
|
|
|
33765
33838
|
}
|
|
33766
33839
|
async function resolveOutgoing(path, { cwd, roots, forbidden, home }) {
|
|
33767
33840
|
const shown = JSON.stringify(path);
|
|
33768
|
-
const real = await realPathOf(
|
|
33841
|
+
const real = await realPathOf(resolve3(cwd, path), shown);
|
|
33769
33842
|
const stats = await lstat6(real, { bigint: true });
|
|
33770
33843
|
if (!stats.isFile()) throw new ToolError("invalid_argument", `${shown} is not a regular file.`);
|
|
33771
33844
|
if (stats.nlink > 1n) throw hardLinked(shown);
|
|
@@ -33797,7 +33870,7 @@ async function resolveOutgoing(path, { cwd, roots, forbidden, home }) {
|
|
|
33797
33870
|
var FALLBACK_KIND = "file";
|
|
33798
33871
|
async function resolveFiles(files, ctx) {
|
|
33799
33872
|
const forbidden = [ctx.stateDir, ctx.ownDir].filter((directory) => directory !== void 0);
|
|
33800
|
-
const home =
|
|
33873
|
+
const home = homedir3();
|
|
33801
33874
|
const roots = await allowedRoots({ cwd: ctx.cwd, sendDirs: ctx.sendDirs ?? [], home, forbidden });
|
|
33802
33875
|
const seen = /* @__PURE__ */ new Set();
|
|
33803
33876
|
const resolvedFiles = [];
|
|
@@ -34010,12 +34083,12 @@ var DUPLICATE_NOTE = "An earlier delivery of this same call had already gone out
|
|
|
34010
34083
|
var DUPLICATE_UNKNOWN_ID_NOTE = `${DUPLICATE_NOTE} Its id is not known yet; \`telegram_chat_read\` shows it once the service receives it.`;
|
|
34011
34084
|
|
|
34012
34085
|
// src/core/message/uncertain.ts
|
|
34013
|
-
function sentLike(paths, chat,
|
|
34086
|
+
function sentLike(paths, chat, text2, startedAt) {
|
|
34014
34087
|
const rows = readMirror(
|
|
34015
34088
|
paths,
|
|
34016
34089
|
(mirror) => mirror.prepare(
|
|
34017
34090
|
"SELECT id, ts FROM messages WHERE chat = ? AND from_me = 1 AND body = ? AND ts >= ? ORDER BY ts DESC, id DESC LIMIT ?"
|
|
34018
|
-
).all(chat,
|
|
34091
|
+
).all(chat, text2, startedAt - SENT_LOOKBACK_MS, MAX_SENT_LIKE)
|
|
34019
34092
|
);
|
|
34020
34093
|
return rows.map(({ id, ts }) => ({ id, time: formatLocalTime(ts) }));
|
|
34021
34094
|
}
|
|
@@ -34035,8 +34108,8 @@ function withFound(error62, find, describe3) {
|
|
|
34035
34108
|
details: { ...error62.details, sent_like_this: found }
|
|
34036
34109
|
});
|
|
34037
34110
|
}
|
|
34038
|
-
function withSentLike(error62, paths, chat,
|
|
34039
|
-
return withFound(error62, () => sentLike(paths, chat,
|
|
34111
|
+
function withSentLike(error62, paths, chat, text2, startedAt) {
|
|
34112
|
+
return withFound(error62, () => sentLike(paths, chat, text2, startedAt), sentence);
|
|
34040
34113
|
}
|
|
34041
34114
|
|
|
34042
34115
|
// src/core/file/send/uncertain.ts
|
|
@@ -34067,7 +34140,7 @@ function cannotBeSent(shown, refusal) {
|
|
|
34067
34140
|
return new ToolError("forbidden", `${shown} cannot be sent: ${why}.`, { cause: refusal });
|
|
34068
34141
|
}
|
|
34069
34142
|
async function fileTarget(path, cwd) {
|
|
34070
|
-
const absolute =
|
|
34143
|
+
const absolute = resolve4(cwd, path);
|
|
34071
34144
|
return realpath6(absolute).catch(() => absolute);
|
|
34072
34145
|
}
|
|
34073
34146
|
async function stageAll(files, folder, budget, signal) {
|
|
@@ -34164,39 +34237,46 @@ var telegramFileSend = createFileSend();
|
|
|
34164
34237
|
// src/core/message/action-describe.ts
|
|
34165
34238
|
var EDIT_HEADLINES = {
|
|
34166
34239
|
named: "About to edit message {id} in {chat}",
|
|
34167
|
-
saved: "About to edit message {id} in Saved Messages"
|
|
34240
|
+
saved: "About to edit message {id} in Saved Messages",
|
|
34241
|
+
bare: "About to edit message {id}"
|
|
34168
34242
|
};
|
|
34169
34243
|
var DELETE_HEADLINES = {
|
|
34170
|
-
named: "About to delete message {id} from {chat}",
|
|
34171
|
-
saved: "About to delete message {id} from Saved Messages"
|
|
34244
|
+
named: "About to delete message {id} from {chat} for everyone",
|
|
34245
|
+
saved: "About to delete message {id} from Saved Messages",
|
|
34246
|
+
bare: "About to delete message {id} for everyone"
|
|
34172
34247
|
};
|
|
34173
34248
|
var REACT_HEADLINES = {
|
|
34174
34249
|
named: "About to react {emoji} to message {id} in {chat}",
|
|
34175
|
-
saved: "About to react {emoji} to message {id} in Saved Messages"
|
|
34250
|
+
saved: "About to react {emoji} to message {id} in Saved Messages",
|
|
34251
|
+
bare: "About to react {emoji} to message {id}"
|
|
34176
34252
|
};
|
|
34177
34253
|
var UNREACT_HEADLINES = {
|
|
34178
34254
|
named: "About to remove your reaction from message {id} in {chat}",
|
|
34179
|
-
saved: "About to remove your reaction from message {id} in Saved Messages"
|
|
34255
|
+
saved: "About to remove your reaction from message {id} in Saved Messages",
|
|
34256
|
+
bare: "About to remove your reaction from message {id}"
|
|
34180
34257
|
};
|
|
34181
34258
|
var PIN_HEADLINES = {
|
|
34182
34259
|
named: "About to pin message {id} in {chat}",
|
|
34183
|
-
saved: "About to pin message {id} in Saved Messages"
|
|
34260
|
+
saved: "About to pin message {id} in Saved Messages",
|
|
34261
|
+
bare: "About to pin message {id}"
|
|
34184
34262
|
};
|
|
34185
34263
|
var UNPIN_HEADLINES = {
|
|
34186
34264
|
named: "About to unpin message {id} in {chat}",
|
|
34187
|
-
saved: "About to unpin message {id} in Saved Messages"
|
|
34265
|
+
saved: "About to unpin message {id} in Saved Messages",
|
|
34266
|
+
bare: "About to unpin message {id}"
|
|
34188
34267
|
};
|
|
34189
34268
|
var MARK_READ_HEADLINES = {
|
|
34190
34269
|
named: "About to mark {chat} read up to message {id}",
|
|
34191
|
-
saved: "About to mark Saved Messages read up to message {id}"
|
|
34270
|
+
saved: "About to mark Saved Messages read up to message {id}",
|
|
34271
|
+
bare: "About to mark messages read up to message {id}"
|
|
34192
34272
|
};
|
|
34193
34273
|
function actionHeadline(headlines, { kind, name }, id, values) {
|
|
34194
34274
|
if (kind === "self") return { text: headlines.saved, values: { id: String(id), ...values } };
|
|
34195
|
-
return name === null ?
|
|
34275
|
+
return name === null ? { text: headlines.bare, values: { id: String(id), ...values } } : { text: headlines.named, values: { id: String(id), chat: name, ...values } };
|
|
34196
34276
|
}
|
|
34197
34277
|
function currentFacts({ body, media }) {
|
|
34198
|
-
|
|
34199
|
-
return
|
|
34278
|
+
if (body) return [{ label: "Current", value: cut(body, MAX_VALUE_LENGTH) }];
|
|
34279
|
+
return media ? [{ label: "Media", value: mediaKindValue(media.type) }] : [];
|
|
34200
34280
|
}
|
|
34201
34281
|
function describeAction(headlines, chat, id, message, extras = {}) {
|
|
34202
34282
|
const headline = actionHeadline(headlines, chat, id, extras.values ?? {});
|
|
@@ -34432,7 +34512,7 @@ var telegramMessageDelete = defineTool({
|
|
|
34432
34512
|
"A result means Telegram deleted the message for everyone. `already` means it was gone before this call.",
|
|
34433
34513
|
"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."
|
|
34434
34514
|
].join(" "),
|
|
34435
|
-
intent: "About to delete a message",
|
|
34515
|
+
intent: "About to delete a message for everyone",
|
|
34436
34516
|
toolset: "actions",
|
|
34437
34517
|
class: "administrative",
|
|
34438
34518
|
input: deleteInput,
|
|
@@ -34464,10 +34544,10 @@ var telegramMessageDelete = defineTool({
|
|
|
34464
34544
|
});
|
|
34465
34545
|
|
|
34466
34546
|
// src/core/message/edit-prepare.ts
|
|
34467
|
-
function prepareEdit(mirror, chatId, id,
|
|
34547
|
+
function prepareEdit(mirror, chatId, id, text2) {
|
|
34468
34548
|
const { chat, message } = findOwnMessage(mirror, chatId, id, "edit");
|
|
34469
34549
|
if (!message) throw deletedMessage();
|
|
34470
|
-
checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) },
|
|
34550
|
+
checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) }, text2);
|
|
34471
34551
|
return { chat, message };
|
|
34472
34552
|
}
|
|
34473
34553
|
|
|
@@ -34490,22 +34570,22 @@ var telegramMessageEdit = defineTool({
|
|
|
34490
34570
|
input: editInput,
|
|
34491
34571
|
output: editOutput,
|
|
34492
34572
|
async describe(args, ctx) {
|
|
34493
|
-
const
|
|
34573
|
+
const text2 = checkedText(args.text);
|
|
34494
34574
|
const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
|
|
34495
34575
|
const paths = await pickPaths(ctx, args.account);
|
|
34496
|
-
const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id,
|
|
34576
|
+
const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text2));
|
|
34497
34577
|
return {
|
|
34498
34578
|
...describeAction(EDIT_HEADLINES, target.chat, args.id, target.message),
|
|
34499
|
-
text: { label: "New text", body:
|
|
34579
|
+
text: { label: "New text", body: text2 }
|
|
34500
34580
|
};
|
|
34501
34581
|
},
|
|
34502
34582
|
targets: (args, ctx) => actionTargets(MESSAGE_EDIT_TOOL_ID, args, ctx),
|
|
34503
34583
|
async execute(args, ctx) {
|
|
34504
34584
|
const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
|
|
34505
|
-
const
|
|
34585
|
+
const text2 = checkedText(args.text);
|
|
34506
34586
|
const paths = await pickPaths(ctx, args.account);
|
|
34507
|
-
readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id,
|
|
34508
|
-
const params = { chat, id: args.id, text };
|
|
34587
|
+
readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text2));
|
|
34588
|
+
const params = { chat, id: args.id, text: text2 };
|
|
34509
34589
|
const edited = await callService(paths.socket, SERVICE_REQUESTS.edit, params, {
|
|
34510
34590
|
effect: "write",
|
|
34511
34591
|
signal: ctx.signal,
|
|
@@ -34701,7 +34781,7 @@ var telegramMessageSend = defineTool({
|
|
|
34701
34781
|
input: input5,
|
|
34702
34782
|
output: output5,
|
|
34703
34783
|
async describe(args, ctx) {
|
|
34704
|
-
const
|
|
34784
|
+
const text2 = checkedText(args.text);
|
|
34705
34785
|
const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
|
|
34706
34786
|
const paths = await pickPaths(ctx, args.account);
|
|
34707
34787
|
const { row, title } = readMirror(paths, (mirror) => {
|
|
@@ -34713,17 +34793,17 @@ var telegramMessageSend = defineTool({
|
|
|
34713
34793
|
headline: { text: "About to send a message to {chat}", values: { chat: row.name } }
|
|
34714
34794
|
},
|
|
34715
34795
|
facts: [chatFact(row.kind), ...topicFacts(args.topic, title), ...replyFacts(args.reply_to)],
|
|
34716
|
-
text: { label: "Message text", body:
|
|
34796
|
+
text: { label: "Message text", body: text2 }
|
|
34717
34797
|
};
|
|
34718
34798
|
},
|
|
34719
34799
|
targets: (args, ctx) => chatTargets(MESSAGE_SEND_TOOL_ID, args, ctx),
|
|
34720
34800
|
async execute(args, ctx) {
|
|
34721
34801
|
const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
|
|
34722
|
-
const
|
|
34802
|
+
const text2 = checkedText(args.text);
|
|
34723
34803
|
const paths = await pickPaths(ctx, args.account);
|
|
34724
34804
|
const params = {
|
|
34725
34805
|
chat,
|
|
34726
|
-
text,
|
|
34806
|
+
text: text2,
|
|
34727
34807
|
...args.topic !== void 0 && { topic: args.topic },
|
|
34728
34808
|
...args.reply_to !== void 0 && { reply_to: args.reply_to }
|
|
34729
34809
|
};
|
|
@@ -34736,7 +34816,7 @@ var telegramMessageSend = defineTool({
|
|
|
34736
34816
|
});
|
|
34737
34817
|
return sendResult(chat, sent);
|
|
34738
34818
|
} catch (error62) {
|
|
34739
|
-
throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat,
|
|
34819
|
+
throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat, text2, startedAt) : error62;
|
|
34740
34820
|
}
|
|
34741
34821
|
}
|
|
34742
34822
|
});
|
|
@@ -35562,7 +35642,7 @@ var Protocol = class {
|
|
|
35562
35642
|
return;
|
|
35563
35643
|
}
|
|
35564
35644
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
35565
|
-
await new Promise((
|
|
35645
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
35566
35646
|
options?.signal?.throwIfAborted();
|
|
35567
35647
|
}
|
|
35568
35648
|
} catch (error62) {
|
|
@@ -35579,7 +35659,7 @@ var Protocol = class {
|
|
|
35579
35659
|
*/
|
|
35580
35660
|
request(request, resultSchema, options) {
|
|
35581
35661
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
35582
|
-
return new Promise((
|
|
35662
|
+
return new Promise((resolve5, reject) => {
|
|
35583
35663
|
const earlyReject = (error62) => {
|
|
35584
35664
|
reject(error62);
|
|
35585
35665
|
};
|
|
@@ -35657,7 +35737,7 @@ var Protocol = class {
|
|
|
35657
35737
|
if (!parseResult.success) {
|
|
35658
35738
|
reject(parseResult.error);
|
|
35659
35739
|
} else {
|
|
35660
|
-
|
|
35740
|
+
resolve5(parseResult.data);
|
|
35661
35741
|
}
|
|
35662
35742
|
} catch (error62) {
|
|
35663
35743
|
reject(error62);
|
|
@@ -35919,12 +35999,12 @@ var Protocol = class {
|
|
|
35919
35999
|
}
|
|
35920
36000
|
} catch {
|
|
35921
36001
|
}
|
|
35922
|
-
return new Promise((
|
|
36002
|
+
return new Promise((resolve5, reject) => {
|
|
35923
36003
|
if (signal.aborted) {
|
|
35924
36004
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
35925
36005
|
return;
|
|
35926
36006
|
}
|
|
35927
|
-
const timeoutId = setTimeout(
|
|
36007
|
+
const timeoutId = setTimeout(resolve5, interval);
|
|
35928
36008
|
signal.addEventListener("abort", () => {
|
|
35929
36009
|
clearTimeout(timeoutId);
|
|
35930
36010
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -36740,23 +36820,52 @@ function elicitationConfirm(server, signal) {
|
|
|
36740
36820
|
|
|
36741
36821
|
// src/mcp/roots.ts
|
|
36742
36822
|
import { statSync as statSync2 } from "node:fs";
|
|
36823
|
+
import { isAbsolute as isAbsolute7 } from "node:path";
|
|
36743
36824
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
36744
36825
|
var FILE_URI_PROTOCOL = "file:";
|
|
36826
|
+
var SANDBOX_STATE_META = "codex/sandbox-state-meta";
|
|
36827
|
+
var TURN_METADATA = "x-codex-turn-metadata";
|
|
36828
|
+
function existingDirectory(dir) {
|
|
36829
|
+
try {
|
|
36830
|
+
return statSync2(dir, { throwIfNoEntry: false })?.isDirectory() ? dir : void 0;
|
|
36831
|
+
} catch {
|
|
36832
|
+
return void 0;
|
|
36833
|
+
}
|
|
36834
|
+
}
|
|
36745
36835
|
function localDirectory(uri) {
|
|
36746
36836
|
try {
|
|
36747
36837
|
const url2 = new URL(uri);
|
|
36748
|
-
|
|
36749
|
-
const dir = fileURLToPath2(url2);
|
|
36750
|
-
return statSync2(dir, { throwIfNoEntry: false })?.isDirectory() ? dir : void 0;
|
|
36838
|
+
return url2.protocol === FILE_URI_PROTOCOL ? existingDirectory(fileURLToPath2(url2)) : void 0;
|
|
36751
36839
|
} catch {
|
|
36752
36840
|
return void 0;
|
|
36753
36841
|
}
|
|
36754
36842
|
}
|
|
36843
|
+
function isRecord2(value) {
|
|
36844
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36845
|
+
}
|
|
36846
|
+
async function usableDirectory(candidate, ownDir, allowPath = false) {
|
|
36847
|
+
if (typeof candidate !== "string") return void 0;
|
|
36848
|
+
const dir = allowPath && isAbsolute7(candidate) ? existingDirectory(candidate) : localDirectory(candidate);
|
|
36849
|
+
if (dir === void 0 || ownDir !== void 0 && await isWithin(dir, ownDir)) return void 0;
|
|
36850
|
+
return dir;
|
|
36851
|
+
}
|
|
36852
|
+
async function callDirectory(meta3, ownDir) {
|
|
36853
|
+
if (!isRecord2(meta3)) return void 0;
|
|
36854
|
+
const sandbox = meta3[SANDBOX_STATE_META];
|
|
36855
|
+
if (isRecord2(sandbox)) {
|
|
36856
|
+
const dir = await usableDirectory(sandbox.sandboxCwd, ownDir, true);
|
|
36857
|
+
if (dir !== void 0) return dir;
|
|
36858
|
+
}
|
|
36859
|
+
const turn = meta3[TURN_METADATA];
|
|
36860
|
+
if (!isRecord2(turn) || !isRecord2(turn.workspaces)) return void 0;
|
|
36861
|
+
const workspaces = Object.keys(turn.workspaces);
|
|
36862
|
+
return workspaces.length === 1 ? usableDirectory(workspaces[0], ownDir, true) : void 0;
|
|
36863
|
+
}
|
|
36755
36864
|
async function firstUsableRoot(server, ownDir, signal) {
|
|
36756
36865
|
const { roots } = await server.listRoots(void 0, { signal });
|
|
36757
36866
|
for (const root of roots) {
|
|
36758
|
-
const dir =
|
|
36759
|
-
if (dir !== void 0
|
|
36867
|
+
const dir = await usableDirectory(root.uri, ownDir);
|
|
36868
|
+
if (dir !== void 0) return dir;
|
|
36760
36869
|
}
|
|
36761
36870
|
return void 0;
|
|
36762
36871
|
}
|
|
@@ -36767,7 +36876,9 @@ function createWorkingDirResolver(server, fallback, ownDir) {
|
|
|
36767
36876
|
cached2 = void 0;
|
|
36768
36877
|
generation++;
|
|
36769
36878
|
});
|
|
36770
|
-
return async (signal) => {
|
|
36879
|
+
return async (signal, meta3) => {
|
|
36880
|
+
const callDir = await callDirectory(meta3, ownDir);
|
|
36881
|
+
if (callDir !== void 0) return callDir;
|
|
36771
36882
|
if (!server.getClientCapabilities()?.roots) return fallback();
|
|
36772
36883
|
if (cached2 !== void 0) return cached2;
|
|
36773
36884
|
const started = generation;
|
|
@@ -36808,7 +36919,7 @@ function createServer(specs, settings, options = {}) {
|
|
|
36808
36919
|
`));
|
|
36809
36920
|
const server = new Server(
|
|
36810
36921
|
{ name: PROJECT.name, version: options.version ?? DEFAULT_VERSION },
|
|
36811
|
-
{ capabilities: { tools: {} } }
|
|
36922
|
+
{ capabilities: { tools: {}, experimental: { [SANDBOX_STATE_META]: {} } } }
|
|
36812
36923
|
);
|
|
36813
36924
|
const workingDir = createWorkingDirResolver(server, options.cwd ?? (() => process.cwd()), options.ownDir);
|
|
36814
36925
|
const toolsets = options.toolsets ?? PROJECT_PROFILE.toolsets;
|
|
@@ -36821,13 +36932,14 @@ function createServer(specs, settings, options = {}) {
|
|
|
36821
36932
|
try {
|
|
36822
36933
|
const confirm = settings.confirm === "elicitation" ? elicitationConfirm(server, extra.signal) : void 0;
|
|
36823
36934
|
const ctx = {
|
|
36824
|
-
cwd: await workingDir(extra.signal),
|
|
36935
|
+
cwd: await workingDir(extra.signal, request.params._meta),
|
|
36825
36936
|
ownDir: options.ownDir,
|
|
36826
36937
|
stateDir: settings.state_dir,
|
|
36827
36938
|
downloadDir: settings.download_dir,
|
|
36828
36939
|
downloadMaxMb: settings.download_max_mb,
|
|
36829
36940
|
sendDirs: settings.send_dirs,
|
|
36830
36941
|
programName: PROJECT.name,
|
|
36942
|
+
options: settings.options,
|
|
36831
36943
|
signal: extra.signal,
|
|
36832
36944
|
...confirm && { confirm }
|
|
36833
36945
|
};
|
|
@@ -36853,7 +36965,7 @@ async function main() {
|
|
|
36853
36965
|
const settings = parseSettings(process.argv.slice(2), process.env);
|
|
36854
36966
|
server = createServer(ALL_TOOLS, settings, {
|
|
36855
36967
|
ownDir: packageRoot(import.meta.url),
|
|
36856
|
-
version: true ? "0.
|
|
36968
|
+
version: true ? "0.3.0" : void 0
|
|
36857
36969
|
});
|
|
36858
36970
|
} catch (error62) {
|
|
36859
36971
|
if (!isToolError(error62)) throw error62;
|