@renxqoo/renx-code 0.0.4 → 0.0.5

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 (209) hide show
  1. package/bin/renx.cjs +16 -0
  2. package/package.json +2 -45
  3. package/src/agent/runtime/runtime.context-usage.test.ts +4 -5
  4. package/src/agent/runtime/runtime.error-handling.test.ts +4 -5
  5. package/src/agent/runtime/runtime.test.ts +7 -4
  6. package/src/agent/runtime/runtime.ts +3 -9
  7. package/src/agent/runtime/runtime.usage-forwarding.test.ts +4 -5
  8. package/src/agent/runtime/source-modules.test.ts +16 -35
  9. package/src/agent/runtime/source-modules.ts +17 -0
  10. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +95 -0
  11. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +1345 -0
  12. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +1353 -0
  13. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +60 -0
  14. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +278 -0
  15. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +72 -0
  16. package/vendor/agent-root/src/agent/__test__/types.test.ts +137 -0
  17. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +83 -0
  18. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +34 -0
  19. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +323 -0
  20. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +290 -0
  21. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +377 -0
  22. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +212 -0
  23. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +295 -0
  24. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +3607 -0
  25. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +35 -0
  26. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +517 -0
  27. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +97 -0
  28. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +479 -0
  29. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +80 -0
  30. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +76 -0
  31. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +173 -0
  32. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +109 -0
  33. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +71 -0
  34. package/vendor/agent-root/src/agent/agent/callback-safety.ts +33 -0
  35. package/vendor/agent-root/src/agent/agent/compaction.ts +291 -0
  36. package/vendor/agent-root/src/agent/agent/concurrency.ts +103 -0
  37. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +190 -0
  38. package/vendor/agent-root/src/agent/agent/error.ts +198 -0
  39. package/vendor/agent-root/src/agent/agent/index.ts +1772 -0
  40. package/vendor/agent-root/src/agent/agent/logger.ts +65 -0
  41. package/vendor/agent-root/src/agent/agent/message-utils.ts +101 -0
  42. package/vendor/agent-root/src/agent/agent/stream-events.ts +61 -0
  43. package/vendor/agent-root/src/agent/agent/telemetry.ts +123 -0
  44. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +227 -0
  45. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +111 -0
  46. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +164 -0
  47. package/vendor/agent-root/src/agent/agent/write-buffer.ts +188 -0
  48. package/vendor/agent-root/src/agent/agent/write-file-session.ts +238 -0
  49. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +1053 -0
  50. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +158 -0
  51. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +437 -0
  52. package/vendor/agent-root/src/agent/app/agent-app-service.ts +748 -0
  53. package/vendor/agent-root/src/agent/app/contracts.ts +109 -0
  54. package/vendor/agent-root/src/agent/app/index.ts +5 -0
  55. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +151 -0
  56. package/vendor/agent-root/src/agent/app/ports.ts +72 -0
  57. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +1182 -0
  58. package/vendor/agent-root/src/agent/app/sqlite-client.ts +177 -0
  59. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +36 -0
  60. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +33 -0
  61. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +40 -0
  62. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +91 -0
  63. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +116 -0
  64. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +52 -0
  65. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +53 -0
  66. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +52 -0
  67. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +40 -0
  68. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +19 -0
  69. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +28 -0
  70. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +26 -0
  71. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +30 -0
  72. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +567 -0
  73. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +583 -0
  74. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +972 -0
  75. package/vendor/agent-root/src/agent/error-contract.ts +154 -0
  76. package/vendor/agent-root/src/agent/prompts/system.ts +246 -0
  77. package/vendor/agent-root/src/agent/prompts/system1.ts +208 -0
  78. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +98 -0
  79. package/vendor/agent-root/src/agent/storage/file-history-store.ts +313 -0
  80. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +94 -0
  81. package/vendor/agent-root/src/agent/storage/file-system.ts +31 -0
  82. package/vendor/agent-root/src/agent/storage/file-write-service.ts +21 -0
  83. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +413 -0
  84. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +356 -0
  85. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +375 -0
  86. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +372 -0
  87. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +108 -0
  88. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +258 -0
  89. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +121 -0
  90. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +210 -0
  91. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +139 -0
  92. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +456 -0
  93. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +192 -0
  94. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +300 -0
  95. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +214 -0
  96. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +336 -0
  97. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +494 -0
  98. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +543 -0
  99. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +172 -0
  100. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +116 -0
  101. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +267 -0
  102. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +519 -0
  103. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +225 -0
  104. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +223 -0
  105. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +184 -0
  106. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +287 -0
  107. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +190 -0
  108. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +352 -0
  109. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +395 -0
  110. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +391 -0
  111. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +176 -0
  112. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +68 -0
  113. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +630 -0
  114. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +732 -0
  115. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +494 -0
  116. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +175 -0
  117. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +505 -0
  118. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +55 -0
  119. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +244 -0
  120. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +290 -0
  121. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +368 -0
  122. package/vendor/agent-root/src/agent/tool/base-tool.ts +345 -0
  123. package/vendor/agent-root/src/agent/tool/bash-policy.ts +636 -0
  124. package/vendor/agent-root/src/agent/tool/bash.ts +688 -0
  125. package/vendor/agent-root/src/agent/tool/error.ts +131 -0
  126. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +264 -0
  127. package/vendor/agent-root/src/agent/tool/file-history-list.ts +103 -0
  128. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +149 -0
  129. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +211 -0
  130. package/vendor/agent-root/src/agent/tool/glob.ts +171 -0
  131. package/vendor/agent-root/src/agent/tool/grep.ts +496 -0
  132. package/vendor/agent-root/src/agent/tool/lsp.ts +481 -0
  133. package/vendor/agent-root/src/agent/tool/path-security.ts +117 -0
  134. package/vendor/agent-root/src/agent/tool/search/common.ts +153 -0
  135. package/vendor/agent-root/src/agent/tool/skill/index.ts +13 -0
  136. package/vendor/agent-root/src/agent/tool/skill/loader.ts +229 -0
  137. package/vendor/agent-root/src/agent/tool/skill/parser.ts +124 -0
  138. package/vendor/agent-root/src/agent/tool/skill/types.ts +27 -0
  139. package/vendor/agent-root/src/agent/tool/skill-tool.ts +143 -0
  140. package/vendor/agent-root/src/agent/tool/task-create.ts +186 -0
  141. package/vendor/agent-root/src/agent/tool/task-errors.ts +42 -0
  142. package/vendor/agent-root/src/agent/tool/task-get.ts +116 -0
  143. package/vendor/agent-root/src/agent/tool/task-graph.ts +78 -0
  144. package/vendor/agent-root/src/agent/tool/task-list.ts +141 -0
  145. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +232 -0
  146. package/vendor/agent-root/src/agent/tool/task-output.ts +223 -0
  147. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +115 -0
  148. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +336 -0
  149. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +55 -0
  150. package/vendor/agent-root/src/agent/tool/task-stop.ts +187 -0
  151. package/vendor/agent-root/src/agent/tool/task-store.ts +217 -0
  152. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +149 -0
  153. package/vendor/agent-root/src/agent/tool/task-types.ts +264 -0
  154. package/vendor/agent-root/src/agent/tool/task-update.ts +315 -0
  155. package/vendor/agent-root/src/agent/tool/task.ts +209 -0
  156. package/vendor/agent-root/src/agent/tool/tool-manager.ts +362 -0
  157. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +242 -0
  158. package/vendor/agent-root/src/agent/tool/types.ts +116 -0
  159. package/vendor/agent-root/src/agent/tool/web-fetch.ts +227 -0
  160. package/vendor/agent-root/src/agent/tool/web-search.ts +208 -0
  161. package/vendor/agent-root/src/agent/tool/write-file.ts +497 -0
  162. package/vendor/agent-root/src/agent/types.ts +232 -0
  163. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +18 -0
  164. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +610 -0
  165. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +223 -0
  166. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +42 -0
  167. package/vendor/agent-root/src/agent/utils/index.ts +16 -0
  168. package/vendor/agent-root/src/agent/utils/message.ts +171 -0
  169. package/vendor/agent-root/src/agent/utils/token.ts +28 -0
  170. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +129 -0
  171. package/vendor/agent-root/src/config/__tests__/loader.test.ts +247 -0
  172. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +88 -0
  173. package/vendor/agent-root/src/config/index.ts +54 -0
  174. package/vendor/agent-root/src/config/loader.ts +431 -0
  175. package/vendor/agent-root/src/config/paths.ts +30 -0
  176. package/vendor/agent-root/src/config/runtime.ts +163 -0
  177. package/vendor/agent-root/src/config/types.ts +70 -0
  178. package/vendor/agent-root/src/logger/index.ts +57 -0
  179. package/vendor/agent-root/src/logger/logger.ts +819 -0
  180. package/vendor/agent-root/src/logger/types.ts +150 -0
  181. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +441 -0
  182. package/vendor/agent-root/src/providers/__tests__/index.test.ts +16 -0
  183. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +318 -0
  184. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +600 -0
  185. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +449 -0
  186. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +298 -0
  187. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +354 -0
  188. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +58 -0
  189. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +261 -0
  190. package/vendor/agent-root/src/providers/adapters/anthropic.ts +572 -0
  191. package/vendor/agent-root/src/providers/adapters/base.ts +131 -0
  192. package/vendor/agent-root/src/providers/adapters/kimi.ts +48 -0
  193. package/vendor/agent-root/src/providers/adapters/responses.ts +732 -0
  194. package/vendor/agent-root/src/providers/adapters/standard.ts +120 -0
  195. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +313 -0
  196. package/vendor/agent-root/src/providers/http/client.ts +289 -0
  197. package/vendor/agent-root/src/providers/http/stream-parser.ts +109 -0
  198. package/vendor/agent-root/src/providers/index.ts +76 -0
  199. package/vendor/agent-root/src/providers/kimi-headers.ts +177 -0
  200. package/vendor/agent-root/src/providers/openai-compatible.ts +387 -0
  201. package/vendor/agent-root/src/providers/registry/model-config.ts +230 -0
  202. package/vendor/agent-root/src/providers/registry/provider-factory.ts +123 -0
  203. package/vendor/agent-root/src/providers/registry.ts +135 -0
  204. package/vendor/agent-root/src/providers/types/api.ts +284 -0
  205. package/vendor/agent-root/src/providers/types/config.ts +58 -0
  206. package/vendor/agent-root/src/providers/types/errors.ts +323 -0
  207. package/vendor/agent-root/src/providers/types/index.ts +72 -0
  208. package/vendor/agent-root/src/providers/types/provider.ts +45 -0
  209. package/vendor/agent-root/src/providers/types/registry.ts +88 -0
@@ -0,0 +1,336 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import {
6
+ expandHomePath,
7
+ normalizeAllowedDirectories,
8
+ resolveRequestedPath,
9
+ normalizePathWithExistingAncestor,
10
+ isWithinAllowedDirectories,
11
+ assessPathAccess,
12
+ ensurePathWithinAllowed,
13
+ toPosixPath,
14
+ } from '../path-security';
15
+
16
+ describe('expandHomePath', () => {
17
+ it('expands ~ to home directory', () => {
18
+ const result = expandHomePath('~');
19
+ expect(result).toBe(os.homedir());
20
+ });
21
+
22
+ it('expands ~/path to home directory path', () => {
23
+ const result = expandHomePath('~/Documents');
24
+ expect(result).toBe(path.join(os.homedir(), 'Documents'));
25
+ });
26
+
27
+ it('returns absolute path unchanged', () => {
28
+ const absolutePath = '/absolute/path';
29
+ expect(expandHomePath(absolutePath)).toBe(absolutePath);
30
+ });
31
+
32
+ it('returns relative path unchanged', () => {
33
+ const relativePath = 'relative/path';
34
+ expect(expandHomePath(relativePath)).toBe(relativePath);
35
+ });
36
+
37
+ it('handles empty string', () => {
38
+ expect(expandHomePath('')).toBe('');
39
+ });
40
+ });
41
+
42
+ describe('normalizeAllowedDirectories', () => {
43
+ it('returns current working directory when no input', () => {
44
+ const result = normalizeAllowedDirectories();
45
+ expect(result).toEqual([process.cwd()]);
46
+ });
47
+
48
+ it('returns current working directory for empty array', () => {
49
+ const result = normalizeAllowedDirectories([]);
50
+ expect(result).toEqual([process.cwd()]);
51
+ });
52
+
53
+ it('normalizes single directory', () => {
54
+ const result = normalizeAllowedDirectories(['/tmp']);
55
+ expect(result).toHaveLength(1);
56
+ // On macOS, /tmp is a symlink to /private/tmp
57
+ expect(result[0]).toBe(fs.realpathSync('/tmp'));
58
+ });
59
+
60
+ it('normalizes multiple directories', () => {
61
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
62
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
63
+ try {
64
+ const result = normalizeAllowedDirectories([tempDir1, tempDir2]);
65
+ expect(result).toHaveLength(2);
66
+ expect(result).toContain(fs.realpathSync(tempDir1));
67
+ expect(result).toContain(fs.realpathSync(tempDir2));
68
+ } finally {
69
+ fs.rmSync(tempDir1, { recursive: true });
70
+ fs.rmSync(tempDir2, { recursive: true });
71
+ }
72
+ });
73
+
74
+ it('expands home paths', () => {
75
+ const result = normalizeAllowedDirectories(['~/Documents']);
76
+ expect(result).toHaveLength(1);
77
+ expect(result[0]).toBe(fs.realpathSync(path.join(os.homedir(), 'Documents')));
78
+ });
79
+
80
+ it('resolves relative paths', () => {
81
+ const result = normalizeAllowedDirectories(['./relative']);
82
+ expect(result).toHaveLength(1);
83
+ expect(path.isAbsolute(result[0])).toBe(true);
84
+ });
85
+ });
86
+
87
+ describe('resolveRequestedPath', () => {
88
+ it('resolves absolute path', () => {
89
+ const result = resolveRequestedPath('/absolute/path');
90
+ // On Windows, path.resolve converts /absolute/path to D:\absolute\path
91
+ expect(path.isAbsolute(result)).toBe(true);
92
+ expect(result).toContain('absolute');
93
+ expect(result).toContain('path');
94
+ });
95
+
96
+ it('resolves relative path with default base', () => {
97
+ const result = resolveRequestedPath('relative/path');
98
+ expect(result).toBe(path.resolve(process.cwd(), 'relative/path'));
99
+ });
100
+
101
+ it('resolves relative path with custom base', () => {
102
+ const result = resolveRequestedPath('relative/path', '/custom/base');
103
+ expect(result).toBe(path.resolve('/custom/base', 'relative/path'));
104
+ });
105
+
106
+ it('expands home path', () => {
107
+ const result = resolveRequestedPath('~/Documents');
108
+ expect(result).toBe(path.join(os.homedir(), 'Documents'));
109
+ });
110
+
111
+ it('trims whitespace', () => {
112
+ const result = resolveRequestedPath(' /path ');
113
+ // On Windows, path.resolve converts /path to D:\path
114
+ expect(path.isAbsolute(result)).toBe(true);
115
+ expect(result).toContain('path');
116
+ });
117
+ });
118
+
119
+ describe('normalizePathWithExistingAncestor', () => {
120
+ it('returns real path for existing path', () => {
121
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
122
+ try {
123
+ const result = normalizePathWithExistingAncestor(tempDir);
124
+ expect(result).toBe(fs.realpathSync(tempDir));
125
+ } finally {
126
+ fs.rmSync(tempDir, { recursive: true });
127
+ }
128
+ });
129
+
130
+ it('returns resolved path for non-existing path with existing parent', () => {
131
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
132
+ try {
133
+ const nonExisting = path.join(tempDir, 'non-existing');
134
+ const result = normalizePathWithExistingAncestor(nonExisting);
135
+ expect(result).toBe(path.join(fs.realpathSync(tempDir), 'non-existing'));
136
+ } finally {
137
+ fs.rmSync(tempDir, { recursive: true });
138
+ }
139
+ });
140
+
141
+ it('returns absolute path for completely non-existing path', () => {
142
+ const result = normalizePathWithExistingAncestor('/completely/non-existing/path');
143
+ expect(path.isAbsolute(result)).toBe(true);
144
+ });
145
+
146
+ it('handles root directory', () => {
147
+ const result = normalizePathWithExistingAncestor('/');
148
+ // On Windows, root is 'D:\' not '/'
149
+ expect(path.isAbsolute(result)).toBe(true);
150
+ });
151
+ });
152
+
153
+ describe('isWithinAllowedDirectories', () => {
154
+ it('returns true for path within allowed directory', () => {
155
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
156
+ try {
157
+ const subDir = path.join(tempDir, 'subdir');
158
+ fs.mkdirSync(subDir);
159
+
160
+ // Normalize the allowed directories
161
+ const allowedDirs = normalizeAllowedDirectories([tempDir]);
162
+ const result = isWithinAllowedDirectories(subDir, allowedDirs);
163
+ expect(result).toBe(true);
164
+ } finally {
165
+ fs.rmSync(tempDir, { recursive: true });
166
+ }
167
+ });
168
+
169
+ it('returns false for path outside allowed directory', () => {
170
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
171
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
172
+ try {
173
+ // Normalize the allowed directories
174
+ const allowedDirs = normalizeAllowedDirectories([tempDir1]);
175
+ const result = isWithinAllowedDirectories(tempDir2, allowedDirs);
176
+ expect(result).toBe(false);
177
+ } finally {
178
+ fs.rmSync(tempDir1, { recursive: true });
179
+ fs.rmSync(tempDir2, { recursive: true });
180
+ }
181
+ });
182
+
183
+ it('returns true for path equal to allowed directory', () => {
184
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
185
+ try {
186
+ // Normalize the allowed directories
187
+ const allowedDirs = normalizeAllowedDirectories([tempDir]);
188
+ const result = isWithinAllowedDirectories(tempDir, allowedDirs);
189
+ expect(result).toBe(true);
190
+ } finally {
191
+ fs.rmSync(tempDir, { recursive: true });
192
+ }
193
+ });
194
+
195
+ it('checks against multiple allowed directories', () => {
196
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
197
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
198
+ try {
199
+ const subDir = path.join(tempDir2, 'subdir');
200
+ fs.mkdirSync(subDir);
201
+
202
+ // Normalize the allowed directories
203
+ const allowedDirs = normalizeAllowedDirectories([tempDir1, tempDir2]);
204
+ const result = isWithinAllowedDirectories(subDir, allowedDirs);
205
+ expect(result).toBe(true);
206
+ } finally {
207
+ fs.rmSync(tempDir1, { recursive: true });
208
+ fs.rmSync(tempDir2, { recursive: true });
209
+ }
210
+ });
211
+ });
212
+
213
+ describe('assessPathAccess', () => {
214
+ it('returns allowed true for path within allowed directory', () => {
215
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
216
+ try {
217
+ const subDir = path.join(tempDir, 'subdir');
218
+ fs.mkdirSync(subDir);
219
+
220
+ // Use realpathSync to get the real path
221
+ const realTempDir = fs.realpathSync(tempDir);
222
+ const realSubDir = fs.realpathSync(subDir);
223
+
224
+ const result = assessPathAccess(realSubDir, [realTempDir]);
225
+ expect(result.allowed).toBe(true);
226
+ expect(result.normalizedCandidate).toBeDefined();
227
+ // Message always contains 'outside allowed directories' regardless of allowed status
228
+ expect(result.message).toContain('outside allowed directories');
229
+ } finally {
230
+ fs.rmSync(tempDir, { recursive: true });
231
+ }
232
+ });
233
+
234
+ it('returns allowed false for path outside allowed directory', () => {
235
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
236
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
237
+ try {
238
+ const result = assessPathAccess(tempDir2, [tempDir1]);
239
+ expect(result.allowed).toBe(false);
240
+ expect(result.message).toContain(tempDir2);
241
+ expect(result.message).toContain(tempDir1);
242
+ } finally {
243
+ fs.rmSync(tempDir1, { recursive: true });
244
+ fs.rmSync(tempDir2, { recursive: true });
245
+ }
246
+ });
247
+
248
+ it('uses custom error prefix', () => {
249
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
250
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
251
+ try {
252
+ const result = assessPathAccess(tempDir2, [tempDir1], 'CUSTOM_ERROR');
253
+ expect(result.message).toContain('CUSTOM_ERROR');
254
+ } finally {
255
+ fs.rmSync(tempDir1, { recursive: true });
256
+ fs.rmSync(tempDir2, { recursive: true });
257
+ }
258
+ });
259
+ });
260
+
261
+ describe('ensurePathWithinAllowed', () => {
262
+ it('returns normalized path when allowed', () => {
263
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-'));
264
+ try {
265
+ const subDir = path.join(tempDir, 'subdir');
266
+ fs.mkdirSync(subDir);
267
+
268
+ // Normalize the allowed directories
269
+ const allowedDirs = normalizeAllowedDirectories([tempDir]);
270
+ const result = ensurePathWithinAllowed(subDir, allowedDirs);
271
+ expect(result).toBeDefined();
272
+ } finally {
273
+ fs.rmSync(tempDir, { recursive: true });
274
+ }
275
+ });
276
+
277
+ it('throws error when not allowed', () => {
278
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
279
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
280
+ try {
281
+ expect(() => ensurePathWithinAllowed(tempDir2, [tempDir1])).toThrow();
282
+ } finally {
283
+ fs.rmSync(tempDir1, { recursive: true });
284
+ fs.rmSync(tempDir2, { recursive: true });
285
+ }
286
+ });
287
+
288
+ it('returns path when not allowed but allowOutsideAllowedDirectories is true', () => {
289
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
290
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
291
+ try {
292
+ const result = ensurePathWithinAllowed(tempDir2, [tempDir1], 'PATH_NOT_ALLOWED', true);
293
+ expect(result).toBeDefined();
294
+ } finally {
295
+ fs.rmSync(tempDir1, { recursive: true });
296
+ fs.rmSync(tempDir2, { recursive: true });
297
+ }
298
+ });
299
+
300
+ it('uses custom error prefix', () => {
301
+ const tempDir1 = fs.mkdtempSync(path.join(os.tmpdir(), 'test1-'));
302
+ const tempDir2 = fs.mkdtempSync(path.join(os.tmpdir(), 'test2-'));
303
+ try {
304
+ expect(() => ensurePathWithinAllowed(tempDir2, [tempDir1], 'CUSTOM_ERROR')).toThrow(
305
+ 'CUSTOM_ERROR'
306
+ );
307
+ } finally {
308
+ fs.rmSync(tempDir1, { recursive: true });
309
+ fs.rmSync(tempDir2, { recursive: true });
310
+ }
311
+ });
312
+ });
313
+
314
+ describe('toPosixPath', () => {
315
+ it('converts path separators to POSIX format', () => {
316
+ // Test with the current platform's separator
317
+ const testPath = path.join('Users', 'test', 'file.txt');
318
+ const result = toPosixPath(testPath);
319
+
320
+ // Should always use forward slashes
321
+ expect(result).toBe('Users/test/file.txt');
322
+ });
323
+
324
+ it('leaves POSIX path unchanged', () => {
325
+ const result = toPosixPath('/Users/test/file.txt');
326
+ expect(result).toBe('/Users/test/file.txt');
327
+ });
328
+
329
+ it('handles empty string', () => {
330
+ expect(toPosixPath('')).toBe('');
331
+ });
332
+
333
+ it('handles path with no separators', () => {
334
+ expect(toPosixPath('filename')).toBe('filename');
335
+ });
336
+ });