@craftsamo/telegram-tools 0.2.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/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 = resolve7.call(this, root, ref);
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 resolve7(root, ref) {
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 resolve7(baseURI, relativeURI, options) {
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: resolve7,
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((text, msg) => text + separator + msg);
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, resolve7) {
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, resolve7);
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, resolve7) : NONE;
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 ?? (resolve7 ? inst._zod.innerType : void 0);
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 = (text) => {
16612
- return text.charAt(0).toUpperCase() + text.slice(1);
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((resolve7) => {
28590
+ return new Promise((resolve5) => {
28591
28591
  const json2 = serializeMessage(message);
28592
28592
  if (this._stdout.write(json2)) {
28593
- resolve7();
28593
+ resolve5();
28594
28594
  } else {
28595
- this._stdout.once("drain", resolve7);
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((resolve7, reject) => {
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
- resolve7({
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(text, limit) {
28876
- const points = Array.from(text);
28877
- return points.length > limit ? `${points.slice(0, limit - 1).join("")}\u2026` : text;
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, join, resolve, sep as sep2 } from "node:path";
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 resolveGivenDirectory(given, home) {
28922
- const text = given.text.trim();
28923
- const expanded = text === "~" ? home : text.startsWith("~/") || text.startsWith(`~${sep2}`) ? join(home, text.slice(2)) : text;
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
- // src/entry/download-dir.ts
28931
- var DOWNLOADS_DIR = "Downloads";
28932
- function resolveDownloadDir(given, env, profile) {
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
- return given !== void 0 ? resolveGivenDirectory(given, home) : resolve2(home, DOWNLOADS_DIR, profile.name);
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
- var SERVICE_OPTION_NAMES = ["keep_disappearing", "channels"];
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}_${OPTIONS[name].envSuffix}`;
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.keys(OPTIONS).map((name) => [OPTIONS[name].flag, { name, ...OPTIONS[name] }])
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 text = value.trim().toLowerCase();
29024
- if (TRUE_VALUES.includes(text)) return true;
29025
- if (FALSE_VALUES.includes(text)) return false;
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 listedDirectories(given) {
29042
- return given === void 0 ? [] : splitList(given.text).map((text) => ({ text, source: given.source }));
29043
- }
29044
- function downloadMaxMb(value, source) {
29045
- if (typeof value !== "number" || !Number.isInteger(value) || value < 1 || value > MAX_DOWNLOAD_MB) {
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 value;
29056
+ return parsed;
29049
29057
  }
29050
- function downloadMaxMbText({ text, source }) {
29051
- const trimmed = text.trim();
29052
- return downloadMaxMb(/^\d+$/.test(trimmed) ? Number(trimmed) : Number.NaN, source);
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 downloadSettings(given, env, profile) {
29055
- const value = given ?? ((name) => envText(name, env, profile));
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 text = env[variable];
29065
- return text === void 0 || text.trim() === "" ? void 0 : { text, source: variable };
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
- state_dir: resolveStateDir(value("state_dir"), env, profile),
29077
- ...downloadSettings(value, env, profile),
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
- var TOOL_OPTION_NAMES = [
29097
- "toolsets",
29098
- "read_only",
29099
- "tools",
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(text) {
29125
- return typeof text === "string" && LABEL_PATTERN.test(text);
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)) {
@@ -29361,10 +29419,10 @@ var MILLISECOND_DIGITS = 3;
29361
29419
  var MIN_YEAR = 1e3;
29362
29420
  var MAX_HOUR = 23;
29363
29421
  var MAX_MINUTE = 59;
29364
- function badTime(text, name) {
29422
+ function badTime(text2, name) {
29365
29423
  return new ToolError(
29366
29424
  "invalid_argument",
29367
- `${name} is not a time: ${JSON.stringify(text)}. 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.`
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.`
29368
29426
  );
29369
29427
  }
29370
29428
  function isCalendarDay(year, month, day) {
@@ -29372,21 +29430,21 @@ function isCalendarDay(year, month, day) {
29372
29430
  date5.setUTCFullYear(year, month - 1, day);
29373
29431
  return date5.getUTCFullYear() === year && date5.getUTCMonth() === month - 1 && date5.getUTCDate() === day;
29374
29432
  }
29375
- function parseTimeArgument(text, name) {
29376
- const match = TIME_PATTERN.exec(text.trim());
29377
- if (!match) throw badTime(text, name);
29433
+ function parseTimeArgument(text2, name) {
29434
+ const match = TIME_PATTERN.exec(text2.trim());
29435
+ if (!match) throw badTime(text2, name);
29378
29436
  const [, year, month, day, hour = "0", minute = "0", second = "0", fraction = "", zulu, sign, offsetHour, offsetMin] = match;
29379
29437
  const [y, mon, d, h, mi, s] = [year, month, day, hour, minute, second].map(Number);
29380
29438
  const ms = Number(fraction.padEnd(MILLISECOND_DIGITS, "0").slice(0, MILLISECOND_DIGITS));
29381
29439
  if (y < MIN_YEAR || !isCalendarDay(y, mon, d) || h > MAX_HOUR || mi > MAX_MINUTE || s > MAX_MINUTE) {
29382
- throw badTime(text, name);
29440
+ throw badTime(text2, name);
29383
29441
  }
29384
29442
  if (sign === void 0 && zulu === void 0) return new Date(y, mon - 1, d, h, mi, s, ms).getTime();
29385
29443
  const wall = Date.UTC(y, mon - 1, d, h, mi, s, ms);
29386
29444
  if (zulu) return wall;
29387
29445
  const offsetH = Number(offsetHour);
29388
29446
  const offsetM = Number(offsetMin);
29389
- if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(text, name);
29447
+ if (offsetH > MAX_HOUR || offsetM > MAX_MINUTE) throw badTime(text2, name);
29390
29448
  const offset = (offsetH * MINUTES_PER_HOUR + offsetM) * MS_PER_MINUTE;
29391
29449
  return sign === "-" ? wall + offset : wall - offset;
29392
29450
  }
@@ -29605,23 +29663,23 @@ function encodeCursor(value) {
29605
29663
  function notACursor(name) {
29606
29664
  return new ToolError("invalid_argument", `${name} is not a cursor this tool returned.`);
29607
29665
  }
29608
- function decodeCursor(text, name) {
29609
- const bytes = Buffer3.from(text, "base64url");
29610
- if (bytes.toString("base64url") !== text) throw notACursor(name);
29666
+ function decodeCursor(text2, name) {
29667
+ const bytes = Buffer3.from(text2, "base64url");
29668
+ if (bytes.toString("base64url") !== text2) throw notACursor(name);
29611
29669
  try {
29612
29670
  return JSON.parse(bytes.toString("utf8"));
29613
29671
  } catch {
29614
29672
  throw notACursor(name);
29615
29673
  }
29616
29674
  }
29617
- function readCursor(text, name, schema) {
29618
- const parsed = schema.safeParse(decodeCursor(text, name));
29675
+ function readCursor(text2, name, schema) {
29676
+ const parsed = schema.safeParse(decodeCursor(text2, name));
29619
29677
  if (!parsed.success) throw notACursor(name);
29620
29678
  return parsed.data;
29621
29679
  }
29622
29680
  var HIGH_SURROGATE = /[\uD800-\uDBFF]$/;
29623
- function cutText(text, keep) {
29624
- return text.length <= keep ? text : text.slice(0, keep).replace(HIGH_SURROGATE, "");
29681
+ function cutText(text2, keep) {
29682
+ return text2.length <= keep ? text2 : text2.slice(0, keep).replace(HIGH_SURROGATE, "");
29625
29683
  }
29626
29684
  function jsonLength(value) {
29627
29685
  return JSON.stringify(value).length;
@@ -29711,15 +29769,15 @@ var ERROR_CODES = {
29711
29769
  function isErrorCode(value) {
29712
29770
  return typeof value === "string" && Object.hasOwn(ERROR_CODES, value);
29713
29771
  }
29714
- function maskPhoneNumbers(text) {
29715
- return text.replace(PHONE_NUMBER, "[number]");
29772
+ function maskPhoneNumbers(text2) {
29773
+ return text2.replace(PHONE_NUMBER, "[number]");
29716
29774
  }
29717
29775
  function cut2(message) {
29718
29776
  return maskPhoneNumbers(message).trim().slice(0, MAX_DETAIL_LENGTH);
29719
29777
  }
29720
29778
  function detail(message) {
29721
- const text = cut2(message);
29722
- return text ? `: ${text}` : "";
29779
+ const text2 = cut2(message);
29780
+ return text2 ? `: ${text2}` : "";
29723
29781
  }
29724
29782
  function afterWriteError(method, effect, reason) {
29725
29783
  return effect === "write" ? new ToolError("uncertain", `${method} may have taken effect (${reason}). ${UNCERTAIN_ADVICE}`) : new ToolError("upstream_error", `${method} failed (${reason}).`);
@@ -29897,19 +29955,19 @@ var ServiceConnection = class _ServiceConnection {
29897
29955
  socket.on("error", (error62) => {
29898
29956
  this.endReason ??= `the connection to the service broke${error62.code ? ` (${error62.code})` : ""}`;
29899
29957
  });
29900
- this.closed = new Promise((resolve7) => {
29958
+ this.closed = new Promise((resolve5) => {
29901
29959
  socket.once("close", () => {
29902
29960
  this.endReason ??= "the service closed the connection";
29903
29961
  const lost = { lost: this.endReason };
29904
29962
  for (const settle2 of [...this.pending.values()]) settle2(lost);
29905
- resolve7();
29963
+ resolve5();
29906
29964
  });
29907
29965
  });
29908
29966
  }
29909
29967
  /** Connects to the service's socket; rejects as `upstream_error` when nothing is listening there. */
29910
29968
  static connect(socketPath, options = {}) {
29911
29969
  const { timeoutMs = DEFAULT_CONNECT_TIMEOUT_MS, signal, maxLineLength = DEFAULT_MAX_LINE_LENGTH } = options;
29912
- return new Promise((resolve7, reject) => {
29970
+ return new Promise((resolve5, reject) => {
29913
29971
  if (signal?.aborted) {
29914
29972
  reject(abortError(signal));
29915
29973
  return;
@@ -29931,7 +29989,7 @@ var ServiceConnection = class _ServiceConnection {
29931
29989
  };
29932
29990
  const onConnect = () => {
29933
29991
  detach();
29934
- resolve7(new _ServiceConnection(socket, maxLineLength));
29992
+ resolve5(new _ServiceConnection(socket, maxLineLength));
29935
29993
  };
29936
29994
  const onFailure = () => stop(new ToolError("upstream_error", NOT_RUNNING_MESSAGE));
29937
29995
  const onAbort = () => stop(abortError(signal));
@@ -29954,7 +30012,7 @@ var ServiceConnection = class _ServiceConnection {
29954
30012
  */
29955
30013
  call(method, params, options) {
29956
30014
  const { effect, timeoutMs = DEFAULT_CALL_TIMEOUT_MS, signal } = options;
29957
- return new Promise((resolve7, reject) => {
30015
+ return new Promise((resolve5, reject) => {
29958
30016
  if (signal?.aborted) {
29959
30017
  reject(abortError(signal));
29960
30018
  return;
@@ -29983,7 +30041,7 @@ var ServiceConnection = class _ServiceConnection {
29983
30041
  clearTimeout(timer);
29984
30042
  signal?.removeEventListener("abort", onAbort);
29985
30043
  try {
29986
- resolve7(produce());
30044
+ resolve5(produce());
29987
30045
  } catch (error62) {
29988
30046
  reject(error62);
29989
30047
  }
@@ -30303,10 +30361,10 @@ function replyTo(parsed, related) {
30303
30361
  if (reply.chat !== void 0) entry2.chat = reply.chat;
30304
30362
  if (reply.topic !== void 0) entry2.topic = reply.topic;
30305
30363
  if (reply.quote !== void 0) entry2.quote = reply.quote;
30306
- const text = repliedText(parsed, related)?.text;
30307
- if (text !== void 0) {
30308
- entry2.text = cutText(text, REPLY_TEXT_LENGTH);
30309
- if (entry2.text.length < text.length) entry2.text_cut = true;
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;
30310
30368
  }
30311
30369
  return entry2;
30312
30370
  }
@@ -30375,25 +30433,25 @@ function texts(entry2) {
30375
30433
  ];
30376
30434
  }
30377
30435
  function messageTextLength(entry2) {
30378
- return texts(entry2).reduce((total, text) => total + text.length, 0);
30436
+ return texts(entry2).reduce((total, text2) => total + text2.length, 0);
30379
30437
  }
30380
30438
  function cutMessage(entry2, keep) {
30381
30439
  let room = keep;
30382
30440
  let cut3 = false;
30383
- const take = (text) => {
30384
- const kept = cutText(text, room);
30385
- room = Math.max(0, room - text.length);
30386
- if (kept.length < text.length) cut3 = true;
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;
30387
30445
  return kept;
30388
30446
  };
30389
30447
  const cutEntry = { ...entry2 };
30390
30448
  if (entry2.text !== void 0) cutEntry.text = take(entry2.text);
30391
30449
  if (entry2.reply_to) {
30392
- const { quote, text } = entry2.reply_to;
30450
+ const { quote, text: text2 } = entry2.reply_to;
30393
30451
  cutEntry.reply_to = {
30394
30452
  ...entry2.reply_to,
30395
30453
  ...quote === void 0 ? {} : { quote: take(quote) },
30396
- ...text === void 0 ? {} : { text: take(text) }
30454
+ ...text2 === void 0 ? {} : { text: take(text2) }
30397
30455
  };
30398
30456
  }
30399
30457
  if (entry2.earlier_versions)
@@ -30642,8 +30700,8 @@ function fetchResult(read, stored) {
30642
30700
  }
30643
30701
 
30644
30702
  // src/core/fold.ts
30645
- function foldCase(text) {
30646
- return text.normalize("NFKC").toUpperCase().toLowerCase().replace(/ς/g, "\u03C3");
30703
+ function foldCase(text2) {
30704
+ return text2.normalize("NFKC").toUpperCase().toLowerCase().replace(/ς/g, "\u03C3");
30647
30705
  }
30648
30706
 
30649
30707
  // src/core/chat/filter.ts
@@ -30782,8 +30840,8 @@ function foldedFileName(media) {
30782
30840
  return isRecord(info) && typeof info.name === "string" ? foldCase(info.name) : void 0;
30783
30841
  }
30784
30842
  function matchesAllWords(row, words2) {
30785
- const text = foldCase(row.body ?? "");
30786
- const unmatched = words2.filter((word) => !text.includes(word));
30843
+ const text2 = foldCase(row.body ?? "");
30844
+ const unmatched = words2.filter((word) => !text2.includes(word));
30787
30845
  if (unmatched.length === 0) return true;
30788
30846
  const name = row.media === null ? void 0 : foldedFileName(row.media);
30789
30847
  return name !== void 0 && unmatched.every((word) => name.includes(word));
@@ -31342,7 +31400,7 @@ async function openMessageFolder(downloadDir, folder) {
31342
31400
 
31343
31401
  // src/core/file/incoming.ts
31344
31402
  import { lstat as lstat4, realpath as realpath3 } from "node:fs/promises";
31345
- import { dirname as dirname3, isAbsolute as isAbsolute6, resolve as resolve4 } from "node:path";
31403
+ import { dirname as dirname3, isAbsolute as isAbsolute6, resolve as resolve2 } from "node:path";
31346
31404
 
31347
31405
  // src/core/file/place.ts
31348
31406
  import { createHash as createHash3, randomBytes } from "node:crypto";
@@ -31360,11 +31418,11 @@ var ANIMATED_STICKER = "an animated sticker (.tgs), which cannot be inspected";
31360
31418
  function unreadableArchive(label) {
31361
31419
  return `an archive that cannot be inspected (${label})`;
31362
31420
  }
31363
- function words(text) {
31364
- return text.split(/\s+/).filter((word) => word !== "");
31421
+ function words(text2) {
31422
+ return text2.split(/\s+/).filter((word) => word !== "");
31365
31423
  }
31366
- function ascii(text) {
31367
- return Array.from(text, (character) => character.charCodeAt(0));
31424
+ function ascii(text2) {
31425
+ return Array.from(text2, (character) => character.charCodeAt(0));
31368
31426
  }
31369
31427
  function at(offset, bytes) {
31370
31428
  return { offset, bytes };
@@ -31581,7 +31639,7 @@ function parseOctal(field) {
31581
31639
  }
31582
31640
  return digits > 0 ? value : void 0;
31583
31641
  }
31584
- function parseNumber(field) {
31642
+ function parseNumber2(field) {
31585
31643
  const first = field[0];
31586
31644
  if (first === void 0 || (first & BASE256_FLAG) === 0) return parseOctal(field);
31587
31645
  if (first === BASE256_NEGATIVE) return void 0;
@@ -31620,11 +31678,11 @@ function parseHeader(block) {
31620
31678
  path[prefix.length] = "/".charCodeAt(0);
31621
31679
  path.set(name, prefix.length + 1);
31622
31680
  }
31623
- return { path, size: parseNumber(block.subarray(SIZE_START, SIZE_END)), type: block[TYPE_OFFSET] };
31681
+ return { path, size: parseNumber2(block.subarray(SIZE_START, SIZE_END)), type: block[TYPE_OFFSET] };
31624
31682
  }
31625
- function parseDecimal(text) {
31626
- if (!/^[0-9]{1,15}$/.test(text)) return void 0;
31627
- return Number(text);
31683
+ function parseDecimal(text2) {
31684
+ if (!/^[0-9]{1,15}$/.test(text2)) return void 0;
31685
+ return Number(text2);
31628
31686
  }
31629
31687
  function parsePaxRecords(data, maxRecords = Infinity) {
31630
31688
  const records = [];
@@ -31814,8 +31872,8 @@ var EXTENSIONS = {
31814
31872
  };
31815
31873
  var KIND_PATTERN = /^[a-z]{1,16}$/;
31816
31874
  var UNKNOWN_KIND = "file";
31817
- function byteLength(text) {
31818
- return Buffer5.byteLength(text);
31875
+ function byteLength(text2) {
31876
+ return Buffer5.byteLength(text2);
31819
31877
  }
31820
31878
  function extensionOf2(type) {
31821
31879
  return type == null ? "" : EXTENSIONS[type.split(";")[0].trim().toLowerCase()] ?? "";
@@ -31983,7 +32041,7 @@ async function openDownloaded(incoming, path) {
31983
32041
  }
31984
32042
  async function discardDownload(incoming, path) {
31985
32043
  if (!isAbsolute6(path)) return;
31986
- const folder = dirname3(resolve4(path));
32044
+ const folder = dirname3(resolve2(path));
31987
32045
  if (dirname3(folder) !== incoming) return;
31988
32046
  await discard(folder).catch(() => {
31989
32047
  });
@@ -32084,8 +32142,8 @@ function fitListings(result) {
32084
32142
  var MAX_NAME_CHARACTERS = 255;
32085
32143
  var CUT_MARK = "\u2026";
32086
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;
32087
- function cleanName(text) {
32088
- const cleaned = text.normalize("NFC").replace(HIDDEN_CHARACTERS, "?");
32145
+ function cleanName(text2) {
32146
+ const cleaned = text2.normalize("NFC").replace(HIDDEN_CHARACTERS, "?");
32089
32147
  const characters = Array.from(cleaned);
32090
32148
  if (characters.length <= MAX_NAME_CHARACTERS) return cleaned;
32091
32149
  return characters.slice(0, MAX_NAME_CHARACTERS - CUT_MARK.length).join("") + CUT_MARK;
@@ -32258,9 +32316,9 @@ function decodeUtf8Lossy(bytes) {
32258
32316
  return LOSSY_UTF8.decode(bytes);
32259
32317
  }
32260
32318
  function decodeCp437(bytes) {
32261
- let text = "";
32262
- for (const byte of bytes) text += byte < ASCII_END ? String.fromCharCode(byte) : CP437_HIGH[byte - ASCII_END];
32263
- return text;
32319
+ let text2 = "";
32320
+ for (const byte of bytes) text2 += byte < ASCII_END ? String.fromCharCode(byte) : CP437_HIGH[byte - ASCII_END];
32321
+ return text2;
32264
32322
  }
32265
32323
 
32266
32324
  // src/core/archive/tar.ts
@@ -33237,7 +33295,7 @@ var telegramFileSave = createFileSave();
33237
33295
 
33238
33296
  // src/core/file/send/tool.ts
33239
33297
  import { realpath as realpath6 } from "node:fs/promises";
33240
- import { join as join10, resolve as resolve6 } from "node:path";
33298
+ import { join as join10, resolve as resolve4 } from "node:path";
33241
33299
 
33242
33300
  // src/core/telegram/action-checks.ts
33243
33301
  var LINK_PREVIEW = "webpage";
@@ -33319,14 +33377,14 @@ function storedReactions(json2) {
33319
33377
  function ownReaction(reactions) {
33320
33378
  return reactions.find((reaction2) => reaction2.mine)?.emoji;
33321
33379
  }
33322
- function checkEditable({ kind, body, captioned }, text) {
33380
+ function checkEditable({ kind, body, captioned }, text2) {
33323
33381
  if (kind === "service" || body === null && !captioned) {
33324
33382
  throw new ToolError("invalid_argument", "This message has no text or caption to edit; nothing was edited.");
33325
33383
  }
33326
- if (body === text) {
33384
+ if (body === text2) {
33327
33385
  throw new ToolError("invalid_argument", "The text is the same as the message's; nothing to edit.");
33328
33386
  }
33329
- if (captioned && text.length > CAPTION_MAX_UNITS) {
33387
+ if (captioned && text2.length > CAPTION_MAX_UNITS) {
33330
33388
  throw new ToolError(
33331
33389
  "invalid_argument",
33332
33390
  `A caption must be at most ${CAPTION_MAX_UNITS} characters; nothing was edited.`
@@ -33335,8 +33393,8 @@ function checkEditable({ kind, body, captioned }, text) {
33335
33393
  }
33336
33394
 
33337
33395
  // src/core/message/arguments.ts
33338
- function checkedText(text) {
33339
- const trimmed = text.trim();
33396
+ function checkedText(text2) {
33397
+ const trimmed = text2.trim();
33340
33398
  if (trimmed === "") throw new ToolError("invalid_argument", "text is blank; give the text to send.");
33341
33399
  if (trimmed.length > TEXT_MAX_UNITS) {
33342
33400
  throw new ToolError(
@@ -33394,8 +33452,8 @@ var Window = class {
33394
33452
  get tail() {
33395
33453
  return this.#tail;
33396
33454
  }
33397
- sees(text) {
33398
- const all = this.#tail + text;
33455
+ sees(text2) {
33456
+ const all = this.#tail + text2;
33399
33457
  this.#tail = all.slice(-TAIL_LENGTH);
33400
33458
  return MARKER.test(all);
33401
33459
  }
@@ -33405,13 +33463,13 @@ var PrivateKeyScan = class {
33405
33463
  #withoutNuls;
33406
33464
  /** Feeds the next chunk; whether a marker starts anywhere in the bytes so far. */
33407
33465
  sees(chunk) {
33408
- const text = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength).toString("latin1");
33466
+ const text2 = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength).toString("latin1");
33409
33467
  const before = this.#plain.tail;
33410
- const plain2 = this.#plain.sees(text);
33411
- if (this.#withoutNuls === void 0 && text.includes(NUL)) {
33468
+ const plain2 = this.#plain.sees(text2);
33469
+ if (this.#withoutNuls === void 0 && text2.includes(NUL)) {
33412
33470
  this.#withoutNuls = new Window(before);
33413
33471
  }
33414
- const stripped = this.#withoutNuls?.sees(text.replaceAll(NUL, "")) ?? false;
33472
+ const stripped = this.#withoutNuls?.sees(text2.replaceAll(NUL, "")) ?? false;
33415
33473
  return plain2 || stripped;
33416
33474
  }
33417
33475
  };
@@ -33727,7 +33785,7 @@ async function hashResolved({ shown, resolved }, budget, signal) {
33727
33785
  }
33728
33786
 
33729
33787
  // src/core/file/send/resolve-files.ts
33730
- import { homedir as homedir2 } from "node:os";
33788
+ import { homedir as homedir3 } from "node:os";
33731
33789
 
33732
33790
  // src/core/outgoing/roots.ts
33733
33791
  import { realpath as realpath4 } from "node:fs/promises";
@@ -33765,7 +33823,7 @@ async function allowedRoots({ cwd, sendDirs, home, forbidden }) {
33765
33823
 
33766
33824
  // src/core/outgoing/resolve.ts
33767
33825
  import { lstat as lstat6, realpath as realpath5 } from "node:fs/promises";
33768
- import { basename as basename2, resolve as resolve5, sep as sep4 } from "node:path";
33826
+ import { basename as basename2, resolve as resolve3, sep as sep4 } from "node:path";
33769
33827
  var UNRESOLVABLE = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR", "ELOOP"]);
33770
33828
  var UNREADABLE = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
33771
33829
  async function realPathOf(path, shown) {
@@ -33780,7 +33838,7 @@ async function realPathOf(path, shown) {
33780
33838
  }
33781
33839
  async function resolveOutgoing(path, { cwd, roots, forbidden, home }) {
33782
33840
  const shown = JSON.stringify(path);
33783
- const real = await realPathOf(resolve5(cwd, path), shown);
33841
+ const real = await realPathOf(resolve3(cwd, path), shown);
33784
33842
  const stats = await lstat6(real, { bigint: true });
33785
33843
  if (!stats.isFile()) throw new ToolError("invalid_argument", `${shown} is not a regular file.`);
33786
33844
  if (stats.nlink > 1n) throw hardLinked(shown);
@@ -33812,7 +33870,7 @@ async function resolveOutgoing(path, { cwd, roots, forbidden, home }) {
33812
33870
  var FALLBACK_KIND = "file";
33813
33871
  async function resolveFiles(files, ctx) {
33814
33872
  const forbidden = [ctx.stateDir, ctx.ownDir].filter((directory) => directory !== void 0);
33815
- const home = homedir2();
33873
+ const home = homedir3();
33816
33874
  const roots = await allowedRoots({ cwd: ctx.cwd, sendDirs: ctx.sendDirs ?? [], home, forbidden });
33817
33875
  const seen = /* @__PURE__ */ new Set();
33818
33876
  const resolvedFiles = [];
@@ -34025,12 +34083,12 @@ var DUPLICATE_NOTE = "An earlier delivery of this same call had already gone out
34025
34083
  var DUPLICATE_UNKNOWN_ID_NOTE = `${DUPLICATE_NOTE} Its id is not known yet; \`telegram_chat_read\` shows it once the service receives it.`;
34026
34084
 
34027
34085
  // src/core/message/uncertain.ts
34028
- function sentLike(paths, chat, text, startedAt) {
34086
+ function sentLike(paths, chat, text2, startedAt) {
34029
34087
  const rows = readMirror(
34030
34088
  paths,
34031
34089
  (mirror) => mirror.prepare(
34032
34090
  "SELECT id, ts FROM messages WHERE chat = ? AND from_me = 1 AND body = ? AND ts >= ? ORDER BY ts DESC, id DESC LIMIT ?"
34033
- ).all(chat, text, startedAt - SENT_LOOKBACK_MS, MAX_SENT_LIKE)
34091
+ ).all(chat, text2, startedAt - SENT_LOOKBACK_MS, MAX_SENT_LIKE)
34034
34092
  );
34035
34093
  return rows.map(({ id, ts }) => ({ id, time: formatLocalTime(ts) }));
34036
34094
  }
@@ -34050,8 +34108,8 @@ function withFound(error62, find, describe3) {
34050
34108
  details: { ...error62.details, sent_like_this: found }
34051
34109
  });
34052
34110
  }
34053
- function withSentLike(error62, paths, chat, text, startedAt) {
34054
- return withFound(error62, () => sentLike(paths, chat, text, startedAt), sentence);
34111
+ function withSentLike(error62, paths, chat, text2, startedAt) {
34112
+ return withFound(error62, () => sentLike(paths, chat, text2, startedAt), sentence);
34055
34113
  }
34056
34114
 
34057
34115
  // src/core/file/send/uncertain.ts
@@ -34082,7 +34140,7 @@ function cannotBeSent(shown, refusal) {
34082
34140
  return new ToolError("forbidden", `${shown} cannot be sent: ${why}.`, { cause: refusal });
34083
34141
  }
34084
34142
  async function fileTarget(path, cwd) {
34085
- const absolute = resolve6(cwd, path);
34143
+ const absolute = resolve4(cwd, path);
34086
34144
  return realpath6(absolute).catch(() => absolute);
34087
34145
  }
34088
34146
  async function stageAll(files, folder, budget, signal) {
@@ -34486,10 +34544,10 @@ var telegramMessageDelete = defineTool({
34486
34544
  });
34487
34545
 
34488
34546
  // src/core/message/edit-prepare.ts
34489
- function prepareEdit(mirror, chatId, id, text) {
34547
+ function prepareEdit(mirror, chatId, id, text2) {
34490
34548
  const { chat, message } = findOwnMessage(mirror, chatId, id, "edit");
34491
34549
  if (!message) throw deletedMessage();
34492
- checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) }, text);
34550
+ checkEditable({ ...message, captioned: message.media !== null && takesCaption(message.media.type) }, text2);
34493
34551
  return { chat, message };
34494
34552
  }
34495
34553
 
@@ -34512,22 +34570,22 @@ var telegramMessageEdit = defineTool({
34512
34570
  input: editInput,
34513
34571
  output: editOutput,
34514
34572
  async describe(args, ctx) {
34515
- const text = checkedText(args.text);
34573
+ const text2 = checkedText(args.text);
34516
34574
  const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
34517
34575
  const paths = await pickPaths(ctx, args.account);
34518
- const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text));
34576
+ const target = readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text2));
34519
34577
  return {
34520
34578
  ...describeAction(EDIT_HEADLINES, target.chat, args.id, target.message),
34521
- text: { label: "New text", body: text }
34579
+ text: { label: "New text", body: text2 }
34522
34580
  };
34523
34581
  },
34524
34582
  targets: (args, ctx) => actionTargets(MESSAGE_EDIT_TOOL_ID, args, ctx),
34525
34583
  async execute(args, ctx) {
34526
34584
  const chat = requireChatId(args.chat, MESSAGE_EDIT_TOOL_ID);
34527
- const text = checkedText(args.text);
34585
+ const text2 = checkedText(args.text);
34528
34586
  const paths = await pickPaths(ctx, args.account);
34529
- readMirror(paths, (mirror) => prepareEdit(mirror, chat, args.id, text));
34530
- 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 };
34531
34589
  const edited = await callService(paths.socket, SERVICE_REQUESTS.edit, params, {
34532
34590
  effect: "write",
34533
34591
  signal: ctx.signal,
@@ -34723,7 +34781,7 @@ var telegramMessageSend = defineTool({
34723
34781
  input: input5,
34724
34782
  output: output5,
34725
34783
  async describe(args, ctx) {
34726
- const text = checkedText(args.text);
34784
+ const text2 = checkedText(args.text);
34727
34785
  const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
34728
34786
  const paths = await pickPaths(ctx, args.account);
34729
34787
  const { row, title } = readMirror(paths, (mirror) => {
@@ -34735,17 +34793,17 @@ var telegramMessageSend = defineTool({
34735
34793
  headline: { text: "About to send a message to {chat}", values: { chat: row.name } }
34736
34794
  },
34737
34795
  facts: [chatFact(row.kind), ...topicFacts(args.topic, title), ...replyFacts(args.reply_to)],
34738
- text: { label: "Message text", body: text }
34796
+ text: { label: "Message text", body: text2 }
34739
34797
  };
34740
34798
  },
34741
34799
  targets: (args, ctx) => chatTargets(MESSAGE_SEND_TOOL_ID, args, ctx),
34742
34800
  async execute(args, ctx) {
34743
34801
  const chat = requireChatId(args.chat, MESSAGE_SEND_TOOL_ID);
34744
- const text = checkedText(args.text);
34802
+ const text2 = checkedText(args.text);
34745
34803
  const paths = await pickPaths(ctx, args.account);
34746
34804
  const params = {
34747
34805
  chat,
34748
- text,
34806
+ text: text2,
34749
34807
  ...args.topic !== void 0 && { topic: args.topic },
34750
34808
  ...args.reply_to !== void 0 && { reply_to: args.reply_to }
34751
34809
  };
@@ -34758,7 +34816,7 @@ var telegramMessageSend = defineTool({
34758
34816
  });
34759
34817
  return sendResult(chat, sent);
34760
34818
  } catch (error62) {
34761
- throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat, text, startedAt) : error62;
34819
+ throw isToolError(error62) && error62.code === "uncertain" ? withSentLike(error62, paths, chat, text2, startedAt) : error62;
34762
34820
  }
34763
34821
  }
34764
34822
  });
@@ -35584,7 +35642,7 @@ var Protocol = class {
35584
35642
  return;
35585
35643
  }
35586
35644
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
35587
- await new Promise((resolve7) => setTimeout(resolve7, pollInterval));
35645
+ await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
35588
35646
  options?.signal?.throwIfAborted();
35589
35647
  }
35590
35648
  } catch (error62) {
@@ -35601,7 +35659,7 @@ var Protocol = class {
35601
35659
  */
35602
35660
  request(request, resultSchema, options) {
35603
35661
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
35604
- return new Promise((resolve7, reject) => {
35662
+ return new Promise((resolve5, reject) => {
35605
35663
  const earlyReject = (error62) => {
35606
35664
  reject(error62);
35607
35665
  };
@@ -35679,7 +35737,7 @@ var Protocol = class {
35679
35737
  if (!parseResult.success) {
35680
35738
  reject(parseResult.error);
35681
35739
  } else {
35682
- resolve7(parseResult.data);
35740
+ resolve5(parseResult.data);
35683
35741
  }
35684
35742
  } catch (error62) {
35685
35743
  reject(error62);
@@ -35941,12 +35999,12 @@ var Protocol = class {
35941
35999
  }
35942
36000
  } catch {
35943
36001
  }
35944
- return new Promise((resolve7, reject) => {
36002
+ return new Promise((resolve5, reject) => {
35945
36003
  if (signal.aborted) {
35946
36004
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
35947
36005
  return;
35948
36006
  }
35949
- const timeoutId = setTimeout(resolve7, interval);
36007
+ const timeoutId = setTimeout(resolve5, interval);
35950
36008
  signal.addEventListener("abort", () => {
35951
36009
  clearTimeout(timeoutId);
35952
36010
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -36762,23 +36820,52 @@ function elicitationConfirm(server, signal) {
36762
36820
 
36763
36821
  // src/mcp/roots.ts
36764
36822
  import { statSync as statSync2 } from "node:fs";
36823
+ import { isAbsolute as isAbsolute7 } from "node:path";
36765
36824
  import { fileURLToPath as fileURLToPath2 } from "node:url";
36766
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
+ }
36767
36835
  function localDirectory(uri) {
36768
36836
  try {
36769
36837
  const url2 = new URL(uri);
36770
- if (url2.protocol !== FILE_URI_PROTOCOL) return void 0;
36771
- const dir = fileURLToPath2(url2);
36772
- return statSync2(dir, { throwIfNoEntry: false })?.isDirectory() ? dir : void 0;
36838
+ return url2.protocol === FILE_URI_PROTOCOL ? existingDirectory(fileURLToPath2(url2)) : void 0;
36773
36839
  } catch {
36774
36840
  return void 0;
36775
36841
  }
36776
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
+ }
36777
36864
  async function firstUsableRoot(server, ownDir, signal) {
36778
36865
  const { roots } = await server.listRoots(void 0, { signal });
36779
36866
  for (const root of roots) {
36780
- const dir = localDirectory(root.uri);
36781
- if (dir !== void 0 && !(ownDir !== void 0 && await isWithin(dir, ownDir))) return dir;
36867
+ const dir = await usableDirectory(root.uri, ownDir);
36868
+ if (dir !== void 0) return dir;
36782
36869
  }
36783
36870
  return void 0;
36784
36871
  }
@@ -36789,7 +36876,9 @@ function createWorkingDirResolver(server, fallback, ownDir) {
36789
36876
  cached2 = void 0;
36790
36877
  generation++;
36791
36878
  });
36792
- return async (signal) => {
36879
+ return async (signal, meta3) => {
36880
+ const callDir = await callDirectory(meta3, ownDir);
36881
+ if (callDir !== void 0) return callDir;
36793
36882
  if (!server.getClientCapabilities()?.roots) return fallback();
36794
36883
  if (cached2 !== void 0) return cached2;
36795
36884
  const started = generation;
@@ -36830,7 +36919,7 @@ function createServer(specs, settings, options = {}) {
36830
36919
  `));
36831
36920
  const server = new Server(
36832
36921
  { name: PROJECT.name, version: options.version ?? DEFAULT_VERSION },
36833
- { capabilities: { tools: {} } }
36922
+ { capabilities: { tools: {}, experimental: { [SANDBOX_STATE_META]: {} } } }
36834
36923
  );
36835
36924
  const workingDir = createWorkingDirResolver(server, options.cwd ?? (() => process.cwd()), options.ownDir);
36836
36925
  const toolsets = options.toolsets ?? PROJECT_PROFILE.toolsets;
@@ -36843,13 +36932,14 @@ function createServer(specs, settings, options = {}) {
36843
36932
  try {
36844
36933
  const confirm = settings.confirm === "elicitation" ? elicitationConfirm(server, extra.signal) : void 0;
36845
36934
  const ctx = {
36846
- cwd: await workingDir(extra.signal),
36935
+ cwd: await workingDir(extra.signal, request.params._meta),
36847
36936
  ownDir: options.ownDir,
36848
36937
  stateDir: settings.state_dir,
36849
36938
  downloadDir: settings.download_dir,
36850
36939
  downloadMaxMb: settings.download_max_mb,
36851
36940
  sendDirs: settings.send_dirs,
36852
36941
  programName: PROJECT.name,
36942
+ options: settings.options,
36853
36943
  signal: extra.signal,
36854
36944
  ...confirm && { confirm }
36855
36945
  };
@@ -36875,7 +36965,7 @@ async function main() {
36875
36965
  const settings = parseSettings(process.argv.slice(2), process.env);
36876
36966
  server = createServer(ALL_TOOLS, settings, {
36877
36967
  ownDir: packageRoot(import.meta.url),
36878
- version: true ? "0.2.0" : void 0
36968
+ version: true ? "0.3.0" : void 0
36879
36969
  });
36880
36970
  } catch (error62) {
36881
36971
  if (!isToolError(error62)) throw error62;