@yuaone/tools 0.1.0

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 (87) hide show
  1. package/LICENSE +663 -0
  2. package/README.md +15 -0
  3. package/dist/__tests__/file-edit.test.d.ts +8 -0
  4. package/dist/__tests__/file-edit.test.d.ts.map +1 -0
  5. package/dist/__tests__/file-edit.test.js +125 -0
  6. package/dist/__tests__/file-edit.test.js.map +1 -0
  7. package/dist/__tests__/registry.test.d.ts +7 -0
  8. package/dist/__tests__/registry.test.d.ts.map +1 -0
  9. package/dist/__tests__/registry.test.js +83 -0
  10. package/dist/__tests__/registry.test.js.map +1 -0
  11. package/dist/__tests__/validators.test.d.ts +8 -0
  12. package/dist/__tests__/validators.test.d.ts.map +1 -0
  13. package/dist/__tests__/validators.test.js +189 -0
  14. package/dist/__tests__/validators.test.js.map +1 -0
  15. package/dist/base-tool.d.ts +45 -0
  16. package/dist/base-tool.d.ts.map +1 -0
  17. package/dist/base-tool.js +87 -0
  18. package/dist/base-tool.js.map +1 -0
  19. package/dist/browser-tool.d.ts +39 -0
  20. package/dist/browser-tool.d.ts.map +1 -0
  21. package/dist/browser-tool.js +518 -0
  22. package/dist/browser-tool.js.map +1 -0
  23. package/dist/code-search.d.ts +42 -0
  24. package/dist/code-search.d.ts.map +1 -0
  25. package/dist/code-search.js +298 -0
  26. package/dist/code-search.js.map +1 -0
  27. package/dist/design-tools.d.ts +70 -0
  28. package/dist/design-tools.d.ts.map +1 -0
  29. package/dist/design-tools.js +471 -0
  30. package/dist/design-tools.js.map +1 -0
  31. package/dist/dev-server-manager.d.ts +32 -0
  32. package/dist/dev-server-manager.d.ts.map +1 -0
  33. package/dist/dev-server-manager.js +183 -0
  34. package/dist/dev-server-manager.js.map +1 -0
  35. package/dist/file-edit.d.ts +19 -0
  36. package/dist/file-edit.d.ts.map +1 -0
  37. package/dist/file-edit.js +217 -0
  38. package/dist/file-edit.js.map +1 -0
  39. package/dist/file-read.d.ts +19 -0
  40. package/dist/file-read.d.ts.map +1 -0
  41. package/dist/file-read.js +142 -0
  42. package/dist/file-read.js.map +1 -0
  43. package/dist/file-write.d.ts +18 -0
  44. package/dist/file-write.d.ts.map +1 -0
  45. package/dist/file-write.js +139 -0
  46. package/dist/file-write.js.map +1 -0
  47. package/dist/git-ops.d.ts +25 -0
  48. package/dist/git-ops.d.ts.map +1 -0
  49. package/dist/git-ops.js +219 -0
  50. package/dist/git-ops.js.map +1 -0
  51. package/dist/glob.d.ts +18 -0
  52. package/dist/glob.d.ts.map +1 -0
  53. package/dist/glob.js +91 -0
  54. package/dist/glob.js.map +1 -0
  55. package/dist/grep.d.ts +19 -0
  56. package/dist/grep.d.ts.map +1 -0
  57. package/dist/grep.js +177 -0
  58. package/dist/grep.js.map +1 -0
  59. package/dist/index.d.ts +27 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +29 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/security-scan.d.ts +62 -0
  64. package/dist/security-scan.d.ts.map +1 -0
  65. package/dist/security-scan.js +445 -0
  66. package/dist/security-scan.js.map +1 -0
  67. package/dist/shell-exec.d.ts +20 -0
  68. package/dist/shell-exec.d.ts.map +1 -0
  69. package/dist/shell-exec.js +206 -0
  70. package/dist/shell-exec.js.map +1 -0
  71. package/dist/test-run.d.ts +51 -0
  72. package/dist/test-run.d.ts.map +1 -0
  73. package/dist/test-run.js +359 -0
  74. package/dist/test-run.js.map +1 -0
  75. package/dist/tool-registry.d.ts +70 -0
  76. package/dist/tool-registry.d.ts.map +1 -0
  77. package/dist/tool-registry.js +181 -0
  78. package/dist/tool-registry.js.map +1 -0
  79. package/dist/types.d.ts +137 -0
  80. package/dist/types.d.ts.map +1 -0
  81. package/dist/types.js +8 -0
  82. package/dist/types.js.map +1 -0
  83. package/dist/validators.d.ts +57 -0
  84. package/dist/validators.d.ts.map +1 -0
  85. package/dist/validators.js +218 -0
  86. package/dist/validators.js.map +1 -0
  87. package/package.json +42 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @yuaone/tools — FileEditTool unit tests
3
+ *
4
+ * Tests file editing: replacement, ambiguity, replace_all,
5
+ * deletion, whitespace sensitivity, large files, fuzzy suggestions.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=file-edit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-edit.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/file-edit.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * @yuaone/tools — FileEditTool unit tests
3
+ *
4
+ * Tests file editing: replacement, ambiguity, replace_all,
5
+ * deletion, whitespace sensitivity, large files, fuzzy suggestions.
6
+ */
7
+ import { describe, it, beforeEach, afterEach } from 'node:test';
8
+ import assert from 'node:assert/strict';
9
+ import { join } from 'node:path';
10
+ import { mkdtempSync, writeFileSync, readFileSync, mkdirSync, rmSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { FileEditTool } from '../file-edit.js';
13
+ let tool;
14
+ let tmpDir;
15
+ function setup() {
16
+ tool = new FileEditTool();
17
+ tmpDir = mkdtempSync(join(tmpdir(), 'yuan-edit-test-'));
18
+ }
19
+ function teardown() {
20
+ rmSync(tmpDir, { recursive: true, force: true });
21
+ }
22
+ // Helper to write a temp file and return its relative path
23
+ function writeTempFile(name, content) {
24
+ const absPath = join(tmpDir, name);
25
+ const dir = absPath.substring(0, absPath.lastIndexOf('/'));
26
+ if (dir !== tmpDir) {
27
+ mkdirSync(dir, { recursive: true });
28
+ }
29
+ writeFileSync(absPath, content, 'utf-8');
30
+ return name;
31
+ }
32
+ function readTempFile(name) {
33
+ return readFileSync(join(tmpDir, name), 'utf-8');
34
+ }
35
+ describe('FileEditTool', () => {
36
+ beforeEach(() => setup());
37
+ afterEach(() => teardown());
38
+ it('should have correct name and risk level', () => {
39
+ assert.equal(tool.name, 'file_edit');
40
+ assert.equal(tool.riskLevel, 'medium');
41
+ });
42
+ // 1. Simple replacement
43
+ it('should perform simple replacement when exact match found', async () => {
44
+ const file = writeTempFile('app.ts', 'const x = 1;\nconst y = 2;\n');
45
+ const result = await tool.execute({ path: file, old_string: 'const x = 1;', new_string: 'const x = 42;', _toolCallId: 't1' }, tmpDir);
46
+ assert.equal(result.success, true);
47
+ assert.ok(result.output.includes('1 replacement'));
48
+ assert.equal(readTempFile(file), 'const x = 42;\nconst y = 2;\n');
49
+ });
50
+ // 2. No match → error with suggestion
51
+ it('should return error when old_string not found', async () => {
52
+ const file = writeTempFile('app.ts', 'const x = 1;\n');
53
+ const result = await tool.execute({ path: file, old_string: 'const z = 99;', new_string: 'replaced', _toolCallId: 't2' }, tmpDir);
54
+ assert.equal(result.success, false);
55
+ assert.ok(result.output.includes('not found'));
56
+ });
57
+ // 3. Multiple matches without replace_all → error (ambiguous)
58
+ it('should return error when old_string matches multiple times without replace_all', async () => {
59
+ const file = writeTempFile('app.ts', 'foo\nbar\nfoo\nbaz\n');
60
+ const result = await tool.execute({ path: file, old_string: 'foo', new_string: 'qux', _toolCallId: 't3' }, tmpDir);
61
+ assert.equal(result.success, false);
62
+ assert.ok(result.output.includes('matches 2 times'));
63
+ });
64
+ // 4. replace_all: multiple matches → all replaced
65
+ it('should replace all occurrences when replace_all=true', async () => {
66
+ const file = writeTempFile('app.ts', 'foo\nbar\nfoo\nbaz\n');
67
+ const result = await tool.execute({ path: file, old_string: 'foo', new_string: 'qux', replace_all: true, _toolCallId: 't4' }, tmpDir);
68
+ assert.equal(result.success, true);
69
+ assert.ok(result.output.includes('2 replacement'));
70
+ assert.equal(readTempFile(file), 'qux\nbar\nqux\nbaz\n');
71
+ });
72
+ // 5. Empty new_string → deletion
73
+ it('should delete when new_string is empty', async () => {
74
+ const file = writeTempFile('app.ts', 'keep\ndelete-me\nkeep\n');
75
+ const result = await tool.execute({ path: file, old_string: 'delete-me\n', new_string: '', _toolCallId: 't5' }, tmpDir);
76
+ assert.equal(result.success, true);
77
+ assert.equal(readTempFile(file), 'keep\nkeep\n');
78
+ });
79
+ // 6. Whitespace sensitivity: exact whitespace match required
80
+ it('should require exact whitespace match', async () => {
81
+ const file = writeTempFile('app.ts', ' const x = 1;\n');
82
+ // Missing leading spaces → should not match
83
+ const result = await tool.execute({ path: file, old_string: 'const x = 1;', new_string: 'const x = 2;', _toolCallId: 't6' }, tmpDir);
84
+ // It should find it (substring match), but the replacement is exact
85
+ // Actually 'const x = 1;' IS found as substring of ' const x = 1;'
86
+ assert.equal(result.success, true);
87
+ // The leading spaces should be preserved since only the matching portion is replaced
88
+ assert.equal(readTempFile(file), ' const x = 2;\n');
89
+ });
90
+ // 7. Large file: handle 10K+ lines
91
+ it('should handle large files with 10K+ lines', async () => {
92
+ const lines = [];
93
+ for (let i = 0; i < 12000; i++) {
94
+ lines.push(`line ${i}: content here`);
95
+ }
96
+ // Put a unique string at line 6000
97
+ lines[6000] = 'UNIQUE_MARKER_HERE';
98
+ const file = writeTempFile('large.ts', lines.join('\n'));
99
+ const result = await tool.execute({ path: file, old_string: 'UNIQUE_MARKER_HERE', new_string: 'REPLACED_MARKER', _toolCallId: 't7' }, tmpDir);
100
+ assert.equal(result.success, true);
101
+ const content = readTempFile(file);
102
+ assert.ok(content.includes('REPLACED_MARKER'));
103
+ assert.ok(!content.includes('UNIQUE_MARKER_HERE'));
104
+ });
105
+ // 8. Missing path parameter
106
+ it('should fail when path is missing', async () => {
107
+ const result = await tool.execute({ old_string: 'x', new_string: 'y', _toolCallId: 't8' }, tmpDir);
108
+ assert.equal(result.success, false);
109
+ assert.ok(result.output.includes('Missing'));
110
+ });
111
+ // 9. File not found
112
+ it('should fail when file does not exist', async () => {
113
+ const result = await tool.execute({ path: 'nonexistent.ts', old_string: 'x', new_string: 'y', _toolCallId: 't9' }, tmpDir);
114
+ assert.equal(result.success, false);
115
+ assert.ok(result.output.includes('not found'));
116
+ });
117
+ // 10. Sensitive file blocked
118
+ it('should block editing sensitive files', async () => {
119
+ writeTempFile('.env', 'SECRET=value');
120
+ const result = await tool.execute({ path: '.env', old_string: 'SECRET=value', new_string: 'SECRET=new', _toolCallId: 't10' }, tmpDir);
121
+ assert.equal(result.success, false);
122
+ assert.ok(result.output.includes('Sensitive'));
123
+ });
124
+ });
125
+ //# sourceMappingURL=file-edit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-edit.test.js","sourceRoot":"","sources":["../../src/__tests__/file-edit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @yuaone/tools — ToolRegistry unit tests
3
+ *
4
+ * Tests registry: default tools, get/has, definitions, executor.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/registry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @yuaone/tools — ToolRegistry unit tests
3
+ *
4
+ * Tests registry: default tools, get/has, definitions, executor.
5
+ */
6
+ import { describe, it } from 'node:test';
7
+ import assert from 'node:assert/strict';
8
+ import { ToolRegistry, createDefaultRegistry } from '../tool-registry.js';
9
+ import { FileReadTool } from '../file-read.js';
10
+ const EXPECTED_TOOL_NAMES = [
11
+ 'file_read',
12
+ 'file_write',
13
+ 'file_edit',
14
+ 'shell_exec',
15
+ 'grep',
16
+ 'glob',
17
+ 'git_ops',
18
+ 'test_run',
19
+ 'code_search',
20
+ 'security_scan',
21
+ ];
22
+ describe('ToolRegistry', () => {
23
+ // 1. Default registry has 9 tools registered
24
+ it('should create default registry with 10 tools', () => {
25
+ const registry = createDefaultRegistry();
26
+ assert.equal(registry.size, 10);
27
+ });
28
+ // 2. All expected tool names present
29
+ it('should contain all expected tool names', () => {
30
+ const registry = createDefaultRegistry();
31
+ const names = registry.listNames();
32
+ for (const name of EXPECTED_TOOL_NAMES) {
33
+ assert.ok(names.includes(name), `Missing tool: ${name}`);
34
+ }
35
+ });
36
+ // 3. Get tool returns correct tool by name
37
+ it('should return correct tool by name', () => {
38
+ const registry = createDefaultRegistry();
39
+ const tool = registry.get('file_read');
40
+ assert.ok(tool !== undefined);
41
+ assert.equal(tool.name, 'file_read');
42
+ });
43
+ // 4. Unknown tool returns undefined
44
+ it('should return undefined for unknown tool', () => {
45
+ const registry = createDefaultRegistry();
46
+ const tool = registry.get('nonexistent_tool');
47
+ assert.equal(tool, undefined);
48
+ });
49
+ // 5. Each tool has valid input_schema (parameters with type: 'object')
50
+ it('should generate valid definitions for each tool', () => {
51
+ const registry = createDefaultRegistry();
52
+ const definitions = registry.toDefinitions();
53
+ assert.equal(definitions.length, 10);
54
+ for (const def of definitions) {
55
+ assert.ok(typeof def.name === 'string' && def.name.length > 0);
56
+ assert.ok(typeof def.description === 'string' && def.description.length > 0);
57
+ assert.ok(def.parameters !== undefined);
58
+ assert.equal(def.parameters.type, 'object');
59
+ assert.ok(def.parameters.properties !== undefined);
60
+ }
61
+ });
62
+ // 6. toExecutor returns a function-based executor
63
+ it('should create executor with definitions and execute function', () => {
64
+ const registry = createDefaultRegistry();
65
+ const executor = registry.toExecutor('/tmp/test');
66
+ assert.ok(executor.definitions.length === 10);
67
+ assert.ok(typeof executor.execute === 'function');
68
+ });
69
+ // 7. Duplicate registration throws
70
+ it('should throw on duplicate tool registration', () => {
71
+ const registry = new ToolRegistry();
72
+ registry.register(new FileReadTool());
73
+ assert.throws(() => registry.register(new FileReadTool()), /already registered/);
74
+ });
75
+ // 8. Execute unknown tool returns error result
76
+ it('should return error result for unknown tool execution', async () => {
77
+ const registry = createDefaultRegistry();
78
+ const result = await registry.execute('nonexistent', { _toolCallId: 'x' }, '/tmp');
79
+ assert.equal(result.success, false);
80
+ assert.ok(result.output.includes('Unknown tool'));
81
+ });
82
+ });
83
+ //# sourceMappingURL=registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.test.js","sourceRoot":"","sources":["../../src/__tests__/registry.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,mBAAmB,GAAG;IAC1B,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IACV,aAAa;IACb,eAAe;CAChB,CAAC;AAEF,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,6CAA6C;IAC7C,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,qCAAqC;IACrC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,mBAAmB,EAAE,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,2CAA2C;IAC3C,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAC5C,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvC,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;QAC9B,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,oCAAoC;IACpC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAClD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,uEAAuE;IACvE,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACrC,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/D,MAAM,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC7E,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;QACrD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,kDAAkD;IAClD,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;QAClD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,EAAE,CAAC,OAAO,QAAQ,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,mCAAmC;IACnC,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,QAAQ,GAAG,IAAI,YAAY,EAAE,CAAC;QACpC,QAAQ,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,YAAY,EAAE,CAAC,EAC3C,oBAAoB,CACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,+CAA+C;IAC/C,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,QAAQ,GAAG,qBAAqB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QACnF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @yuaone/tools — Validator unit tests
3
+ *
4
+ * Tests security validators: command blocking, path traversal,
5
+ * shell metacharacters, sensitive file detection, binary detection.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=validators.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/validators.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @yuaone/tools — Validator unit tests
3
+ *
4
+ * Tests security validators: command blocking, path traversal,
5
+ * shell metacharacters, sensitive file detection, binary detection.
6
+ */
7
+ import { describe, it } from 'node:test';
8
+ import assert from 'node:assert/strict';
9
+ import { join } from 'node:path';
10
+ import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { validatePath, validateNoShellMeta, validateCommand, isSensitiveFile, isBinaryFile, isImageFile, truncateOutput, detectLanguage, } from '../validators.js';
13
+ // ─── Path Traversal Defence ─────────────────────────────────────────
14
+ describe('validatePath', () => {
15
+ const workDir = '/home/user/project';
16
+ it('should resolve a valid relative path', () => {
17
+ const result = validatePath('src/app.ts', workDir);
18
+ assert.equal(result, join(workDir, 'src/app.ts'));
19
+ });
20
+ it('should throw on path traversal via ../../../etc/passwd', () => {
21
+ assert.throws(() => validatePath('../../../etc/passwd', workDir), /Path traversal detected/);
22
+ });
23
+ it('should throw on path traversal via ../', () => {
24
+ assert.throws(() => validatePath('../../outside', workDir), /Path traversal detected/);
25
+ });
26
+ it('should throw on null byte in path', () => {
27
+ assert.throws(() => validatePath('src/app\0.ts', workDir), /null byte/);
28
+ });
29
+ it('should allow nested valid paths', () => {
30
+ const result = validatePath('src/deep/nested/file.ts', workDir);
31
+ assert.equal(result, join(workDir, 'src/deep/nested/file.ts'));
32
+ });
33
+ });
34
+ // ─── Shell Metacharacter Defence ────────────────────────────────────
35
+ describe('validateNoShellMeta', () => {
36
+ it('should pass for clean executable and args', () => {
37
+ assert.doesNotThrow(() => validateNoShellMeta('node', ['index.js']));
38
+ });
39
+ it('should throw on semicolon in arg', () => {
40
+ assert.throws(() => validateNoShellMeta('ls', ['; rm -rf /']), /Shell metacharacter in arg/);
41
+ });
42
+ it('should throw on pipe in executable', () => {
43
+ assert.throws(() => validateNoShellMeta('ls | cat', []), /Shell metacharacter in executable/);
44
+ });
45
+ it('should throw on backtick in arg', () => {
46
+ assert.throws(() => validateNoShellMeta('echo', ['`whoami`']), /Shell metacharacter in arg/);
47
+ });
48
+ it('should throw on && in arg', () => {
49
+ assert.throws(() => validateNoShellMeta('echo', ['hello && rm -rf /']), /Shell metacharacter in arg/);
50
+ });
51
+ it('should throw on $() in arg', () => {
52
+ assert.throws(() => validateNoShellMeta('echo', ['$(cat /etc/passwd)']), /Shell metacharacter in arg/);
53
+ });
54
+ });
55
+ // ─── Command Validation (delegates to @yuaone/core) ───────────────────
56
+ describe('validateCommand', () => {
57
+ it('should allow safe commands: ls', () => {
58
+ assert.doesNotThrow(() => validateCommand('ls', ['-la']));
59
+ });
60
+ it('should allow safe commands: node', () => {
61
+ assert.doesNotThrow(() => validateCommand('node', ['index.js']));
62
+ });
63
+ it('should allow safe commands: pnpm', () => {
64
+ assert.doesNotThrow(() => validateCommand('pnpm', ['install']));
65
+ });
66
+ it('should allow safe commands: git status', () => {
67
+ assert.doesNotThrow(() => validateCommand('git', ['status']));
68
+ });
69
+ it('should block rm -rf /', () => {
70
+ assert.throws(() => validateCommand('rm', ['-rf', '/']), /blocked|Destructive/i);
71
+ });
72
+ it('should block interactive commands: vim', () => {
73
+ assert.throws(() => validateCommand('vim', ['file.txt']), /blocked|Interactive|TTY/i);
74
+ });
75
+ it('should block interactive commands: nano', () => {
76
+ assert.throws(() => validateCommand('nano', ['file.txt']), /blocked|Interactive|TTY/i);
77
+ });
78
+ it('should block sudo', () => {
79
+ assert.throws(() => validateCommand('sudo', ['ls']), /blocked|Blocked/i);
80
+ });
81
+ it('should block su', () => {
82
+ assert.throws(() => validateCommand('su', ['-']), /blocked|Blocked/i);
83
+ });
84
+ });
85
+ // ─── Sensitive File Detection ───────────────────────────────────────
86
+ describe('isSensitiveFile', () => {
87
+ it('should detect .env as sensitive', () => {
88
+ assert.equal(isSensitiveFile('.env'), true);
89
+ });
90
+ it('should detect .env.local as sensitive', () => {
91
+ assert.equal(isSensitiveFile('.env.local'), true);
92
+ });
93
+ it('should detect credentials.json as sensitive', () => {
94
+ assert.equal(isSensitiveFile('credentials.json'), true);
95
+ });
96
+ it('should detect .pem files as sensitive', () => {
97
+ assert.equal(isSensitiveFile('server.pem'), true);
98
+ });
99
+ it('should detect id_rsa as sensitive', () => {
100
+ assert.equal(isSensitiveFile('id_rsa'), true);
101
+ });
102
+ it('should NOT detect src/app.ts as sensitive', () => {
103
+ assert.equal(isSensitiveFile('src/app.ts'), false);
104
+ });
105
+ it('should NOT detect package.json as sensitive', () => {
106
+ assert.equal(isSensitiveFile('package.json'), false);
107
+ });
108
+ it('should NOT detect README.md as sensitive', () => {
109
+ assert.equal(isSensitiveFile('README.md'), false);
110
+ });
111
+ });
112
+ // ─── Binary File Detection ──────────────────────────────────────────
113
+ describe('isBinaryFile', () => {
114
+ let tmpDir;
115
+ it('should detect .png as binary (image)', async () => {
116
+ const result = await isBinaryFile('image.png');
117
+ assert.equal(result, true);
118
+ });
119
+ it('should detect .jpg as binary (image)', async () => {
120
+ const result = await isBinaryFile('photo.jpg');
121
+ assert.equal(result, true);
122
+ });
123
+ it('should detect .ts as text (by extension)', async () => {
124
+ const result = await isBinaryFile('src/app.ts');
125
+ assert.equal(result, false);
126
+ });
127
+ it('should detect .json as text (by extension)', async () => {
128
+ const result = await isBinaryFile('config.json');
129
+ assert.equal(result, false);
130
+ });
131
+ it('should sniff binary content via null bytes', async () => {
132
+ tmpDir = mkdtempSync(join(tmpdir(), 'yuan-test-'));
133
+ const binFile = join(tmpDir, 'data.bin');
134
+ const buf = Buffer.from([0x48, 0x65, 0x6c, 0x00, 0x6f]); // "Hel\0o"
135
+ writeFileSync(binFile, buf);
136
+ const result = await isBinaryFile(binFile);
137
+ assert.equal(result, true);
138
+ rmSync(tmpDir, { recursive: true, force: true });
139
+ });
140
+ it('should sniff text content without null bytes', async () => {
141
+ tmpDir = mkdtempSync(join(tmpdir(), 'yuan-test-'));
142
+ const textFile = join(tmpDir, 'data.unknown');
143
+ writeFileSync(textFile, 'Hello, this is plain text');
144
+ const result = await isBinaryFile(textFile);
145
+ assert.equal(result, false);
146
+ rmSync(tmpDir, { recursive: true, force: true });
147
+ });
148
+ });
149
+ // ─── Image File Detection ───────────────────────────────────────────
150
+ describe('isImageFile', () => {
151
+ it('should detect .png as image', () => {
152
+ assert.equal(isImageFile('logo.png'), true);
153
+ });
154
+ it('should detect .svg as image', () => {
155
+ assert.equal(isImageFile('icon.svg'), true);
156
+ });
157
+ it('should NOT detect .ts as image', () => {
158
+ assert.equal(isImageFile('src/app.ts'), false);
159
+ });
160
+ });
161
+ // ─── Output Truncation ─────────────────────────────────────────────
162
+ describe('truncateOutput', () => {
163
+ it('should not truncate short output', () => {
164
+ const output = 'Hello, world!';
165
+ assert.equal(truncateOutput(output), output);
166
+ });
167
+ it('should truncate long output with head/tail', () => {
168
+ const output = 'x'.repeat(100_000);
169
+ const result = truncateOutput(output, 1000);
170
+ assert.ok(result.length < output.length);
171
+ assert.ok(result.includes('truncated'));
172
+ });
173
+ });
174
+ // ─── Language Detection ─────────────────────────────────────────────
175
+ describe('detectLanguage', () => {
176
+ it('should detect TypeScript', () => {
177
+ assert.equal(detectLanguage('src/app.ts'), 'typescript');
178
+ });
179
+ it('should detect Python', () => {
180
+ assert.equal(detectLanguage('main.py'), 'python');
181
+ });
182
+ it('should detect Dockerfile', () => {
183
+ assert.equal(detectLanguage('Dockerfile'), 'dockerfile');
184
+ });
185
+ it('should return plaintext for unknown', () => {
186
+ assert.equal(detectLanguage('file.xyz'), 'plaintext');
187
+ });
188
+ });
189
+ //# sourceMappingURL=validators.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.test.js","sourceRoot":"","sources":["../../src/__tests__/validators.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @yuaone/tools — BaseTool abstract class
3
+ *
4
+ * Every tool inherits from BaseTool which provides:
5
+ * - Tool definition metadata
6
+ * - Path validation (path traversal defence)
7
+ * - Output truncation
8
+ * - Common execute contract
9
+ *
10
+ * ToolResult now uses @yuaone/core's format:
11
+ * { tool_call_id, name, output, success, durationMs }
12
+ */
13
+ import type { ToolResult, ToolDefinition } from '@yuaone/core';
14
+ import type { ParameterDef, RiskLevel } from './types.js';
15
+ export declare abstract class BaseTool {
16
+ abstract readonly name: string;
17
+ abstract readonly description: string;
18
+ abstract readonly parameters: Record<string, ParameterDef>;
19
+ abstract readonly riskLevel: RiskLevel;
20
+ /** Tools with riskLevel !== 'low' require user approval by default. */
21
+ get requiresApproval(): boolean;
22
+ /**
23
+ * Execute the tool with the given arguments and workDir.
24
+ * @param args - Tool arguments
25
+ * @param workDir - Working directory
26
+ * @param abortSignal - Optional AbortSignal for interrupt-based cancellation
27
+ */
28
+ abstract execute(args: Record<string, unknown>, workDir: string, abortSignal?: AbortSignal): Promise<ToolResult>;
29
+ /** Validate and resolve a path within workDir. Throws on traversal. */
30
+ protected validatePath(path: string, workDir: string): string;
31
+ /** Truncate output to maxBytes. */
32
+ protected truncateOutput(output: string, maxBytes?: number): string;
33
+ /**
34
+ * Convert ParameterDef map to JSON Schema for LLM consumption.
35
+ * This bridges the tools' ParameterDef format to core's ToolParameterSchema.
36
+ */
37
+ private toJsonSchema;
38
+ /** Generate a ToolDefinition (core-compatible) for LLM consumption. */
39
+ toDefinition(): ToolDefinition;
40
+ /** Helper to build a success ToolResult (core-compatible). */
41
+ protected ok(toolCallId: string, output: string, metadata?: Record<string, unknown>): ToolResult;
42
+ /** Helper to build a failure ToolResult (core-compatible). */
43
+ protected fail(toolCallId: string, error: string): ToolResult;
44
+ }
45
+ //# sourceMappingURL=base-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-tool.d.ts","sourceRoot":"","sources":["../src/base-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAuB,MAAM,cAAc,CAAC;AACpF,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAG1D,8BAAsB,QAAQ;IAC5B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC3D,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAEvC,uEAAuE;IACvE,IAAI,gBAAgB,IAAI,OAAO,CAE9B;IAED;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAEhH,uEAAuE;IACvE,SAAS,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM;IAI7D,mCAAmC;IACnC,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM;IAInE;;;OAGG;IACH,OAAO,CAAC,YAAY;IA4BpB,uEAAuE;IACvE,YAAY,IAAI,cAAc;IAQ9B,8DAA8D;IAC9D,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU;IAUhG,8DAA8D;IAC9D,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU;CAS9D"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @yuaone/tools — BaseTool abstract class
3
+ *
4
+ * Every tool inherits from BaseTool which provides:
5
+ * - Tool definition metadata
6
+ * - Path validation (path traversal defence)
7
+ * - Output truncation
8
+ * - Common execute contract
9
+ *
10
+ * ToolResult now uses @yuaone/core's format:
11
+ * { tool_call_id, name, output, success, durationMs }
12
+ */
13
+ import { validatePath as _validatePath, truncateOutput as _truncateOutput } from './validators.js';
14
+ export class BaseTool {
15
+ /** Tools with riskLevel !== 'low' require user approval by default. */
16
+ get requiresApproval() {
17
+ return this.riskLevel !== 'low';
18
+ }
19
+ /** Validate and resolve a path within workDir. Throws on traversal. */
20
+ validatePath(path, workDir) {
21
+ return _validatePath(path, workDir);
22
+ }
23
+ /** Truncate output to maxBytes. */
24
+ truncateOutput(output, maxBytes) {
25
+ return _truncateOutput(output, maxBytes);
26
+ }
27
+ /**
28
+ * Convert ParameterDef map to JSON Schema for LLM consumption.
29
+ * This bridges the tools' ParameterDef format to core's ToolParameterSchema.
30
+ */
31
+ toJsonSchema() {
32
+ const properties = {};
33
+ const required = [];
34
+ for (const [key, param] of Object.entries(this.parameters)) {
35
+ const prop = {
36
+ type: param.type,
37
+ description: param.description,
38
+ };
39
+ if (param.enum)
40
+ prop.enum = param.enum;
41
+ if (param.default !== undefined)
42
+ prop.default = param.default;
43
+ if (param.items) {
44
+ prop.items = { type: param.items.type, description: param.items.description };
45
+ }
46
+ properties[key] = prop;
47
+ if (param.required) {
48
+ required.push(key);
49
+ }
50
+ }
51
+ return {
52
+ type: 'object',
53
+ properties,
54
+ required: required.length > 0 ? required : undefined,
55
+ additionalProperties: false,
56
+ };
57
+ }
58
+ /** Generate a ToolDefinition (core-compatible) for LLM consumption. */
59
+ toDefinition() {
60
+ return {
61
+ name: this.name,
62
+ description: this.description,
63
+ parameters: this.toJsonSchema(),
64
+ };
65
+ }
66
+ /** Helper to build a success ToolResult (core-compatible). */
67
+ ok(toolCallId, output, metadata) {
68
+ return {
69
+ tool_call_id: toolCallId,
70
+ name: this.name,
71
+ output: this.truncateOutput(output),
72
+ success: true,
73
+ durationMs: 0, // Caller can override via wrapper
74
+ };
75
+ }
76
+ /** Helper to build a failure ToolResult (core-compatible). */
77
+ fail(toolCallId, error) {
78
+ return {
79
+ tool_call_id: toolCallId,
80
+ name: this.name,
81
+ output: `Error: ${error}`,
82
+ success: false,
83
+ durationMs: 0,
84
+ };
85
+ }
86
+ }
87
+ //# sourceMappingURL=base-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-tool.js","sourceRoot":"","sources":["../src/base-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,IAAI,aAAa,EAAE,cAAc,IAAI,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAEnG,MAAM,OAAgB,QAAQ;IAM5B,uEAAuE;IACvE,IAAI,gBAAgB;QAClB,OAAO,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;IAClC,CAAC;IAUD,uEAAuE;IAC7D,YAAY,CAAC,IAAY,EAAE,OAAe;QAClD,OAAO,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,mCAAmC;IACzB,cAAc,CAAC,MAAc,EAAE,QAAiB;QACxD,OAAO,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACK,YAAY;QAClB,MAAM,UAAU,GAA4B,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,GAA4B;gBACpC,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC;YACF,IAAI,KAAK,CAAC,IAAI;gBAAE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;YACvC,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;gBAAE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;YAC9D,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,KAAK,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YAChF,CAAC;YACD,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC;YACvB,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;gBACnB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,UAAU;YACV,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;YACpD,oBAAoB,EAAE,KAAK;SAC5B,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,YAAY;QACV,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,YAAY,EAAE;SAChC,CAAC;IACJ,CAAC;IAED,8DAA8D;IACpD,EAAE,CAAC,UAAkB,EAAE,MAAc,EAAE,QAAkC;QACjF,OAAO;YACL,YAAY,EAAE,UAAU;YACxB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;YACnC,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,CAAC,EAAE,kCAAkC;SAClD,CAAC;IACJ,CAAC;IAED,8DAA8D;IACpD,IAAI,CAAC,UAAkB,EAAE,KAAa;QAC9C,OAAO;YACL,YAAY,EAAE,UAAU;YACxB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,MAAM,EAAE,UAAU,KAAK,EAAE;YACzB,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,CAAC;SACd,CAAC;IACJ,CAAC;CACF"}