@visorcraft/idlehands 1.4.6 → 2.0.1
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/agent/constants.js +12 -0
- package/dist/agent/constants.js.map +1 -0
- package/dist/agent/context-budget.js +103 -0
- package/dist/agent/context-budget.js.map +1 -0
- package/dist/agent/errors.js +8 -0
- package/dist/agent/errors.js.map +1 -0
- package/dist/agent/exec-helpers.js +105 -0
- package/dist/agent/exec-helpers.js.map +1 -0
- package/dist/agent/model-pick.js +21 -0
- package/dist/agent/model-pick.js.map +1 -0
- package/dist/agent/session-utils.js +63 -0
- package/dist/agent/session-utils.js.map +1 -0
- package/dist/agent/subagent-context.js +78 -0
- package/dist/agent/subagent-context.js.map +1 -0
- package/dist/agent/tool-loop-detection.js +91 -20
- package/dist/agent/tool-loop-detection.js.map +1 -1
- package/dist/agent/tool-loop-guard.js.map +1 -1
- package/dist/agent/tool-policy.js +54 -0
- package/dist/agent/tool-policy.js.map +1 -0
- package/dist/agent/tools-schema.js +281 -0
- package/dist/agent/tools-schema.js.map +1 -0
- package/dist/agent.js +191 -641
- package/dist/agent.js.map +1 -1
- package/dist/anton/controller.js +235 -163
- package/dist/anton/controller.js.map +1 -1
- package/dist/anton/lint-baseline.js +64 -0
- package/dist/anton/lint-baseline.js.map +1 -0
- package/dist/anton/preflight.js +7 -0
- package/dist/anton/preflight.js.map +1 -1
- package/dist/anton/prompt.js +71 -71
- package/dist/anton/reporter.js.map +1 -1
- package/dist/anton/runtime-ready.js +120 -0
- package/dist/anton/runtime-ready.js.map +1 -0
- package/dist/anton/session.js +7 -1
- package/dist/anton/session.js.map +1 -1
- package/dist/anton/verifier-utils.js +148 -0
- package/dist/anton/verifier-utils.js.map +1 -0
- package/dist/anton/verifier.js +26 -227
- package/dist/anton/verifier.js.map +1 -1
- package/dist/bot/anton-auto-pin.js +12 -0
- package/dist/bot/anton-auto-pin.js.map +1 -0
- package/dist/bot/anton-commands.js +137 -0
- package/dist/bot/anton-commands.js.map +1 -0
- package/dist/bot/anton-run.js +155 -0
- package/dist/bot/anton-run.js.map +1 -0
- package/dist/bot/anton-status-format.js +18 -0
- package/dist/bot/anton-status-format.js.map +1 -0
- package/dist/bot/basic-commands.js +114 -0
- package/dist/bot/basic-commands.js.map +1 -0
- package/dist/bot/command-format.js.map +1 -1
- package/dist/bot/command-logic.js +8 -728
- package/dist/bot/command-logic.js.map +1 -1
- package/dist/bot/commands.js +18 -1
- package/dist/bot/commands.js.map +1 -1
- package/dist/bot/discord-anton-autopin.js +29 -0
- package/dist/bot/discord-anton-autopin.js.map +1 -0
- package/dist/bot/discord-anton.js +45 -0
- package/dist/bot/discord-anton.js.map +1 -0
- package/dist/bot/discord-commands.js +20 -52
- package/dist/bot/discord-commands.js.map +1 -1
- package/dist/bot/discord-result.js +9 -0
- package/dist/bot/discord-result.js.map +1 -0
- package/dist/bot/discord-routing.js.map +1 -1
- package/dist/bot/discord.js +55 -12
- package/dist/bot/discord.js.map +1 -1
- package/dist/bot/escalation-commands.js +145 -0
- package/dist/bot/escalation-commands.js.map +1 -0
- package/dist/bot/escalation.js.map +1 -1
- package/dist/bot/format.js +0 -5
- package/dist/bot/format.js.map +1 -1
- package/dist/bot/git-status-command.js +28 -0
- package/dist/bot/git-status-command.js.map +1 -0
- package/dist/bot/model-endpoint.js +25 -0
- package/dist/bot/model-endpoint.js.map +1 -0
- package/dist/bot/session-history.js +61 -0
- package/dist/bot/session-history.js.map +1 -0
- package/dist/bot/session-settings.js +89 -0
- package/dist/bot/session-settings.js.map +1 -0
- package/dist/bot/telegram-commands.js +15 -7
- package/dist/bot/telegram-commands.js.map +1 -1
- package/dist/bot/telegram.js +15 -29
- package/dist/bot/telegram.js.map +1 -1
- package/dist/cli/agent-turn.js +8 -2
- package/dist/cli/agent-turn.js.map +1 -1
- package/dist/cli/commands/anton.js +6 -1
- package/dist/cli/commands/anton.js.map +1 -1
- package/dist/cli/commands/model.js +1 -3
- package/dist/cli/commands/model.js.map +1 -1
- package/dist/cli/commands/project.js +1 -1
- package/dist/cli/commands/project.js.map +1 -1
- package/dist/cli/commands/secrets.js +1 -1
- package/dist/cli/commands/secrets.js.map +1 -1
- package/dist/cli/commands/session.js +22 -12
- package/dist/cli/commands/session.js.map +1 -1
- package/dist/cli/guided-onboarding.js +20 -0
- package/dist/cli/guided-onboarding.js.map +1 -0
- package/dist/cli/runtime-cmds.js +8 -133
- package/dist/cli/runtime-cmds.js.map +1 -1
- package/dist/cli/runtime-common.js +35 -0
- package/dist/cli/runtime-common.js.map +1 -0
- package/dist/cli/runtime-detect.js +12 -0
- package/dist/cli/runtime-detect.js.map +1 -0
- package/dist/cli/runtime-host-command.js +7 -0
- package/dist/cli/runtime-host-command.js.map +1 -0
- package/dist/cli/runtime-probe-defaults.js +63 -0
- package/dist/cli/runtime-probe-defaults.js.map +1 -0
- package/dist/cli/runtime-scan-ports.js +30 -0
- package/dist/cli/runtime-scan-ports.js.map +1 -0
- package/dist/cli/setup-bot-step.js +51 -0
- package/dist/cli/setup-bot-step.js.map +1 -0
- package/dist/cli/setup-runtime-forms.js +214 -0
- package/dist/cli/setup-runtime-forms.js.map +1 -0
- package/dist/cli/setup-style.js +8 -0
- package/dist/cli/setup-style.js.map +1 -0
- package/dist/cli/setup-ui.js +146 -0
- package/dist/cli/setup-ui.js.map +1 -0
- package/dist/cli/setup.js +11 -449
- package/dist/cli/setup.js.map +1 -1
- package/dist/client/error-utils.js +37 -0
- package/dist/client/error-utils.js.map +1 -0
- package/dist/client/pressure.js +77 -0
- package/dist/client/pressure.js.map +1 -0
- package/dist/client.js +24 -122
- package/dist/client.js.map +1 -1
- package/dist/config.js +31 -14
- package/dist/config.js.map +1 -1
- package/dist/git.js +8 -2
- package/dist/git.js.map +1 -1
- package/dist/history.js +418 -0
- package/dist/history.js.map +1 -1
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/progress/message-edit-scheduler.js.map +1 -1
- package/dist/progress/turn-progress.js.map +1 -1
- package/dist/runtime/executor.js +4 -1
- package/dist/runtime/executor.js.map +1 -1
- package/dist/runtime/health.js.map +1 -1
- package/dist/runtime/host-runner.js.map +1 -1
- package/dist/safety.js +3 -2
- package/dist/safety.js.map +1 -1
- package/dist/shared/config-utils.js.map +1 -1
- package/dist/tools/exec-core.js +252 -0
- package/dist/tools/exec-core.js.map +1 -0
- package/dist/tools/exec-pty.js +89 -0
- package/dist/tools/exec-pty.js.map +1 -0
- package/dist/tools/exec-utils.js +94 -0
- package/dist/tools/exec-utils.js.map +1 -0
- package/dist/tools/file-discovery.js +144 -0
- package/dist/tools/file-discovery.js.map +1 -0
- package/dist/tools/file-mutations.js +326 -0
- package/dist/tools/file-mutations.js.map +1 -0
- package/dist/tools/file-read.js +133 -0
- package/dist/tools/file-read.js.map +1 -0
- package/dist/tools/patch-apply.js +168 -0
- package/dist/tools/patch-apply.js.map +1 -0
- package/dist/tools/path-safety.js.map +1 -1
- package/dist/tools/replay-utils.js +25 -0
- package/dist/tools/replay-utils.js.map +1 -0
- package/dist/tools/search-utils.js +55 -0
- package/dist/tools/search-utils.js.map +1 -0
- package/dist/tools/sys-notes.js +34 -0
- package/dist/tools/sys-notes.js.map +1 -0
- package/dist/tools/text-utils.js +164 -0
- package/dist/tools/text-utils.js.map +1 -0
- package/dist/tools/undo.js +1 -1
- package/dist/tools/undo.js.map +1 -1
- package/dist/tools/vault-tools.js +36 -0
- package/dist/tools/vault-tools.js.map +1 -0
- package/dist/tools.js +19 -1460
- package/dist/tools.js.map +1 -1
- package/dist/tui/controller.js +5 -2
- package/dist/tui/controller.js.map +1 -1
- package/dist/tui/render.js.map +1 -1
- package/dist/utils.js +2 -2
- package/dist/utils.js.map +1 -1
- package/dist/vault.js +134 -1
- package/dist/vault.js.map +1 -1
- package/dist/watchdog.js +1 -3
- package/dist/watchdog.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { execute, loadActiveRuntime, runOnHost } from '../runtime/executor.js';
|
|
2
|
+
import { waitForModelsReady } from '../runtime/health.js';
|
|
3
|
+
import { plan } from '../runtime/planner.js';
|
|
4
|
+
import { loadRuntimes } from '../runtime/store.js';
|
|
5
|
+
function endpointBase(endpoint) {
|
|
6
|
+
if (!endpoint)
|
|
7
|
+
return null;
|
|
8
|
+
const e = endpoint.trim().replace(/\/+$/, '');
|
|
9
|
+
if (!e)
|
|
10
|
+
return null;
|
|
11
|
+
return e.endsWith('/v1') ? e : `${e}/v1`;
|
|
12
|
+
}
|
|
13
|
+
async function probeEndpointReady(endpoint) {
|
|
14
|
+
const base = endpointBase(endpoint);
|
|
15
|
+
if (!base)
|
|
16
|
+
return { ok: false, reason: 'endpoint-not-configured' };
|
|
17
|
+
const ctrl = new AbortController();
|
|
18
|
+
const t = setTimeout(() => ctrl.abort(), 7000);
|
|
19
|
+
try {
|
|
20
|
+
const res = await fetch(`${base}/models`, { signal: ctrl.signal });
|
|
21
|
+
if (res.status === 503)
|
|
22
|
+
return { ok: false, reason: 'loading-http-503' };
|
|
23
|
+
if (!res.ok)
|
|
24
|
+
return { ok: false, reason: `http-${res.status}` };
|
|
25
|
+
return { ok: true, reason: 'ok' };
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
const msg = String(e?.message ?? e).toLowerCase();
|
|
29
|
+
if (msg.includes('aborted'))
|
|
30
|
+
return { ok: false, reason: 'timeout' };
|
|
31
|
+
return { ok: false, reason: msg.slice(0, 120) };
|
|
32
|
+
}
|
|
33
|
+
finally {
|
|
34
|
+
clearTimeout(t);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function classifyInfraError(err) {
|
|
38
|
+
const msg = String(err?.message ?? err ?? '').toLowerCase();
|
|
39
|
+
if (!msg)
|
|
40
|
+
return 'other';
|
|
41
|
+
if (msg.includes('aborted') || msg.includes('cancel'))
|
|
42
|
+
return 'other';
|
|
43
|
+
if (msg.includes('503') || msg.includes('model is loading') || msg.includes('loading')) {
|
|
44
|
+
return 'loading';
|
|
45
|
+
}
|
|
46
|
+
const infraPatterns = [
|
|
47
|
+
'econnrefused',
|
|
48
|
+
'could not connect',
|
|
49
|
+
'connection refused',
|
|
50
|
+
'enotfound',
|
|
51
|
+
'fetch failed',
|
|
52
|
+
'connect timeout',
|
|
53
|
+
'socket hang up',
|
|
54
|
+
'no models found',
|
|
55
|
+
'endpoint',
|
|
56
|
+
];
|
|
57
|
+
if (infraPatterns.some((p) => msg.includes(p))) {
|
|
58
|
+
return 'infra_down';
|
|
59
|
+
}
|
|
60
|
+
return 'other';
|
|
61
|
+
}
|
|
62
|
+
export async function ensureAntonRuntimeReady(idlehandsConfig, opts) {
|
|
63
|
+
const endpointProbe = await probeEndpointReady(idlehandsConfig.endpoint);
|
|
64
|
+
if (endpointProbe.ok)
|
|
65
|
+
return { ok: true, detail: 'endpoint-ready' };
|
|
66
|
+
let rtConfig;
|
|
67
|
+
try {
|
|
68
|
+
rtConfig = await loadRuntimes();
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
detail: `endpoint-not-ready (${endpointProbe.reason}); runtimes-unavailable`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const active = await loadActiveRuntime();
|
|
77
|
+
let targetModelId;
|
|
78
|
+
if (active?.modelId && rtConfig.models.some((m) => m.id === active.modelId && m.enabled)) {
|
|
79
|
+
targetModelId = active.modelId;
|
|
80
|
+
}
|
|
81
|
+
else if (typeof idlehandsConfig.model === 'string' &&
|
|
82
|
+
rtConfig.models.some((m) => m.id === idlehandsConfig.model && m.enabled)) {
|
|
83
|
+
targetModelId = idlehandsConfig.model;
|
|
84
|
+
}
|
|
85
|
+
if (!targetModelId) {
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
detail: `endpoint-not-ready (${endpointProbe.reason}); no-runtime-model-mapping`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const planOut = plan({ modelId: targetModelId, mode: 'live', forceRestart: opts.forceRestart }, rtConfig, active);
|
|
92
|
+
if (!planOut.ok) {
|
|
93
|
+
return { ok: false, detail: `runtime-plan-failed ${planOut.code}: ${planOut.reason}` };
|
|
94
|
+
}
|
|
95
|
+
const execRes = await execute(planOut, {
|
|
96
|
+
force: true,
|
|
97
|
+
confirm: async () => true,
|
|
98
|
+
});
|
|
99
|
+
if (!execRes.ok) {
|
|
100
|
+
return { ok: false, detail: `runtime-exec-failed: ${execRes.error ?? 'unknown'}` };
|
|
101
|
+
}
|
|
102
|
+
const timeoutMs = Math.max(10_000, opts.timeoutMs ?? (planOut.model.launch.probe_timeout_sec ?? 600) * 1000);
|
|
103
|
+
for (const resolvedHost of planOut.hosts) {
|
|
104
|
+
const hostCfg = rtConfig.hosts.find((h) => h.id === resolvedHost.id);
|
|
105
|
+
if (!hostCfg)
|
|
106
|
+
continue;
|
|
107
|
+
const ready = await waitForModelsReady(runOnHost, hostCfg, planOut.model.runtime_defaults?.port ?? 8080, {
|
|
108
|
+
timeoutMs,
|
|
109
|
+
intervalMs: planOut.model.launch.probe_interval_ms ?? 2000,
|
|
110
|
+
});
|
|
111
|
+
if (!ready.ok) {
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
detail: `wait-ready failed on ${resolvedHost.id}: ${ready.reason ?? 'timeout'}`,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return { ok: true, detail: 'runtime-ready' };
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=runtime-ready.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-ready.js","sourceRoot":"","sources":["../../src/anton/runtime-ready.ts"],"names":[],"mappings":"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"}
|
package/dist/anton/session.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Anton autonomous task runner — session config builders and factory wrapper.
|
|
3
3
|
*/
|
|
4
|
+
import path from 'node:path';
|
|
4
5
|
import { createSession } from '../agent.js';
|
|
5
6
|
/**
|
|
6
7
|
* Build session config for main task execution sessions.
|
|
@@ -36,7 +37,8 @@ export function buildPreflightConfig(base, config, stageTimeoutSec, maxIteration
|
|
|
36
37
|
const preflightTimeoutCapSec = Number.isFinite(config.preflightSessionTimeoutSec) &&
|
|
37
38
|
Number(config.preflightSessionTimeoutSec) > 0
|
|
38
39
|
? Math.floor(Number(config.preflightSessionTimeoutSec))
|
|
39
|
-
:
|
|
40
|
+
: Math.max(10, Math.floor(Number(config.taskTimeoutSec) || 600));
|
|
41
|
+
const tasksDir = path.resolve(config.projectDir, '.agents', 'tasks');
|
|
40
42
|
return {
|
|
41
43
|
...base,
|
|
42
44
|
dir: config.projectDir,
|
|
@@ -48,6 +50,10 @@ export function buildPreflightConfig(base, config, stageTimeoutSec, maxIteration
|
|
|
48
50
|
timeout: Math.max(10, Math.min(Math.floor(stageTimeoutSec), preflightTimeoutCapSec)),
|
|
49
51
|
compact_at: 0.65,
|
|
50
52
|
compact_min_tail: 4,
|
|
53
|
+
// Preflight can write only plan artifacts under .agents/tasks.
|
|
54
|
+
allowed_write_roots: [tasksDir],
|
|
55
|
+
require_dir_pin_for_mutations: false,
|
|
56
|
+
dir_pinned: true,
|
|
51
57
|
no_tools: false,
|
|
52
58
|
trifecta: { enabled: false },
|
|
53
59
|
mcp: { servers: [] },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/anton/session.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/anton/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { getChangedFiles } from '../git.js';
|
|
3
|
+
/**
|
|
4
|
+
* If task text explicitly names files, enforce working tree changes stay in scope.
|
|
5
|
+
*/
|
|
6
|
+
export function checkTaskScopeGuard(taskText, projectDir) {
|
|
7
|
+
const expected = extractExplicitTaskFiles(taskText);
|
|
8
|
+
if (expected.length === 0)
|
|
9
|
+
return { ok: true };
|
|
10
|
+
const changed = getChangedFiles(projectDir)
|
|
11
|
+
.map((p) => p.replace(/^\.\//, ''))
|
|
12
|
+
.filter(Boolean);
|
|
13
|
+
if (changed.length === 0)
|
|
14
|
+
return { ok: true };
|
|
15
|
+
const expectedSet = new Set(expected);
|
|
16
|
+
const outOfScope = changed.filter((f) => !expectedSet.has(f));
|
|
17
|
+
if (outOfScope.length === 0)
|
|
18
|
+
return { ok: true };
|
|
19
|
+
return {
|
|
20
|
+
ok: false,
|
|
21
|
+
reason: `Scope guard failed: task explicitly targets ${expected.join(', ')} but modified out-of-scope files`,
|
|
22
|
+
details: `Expected: ${expected.join(', ')}\nChanged: ${changed.join(', ')}\nOut-of-scope: ${outOfScope.join(', ')}`,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function extractExplicitTaskFiles(taskText) {
|
|
26
|
+
const text = String(taskText || '');
|
|
27
|
+
const files = new Set();
|
|
28
|
+
const pathRegex = /\b([A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+\.[A-Za-z0-9]{1,8})\b/g;
|
|
29
|
+
for (const m of text.matchAll(pathRegex)) {
|
|
30
|
+
files.add(m[1].replace(/^\.\//, ''));
|
|
31
|
+
}
|
|
32
|
+
const bareRegex = /\b([A-Za-z0-9._-]+\.[A-Za-z0-9]{1,8})\b/g;
|
|
33
|
+
for (const m of text.matchAll(bareRegex)) {
|
|
34
|
+
const file = m[1];
|
|
35
|
+
if (!file.includes('/'))
|
|
36
|
+
files.add(file);
|
|
37
|
+
}
|
|
38
|
+
return [...files];
|
|
39
|
+
}
|
|
40
|
+
export function isCommandAvailable(...cmd) {
|
|
41
|
+
const command = cmd.length === 1 ? cmd[0] : cmd.join(' ');
|
|
42
|
+
const result = spawnSync('which', [cmd[0]], {
|
|
43
|
+
timeout: 5000,
|
|
44
|
+
encoding: 'utf8',
|
|
45
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
46
|
+
});
|
|
47
|
+
if (result.status !== 0)
|
|
48
|
+
return false;
|
|
49
|
+
if (cmd.length > 1) {
|
|
50
|
+
const testResult = spawnSync('bash', ['-c', `${command} --help >/dev/null 2>&1`], {
|
|
51
|
+
timeout: 5000,
|
|
52
|
+
});
|
|
53
|
+
return testResult.status === 0;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
export function makeTargetExists(cwd, target) {
|
|
58
|
+
try {
|
|
59
|
+
const result = spawnSync('make', ['-n', target], {
|
|
60
|
+
cwd,
|
|
61
|
+
timeout: 5000,
|
|
62
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
63
|
+
});
|
|
64
|
+
return result.status === 0;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function truncateOutput(text, maxLen = 2000) {
|
|
71
|
+
const cleaned = text.trim();
|
|
72
|
+
return cleaned.length > maxLen ? `${cleaned.slice(0, maxLen)}...` : cleaned;
|
|
73
|
+
}
|
|
74
|
+
export function combineOutput(label, stdout, stderr) {
|
|
75
|
+
const parts = [`=== ${label} ===`];
|
|
76
|
+
const out = stdout.trim();
|
|
77
|
+
const err = stderr.trim();
|
|
78
|
+
if (out)
|
|
79
|
+
parts.push(`stdout:\n${out}`);
|
|
80
|
+
if (err)
|
|
81
|
+
parts.push(`stderr:\n${err}`);
|
|
82
|
+
if (!out && !err)
|
|
83
|
+
parts.push('(no output)');
|
|
84
|
+
return parts.join('\n');
|
|
85
|
+
}
|
|
86
|
+
export function parseVerifierResponse(raw) {
|
|
87
|
+
const text = raw.trim();
|
|
88
|
+
// 1. Try direct JSON parse
|
|
89
|
+
try {
|
|
90
|
+
const parsed = JSON.parse(text);
|
|
91
|
+
if (typeof parsed.pass === 'boolean') {
|
|
92
|
+
return { pass: parsed.pass, reason: parsed.reason || 'No reason provided' };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
/* not valid JSON, continue */
|
|
97
|
+
}
|
|
98
|
+
// 2. Try extracting JSON from markdown code fences or inline braces
|
|
99
|
+
const jsonMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/) || text.match(/(\{[\s\S]*?"pass"[\s\S]*?\})/);
|
|
100
|
+
if (jsonMatch) {
|
|
101
|
+
try {
|
|
102
|
+
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
103
|
+
if (typeof parsed.pass === 'boolean') {
|
|
104
|
+
return { pass: parsed.pass, reason: parsed.reason || 'No reason provided' };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* still not valid, continue */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// 3. Keyword inference from prose
|
|
112
|
+
const lower = text.toLowerCase();
|
|
113
|
+
const passPatterns = [
|
|
114
|
+
/\bpass\b/,
|
|
115
|
+
/\bapproved?\b/,
|
|
116
|
+
/\blooks?\s+good\b/,
|
|
117
|
+
/\bcorrect(ly)?\b/,
|
|
118
|
+
/\bwell[- ]implemented\b/,
|
|
119
|
+
/\bno\s+(issues?|problems?|concerns?)\b/,
|
|
120
|
+
/\bcode\s+(is\s+)?clean\b/,
|
|
121
|
+
/\btask\s+(is\s+)?(complete|done)\b/,
|
|
122
|
+
];
|
|
123
|
+
const failPatterns = [
|
|
124
|
+
/\bfail\b/,
|
|
125
|
+
/\breject(ed)?\b/,
|
|
126
|
+
/\bnot\s+(correct|approved?)\b/,
|
|
127
|
+
/\bissues?\s+found\b/,
|
|
128
|
+
/\bproblems?\s+found\b/,
|
|
129
|
+
/\bbug(s)?\b/,
|
|
130
|
+
/\bmissing\b/,
|
|
131
|
+
/\bincorrect\b/,
|
|
132
|
+
/\bbroken\b/,
|
|
133
|
+
];
|
|
134
|
+
const passScore = passPatterns.filter((p) => p.test(lower)).length;
|
|
135
|
+
const failScore = failPatterns.filter((p) => p.test(lower)).length;
|
|
136
|
+
if (passScore > 0 && passScore > failScore) {
|
|
137
|
+
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
138
|
+
return { pass: true, reason: `(inferred from prose) ${snippet}` };
|
|
139
|
+
}
|
|
140
|
+
if (failScore > 0) {
|
|
141
|
+
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
142
|
+
return { pass: false, reason: `(inferred from prose) ${snippet}` };
|
|
143
|
+
}
|
|
144
|
+
// 4. Ambiguous — default to pass since L1 already validated build/test
|
|
145
|
+
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
146
|
+
return { pass: true, reason: `(ambiguous response, defaulting to pass) ${snippet}` };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=verifier-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verifier-utils.js","sourceRoot":"","sources":["../../src/anton/verifier-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/anton/verifier.js
CHANGED
|
@@ -11,6 +11,9 @@ import { readFileSync, existsSync } from 'node:fs';
|
|
|
11
11
|
import { join, extname } from 'node:path';
|
|
12
12
|
import { getChangedFiles } from '../git.js';
|
|
13
13
|
import { runCommand } from '../runtime/executor.js';
|
|
14
|
+
import { countLintErrors, filterLintErrorLines } from './lint-baseline.js';
|
|
15
|
+
export { captureLintBaseline } from './lint-baseline.js';
|
|
16
|
+
import { checkTaskScopeGuard, isCommandAvailable, makeTargetExists, truncateOutput, combineOutput, parseVerifierResponse, } from './verifier-utils.js';
|
|
14
17
|
/**
|
|
15
18
|
* Detect verification commands based on project files and overrides.
|
|
16
19
|
* Priority: overrides → package.json → Cargo.toml → Makefile → Python configs
|
|
@@ -265,9 +268,22 @@ or
|
|
|
265
268
|
// ── Pre-verify autofix ──────────────────────────────────────────
|
|
266
269
|
/** File extensions eligible for autoformat/autofix. */
|
|
267
270
|
const AUTOFIX_EXTENSIONS = new Set([
|
|
268
|
-
'.ts',
|
|
269
|
-
'.
|
|
270
|
-
'.
|
|
271
|
+
'.ts',
|
|
272
|
+
'.tsx',
|
|
273
|
+
'.js',
|
|
274
|
+
'.jsx',
|
|
275
|
+
'.mjs',
|
|
276
|
+
'.cjs',
|
|
277
|
+
'.css',
|
|
278
|
+
'.scss',
|
|
279
|
+
'.less',
|
|
280
|
+
'.json',
|
|
281
|
+
'.md',
|
|
282
|
+
'.yaml',
|
|
283
|
+
'.yml',
|
|
284
|
+
'.vue',
|
|
285
|
+
'.svelte',
|
|
286
|
+
'.html',
|
|
271
287
|
]);
|
|
272
288
|
/**
|
|
273
289
|
* Attempt to auto-fix lint/format issues on files changed in the current attempt.
|
|
@@ -306,7 +322,12 @@ export async function tryAutofixChangedFiles(projectDir) {
|
|
|
306
322
|
// Try prettier --write (only if prettier is available)
|
|
307
323
|
if (isCommandAvailable('npx')) {
|
|
308
324
|
try {
|
|
309
|
-
const prettierRes = spawnSync('npx', ['prettier', '--write', '--ignore-unknown', ...batch], {
|
|
325
|
+
const prettierRes = spawnSync('npx', ['prettier', '--write', '--ignore-unknown', ...batch], {
|
|
326
|
+
cwd: projectDir,
|
|
327
|
+
timeout: 60_000,
|
|
328
|
+
encoding: 'utf8',
|
|
329
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
330
|
+
});
|
|
310
331
|
if (prettierRes.status === 0) {
|
|
311
332
|
ran = true;
|
|
312
333
|
console.error(`[anton:autofix] prettier --write ran on ${batch.length} files`);
|
|
@@ -318,227 +339,5 @@ export async function tryAutofixChangedFiles(projectDir) {
|
|
|
318
339
|
}
|
|
319
340
|
return ran;
|
|
320
341
|
}
|
|
321
|
-
|
|
322
|
-
* If task text explicitly names files (e.g. "create src/foo.ts"), enforce that
|
|
323
|
-
* working tree changes stay within that set. This prevents task scope bleed.
|
|
324
|
-
*/
|
|
325
|
-
function checkTaskScopeGuard(taskText, projectDir) {
|
|
326
|
-
const expected = extractExplicitTaskFiles(taskText);
|
|
327
|
-
if (expected.length === 0)
|
|
328
|
-
return { ok: true };
|
|
329
|
-
const changed = getChangedFiles(projectDir)
|
|
330
|
-
.map((p) => p.replace(/^\.\//, ''))
|
|
331
|
-
.filter(Boolean);
|
|
332
|
-
if (changed.length === 0)
|
|
333
|
-
return { ok: true };
|
|
334
|
-
const expectedSet = new Set(expected);
|
|
335
|
-
const outOfScope = changed.filter((f) => !expectedSet.has(f));
|
|
336
|
-
if (outOfScope.length === 0)
|
|
337
|
-
return { ok: true };
|
|
338
|
-
return {
|
|
339
|
-
ok: false,
|
|
340
|
-
reason: `Scope guard failed: task explicitly targets ${expected.join(', ')} but modified out-of-scope files`,
|
|
341
|
-
details: `Expected: ${expected.join(', ')}\nChanged: ${changed.join(', ')}\nOut-of-scope: ${outOfScope.join(', ')}`,
|
|
342
|
-
};
|
|
343
|
-
}
|
|
344
|
-
function extractExplicitTaskFiles(taskText) {
|
|
345
|
-
const text = String(taskText || '');
|
|
346
|
-
const files = new Set();
|
|
347
|
-
// Common explicit path pattern (supports nested dirs and dots/dashes/underscores)
|
|
348
|
-
const pathRegex = /\b([A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+\.[A-Za-z0-9]{1,8})\b/g;
|
|
349
|
-
for (const m of text.matchAll(pathRegex)) {
|
|
350
|
-
files.add(m[1].replace(/^\.\//, ''));
|
|
351
|
-
}
|
|
352
|
-
// Bare filename pattern (e.g. "agent.ts")
|
|
353
|
-
const bareRegex = /\b([A-Za-z0-9._-]+\.[A-Za-z0-9]{1,8})\b/g;
|
|
354
|
-
for (const m of text.matchAll(bareRegex)) {
|
|
355
|
-
const file = m[1];
|
|
356
|
-
if (!file.includes('/'))
|
|
357
|
-
files.add(file);
|
|
358
|
-
}
|
|
359
|
-
return [...files];
|
|
360
|
-
}
|
|
361
|
-
function isCommandAvailable(...cmd) {
|
|
362
|
-
const command = cmd.length === 1 ? cmd[0] : cmd.join(' ');
|
|
363
|
-
const result = spawnSync('which', [cmd[0]], {
|
|
364
|
-
timeout: 5000,
|
|
365
|
-
encoding: 'utf8',
|
|
366
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
367
|
-
});
|
|
368
|
-
if (result.status !== 0)
|
|
369
|
-
return false;
|
|
370
|
-
// For compound commands like 'cargo clippy', test the full command
|
|
371
|
-
if (cmd.length > 1) {
|
|
372
|
-
const testResult = spawnSync('bash', ['-c', `${command} --help >/dev/null 2>&1`], {
|
|
373
|
-
timeout: 5000,
|
|
374
|
-
});
|
|
375
|
-
return testResult.status === 0;
|
|
376
|
-
}
|
|
377
|
-
return true;
|
|
378
|
-
}
|
|
379
|
-
function makeTargetExists(cwd, target) {
|
|
380
|
-
try {
|
|
381
|
-
const result = spawnSync('make', ['-n', target], {
|
|
382
|
-
cwd,
|
|
383
|
-
timeout: 5000,
|
|
384
|
-
stdio: ['ignore', 'ignore', 'pipe'],
|
|
385
|
-
});
|
|
386
|
-
// make -n returns 0 if target exists and is valid
|
|
387
|
-
return result.status === 0;
|
|
388
|
-
}
|
|
389
|
-
catch {
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
function truncateOutput(text, maxLen = 2000) {
|
|
394
|
-
const cleaned = text.trim();
|
|
395
|
-
return cleaned.length > maxLen ? `${cleaned.slice(0, maxLen)}...` : cleaned;
|
|
396
|
-
}
|
|
397
|
-
/** Combine stdout and stderr into a single labeled output block. */
|
|
398
|
-
function combineOutput(label, stdout, stderr) {
|
|
399
|
-
const parts = [`=== ${label} ===`];
|
|
400
|
-
const out = stdout.trim();
|
|
401
|
-
const err = stderr.trim();
|
|
402
|
-
if (out)
|
|
403
|
-
parts.push(`stdout:\n${out}`);
|
|
404
|
-
if (err)
|
|
405
|
-
parts.push(`stderr:\n${err}`);
|
|
406
|
-
if (!out && !err)
|
|
407
|
-
parts.push('(no output)');
|
|
408
|
-
return parts.join('\n');
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Parse L2 verifier response with fault tolerance.
|
|
412
|
-
* Tries JSON first, then extracts JSON from markdown fences,
|
|
413
|
-
* then falls back to keyword inference from prose.
|
|
414
|
-
*/
|
|
415
|
-
function parseVerifierResponse(raw) {
|
|
416
|
-
const text = raw.trim();
|
|
417
|
-
// 1. Try direct JSON parse
|
|
418
|
-
try {
|
|
419
|
-
const parsed = JSON.parse(text);
|
|
420
|
-
if (typeof parsed.pass === 'boolean') {
|
|
421
|
-
return { pass: parsed.pass, reason: parsed.reason || 'No reason provided' };
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
catch { /* not valid JSON, continue */ }
|
|
425
|
-
// 2. Try extracting JSON from markdown code fences or inline braces
|
|
426
|
-
const jsonMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/) || text.match(/(\{[\s\S]*?"pass"[\s\S]*?\})/);
|
|
427
|
-
if (jsonMatch) {
|
|
428
|
-
try {
|
|
429
|
-
const parsed = JSON.parse(jsonMatch[1].trim());
|
|
430
|
-
if (typeof parsed.pass === 'boolean') {
|
|
431
|
-
return { pass: parsed.pass, reason: parsed.reason || 'No reason provided' };
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
catch { /* still not valid, continue */ }
|
|
435
|
-
}
|
|
436
|
-
// 3. Keyword inference from prose
|
|
437
|
-
const lower = text.toLowerCase();
|
|
438
|
-
const passPatterns = [
|
|
439
|
-
/\bpass\b/, /\bapproved?\b/, /\blooks?\s+good\b/, /\bcorrect(ly)?\b/,
|
|
440
|
-
/\bwell[- ]implemented\b/, /\bno\s+(issues?|problems?|concerns?)\b/,
|
|
441
|
-
/\bcode\s+(is\s+)?clean\b/, /\btask\s+(is\s+)?(complete|done)\b/,
|
|
442
|
-
];
|
|
443
|
-
const failPatterns = [
|
|
444
|
-
/\bfail\b/, /\breject(ed)?\b/, /\bnot\s+(correct|approved?)\b/,
|
|
445
|
-
/\bissues?\s+found\b/, /\bproblems?\s+found\b/, /\bbug(s)?\b/,
|
|
446
|
-
/\bmissing\b/, /\bincorrect\b/, /\bbroken\b/,
|
|
447
|
-
];
|
|
448
|
-
const passScore = passPatterns.filter(p => p.test(lower)).length;
|
|
449
|
-
const failScore = failPatterns.filter(p => p.test(lower)).length;
|
|
450
|
-
if (passScore > 0 && passScore > failScore) {
|
|
451
|
-
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
452
|
-
return { pass: true, reason: `(inferred from prose) ${snippet}` };
|
|
453
|
-
}
|
|
454
|
-
if (failScore > 0) {
|
|
455
|
-
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
456
|
-
return { pass: false, reason: `(inferred from prose) ${snippet}` };
|
|
457
|
-
}
|
|
458
|
-
// 4. Ambiguous — default to pass since L1 already validated build/test
|
|
459
|
-
const snippet = text.length > 200 ? text.slice(0, 200) + '...' : text;
|
|
460
|
-
return { pass: true, reason: `(ambiguous response, defaulting to pass) ${snippet}` };
|
|
461
|
-
}
|
|
462
|
-
// ── Lint output filtering ───────────────────────────────────────────
|
|
463
|
-
/**
|
|
464
|
-
* Filter lint output to only include error-level lines (not warnings).
|
|
465
|
-
* Keeps file path headers for context. Returns empty string if no errors found.
|
|
466
|
-
*/
|
|
467
|
-
export function filterLintErrorLines(output) {
|
|
468
|
-
const lines = output.split('\n');
|
|
469
|
-
const result = [];
|
|
470
|
-
let lastFilePath = '';
|
|
471
|
-
for (const line of lines) {
|
|
472
|
-
// File path line (eslint): "/path/to/file.ts"
|
|
473
|
-
if (/^\/.*\.\w+$/.test(line.trim()) || /^[A-Z]:\\/.test(line.trim())) {
|
|
474
|
-
lastFilePath = line;
|
|
475
|
-
continue;
|
|
476
|
-
}
|
|
477
|
-
// Error line: " 1:1 error ..."
|
|
478
|
-
if (/\d+:\d+\s+error\s/.test(line) || /\berror\s+TS\d+/.test(line) || /\berror\[E\d+\]/.test(line)) {
|
|
479
|
-
if (lastFilePath && (result.length === 0 || result[result.length - 1] !== lastFilePath)) {
|
|
480
|
-
result.push(lastFilePath);
|
|
481
|
-
}
|
|
482
|
-
result.push(line);
|
|
483
|
-
}
|
|
484
|
-
// Summary line: "✖ N problems (N errors, N warnings)"
|
|
485
|
-
if (/^\u2716\s+\d+\s+problem/.test(line) || /^\d+\s+error/.test(line)) {
|
|
486
|
-
result.push(line);
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
return result.join('\n');
|
|
490
|
-
}
|
|
491
|
-
// ── Lint baseline helpers ───────────────────────────────────────────
|
|
492
|
-
/**
|
|
493
|
-
* Count the number of "error" lines in lint output.
|
|
494
|
-
* Works for eslint, tsc, ruff, clippy — all emit lines containing "error".
|
|
495
|
-
*/
|
|
496
|
-
export function countLintErrors(output) {
|
|
497
|
-
// Match lines like:
|
|
498
|
-
// 1:1 error `./types.js` ... (eslint)
|
|
499
|
-
// error TS2322: ... (tsc)
|
|
500
|
-
// src/foo.rs:1:1: error[E0308]: ... (clippy)
|
|
501
|
-
// src/foo.py:1:1: E302 ... (ruff — codes starting with E/W/F)
|
|
502
|
-
const lines = output.split('\n');
|
|
503
|
-
let count = 0;
|
|
504
|
-
for (const line of lines) {
|
|
505
|
-
// eslint: " 1:1 error ..."
|
|
506
|
-
if (/\d+:\d+\s+error\s/.test(line)) {
|
|
507
|
-
count++;
|
|
508
|
-
continue;
|
|
509
|
-
}
|
|
510
|
-
// tsc: "error TS..." or "file.ts(1,1): error TS..."
|
|
511
|
-
if (/\berror\s+TS\d+/.test(line)) {
|
|
512
|
-
count++;
|
|
513
|
-
continue;
|
|
514
|
-
}
|
|
515
|
-
// clippy/rustc: "error[E"
|
|
516
|
-
if (/\berror\[E\d+\]/.test(line)) {
|
|
517
|
-
count++;
|
|
518
|
-
continue;
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
return count;
|
|
522
|
-
}
|
|
523
|
-
/**
|
|
524
|
-
* Capture baseline lint error count before Anton starts modifying files.
|
|
525
|
-
* Returns the count, or undefined if lint is not configured or passes cleanly.
|
|
526
|
-
*/
|
|
527
|
-
export async function captureLintBaseline(lintCommand, projectDir) {
|
|
528
|
-
if (!lintCommand)
|
|
529
|
-
return undefined;
|
|
530
|
-
try {
|
|
531
|
-
const result = await runCommand(lintCommand, 180_000, projectDir);
|
|
532
|
-
if (result.exitCode === 0)
|
|
533
|
-
return 0; // clean baseline
|
|
534
|
-
const count = countLintErrors(result.stdout + '\n' + result.stderr);
|
|
535
|
-
if (count > 0) {
|
|
536
|
-
console.error(`[anton:baseline] pre-existing lint errors: ${count}`);
|
|
537
|
-
}
|
|
538
|
-
return count;
|
|
539
|
-
}
|
|
540
|
-
catch {
|
|
541
|
-
return undefined;
|
|
542
|
-
}
|
|
543
|
-
}
|
|
342
|
+
// Helper functions
|
|
544
343
|
//# sourceMappingURL=verifier.js.map
|