@todoforai/edge 0.13.13 → 0.13.14

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.
Files changed (2) hide show
  1. package/dist/index.js +190 -130
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -47695,7 +47695,7 @@ var require_ignore = __commonJS((exports, module) => {
47695
47695
  makeArray(isString(pattern) ? splitPattern(pattern) : pattern).forEach(this._add, this);
47696
47696
  return this._added;
47697
47697
  }
47698
- test(path7, checkUnignored, mode) {
47698
+ test(path8, checkUnignored, mode) {
47699
47699
  let ignored = false;
47700
47700
  let unignored = false;
47701
47701
  let matchedRule;
@@ -47704,7 +47704,7 @@ var require_ignore = __commonJS((exports, module) => {
47704
47704
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
47705
47705
  return;
47706
47706
  }
47707
- const matched = rule[mode].test(path7);
47707
+ const matched = rule[mode].test(path8);
47708
47708
  if (!matched) {
47709
47709
  return;
47710
47710
  }
@@ -47725,20 +47725,20 @@ var require_ignore = __commonJS((exports, module) => {
47725
47725
  var throwError = (message, Ctor) => {
47726
47726
  throw new Ctor(message);
47727
47727
  };
47728
- var checkPath = (path7, originalPath, doThrow) => {
47729
- if (!isString(path7)) {
47728
+ var checkPath = (path8, originalPath, doThrow) => {
47729
+ if (!isString(path8)) {
47730
47730
  return doThrow(`path must be a string, but got \`${originalPath}\``, TypeError);
47731
47731
  }
47732
- if (!path7) {
47732
+ if (!path8) {
47733
47733
  return doThrow(`path must not be empty`, TypeError);
47734
47734
  }
47735
- if (checkPath.isNotRelative(path7)) {
47735
+ if (checkPath.isNotRelative(path8)) {
47736
47736
  const r = "`path.relative()`d";
47737
47737
  return doThrow(`path should be a ${r} string, but got "${originalPath}"`, RangeError);
47738
47738
  }
47739
47739
  return true;
47740
47740
  };
47741
- var isNotRelative = (path7) => REGEX_TEST_INVALID_PATH.test(path7);
47741
+ var isNotRelative = (path8) => REGEX_TEST_INVALID_PATH.test(path8);
47742
47742
  checkPath.isNotRelative = isNotRelative;
47743
47743
  checkPath.convert = (p10) => p10;
47744
47744
 
@@ -47767,15 +47767,15 @@ var require_ignore = __commonJS((exports, module) => {
47767
47767
  return this.add(pattern);
47768
47768
  }
47769
47769
  _test(originalPath, cache, checkUnignored, slices) {
47770
- const path7 = originalPath && checkPath.convert(originalPath);
47771
- checkPath(path7, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
47772
- return this._t(path7, cache, checkUnignored, slices);
47770
+ const path8 = originalPath && checkPath.convert(originalPath);
47771
+ checkPath(path8, originalPath, this._strictPathCheck ? throwError : RETURN_FALSE);
47772
+ return this._t(path8, cache, checkUnignored, slices);
47773
47773
  }
47774
- checkIgnore(path7) {
47775
- if (!REGEX_TEST_TRAILING_SLASH.test(path7)) {
47776
- return this.test(path7);
47774
+ checkIgnore(path8) {
47775
+ if (!REGEX_TEST_TRAILING_SLASH.test(path8)) {
47776
+ return this.test(path8);
47777
47777
  }
47778
- const slices = path7.split(SLASH).filter(Boolean);
47778
+ const slices = path8.split(SLASH).filter(Boolean);
47779
47779
  slices.pop();
47780
47780
  if (slices.length) {
47781
47781
  const parent = this._t(slices.join(SLASH) + SLASH, this._testCache, true, slices);
@@ -47783,42 +47783,42 @@ var require_ignore = __commonJS((exports, module) => {
47783
47783
  return parent;
47784
47784
  }
47785
47785
  }
47786
- return this._rules.test(path7, false, MODE_CHECK_IGNORE);
47786
+ return this._rules.test(path8, false, MODE_CHECK_IGNORE);
47787
47787
  }
47788
- _t(path7, cache, checkUnignored, slices) {
47789
- if (path7 in cache) {
47790
- return cache[path7];
47788
+ _t(path8, cache, checkUnignored, slices) {
47789
+ if (path8 in cache) {
47790
+ return cache[path8];
47791
47791
  }
47792
47792
  if (!slices) {
47793
- slices = path7.split(SLASH).filter(Boolean);
47793
+ slices = path8.split(SLASH).filter(Boolean);
47794
47794
  }
47795
47795
  slices.pop();
47796
47796
  if (!slices.length) {
47797
- return cache[path7] = this._rules.test(path7, checkUnignored, MODE_IGNORE);
47797
+ return cache[path8] = this._rules.test(path8, checkUnignored, MODE_IGNORE);
47798
47798
  }
47799
47799
  const parent = this._t(slices.join(SLASH) + SLASH, cache, checkUnignored, slices);
47800
- return cache[path7] = parent.ignored ? parent : this._rules.test(path7, checkUnignored, MODE_IGNORE);
47800
+ return cache[path8] = parent.ignored ? parent : this._rules.test(path8, checkUnignored, MODE_IGNORE);
47801
47801
  }
47802
- ignores(path7) {
47803
- return this._test(path7, this._ignoreCache, false).ignored;
47802
+ ignores(path8) {
47803
+ return this._test(path8, this._ignoreCache, false).ignored;
47804
47804
  }
47805
47805
  createFilter() {
47806
- return (path7) => !this.ignores(path7);
47806
+ return (path8) => !this.ignores(path8);
47807
47807
  }
47808
47808
  filter(paths) {
47809
47809
  return makeArray(paths).filter(this.createFilter());
47810
47810
  }
47811
- test(path7) {
47812
- return this._test(path7, this._testCache, true);
47811
+ test(path8) {
47812
+ return this._test(path8, this._testCache, true);
47813
47813
  }
47814
47814
  }
47815
47815
  var factory = (options) => new Ignore(options);
47816
- var isPathValid = (path7) => checkPath(path7 && checkPath.convert(path7), path7, RETURN_FALSE);
47816
+ var isPathValid = (path8) => checkPath(path8 && checkPath.convert(path8), path8, RETURN_FALSE);
47817
47817
  var setupWindows = () => {
47818
47818
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
47819
47819
  checkPath.convert = makePosix;
47820
47820
  const REGEX_TEST_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
47821
- checkPath.isNotRelative = (path7) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path7) || isNotRelative(path7);
47821
+ checkPath.isNotRelative = (path8) => REGEX_TEST_WINDOWS_PATH_ABSOLUTE.test(path8) || isNotRelative(path8);
47822
47822
  };
47823
47823
  if (typeof process !== "undefined" && process.platform === "win32") {
47824
47824
  setupWindows();
@@ -48645,9 +48645,9 @@ class BrowserExtensionBridge {
48645
48645
  }
48646
48646
 
48647
48647
  // src/handlers.ts
48648
- import fs11 from "fs";
48648
+ import fs12 from "fs";
48649
48649
  import { mkdir, rm as rm2, writeFile } from "fs/promises";
48650
- import path8 from "path";
48650
+ import path9 from "path";
48651
48651
 
48652
48652
  // src/path-utils.ts
48653
48653
  import path2 from "path";
@@ -49091,7 +49091,6 @@ var tool_catalog_default = {
49091
49091
  label: "TODOforAI",
49092
49092
  capabilities: "Create & manage TODOs, run workflows, API access",
49093
49093
  description: "Use to programmatically create/list/update TODOs in TODOforAI, kick off workflows, call the platform API.",
49094
- statusCmd: "todoai whoami >/dev/null 2>&1",
49095
49094
  installCmd: "bun add -g @todoforai/cli",
49096
49095
  versionCmd: "todoai --version 2>/dev/null | head -1",
49097
49096
  internal: true
@@ -51889,9 +51888,9 @@ function consumeExitedOutput(pid) {
51889
51888
  }
51890
51889
 
51891
51890
  // src/functions.ts
51892
- import fs10 from "fs";
51893
- import path7 from "path";
51894
- import os8 from "os";
51891
+ import fs11 from "fs";
51892
+ import path8 from "path";
51893
+ import os9 from "os";
51895
51894
 
51896
51895
  // src/skills.ts
51897
51896
  import fs9 from "fs";
@@ -52068,6 +52067,62 @@ function sanitize(s) {
52068
52067
  return s.split(/\s+/).filter(Boolean).join(" ");
52069
52068
  }
52070
52069
 
52070
+ // src/agent-md.ts
52071
+ import fs10 from "fs";
52072
+ import path7 from "path";
52073
+ import os8 from "os";
52074
+ var MAX_BYTES = 64 * 1024;
52075
+ var FILENAMES = ["AGENT.md", "AGENTS.md"];
52076
+ async function discoverAgentMd(rootPaths, opts = {}) {
52077
+ const includeUserScope = opts.includeUserScope ?? true;
52078
+ const maxBytes = opts.maxBytes ?? MAX_BYTES;
52079
+ const dirs = [
52080
+ ...rootPaths.map((p10) => ({ dir: p10, scope: "repo" }))
52081
+ ];
52082
+ if (includeUserScope) {
52083
+ dirs.push({ dir: path7.join(os8.homedir(), ".agents"), scope: "user" });
52084
+ }
52085
+ const files = [];
52086
+ const errors = [];
52087
+ const seen = new Set;
52088
+ for (const { dir, scope } of dirs) {
52089
+ for (const name of FILENAMES) {
52090
+ const full = path7.join(dir, name);
52091
+ if (seen.has(full))
52092
+ continue;
52093
+ let stat;
52094
+ try {
52095
+ stat = fs10.statSync(full);
52096
+ } catch {
52097
+ continue;
52098
+ }
52099
+ if (!stat.isFile())
52100
+ continue;
52101
+ seen.add(full);
52102
+ try {
52103
+ const fd3 = fs10.openSync(full, "r");
52104
+ const buf = Buffer.alloc(maxBytes);
52105
+ let bytes;
52106
+ try {
52107
+ bytes = fs10.readSync(fd3, buf, 0, maxBytes, 0);
52108
+ } finally {
52109
+ fs10.closeSync(fd3);
52110
+ }
52111
+ files.push({
52112
+ path: full,
52113
+ scope,
52114
+ content: buf.subarray(0, bytes).toString("utf-8"),
52115
+ bytes: stat.size,
52116
+ truncated: stat.size > maxBytes
52117
+ });
52118
+ } catch (e) {
52119
+ errors.push({ path: full, message: `read failed: ${e?.message ?? e}` });
52120
+ }
52121
+ }
52122
+ }
52123
+ return { files, errors };
52124
+ }
52125
+
52071
52126
  // src/functions.ts
52072
52127
  var FUNCTION_REGISTRY = new Map;
52073
52128
  function register(name, fn2) {
@@ -52083,12 +52138,12 @@ register("get_environment_variable", async (args) => ({
52083
52138
  value: process.env[args.var_name] ?? null
52084
52139
  }));
52085
52140
  register("get_system_info", async () => {
52086
- let system2 = os8.platform();
52141
+ let system2 = os9.platform();
52087
52142
  if (system2 === "darwin")
52088
52143
  system2 = "macOS";
52089
52144
  else if (system2 === "linux") {
52090
52145
  try {
52091
- const release = fs10.readFileSync("/etc/os-release", "utf-8");
52146
+ const release = fs11.readFileSync("/etc/os-release", "utf-8");
52092
52147
  const m = release.match(/PRETTY_NAME="(.+?)"/);
52093
52148
  if (m)
52094
52149
  system2 = m[1];
@@ -52098,10 +52153,10 @@ register("get_system_info", async () => {
52098
52153
  system2 = "Linux";
52099
52154
  }
52100
52155
  } else if (system2 === "win32") {
52101
- system2 = `Windows ${os8.release()}`;
52156
+ system2 = `Windows ${os9.release()}`;
52102
52157
  }
52103
- const shell = process.env.SHELL ? path7.basename(process.env.SHELL) : "unknown";
52104
- const mount_path = path7.join(os8.homedir(), ".todoforai", "mnt", "todoforai");
52158
+ const shell = process.env.SHELL ? path8.basename(process.env.SHELL) : "unknown";
52159
+ const mount_path = path8.join(os9.homedir(), ".todoforai", "mnt", "todoforai");
52105
52160
  return { system: system2, shell, mount_path };
52106
52161
  });
52107
52162
  register("get_available_tools", async () => {
@@ -52145,11 +52200,11 @@ register("uninstall_tool", async (args) => {
52145
52200
  });
52146
52201
  register("get_workspace_tree", async (args) => {
52147
52202
  const { path: p10, max_depth = 2 } = args;
52148
- const root = path7.resolve(p10.replace(/^~/, process.env.HOME || "~"));
52149
- if (!fs10.existsSync(root) || !fs10.statSync(root).isDirectory()) {
52203
+ const root = path8.resolve(p10.replace(/^~/, process.env.HOME || "~"));
52204
+ if (!fs11.existsSync(root) || !fs11.statSync(root).isDirectory()) {
52150
52205
  return { tree: "", is_git: false };
52151
52206
  }
52152
- const isGit = fs10.existsSync(path7.join(root, ".git"));
52207
+ const isGit = fs11.existsSync(path8.join(root, ".git"));
52153
52208
  if (process.platform !== "win32") {
52154
52209
  try {
52155
52210
  const { execSync: execSync2 } = await import("child_process");
@@ -52172,12 +52227,12 @@ register("get_workspace_tree", async (args) => {
52172
52227
  const ig2 = ignore();
52173
52228
  if (isGit) {
52174
52229
  let scanGitignores = function(dir) {
52175
- const giPath = path7.join(dir, ".gitignore");
52176
- if (fs10.existsSync(giPath)) {
52230
+ const giPath = path8.join(dir, ".gitignore");
52231
+ if (fs11.existsSync(giPath)) {
52177
52232
  try {
52178
- const relDir = path7.relative(root, dir).replace(/\\/g, "/");
52233
+ const relDir = path8.relative(root, dir).replace(/\\/g, "/");
52179
52234
  const prefix = relDir === "" || relDir === "." ? "" : relDir + "/";
52180
- for (let line of fs10.readFileSync(giPath, "utf-8").split(`
52235
+ for (let line of fs11.readFileSync(giPath, "utf-8").split(`
52181
52236
  `)) {
52182
52237
  line = line.trim();
52183
52238
  if (!line || line.startsWith("#"))
@@ -52191,21 +52246,21 @@ register("get_workspace_tree", async (args) => {
52191
52246
  } catch {}
52192
52247
  }
52193
52248
  try {
52194
- for (const e of fs10.readdirSync(dir, { withFileTypes: true })) {
52249
+ for (const e of fs11.readdirSync(dir, { withFileTypes: true })) {
52195
52250
  if (e.isDirectory() && e.name !== ".git")
52196
- scanGitignores(path7.join(dir, e.name));
52251
+ scanGitignores(path8.join(dir, e.name));
52197
52252
  }
52198
52253
  } catch {}
52199
52254
  };
52200
52255
  scanGitignores(root);
52201
52256
  }
52202
- const lines = [path7.basename(root) + "/"];
52257
+ const lines = [path8.basename(root) + "/"];
52203
52258
  function walk(dirPath, prefix, depth) {
52204
52259
  if (depth > max_depth)
52205
52260
  return;
52206
52261
  let entries;
52207
52262
  try {
52208
- entries = fs10.readdirSync(dirPath, { withFileTypes: true });
52263
+ entries = fs11.readdirSync(dirPath, { withFileTypes: true });
52209
52264
  } catch {
52210
52265
  return;
52211
52266
  }
@@ -52213,7 +52268,7 @@ register("get_workspace_tree", async (args) => {
52213
52268
  if (e.name === ".git")
52214
52269
  return false;
52215
52270
  if (isGit) {
52216
- let rel = path7.relative(root, path7.join(dirPath, e.name)).replace(/\\/g, "/");
52271
+ let rel = path8.relative(root, path8.join(dirPath, e.name)).replace(/\\/g, "/");
52217
52272
  if (e.isDirectory())
52218
52273
  rel += "/";
52219
52274
  if (ig2.ignores(rel))
@@ -52235,7 +52290,7 @@ register("get_workspace_tree", async (args) => {
52235
52290
  lines.push(`${prefix}${connector}${entry.name}${suffix}`);
52236
52291
  if (entry.isDirectory()) {
52237
52292
  const extension2 = isLast ? " " : "│ ";
52238
- walk(path7.join(dirPath, entry.name), prefix + extension2, depth + 1);
52293
+ walk(path8.join(dirPath, entry.name), prefix + extension2, depth + 1);
52239
52294
  }
52240
52295
  }
52241
52296
  }
@@ -52248,25 +52303,30 @@ register("get_skills", async (args) => {
52248
52303
  const includeUserScope = args?.includeUserScope ?? true;
52249
52304
  return await discoverSkills(paths, { includeUserScope });
52250
52305
  });
52306
+ register("get_agent_md", async (args) => {
52307
+ const paths = Array.isArray(args?.paths) ? args.paths : [];
52308
+ const includeUserScope = args?.includeUserScope ?? true;
52309
+ return await discoverAgentMd(paths, { includeUserScope });
52310
+ });
52251
52311
  register("get_os_aware_default_path", async () => {
52252
52312
  let p10 = getPlatformDefaultDirectory();
52253
- if (!p10.endsWith(path7.sep))
52254
- p10 += path7.sep;
52313
+ if (!p10.endsWith(path8.sep))
52314
+ p10 += path8.sep;
52255
52315
  return { path: p10 };
52256
52316
  });
52257
52317
  register("create_directory", async (args) => {
52258
52318
  const { name } = args;
52259
52319
  if (!name?.trim())
52260
52320
  throw new Error("Folder name cannot be empty");
52261
- const baseDir = path7.resolve(getPathOrDefault(args.path).replace(/^~/, process.env.HOME || "~"));
52262
- let target = path7.resolve(name.replace(/^~/, process.env.HOME || "~"));
52263
- if (!path7.isAbsolute(name))
52264
- target = path7.join(baseDir, name.trim());
52265
- const existed = fs10.existsSync(target);
52266
- fs10.mkdirSync(target, { recursive: true });
52321
+ const baseDir = path8.resolve(getPathOrDefault(args.path).replace(/^~/, process.env.HOME || "~"));
52322
+ let target = path8.resolve(name.replace(/^~/, process.env.HOME || "~"));
52323
+ if (!path8.isAbsolute(name))
52324
+ target = path8.join(baseDir, name.trim());
52325
+ const existed = fs11.existsSync(target);
52326
+ fs11.mkdirSync(target, { recursive: true });
52267
52327
  let full = target;
52268
- if (!full.endsWith(path7.sep))
52269
- full += path7.sep;
52328
+ if (!full.endsWith(path8.sep))
52329
+ full += path8.sep;
52270
52330
  return { path: full, created: !existed, exists: true };
52271
52331
  });
52272
52332
  FUNCTION_REGISTRY.set("getOSAwareDefaultPath", FUNCTION_REGISTRY.get("get_os_aware_default_path"));
@@ -52300,7 +52360,7 @@ register("execute_shell_command", async (args, client) => {
52300
52360
  if (!canStream) {
52301
52361
  const { exec } = await import("child_process");
52302
52362
  const result = await new Promise((resolve) => {
52303
- exec(cmd, { cwd: cwd || os8.tmpdir(), encoding: "utf-8", timeout: timeout * 1000, maxBuffer: 10485760, env: { ...buildEnvWithTools(), ...getConnectionEnv(), TODOFORAI_TODO_ID: todoId, TODOFORAI_MESSAGE_ID: messageId, TODOFORAI_BLOCK_ID: blockId, TODOFORAI_AGENT_SETTINGS_ID: agentSettingsId } }, (_err, stdout, stderr) => {
52363
+ exec(cmd, { cwd: cwd || os9.tmpdir(), encoding: "utf-8", timeout: timeout * 1000, maxBuffer: 10485760, env: { ...buildEnvWithTools(), ...getConnectionEnv(), TODOFORAI_TODO_ID: todoId, TODOFORAI_MESSAGE_ID: messageId, TODOFORAI_BLOCK_ID: blockId, TODOFORAI_AGENT_SETTINGS_ID: agentSettingsId } }, (_err, stdout, stderr) => {
52304
52364
  resolve((stdout || "") + (stderr || ""));
52305
52365
  });
52306
52366
  });
@@ -52365,17 +52425,17 @@ var LIST_DIR_MAX_ENTRIES = 1e4;
52365
52425
  register("list_dir", async (args) => {
52366
52426
  const { path: p10, rootPath = "", fallbackRootPaths = [] } = args;
52367
52427
  const fullPath = resolveFilePath(p10, rootPath, fallbackRootPaths);
52368
- const st2 = fs10.statSync(fullPath);
52428
+ const st2 = fs11.statSync(fullPath);
52369
52429
  if (!st2.isDirectory())
52370
52430
  throw new Error(`Not a directory: ${fullPath}`);
52371
- const dirents = fs10.readdirSync(fullPath, { withFileTypes: true });
52431
+ const dirents = fs11.readdirSync(fullPath, { withFileTypes: true });
52372
52432
  if (dirents.length > LIST_DIR_MAX_ENTRIES) {
52373
52433
  throw new Error(`Directory too large: ${dirents.length} entries (max ${LIST_DIR_MAX_ENTRIES})`);
52374
52434
  }
52375
52435
  const entries = dirents.map((d) => {
52376
52436
  let size = 0, mtime = 0, mode = 0, is_dir = d.isDirectory();
52377
52437
  try {
52378
- const s = fs10.lstatSync(path7.join(fullPath, d.name));
52438
+ const s = fs11.lstatSync(path8.join(fullPath, d.name));
52379
52439
  size = Number(s.size);
52380
52440
  mtime = s.mtimeMs / 1000;
52381
52441
  mode = s.mode & 511;
@@ -52388,21 +52448,21 @@ register("list_dir", async (args) => {
52388
52448
  register("create_file", async (args) => {
52389
52449
  const { path: p10, content, rootPath = "", fallbackRootPaths = [] } = args;
52390
52450
  const fullPath = resolveFilePath(p10, rootPath, fallbackRootPaths);
52391
- const dir = path7.dirname(fullPath);
52451
+ const dir = path8.dirname(fullPath);
52392
52452
  if (dir)
52393
- fs10.mkdirSync(dir, { recursive: true });
52394
- fs10.writeFileSync(fullPath, content, "utf-8");
52453
+ fs11.mkdirSync(dir, { recursive: true });
52454
+ fs11.writeFileSync(fullPath, content, "utf-8");
52395
52455
  return { path: fullPath, bytes: Buffer.byteLength(content, "utf-8") };
52396
52456
  });
52397
52457
  register("read_file_base64", async (args) => {
52398
52458
  const { path: p10, rootPath = "", fallbackRootPaths = [] } = args;
52399
52459
  const fullPath = resolveFilePath(p10, rootPath, fallbackRootPaths);
52400
- if (!fs10.existsSync(fullPath))
52460
+ if (!fs11.existsSync(fullPath))
52401
52461
  throw new Error(`File not found: ${fullPath}`);
52402
- const stat = fs10.statSync(fullPath);
52462
+ const stat = fs11.statSync(fullPath);
52403
52463
  if (stat.size > 50000000)
52404
52464
  throw new Error(`File too large: ${stat.size.toLocaleString()} bytes (max 50MB)`);
52405
- const data = fs10.readFileSync(fullPath);
52465
+ const data = fs11.readFileSync(fullPath);
52406
52466
  return { path: fullPath, base64: data.toString("base64"), bytes: data.length };
52407
52467
  });
52408
52468
  register("download_attachment", async (args, client) => {
@@ -52419,13 +52479,13 @@ register("download_attachment", async (args, client) => {
52419
52479
  throw new Error(`Backend responded with ${res.status}`);
52420
52480
  const base = getPathOrDefault(rootPath);
52421
52481
  let target = p10.replace(/^~/, process.env.HOME || "~");
52422
- if (!path7.isAbsolute(target))
52423
- target = path7.join(base, target);
52424
- target = path7.resolve(target);
52425
- fs10.mkdirSync(path7.dirname(target), { recursive: true });
52482
+ if (!path8.isAbsolute(target))
52483
+ target = path8.join(base, target);
52484
+ target = path8.resolve(target);
52485
+ fs11.mkdirSync(path8.dirname(target), { recursive: true });
52426
52486
  try {
52427
52487
  const data = Buffer.from(await res.arrayBuffer());
52428
- fs10.writeFileSync(target, data);
52488
+ fs11.writeFileSync(target, data);
52429
52489
  return { path: target, bytes: data.length };
52430
52490
  } catch (e) {
52431
52491
  throw new Error(`Download failed: ${e.message}`);
@@ -52453,13 +52513,13 @@ register("register_attachment", async (args, client) => {
52453
52513
  const { filePath, userId = "test-user", isPublic = false, agentSettingsId = "", todoId = "", rootPath = "" } = args;
52454
52514
  const base = getPathOrDefault(rootPath);
52455
52515
  let target = filePath.replace(/^~/, process.env.HOME || "~");
52456
- if (!path7.isAbsolute(target))
52457
- target = path7.join(base, target);
52458
- target = path7.resolve(target);
52459
- if (!fs10.existsSync(target))
52516
+ if (!path8.isAbsolute(target))
52517
+ target = path8.join(base, target);
52518
+ target = path8.resolve(target);
52519
+ if (!fs11.existsSync(target))
52460
52520
  throw new Error(`File not found: ${target}`);
52461
52521
  const form = new FormData;
52462
- form.append("file", new Blob([fs10.readFileSync(target)]), path7.basename(target));
52522
+ form.append("file", new Blob([fs11.readFileSync(target)]), path8.basename(target));
52463
52523
  if (userId)
52464
52524
  form.append("userId", userId);
52465
52525
  if (agentSettingsId)
@@ -52503,9 +52563,9 @@ async function handleBlockSave(payload, send) {
52503
52563
  const { blockId, todoId, filepath, rootPath, fallbackRootPaths = [], content, requestId } = payload;
52504
52564
  try {
52505
52565
  const resolved = resolveFilePath(filepath, rootPath, fallbackRootPaths);
52506
- const ext = path8.extname(resolved).toLowerCase();
52566
+ const ext = path9.extname(resolved).toLowerCase();
52507
52567
  if (ext === ".docx" || ext === ".xlsx") {
52508
- if (!fs11.existsSync(resolved)) {
52568
+ if (!fs12.existsSync(resolved)) {
52509
52569
  throw new Error(`Cannot create new ${ext} file from XML — file must already exist: ${filepath}`);
52510
52570
  }
52511
52571
  if (ext === ".docx")
@@ -52513,10 +52573,10 @@ async function handleBlockSave(payload, send) {
52513
52573
  else
52514
52574
  saveXlsxContent(resolved, content);
52515
52575
  } else {
52516
- const dir = path8.dirname(resolved);
52576
+ const dir = path9.dirname(resolved);
52517
52577
  if (dir)
52518
- fs11.mkdirSync(dir, { recursive: true });
52519
- fs11.writeFileSync(resolved, content, "utf-8");
52578
+ fs12.mkdirSync(dir, { recursive: true });
52579
+ fs12.writeFileSync(resolved, content, "utf-8");
52520
52580
  }
52521
52581
  await send(msg.blockSaveResult(blockId, todoId, "SUCCESS", requestId));
52522
52582
  } catch (e) {
@@ -52527,22 +52587,22 @@ async function handleGetFolders(payload, send) {
52527
52587
  const { requestId, edgeId } = payload;
52528
52588
  const rawPath = getPathOrDefault(payload.path);
52529
52589
  try {
52530
- const expandedPath = path8.resolve(rawPath.replace(/^~/, process.env.HOME || "~"));
52590
+ const expandedPath = path9.resolve(rawPath.replace(/^~/, process.env.HOME || "~"));
52531
52591
  let targetPath;
52532
- if (fs11.existsSync(expandedPath) && fs11.statSync(expandedPath).isDirectory()) {
52592
+ if (fs12.existsSync(expandedPath) && fs12.statSync(expandedPath).isDirectory()) {
52533
52593
  targetPath = expandedPath;
52534
52594
  } else {
52535
- targetPath = path8.dirname(expandedPath);
52595
+ targetPath = path9.dirname(expandedPath);
52536
52596
  }
52537
- if (!fs11.existsSync(targetPath) || !fs11.statSync(targetPath).isDirectory()) {
52597
+ if (!fs12.existsSync(targetPath) || !fs12.statSync(targetPath).isDirectory()) {
52538
52598
  throw new Error(`No existing ancestor for path: ${rawPath}`);
52539
52599
  }
52540
52600
  const folders = [];
52541
52601
  const files = [];
52542
- for (const item of fs11.readdirSync(targetPath)) {
52543
- const full = path8.join(targetPath, item);
52602
+ for (const item of fs12.readdirSync(targetPath)) {
52603
+ const full = path9.join(targetPath, item);
52544
52604
  try {
52545
- if (fs11.statSync(full).isDirectory())
52605
+ if (fs12.statSync(full).isDirectory())
52546
52606
  folders.push(full);
52547
52607
  else
52548
52608
  files.push(full);
@@ -52576,10 +52636,10 @@ async function handleDeletePath(payload, send) {
52576
52636
  async function handleWriteFile(payload, send, pendingBinaries) {
52577
52637
  const { requestId, edgeId, path: dirPath, fileName, binaryId, dataBase64 } = payload;
52578
52638
  try {
52579
- const filePath = path8.join(dirPath, fileName);
52580
- const dir = path8.dirname(filePath);
52639
+ const filePath = path9.join(dirPath, fileName);
52640
+ const dir = path9.dirname(filePath);
52581
52641
  if (dir)
52582
- fs11.mkdirSync(dir, { recursive: true });
52642
+ fs12.mkdirSync(dir, { recursive: true });
52583
52643
  let buffer;
52584
52644
  if (binaryId && pendingBinaries?.has(binaryId)) {
52585
52645
  buffer = pendingBinaries.get(binaryId);
@@ -52600,8 +52660,8 @@ async function handleCd(payload, send, edgeConfig, onConfigChange) {
52600
52660
  const { requestId, edgeId } = payload;
52601
52661
  const rawPath = getPathOrDefault(payload.path);
52602
52662
  try {
52603
- const resolved = path8.resolve(rawPath.replace(/^~/, process.env.HOME || "~"));
52604
- if (!fs11.existsSync(resolved) || !fs11.statSync(resolved).isDirectory()) {
52663
+ const resolved = path9.resolve(rawPath.replace(/^~/, process.env.HOME || "~"));
52664
+ if (!fs12.existsSync(resolved) || !fs12.statSync(resolved).isDirectory()) {
52605
52665
  throw new Error(`Path does not exist or is not a directory: ${rawPath}`);
52606
52666
  }
52607
52667
  const normalized = resolved.replace(/\/+$/, "");
@@ -52656,12 +52716,12 @@ async function handleFunctionCall(payload, send, client) {
52656
52716
 
52657
52717
  // src/edge.ts
52658
52718
  function generateFingerprint() {
52659
- const os9 = __require("os");
52660
- const fs12 = __require("fs");
52719
+ const os10 = __require("os");
52720
+ const fs13 = __require("fs");
52661
52721
  const identifiers = {};
52662
52722
  if (process.platform === "linux") {
52663
52723
  try {
52664
- const mid = fs12.readFileSync("/etc/machine-id", "utf-8").trim();
52724
+ const mid = fs13.readFileSync("/etc/machine-id", "utf-8").trim();
52665
52725
  if (mid)
52666
52726
  identifiers.machine_id = mid;
52667
52727
  } catch {}
@@ -52676,8 +52736,8 @@ function generateFingerprint() {
52676
52736
  }
52677
52737
  if (Object.keys(identifiers).length === 0) {
52678
52738
  identifiers.platform = process.platform;
52679
- identifiers.machine = os9.machine?.() || os9.arch();
52680
- identifiers.node = os9.hostname();
52739
+ identifiers.machine = os10.machine?.() || os10.arch();
52740
+ identifiers.node = os10.hostname();
52681
52741
  }
52682
52742
  const keys = Object.keys(identifiers).sort();
52683
52743
  const json = "{" + keys.map((k) => JSON.stringify(k) + ": " + JSON.stringify(identifiers[k])).join(", ") + "}";
@@ -52863,8 +52923,8 @@ class TODOforAIEdge {
52863
52923
  if (edgeId && edgeId !== this.edgeId)
52864
52924
  return;
52865
52925
  if (payload.workspacepaths) {
52866
- const path9 = __require("path");
52867
- payload.workspacepaths = payload.workspacepaths.filter((p10) => !FORBIDDEN_PATHS2.has(path9.normalize(p10).replace(/\/+$/, "")));
52926
+ const path10 = __require("path");
52927
+ payload.workspacepaths = payload.workspacepaths.filter((p10) => !FORBIDDEN_PATHS2.has(path10.normalize(p10).replace(/\/+$/, "")));
52868
52928
  }
52869
52929
  Object.assign(this.edgeConfig, payload);
52870
52930
  if (this.addWorkspacePath) {
@@ -53146,18 +53206,18 @@ class ServerError extends Error {
53146
53206
  }
53147
53207
 
53148
53208
  // node_modules/@todoforai/update-notifier/src/index.ts
53149
- import fs12 from "node:fs";
53150
- import path9 from "node:path";
53151
- import os9 from "node:os";
53209
+ import fs13 from "node:fs";
53210
+ import path10 from "node:path";
53211
+ import os10 from "node:os";
53152
53212
  function isLinkedInstall() {
53153
53213
  try {
53154
- return !fs12.realpathSync(process.argv[1] || "").includes(`${path9.sep}node_modules${path9.sep}`);
53214
+ return !fs13.realpathSync(process.argv[1] || "").includes(`${path10.sep}node_modules${path10.sep}`);
53155
53215
  } catch {
53156
53216
  return false;
53157
53217
  }
53158
53218
  }
53159
53219
  var TTL_MS = 24 * 60 * 60 * 1000;
53160
- var CACHE_DIR = path9.join(os9.homedir(), ".config", "todoforai");
53220
+ var CACHE_DIR = path10.join(os10.homedir(), ".config", "todoforai");
53161
53221
  function cmpVer(a, b) {
53162
53222
  const pa2 = a.split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
53163
53223
  const pb2 = b.split("-")[0].split(".").map((n) => parseInt(n, 10) || 0);
@@ -53171,10 +53231,10 @@ function cmpVer(a, b) {
53171
53231
  function checkForUpdates(pkg) {
53172
53232
  if (!process.stderr.isTTY || process.env.CI || process.env.NO_UPDATE_NOTIFIER || isLinkedInstall())
53173
53233
  return;
53174
- const cacheFile = path9.join(CACHE_DIR, `notifier-${encodeURIComponent(pkg.name)}.json`);
53234
+ const cacheFile = path10.join(CACHE_DIR, `notifier-${encodeURIComponent(pkg.name)}.json`);
53175
53235
  let cache = {};
53176
53236
  try {
53177
- cache = JSON.parse(fs12.readFileSync(cacheFile, "utf8"));
53237
+ cache = JSON.parse(fs13.readFileSync(cacheFile, "utf8"));
53178
53238
  } catch {}
53179
53239
  if (cache.latest && cmpVer(cache.latest, pkg.version) > 0) {
53180
53240
  process.stderr.write(`
@@ -53185,42 +53245,42 @@ function checkForUpdates(pkg) {
53185
53245
  }
53186
53246
  if (Date.now() - (cache.ts ?? 0) > TTL_MS) {
53187
53247
  try {
53188
- fs12.mkdirSync(CACHE_DIR, { recursive: true });
53189
- fs12.writeFileSync(cacheFile, JSON.stringify({ ...cache, ts: Date.now() }));
53248
+ fs13.mkdirSync(CACHE_DIR, { recursive: true });
53249
+ fs13.writeFileSync(cacheFile, JSON.stringify({ ...cache, ts: Date.now() }));
53190
53250
  } catch {}
53191
53251
  fetch(`https://registry.npmjs.org/${pkg.name}/latest`, { signal: AbortSignal.timeout(3000) }).then((r) => r.ok ? r.json() : null).then((j) => {
53192
53252
  if (!j?.version)
53193
53253
  return;
53194
- fs12.writeFileSync(cacheFile, JSON.stringify({ ts: Date.now(), latest: j.version }));
53254
+ fs13.writeFileSync(cacheFile, JSON.stringify({ ts: Date.now(), latest: j.version }));
53195
53255
  }).catch(() => {});
53196
53256
  }
53197
53257
  }
53198
53258
 
53199
53259
  // src/index.ts
53200
53260
  import { fileURLToPath as fileURLToPath2 } from "url";
53201
- import fs13 from "fs";
53202
- import path10 from "path";
53203
- import os10 from "os";
53261
+ import fs14 from "fs";
53262
+ import path11 from "path";
53263
+ import os11 from "os";
53204
53264
  import crypto3 from "crypto";
53205
53265
  function readOwnPackage() {
53206
53266
  try {
53207
- const pkgPath = path10.resolve(fileURLToPath2(import.meta.url), "../../package.json");
53208
- return JSON.parse(fs13.readFileSync(pkgPath, "utf-8"));
53267
+ const pkgPath = path11.resolve(fileURLToPath2(import.meta.url), "../../package.json");
53268
+ return JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
53209
53269
  } catch {
53210
53270
  return null;
53211
53271
  }
53212
53272
  }
53213
53273
  function lockPath(apiUrl, userId) {
53214
- const dir = path10.join(os10.homedir(), ".todoforai");
53215
- fs13.mkdirSync(dir, { recursive: true });
53274
+ const dir = path11.join(os11.homedir(), ".todoforai");
53275
+ fs14.mkdirSync(dir, { recursive: true });
53216
53276
  const hash = crypto3.createHash("sha256").update(`${apiUrl}
53217
53277
  ${userId}`).digest("hex").slice(0, 12);
53218
- return path10.join(dir, `edge-${hash}.lock`);
53278
+ return path11.join(dir, `edge-${hash}.lock`);
53219
53279
  }
53220
53280
  function isEdgeProcess(pid) {
53221
53281
  try {
53222
53282
  process.kill(pid, 0);
53223
- const cmdline = fs13.readFileSync(`/proc/${pid}/cmdline`, "utf-8");
53283
+ const cmdline = fs14.readFileSync(`/proc/${pid}/cmdline`, "utf-8");
53224
53284
  return cmdline.includes("index.ts") || cmdline.includes("todoforai-edge");
53225
53285
  } catch {
53226
53286
  return false;
@@ -53228,7 +53288,7 @@ function isEdgeProcess(pid) {
53228
53288
  }
53229
53289
  function killExistingEdge(lp2) {
53230
53290
  try {
53231
- const pid = parseInt(fs13.readFileSync(lp2, "utf-8").trim(), 10);
53291
+ const pid = parseInt(fs14.readFileSync(lp2, "utf-8").trim(), 10);
53232
53292
  if (!isNaN(pid) && isEdgeProcess(pid)) {
53233
53293
  console.log(`\x1B[33mKilling existing edge process (pid ${pid})...\x1B[0m`);
53234
53294
  process.kill(pid, "SIGTERM");
@@ -53251,7 +53311,7 @@ function killExistingEdge(lp2) {
53251
53311
  }
53252
53312
  function acquireLock(lp2, kill = false) {
53253
53313
  try {
53254
- const pid = parseInt(fs13.readFileSync(lp2, "utf-8").trim(), 10);
53314
+ const pid = parseInt(fs14.readFileSync(lp2, "utf-8").trim(), 10);
53255
53315
  if (!isNaN(pid) && isEdgeProcess(pid)) {
53256
53316
  if (kill) {
53257
53317
  killExistingEdge(lp2);
@@ -53259,13 +53319,13 @@ function acquireLock(lp2, kill = false) {
53259
53319
  return false;
53260
53320
  }
53261
53321
  } catch {}
53262
- fs13.writeFileSync(lp2, String(process.pid));
53322
+ fs14.writeFileSync(lp2, String(process.pid));
53263
53323
  return true;
53264
53324
  }
53265
53325
  function releaseLock(lp2) {
53266
53326
  try {
53267
- if (fs13.readFileSync(lp2, "utf-8").trim() === String(process.pid))
53268
- fs13.unlinkSync(lp2);
53327
+ if (fs14.readFileSync(lp2, "utf-8").trim() === String(process.pid))
53328
+ fs14.unlinkSync(lp2);
53269
53329
  } catch {}
53270
53330
  }
53271
53331
  var MIN_BUN_VERSION = "1.3.14";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@todoforai/edge",
3
- "version": "0.13.13",
3
+ "version": "0.13.14",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "todoforai-edge": "dist/index.js"