@agent-api/sdk 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog — @agent-api/sdk
2
2
 
3
+ ## 1.2.3
4
+
5
+ ### Fixed
6
+
7
+ - Hardened local workdir scans so broken symlinks and files that disappear during recursive list, grep, and summarize operations do not abort the scan.
8
+
3
9
  ## 1.2.2
4
10
 
5
11
  ### Added
@@ -1,6 +1,6 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { constants as fsConstants, watch as watchFS } from "node:fs";
3
- import { access, copyFile, mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
3
+ import { access, copyFile, lstat, mkdir, readdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
4
4
  import { homedir, tmpdir } from "node:os";
5
5
  import path from "node:path";
6
6
  import { localSkillFromDirectory } from "../local-skills.js";
@@ -322,12 +322,15 @@ export class LocalFileStore {
322
322
  if (item.type !== "file" || item.size > maxBytesPerFile || !isLikelyTextFile(item.path)) {
323
323
  continue;
324
324
  }
325
- const raw = await readFile(item.fullPath);
325
+ const raw = await readOptionalFile(item.fullPath);
326
+ if (!raw) {
327
+ continue;
328
+ }
326
329
  if (looksBinary(raw)) {
327
330
  continue;
328
331
  }
329
332
  filesScanned++;
330
- const lines = splitLines(raw.toString("utf8"));
333
+ const lines = splitLines(Buffer.from(raw).toString("utf8"));
331
334
  for (let i = 0; i < lines.length; i++) {
332
335
  if (!lines[i].includes(pattern)) {
333
336
  continue;
@@ -363,7 +366,10 @@ export class LocalFileStore {
363
366
  if (!isLikelyTextFile(item.path) || item.size > previewBytes * 4) {
364
367
  continue;
365
368
  }
366
- const raw = await readFile(item.fullPath);
369
+ const raw = await readOptionalFile(item.fullPath);
370
+ if (!raw) {
371
+ continue;
372
+ }
367
373
  if (looksBinary(raw)) {
368
374
  continue;
369
375
  }
@@ -371,7 +377,7 @@ export class LocalFileStore {
371
377
  previews.push({
372
378
  path: item.path,
373
379
  size: item.size,
374
- preview: raw.subarray(0, previewBytes).toString("utf8"),
380
+ preview: Buffer.from(raw.subarray(0, previewBytes)).toString("utf8"),
375
381
  preview_truncated: truncated || undefined,
376
382
  });
377
383
  }
@@ -393,7 +399,10 @@ export class LocalFileStore {
393
399
  if (ignored(relativePath, options.ignore)) {
394
400
  continue;
395
401
  }
396
- const info = await stat(fullPath);
402
+ const info = await lstatOptional(fullPath);
403
+ if (!info) {
404
+ continue;
405
+ }
397
406
  const item = {
398
407
  path: relativePath,
399
408
  fullPath,
@@ -401,7 +410,7 @@ export class LocalFileStore {
401
410
  size: info.size,
402
411
  modifiedAt: info.mtime,
403
412
  };
404
- if (entry.isDirectory()) {
413
+ if (info.isDirectory()) {
405
414
  if (options.includeDirectories) {
406
415
  out.push(item);
407
416
  }
@@ -813,6 +822,28 @@ async function fileExists(fullPath) {
813
822
  return false;
814
823
  }
815
824
  }
825
+ async function lstatOptional(fullPath) {
826
+ try {
827
+ return await lstat(fullPath);
828
+ }
829
+ catch (error) {
830
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR") {
831
+ return null;
832
+ }
833
+ throw error;
834
+ }
835
+ }
836
+ async function readOptionalFile(fullPath) {
837
+ try {
838
+ return await readFile(fullPath);
839
+ }
840
+ catch (error) {
841
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR" || error?.code === "EISDIR") {
842
+ return null;
843
+ }
844
+ throw error;
845
+ }
846
+ }
816
847
  function normalizeAppName(appName) {
817
848
  const trimmed = appName.trim();
818
849
  if (!trimmed) {
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "1.2.2";
2
- export declare const USER_AGENT = "@agent-api/sdk/1.2.2";
1
+ export declare const VERSION = "1.2.3";
2
+ export declare const USER_AGENT = "@agent-api/sdk/1.2.3";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = "1.2.2";
1
+ export const VERSION = "1.2.3";
2
2
  export const USER_AGENT = `@agent-api/sdk/${VERSION}`;
@@ -337,12 +337,15 @@ class LocalFileStore {
337
337
  if (item.type !== "file" || item.size > maxBytesPerFile || !isLikelyTextFile(item.path)) {
338
338
  continue;
339
339
  }
340
- const raw = await (0, promises_1.readFile)(item.fullPath);
340
+ const raw = await readOptionalFile(item.fullPath);
341
+ if (!raw) {
342
+ continue;
343
+ }
341
344
  if (looksBinary(raw)) {
342
345
  continue;
343
346
  }
344
347
  filesScanned++;
345
- const lines = splitLines(raw.toString("utf8"));
348
+ const lines = splitLines(Buffer.from(raw).toString("utf8"));
346
349
  for (let i = 0; i < lines.length; i++) {
347
350
  if (!lines[i].includes(pattern)) {
348
351
  continue;
@@ -378,7 +381,10 @@ class LocalFileStore {
378
381
  if (!isLikelyTextFile(item.path) || item.size > previewBytes * 4) {
379
382
  continue;
380
383
  }
381
- const raw = await (0, promises_1.readFile)(item.fullPath);
384
+ const raw = await readOptionalFile(item.fullPath);
385
+ if (!raw) {
386
+ continue;
387
+ }
382
388
  if (looksBinary(raw)) {
383
389
  continue;
384
390
  }
@@ -386,7 +392,7 @@ class LocalFileStore {
386
392
  previews.push({
387
393
  path: item.path,
388
394
  size: item.size,
389
- preview: raw.subarray(0, previewBytes).toString("utf8"),
395
+ preview: Buffer.from(raw.subarray(0, previewBytes)).toString("utf8"),
390
396
  preview_truncated: truncated || undefined,
391
397
  });
392
398
  }
@@ -408,7 +414,10 @@ class LocalFileStore {
408
414
  if (ignored(relativePath, options.ignore)) {
409
415
  continue;
410
416
  }
411
- const info = await (0, promises_1.stat)(fullPath);
417
+ const info = await lstatOptional(fullPath);
418
+ if (!info) {
419
+ continue;
420
+ }
412
421
  const item = {
413
422
  path: relativePath,
414
423
  fullPath,
@@ -416,7 +425,7 @@ class LocalFileStore {
416
425
  size: info.size,
417
426
  modifiedAt: info.mtime,
418
427
  };
419
- if (entry.isDirectory()) {
428
+ if (info.isDirectory()) {
420
429
  if (options.includeDirectories) {
421
430
  out.push(item);
422
431
  }
@@ -833,6 +842,28 @@ async function fileExists(fullPath) {
833
842
  return false;
834
843
  }
835
844
  }
845
+ async function lstatOptional(fullPath) {
846
+ try {
847
+ return await (0, promises_1.lstat)(fullPath);
848
+ }
849
+ catch (error) {
850
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR") {
851
+ return null;
852
+ }
853
+ throw error;
854
+ }
855
+ }
856
+ async function readOptionalFile(fullPath) {
857
+ try {
858
+ return await (0, promises_1.readFile)(fullPath);
859
+ }
860
+ catch (error) {
861
+ if (error?.code === "ENOENT" || error?.code === "ENOTDIR" || error?.code === "EISDIR") {
862
+ return null;
863
+ }
864
+ throw error;
865
+ }
866
+ }
836
867
  function normalizeAppName(appName) {
837
868
  const trimmed = appName.trim();
838
869
  if (!trimmed) {
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.USER_AGENT = exports.VERSION = void 0;
4
- exports.VERSION = "1.2.2";
4
+ exports.VERSION = "1.2.3";
5
5
  exports.USER_AGENT = `@agent-api/sdk/${exports.VERSION}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-api/sdk",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Production JavaScript SDK for the Managed Agent API",
5
5
  "license": "MIT",
6
6
  "repository": {