@zigrivers/mmr 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.
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +21 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +7 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +98 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/jobs.d.ts +7 -0
- package/dist/commands/jobs.d.ts.map +1 -0
- package/dist/commands/jobs.js +48 -0
- package/dist/commands/jobs.js.map +1 -0
- package/dist/commands/results.d.ts +9 -0
- package/dist/commands/results.d.ts.map +1 -0
- package/dist/commands/results.js +145 -0
- package/dist/commands/results.js.map +1 -0
- package/dist/commands/review.d.ts +18 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +203 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +56 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config/defaults.d.ts +12 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +69 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +23 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +100 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +207 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +38 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/auth.d.ts +17 -0
- package/dist/core/auth.d.ts.map +1 -0
- package/dist/core/auth.js +60 -0
- package/dist/core/auth.js.map +1 -0
- package/dist/core/dispatcher.d.ts +15 -0
- package/dist/core/dispatcher.d.ts.map +1 -0
- package/dist/core/dispatcher.js +107 -0
- package/dist/core/dispatcher.js.map +1 -0
- package/dist/core/job-store.d.ts +46 -0
- package/dist/core/job-store.d.ts.map +1 -0
- package/dist/core/job-store.js +141 -0
- package/dist/core/job-store.js.map +1 -0
- package/dist/core/parser.d.ts +16 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +123 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/prompt.d.ts +26 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +53 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/reconciler.d.ts +17 -0
- package/dist/core/reconciler.d.ts.map +1 -0
- package/dist/core/reconciler.js +84 -0
- package/dist/core/reconciler.js.map +1 -0
- package/dist/formatters/json.d.ts +3 -0
- package/dist/formatters/json.d.ts.map +1 -0
- package/dist/formatters/json.js +4 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/formatters/markdown.d.ts +3 -0
- package/dist/formatters/markdown.d.ts.map +1 -0
- package/dist/formatters/markdown.js +36 -0
- package/dist/formatters/markdown.js.map +1 -0
- package/dist/formatters/text.d.ts +3 -0
- package/dist/formatters/text.d.ts.map +1 -0
- package/dist/formatters/text.js +31 -0
- package/dist/formatters/text.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +59 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +45 -0
- package/templates/core-prompt.md +33 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import { JobStore } from '../core/job-store.js';
|
|
4
|
+
export const statusCommand = {
|
|
5
|
+
command: 'status <job-id>',
|
|
6
|
+
describe: 'Check the status of a review job',
|
|
7
|
+
builder: (yargs) => yargs.positional('job-id', {
|
|
8
|
+
type: 'string',
|
|
9
|
+
demandOption: true,
|
|
10
|
+
describe: 'Job ID (e.g. mmr-abc123)',
|
|
11
|
+
}),
|
|
12
|
+
handler: (args) => {
|
|
13
|
+
const jobsDir = path.join(os.homedir(), '.mmr', 'jobs');
|
|
14
|
+
const store = new JobStore(jobsDir);
|
|
15
|
+
let job;
|
|
16
|
+
try {
|
|
17
|
+
job = store.loadJob(args['job-id']);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
console.error(`Job not found: ${args['job-id']}`);
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
const channelStatuses = {};
|
|
24
|
+
let allComplete = true;
|
|
25
|
+
let anyFailed = false;
|
|
26
|
+
for (const [name, entry] of Object.entries(job.channels)) {
|
|
27
|
+
const elapsed = entry.started_at && entry.completed_at
|
|
28
|
+
? `${((new Date(entry.completed_at).getTime() - new Date(entry.started_at).getTime()) / 1000).toFixed(1)}s`
|
|
29
|
+
: entry.started_at
|
|
30
|
+
? 'running'
|
|
31
|
+
: undefined;
|
|
32
|
+
channelStatuses[name] = { status: entry.status, elapsed };
|
|
33
|
+
if (!['completed', 'failed', 'timeout', 'auth_failed', 'skipped'].includes(entry.status)) {
|
|
34
|
+
allComplete = false;
|
|
35
|
+
}
|
|
36
|
+
if (['failed', 'timeout', 'auth_failed'].includes(entry.status)) {
|
|
37
|
+
anyFailed = true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const output = {
|
|
41
|
+
job_id: job.job_id,
|
|
42
|
+
status: job.status,
|
|
43
|
+
channels: channelStatuses,
|
|
44
|
+
};
|
|
45
|
+
console.log(JSON.stringify(output, null, 2));
|
|
46
|
+
// Exit codes: 0 = all complete, 1 = still running, 2 = at least one failed
|
|
47
|
+
if (!allComplete) {
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
if (anyFailed) {
|
|
51
|
+
process.exit(2);
|
|
52
|
+
}
|
|
53
|
+
process.exit(0);
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MmrConfigParsed, ChannelConfigParsed } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default configuration applied when no config files are present.
|
|
4
|
+
* version is set to 1 as the baseline; loadConfig supplies it
|
|
5
|
+
* before Zod validation so partial user/project configs work.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_CONFIG: MmrConfigParsed;
|
|
8
|
+
/**
|
|
9
|
+
* Built-in channel presets. Users can override any field via config files.
|
|
10
|
+
*/
|
|
11
|
+
export declare const BUILTIN_CHANNELS: Record<string, ChannelConfigParsed>;
|
|
12
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEvE;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,eAU5B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CA8ChE,CAAA"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default configuration applied when no config files are present.
|
|
3
|
+
* version is set to 1 as the baseline; loadConfig supplies it
|
|
4
|
+
* before Zod validation so partial user/project configs work.
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_CONFIG = {
|
|
7
|
+
version: 1,
|
|
8
|
+
defaults: {
|
|
9
|
+
fix_threshold: 'P2',
|
|
10
|
+
timeout: 300,
|
|
11
|
+
format: 'json',
|
|
12
|
+
parallel: true,
|
|
13
|
+
job_retention_days: 7,
|
|
14
|
+
},
|
|
15
|
+
channels: {}, // Populated below after BUILTIN_CHANNELS definition
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Built-in channel presets. Users can override any field via config files.
|
|
19
|
+
*/
|
|
20
|
+
export const BUILTIN_CHANNELS = {
|
|
21
|
+
claude: {
|
|
22
|
+
enabled: true,
|
|
23
|
+
command: 'claude -p',
|
|
24
|
+
flags: ['--output-format', 'json'],
|
|
25
|
+
env: {},
|
|
26
|
+
auth: {
|
|
27
|
+
check: 'claude -p "respond with ok" 2>/dev/null',
|
|
28
|
+
timeout: 5,
|
|
29
|
+
failure_exit_codes: [1],
|
|
30
|
+
recovery: 'Run: claude login',
|
|
31
|
+
},
|
|
32
|
+
prompt_wrapper: '{{prompt}}',
|
|
33
|
+
output_parser: 'claude',
|
|
34
|
+
stderr: 'capture',
|
|
35
|
+
},
|
|
36
|
+
gemini: {
|
|
37
|
+
enabled: true,
|
|
38
|
+
command: 'gemini -p',
|
|
39
|
+
flags: ['--output-format', 'json'],
|
|
40
|
+
env: { NO_BROWSER: 'true' },
|
|
41
|
+
auth: {
|
|
42
|
+
check: 'NO_BROWSER=true gemini -p "respond with ok" -o json 2>&1',
|
|
43
|
+
timeout: 5,
|
|
44
|
+
failure_exit_codes: [41],
|
|
45
|
+
recovery: 'Run: gemini -p "hello"',
|
|
46
|
+
},
|
|
47
|
+
prompt_wrapper: '{{prompt}}',
|
|
48
|
+
output_parser: 'gemini',
|
|
49
|
+
stderr: 'capture',
|
|
50
|
+
},
|
|
51
|
+
codex: {
|
|
52
|
+
enabled: true,
|
|
53
|
+
command: 'codex exec',
|
|
54
|
+
flags: ['--skip-git-repo-check', '-s', 'read-only', '--ephemeral'],
|
|
55
|
+
env: {},
|
|
56
|
+
auth: {
|
|
57
|
+
check: 'codex login status 2>/dev/null',
|
|
58
|
+
timeout: 5,
|
|
59
|
+
failure_exit_codes: [1],
|
|
60
|
+
recovery: 'Run: codex login',
|
|
61
|
+
},
|
|
62
|
+
prompt_wrapper: '{{prompt}}',
|
|
63
|
+
output_parser: 'codex',
|
|
64
|
+
stderr: 'suppress',
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
// Seed DEFAULT_CONFIG with builtin channels
|
|
68
|
+
DEFAULT_CONFIG.channels = { ...BUILTIN_CHANNELS };
|
|
69
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE;QACR,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,GAAG;QACZ,MAAM,EAAE,MAAM;QACd,QAAQ,EAAE,IAAI;QACd,kBAAkB,EAAE,CAAC;KACtB;IACD,QAAQ,EAAE,EAAyC,EAAE,oDAAoD;CAC1G,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAwC;IACnE,MAAM,EAAE;QACN,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,WAAW;QACpB,KAAK,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC;QAClC,GAAG,EAAE,EAAE;QACP,IAAI,EAAE;YACJ,KAAK,EAAE,yCAAyC;YAChD,OAAO,EAAE,CAAC;YACV,kBAAkB,EAAE,CAAC,CAAC,CAAC;YACvB,QAAQ,EAAE,mBAAmB;SAC9B;QACD,cAAc,EAAE,YAAY;QAC5B,aAAa,EAAE,QAAQ;QACvB,MAAM,EAAE,SAAS;KAClB;IACD,MAAM,EAAE;QACN,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,WAAW;QACpB,KAAK,EAAE,CAAC,iBAAiB,EAAE,MAAM,CAAC;QAClC,GAAG,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;QAC3B,IAAI,EAAE;YACJ,KAAK,EAAE,0DAA0D;YACjE,OAAO,EAAE,CAAC;YACV,kBAAkB,EAAE,CAAC,EAAE,CAAC;YACxB,QAAQ,EAAE,wBAAwB;SACnC;QACD,cAAc,EAAE,YAAY;QAC5B,aAAa,EAAE,QAAQ;QACvB,MAAM,EAAE,SAAS;KAClB;IACD,KAAK,EAAE;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,YAAY;QACrB,KAAK,EAAE,CAAC,uBAAuB,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,CAAC;QAClE,GAAG,EAAE,EAAE;QACP,IAAI,EAAE;YACJ,KAAK,EAAE,gCAAgC;YACvC,OAAO,EAAE,CAAC;YACV,kBAAkB,EAAE,CAAC,CAAC,CAAC;YACvB,QAAQ,EAAE,kBAAkB;SAC7B;QACD,cAAc,EAAE,YAAY;QAC5B,aAAa,EAAE,OAAO;QACtB,MAAM,EAAE,UAAU;KACnB;CACF,CAAA;AAED,4CAA4C;AAC5C,cAAc,CAAC,QAAQ,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type MmrConfigParsed } from './schema.js';
|
|
2
|
+
export interface LoadConfigOptions {
|
|
3
|
+
projectRoot: string;
|
|
4
|
+
userHome?: string;
|
|
5
|
+
cliOverrides?: {
|
|
6
|
+
fix_threshold?: string;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
format?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Load and merge configuration from multiple sources.
|
|
13
|
+
*
|
|
14
|
+
* Merge order (later wins):
|
|
15
|
+
* 1. Built-in defaults
|
|
16
|
+
* 2. User config (~/.mmr/config.yaml)
|
|
17
|
+
* 3. Project config (.mmr.yaml in projectRoot)
|
|
18
|
+
* 4. CLI overrides
|
|
19
|
+
*
|
|
20
|
+
* The merged result is validated through MmrConfigSchema.parse().
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadConfig(opts: LoadConfigOptions): MmrConfigParsed;
|
|
23
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAA;AAGnE,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE;QACb,aAAa,CAAC,EAAE,MAAM,CAAA;QACtB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF;AAuDD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAmCnE"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import yaml from 'js-yaml';
|
|
5
|
+
import { MmrConfigSchema } from './schema.js';
|
|
6
|
+
import { DEFAULT_CONFIG } from './defaults.js';
|
|
7
|
+
/**
|
|
8
|
+
* Deep-merge two plain objects. Arrays replace (not concat).
|
|
9
|
+
* Primitives from `overlay` win over `base`.
|
|
10
|
+
*/
|
|
11
|
+
function deepMerge(base, overlay) {
|
|
12
|
+
const result = { ...base };
|
|
13
|
+
for (const key of Object.keys(overlay)) {
|
|
14
|
+
const baseVal = result[key];
|
|
15
|
+
const overVal = overlay[key];
|
|
16
|
+
if (overVal !== null &&
|
|
17
|
+
typeof overVal === 'object' &&
|
|
18
|
+
!Array.isArray(overVal) &&
|
|
19
|
+
baseVal !== null &&
|
|
20
|
+
typeof baseVal === 'object' &&
|
|
21
|
+
!Array.isArray(baseVal)) {
|
|
22
|
+
result[key] = deepMerge(baseVal, overVal);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
result[key] = overVal;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Try to read and parse a YAML file; returns undefined if missing.
|
|
32
|
+
*/
|
|
33
|
+
function loadYaml(filePath) {
|
|
34
|
+
if (!fs.existsSync(filePath))
|
|
35
|
+
return undefined;
|
|
36
|
+
let raw;
|
|
37
|
+
try {
|
|
38
|
+
raw = fs.readFileSync(filePath, 'utf-8');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
let parsed;
|
|
44
|
+
try {
|
|
45
|
+
parsed = yaml.load(raw);
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
throw new Error(`Failed to parse ${filePath}: ${msg}`);
|
|
50
|
+
}
|
|
51
|
+
if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
52
|
+
throw new Error(`Invalid config in ${filePath}: expected an object, got ${typeof parsed}`);
|
|
53
|
+
}
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Load and merge configuration from multiple sources.
|
|
58
|
+
*
|
|
59
|
+
* Merge order (later wins):
|
|
60
|
+
* 1. Built-in defaults
|
|
61
|
+
* 2. User config (~/.mmr/config.yaml)
|
|
62
|
+
* 3. Project config (.mmr.yaml in projectRoot)
|
|
63
|
+
* 4. CLI overrides
|
|
64
|
+
*
|
|
65
|
+
* The merged result is validated through MmrConfigSchema.parse().
|
|
66
|
+
*/
|
|
67
|
+
export function loadConfig(opts) {
|
|
68
|
+
const { projectRoot, cliOverrides } = opts;
|
|
69
|
+
const userHome = opts.userHome ?? os.homedir();
|
|
70
|
+
// Start with defaults
|
|
71
|
+
let merged = structuredClone(DEFAULT_CONFIG);
|
|
72
|
+
// Layer 2: user config
|
|
73
|
+
const userConfigPath = path.join(userHome, '.mmr', 'config.yaml');
|
|
74
|
+
const userConfig = loadYaml(userConfigPath);
|
|
75
|
+
if (userConfig) {
|
|
76
|
+
merged = deepMerge(merged, userConfig);
|
|
77
|
+
}
|
|
78
|
+
// Layer 3: project config
|
|
79
|
+
const projectConfigPath = path.join(projectRoot, '.mmr.yaml');
|
|
80
|
+
const projectConfig = loadYaml(projectConfigPath);
|
|
81
|
+
if (projectConfig) {
|
|
82
|
+
merged = deepMerge(merged, projectConfig);
|
|
83
|
+
}
|
|
84
|
+
// Layer 4: CLI overrides (applied to defaults sub-object)
|
|
85
|
+
if (cliOverrides) {
|
|
86
|
+
const overrideDefaults = {};
|
|
87
|
+
if (cliOverrides.fix_threshold !== undefined)
|
|
88
|
+
overrideDefaults.fix_threshold = cliOverrides.fix_threshold;
|
|
89
|
+
if (cliOverrides.timeout !== undefined)
|
|
90
|
+
overrideDefaults.timeout = cliOverrides.timeout;
|
|
91
|
+
if (cliOverrides.format !== undefined)
|
|
92
|
+
overrideDefaults.format = cliOverrides.format;
|
|
93
|
+
if (Object.keys(overrideDefaults).length > 0) {
|
|
94
|
+
merged = deepMerge(merged, { defaults: overrideDefaults });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Validate through Zod schema
|
|
98
|
+
return MmrConfigSchema.parse(merged);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,SAAS,CAAA;AAC1B,OAAO,EAAE,eAAe,EAAwB,MAAM,aAAa,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAY9C;;;GAGG;AACH,SAAS,SAAS,CAAoC,IAAO,EAAE,OAAgC;IAC7F,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAA6B,CAAA;IACrD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;QAE5B,IACE,OAAO,KAAK,IAAI;YAChB,OAAO,OAAO,KAAK,QAAQ;YAC3B,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;YACvB,OAAO,KAAK,IAAI;YAChB,OAAO,OAAO,KAAK,QAAQ;YAC3B,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EACvB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CACrB,OAAkC,EAClC,OAAkC,CACnC,CAAA;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAA;QACvB,CAAC;IACH,CAAC;IACD,OAAO,MAAW,CAAA;AACpB,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,QAAgB;IAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAC9C,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,IAAI,MAAe,CAAA;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACzB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC5D,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,KAAK,GAAG,EAAE,CAAC,CAAA;IACxD,CAAC;IACD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnG,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,6BAA6B,OAAO,MAAM,EAAE,CAAC,CAAA;IAC5F,CAAC;IACD,OAAO,MAAiC,CAAA;AAC1C,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,IAAI,CAAA;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;IAE9C,sBAAsB;IACtB,IAAI,MAAM,GAA4B,eAAe,CAAC,cAAc,CAAuC,CAAA;IAE3G,uBAAuB;IACvB,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,CAAA;IACjE,MAAM,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAA;IAC3C,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;IACxC,CAAC;IAED,0BAA0B;IAC1B,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;IAC7D,MAAM,aAAa,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAA;IACjD,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC3C,CAAC;IAED,0DAA0D;IAC1D,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,gBAAgB,GAA4B,EAAE,CAAA;QACpD,IAAI,YAAY,CAAC,aAAa,KAAK,SAAS;YAAE,gBAAgB,CAAC,aAAa,GAAG,YAAY,CAAC,aAAa,CAAA;QACzG,IAAI,YAAY,CAAC,OAAO,KAAK,SAAS;YAAE,gBAAgB,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO,CAAA;QACvF,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS;YAAE,gBAAgB,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAA;QAEpF,IAAI,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAED,8BAA8B;IAC9B,OAAO,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;AACtC,CAAC"}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const Severity: z.ZodEnum<["P0", "P1", "P2", "P3"]>;
|
|
3
|
+
export declare const OutputFormat: z.ZodEnum<["json", "text", "markdown", "sarif"]>;
|
|
4
|
+
declare const ChannelConfigSchema: z.ZodObject<{
|
|
5
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
6
|
+
command: z.ZodString;
|
|
7
|
+
flags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
8
|
+
env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
9
|
+
auth: z.ZodObject<{
|
|
10
|
+
check: z.ZodString;
|
|
11
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
12
|
+
failure_exit_codes: z.ZodArray<z.ZodNumber, "many">;
|
|
13
|
+
recovery: z.ZodString;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
check: string;
|
|
16
|
+
timeout: number;
|
|
17
|
+
failure_exit_codes: number[];
|
|
18
|
+
recovery: string;
|
|
19
|
+
}, {
|
|
20
|
+
check: string;
|
|
21
|
+
failure_exit_codes: number[];
|
|
22
|
+
recovery: string;
|
|
23
|
+
timeout?: number | undefined;
|
|
24
|
+
}>;
|
|
25
|
+
prompt_wrapper: z.ZodDefault<z.ZodString>;
|
|
26
|
+
output_parser: z.ZodDefault<z.ZodString>;
|
|
27
|
+
stderr: z.ZodDefault<z.ZodEnum<["suppress", "capture", "passthrough"]>>;
|
|
28
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
command: string;
|
|
32
|
+
flags: string[];
|
|
33
|
+
env: Record<string, string>;
|
|
34
|
+
auth: {
|
|
35
|
+
check: string;
|
|
36
|
+
timeout: number;
|
|
37
|
+
failure_exit_codes: number[];
|
|
38
|
+
recovery: string;
|
|
39
|
+
};
|
|
40
|
+
prompt_wrapper: string;
|
|
41
|
+
output_parser: string;
|
|
42
|
+
stderr: "passthrough" | "suppress" | "capture";
|
|
43
|
+
timeout?: number | undefined;
|
|
44
|
+
}, {
|
|
45
|
+
command: string;
|
|
46
|
+
auth: {
|
|
47
|
+
check: string;
|
|
48
|
+
failure_exit_codes: number[];
|
|
49
|
+
recovery: string;
|
|
50
|
+
timeout?: number | undefined;
|
|
51
|
+
};
|
|
52
|
+
timeout?: number | undefined;
|
|
53
|
+
enabled?: boolean | undefined;
|
|
54
|
+
flags?: string[] | undefined;
|
|
55
|
+
env?: Record<string, string> | undefined;
|
|
56
|
+
prompt_wrapper?: string | undefined;
|
|
57
|
+
output_parser?: string | undefined;
|
|
58
|
+
stderr?: "passthrough" | "suppress" | "capture" | undefined;
|
|
59
|
+
}>;
|
|
60
|
+
export declare const MmrConfigSchema: z.ZodObject<{
|
|
61
|
+
version: z.ZodNumber;
|
|
62
|
+
defaults: z.ZodDefault<z.ZodObject<{
|
|
63
|
+
fix_threshold: z.ZodDefault<z.ZodEnum<["P0", "P1", "P2", "P3"]>>;
|
|
64
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
65
|
+
format: z.ZodDefault<z.ZodEnum<["json", "text", "markdown", "sarif"]>>;
|
|
66
|
+
parallel: z.ZodDefault<z.ZodBoolean>;
|
|
67
|
+
job_retention_days: z.ZodDefault<z.ZodNumber>;
|
|
68
|
+
}, "strip", z.ZodTypeAny, {
|
|
69
|
+
timeout: number;
|
|
70
|
+
fix_threshold: "P0" | "P1" | "P2" | "P3";
|
|
71
|
+
format: "json" | "text" | "markdown" | "sarif";
|
|
72
|
+
parallel: boolean;
|
|
73
|
+
job_retention_days: number;
|
|
74
|
+
}, {
|
|
75
|
+
timeout?: number | undefined;
|
|
76
|
+
fix_threshold?: "P0" | "P1" | "P2" | "P3" | undefined;
|
|
77
|
+
format?: "json" | "text" | "markdown" | "sarif" | undefined;
|
|
78
|
+
parallel?: boolean | undefined;
|
|
79
|
+
job_retention_days?: number | undefined;
|
|
80
|
+
}>>;
|
|
81
|
+
review_criteria: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
82
|
+
templates: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
83
|
+
criteria: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
84
|
+
}, "strip", z.ZodTypeAny, {
|
|
85
|
+
criteria?: string[] | undefined;
|
|
86
|
+
}, {
|
|
87
|
+
criteria?: string[] | undefined;
|
|
88
|
+
}>>>;
|
|
89
|
+
channels: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
90
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
91
|
+
command: z.ZodString;
|
|
92
|
+
flags: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
93
|
+
env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
94
|
+
auth: z.ZodObject<{
|
|
95
|
+
check: z.ZodString;
|
|
96
|
+
timeout: z.ZodDefault<z.ZodNumber>;
|
|
97
|
+
failure_exit_codes: z.ZodArray<z.ZodNumber, "many">;
|
|
98
|
+
recovery: z.ZodString;
|
|
99
|
+
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
check: string;
|
|
101
|
+
timeout: number;
|
|
102
|
+
failure_exit_codes: number[];
|
|
103
|
+
recovery: string;
|
|
104
|
+
}, {
|
|
105
|
+
check: string;
|
|
106
|
+
failure_exit_codes: number[];
|
|
107
|
+
recovery: string;
|
|
108
|
+
timeout?: number | undefined;
|
|
109
|
+
}>;
|
|
110
|
+
prompt_wrapper: z.ZodDefault<z.ZodString>;
|
|
111
|
+
output_parser: z.ZodDefault<z.ZodString>;
|
|
112
|
+
stderr: z.ZodDefault<z.ZodEnum<["suppress", "capture", "passthrough"]>>;
|
|
113
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
114
|
+
}, "strip", z.ZodTypeAny, {
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
command: string;
|
|
117
|
+
flags: string[];
|
|
118
|
+
env: Record<string, string>;
|
|
119
|
+
auth: {
|
|
120
|
+
check: string;
|
|
121
|
+
timeout: number;
|
|
122
|
+
failure_exit_codes: number[];
|
|
123
|
+
recovery: string;
|
|
124
|
+
};
|
|
125
|
+
prompt_wrapper: string;
|
|
126
|
+
output_parser: string;
|
|
127
|
+
stderr: "passthrough" | "suppress" | "capture";
|
|
128
|
+
timeout?: number | undefined;
|
|
129
|
+
}, {
|
|
130
|
+
command: string;
|
|
131
|
+
auth: {
|
|
132
|
+
check: string;
|
|
133
|
+
failure_exit_codes: number[];
|
|
134
|
+
recovery: string;
|
|
135
|
+
timeout?: number | undefined;
|
|
136
|
+
};
|
|
137
|
+
timeout?: number | undefined;
|
|
138
|
+
enabled?: boolean | undefined;
|
|
139
|
+
flags?: string[] | undefined;
|
|
140
|
+
env?: Record<string, string> | undefined;
|
|
141
|
+
prompt_wrapper?: string | undefined;
|
|
142
|
+
output_parser?: string | undefined;
|
|
143
|
+
stderr?: "passthrough" | "suppress" | "capture" | undefined;
|
|
144
|
+
}>>>;
|
|
145
|
+
}, "strip", z.ZodTypeAny, {
|
|
146
|
+
version: number;
|
|
147
|
+
defaults: {
|
|
148
|
+
timeout: number;
|
|
149
|
+
fix_threshold: "P0" | "P1" | "P2" | "P3";
|
|
150
|
+
format: "json" | "text" | "markdown" | "sarif";
|
|
151
|
+
parallel: boolean;
|
|
152
|
+
job_retention_days: number;
|
|
153
|
+
};
|
|
154
|
+
channels: Record<string, {
|
|
155
|
+
enabled: boolean;
|
|
156
|
+
command: string;
|
|
157
|
+
flags: string[];
|
|
158
|
+
env: Record<string, string>;
|
|
159
|
+
auth: {
|
|
160
|
+
check: string;
|
|
161
|
+
timeout: number;
|
|
162
|
+
failure_exit_codes: number[];
|
|
163
|
+
recovery: string;
|
|
164
|
+
};
|
|
165
|
+
prompt_wrapper: string;
|
|
166
|
+
output_parser: string;
|
|
167
|
+
stderr: "passthrough" | "suppress" | "capture";
|
|
168
|
+
timeout?: number | undefined;
|
|
169
|
+
}>;
|
|
170
|
+
review_criteria?: string[] | undefined;
|
|
171
|
+
templates?: Record<string, {
|
|
172
|
+
criteria?: string[] | undefined;
|
|
173
|
+
}> | undefined;
|
|
174
|
+
}, {
|
|
175
|
+
version: number;
|
|
176
|
+
defaults?: {
|
|
177
|
+
timeout?: number | undefined;
|
|
178
|
+
fix_threshold?: "P0" | "P1" | "P2" | "P3" | undefined;
|
|
179
|
+
format?: "json" | "text" | "markdown" | "sarif" | undefined;
|
|
180
|
+
parallel?: boolean | undefined;
|
|
181
|
+
job_retention_days?: number | undefined;
|
|
182
|
+
} | undefined;
|
|
183
|
+
review_criteria?: string[] | undefined;
|
|
184
|
+
templates?: Record<string, {
|
|
185
|
+
criteria?: string[] | undefined;
|
|
186
|
+
}> | undefined;
|
|
187
|
+
channels?: Record<string, {
|
|
188
|
+
command: string;
|
|
189
|
+
auth: {
|
|
190
|
+
check: string;
|
|
191
|
+
failure_exit_codes: number[];
|
|
192
|
+
recovery: string;
|
|
193
|
+
timeout?: number | undefined;
|
|
194
|
+
};
|
|
195
|
+
timeout?: number | undefined;
|
|
196
|
+
enabled?: boolean | undefined;
|
|
197
|
+
flags?: string[] | undefined;
|
|
198
|
+
env?: Record<string, string> | undefined;
|
|
199
|
+
prompt_wrapper?: string | undefined;
|
|
200
|
+
output_parser?: string | undefined;
|
|
201
|
+
stderr?: "passthrough" | "suppress" | "capture" | undefined;
|
|
202
|
+
}> | undefined;
|
|
203
|
+
}>;
|
|
204
|
+
export type MmrConfigParsed = z.infer<typeof MmrConfigSchema>;
|
|
205
|
+
export type ChannelConfigParsed = z.infer<typeof ChannelConfigSchema>;
|
|
206
|
+
export {};
|
|
207
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,eAAO,MAAM,QAAQ,qCAAmC,CAAA;AAExD,eAAO,MAAM,YAAY,kDAAgD,CAAA;AASzE,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUvB,CAAA;AAcF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAM1B,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAC7D,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const Severity = z.enum(['P0', 'P1', 'P2', 'P3']);
|
|
3
|
+
export const OutputFormat = z.enum(['json', 'text', 'markdown', 'sarif']);
|
|
4
|
+
const AuthConfigSchema = z.object({
|
|
5
|
+
check: z.string(),
|
|
6
|
+
timeout: z.number().default(5),
|
|
7
|
+
failure_exit_codes: z.array(z.number()),
|
|
8
|
+
recovery: z.string(),
|
|
9
|
+
});
|
|
10
|
+
const ChannelConfigSchema = z.object({
|
|
11
|
+
enabled: z.boolean().default(true),
|
|
12
|
+
command: z.string(),
|
|
13
|
+
flags: z.array(z.string()).default([]),
|
|
14
|
+
env: z.record(z.string()).default({}),
|
|
15
|
+
auth: AuthConfigSchema,
|
|
16
|
+
prompt_wrapper: z.string().default('{{prompt}}'),
|
|
17
|
+
output_parser: z.string().default('default'),
|
|
18
|
+
stderr: z.enum(['suppress', 'capture', 'passthrough']).default('capture'),
|
|
19
|
+
timeout: z.number().optional(),
|
|
20
|
+
});
|
|
21
|
+
const TemplateSchema = z.object({
|
|
22
|
+
criteria: z.array(z.string()).optional(),
|
|
23
|
+
});
|
|
24
|
+
const DefaultsSchema = z.object({
|
|
25
|
+
fix_threshold: Severity.default('P2'),
|
|
26
|
+
timeout: z.number().default(300),
|
|
27
|
+
format: OutputFormat.default('json'),
|
|
28
|
+
parallel: z.boolean().default(true),
|
|
29
|
+
job_retention_days: z.number().default(7),
|
|
30
|
+
});
|
|
31
|
+
export const MmrConfigSchema = z.object({
|
|
32
|
+
version: z.number(),
|
|
33
|
+
defaults: DefaultsSchema.default({}),
|
|
34
|
+
review_criteria: z.array(z.string()).optional(),
|
|
35
|
+
templates: z.record(TemplateSchema).optional(),
|
|
36
|
+
channels: z.record(ChannelConfigSchema).default({}),
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC,CAAA;AAEzE,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9B,kBAAkB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;CACrB,CAAC,CAAA;AAEF,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACtC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;IACrC,IAAI,EAAE,gBAAgB;IACtB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IAChD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IAC5C,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;IACzE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAA;AAEF,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;IAChC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC;IACpC,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IACnC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1C,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;IACpC,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC/C,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;IAC9C,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACpD,CAAC,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChannelConfigParsed } from '../config/schema.js';
|
|
2
|
+
export interface AuthResult {
|
|
3
|
+
status: 'ok' | 'failed' | 'timeout';
|
|
4
|
+
recovery?: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Check whether a CLI command is installed (available on PATH).
|
|
8
|
+
* Uses `command -v` via shell.
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkInstalled(command: string): Promise<boolean>;
|
|
11
|
+
/**
|
|
12
|
+
* Run the auth check defined in a channel config.
|
|
13
|
+
* Spawns `sh -c <auth.check>` with the channel's env merged into process.env.
|
|
14
|
+
* Returns ok/failed/timeout based on exit code and timeout.
|
|
15
|
+
*/
|
|
16
|
+
export declare function checkAuth(config: ChannelConfigParsed): Promise<AuthResult>;
|
|
17
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE9D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,CAAA;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAStE;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,UAAU,CAAC,CA2ChF"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Check whether a CLI command is installed (available on PATH).
|
|
4
|
+
* Uses `command -v` via shell.
|
|
5
|
+
*/
|
|
6
|
+
export async function checkInstalled(command) {
|
|
7
|
+
// Validate command name contains only safe characters
|
|
8
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(command))
|
|
9
|
+
return false;
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
// Use 'which' with argument array to avoid shell interpolation
|
|
12
|
+
const child = spawn('which', [command], { stdio: 'ignore' });
|
|
13
|
+
child.on('close', (code) => resolve(code === 0));
|
|
14
|
+
child.on('error', () => resolve(false));
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run the auth check defined in a channel config.
|
|
19
|
+
* Spawns `sh -c <auth.check>` with the channel's env merged into process.env.
|
|
20
|
+
* Returns ok/failed/timeout based on exit code and timeout.
|
|
21
|
+
*/
|
|
22
|
+
export async function checkAuth(config) {
|
|
23
|
+
const { auth, env } = config;
|
|
24
|
+
return new Promise((resolve) => {
|
|
25
|
+
let settled = false;
|
|
26
|
+
let timedOut = false;
|
|
27
|
+
const child = spawn('sh', ['-c', auth.check], {
|
|
28
|
+
env: { ...process.env, ...env },
|
|
29
|
+
stdio: 'ignore',
|
|
30
|
+
});
|
|
31
|
+
const timer = setTimeout(() => {
|
|
32
|
+
timedOut = true;
|
|
33
|
+
child.kill('SIGKILL');
|
|
34
|
+
}, auth.timeout * 1000);
|
|
35
|
+
child.on('close', (code) => {
|
|
36
|
+
if (settled)
|
|
37
|
+
return;
|
|
38
|
+
settled = true;
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
if (timedOut) {
|
|
41
|
+
resolve({ status: 'timeout' });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (code !== null && auth.failure_exit_codes.includes(code)) {
|
|
45
|
+
resolve({ status: 'failed', recovery: auth.recovery });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// Exit code 0 or any code not in failure_exit_codes -> ok (transient)
|
|
49
|
+
resolve({ status: 'ok' });
|
|
50
|
+
});
|
|
51
|
+
child.on('error', () => {
|
|
52
|
+
if (settled)
|
|
53
|
+
return;
|
|
54
|
+
settled = true;
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
resolve({ status: 'failed', recovery: auth.recovery });
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/core/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAQ1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,sDAAsD;IACtD,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACpD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,+DAA+D;QAC/D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC5D,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAA;QAChD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAA2B;IACzD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAA;IAE5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,IAAI,QAAQ,GAAG,KAAK,CAAA;QAEpB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;YAC5C,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE;YAC/B,KAAK,EAAE,QAAQ;SAChB,CAAC,CAAA;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,QAAQ,GAAG,IAAI,CAAA;YACf,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACvB,CAAC,EAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;QAEvB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YAEnB,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;gBAC9B,OAAM;YACR,CAAC;YAED,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC5D,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;gBACtD,OAAM;YACR,CAAC;YAED,sEAAsE;YACtE,OAAO,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;QAEF,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,IAAI,OAAO;gBAAE,OAAM;YACnB,OAAO,GAAG,IAAI,CAAA;YACd,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ChannelStatus } from '../types.js';
|
|
2
|
+
import type { JobStore } from './job-store.js';
|
|
3
|
+
export interface DispatchOptions {
|
|
4
|
+
command: string;
|
|
5
|
+
prompt: string;
|
|
6
|
+
flags: string[];
|
|
7
|
+
env: Record<string, string>;
|
|
8
|
+
timeout: number;
|
|
9
|
+
stderr: 'capture' | 'ignore';
|
|
10
|
+
}
|
|
11
|
+
/** Check whether a channel status represents a terminal (done) state */
|
|
12
|
+
export declare function isChannelComplete(status: ChannelStatus): boolean;
|
|
13
|
+
/** Spawn a background process for a review channel and monitor it */
|
|
14
|
+
export declare function dispatchChannel(store: JobStore, jobId: string, channelName: string, opts: DispatchOptions): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/core/dispatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAA;CAC7B;AAUD,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAEhE;AAED,qEAAqE;AACrE,wBAAsB,eAAe,CACnC,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,IAAI,CAAC,CAuGf"}
|