@evomap/evolver 1.85.0 → 1.85.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/README.md +22 -1
- package/package.json +1 -1
- package/scripts/build_binaries.js +69 -12
- package/src/adapters/scripts/evolver-session-end.js +110 -15
- package/src/evolve/guards.js +1 -1
- package/src/evolve/pipeline/collect.js +1 -1
- package/src/evolve/pipeline/dispatch.js +1 -1
- package/src/evolve/pipeline/enrich.js +1 -1
- package/src/evolve/pipeline/hub.js +1 -1
- package/src/evolve/pipeline/select.js +1 -1
- package/src/evolve/pipeline/signals.js +1 -1
- package/src/evolve/utils.js +1 -1
- package/src/evolve.js +1 -1
- package/src/gep/a2aProtocol.js +1 -1
- package/src/gep/assetStore.js +17 -0
- package/src/gep/candidateEval.js +1 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/contentHash.js +1 -1
- package/src/gep/crypto.js +1 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +1 -1
- package/src/gep/envFingerprint.js +1 -1
- package/src/gep/epigenetics.js +1 -1
- package/src/gep/explore.js +1 -1
- package/src/gep/hash.js +1 -1
- package/src/gep/hubFetch.js +1 -1
- package/src/gep/hubReview.js +1 -1
- package/src/gep/hubSearch.js +1 -1
- package/src/gep/hubVerify.js +1 -1
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1 -1
- package/src/gep/memoryGraphAdapter.js +1 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/openPRRegistry.js +1 -1
- package/src/gep/paths.js +79 -0
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/prompt.js +1 -1
- package/src/gep/recallVerifier.js +1 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
package/README.md
CHANGED
|
@@ -136,11 +136,32 @@ Evolver integrates with major agent runtimes through `setup-hooks`. Run it once
|
|
|
136
136
|
|---|---|---|
|
|
137
137
|
| [Cursor](https://cursor.com) | `evolver setup-hooks --platform=cursor` | `~/.cursor/hooks.json` + scripts in `~/.cursor/hooks/`. Restart Cursor or open a new session. Fires on `sessionStart`, `afterFileEdit`, `stop`. |
|
|
138
138
|
| [Claude Code](https://www.anthropic.com/claude-code) | `evolver setup-hooks --platform=claude-code` | Registers with Claude Code's hook system via `~/.claude/`. Restart the Claude Code CLI. |
|
|
139
|
-
| [Codex](https://github.com/openai/codex) | `evolver setup-hooks --platform=codex` | `~/.codex/hooks.json` + scripts in `~/.codex/hooks/`, enables `codex_hooks` feature in `config.toml`. Restart the Codex CLI. |
|
|
139
|
+
| [Codex](https://github.com/openai/codex) | `evolver setup-hooks --platform=codex` | `~/.codex/hooks.json` + scripts in `~/.codex/hooks/`, enables `codex_hooks` feature in `config.toml`. Restart the Codex CLI. See [Codex caveats](#codex-caveats) below. |
|
|
140
140
|
| [Kiro](https://kiro.dev) | `evolver setup-hooks --platform=kiro` | Three `*.kiro.hook` files + scripts in `~/.kiro/hooks/`. Auto-discovered, no restart needed. |
|
|
141
141
|
| [opencode](https://opencode.ai) | `evolver setup-hooks --platform=opencode` | Plugin at `~/.opencode/plugins/evolver.js` + scripts in `~/.opencode/hooks/`. Restart opencode. |
|
|
142
142
|
| [OpenClaw](https://openclaw.com) | No setup needed | OpenClaw natively interprets the `sessions_spawn(...)` stdout directives Evolver emits. Just run `evolver` from inside an OpenClaw session. |
|
|
143
143
|
|
|
144
|
+
#### Codex caveats
|
|
145
|
+
|
|
146
|
+
The Codex CLI exposes `SessionStart` / `Stop` / `PostToolUse` hooks (which is
|
|
147
|
+
how `setup-hooks --platform=codex` wires Evolver in), but it does **not**
|
|
148
|
+
emit a session transcript file the way Cursor / Claude Code / opencode do.
|
|
149
|
+
That means `evolver --review` cannot read raw session logs on Codex.
|
|
150
|
+
|
|
151
|
+
Evolver compensates by reading, in order:
|
|
152
|
+
|
|
153
|
+
1. `MEMORY.md` / `USER.md` in the workspace root (if you maintain them);
|
|
154
|
+
2. the `<!-- evolver-evolution-memory -->` section that
|
|
155
|
+
`setup-hooks --platform=codex` injects into your project's
|
|
156
|
+
`AGENTS.md`;
|
|
157
|
+
3. the tail of the local `memory_graph.jsonl` (the per-cycle outcome log
|
|
158
|
+
that Evolver writes itself).
|
|
159
|
+
|
|
160
|
+
If none of those have content yet, you'll see `memory_missing` /
|
|
161
|
+
`user_missing` / `session_logs_missing` show up as advisory signals
|
|
162
|
+
during the first few cycles. They will go quiet on their own as
|
|
163
|
+
`memory_graph.jsonl` accumulates outcomes — no manual setup required.
|
|
164
|
+
|
|
144
165
|
## Run from Source (Contributors Only)
|
|
145
166
|
|
|
146
167
|
Skip this section entirely if you installed via `npm install -g @evomap/evolver` above. This path exists so contributors can hack on the engine.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver",
|
|
3
|
-
"version": "1.85.
|
|
3
|
+
"version": "1.85.1",
|
|
4
4
|
"description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -208,13 +208,15 @@ if (!OPTS.skipObfuscate) {
|
|
|
208
208
|
if (!OPTS.dryRun) {
|
|
209
209
|
const O = require(require.resolve('javascript-obfuscator', { paths: [REPO_ROOT] }));
|
|
210
210
|
const src = fs.readFileSync(BUNDLED_JS, 'utf8');
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
211
|
+
// Seed obfuscation from release version: gives same-version reruns a
|
|
212
|
+
// narrow PRNG path, but the obfuscator has internal non-determinism
|
|
213
|
+
// beyond the seed (Set iteration / stringArray rotation timing) so two
|
|
214
|
+
// runs with the same seed can still differ slightly. Empirically ~5%
|
|
215
|
+
// of those runs emit invalid syntax (e.g. mangling `new.target` to
|
|
216
|
+
// `#target`, which then crashes `bun compile`). Validate after each
|
|
217
|
+
// attempt and retry — see RETRY note in pipeline rationale below.
|
|
218
|
+
const baseSeed = parseInt(crypto.createHash('sha256').update(`evolver:${releaseVersion}`).digest('hex').slice(0, 8), 16);
|
|
219
|
+
const obfOpts = {
|
|
218
220
|
compact: true,
|
|
219
221
|
controlFlowFlattening: true,
|
|
220
222
|
controlFlowFlatteningThreshold: 0.75,
|
|
@@ -237,12 +239,49 @@ if (!OPTS.skipObfuscate) {
|
|
|
237
239
|
numbersToExpressions: true,
|
|
238
240
|
unicodeEscapeSequence: true,
|
|
239
241
|
target: 'node',
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
const MAX_OBF_ATTEMPTS_RAW = process.env.OBF_MAX_ATTEMPTS;
|
|
245
|
+
const MAX_OBF_ATTEMPTS = MAX_OBF_ATTEMPTS_RAW === undefined
|
|
246
|
+
? 4
|
|
247
|
+
: parseInt(MAX_OBF_ATTEMPTS_RAW, 10);
|
|
248
|
+
if (!Number.isInteger(MAX_OBF_ATTEMPTS) || MAX_OBF_ATTEMPTS < 1) {
|
|
249
|
+
console.error(` ERROR: OBF_MAX_ATTEMPTS must be a positive integer; got ${JSON.stringify(MAX_OBF_ATTEMPTS_RAW)}.`);
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
let attempt = 0;
|
|
253
|
+
let usedSeed = baseSeed;
|
|
254
|
+
let lastValidationErr = null;
|
|
255
|
+
let succeeded = false;
|
|
256
|
+
while (attempt < MAX_OBF_ATTEMPTS) {
|
|
257
|
+
attempt++;
|
|
258
|
+
// Perturb seed on retries to dodge a stuck PRNG path. Attempt 1 keeps
|
|
259
|
+
// the canonical seed for best-effort reproducibility; later attempts
|
|
260
|
+
// shift by attempt index so the next deploy gets a fresh trajectory.
|
|
261
|
+
usedSeed = baseSeed + (attempt - 1);
|
|
262
|
+
const t0 = Date.now();
|
|
263
|
+
const result = O.obfuscate(src, { ...obfOpts, seed: usedSeed });
|
|
264
|
+
fs.writeFileSync(OBF_JS, result.getObfuscatedCode());
|
|
265
|
+
const obfSize = fs.statSync(OBF_JS).size;
|
|
266
|
+
const obfSecs = ((Date.now() - t0) / 1000).toFixed(1);
|
|
267
|
+
|
|
268
|
+
const check = spawnSync('node', ['--check', OBF_JS], { encoding: 'utf8' });
|
|
269
|
+
if (check.status === 0) {
|
|
270
|
+
console.log(` obfuscation: ${obfSecs}s, output ${(obfSize / 1024 / 1024).toFixed(2)} MB (attempt ${attempt}/${MAX_OBF_ATTEMPTS}, seed=0x${usedSeed.toString(16)})`);
|
|
271
|
+
succeeded = true;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
lastValidationErr = (check.stderr || check.stdout || '').split('\n').slice(0, 3).join(' | ');
|
|
275
|
+
console.warn(` attempt ${attempt}/${MAX_OBF_ATTEMPTS}: obfuscator output failed node --check (${lastValidationErr.slice(0, 200)}); retrying with perturbed seed...`);
|
|
276
|
+
}
|
|
277
|
+
if (!succeeded) {
|
|
278
|
+
console.error(` ERROR: javascript-obfuscator produced syntactically invalid output in ${MAX_OBF_ATTEMPTS} attempts.`);
|
|
279
|
+
console.error(` last error: ${lastValidationErr || '(none — loop did not run)'}`);
|
|
280
|
+
console.error(` raise OBF_MAX_ATTEMPTS env var to retry more times, or temporarily run with --skip-obfuscate.`);
|
|
281
|
+
process.exit(2);
|
|
282
|
+
}
|
|
244
283
|
} else {
|
|
245
|
-
console.log(' [dry-run] would obfuscate stage/bundled.js -> stage/bundled.obf.js');
|
|
284
|
+
console.log(' [dry-run] would obfuscate stage/bundled.js -> stage/bundled.obf.js (with retry-on-syntax-error)');
|
|
246
285
|
}
|
|
247
286
|
|
|
248
287
|
payloadJs = OBF_JS;
|
|
@@ -386,3 +425,21 @@ console.log(' next: gh release upload v<ver> dist-binaries/* --repo EvoMap/evol
|
|
|
386
425
|
// in GitHub Actions on `runs-on: macos-latest, ubuntu-latest` should
|
|
387
426
|
// set up the matrix so each runner smoke-tests its own native target.
|
|
388
427
|
//
|
|
428
|
+
// Stage 2 retry-on-syntax-error (added 2026-05-22, v1.85.0 deploy
|
|
429
|
+
// post-mortem):
|
|
430
|
+
//
|
|
431
|
+
// The v1.85.0 release deploy hit `bun compile` failing with
|
|
432
|
+
// `Expected "in" but found ","` at offset ~1.5MB into bundled.obf.js.
|
|
433
|
+
// The failing region contained `(#target,this)` — javascript-obfuscator
|
|
434
|
+
// had mangled `new.target` into `#target` (a private class field syntax
|
|
435
|
+
// that's only legal inside a class body). A from-scratch rebuild on the
|
|
436
|
+
// same source + seed produced a different output (15.18 MB vs 15.14 MB)
|
|
437
|
+
// that compiled cleanly, confirming the obfuscator has internal
|
|
438
|
+
// non-determinism beyond the user-supplied seed.
|
|
439
|
+
//
|
|
440
|
+
// Mitigation: after each obfuscation attempt, run `node --check` on the
|
|
441
|
+
// output; if syntax is invalid, perturb the seed by +attempt and retry
|
|
442
|
+
// up to OBF_MAX_ATTEMPTS times (default 4). Cost of validation is
|
|
443
|
+
// ~1 second on 15 MB; cost of catching the failure here vs after a
|
|
444
|
+
// doomed bun compile pass is roughly 50s saved per failure.
|
|
445
|
+
//
|
|
@@ -2,16 +2,40 @@
|
|
|
2
2
|
// evolver-session-end.js
|
|
3
3
|
// Records evolution outcome at session end.
|
|
4
4
|
// Collects git diff stats, extracts signals, records via Hub API or local memory.
|
|
5
|
-
// Input: stdin JSON. Output: stdout JSON with
|
|
5
|
+
// Input: stdin JSON. Output: stdout JSON with `systemMessage` (Claude Code Stop
|
|
6
|
+
// hook notification) — or empty `{}` on Cursor where systemMessage is mishandled.
|
|
6
7
|
|
|
7
8
|
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
8
11
|
const { spawnSync } = require('child_process');
|
|
9
12
|
// 10 MB — prevents RangeError on large child process output (e.g. git log/diff
|
|
10
13
|
// on large repos). See GHSA reports / issue #451.
|
|
11
14
|
const MAX_EXEC_BUFFER = 10 * 1024 * 1024;
|
|
12
15
|
|
|
16
|
+
const path = require('path');
|
|
13
17
|
const { findEvolverRoot, findMemoryGraph } = require('./_runtimePaths');
|
|
14
18
|
|
|
19
|
+
// Workspace-id must use the same resolution as the reader in
|
|
20
|
+
// src/evolve/pipeline/collect.js (which goes through src/gep/paths.js#
|
|
21
|
+
// getWorkspaceRoot()). Otherwise writer and reader could land on
|
|
22
|
+
// different `.evolver/workspace-id` files when EVOLVER_REPO_ROOT or
|
|
23
|
+
// OPENCLAW_WORKSPACE is set, or when a `<repoRoot>/workspace`
|
|
24
|
+
// subdirectory exists — in which case the IDs would never match and
|
|
25
|
+
// every memory-graph entry would silently get dropped (Bugbot PR #109
|
|
26
|
+
// round-1 MEDIUM). Lazy-load the canonical resolver from the resolved
|
|
27
|
+
// evolver root; fall back to env-only when paths.js is unreachable.
|
|
28
|
+
function resolveWorkspaceIdForWriter() {
|
|
29
|
+
if (process.env.EVOLVER_WORKSPACE_ID) return String(process.env.EVOLVER_WORKSPACE_ID);
|
|
30
|
+
const evolverRoot = findEvolverRoot();
|
|
31
|
+
if (!evolverRoot) return null;
|
|
32
|
+
try {
|
|
33
|
+
const paths = require(path.join(evolverRoot, 'src', 'gep', 'paths.js'));
|
|
34
|
+
if (typeof paths.getWorkspaceId === 'function') return paths.getWorkspaceId();
|
|
35
|
+
} catch { /* paths.js unreachable — return null */ }
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
15
39
|
function runGit(args, cwd) {
|
|
16
40
|
// Argv-array form, no shell. Avoids POSIX `2>/dev/null` redirects that
|
|
17
41
|
// break on Windows cmd.exe (#537). Failures (e.g. no HEAD~1 in a fresh
|
|
@@ -52,6 +76,31 @@ function getGitDiffStats() {
|
|
|
52
76
|
};
|
|
53
77
|
}
|
|
54
78
|
|
|
79
|
+
// Detect whether the hook is running inside Cursor.
|
|
80
|
+
//
|
|
81
|
+
// Why: Claude Code's Stop hook spec says `systemMessage` is a notification
|
|
82
|
+
// shown to the user and is NOT fed back into Claude's context. Cursor's
|
|
83
|
+
// Claude Code-compatible runtime currently splices it into the next
|
|
84
|
+
// inference round as if it were a user prompt, so Claude "responds" to the
|
|
85
|
+
// evolution receipt — visible to users as an unexplained extra reasoning
|
|
86
|
+
// turn after every task. Until Cursor fixes this, suppress systemMessage
|
|
87
|
+
// on Cursor while keeping the local-memory append intact.
|
|
88
|
+
//
|
|
89
|
+
// Detection (any of):
|
|
90
|
+
// - TERM_PROGRAM=cursor
|
|
91
|
+
// - CURSOR_TRACE_ID / CURSOR_SESSION_ID set
|
|
92
|
+
// - EVOLVER_HOOK_HOST=cursor (manual override)
|
|
93
|
+
// Escape hatch: EVOLVER_HOOK_VERBOSE=1 forces the message on regardless.
|
|
94
|
+
function isCursorHost() {
|
|
95
|
+
const verbose = String(process.env.EVOLVER_HOOK_VERBOSE || '').toLowerCase();
|
|
96
|
+
if (verbose === '1' || verbose === 'true') return false;
|
|
97
|
+
if (String(process.env.EVOLVER_HOOK_HOST || '').toLowerCase() === 'cursor') return true;
|
|
98
|
+
if (String(process.env.TERM_PROGRAM || '').toLowerCase() === 'cursor') return true;
|
|
99
|
+
if (process.env.CURSOR_TRACE_ID) return true;
|
|
100
|
+
if (process.env.CURSOR_SESSION_ID) return true;
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
|
|
55
104
|
function detectSignals(text) {
|
|
56
105
|
if (!text) return [];
|
|
57
106
|
const lower = text.toLowerCase();
|
|
@@ -113,6 +162,21 @@ function recordToLocal(graphPath, outcome) {
|
|
|
113
162
|
score: outcome.score,
|
|
114
163
|
note: outcome.summary,
|
|
115
164
|
},
|
|
165
|
+
// Tag the originating workspace so the review-time reader in
|
|
166
|
+
// collect.js can scope user-level fallback entries to the current
|
|
167
|
+
// cwd. Without this, two unrelated projects sharing the user-level
|
|
168
|
+
// fallback file (~/.evolver/memory/evolution/memory_graph.jsonl,
|
|
169
|
+
// used by npm-global installs) would cross-pollinate each other's
|
|
170
|
+
// review context — a prompt-injection / disclosure surface flagged
|
|
171
|
+
// by Bugbot on PR #105 round-2.
|
|
172
|
+
//
|
|
173
|
+
// workspace_id is the forge-resistant tag (PR #108 round-3): the
|
|
174
|
+
// reader compares it against the secret in the workspace's own
|
|
175
|
+
// .evolver/workspace-id file. cwd is retained as a backward-compat
|
|
176
|
+
// tag so older entries written before this hardening still pass
|
|
177
|
+
// the cwd check.
|
|
178
|
+
cwd: process.cwd(),
|
|
179
|
+
workspace_id: resolveWorkspaceIdForWriter(),
|
|
116
180
|
source: 'hook:session-end',
|
|
117
181
|
};
|
|
118
182
|
fs.appendFileSync(graphPath, JSON.stringify(entry) + '\n', 'utf8');
|
|
@@ -125,16 +189,23 @@ function recordToLocal(graphPath, outcome) {
|
|
|
125
189
|
function main() {
|
|
126
190
|
let inputData = '';
|
|
127
191
|
let handled = false;
|
|
192
|
+
let watchdog = null;
|
|
193
|
+
const finish = (payload) => {
|
|
194
|
+
if (handled) return;
|
|
195
|
+
handled = true;
|
|
196
|
+
if (watchdog) clearTimeout(watchdog);
|
|
197
|
+
process.stdout.write(JSON.stringify(payload || {}));
|
|
198
|
+
process.exit(0);
|
|
199
|
+
};
|
|
128
200
|
process.stdin.setEncoding('utf8');
|
|
129
201
|
process.stdin.on('data', chunk => { inputData += chunk; });
|
|
130
202
|
process.stdin.on('end', () => {
|
|
131
203
|
if (handled) return;
|
|
132
|
-
handled = true;
|
|
133
204
|
try {
|
|
134
205
|
const diffInfo = getGitDiffStats();
|
|
135
206
|
|
|
136
207
|
if (!diffInfo.hasChanges) {
|
|
137
|
-
|
|
208
|
+
finish({});
|
|
138
209
|
return;
|
|
139
210
|
}
|
|
140
211
|
|
|
@@ -162,22 +233,46 @@ function main() {
|
|
|
162
233
|
const target = hubOk ? 'Hub' : localOk ? 'local memory' : 'nowhere (no Hub or local path)';
|
|
163
234
|
const msg = `[Evolution] Session outcome recorded to ${target}: ${outcome.summary}`;
|
|
164
235
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
236
|
+
// Stop hook output schema (per Claude Code docs):
|
|
237
|
+
// - decision: "approve" | "block"
|
|
238
|
+
// - reason: string (shown when decision is set)
|
|
239
|
+
// - systemMessage: string (notification displayed to user)
|
|
240
|
+
// - continue: boolean
|
|
241
|
+
// - stopReason: string
|
|
242
|
+
//
|
|
243
|
+
// Earlier versions emitted `followup_message`, `stopMessage`, and
|
|
244
|
+
// `additionalContext` together. `followup_message` is the field that
|
|
245
|
+
// re-injects the receipt into Claude's next inference round, which
|
|
246
|
+
// caused the agent to "respond" to its own evolution log line —
|
|
247
|
+
// visible to users as an unexplained extra reasoning turn after
|
|
248
|
+
// every task. The evolver is supposed to be observational, so we
|
|
249
|
+
// now use `systemMessage` only — that surfaces the receipt to the
|
|
250
|
+
// user without forcing another inference round.
|
|
251
|
+
//
|
|
252
|
+
// Cursor compatibility: Cursor's Claude Code-compatible runtime
|
|
253
|
+
// currently treats `systemMessage` as a user prompt for the next
|
|
254
|
+
// inference round. When we detect Cursor, omit systemMessage too.
|
|
255
|
+
// The receipt is always appended to ~/.evolver/logs/evolution.log
|
|
256
|
+
// so it is never silently lost; users can opt back in to the inline
|
|
257
|
+
// notification with EVOLVER_HOOK_VERBOSE=1.
|
|
258
|
+
try {
|
|
259
|
+
const logDir = process.env.EVOLVER_HOOK_LOG_DIR
|
|
260
|
+
|| path.join(os.homedir(), '.evolver', 'logs');
|
|
261
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
262
|
+
fs.appendFileSync(
|
|
263
|
+
path.join(logDir, 'evolution.log'),
|
|
264
|
+
`${new Date().toISOString()} ${msg}\n`,
|
|
265
|
+
'utf8'
|
|
266
|
+
);
|
|
267
|
+
} catch { /* best-effort, never break the hook on log write */ }
|
|
268
|
+
|
|
269
|
+
finish(isCursorHost() ? {} : { systemMessage: msg });
|
|
170
270
|
} catch (e) {
|
|
171
|
-
|
|
271
|
+
finish({});
|
|
172
272
|
}
|
|
173
273
|
});
|
|
174
274
|
|
|
175
|
-
setTimeout(() => {
|
|
176
|
-
if (handled) return;
|
|
177
|
-
handled = true;
|
|
178
|
-
process.stdout.write(JSON.stringify({}));
|
|
179
|
-
process.exit(0);
|
|
180
|
-
}, 7000);
|
|
275
|
+
watchdog = setTimeout(() => finish({}), 7000);
|
|
181
276
|
}
|
|
182
277
|
|
|
183
278
|
main();
|