@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,393 +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 {
|
|
6
|
-
executeBash,
|
|
7
|
-
executeSpawn,
|
|
8
|
-
executeKill,
|
|
9
|
-
executeListProcesses,
|
|
10
|
-
executeWaitProcess,
|
|
11
|
-
} from "../../src/executors/shell.js";
|
|
12
|
-
import { SpawnedProcessRegistry } from "../../src/executors/process-registry.js";
|
|
13
|
-
import { PTYSessionStore } from "../../src/executors/pty-session-store.js";
|
|
14
|
-
import * as ptyModule from "../../src/executors/pty.js";
|
|
15
|
-
import type { ToolContext } from "../../src/types.js";
|
|
16
|
-
|
|
17
|
-
describe("Shell Tool Executors", () => {
|
|
18
|
-
let tempDir: string;
|
|
19
|
-
let mockContext: ToolContext;
|
|
20
|
-
const pidsToCleanup: number[] = [];
|
|
21
|
-
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "aria-shell-test-"));
|
|
24
|
-
mockContext = {
|
|
25
|
-
workingDir: tempDir,
|
|
26
|
-
env: {},
|
|
27
|
-
confirm: async () => true,
|
|
28
|
-
};
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
afterEach(async () => {
|
|
32
|
-
for (const pid of pidsToCleanup) {
|
|
33
|
-
try {
|
|
34
|
-
process.kill(pid, "SIGKILL");
|
|
35
|
-
} catch {
|
|
36
|
-
// Process may already be dead
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
pidsToCleanup.length = 0;
|
|
40
|
-
await fs.rm(tempDir, { recursive: true, force: true }).catch(() => {});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe("executeBash", () => {
|
|
44
|
-
it("should execute command and return output", async () => {
|
|
45
|
-
const result = await executeBash(
|
|
46
|
-
{ command: 'echo "Hello World"' },
|
|
47
|
-
mockContext,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
expect(result.success).toBe(true);
|
|
51
|
-
expect(result.data).toBeDefined();
|
|
52
|
-
const data = result.data as { stdout: string };
|
|
53
|
-
expect(data.stdout).toContain("Hello World");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("should handle command failures", async () => {
|
|
57
|
-
const result = await executeBash({ command: "exit 1" }, mockContext);
|
|
58
|
-
|
|
59
|
-
expect(result.success).toBe(false);
|
|
60
|
-
expect(result.message).toMatch(/exit.*code 1|failed/i);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("should respect timeout", async () => {
|
|
64
|
-
const result = await executeBash(
|
|
65
|
-
{ command: "sleep 10", timeout: 100 },
|
|
66
|
-
mockContext,
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
expect(result.success).toBe(false);
|
|
70
|
-
expect(result.message).toMatch(/timed? ?out|SIGTERM/i);
|
|
71
|
-
}, 5000);
|
|
72
|
-
|
|
73
|
-
it("should set working directory", async () => {
|
|
74
|
-
const subDir = path.join(tempDir, "subdir");
|
|
75
|
-
await fs.mkdir(subDir);
|
|
76
|
-
|
|
77
|
-
const result = await executeBash(
|
|
78
|
-
{ command: "pwd" },
|
|
79
|
-
{ ...mockContext, workingDir: subDir },
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
expect(result.success).toBe(true);
|
|
83
|
-
expect(result.data).toBeDefined();
|
|
84
|
-
const data = result.data as { stdout: string };
|
|
85
|
-
expect(data.stdout).toContain("subdir");
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
it("should pass custom environment variables to command", async () => {
|
|
89
|
-
const result = await executeBash(
|
|
90
|
-
{
|
|
91
|
-
command: "echo $CUSTOM_VAR",
|
|
92
|
-
env: { CUSTOM_VAR: "test123" },
|
|
93
|
-
},
|
|
94
|
-
mockContext,
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
expect(result.success).toBe(true);
|
|
98
|
-
const data = result.data as { stdout: string; stderr: string };
|
|
99
|
-
expect(data.stdout.trim()).toBe("test123");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("should merge context env with command env", async () => {
|
|
103
|
-
const contextWithEnv: ToolContext = {
|
|
104
|
-
...mockContext,
|
|
105
|
-
env: { BASE_VAR: "base" },
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const result = await executeBash(
|
|
109
|
-
{
|
|
110
|
-
command: "echo $BASE_VAR $CUSTOM_VAR",
|
|
111
|
-
env: { CUSTOM_VAR: "custom" },
|
|
112
|
-
},
|
|
113
|
-
contextWithEnv,
|
|
114
|
-
);
|
|
115
|
-
|
|
116
|
-
expect(result.success).toBe(true);
|
|
117
|
-
const data = result.data as { stdout: string };
|
|
118
|
-
expect(data.stdout.trim()).toBe("base custom");
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
describe("process observability tools", () => {
|
|
123
|
-
it("list_processes should fail when process registry is unavailable", async () => {
|
|
124
|
-
const result = await executeListProcesses({}, mockContext);
|
|
125
|
-
|
|
126
|
-
expect(result.success).toBe(false);
|
|
127
|
-
expect(result.message).toContain("Process registry not available");
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("list_processes should return tracked process metadata", async () => {
|
|
131
|
-
const registry = new SpawnedProcessRegistry();
|
|
132
|
-
const ctxWithRegistry: ToolContext = {
|
|
133
|
-
...mockContext,
|
|
134
|
-
processRegistry: registry,
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const spawnResult = await executeSpawn({ program: "sleep", args: ["60"] }, ctxWithRegistry);
|
|
138
|
-
expect(spawnResult.success).toBe(true);
|
|
139
|
-
|
|
140
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
141
|
-
pidsToCleanup.push(pid);
|
|
142
|
-
|
|
143
|
-
const result = await executeListProcesses({}, ctxWithRegistry);
|
|
144
|
-
expect(result.success).toBe(true);
|
|
145
|
-
|
|
146
|
-
const data = result.data as {
|
|
147
|
-
processes: Array<{
|
|
148
|
-
pid: number;
|
|
149
|
-
command: string;
|
|
150
|
-
args: string[];
|
|
151
|
-
cwd: string;
|
|
152
|
-
status: string;
|
|
153
|
-
}>;
|
|
154
|
-
};
|
|
155
|
-
const processInfo = data.processes.find((p) => p.pid === pid);
|
|
156
|
-
expect(processInfo).toBeDefined();
|
|
157
|
-
expect(processInfo).toMatchObject({
|
|
158
|
-
pid,
|
|
159
|
-
command: "sleep",
|
|
160
|
-
args: ["60"],
|
|
161
|
-
cwd: tempDir,
|
|
162
|
-
status: "running",
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("wait_process should fail when process registry is unavailable", async () => {
|
|
167
|
-
const result = await executeWaitProcess({ pid: 1234, timeoutMs: 100 }, mockContext);
|
|
168
|
-
|
|
169
|
-
expect(result.success).toBe(false);
|
|
170
|
-
expect(result.message).toContain("Process registry not available");
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
it("wait_process should return exit metadata when tracked process exits", async () => {
|
|
174
|
-
const registry = new SpawnedProcessRegistry();
|
|
175
|
-
const ctxWithRegistry: ToolContext = {
|
|
176
|
-
...mockContext,
|
|
177
|
-
processRegistry: registry,
|
|
178
|
-
};
|
|
179
|
-
|
|
180
|
-
const spawnResult = await executeSpawn({ program: "sleep", args: ["1"] }, ctxWithRegistry);
|
|
181
|
-
expect(spawnResult.success).toBe(true);
|
|
182
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
183
|
-
|
|
184
|
-
const result = await executeWaitProcess({ pid, timeoutMs: 5000 }, ctxWithRegistry);
|
|
185
|
-
expect(result.success).toBe(true);
|
|
186
|
-
|
|
187
|
-
const data = result.data as {
|
|
188
|
-
pid: number;
|
|
189
|
-
status: string;
|
|
190
|
-
exited: boolean;
|
|
191
|
-
timedOut: boolean;
|
|
192
|
-
waitedMs: number;
|
|
193
|
-
exitCode: number | null;
|
|
194
|
-
};
|
|
195
|
-
expect(data.pid).toBe(pid);
|
|
196
|
-
expect(data.status).toBe("exited");
|
|
197
|
-
expect(data.exited).toBe(true);
|
|
198
|
-
expect(data.timedOut).toBe(false);
|
|
199
|
-
expect(data.waitedMs).toBeGreaterThanOrEqual(0);
|
|
200
|
-
expect(data.exitCode).toBe(0);
|
|
201
|
-
}, 10000);
|
|
202
|
-
|
|
203
|
-
it("wait_process should timeout for running process", async () => {
|
|
204
|
-
const registry = new SpawnedProcessRegistry();
|
|
205
|
-
const ctxWithRegistry: ToolContext = {
|
|
206
|
-
...mockContext,
|
|
207
|
-
processRegistry: registry,
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
const spawnResult = await executeSpawn({ program: "sleep", args: ["60"] }, ctxWithRegistry);
|
|
211
|
-
expect(spawnResult.success).toBe(true);
|
|
212
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
213
|
-
pidsToCleanup.push(pid);
|
|
214
|
-
|
|
215
|
-
const result = await executeWaitProcess({ pid, timeoutMs: 50 }, ctxWithRegistry);
|
|
216
|
-
expect(result.success).toBe(false);
|
|
217
|
-
|
|
218
|
-
const data = result.data as {
|
|
219
|
-
pid: number;
|
|
220
|
-
status: string;
|
|
221
|
-
exited: boolean;
|
|
222
|
-
timedOut: boolean;
|
|
223
|
-
waitedMs: number;
|
|
224
|
-
};
|
|
225
|
-
expect(data.pid).toBe(pid);
|
|
226
|
-
expect(data.status).toBe("running");
|
|
227
|
-
expect(data.exited).toBe(false);
|
|
228
|
-
expect(data.timedOut).toBe(true);
|
|
229
|
-
expect(data.waitedMs).toBeGreaterThanOrEqual(0);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("wait_process should perform immediate liveness check when timeoutMs is zero", async () => {
|
|
233
|
-
const registry = new SpawnedProcessRegistry();
|
|
234
|
-
const ctxWithRegistry: ToolContext = {
|
|
235
|
-
...mockContext,
|
|
236
|
-
processRegistry: registry,
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
const spawnResult = await executeSpawn({ program: "sleep", args: ["60"] }, ctxWithRegistry);
|
|
240
|
-
expect(spawnResult.success).toBe(true);
|
|
241
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
242
|
-
pidsToCleanup.push(pid);
|
|
243
|
-
|
|
244
|
-
const result = await executeWaitProcess({ pid, timeoutMs: 0 }, ctxWithRegistry);
|
|
245
|
-
expect(result.success).toBe(false);
|
|
246
|
-
expect(result.message).toContain("Timed out waiting");
|
|
247
|
-
|
|
248
|
-
const data = result.data as {
|
|
249
|
-
pid: number;
|
|
250
|
-
status: string;
|
|
251
|
-
exited: boolean;
|
|
252
|
-
timedOut: boolean;
|
|
253
|
-
waitedMs: number;
|
|
254
|
-
};
|
|
255
|
-
expect(data.pid).toBe(pid);
|
|
256
|
-
expect(data.status).toBe("running");
|
|
257
|
-
expect(data.exited).toBe(false);
|
|
258
|
-
expect(data.timedOut).toBe(true);
|
|
259
|
-
expect(data.waitedMs).toBeGreaterThanOrEqual(0);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
it("wait_process should fail with not tracked for unknown pid", async () => {
|
|
263
|
-
const registry = new SpawnedProcessRegistry();
|
|
264
|
-
const ctxWithRegistry: ToolContext = {
|
|
265
|
-
...mockContext,
|
|
266
|
-
processRegistry: registry,
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
const result = await executeWaitProcess({ pid: 999_999, timeoutMs: 0 }, ctxWithRegistry);
|
|
270
|
-
expect(result.success).toBe(false);
|
|
271
|
-
expect(result.message).toContain("not tracked");
|
|
272
|
-
expect(result.data).toMatchObject({
|
|
273
|
-
pid: 999_999,
|
|
274
|
-
exited: false,
|
|
275
|
-
timedOut: false,
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it("interactive PTY process lifecycle should be reflected in list and wait", async () => {
|
|
280
|
-
const registry = new SpawnedProcessRegistry();
|
|
281
|
-
const ptySessionStore = new PTYSessionStore();
|
|
282
|
-
const ctxWithRegistry: ToolContext = {
|
|
283
|
-
...mockContext,
|
|
284
|
-
processRegistry: registry,
|
|
285
|
-
ptySessionStore,
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const fakePid = 424242;
|
|
289
|
-
const fakeSession = {
|
|
290
|
-
pid: fakePid,
|
|
291
|
-
isRunning: true,
|
|
292
|
-
exitCode: undefined as number | undefined,
|
|
293
|
-
output: "",
|
|
294
|
-
write: () => undefined,
|
|
295
|
-
close: () => undefined,
|
|
296
|
-
};
|
|
297
|
-
const createPTYSessionSpy = vi
|
|
298
|
-
.spyOn(ptyModule, "createPTYSession")
|
|
299
|
-
.mockResolvedValue(fakeSession as unknown as Awaited<ReturnType<typeof ptyModule.createPTYSession>>);
|
|
300
|
-
|
|
301
|
-
try {
|
|
302
|
-
const spawnResult = await executeSpawn(
|
|
303
|
-
{
|
|
304
|
-
program: "fake-shell",
|
|
305
|
-
args: ["-lc", "echo interactive-done"],
|
|
306
|
-
interactive: true,
|
|
307
|
-
},
|
|
308
|
-
ctxWithRegistry,
|
|
309
|
-
);
|
|
310
|
-
expect(spawnResult.success).toBe(true);
|
|
311
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
312
|
-
expect(pid).toBe(fakePid);
|
|
313
|
-
|
|
314
|
-
expect(registry.has(pid)).toBe(true);
|
|
315
|
-
expect(ptySessionStore.has(pid)).toBe(true);
|
|
316
|
-
|
|
317
|
-
setTimeout(() => {
|
|
318
|
-
fakeSession.isRunning = false;
|
|
319
|
-
fakeSession.exitCode = 0;
|
|
320
|
-
}, 20);
|
|
321
|
-
|
|
322
|
-
const waitResult = await executeWaitProcess({ pid, timeoutMs: 5000 }, ctxWithRegistry);
|
|
323
|
-
expect(waitResult.success).toBe(true);
|
|
324
|
-
|
|
325
|
-
const waitData = waitResult.data as {
|
|
326
|
-
pid: number;
|
|
327
|
-
status: string;
|
|
328
|
-
exited: boolean;
|
|
329
|
-
interactive: boolean;
|
|
330
|
-
timedOut: boolean;
|
|
331
|
-
waitedMs: number;
|
|
332
|
-
exitCode: number | null;
|
|
333
|
-
};
|
|
334
|
-
expect(waitData.pid).toBe(pid);
|
|
335
|
-
expect(waitData.status).toBe("exited");
|
|
336
|
-
expect(waitData.exited).toBe(true);
|
|
337
|
-
expect(waitData.interactive).toBe(true);
|
|
338
|
-
expect(waitData.timedOut).toBe(false);
|
|
339
|
-
expect(waitData.waitedMs).toBeGreaterThanOrEqual(0);
|
|
340
|
-
expect(waitData.exitCode).toBe(0);
|
|
341
|
-
|
|
342
|
-
// The lifecycle monitor runs asynchronously after PTY exit.
|
|
343
|
-
await new Promise((resolve) => setTimeout(resolve, 120));
|
|
344
|
-
expect(ptySessionStore.has(pid)).toBe(false);
|
|
345
|
-
|
|
346
|
-
const listResult = await executeListProcesses({ includeExited: true }, ctxWithRegistry);
|
|
347
|
-
expect(listResult.success).toBe(true);
|
|
348
|
-
const listData = listResult.data as {
|
|
349
|
-
processes: Array<{ pid: number; status: string; interactive: boolean }>;
|
|
350
|
-
};
|
|
351
|
-
const processInfo = listData.processes.find((process) => process.pid === pid);
|
|
352
|
-
expect(processInfo).toMatchObject({
|
|
353
|
-
pid,
|
|
354
|
-
status: "exited",
|
|
355
|
-
interactive: true,
|
|
356
|
-
});
|
|
357
|
-
} finally {
|
|
358
|
-
createPTYSessionSpy.mockRestore();
|
|
359
|
-
}
|
|
360
|
-
}, 15000);
|
|
361
|
-
|
|
362
|
-
it("kill should keep tracked process for non-terminating signals", async () => {
|
|
363
|
-
const registry = new SpawnedProcessRegistry();
|
|
364
|
-
const ctxWithRegistry: ToolContext = {
|
|
365
|
-
...mockContext,
|
|
366
|
-
processRegistry: registry,
|
|
367
|
-
};
|
|
368
|
-
|
|
369
|
-
const spawnResult = await executeSpawn({ program: "sleep", args: ["60"] }, ctxWithRegistry);
|
|
370
|
-
expect(spawnResult.success).toBe(true);
|
|
371
|
-
const { pid } = spawnResult.data as { pid: number };
|
|
372
|
-
pidsToCleanup.push(pid);
|
|
373
|
-
expect(registry.has(pid)).toBe(true);
|
|
374
|
-
|
|
375
|
-
const killResult = await executeKill({ pid, signal: "SIGCONT" }, ctxWithRegistry);
|
|
376
|
-
expect(killResult.success).toBe(true);
|
|
377
|
-
expect(registry.has(pid)).toBe(true);
|
|
378
|
-
|
|
379
|
-
const waitResult = await executeWaitProcess({ pid, timeoutMs: 50 }, ctxWithRegistry);
|
|
380
|
-
expect(waitResult.success).toBe(false);
|
|
381
|
-
const waitData = waitResult.data as {
|
|
382
|
-
status: string;
|
|
383
|
-
exited: boolean;
|
|
384
|
-
timedOut: boolean;
|
|
385
|
-
waitedMs: number;
|
|
386
|
-
};
|
|
387
|
-
expect(waitData.status).toBe("running");
|
|
388
|
-
expect(waitData.exited).toBe(false);
|
|
389
|
-
expect(waitData.timedOut).toBe(true);
|
|
390
|
-
expect(waitData.waitedMs).toBeGreaterThanOrEqual(0);
|
|
391
|
-
});
|
|
392
|
-
});
|
|
393
|
-
});
|