mtech-ai-local-runner 0.1.30 → 0.1.32
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/README.md +64 -1
- package/dist/src/adapters/claude-code/adapter.js +76 -17
- package/dist/src/adapters/codex/adapter.js +146 -30
- package/dist/src/adapters/codex/exec-launch-host.js +50 -11
- package/dist/src/adapters/codex/stream-parser.js +8 -17
- package/dist/src/adapters/completion-report.js +8 -5
- package/dist/src/cli.js +23 -0
- package/dist/src/config.js +4 -4
- package/dist/src/daemon/daemon.js +62 -4
- package/dist/src/daemon/execution-coordinator.js +351 -77
- package/dist/src/daemon/job-poller.js +4 -1
- package/dist/src/daemon/manual-codex.js +10 -3
- package/dist/src/daemon/preparation-lease.js +142 -0
- package/dist/src/daemon/runtime.js +65 -23
- package/dist/src/daemon/terminal-recovery.js +29 -5
- package/dist/src/gateway-client.js +120 -22
- package/dist/src/platform/macos/launchd.js +13 -2
- package/dist/src/process/node-process-group-host.js +89 -34
- package/dist/src/process/owned-process-guardian.js +140 -0
- package/dist/src/publication/candidate.js +95 -0
- package/dist/src/publication/execution-host.js +55 -0
- package/dist/src/publication/git-credential-broker.js +150 -0
- package/dist/src/publication/git-credential-helper.js +29 -0
- package/dist/src/publication/git-snapshot.js +321 -0
- package/dist/src/publication/git-transport.js +156 -0
- package/dist/src/publication/installed-host.js +120 -0
- package/dist/src/publication/isolated-verifier.js +67 -0
- package/dist/src/publication/journal.js +87 -0
- package/dist/src/publication/production-host.js +155 -0
- package/dist/src/publication/project-registration.js +49 -0
- package/dist/src/publication/publisher.js +166 -0
- package/dist/src/publication/recovery.js +53 -0
- package/dist/src/publication/runtime-release.js +91 -0
- package/dist/src/publication/server-ci-error.js +15 -0
- package/dist/src/publication/server-ci-host.js +160 -0
- package/dist/src/runner.js +33 -4
- package/dist/src/safety/codex-daemon-host.js +2 -2
- package/dist/src/safety/command-policy-core.js +124 -0
- package/dist/src/safety/command-policy.js +1 -124
- package/dist/src/safety/execution-failure.js +4 -0
- package/dist/src/safety/job-tool-policy.js +9 -0
- package/dist/src/safety/local-tool-policy.js +1 -1
- package/dist/src/safety/terminal-evidence.js +67 -16
- package/dist/src/safety/unsupported-supervisor-command.js +12 -0
- package/dist/src/state-store.js +50 -7
- package/dist/src/workspace/workspace-manager.js +14 -0
- package/package.json +3 -2
- package/verification/README.md +63 -0
- package/verification/runner-policy.cjs +24 -0
package/dist/src/config.js
CHANGED
|
@@ -6,11 +6,11 @@ export function isExecutionConfig(config) {
|
|
|
6
6
|
return config.mode === "shadow" || config.mode === "once";
|
|
7
7
|
}
|
|
8
8
|
export function isServiceConfig(config) {
|
|
9
|
-
return ["setup", "doctor", "run", "start", "stop", "status", "uninstall", "manual-codex"].includes(config.mode);
|
|
9
|
+
return ["setup", "doctor", "run", "start", "stop", "status", "uninstall", "manual-codex", "publication-recover"].includes(config.mode);
|
|
10
10
|
}
|
|
11
11
|
const EXECUTION_MODES = ["shadow", "once"];
|
|
12
12
|
const AUTH_MODES = ["login", "logout"];
|
|
13
|
-
const SERVICE_MODES = ["setup", "doctor", "run", "start", "stop", "status", "uninstall", "manual-codex"];
|
|
13
|
+
const SERVICE_MODES = ["setup", "doctor", "run", "start", "stop", "status", "uninstall", "manual-codex", "publication-recover"];
|
|
14
14
|
const ALL_MODES = [...EXECUTION_MODES, ...AUTH_MODES, ...SERVICE_MODES];
|
|
15
15
|
export const DEFAULT_GATEWAY_MCP_URL = "https://cloud.dev.service.ai-gateway.laravelvapor.org/api/v1/web/ai-gateway/mcp";
|
|
16
16
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -101,9 +101,9 @@ export function loadConfig(argv, env) {
|
|
|
101
101
|
const stateRoot = defaultStateRootFromEnv(env);
|
|
102
102
|
if (SERVICE_MODES.includes(mode)) {
|
|
103
103
|
let manualJobId;
|
|
104
|
-
if (mode === 'manual-codex') {
|
|
104
|
+
if (mode === 'manual-codex' || mode === 'publication-recover') {
|
|
105
105
|
if (rest.length !== 1 || !rest[0].startsWith('--job-id=') || !UUID_PATTERN.test(rest[0].slice(9)))
|
|
106
|
-
throw new Error(
|
|
106
|
+
throw new Error(`${mode} requires exactly --job-id=<uuid>`);
|
|
107
107
|
manualJobId = rest[0].slice(9).toLowerCase();
|
|
108
108
|
}
|
|
109
109
|
return {
|
|
@@ -1,15 +1,73 @@
|
|
|
1
1
|
export class Daemon {
|
|
2
2
|
deps;
|
|
3
|
+
stopping = new AbortController();
|
|
3
4
|
constructor(deps) {
|
|
4
5
|
this.deps = deps;
|
|
5
6
|
}
|
|
7
|
+
stop() { this.deps.poller.stop?.(); this.stopping.abort(); }
|
|
8
|
+
async suspend(state, duringExecution = false) {
|
|
9
|
+
const phase = state && typeof state === 'object' && 'phase' in state ? state.phase : undefined;
|
|
10
|
+
const reason = duringExecution ? 'execution_outcome_unknown' : phase === 'binding' || phase === 'binding_uncertain' ? 'binding_outcome_unknown' : 'runner_restarted';
|
|
11
|
+
try {
|
|
12
|
+
await this.deps.state.suspend?.(reason);
|
|
13
|
+
}
|
|
14
|
+
catch { /* Preserve original state and remain alive even if the marker cannot be written. */ }
|
|
15
|
+
try {
|
|
16
|
+
this.deps.reportRecoveryRequired?.(reason);
|
|
17
|
+
}
|
|
18
|
+
catch { /* Logging cannot reopen claims or exit suspended recovery. */ }
|
|
19
|
+
if (this.stopping.signal.aborted)
|
|
20
|
+
return;
|
|
21
|
+
if (this.deps.wait) {
|
|
22
|
+
await this.deps.wait(this.stopping.signal);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// A pending promise does not keep Node alive. This timer deliberately stays
|
|
26
|
+
// referenced, holds the process lock and wakes only for explicit close.
|
|
27
|
+
await new Promise(resolve => {
|
|
28
|
+
const timer = setInterval(() => { }, 60_000);
|
|
29
|
+
this.stopping.signal.addEventListener('abort', () => { clearInterval(timer); resolve(); }, { once: true });
|
|
30
|
+
});
|
|
31
|
+
}
|
|
6
32
|
async run() {
|
|
7
33
|
await this.deps.lock.acquire();
|
|
8
34
|
try {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
await this.deps.
|
|
12
|
-
|
|
35
|
+
let state;
|
|
36
|
+
try {
|
|
37
|
+
state = await this.deps.state.load();
|
|
38
|
+
if (state !== null && state !== undefined) {
|
|
39
|
+
await this.deps.reconcile(state);
|
|
40
|
+
state = await this.deps.state.load();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
await this.suspend(state);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (state !== null && state !== undefined) {
|
|
48
|
+
await this.suspend(state);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (this.stopping.signal.aborted)
|
|
52
|
+
return;
|
|
53
|
+
try {
|
|
54
|
+
await this.deps.poller.run();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
try {
|
|
58
|
+
this.deps.poller.stop?.();
|
|
59
|
+
}
|
|
60
|
+
catch { /* Still inspect retained state and suspend below. */ }
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
state = await this.deps.state.load();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
await this.suspend(undefined, true);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (state !== null && state !== undefined)
|
|
70
|
+
await this.suspend(state, true);
|
|
13
71
|
}
|
|
14
72
|
finally {
|
|
15
73
|
await this.deps.lock.release();
|