scalix 0.0.1 → 1.0.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 (48) hide show
  1. package/CHANGELOG.md +122 -0
  2. package/LICENSE +100 -0
  3. package/README.md +300 -2
  4. package/app.py +55 -0
  5. package/bin/scalix.js +19 -0
  6. package/dist/agent-replay.js +166 -0
  7. package/dist/agent.js +852 -0
  8. package/dist/auto-verify.js +136 -0
  9. package/dist/change-tracker.js +53 -0
  10. package/dist/cli.js +2329 -0
  11. package/dist/commands.js +71 -0
  12. package/dist/config.js +16 -0
  13. package/dist/constants.js +324 -0
  14. package/dist/context-builder.js +151 -0
  15. package/dist/context-manager.js +148 -0
  16. package/dist/cost-tracker.js +85 -0
  17. package/dist/diff.js +140 -0
  18. package/dist/git-context.js +180 -0
  19. package/dist/git-undo.js +67 -0
  20. package/dist/headless.js +654 -0
  21. package/dist/hooks.js +94 -0
  22. package/dist/ipc-server.js +228 -0
  23. package/dist/logger.js +45 -0
  24. package/dist/markdown.js +41 -0
  25. package/dist/mcp.js +49 -0
  26. package/dist/model-router.js +68 -0
  27. package/dist/plugins.js +132 -0
  28. package/dist/project-index.js +374 -0
  29. package/dist/project-memory.js +165 -0
  30. package/dist/safe-math.js +194 -0
  31. package/dist/sandbox.js +279 -0
  32. package/dist/scoped-rules.js +82 -0
  33. package/dist/sessions.js +71 -0
  34. package/dist/settings.js +155 -0
  35. package/dist/sub-agent.js +79 -0
  36. package/dist/token-counter.js +47 -0
  37. package/dist/tool-helper.js +97 -0
  38. package/dist/tool-selector.js +77 -0
  39. package/dist/tools-advanced.js +232 -0
  40. package/dist/tools-browser.js +273 -0
  41. package/dist/tools-extra.js +383 -0
  42. package/dist/tools-vision.js +115 -0
  43. package/dist/tools-voice.js +147 -0
  44. package/dist/tools-web.js +346 -0
  45. package/dist/tools.js +370 -0
  46. package/dist/types.js +1 -0
  47. package/docs/DISTRIBUTION.md +301 -0
  48. package/package.json +67 -6
@@ -0,0 +1,136 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { promisify } from 'node:util';
3
+ import fs from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ const execFileAsync = promisify(execFile);
6
+ export const VERIFY_DEFAULTS = {
7
+ enabled: true,
8
+ timeoutMs: 15_000,
9
+ maxOutputChars: 3000,
10
+ maxFailRetries: 3,
11
+ };
12
+ const CHECKER_REGISTRY = [
13
+ {
14
+ name: 'tsc',
15
+ detectFiles: ['tsconfig.json'],
16
+ detectExtensions: ['.ts', '.tsx'],
17
+ command: ['npx', 'tsc', '--noEmit', '--pretty'],
18
+ fileSpecific: false,
19
+ },
20
+ {
21
+ name: 'cargo',
22
+ detectFiles: ['Cargo.toml'],
23
+ detectExtensions: ['.rs'],
24
+ command: ['cargo', 'check', '--message-format=short'],
25
+ fileSpecific: false,
26
+ },
27
+ {
28
+ name: 'go-vet',
29
+ detectFiles: ['go.mod'],
30
+ detectExtensions: ['.go'],
31
+ command: ['go', 'vet', './...'],
32
+ fileSpecific: false,
33
+ },
34
+ {
35
+ name: 'python',
36
+ detectFiles: [],
37
+ detectExtensions: ['.py'],
38
+ command: ['python3', '-m', 'py_compile'],
39
+ fileSpecific: true,
40
+ },
41
+ {
42
+ name: 'ruby',
43
+ detectFiles: [],
44
+ detectExtensions: ['.rb'],
45
+ command: ['ruby', '-c'],
46
+ fileSpecific: true,
47
+ },
48
+ ];
49
+ // Cache detected checker per project root to avoid repeated filesystem probes
50
+ const checkerCache = new Map();
51
+ async function fileExists(filePath) {
52
+ try {
53
+ await fs.access(filePath);
54
+ return true;
55
+ }
56
+ catch {
57
+ return false;
58
+ }
59
+ }
60
+ async function detectChecker(filePath, projectRoot) {
61
+ const ext = path.extname(filePath);
62
+ // Check cache first (keyed by root + extension category)
63
+ const cacheKey = `${projectRoot}:${ext}`;
64
+ if (checkerCache.has(cacheKey)) {
65
+ return checkerCache.get(cacheKey);
66
+ }
67
+ for (const checker of CHECKER_REGISTRY) {
68
+ if (!checker.detectExtensions.includes(ext))
69
+ continue;
70
+ if (checker.detectFiles.length > 0) {
71
+ const found = await Promise.all(checker.detectFiles.map((f) => fileExists(path.join(projectRoot, f))));
72
+ if (!found.some(Boolean))
73
+ continue;
74
+ }
75
+ // Verify the tool is available
76
+ try {
77
+ await execFileAsync('which', [checker.command[0]], { timeout: 3000 });
78
+ }
79
+ catch {
80
+ // Tool not installed, skip
81
+ checkerCache.set(cacheKey, null);
82
+ continue;
83
+ }
84
+ checkerCache.set(cacheKey, checker);
85
+ return checker;
86
+ }
87
+ checkerCache.set(cacheKey, null);
88
+ return null;
89
+ }
90
+ export async function runVerification(filePath, projectRoot, config = VERIFY_DEFAULTS) {
91
+ const checker = await detectChecker(filePath, projectRoot);
92
+ if (!checker)
93
+ return null;
94
+ const start = Date.now();
95
+ const args = checker.fileSpecific
96
+ ? [...checker.command.slice(1), filePath]
97
+ : [...checker.command.slice(1)];
98
+ try {
99
+ const { stdout, stderr } = await execFileAsync(checker.command[0], args, {
100
+ cwd: projectRoot,
101
+ timeout: config.timeoutMs,
102
+ maxBuffer: 512 * 1024,
103
+ });
104
+ const output = (stderr || stdout).trim();
105
+ return {
106
+ passed: true,
107
+ checker: checker.name,
108
+ output: output.slice(0, config.maxOutputChars),
109
+ file: filePath,
110
+ durationMs: Date.now() - start,
111
+ };
112
+ }
113
+ catch (err) {
114
+ // Exit code != 0 means verification found errors
115
+ if (err.killed) {
116
+ return {
117
+ passed: false,
118
+ checker: `${checker.name} (timeout)`,
119
+ output: 'Verification timed out — treat as failed. Fix errors or increase timeout.',
120
+ file: filePath,
121
+ durationMs: Date.now() - start,
122
+ };
123
+ }
124
+ const output = ((err.stderr || '') + '\n' + (err.stdout || '')).trim();
125
+ return {
126
+ passed: false,
127
+ checker: checker.name,
128
+ output: output.slice(0, config.maxOutputChars),
129
+ file: filePath,
130
+ durationMs: Date.now() - start,
131
+ };
132
+ }
133
+ }
134
+ export function clearCheckerCache() {
135
+ checkerCache.clear();
136
+ }
@@ -0,0 +1,53 @@
1
+ export class ChangeTracker {
2
+ changes = [];
3
+ track(filePath, toolName) {
4
+ this.changes.push({
5
+ filePath,
6
+ toolName,
7
+ timestamp: Date.now(),
8
+ verified: false,
9
+ verifyPassed: false,
10
+ });
11
+ }
12
+ markVerified(filePath, passed) {
13
+ for (let i = this.changes.length - 1; i >= 0; i--) {
14
+ if (this.changes[i].filePath === filePath && !this.changes[i].verified) {
15
+ this.changes[i].verified = true;
16
+ this.changes[i].verifyPassed = passed;
17
+ break;
18
+ }
19
+ }
20
+ }
21
+ getChangedFiles() {
22
+ const seen = new Set();
23
+ return this.changes
24
+ .map((c) => c.filePath)
25
+ .filter((f) => {
26
+ if (seen.has(f))
27
+ return false;
28
+ seen.add(f);
29
+ return true;
30
+ });
31
+ }
32
+ getChanges() {
33
+ return [...this.changes];
34
+ }
35
+ getSessionSummary() {
36
+ if (this.changes.length === 0)
37
+ return 'No files modified this session.';
38
+ const files = this.getChangedFiles();
39
+ const verified = this.changes.filter((c) => c.verified && c.verifyPassed).length;
40
+ const failed = this.changes.filter((c) => c.verified && !c.verifyPassed).length;
41
+ const lines = [
42
+ `Files modified: ${files.length}`,
43
+ ...files.map((f) => ` ${f}`),
44
+ ];
45
+ if (verified > 0 || failed > 0) {
46
+ lines.push(`Verification: ${verified} passed, ${failed} failed`);
47
+ }
48
+ return lines.join('\n');
49
+ }
50
+ clear() {
51
+ this.changes = [];
52
+ }
53
+ }