mocode-ai 0.7.0 → 0.7.2

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.
@@ -0,0 +1,96 @@
1
+ import { existsSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ const TEST_FILE = /(?:^|[/\\])(?:__tests__[/\\].+|.+\.(?:test|spec))\.[cm]?[jt]sx?$/i;
4
+ const SOURCE_EXTENSION = /\.[cm]?[jt]sx?$/i;
5
+ function isFile(file) {
6
+ try {
7
+ return statSync(file).isFile();
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ }
13
+ function inside(root, candidate) {
14
+ const relative = path.relative(root, candidate);
15
+ return relative === '' || (!relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative));
16
+ }
17
+ function quoteArg(value) {
18
+ if (process.platform === 'win32')
19
+ return `"${value.replace(/%/g, '%%').replace(/"/g, '""')}"`;
20
+ return `'${value.replace(/'/g, `'\\''`)}'`;
21
+ }
22
+ function adapterFor(script) {
23
+ if (/\bvitest\b/i.test(script))
24
+ return 'vitest';
25
+ if (/\bjest\b/i.test(script))
26
+ return 'jest';
27
+ if (/\bnode\s+--test\b/i.test(script))
28
+ return 'node-test';
29
+ return null;
30
+ }
31
+ function candidateTests(source) {
32
+ if (TEST_FILE.test(source))
33
+ return [source];
34
+ if (!SOURCE_EXTENSION.test(source) || source.endsWith('.d.ts'))
35
+ return [];
36
+ const extension = path.extname(source);
37
+ const stem = source.slice(0, -extension.length);
38
+ const base = path.basename(stem);
39
+ const directory = path.dirname(source);
40
+ return [
41
+ `${stem}.test${extension}`,
42
+ `${stem}.spec${extension}`,
43
+ path.join(directory, '__tests__', `${base}.test${extension}`),
44
+ path.join(directory, '__tests__', `${base}.spec${extension}`),
45
+ ];
46
+ }
47
+ function runnerArgs(adapter, script) {
48
+ if (adapter === 'vitest' && !/\bvitest\s+run\b/i.test(script))
49
+ return ['--run'];
50
+ if (adapter === 'jest')
51
+ return ['--runInBand'];
52
+ return [];
53
+ }
54
+ /** Discover reliable direct/co-located tests without crossing package boundaries. */
55
+ export function discoverTargetedTestCommands(profile, affectedPackages) {
56
+ const selected = [];
57
+ for (const affected of affectedPackages) {
58
+ const script = affected.package.scripts.test;
59
+ if (typeof script !== 'string')
60
+ continue;
61
+ const adapter = adapterFor(script);
62
+ if (!adapter)
63
+ continue;
64
+ const files = new Set();
65
+ for (const reason of affected.reasons) {
66
+ if (reason.kind !== 'direct_change')
67
+ continue;
68
+ const changed = path.resolve(profile.root, reason.changedPath);
69
+ if (!inside(affected.package.root, changed))
70
+ continue;
71
+ for (const candidate of candidateTests(changed)) {
72
+ if (existsSync(candidate) && isFile(candidate) && inside(affected.package.root, candidate)) {
73
+ files.add(candidate);
74
+ }
75
+ }
76
+ }
77
+ if (files.size === 0)
78
+ continue;
79
+ const relativeFiles = [...files]
80
+ .map((file) => path.relative(affected.package.root, file))
81
+ .sort();
82
+ const args = [...runnerArgs(adapter, script), ...relativeFiles].map(quoteArg).join(' ');
83
+ selected.push({
84
+ affected,
85
+ adapter,
86
+ files: relativeFiles,
87
+ command: {
88
+ script: 'test',
89
+ command: `${profile.packageManager} run test -- ${args}`,
90
+ packageManager: profile.packageManager,
91
+ cwd: affected.package.root,
92
+ },
93
+ });
94
+ }
95
+ return selected;
96
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mocode-ai",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "终端编码 agent:LLM + tool-call 循环 + 流式输出(含思考)+ 16 个工具,接任意 OpenAI 兼容后端。",
5
5
  "type": "module",
6
6
  "bin": {
@@ -20,7 +20,10 @@
20
20
  "scripts": {
21
21
  "start": "tsx src/index.ts",
22
22
  "build": "tsc -p tsconfig.build.json",
23
- "typecheck": "tsc --noEmit",
23
+ "typecheck": "tsc --noEmit && tsc -p evals/tsconfig.json",
24
+ "eval:smoke": "tsx evals/smoke.ts && tsx evals/coding/smoke.ts",
25
+ "eval:coding": "tsx evals/coding/runner.ts",
26
+ "eval:coding:list": "tsx evals/coding/runner.ts --list",
24
27
  "prepare": "npm run build"
25
28
  },
26
29
  "dependencies": {