@aria-cli/tools 1.0.9 → 1.0.11
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/package.json +9 -5
- package/src/__tests__/web-fetch-download.test.ts +0 -433
- package/src/__tests__/web-tools.test.ts +0 -619
- package/src/ask-user-interaction.ts +0 -33
- package/src/cache/web-cache.ts +0 -110
- package/src/definitions/arion.ts +0 -118
- package/src/definitions/browser/browser.ts +0 -502
- package/src/definitions/browser/index.ts +0 -5
- package/src/definitions/browser/pw-downloads.ts +0 -142
- package/src/definitions/browser/pw-interactions.ts +0 -282
- package/src/definitions/browser/pw-responses.ts +0 -98
- package/src/definitions/browser/pw-session.ts +0 -405
- package/src/definitions/browser/pw-shared.ts +0 -85
- package/src/definitions/browser/pw-snapshot.ts +0 -383
- package/src/definitions/browser/pw-state.ts +0 -101
- package/src/definitions/browser/types.ts +0 -203
- package/src/definitions/code-intelligence.ts +0 -526
- package/src/definitions/core.ts +0 -118
- package/src/definitions/delegation.ts +0 -567
- package/src/definitions/deploy.ts +0 -73
- package/src/definitions/filesystem.ts +0 -217
- package/src/definitions/frg.ts +0 -67
- package/src/definitions/index.ts +0 -28
- package/src/definitions/memory.ts +0 -150
- package/src/definitions/messaging.ts +0 -734
- package/src/definitions/meta.ts +0 -392
- package/src/definitions/network.ts +0 -179
- package/src/definitions/outlook.ts +0 -318
- package/src/definitions/patch/apply-patch.ts +0 -235
- package/src/definitions/patch/fuzzy-match.ts +0 -217
- package/src/definitions/patch/index.ts +0 -1
- package/src/definitions/patch/patch-parser.ts +0 -297
- package/src/definitions/patch/sandbox-paths.ts +0 -129
- package/src/definitions/process/index.ts +0 -5
- package/src/definitions/process/process-registry.ts +0 -303
- package/src/definitions/process/process.ts +0 -456
- package/src/definitions/process/pty-keys.ts +0 -298
- package/src/definitions/process/session-slug.ts +0 -147
- package/src/definitions/quip.ts +0 -225
- package/src/definitions/search.ts +0 -67
- package/src/definitions/session-history.ts +0 -79
- package/src/definitions/shell.ts +0 -202
- package/src/definitions/slack.ts +0 -211
- package/src/definitions/web.ts +0 -119
- package/src/executors/apply-patch.ts +0 -1035
- package/src/executors/arion.ts +0 -199
- package/src/executors/code-intelligence.ts +0 -1179
- package/src/executors/deploy.ts +0 -1066
- package/src/executors/filesystem.ts +0 -1428
- package/src/executors/frg-freshness.ts +0 -743
- package/src/executors/frg.ts +0 -394
- package/src/executors/index.ts +0 -280
- package/src/executors/learning-meta.ts +0 -1367
- package/src/executors/lsp-client.ts +0 -355
- package/src/executors/memory.ts +0 -978
- package/src/executors/meta.ts +0 -293
- package/src/executors/process-registry.ts +0 -570
- package/src/executors/pty-session-store.ts +0 -43
- package/src/executors/pty.ts +0 -342
- package/src/executors/restart.ts +0 -133
- package/src/executors/search-freshness.ts +0 -249
- package/src/executors/search-types.ts +0 -98
- package/src/executors/search.ts +0 -89
- package/src/executors/self-diagnose.ts +0 -552
- package/src/executors/session-history.ts +0 -435
- package/src/executors/shell-safety.ts +0 -519
- package/src/executors/shell.ts +0 -1243
- package/src/executors/utils.ts +0 -40
- package/src/executors/web.ts +0 -786
- package/src/extraction/content-extraction.ts +0 -281
- package/src/extraction/index.ts +0 -5
- package/src/headless-control-contract.ts +0 -1149
- package/src/index.ts +0 -788
- package/src/local-control-http-auth.ts +0 -2
- package/src/mcp/client.ts +0 -218
- package/src/mcp/connection.ts +0 -568
- package/src/mcp/index.ts +0 -11
- package/src/mcp/jsonrpc.ts +0 -195
- package/src/mcp/types.ts +0 -199
- package/src/network-control-adapter.ts +0 -88
- package/src/network-runtime/address-types.ts +0 -218
- package/src/network-runtime/db-owner-fencing.ts +0 -91
- package/src/network-runtime/delivery-receipts.ts +0 -372
- package/src/network-runtime/direct-endpoint-authority.ts +0 -35
- package/src/network-runtime/index.ts +0 -316
- package/src/network-runtime/local-control-contract.ts +0 -784
- package/src/network-runtime/node-store-contract.ts +0 -46
- package/src/network-runtime/pair-route-contract.ts +0 -97
- package/src/network-runtime/peer-capabilities.ts +0 -48
- package/src/network-runtime/peer-principal-ref.ts +0 -20
- package/src/network-runtime/peer-state-machine.ts +0 -160
- package/src/network-runtime/protocol-schemas.ts +0 -265
- package/src/network-runtime/runtime-bootstrap-contract.ts +0 -83
- package/src/outlook/desktop-session.ts +0 -409
- package/src/policy.ts +0 -171
- package/src/providers/brave.ts +0 -80
- package/src/providers/duckduckgo.ts +0 -199
- package/src/providers/exa.ts +0 -85
- package/src/providers/firecrawl.ts +0 -77
- package/src/providers/index.ts +0 -8
- package/src/providers/jina.ts +0 -70
- package/src/providers/router.ts +0 -121
- package/src/providers/search-provider.ts +0 -74
- package/src/providers/tavily.ts +0 -74
- package/src/quip/desktop-session.ts +0 -435
- package/src/registry/index.ts +0 -1
- package/src/registry/registry.ts +0 -905
- package/src/runtime-socket-local-control-client.ts +0 -632
- package/src/security/dns-normalization.ts +0 -34
- package/src/security/dns-pinning.ts +0 -138
- package/src/security/external-content.ts +0 -129
- package/src/security/ssrf.ts +0 -207
- package/src/slack/desktop-session.ts +0 -493
- package/src/tool-factory.ts +0 -91
- package/src/types.ts +0 -1341
- package/src/utils/retry.ts +0 -163
- package/src/utils/safe-parse-json.ts +0 -176
- package/src/utils/url.ts +0 -20
- package/tests/benchmarks/registry.bench.ts +0 -57
- package/tests/cache/web-cache.test.ts +0 -147
- package/tests/critical-integration.test.ts +0 -1465
- package/tests/definitions/apply-patch.test.ts +0 -586
- package/tests/definitions/browser.test.ts +0 -495
- package/tests/definitions/delegation-pause-resume.test.ts +0 -758
- package/tests/definitions/execution.test.ts +0 -671
- package/tests/definitions/messaging-inbox-scope.test.ts +0 -229
- package/tests/definitions/messaging.test.ts +0 -1468
- package/tests/definitions/outlook.test.ts +0 -30
- package/tests/definitions/process.test.ts +0 -469
- package/tests/definitions/slack.test.ts +0 -28
- package/tests/definitions/tool-inventory.test.ts +0 -218
- package/tests/e2e/delegation-quest-orchestration.e2e.test.ts +0 -433
- package/tests/e2e/memory-tool-discovery-contract.e2e.test.ts +0 -81
- package/tests/executors/apply-patch.test.ts +0 -538
- package/tests/executors/arion.test.ts +0 -309
- package/tests/executors/conversation-primitives.test.ts +0 -250
- package/tests/executors/deploy.test.ts +0 -746
- package/tests/executors/filesystem-tools.test.ts +0 -357
- package/tests/executors/filesystem.test.ts +0 -959
- package/tests/executors/frg-freshness.test.ts +0 -136
- package/tests/executors/frg-merge.test.ts +0 -70
- package/tests/executors/frg-session-content.test.ts +0 -40
- package/tests/executors/frg.test.ts +0 -56
- package/tests/executors/memory-bugfixes.test.ts +0 -257
- package/tests/executors/memory-real-memoria.integration.test.ts +0 -316
- package/tests/executors/memory.test.ts +0 -853
- package/tests/executors/meta-tools.test.ts +0 -411
- package/tests/executors/meta.test.ts +0 -683
- package/tests/executors/path-containment.test.ts +0 -51
- package/tests/executors/process-registry.test.ts +0 -505
- package/tests/executors/pty.test.ts +0 -664
- package/tests/executors/quest-security.test.ts +0 -249
- package/tests/executors/read-file-media.test.ts +0 -230
- package/tests/executors/recall-knowledge-schema.test.ts +0 -209
- package/tests/executors/recall-tags.test.ts +0 -278
- package/tests/executors/remember-null-safety.contract.test.ts +0 -41
- package/tests/executors/restart.test.ts +0 -67
- package/tests/executors/search-unified.test.ts +0 -381
- package/tests/executors/session-history.test.ts +0 -340
- package/tests/executors/session-transcript.test.ts +0 -561
- package/tests/executors/shell-abort.test.ts +0 -416
- package/tests/executors/shell-env-blocklist.test.ts +0 -648
- package/tests/executors/shell-env-process.test.ts +0 -245
- package/tests/executors/shell-process-registry.test.ts +0 -334
- package/tests/executors/shell-tools.test.ts +0 -393
- package/tests/executors/shell.test.ts +0 -690
- package/tests/executors/web-abort-vs-timeout.test.ts +0 -213
- package/tests/executors/web-integration.test.ts +0 -633
- package/tests/executors/web-symlink.test.ts +0 -18
- package/tests/executors/web.test.ts +0 -1400
- package/tests/executors/write-stdin.test.ts +0 -145
- package/tests/extraction/content-extraction.test.ts +0 -153
- package/tests/guards/tools-default-test-lane.integration.test.ts +0 -21
- package/tests/guards/tools-package-test-commands.e2e.test.ts +0 -43
- package/tests/guards/tools-test-lane-manifest.contract.test.ts +0 -76
- package/tests/guards/tools-vitest-workspace-alias.contract.test.ts +0 -63
- package/tests/helpers/async-waits.ts +0 -53
- package/tests/integration/headless-control-contract.integration.test.ts +0 -153
- package/tests/integration/memory-tool-schema-parity.integration.test.ts +0 -67
- package/tests/integration/meta-tools-round-trip.integration.test.ts +0 -506
- package/tests/integration/quest-round-trip.test.ts +0 -303
- package/tests/integration/registry-executor-flow.test.ts +0 -85
- package/tests/integration.test.ts +0 -177
- package/tests/loading-tier.test.ts +0 -126
- package/tests/mcp/client-reconnect.test.ts +0 -267
- package/tests/mcp/connection.test.ts +0 -846
- package/tests/mcp/injectable-logger.test.ts +0 -83
- package/tests/mcp/jsonrpc.test.ts +0 -109
- package/tests/mcp/lifecycle.test.ts +0 -879
- package/tests/network-runtime/address-types.contract.test.ts +0 -143
- package/tests/network-runtime/continuity-bind-schema.contract.test.ts +0 -203
- package/tests/network-runtime/local-control-contract.test.ts +0 -869
- package/tests/network-runtime/local-control-invite-token.contract.test.ts +0 -146
- package/tests/network-runtime/node-store-contract.test.ts +0 -11
- package/tests/network-runtime/pair-protocol-nodeid.contract.test.ts +0 -15
- package/tests/network-runtime/peer-state-machine.contract.test.ts +0 -148
- package/tests/network-runtime/protocol-schemas.contract.test.ts +0 -512
- package/tests/network-runtime/relay-pending-nodeid.contract.test.ts +0 -62
- package/tests/network-runtime/runtime-bootstrap-contract.test.ts +0 -227
- package/tests/network-runtime/runtime-socket-local-control-client.test.ts +0 -621
- package/tests/network-runtime/wait-for-message-script.test.ts +0 -288
- package/tests/parallel.test.ts +0 -71
- package/tests/policy.test.ts +0 -184
- package/tests/print-default-test-lane.ts +0 -14
- package/tests/print-test-lane-manifest.ts +0 -22
- package/tests/providers/brave.test.ts +0 -159
- package/tests/providers/duckduckgo.test.ts +0 -207
- package/tests/providers/exa.test.ts +0 -175
- package/tests/providers/firecrawl.test.ts +0 -168
- package/tests/providers/jina.test.ts +0 -144
- package/tests/providers/router.test.ts +0 -328
- package/tests/providers/tavily.test.ts +0 -165
- package/tests/registry/discovery.test.ts +0 -154
- package/tests/registry/injectable-logger.test.ts +0 -230
- package/tests/registry/input-validation.test.ts +0 -361
- package/tests/registry/interface-completeness.test.ts +0 -85
- package/tests/registry/mcp-integration.test.ts +0 -103
- package/tests/registry/mcp-read-only-hint.test.ts +0 -60
- package/tests/registry/memoria-discovery.test.ts +0 -390
- package/tests/registry/nested-validation.test.ts +0 -283
- package/tests/registry/pseudo-tool-filtering.test.ts +0 -258
- package/tests/registry/registration-lifecycle.test.ts +0 -133
- package/tests/registry-validation.test.ts +0 -424
- package/tests/registry.test.ts +0 -460
- package/tests/security/dns-pinning.test.ts +0 -162
- package/tests/security/external-content.test.ts +0 -144
- package/tests/security/ssrf.test.ts +0 -118
- package/tests/shell-safety-integration.test.ts +0 -32
- package/tests/shell-safety.test.ts +0 -365
- package/tests/slack/desktop-session.test.ts +0 -50
- package/tests/test-lane-manifest.ts +0 -440
- package/tests/test-utils.ts +0 -27
- package/tests/tool-factory.test.ts +0 -188
- package/tests/utils/retry.test.ts +0 -231
- package/tests/utils/url.test.ts +0 -63
- package/tsconfig.cjs.json +0 -24
- package/tsconfig.json +0 -12
- package/vitest.config.ts +0 -55
- package/vitest.e2e.config.ts +0 -24
- package/vitest.integration.config.ts +0 -24
- package/vitest.native.config.ts +0 -24
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
-
import * as fs from "node:fs/promises";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import * as os from "node:os";
|
|
5
|
-
import * as filesystemExecutors from "../../src/executors/filesystem.js";
|
|
6
|
-
import type { ToolContext } from "../../src/types.js";
|
|
7
|
-
|
|
8
|
-
const { executeReadFile, executeWriteFile, executeGlob, executeLs } = filesystemExecutors;
|
|
9
|
-
|
|
10
|
-
describe("Filesystem Tool Executors", () => {
|
|
11
|
-
let tempDir: string;
|
|
12
|
-
let mockContext: ToolContext;
|
|
13
|
-
|
|
14
|
-
beforeEach(async () => {
|
|
15
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "aria-fs-test-"));
|
|
16
|
-
mockContext = {
|
|
17
|
-
workingDir: tempDir,
|
|
18
|
-
env: {},
|
|
19
|
-
confirm: async () => true,
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
afterEach(async () => {
|
|
24
|
-
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe("executeReadFile", () => {
|
|
28
|
-
it("should read file successfully", async () => {
|
|
29
|
-
const filePath = path.join(tempDir, "test.txt");
|
|
30
|
-
await fs.writeFile(filePath, "Hello, World!");
|
|
31
|
-
|
|
32
|
-
const result = await executeReadFile({ path: "test.txt" }, mockContext);
|
|
33
|
-
|
|
34
|
-
expect(result.success).toBe(true);
|
|
35
|
-
expect(result.data).toBe("Hello, World!");
|
|
36
|
-
expect(result.message).toMatch(/Read \d+ characters/);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("should handle file not found", async () => {
|
|
40
|
-
const result = await executeReadFile({ path: "nonexistent.txt" }, mockContext);
|
|
41
|
-
|
|
42
|
-
expect(result.success).toBe(false);
|
|
43
|
-
expect(result.message).toMatch(/ENOENT|no such file/i);
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it("should reject reading directories", async () => {
|
|
47
|
-
const dirPath = path.join(tempDir, "testdir");
|
|
48
|
-
await fs.mkdir(dirPath);
|
|
49
|
-
|
|
50
|
-
const result = await executeReadFile({ path: "testdir" }, mockContext);
|
|
51
|
-
|
|
52
|
-
expect(result.success).toBe(false);
|
|
53
|
-
expect(result.message).toContain("directory");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should support explicit text encoding", async () => {
|
|
57
|
-
const filePath = path.join(tempDir, "utf16.txt");
|
|
58
|
-
const expected = "Hello µ";
|
|
59
|
-
await fs.writeFile(filePath, Buffer.from(expected, "utf16le"));
|
|
60
|
-
|
|
61
|
-
const result = await executeReadFile({ path: "utf16.txt", encoding: "utf16le" }, mockContext);
|
|
62
|
-
|
|
63
|
-
expect(result.success).toBe(true);
|
|
64
|
-
expect(result.data).toBe(expected);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("should reject unsupported encodings", async () => {
|
|
68
|
-
const filePath = path.join(tempDir, "text.txt");
|
|
69
|
-
await fs.writeFile(filePath, "hello");
|
|
70
|
-
|
|
71
|
-
const result = await executeReadFile({ path: "text.txt", encoding: "utf32" }, mockContext);
|
|
72
|
-
|
|
73
|
-
expect(result.success).toBe(false);
|
|
74
|
-
expect(result.message).toContain("Unsupported encoding");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("should enforce media size cap even with non-utf8 encoding", async () => {
|
|
78
|
-
const filePath = path.join(tempDir, "too-large.pdf");
|
|
79
|
-
await fs.writeFile(filePath, Buffer.alloc(10 * 1024 * 1024 + 1));
|
|
80
|
-
|
|
81
|
-
const result = await executeReadFile(
|
|
82
|
-
{ path: "too-large.pdf", encoding: "latin1" },
|
|
83
|
-
mockContext,
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
expect(result.success).toBe(false);
|
|
87
|
-
expect(result.message).toContain("File too large for media reading");
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
describe("executeWriteFile", () => {
|
|
92
|
-
it("should write file successfully", async () => {
|
|
93
|
-
const result = await executeWriteFile(
|
|
94
|
-
{ path: "new.txt", content: "New content" },
|
|
95
|
-
mockContext,
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
expect(result.success).toBe(true);
|
|
99
|
-
|
|
100
|
-
const written = await fs.readFile(path.join(tempDir, "new.txt"), "utf-8");
|
|
101
|
-
expect(written).toBe("New content");
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("should overwrite existing file", async () => {
|
|
105
|
-
const filePath = path.join(tempDir, "existing.txt");
|
|
106
|
-
await fs.writeFile(filePath, "Old content");
|
|
107
|
-
|
|
108
|
-
const result = await executeWriteFile(
|
|
109
|
-
{ path: "existing.txt", content: "New content" },
|
|
110
|
-
mockContext,
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
expect(result.success).toBe(true);
|
|
114
|
-
|
|
115
|
-
const written = await fs.readFile(filePath, "utf-8");
|
|
116
|
-
expect(written).toBe("New content");
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it("should support explicit write encoding", async () => {
|
|
120
|
-
const expected = "Hello µ";
|
|
121
|
-
const result = await executeWriteFile(
|
|
122
|
-
{ path: "utf16-write.txt", content: expected, encoding: "utf16le" },
|
|
123
|
-
mockContext,
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
expect(result.success).toBe(true);
|
|
127
|
-
|
|
128
|
-
const raw = await fs.readFile(path.join(tempDir, "utf16-write.txt"));
|
|
129
|
-
expect(raw.equals(Buffer.from(expected, "utf16le"))).toBe(true);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe("executeGlob", () => {
|
|
134
|
-
it("should support ignore patterns", async () => {
|
|
135
|
-
await fs.mkdir(path.join(tempDir, "src"), { recursive: true });
|
|
136
|
-
await fs.mkdir(path.join(tempDir, "node_modules"), { recursive: true });
|
|
137
|
-
await fs.writeFile(path.join(tempDir, "src", "keep.ts"), "keep");
|
|
138
|
-
await fs.writeFile(path.join(tempDir, "node_modules", "skip.ts"), "skip");
|
|
139
|
-
|
|
140
|
-
const result = await executeGlob(
|
|
141
|
-
{ pattern: "**/*.ts", ignore: ["node_modules/**"] },
|
|
142
|
-
mockContext,
|
|
143
|
-
);
|
|
144
|
-
|
|
145
|
-
expect(result.success).toBe(true);
|
|
146
|
-
expect(result.data).toEqual(["src/keep.ts"]);
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
describe("executeLs", () => {
|
|
151
|
-
it("should hide dotfiles unless all=true", async () => {
|
|
152
|
-
await fs.writeFile(path.join(tempDir, ".env"), "SECRET=1");
|
|
153
|
-
await fs.writeFile(path.join(tempDir, "visible.txt"), "ok");
|
|
154
|
-
|
|
155
|
-
const defaultResult = await executeLs({ path: "." }, mockContext);
|
|
156
|
-
expect(defaultResult.success).toBe(true);
|
|
157
|
-
const defaultEntries = (defaultResult.data as { entries: Array<{ name: string }> }).entries;
|
|
158
|
-
expect(defaultEntries.some((entry) => entry.name === ".env")).toBe(false);
|
|
159
|
-
expect(defaultEntries.some((entry) => entry.name === "visible.txt")).toBe(true);
|
|
160
|
-
|
|
161
|
-
const allResult = await executeLs({ path: ".", all: true }, mockContext);
|
|
162
|
-
expect(allResult.success).toBe(true);
|
|
163
|
-
const allEntries = (allResult.data as { entries: Array<{ name: string }> }).entries;
|
|
164
|
-
expect(allEntries.some((entry) => entry.name === ".env")).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
it("should include long metadata when long=true", async () => {
|
|
168
|
-
await fs.writeFile(path.join(tempDir, "file.txt"), "abc");
|
|
169
|
-
|
|
170
|
-
const result = await executeLs({ path: ".", all: true, long: true }, mockContext);
|
|
171
|
-
|
|
172
|
-
expect(result.success).toBe(true);
|
|
173
|
-
const entries = (result.data as { entries: Array<Record<string, unknown>> }).entries;
|
|
174
|
-
const fileEntry = entries.find((entry) => entry.name === "file.txt");
|
|
175
|
-
expect(fileEntry).toBeDefined();
|
|
176
|
-
expect(typeof fileEntry?.size).toBe("number");
|
|
177
|
-
expect(typeof fileEntry?.mtimeMs).toBe("number");
|
|
178
|
-
expect(typeof fileEntry?.modifiedAt).toBe("string");
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it("should return entries in deterministic name order", async () => {
|
|
182
|
-
await fs.writeFile(path.join(tempDir, "zeta.txt"), "z");
|
|
183
|
-
await fs.writeFile(path.join(tempDir, "alpha.txt"), "a");
|
|
184
|
-
await fs.mkdir(path.join(tempDir, "beta"));
|
|
185
|
-
|
|
186
|
-
const result = await executeLs({ path: ".", all: true }, mockContext);
|
|
187
|
-
|
|
188
|
-
expect(result.success).toBe(true);
|
|
189
|
-
const names = (result.data as { entries: Array<{ name: string }> }).entries.map(
|
|
190
|
-
(entry) => entry.name,
|
|
191
|
-
);
|
|
192
|
-
expect(names).toEqual(["alpha.txt", "beta", "zeta.txt"]);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
describe("executeLs", () => {
|
|
197
|
-
it("should default to cwd and hide dotfiles", async () => {
|
|
198
|
-
await fs.writeFile(path.join(tempDir, "visible.txt"), "visible");
|
|
199
|
-
await fs.writeFile(path.join(tempDir, ".hidden.txt"), "hidden");
|
|
200
|
-
|
|
201
|
-
const result = await executeLs({}, mockContext);
|
|
202
|
-
|
|
203
|
-
expect(result.success).toBe(true);
|
|
204
|
-
const entries = (result.data as { entries: Array<{ name: string }> }).entries;
|
|
205
|
-
const names = entries.map((entry) => entry.name);
|
|
206
|
-
expect(names).toContain("visible.txt");
|
|
207
|
-
expect(names).not.toContain(".hidden.txt");
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it("should include dotfiles when all is true", async () => {
|
|
211
|
-
await fs.writeFile(path.join(tempDir, "visible.txt"), "visible");
|
|
212
|
-
await fs.writeFile(path.join(tempDir, ".hidden.txt"), "hidden");
|
|
213
|
-
|
|
214
|
-
const result = await executeLs({ all: true, path: "." }, mockContext);
|
|
215
|
-
|
|
216
|
-
expect(result.success).toBe(true);
|
|
217
|
-
const entries = (result.data as { entries: Array<{ name: string }> }).entries;
|
|
218
|
-
const names = entries.map((entry) => entry.name);
|
|
219
|
-
expect(names).toContain("visible.txt");
|
|
220
|
-
expect(names).toContain(".hidden.txt");
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it("should return long metadata when long is true", async () => {
|
|
224
|
-
await fs.writeFile(path.join(tempDir, "alpha.txt"), "a");
|
|
225
|
-
await fs.mkdir(path.join(tempDir, "beta-dir"));
|
|
226
|
-
|
|
227
|
-
const result = await executeLs({ path: ".", long: true }, mockContext);
|
|
228
|
-
|
|
229
|
-
expect(result.success).toBe(true);
|
|
230
|
-
const entries = (
|
|
231
|
-
result.data as {
|
|
232
|
-
entries: Array<{
|
|
233
|
-
name: string;
|
|
234
|
-
type: string;
|
|
235
|
-
size: number;
|
|
236
|
-
mode: string;
|
|
237
|
-
mtimeMs: number;
|
|
238
|
-
}>;
|
|
239
|
-
}
|
|
240
|
-
).entries;
|
|
241
|
-
expect(entries.map((entry) => entry.name)).toEqual(["alpha.txt", "beta-dir"]);
|
|
242
|
-
expect(entries).toContainEqual(
|
|
243
|
-
expect.objectContaining({
|
|
244
|
-
name: "alpha.txt",
|
|
245
|
-
type: "file",
|
|
246
|
-
size: expect.any(Number),
|
|
247
|
-
mode: expect.any(String),
|
|
248
|
-
mtimeMs: expect.any(Number),
|
|
249
|
-
}),
|
|
250
|
-
);
|
|
251
|
-
expect(entries).toContainEqual(
|
|
252
|
-
expect.objectContaining({
|
|
253
|
-
name: "beta-dir",
|
|
254
|
-
type: "directory",
|
|
255
|
-
size: expect.any(Number),
|
|
256
|
-
mode: expect.any(String),
|
|
257
|
-
mtimeMs: expect.any(Number),
|
|
258
|
-
}),
|
|
259
|
-
);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it("should continue long listing when one metadata lookup fails", async () => {
|
|
263
|
-
await fs.writeFile(path.join(tempDir, "alpha.txt"), "a");
|
|
264
|
-
await fs.writeFile(path.join(tempDir, "beta.txt"), "b");
|
|
265
|
-
|
|
266
|
-
const realReadMetadata = filesystemExecutors.LS_INTERNALS.readMetadata;
|
|
267
|
-
const metadataSpy = vi
|
|
268
|
-
.spyOn(filesystemExecutors.LS_INTERNALS, "readMetadata")
|
|
269
|
-
.mockImplementation(async (targetPath) => {
|
|
270
|
-
if (String(targetPath).endsWith("beta.txt")) {
|
|
271
|
-
const err = new Error("Permission denied") as NodeJS.ErrnoException;
|
|
272
|
-
err.code = "EACCES";
|
|
273
|
-
throw err;
|
|
274
|
-
}
|
|
275
|
-
return realReadMetadata(targetPath);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
try {
|
|
279
|
-
const result = await executeLs({ path: ".", long: true }, mockContext);
|
|
280
|
-
|
|
281
|
-
expect(result.success).toBe(true);
|
|
282
|
-
const entries = (
|
|
283
|
-
result.data as {
|
|
284
|
-
entries: Array<{
|
|
285
|
-
name: string;
|
|
286
|
-
size?: number;
|
|
287
|
-
mode?: string;
|
|
288
|
-
mtimeMs?: number;
|
|
289
|
-
}>;
|
|
290
|
-
}
|
|
291
|
-
).entries;
|
|
292
|
-
expect(entries.map((entry) => entry.name)).toEqual(["alpha.txt", "beta.txt"]);
|
|
293
|
-
expect(entries.find((entry) => entry.name === "alpha.txt")).toEqual(
|
|
294
|
-
expect.objectContaining({
|
|
295
|
-
size: expect.any(Number),
|
|
296
|
-
mode: expect.any(String),
|
|
297
|
-
mtimeMs: expect.any(Number),
|
|
298
|
-
}),
|
|
299
|
-
);
|
|
300
|
-
expect(entries.find((entry) => entry.name === "beta.txt")).toEqual(
|
|
301
|
-
expect.objectContaining({
|
|
302
|
-
name: "beta.txt",
|
|
303
|
-
}),
|
|
304
|
-
);
|
|
305
|
-
expect(entries.find((entry) => entry.name === "beta.txt")?.size).toBeUndefined();
|
|
306
|
-
} finally {
|
|
307
|
-
metadataSpy.mockRestore();
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it("should skip entries that disappear before metadata read", async () => {
|
|
312
|
-
await fs.writeFile(path.join(tempDir, "alpha.txt"), "a");
|
|
313
|
-
await fs.writeFile(path.join(tempDir, "gone.txt"), "gone");
|
|
314
|
-
|
|
315
|
-
const realReadMetadata = filesystemExecutors.LS_INTERNALS.readMetadata;
|
|
316
|
-
const metadataSpy = vi
|
|
317
|
-
.spyOn(filesystemExecutors.LS_INTERNALS, "readMetadata")
|
|
318
|
-
.mockImplementation(async (targetPath) => {
|
|
319
|
-
if (String(targetPath).endsWith("gone.txt")) {
|
|
320
|
-
const err = new Error("No such file or directory") as NodeJS.ErrnoException;
|
|
321
|
-
err.code = "ENOENT";
|
|
322
|
-
throw err;
|
|
323
|
-
}
|
|
324
|
-
return realReadMetadata(targetPath);
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
try {
|
|
328
|
-
const result = await executeLs({ path: ".", long: true }, mockContext);
|
|
329
|
-
|
|
330
|
-
expect(result.success).toBe(true);
|
|
331
|
-
const entries = (result.data as { entries: Array<{ name: string }> }).entries;
|
|
332
|
-
expect(entries.map((entry) => entry.name)).toEqual(["alpha.txt"]);
|
|
333
|
-
} finally {
|
|
334
|
-
metadataSpy.mockRestore();
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
it("ls should return structured contract with pagination metadata", async () => {
|
|
339
|
-
await fs.mkdir(path.join(tempDir, "nested"), { recursive: true });
|
|
340
|
-
await fs.writeFile(path.join(tempDir, "nested", "file.txt"), "x");
|
|
341
|
-
|
|
342
|
-
const result = await executeLs(
|
|
343
|
-
{ path: ".", depth: 2, limit: 1, offset: 0, ignore: [] },
|
|
344
|
-
mockContext,
|
|
345
|
-
);
|
|
346
|
-
expect(result.success).toBe(true);
|
|
347
|
-
expect(result.data).toMatchObject({
|
|
348
|
-
depth: 2,
|
|
349
|
-
limit: 1,
|
|
350
|
-
offset: 0,
|
|
351
|
-
ignore: [],
|
|
352
|
-
truncated: expect.any(Boolean),
|
|
353
|
-
entries: expect.any(Array),
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
});
|
|
357
|
-
});
|