@x-code-cli/core 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 (125) hide show
  1. package/dist/agent/loop.d.ts +19 -0
  2. package/dist/agent/loop.d.ts.map +1 -0
  3. package/dist/agent/loop.js +443 -0
  4. package/dist/agent/loop.js.map +1 -0
  5. package/dist/agent/messages.d.ts +8 -0
  6. package/dist/agent/messages.d.ts.map +1 -0
  7. package/dist/agent/messages.js +51 -0
  8. package/dist/agent/messages.js.map +1 -0
  9. package/dist/agent/plan-mode.d.ts +11 -0
  10. package/dist/agent/plan-mode.d.ts.map +1 -0
  11. package/dist/agent/plan-mode.js +37 -0
  12. package/dist/agent/plan-mode.js.map +1 -0
  13. package/dist/agent/pricing.d.ts +9 -0
  14. package/dist/agent/pricing.d.ts.map +1 -0
  15. package/dist/agent/pricing.js +47 -0
  16. package/dist/agent/pricing.js.map +1 -0
  17. package/dist/agent/system-prompt.d.ts +9 -0
  18. package/dist/agent/system-prompt.d.ts.map +1 -0
  19. package/dist/agent/system-prompt.js +93 -0
  20. package/dist/agent/system-prompt.js.map +1 -0
  21. package/dist/config/index.d.ts +28 -0
  22. package/dist/config/index.d.ts.map +1 -0
  23. package/dist/config/index.js +88 -0
  24. package/dist/config/index.js.map +1 -0
  25. package/dist/index.d.ts +20 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +24 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/knowledge/auto-memory.d.ts +36 -0
  30. package/dist/knowledge/auto-memory.d.ts.map +1 -0
  31. package/dist/knowledge/auto-memory.js +151 -0
  32. package/dist/knowledge/auto-memory.js.map +1 -0
  33. package/dist/knowledge/hooks.d.ts +3 -0
  34. package/dist/knowledge/hooks.d.ts.map +1 -0
  35. package/dist/knowledge/hooks.js +59 -0
  36. package/dist/knowledge/hooks.js.map +1 -0
  37. package/dist/knowledge/init.d.ts +8 -0
  38. package/dist/knowledge/init.d.ts.map +1 -0
  39. package/dist/knowledge/init.js +98 -0
  40. package/dist/knowledge/init.js.map +1 -0
  41. package/dist/knowledge/loader.d.ts +14 -0
  42. package/dist/knowledge/loader.d.ts.map +1 -0
  43. package/dist/knowledge/loader.js +130 -0
  44. package/dist/knowledge/loader.js.map +1 -0
  45. package/dist/knowledge/session.d.ts +11 -0
  46. package/dist/knowledge/session.d.ts.map +1 -0
  47. package/dist/knowledge/session.js +108 -0
  48. package/dist/knowledge/session.js.map +1 -0
  49. package/dist/permissions/index.d.ts +14 -0
  50. package/dist/permissions/index.d.ts.map +1 -0
  51. package/dist/permissions/index.js +46 -0
  52. package/dist/permissions/index.js.map +1 -0
  53. package/dist/providers/registry.d.ts +2 -0
  54. package/dist/providers/registry.d.ts.map +1 -0
  55. package/dist/providers/registry.js +46 -0
  56. package/dist/providers/registry.js.map +1 -0
  57. package/dist/tools/ask-user.d.ts +8 -0
  58. package/dist/tools/ask-user.d.ts.map +1 -0
  59. package/dist/tools/ask-user.js +19 -0
  60. package/dist/tools/ask-user.js.map +1 -0
  61. package/dist/tools/edit.d.ts +7 -0
  62. package/dist/tools/edit.d.ts.map +1 -0
  63. package/dist/tools/edit.js +14 -0
  64. package/dist/tools/edit.js.map +1 -0
  65. package/dist/tools/enter-plan-mode.d.ts +2 -0
  66. package/dist/tools/enter-plan-mode.d.ts.map +1 -0
  67. package/dist/tools/enter-plan-mode.js +11 -0
  68. package/dist/tools/enter-plan-mode.js.map +1 -0
  69. package/dist/tools/exit-plan-mode.d.ts +2 -0
  70. package/dist/tools/exit-plan-mode.d.ts.map +1 -0
  71. package/dist/tools/exit-plan-mode.js +9 -0
  72. package/dist/tools/exit-plan-mode.js.map +1 -0
  73. package/dist/tools/glob.d.ts +5 -0
  74. package/dist/tools/glob.d.ts.map +1 -0
  75. package/dist/tools/glob.js +28 -0
  76. package/dist/tools/glob.js.map +1 -0
  77. package/dist/tools/grep.d.ts +7 -0
  78. package/dist/tools/grep.d.ts.map +1 -0
  79. package/dist/tools/grep.js +54 -0
  80. package/dist/tools/grep.js.map +1 -0
  81. package/dist/tools/index.d.ts +77 -0
  82. package/dist/tools/index.d.ts.map +1 -0
  83. package/dist/tools/index.js +41 -0
  84. package/dist/tools/index.js.map +1 -0
  85. package/dist/tools/list-dir.d.ts +4 -0
  86. package/dist/tools/list-dir.d.ts.map +1 -0
  87. package/dist/tools/list-dir.js +25 -0
  88. package/dist/tools/list-dir.js.map +1 -0
  89. package/dist/tools/read-file.d.ts +6 -0
  90. package/dist/tools/read-file.d.ts.map +1 -0
  91. package/dist/tools/read-file.js +28 -0
  92. package/dist/tools/read-file.js.map +1 -0
  93. package/dist/tools/save-knowledge.d.ts +8 -0
  94. package/dist/tools/save-knowledge.d.ts.map +1 -0
  95. package/dist/tools/save-knowledge.js +36 -0
  96. package/dist/tools/save-knowledge.js.map +1 -0
  97. package/dist/tools/shell-utils.d.ts +14 -0
  98. package/dist/tools/shell-utils.d.ts.map +1 -0
  99. package/dist/tools/shell-utils.js +111 -0
  100. package/dist/tools/shell-utils.js.map +1 -0
  101. package/dist/tools/shell.d.ts +5 -0
  102. package/dist/tools/shell.d.ts.map +1 -0
  103. package/dist/tools/shell.js +12 -0
  104. package/dist/tools/shell.js.map +1 -0
  105. package/dist/tools/web-fetch.d.ts +5 -0
  106. package/dist/tools/web-fetch.d.ts.map +1 -0
  107. package/dist/tools/web-fetch.js +59 -0
  108. package/dist/tools/web-fetch.js.map +1 -0
  109. package/dist/tools/web-search.d.ts +5 -0
  110. package/dist/tools/web-search.d.ts.map +1 -0
  111. package/dist/tools/web-search.js +27 -0
  112. package/dist/tools/web-search.js.map +1 -0
  113. package/dist/tools/write-file.d.ts +5 -0
  114. package/dist/tools/write-file.d.ts.map +1 -0
  115. package/dist/tools/write-file.js +12 -0
  116. package/dist/tools/write-file.js.map +1 -0
  117. package/dist/types/index.d.ts +108 -0
  118. package/dist/types/index.d.ts.map +1 -0
  119. package/dist/types/index.js +36 -0
  120. package/dist/types/index.js.map +1 -0
  121. package/dist/utils.d.ts +9 -0
  122. package/dist/utils.d.ts.map +1 -0
  123. package/dist/utils.js +34 -0
  124. package/dist/utils.js.map +1 -0
  125. package/package.json +42 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enter-plan-mode.js","sourceRoot":"","sources":["../../src/tools/enter-plan-mode.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;IAChC,WAAW,EAAE;;uEAEwD;IACrE,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,uFAAuF;CACxF,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export declare const exitPlanMode: import("ai").Tool<{}, never>;
2
+ //# sourceMappingURL=exit-plan-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan-mode.d.ts","sourceRoot":"","sources":["../../src/tools/exit-plan-mode.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,8BAKvB,CAAA"}
@@ -0,0 +1,9 @@
1
+ // @x-code/core — exitPlanMode tool (no execute — handled in agent loop)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ export const exitPlanMode = tool({
5
+ description: 'Signal that the plan is complete and ready for user review. The system will read the plan file and present it to the user.',
6
+ inputSchema: z.object({}),
7
+ // No execute — handled in agent loop (read plan file + present to user)
8
+ });
9
+ //# sourceMappingURL=exit-plan-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exit-plan-mode.js","sourceRoot":"","sources":["../../src/tools/exit-plan-mode.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC;IAC/B,WAAW,EACT,4HAA4H;IAC9H,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACzB,wEAAwE;CACzE,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ export declare const glob: import("ai").Tool<{
2
+ pattern: string;
3
+ cwd?: string | undefined;
4
+ }, string>;
5
+ //# sourceMappingURL=glob.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.d.ts","sourceRoot":"","sources":["../../src/tools/glob.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,IAAI;;;UAoBf,CAAA"}
@@ -0,0 +1,28 @@
1
+ // @x-code/core — glob tool (file search by pattern)
2
+ import { globby } from 'globby';
3
+ import { tool } from 'ai';
4
+ import { z } from 'zod';
5
+ export const glob = tool({
6
+ description: 'Find files matching a glob pattern. Returns file paths sorted by modification time.',
7
+ inputSchema: z.object({
8
+ pattern: z.string().describe('Glob pattern (e.g. "**/*.ts", "src/**/*.tsx")'),
9
+ cwd: z.string().optional().describe('Directory to search in (defaults to working directory)'),
10
+ }),
11
+ execute: async ({ pattern, cwd }) => {
12
+ try {
13
+ const files = await globby(pattern, {
14
+ cwd: cwd ?? process.cwd(),
15
+ gitignore: true,
16
+ absolute: true,
17
+ });
18
+ if (files.length === 0)
19
+ return 'No files found matching the pattern.';
20
+ return files.join('\n');
21
+ }
22
+ catch (err) {
23
+ const msg = err instanceof Error ? err.message : String(err);
24
+ return `Error searching files: ${msg}`;
25
+ }
26
+ },
27
+ });
28
+ //# sourceMappingURL=glob.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glob.js","sourceRoot":"","sources":["../../src/tools/glob.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,qFAAqF;IAClG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;QAC7E,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;KAC9F,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE;QAClC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,OAAO,EAAE;gBAClC,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;gBACzB,SAAS,EAAE,IAAI;gBACf,QAAQ,EAAE,IAAI;aACf,CAAC,CAAA;YACF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO,sCAAsC,CAAA;YACrE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACzB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,OAAO,0BAA0B,GAAG,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,7 @@
1
+ export declare const grep: import("ai").Tool<{
2
+ pattern: string;
3
+ path?: string | undefined;
4
+ glob?: string | undefined;
5
+ maxResults?: number | undefined;
6
+ }, string>;
7
+ //# sourceMappingURL=grep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.d.ts","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAyBA,eAAO,MAAM,IAAI;;;;;UAgCf,CAAA"}
@@ -0,0 +1,54 @@
1
+ // @x-code/core — grep tool (content search via ripgrep)
2
+ import { execFile } from 'node:child_process';
3
+ import { promisify } from 'node:util';
4
+ import { tool } from 'ai';
5
+ import { z } from 'zod';
6
+ const execFileAsync = promisify(execFile);
7
+ let _rgPath = null;
8
+ function getRipgrepPath() {
9
+ if (_rgPath)
10
+ return _rgPath;
11
+ try {
12
+ // @vscode/ripgrep provides the binary path
13
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
14
+ const rg = require('@vscode/ripgrep');
15
+ _rgPath = rg.rgPath;
16
+ }
17
+ catch {
18
+ _rgPath = 'rg';
19
+ }
20
+ return _rgPath;
21
+ }
22
+ export const grep = tool({
23
+ description: 'Search file contents by regex pattern using ripgrep. Returns matching lines with file paths and line numbers.',
24
+ inputSchema: z.object({
25
+ pattern: z.string().describe('Regex pattern to search for'),
26
+ path: z.string().optional().describe('File or directory to search in (defaults to working directory)'),
27
+ glob: z.string().optional().describe('Glob pattern to filter files (e.g. "*.ts", "*.{ts,tsx}")'),
28
+ maxResults: z.number().optional().describe('Max number of results (default: 50)'),
29
+ }),
30
+ execute: async ({ pattern, path: searchPath, glob: globPattern, maxResults }) => {
31
+ try {
32
+ const rgPath = getRipgrepPath();
33
+ const args = ['--no-heading', '--line-number', '--color', 'never', '--max-count', String(maxResults ?? 50)];
34
+ if (globPattern) {
35
+ args.push('--glob', globPattern);
36
+ }
37
+ args.push(pattern);
38
+ args.push(searchPath ?? process.cwd());
39
+ const { stdout } = await execFileAsync(rgPath, args, {
40
+ maxBuffer: 1024 * 1024,
41
+ timeout: 30000,
42
+ });
43
+ return stdout.trim() || 'No matches found.';
44
+ }
45
+ catch (err) {
46
+ if (err && typeof err === 'object' && 'code' in err && err.code === 1) {
47
+ return 'No matches found.';
48
+ }
49
+ const msg = err instanceof Error ? err.message : String(err);
50
+ return `Error searching: ${msg}`;
51
+ }
52
+ },
53
+ });
54
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../src/tools/grep.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAA;AAEzC,IAAI,OAAO,GAAkB,IAAI,CAAA;AAEjC,SAAS,cAAc;IACrB,IAAI,OAAO;QAAE,OAAO,OAAO,CAAA;IAC3B,IAAI,CAAC;QACH,2CAA2C;QAC3C,iEAAiE;QACjE,MAAM,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAuB,CAAA;QAC3D,OAAO,GAAG,EAAE,CAAC,MAAM,CAAA;IACrB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,IAAI,CAAA;IAChB,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC;IACvB,WAAW,EACT,+GAA+G;IACjH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;QAC3D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gEAAgE,CAAC;QACtG,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0DAA0D,CAAC;QAChG,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;KAClF,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,EAAE,EAAE;QAC9E,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,cAAc,EAAE,CAAA;YAC/B,MAAM,IAAI,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAA;YAC3G,IAAI,WAAW,EAAE,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAA;YAClC,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAClB,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;YAEtC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE;gBACnD,SAAS,EAAE,IAAI,GAAG,IAAI;gBACtB,OAAO,EAAE,KAAK;aACf,CAAC,CAAA;YACF,OAAO,MAAM,CAAC,IAAI,EAAE,IAAI,mBAAmB,CAAA;QAC7C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACtE,OAAO,mBAAmB,CAAA;YAC5B,CAAC;YACD,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,OAAO,oBAAoB,GAAG,EAAE,CAAA;QAClC,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,77 @@
1
+ import { askUser } from './ask-user.js';
2
+ import { edit } from './edit.js';
3
+ import { enterPlanMode } from './enter-plan-mode.js';
4
+ import { exitPlanMode } from './exit-plan-mode.js';
5
+ import { glob } from './glob.js';
6
+ import { grep } from './grep.js';
7
+ import { listDir } from './list-dir.js';
8
+ import { readFile } from './read-file.js';
9
+ import { saveKnowledge } from './save-knowledge.js';
10
+ import { shell } from './shell.js';
11
+ import { webFetch } from './web-fetch.js';
12
+ import { webSearch } from './web-search.js';
13
+ import { writeFile } from './write-file.js';
14
+ export declare const toolRegistry: {
15
+ readFile: import("ai").Tool<{
16
+ filePath: string;
17
+ offset?: number | undefined;
18
+ limit?: number | undefined;
19
+ }, string>;
20
+ writeFile: import("ai").Tool<{
21
+ filePath: string;
22
+ content: string;
23
+ }, never>;
24
+ edit: import("ai").Tool<{
25
+ filePath: string;
26
+ oldString: string;
27
+ newString: string;
28
+ replaceAll?: boolean | undefined;
29
+ }, never>;
30
+ shell: import("ai").Tool<{
31
+ command: string;
32
+ timeout?: number | undefined;
33
+ }, never>;
34
+ glob: import("ai").Tool<{
35
+ pattern: string;
36
+ cwd?: string | undefined;
37
+ }, string>;
38
+ grep: import("ai").Tool<{
39
+ pattern: string;
40
+ path?: string | undefined;
41
+ glob?: string | undefined;
42
+ maxResults?: number | undefined;
43
+ }, string>;
44
+ listDir: import("ai").Tool<{
45
+ dirPath: string;
46
+ }, string>;
47
+ webSearch: import("ai").Tool<{
48
+ query: string;
49
+ maxResults?: number | undefined;
50
+ }, string>;
51
+ webFetch: import("ai").Tool<{
52
+ url: string;
53
+ prompt?: string | undefined;
54
+ }, string>;
55
+ askUser: import("ai").Tool<{
56
+ options: {
57
+ description: string;
58
+ label: string;
59
+ }[];
60
+ question: string;
61
+ }, never>;
62
+ saveKnowledge: import("ai").Tool<{
63
+ action: "add" | "delete";
64
+ key: string;
65
+ fact: string;
66
+ scope: "project" | "global";
67
+ category: "tech-stack" | "commands" | "conventions" | "preferences" | "context";
68
+ }, string>;
69
+ enterPlanMode: import("ai").Tool<{}, never>;
70
+ exitPlanMode: import("ai").Tool<{}, never>;
71
+ };
72
+ export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, enterPlanMode, exitPlanMode, };
73
+ /** Max characters for tool results before truncation */
74
+ export declare const MAX_TOOL_RESULT_CHARS = 30000;
75
+ /** Truncate tool result, keeping head and tail */
76
+ export declare function truncateToolResult(result: string): string;
77
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAcxB,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,GACb,CAAA;AAED,wDAAwD;AACxD,eAAO,MAAM,qBAAqB,QAAQ,CAAA;AAE1C,kDAAkD;AAClD,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKzD"}
@@ -0,0 +1,41 @@
1
+ // @x-code/core — Tool registry (unified export)
2
+ import { askUser } from './ask-user.js';
3
+ import { edit } from './edit.js';
4
+ import { enterPlanMode } from './enter-plan-mode.js';
5
+ import { exitPlanMode } from './exit-plan-mode.js';
6
+ import { glob } from './glob.js';
7
+ import { grep } from './grep.js';
8
+ import { listDir } from './list-dir.js';
9
+ import { readFile } from './read-file.js';
10
+ import { saveKnowledge } from './save-knowledge.js';
11
+ import { shell } from './shell.js';
12
+ import { webFetch } from './web-fetch.js';
13
+ import { webSearch } from './web-search.js';
14
+ import { writeFile } from './write-file.js';
15
+ export const toolRegistry = {
16
+ readFile,
17
+ writeFile,
18
+ edit,
19
+ shell,
20
+ glob,
21
+ grep,
22
+ listDir,
23
+ webSearch,
24
+ webFetch,
25
+ askUser,
26
+ saveKnowledge,
27
+ enterPlanMode,
28
+ exitPlanMode,
29
+ };
30
+ export { readFile, writeFile, edit, shell, glob, grep, listDir, webSearch, webFetch, askUser, saveKnowledge, enterPlanMode, exitPlanMode, };
31
+ /** Max characters for tool results before truncation */
32
+ export const MAX_TOOL_RESULT_CHARS = 30000;
33
+ /** Truncate tool result, keeping head and tail */
34
+ export function truncateToolResult(result) {
35
+ if (result.length <= MAX_TOOL_RESULT_CHARS)
36
+ return result;
37
+ const half = Math.floor(MAX_TOOL_RESULT_CHARS / 2);
38
+ const truncatedChars = result.length - MAX_TOOL_RESULT_CHARS;
39
+ return result.slice(0, half) + `\n\n... [truncated ${truncatedChars} characters] ...\n\n` + result.slice(-half);
40
+ }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAE3C,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,QAAQ;IACR,SAAS;IACT,IAAI;IACJ,KAAK;IACL,IAAI;IACJ,IAAI;IACJ,OAAO;IACP,SAAS;IACT,QAAQ;IACR,OAAO;IACP,aAAa;IACb,aAAa;IACb,YAAY;CACb,CAAA;AAED,OAAO,EACL,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,aAAa,EACb,aAAa,EACb,YAAY,GACb,CAAA;AAED,wDAAwD;AACxD,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAA;AAE1C,kDAAkD;AAClD,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,IAAI,MAAM,CAAC,MAAM,IAAI,qBAAqB;QAAE,OAAO,MAAM,CAAA;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAA;IAClD,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,GAAG,qBAAqB,CAAA;IAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,sBAAsB,cAAc,sBAAsB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAA;AACjH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare const listDir: import("ai").Tool<{
2
+ dirPath: string;
3
+ }, string>;
4
+ //# sourceMappingURL=list-dir.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dir.d.ts","sourceRoot":"","sources":["../../src/tools/list-dir.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,OAAO;;UAkBlB,CAAA"}
@@ -0,0 +1,25 @@
1
+ // @x-code/core — listDir tool
2
+ import fs from 'node:fs/promises';
3
+ import { tool } from 'ai';
4
+ import { z } from 'zod';
5
+ export const listDir = tool({
6
+ description: 'List the contents of a directory. Returns names with type indicators (/ for directories).',
7
+ inputSchema: z.object({
8
+ dirPath: z.string().describe('Absolute path to the directory'),
9
+ }),
10
+ execute: async ({ dirPath }) => {
11
+ try {
12
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
13
+ const lines = entries.map((e) => {
14
+ const suffix = e.isDirectory() ? '/' : '';
15
+ return `${e.name}${suffix}`;
16
+ });
17
+ return lines.join('\n') || '(empty directory)';
18
+ }
19
+ catch (err) {
20
+ const msg = err instanceof Error ? err.message : String(err);
21
+ return `Error listing directory: ${msg}`;
22
+ }
23
+ },
24
+ });
25
+ //# sourceMappingURL=list-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-dir.js","sourceRoot":"","sources":["../../src/tools/list-dir.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,2FAA2F;IACxG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;KAC/D,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;YAClE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;gBACzC,OAAO,GAAG,CAAC,CAAC,IAAI,GAAG,MAAM,EAAE,CAAA;YAC7B,CAAC,CAAC,CAAA;YACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAA;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,OAAO,4BAA4B,GAAG,EAAE,CAAA;QAC1C,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,6 @@
1
+ export declare const readFile: import("ai").Tool<{
2
+ filePath: string;
3
+ offset?: number | undefined;
4
+ limit?: number | undefined;
5
+ }, string>;
6
+ //# sourceMappingURL=read-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.d.ts","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,QAAQ;;;;UAqBnB,CAAA"}
@@ -0,0 +1,28 @@
1
+ // @x-code/core — readFile tool
2
+ import fs from 'node:fs/promises';
3
+ import { tool } from 'ai';
4
+ import { z } from 'zod';
5
+ export const readFile = tool({
6
+ description: 'Read the contents of a file at the given path. Returns the file content with line numbers.',
7
+ inputSchema: z.object({
8
+ filePath: z.string().describe('Absolute path to the file'),
9
+ offset: z.number().optional().describe('Start line (1-based)'),
10
+ limit: z.number().optional().describe('Max lines to read'),
11
+ }),
12
+ execute: async ({ filePath, offset, limit }) => {
13
+ try {
14
+ const content = await fs.readFile(filePath, 'utf-8');
15
+ const lines = content.split('\n');
16
+ const start = (offset ?? 1) - 1;
17
+ const end = limit ? start + limit : lines.length;
18
+ const sliced = lines.slice(start, end);
19
+ const numbered = sliced.map((line, i) => `${start + i + 1}\t${line}`);
20
+ return numbered.join('\n');
21
+ }
22
+ catch (err) {
23
+ const msg = err instanceof Error ? err.message : String(err);
24
+ return `Error reading file: ${msg}`;
25
+ }
26
+ },
27
+ });
28
+ //# sourceMappingURL=read-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-file.js","sourceRoot":"","sources":["../../src/tools/read-file.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAC/B,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAEjC,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,4FAA4F;IACzG,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAC1D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAC9D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KAC3D,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;QAC7C,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;YACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACjC,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAA;YAChD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;YACrE,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC5B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,OAAO,uBAAuB,GAAG,EAAE,CAAA;QACrC,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,8 @@
1
+ export declare const saveKnowledge: import("ai").Tool<{
2
+ action: "add" | "delete";
3
+ key: string;
4
+ fact: string;
5
+ scope: "project" | "global";
6
+ category: "tech-stack" | "commands" | "conventions" | "preferences" | "context";
7
+ }, string>;
8
+ //# sourceMappingURL=save-knowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/save-knowledge.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa;;;;;;UA+BxB,CAAA"}
@@ -0,0 +1,36 @@
1
+ // @x-code/core — saveKnowledge tool (knowledge CRUD)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ import { getAutoMemory } from '../knowledge/auto-memory.js';
5
+ export const saveKnowledge = tool({
6
+ description: 'Save, update, or delete a project/user knowledge fact in persistent memory. Use when you discover project conventions, user preferences, or important facts worth remembering for future sessions.',
7
+ inputSchema: z.object({
8
+ action: z
9
+ .enum(['add', 'delete'])
10
+ .describe('add = create or update (auto-replaces conflicting old fact), delete = remove outdated fact'),
11
+ key: z
12
+ .string()
13
+ .describe('A short unique identifier for this fact, e.g. "package-manager", "test-framework". Same key = same fact.'),
14
+ fact: z.string().describe('The fact value, e.g. "pnpm (workspace mode)", "Vitest 4"'),
15
+ scope: z.enum(['project', 'global']).describe('project = this repo (.x-code/), global = all repos (~/.xcode/)'),
16
+ category: z.enum(['tech-stack', 'commands', 'conventions', 'preferences', 'context']),
17
+ }),
18
+ execute: ({ action, key, fact, scope, category }) => {
19
+ try {
20
+ const memory = getAutoMemory(scope);
21
+ if (action === 'add') {
22
+ memory.add({ key, fact, category, date: new Date().toISOString().slice(0, 10) });
23
+ return `Knowledge saved: [${category}] ${key}: ${fact}`;
24
+ }
25
+ else {
26
+ memory.delete(key, category);
27
+ return `Knowledge deleted: [${category}] ${key}`;
28
+ }
29
+ }
30
+ catch (err) {
31
+ const msg = err instanceof Error ? err.message : String(err);
32
+ return `Error saving knowledge: ${msg}`;
33
+ }
34
+ },
35
+ });
36
+ //# sourceMappingURL=save-knowledge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"save-knowledge.js","sourceRoot":"","sources":["../../src/tools/save-knowledge.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAE3D,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,CAAC;IAChC,WAAW,EACT,oMAAoM;IACtM,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,MAAM,EAAE,CAAC;aACN,IAAI,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;aACvB,QAAQ,CAAC,4FAA4F,CAAC;QACzG,GAAG,EAAE,CAAC;aACH,MAAM,EAAE;aACR,QAAQ,CACP,0GAA0G,CAC3G;QACH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0DAA0D,CAAC;QACrF,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,gEAAgE,CAAC;QAC/G,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;KACtF,CAAC;IACF,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;QAClD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAA;YACnC,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;gBAChF,OAAO,qBAAqB,QAAQ,KAAK,GAAG,KAAK,IAAI,EAAE,CAAA;YACzD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;gBAC5B,OAAO,uBAAuB,QAAQ,KAAK,GAAG,EAAE,CAAA;YAClD,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC5D,OAAO,2BAA2B,GAAG,EAAE,CAAA;QACzC,CAAC;IACH,CAAC;CACF,CAAC,CAAA"}
@@ -0,0 +1,14 @@
1
+ export type ShellType = 'powershell' | 'bash' | 'zsh';
2
+ export interface ShellConfig {
3
+ executable: string;
4
+ args: string[];
5
+ type: ShellType;
6
+ }
7
+ export declare function getShellConfig(): ShellConfig;
8
+ /** Split compound shell commands by pipe/chain operators for permission checking */
9
+ export declare function splitShellCommands(cmd: string): string[];
10
+ /** Check if a sub-command is read-only (safe to auto-allow) */
11
+ export declare function isReadOnly(cmd: string): boolean;
12
+ /** Check if a sub-command is destructive (should be denied) */
13
+ export declare function isDestructive(cmd: string): boolean;
14
+ //# sourceMappingURL=shell-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-utils.d.ts","sourceRoot":"","sources":["../../src/tools/shell-utils.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,KAAK,CAAA;AAErD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,IAAI,EAAE,SAAS,CAAA;CAChB;AAED,wBAAgB,cAAc,IAAI,WAAW,CAO5C;AAED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CA0CxD;AAkDD,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGlD"}
@@ -0,0 +1,111 @@
1
+ // @x-code/core — Cross-platform shell detection and abstraction
2
+ import os from 'node:os';
3
+ export function getShellConfig() {
4
+ if (os.platform() === 'win32') {
5
+ return { executable: 'powershell.exe', args: ['-NoProfile', '-Command'], type: 'powershell' };
6
+ }
7
+ const userShell = process.env.SHELL ?? '/bin/bash';
8
+ const type = userShell.endsWith('zsh') ? 'zsh' : 'bash';
9
+ return { executable: userShell, args: ['-c'], type };
10
+ }
11
+ /** Split compound shell commands by pipe/chain operators for permission checking */
12
+ export function splitShellCommands(cmd) {
13
+ // Split by |, &&, ;, || — but not inside quotes
14
+ const parts = [];
15
+ let current = '';
16
+ let inSingleQuote = false;
17
+ let inDoubleQuote = false;
18
+ for (let i = 0; i < cmd.length; i++) {
19
+ const ch = cmd[i];
20
+ const next = cmd[i + 1];
21
+ if (ch === "'" && !inDoubleQuote) {
22
+ inSingleQuote = !inSingleQuote;
23
+ current += ch;
24
+ }
25
+ else if (ch === '"' && !inSingleQuote) {
26
+ inDoubleQuote = !inDoubleQuote;
27
+ current += ch;
28
+ }
29
+ else if (!inSingleQuote && !inDoubleQuote) {
30
+ if (ch === '|' && next === '|') {
31
+ parts.push(current);
32
+ current = '';
33
+ i++; // skip next |
34
+ }
35
+ else if (ch === '&' && next === '&') {
36
+ parts.push(current);
37
+ current = '';
38
+ i++; // skip next &
39
+ }
40
+ else if (ch === '|') {
41
+ parts.push(current);
42
+ current = '';
43
+ }
44
+ else if (ch === ';') {
45
+ parts.push(current);
46
+ current = '';
47
+ }
48
+ else {
49
+ current += ch;
50
+ }
51
+ }
52
+ else {
53
+ current += ch;
54
+ }
55
+ }
56
+ if (current.trim())
57
+ parts.push(current);
58
+ return parts.map((p) => p.trim()).filter(Boolean);
59
+ }
60
+ /** Unix/PowerShell commands that are safe to auto-allow */
61
+ const READ_ONLY_COMMANDS = [
62
+ 'cd',
63
+ 'ls',
64
+ 'dir',
65
+ 'pwd',
66
+ 'cat',
67
+ 'head',
68
+ 'tail',
69
+ 'wc',
70
+ 'echo',
71
+ 'which',
72
+ 'type',
73
+ 'file',
74
+ 'stat',
75
+ 'du',
76
+ 'df',
77
+ 'env',
78
+ 'printenv',
79
+ 'find',
80
+ 'tree',
81
+ // PowerShell
82
+ 'Get-ChildItem',
83
+ 'Get-Location',
84
+ 'Get-Content',
85
+ 'Select-String',
86
+ 'Test-Path',
87
+ ];
88
+ /** Git sub-commands that are read-only */
89
+ const READ_ONLY_GIT_SUBCOMMANDS = ['status', 'log', 'diff', 'branch', 'show', 'remote', 'tag'];
90
+ // Pre-compiled regexes for performance
91
+ const READ_ONLY_REGEX = new RegExp(`^\\s*(${READ_ONLY_COMMANDS.join('|')}|git\\s+(${READ_ONLY_GIT_SUBCOMMANDS.join('|')}))\\b`);
92
+ const DESTRUCTIVE_PATTERNS = [
93
+ /\brm\s+(-[a-z]*f|-[a-z]*r|--force|--recursive)/,
94
+ /\bsudo\b/,
95
+ /\bmkfs\b/,
96
+ /\bdd\s+if=/,
97
+ /\b(chmod|chown)\s+.*\//,
98
+ />\s*\/dev\/sd/,
99
+ /\bformat\b/,
100
+ /\bRemove-Item\s+.*-Recurse/,
101
+ ];
102
+ /** Check if a sub-command is read-only (safe to auto-allow) */
103
+ export function isReadOnly(cmd) {
104
+ return READ_ONLY_REGEX.test(cmd.trim());
105
+ }
106
+ /** Check if a sub-command is destructive (should be denied) */
107
+ export function isDestructive(cmd) {
108
+ const c = cmd.trim();
109
+ return DESTRUCTIVE_PATTERNS.some((pattern) => pattern.test(c));
110
+ }
111
+ //# sourceMappingURL=shell-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-utils.js","sourceRoot":"","sources":["../../src/tools/shell-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare const shell: import("ai").Tool<{
2
+ command: string;
3
+ timeout?: number | undefined;
4
+ }, never>;
5
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK;;;SAQhB,CAAA"}
@@ -0,0 +1,12 @@
1
+ // @x-code/core — shell tool (cross-platform command execution, no execute — needs permission check)
2
+ import { tool } from 'ai';
3
+ import { z } from 'zod';
4
+ export const shell = tool({
5
+ description: 'Execute a shell command and return stdout/stderr. Commands should be compatible with the current platform shell.',
6
+ inputSchema: z.object({
7
+ command: z.string().describe('The command to execute'),
8
+ timeout: z.number().optional().describe('Timeout in milliseconds (default: 30000)'),
9
+ }),
10
+ // No execute — handled manually in agent loop for permission check + cross-platform shell + streaming
11
+ });
12
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/tools/shell.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAA;AAEzB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC;IACxB,WAAW,EACT,kHAAkH;IACpH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QACtD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0CAA0C,CAAC;KACpF,CAAC;IACF,sGAAsG;CACvG,CAAC,CAAA"}
@@ -0,0 +1,5 @@
1
+ export declare const webFetch: import("ai").Tool<{
2
+ url: string;
3
+ prompt?: string | undefined;
4
+ }, string>;
5
+ //# sourceMappingURL=web-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,QAAQ;;;UAkDnB,CAAA"}