compact-agent 1.27.1 → 1.28.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/bin/crowcoder.js +48 -3
- package/bin/ecc-hooks.cjs +13 -0
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/debug.d.ts +97 -0
- package/dist/debug.js +217 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.js +96 -1
- package/dist/index.js.map +1 -1
- package/dist/query.js +37 -3
- package/dist/query.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/bin/crowcoder.js
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// In-process best-effort: override process.emitWarning to drop DEP0040.
|
|
3
3
|
// Catches the warning when it's emitted late (after this runs), but does NOT
|
|
4
4
|
// catch warnings fired during Node's ESM bootstrap (before any user code).
|
|
5
|
-
// For a fully clean stderr, invoke
|
|
5
|
+
// For a fully clean stderr, invoke compact-agent via:
|
|
6
6
|
// node --no-deprecation bin/crowcoder.js
|
|
7
|
-
// NODE_OPTIONS=--no-deprecation
|
|
8
|
-
// oag chat # already passes --no-deprecation
|
|
7
|
+
// NODE_OPTIONS=--no-deprecation compact-agent
|
|
9
8
|
(() => {
|
|
10
9
|
const orig = process.emitWarning;
|
|
11
10
|
process.emitWarning = function patched(warning, ...rest) {
|
|
@@ -16,4 +15,50 @@
|
|
|
16
15
|
return orig.call(this, warning, ...rest);
|
|
17
16
|
};
|
|
18
17
|
})();
|
|
18
|
+
|
|
19
|
+
// ── --debug [level] flag ───────────────────────────────────
|
|
20
|
+
// Parse here at the entry point so that the env var is set BEFORE
|
|
21
|
+
// any module-level code in dist/index.js reads it. The debug
|
|
22
|
+
// instrumentation in src/debug.ts checks $COMPACT_AGENT_DEBUG at
|
|
23
|
+
// init time; setting it from argv keeps the implementation in one
|
|
24
|
+
// place (env var as single source of truth).
|
|
25
|
+
//
|
|
26
|
+
// Accepted forms:
|
|
27
|
+
// --debug → info
|
|
28
|
+
// --debug=trace → trace
|
|
29
|
+
// --debug trace → trace
|
|
30
|
+
// --debug=on → info (alias)
|
|
31
|
+
// --debug=off → off
|
|
32
|
+
//
|
|
33
|
+
// Invalid levels fall back to 'info' with a one-line stderr notice.
|
|
34
|
+
(() => {
|
|
35
|
+
const argv = process.argv;
|
|
36
|
+
const VALID = new Set(['off', 'info', 'debug', 'trace', 'on']);
|
|
37
|
+
for (let i = 2; i < argv.length; i++) {
|
|
38
|
+
const a = argv[i];
|
|
39
|
+
if (a === '--debug') {
|
|
40
|
+
const next = argv[i + 1];
|
|
41
|
+
if (next && VALID.has(next.toLowerCase())) {
|
|
42
|
+
process.env.COMPACT_AGENT_DEBUG = next.toLowerCase() === 'on' ? 'info' : next.toLowerCase();
|
|
43
|
+
argv.splice(i, 2);
|
|
44
|
+
} else {
|
|
45
|
+
process.env.COMPACT_AGENT_DEBUG = 'info';
|
|
46
|
+
argv.splice(i, 1);
|
|
47
|
+
}
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
if (a && a.startsWith('--debug=')) {
|
|
51
|
+
const lvl = a.slice('--debug='.length).toLowerCase();
|
|
52
|
+
if (VALID.has(lvl)) {
|
|
53
|
+
process.env.COMPACT_AGENT_DEBUG = lvl === 'on' ? 'info' : lvl;
|
|
54
|
+
} else {
|
|
55
|
+
process.stderr.write(`[compact-agent] unknown --debug level "${lvl}"; defaulting to 'info'.\n`);
|
|
56
|
+
process.env.COMPACT_AGENT_DEBUG = 'info';
|
|
57
|
+
}
|
|
58
|
+
argv.splice(i, 1);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
63
|
+
|
|
19
64
|
import('../dist/index.js');
|
package/bin/ecc-hooks.cjs
CHANGED
|
@@ -194,6 +194,19 @@ const checks = {
|
|
|
194
194
|
const targetPath = filePath();
|
|
195
195
|
if (!targetPath) return ok();
|
|
196
196
|
|
|
197
|
+
// ── Brand-new file bypass ────────────────────────────
|
|
198
|
+
// The "investigate before editing" rule only makes sense for files
|
|
199
|
+
// that already exist (someone could be depending on the current
|
|
200
|
+
// contents). A brand-new file has no existing contents to read, no
|
|
201
|
+
// current consumers to grep for, and no existing data to validate
|
|
202
|
+
// schema against — the three things the block message tells the
|
|
203
|
+
// agent to do are all no-ops. Skipping prevents the false-positive
|
|
204
|
+
// scaffolding lockup where every fresh project hits a wall on
|
|
205
|
+
// every new file.
|
|
206
|
+
try {
|
|
207
|
+
if (!fs.existsSync(targetPath)) return ok();
|
|
208
|
+
} catch { /* if statSync fails, fall through to the normal path */ }
|
|
209
|
+
|
|
197
210
|
const sessionId = process.env.CROWCODER_SESSION_ID || 'unknown';
|
|
198
211
|
const stateDir = pathMod.join(os.homedir(), '.compact-agent', 'state', 'gateguard');
|
|
199
212
|
const stateFile = pathMod.join(stateDir, `${sessionId}.json`);
|
package/dist/config.js
CHANGED
|
@@ -220,7 +220,7 @@ function validateConfig(config) {
|
|
|
220
220
|
config.permissionMode = 'ask';
|
|
221
221
|
}
|
|
222
222
|
// Warn on unexpected fields
|
|
223
|
-
const expectedFields = new Set(['apiKey', 'apiKeys', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice', 'memory', 'sandbox']);
|
|
223
|
+
const expectedFields = new Set(['apiKey', 'apiKeys', 'baseURL', 'model', 'fallbackModel', 'provider', 'maxTokens', 'maxTurns', 'temperature', 'permissionMode', 'alwaysAllowedTools', 'dryRun', 'theme', 'palette', 'showThinking', 'voice', 'memory', 'sandbox']);
|
|
224
224
|
for (const key in config) {
|
|
225
225
|
if (!expectedFields.has(key) && !_alreadyWarnedFields.has(key)) {
|
|
226
226
|
_alreadyWarnedFields.add(key);
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACzG,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGlC,wEAAwE;AACxE,yEAAyE;AACzE,EAAE;AACF,sEAAsE;AACtE,4DAA4D;AAC5D,4CAA4C;AAC5C,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,0EAA0E;AAC1E,+CAA+C;AAC/C,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAChD,MAAM,CAAC,MAAM,sBAAsB,GAAG,YAAY,CAAC;AAEnD,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,kBAAkB;IAC9B,OAAO,CAAC,GAAG,CAAC,cAAc;IAC1B,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACnC,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,uEAAuE;AACvE,yEAAyE;AACzE,6EAA6E;AAC7E,IAAI,uBAAuB,GAAG,KAAK,CAAC;AAEpC;;;;;;;;;;;;;;GAcG;AACH,SAAS,oBAAoB;IAC3B,IAAI,uBAAuB;QAAE,OAAO;IACpC,uBAAuB,GAAG,IAAI,CAAC;IAE/B,uDAAuD;IACvD,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO;IAEzE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,sBAAsB,CAAC,CAAC;IAE1D,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO;IAEzD,IAAI,CAAC;QACH,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC9B,OAAO,CAAC,IAAI,CACV,oBAAoB,sBAAsB,QAAQ,eAAe,6CAA6C,CAC/G,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;QACpE,+DAA+D;QAC/D,IAAI,CAAC;YACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,IAAI,CACV,oBAAoB,sBAAsB,QAAQ,eAAe,eAAe,CACjF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CACV,qCAAqC,sBAAsB,QAAQ,eAAe,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,6DAA6D,CAC7L,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,cAAc,GAAoB;IACtC,MAAM,EAAE,EAAE;IACV,OAAO,EAAE,8BAA8B;IACvC,KAAK,EAAE,2BAA2B;IAClC,gEAAgE;IAChE,mEAAmE;IACnE,gEAAgE;IAChE,oEAAoE;IACpE,4DAA4D;IAC5D,aAAa,EAAE,2BAA2B;IAC1C,QAAQ,EAAE,YAAY;IACtB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,GAAG;IAChB,cAAc,EAAE,KAAK;IACrB,sEAAsE;IACtE,wEAAwE;IACxE,OAAO,EAAE,cAAc;IACvB,4EAA4E;IAC5E,+DAA+D;IAC/D,YAAY,EAAE,IAAI;IAClB,6DAA6D;IAC7D,mEAAmE;IACnE,wEAAwE;IACxE,sBAAsB;IACtB,OAAO,EAAE;QACP,KAAK,EAAE,KAAK;KACb;IACD,2EAA2E;IAC3E,wEAAwE;IACxE,2EAA2E;IAC3E,mDAAmD;IACnD,MAAM,EAAE;QACN,OAAO,EAAE,IAAI;QACb,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,IAAI;KACnB;IACD,4EAA4E;IAC5E,sEAAsE;IACtE,4EAA4E;IAC5E,oDAAoD;IACpD,KAAK,EAAE;QACL,OAAO,EAAE,KAAK;QACd,GAAG,EAAE;YACH,sEAAsE;YACtE,oEAAoE;YACpE,sEAAsE;YACtE,gBAAgB;YAChB,OAAO,EAAE,2BAA2B;YACpC,KAAK,EAAE,WAAW;YAClB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,KAAK;SAClB;QACD,GAAG,EAAE;YACH,uEAAuE;YACvE,wCAAwC;YACxC,OAAO,EAAE,8BAA8B;YACvC,KAAK,EAAE,mBAAmB;YAC1B,sEAAsE;YACtE,iEAAiE;YACjE,4BAA4B;YAC5B,gBAAgB,EAAE,sBAAsB;YACxC,WAAW,EAAE,sBAAsB;YACnC,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,GAAG;YACV,SAAS,EAAE,GAAG;YACd,eAAe,EAAE,IAAI;SACtB;QACD,aAAa,EAAE;YACb,sEAAsE;YACtE,wEAAwE;YACxE,mBAAmB;YACnB,YAAY,EAAE,KAAK;YACnB,SAAS,EAAE,IAAI;YACf,cAAc,EAAE,IAAI;YACpB,oBAAoB,EAAE,IAAI;YAC1B,oBAAoB,EAAE,IAAI;YAC1B,qBAAqB,EAAE,GAAG;SAC3B;KACF;CACF,CAAC;AAEF,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,wEAAwE;IACxE,oBAAoB,EAAE,CAAC;IACvB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,MAAM,EAAE,CAAC;QAChD,cAAc,CAAC,MAAM,CAAC,CAAC;QACvB,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,mCAAmC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QAC5F,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,2EAA2E;AAC3E,0EAA0E;AAC1E,8CAA8C;AAC9C,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;AAE/C,SAAS,cAAc,CAAC,MAAuB;IAC7C,mBAAmB;IACnB,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzD,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,IAAI,CAAC,6BAA6B,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC5D,MAAM,CAAC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACpF,OAAO,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC;IACtC,CAAC;IAED,0BAA0B;IAC1B,MAAM,UAAU,GAAwC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAChF,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,oCAAoC,MAAM,CAAC,cAAc,eAAe,CAAC,CAAC;QACvF,MAAM,CAAC,cAAc,GAAG,KAAK,CAAC;IAChC,CAAC;IAED,4BAA4B;IAC5B,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/debug.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug instrumentation.
|
|
3
|
+
*
|
|
4
|
+
* Writes NDJSON event records to ~/.compact-agent/debug/<sessionId>.jsonl
|
|
5
|
+
* for offline analysis. Designed so that with `level === 'off'` (the
|
|
6
|
+
* default), every emit() call is a single boolean check + early return —
|
|
7
|
+
* zero file I/O and negligible CPU on the hot path.
|
|
8
|
+
*
|
|
9
|
+
* Levels (each includes everything below it):
|
|
10
|
+
*
|
|
11
|
+
* off — no logging (default; for end users)
|
|
12
|
+
* info — high-signal milestones: session start/end, API request/
|
|
13
|
+
* response summary, tool call summary, hook block, stream
|
|
14
|
+
* loop detection, mode/perm/model change
|
|
15
|
+
* debug — info + per-tool argument previews, per-chunk stream stats,
|
|
16
|
+
* per-keypress trace at REPL, slash command dispatch
|
|
17
|
+
* trace — debug + raw API payloads (truncated), full tool I/O,
|
|
18
|
+
* internal state transitions
|
|
19
|
+
*
|
|
20
|
+
* Toggling:
|
|
21
|
+
*
|
|
22
|
+
* - CLI flag: compact-agent --debug [level]
|
|
23
|
+
* - Env var: COMPACT_AGENT_DEBUG=trace
|
|
24
|
+
* - Slash cmd: /debug on [level] /debug off /debug tail [n]
|
|
25
|
+
*
|
|
26
|
+
* The event log is append-only. Each session gets its own file so
|
|
27
|
+
* concurrent compact-agent instances don't fight over a single sink.
|
|
28
|
+
* Files are subject to the same 24h GC window as the gateguard state.
|
|
29
|
+
*
|
|
30
|
+
* Design notes:
|
|
31
|
+
*
|
|
32
|
+
* - We deliberately don't use console.error or any third-party logger.
|
|
33
|
+
* console.error pollutes the user's REPL view; a third-party logger
|
|
34
|
+
* adds startup time + a transitive dep. Direct fs.appendFileSync to
|
|
35
|
+
* an NDJSON file is the lowest-overhead path that's also trivially
|
|
36
|
+
* consumable by jq / Python / another agent.
|
|
37
|
+
*
|
|
38
|
+
* - We DO accept the cost of synchronous appendFileSync — debug
|
|
39
|
+
* instrumentation is rarely on the hot path of perf-sensitive code,
|
|
40
|
+
* and the cost of one syscall per event (only when level >= info)
|
|
41
|
+
* is dwarfed by the cost of the API call the event describes.
|
|
42
|
+
*
|
|
43
|
+
* - Stack traces are NOT captured automatically. Each emit() takes an
|
|
44
|
+
* explicit `data` object — callers include whatever they need.
|
|
45
|
+
* Auto-traces would balloon the log file for limited extra value.
|
|
46
|
+
*/
|
|
47
|
+
export type DebugLevel = 'off' | 'info' | 'debug' | 'trace';
|
|
48
|
+
/**
|
|
49
|
+
* Initialize debug at session start. Resolves level from (in priority order):
|
|
50
|
+
* 1. explicit `level` arg (passed in from --debug flag parsing)
|
|
51
|
+
* 2. $COMPACT_AGENT_DEBUG env var
|
|
52
|
+
* 3. existing state.level (typically 'off')
|
|
53
|
+
*
|
|
54
|
+
* Sets the log file path under ~/.compact-agent/debug/<sessionId>.jsonl
|
|
55
|
+
* but doesn't touch the filesystem until the first emit (lazy create).
|
|
56
|
+
*/
|
|
57
|
+
export declare function initDebug(sessionId: string, explicitLevel?: DebugLevel | string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Emit a debug event. The fastest path is the early-return when the
|
|
60
|
+
* configured level is below the event's level — a single integer compare.
|
|
61
|
+
*
|
|
62
|
+
* `data` is shallow-cloned to a JSON-safe form. Functions, BigInts, and
|
|
63
|
+
* circular refs are stripped via the replacer to keep emit cheap and
|
|
64
|
+
* crash-free regardless of what callers throw in.
|
|
65
|
+
*/
|
|
66
|
+
export declare function emit(eventLevel: Exclude<DebugLevel, 'off'>, eventName: string, data?: Record<string, unknown>): void;
|
|
67
|
+
/**
|
|
68
|
+
* Public read-only state snapshot for /debug status output.
|
|
69
|
+
*/
|
|
70
|
+
export declare function getDebugStatus(): {
|
|
71
|
+
level: DebugLevel;
|
|
72
|
+
logPath: string | null;
|
|
73
|
+
eventCount: number;
|
|
74
|
+
uptimeMs: number;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Change the active debug level at runtime. Called from /debug on/off.
|
|
78
|
+
* If transitioning OFF → non-off, we ensure the log dir exists; if
|
|
79
|
+
* transitioning to OFF we leave the file alone (it's append-only and
|
|
80
|
+
* read by external tools).
|
|
81
|
+
*/
|
|
82
|
+
export declare function setDebugLevel(level: DebugLevel): void;
|
|
83
|
+
/**
|
|
84
|
+
* Read the last N events from the current session's log. Used by
|
|
85
|
+
* /debug tail. Returns lines as JSON strings (one per event); the
|
|
86
|
+
* caller can pretty-print or pass through to jq.
|
|
87
|
+
*/
|
|
88
|
+
export declare function tailDebug(n: number): string[];
|
|
89
|
+
/**
|
|
90
|
+
* True if any non-off level is active. Use this to gate expensive
|
|
91
|
+
* data preparation that you don't want to run when debug is off:
|
|
92
|
+
*
|
|
93
|
+
* if (isDebugActive()) {
|
|
94
|
+
* emit('debug', 'event-name', { detail: computeExpensiveDetail() });
|
|
95
|
+
* }
|
|
96
|
+
*/
|
|
97
|
+
export declare function isDebugActive(): boolean;
|
package/dist/debug.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug instrumentation.
|
|
3
|
+
*
|
|
4
|
+
* Writes NDJSON event records to ~/.compact-agent/debug/<sessionId>.jsonl
|
|
5
|
+
* for offline analysis. Designed so that with `level === 'off'` (the
|
|
6
|
+
* default), every emit() call is a single boolean check + early return —
|
|
7
|
+
* zero file I/O and negligible CPU on the hot path.
|
|
8
|
+
*
|
|
9
|
+
* Levels (each includes everything below it):
|
|
10
|
+
*
|
|
11
|
+
* off — no logging (default; for end users)
|
|
12
|
+
* info — high-signal milestones: session start/end, API request/
|
|
13
|
+
* response summary, tool call summary, hook block, stream
|
|
14
|
+
* loop detection, mode/perm/model change
|
|
15
|
+
* debug — info + per-tool argument previews, per-chunk stream stats,
|
|
16
|
+
* per-keypress trace at REPL, slash command dispatch
|
|
17
|
+
* trace — debug + raw API payloads (truncated), full tool I/O,
|
|
18
|
+
* internal state transitions
|
|
19
|
+
*
|
|
20
|
+
* Toggling:
|
|
21
|
+
*
|
|
22
|
+
* - CLI flag: compact-agent --debug [level]
|
|
23
|
+
* - Env var: COMPACT_AGENT_DEBUG=trace
|
|
24
|
+
* - Slash cmd: /debug on [level] /debug off /debug tail [n]
|
|
25
|
+
*
|
|
26
|
+
* The event log is append-only. Each session gets its own file so
|
|
27
|
+
* concurrent compact-agent instances don't fight over a single sink.
|
|
28
|
+
* Files are subject to the same 24h GC window as the gateguard state.
|
|
29
|
+
*
|
|
30
|
+
* Design notes:
|
|
31
|
+
*
|
|
32
|
+
* - We deliberately don't use console.error or any third-party logger.
|
|
33
|
+
* console.error pollutes the user's REPL view; a third-party logger
|
|
34
|
+
* adds startup time + a transitive dep. Direct fs.appendFileSync to
|
|
35
|
+
* an NDJSON file is the lowest-overhead path that's also trivially
|
|
36
|
+
* consumable by jq / Python / another agent.
|
|
37
|
+
*
|
|
38
|
+
* - We DO accept the cost of synchronous appendFileSync — debug
|
|
39
|
+
* instrumentation is rarely on the hot path of perf-sensitive code,
|
|
40
|
+
* and the cost of one syscall per event (only when level >= info)
|
|
41
|
+
* is dwarfed by the cost of the API call the event describes.
|
|
42
|
+
*
|
|
43
|
+
* - Stack traces are NOT captured automatically. Each emit() takes an
|
|
44
|
+
* explicit `data` object — callers include whatever they need.
|
|
45
|
+
* Auto-traces would balloon the log file for limited extra value.
|
|
46
|
+
*/
|
|
47
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync } from 'node:fs';
|
|
48
|
+
import { join } from 'node:path';
|
|
49
|
+
import { getHomeStateDir } from './config.js';
|
|
50
|
+
const LEVEL_ORDER = {
|
|
51
|
+
off: 0,
|
|
52
|
+
info: 1,
|
|
53
|
+
debug: 2,
|
|
54
|
+
trace: 3,
|
|
55
|
+
};
|
|
56
|
+
const state = {
|
|
57
|
+
level: 'off',
|
|
58
|
+
sessionId: null,
|
|
59
|
+
logPath: null,
|
|
60
|
+
eventCount: 0,
|
|
61
|
+
startedAt: Date.now(),
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Initialize debug at session start. Resolves level from (in priority order):
|
|
65
|
+
* 1. explicit `level` arg (passed in from --debug flag parsing)
|
|
66
|
+
* 2. $COMPACT_AGENT_DEBUG env var
|
|
67
|
+
* 3. existing state.level (typically 'off')
|
|
68
|
+
*
|
|
69
|
+
* Sets the log file path under ~/.compact-agent/debug/<sessionId>.jsonl
|
|
70
|
+
* but doesn't touch the filesystem until the first emit (lazy create).
|
|
71
|
+
*/
|
|
72
|
+
export function initDebug(sessionId, explicitLevel) {
|
|
73
|
+
state.sessionId = sessionId;
|
|
74
|
+
const envLevel = process.env.COMPACT_AGENT_DEBUG;
|
|
75
|
+
const requested = (explicitLevel || envLevel || state.level || 'off').toLowerCase();
|
|
76
|
+
state.level = isValidLevel(requested) ? requested : 'off';
|
|
77
|
+
if (state.level !== 'off') {
|
|
78
|
+
const dir = join(getHomeStateDir(), 'debug');
|
|
79
|
+
state.logPath = join(dir, `${sessionId}.jsonl`);
|
|
80
|
+
try {
|
|
81
|
+
mkdirSync(dir, { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
catch { /* if we can't create the dir, emit() will fail-safe */ }
|
|
84
|
+
// GC: drop any debug files older than 24h.
|
|
85
|
+
try {
|
|
86
|
+
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
|
|
87
|
+
for (const name of readdirSync(dir)) {
|
|
88
|
+
const p = join(dir, name);
|
|
89
|
+
try {
|
|
90
|
+
const s = statSync(p);
|
|
91
|
+
if (s.mtimeMs < cutoff)
|
|
92
|
+
unlinkSync(p);
|
|
93
|
+
}
|
|
94
|
+
catch { /* noop */ }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch { /* noop */ }
|
|
98
|
+
emit('info', 'debug.init', { level: state.level, sessionId });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function isValidLevel(s) {
|
|
102
|
+
return s === 'off' || s === 'info' || s === 'debug' || s === 'trace';
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Emit a debug event. The fastest path is the early-return when the
|
|
106
|
+
* configured level is below the event's level — a single integer compare.
|
|
107
|
+
*
|
|
108
|
+
* `data` is shallow-cloned to a JSON-safe form. Functions, BigInts, and
|
|
109
|
+
* circular refs are stripped via the replacer to keep emit cheap and
|
|
110
|
+
* crash-free regardless of what callers throw in.
|
|
111
|
+
*/
|
|
112
|
+
export function emit(eventLevel, eventName, data) {
|
|
113
|
+
if (LEVEL_ORDER[state.level] < LEVEL_ORDER[eventLevel])
|
|
114
|
+
return;
|
|
115
|
+
if (!state.logPath)
|
|
116
|
+
return;
|
|
117
|
+
const record = {
|
|
118
|
+
t: new Date().toISOString(),
|
|
119
|
+
rel: Date.now() - state.startedAt,
|
|
120
|
+
lvl: eventLevel,
|
|
121
|
+
ev: eventName,
|
|
122
|
+
...(data ? { data: safeClone(data) } : {}),
|
|
123
|
+
};
|
|
124
|
+
try {
|
|
125
|
+
appendFileSync(state.logPath, JSON.stringify(record) + '\n', 'utf-8');
|
|
126
|
+
state.eventCount++;
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
// If the log file write fails, we don't want to spam errors into
|
|
130
|
+
// the REPL — silently drop the event. The user can re-enable via
|
|
131
|
+
// /debug if the underlying issue is fixed.
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* JSON.stringify replacer that prevents crashes on circular refs,
|
|
136
|
+
* BigInt, functions, and overly-large strings. Truncates strings to
|
|
137
|
+
* 8KB so a single huge prompt or tool output doesn't bloat the log.
|
|
138
|
+
*/
|
|
139
|
+
function safeClone(input) {
|
|
140
|
+
const seen = new WeakSet();
|
|
141
|
+
return JSON.parse(JSON.stringify(input, (_key, value) => {
|
|
142
|
+
if (typeof value === 'bigint')
|
|
143
|
+
return value.toString() + 'n';
|
|
144
|
+
if (typeof value === 'function')
|
|
145
|
+
return '[function]';
|
|
146
|
+
if (typeof value === 'string' && value.length > 8192) {
|
|
147
|
+
return value.slice(0, 8192) + `…[truncated ${value.length - 8192}b]`;
|
|
148
|
+
}
|
|
149
|
+
if (value && typeof value === 'object') {
|
|
150
|
+
if (seen.has(value))
|
|
151
|
+
return '[circular]';
|
|
152
|
+
seen.add(value);
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Public read-only state snapshot for /debug status output.
|
|
159
|
+
*/
|
|
160
|
+
export function getDebugStatus() {
|
|
161
|
+
return {
|
|
162
|
+
level: state.level,
|
|
163
|
+
logPath: state.logPath,
|
|
164
|
+
eventCount: state.eventCount,
|
|
165
|
+
uptimeMs: Date.now() - state.startedAt,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Change the active debug level at runtime. Called from /debug on/off.
|
|
170
|
+
* If transitioning OFF → non-off, we ensure the log dir exists; if
|
|
171
|
+
* transitioning to OFF we leave the file alone (it's append-only and
|
|
172
|
+
* read by external tools).
|
|
173
|
+
*/
|
|
174
|
+
export function setDebugLevel(level) {
|
|
175
|
+
const old = state.level;
|
|
176
|
+
state.level = level;
|
|
177
|
+
if (level !== 'off' && !state.logPath && state.sessionId) {
|
|
178
|
+
const dir = join(getHomeStateDir(), 'debug');
|
|
179
|
+
state.logPath = join(dir, `${state.sessionId}.jsonl`);
|
|
180
|
+
try {
|
|
181
|
+
mkdirSync(dir, { recursive: true });
|
|
182
|
+
}
|
|
183
|
+
catch { /* noop */ }
|
|
184
|
+
}
|
|
185
|
+
if (level !== 'off' && old !== level) {
|
|
186
|
+
emit('info', 'debug.level-change', { from: old, to: level });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Read the last N events from the current session's log. Used by
|
|
191
|
+
* /debug tail. Returns lines as JSON strings (one per event); the
|
|
192
|
+
* caller can pretty-print or pass through to jq.
|
|
193
|
+
*/
|
|
194
|
+
export function tailDebug(n) {
|
|
195
|
+
if (!state.logPath || !existsSync(state.logPath))
|
|
196
|
+
return [];
|
|
197
|
+
try {
|
|
198
|
+
const raw = readFileSync(state.logPath, 'utf-8');
|
|
199
|
+
const lines = raw.split('\n').filter((l) => l.trim().length > 0);
|
|
200
|
+
return lines.slice(-Math.max(1, n));
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* True if any non-off level is active. Use this to gate expensive
|
|
208
|
+
* data preparation that you don't want to run when debug is off:
|
|
209
|
+
*
|
|
210
|
+
* if (isDebugActive()) {
|
|
211
|
+
* emit('debug', 'event-name', { detail: computeExpensiveDetail() });
|
|
212
|
+
* }
|
|
213
|
+
*/
|
|
214
|
+
export function isDebugActive() {
|
|
215
|
+
return state.level !== 'off';
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=debug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import { readFileSync as fsReadFileSync, writeFileSync as fsWriteFileSync, unlin
|
|
|
5
5
|
import { tmpdir } from 'node:os';
|
|
6
6
|
import { join as pathJoin } from 'node:path';
|
|
7
7
|
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { initDebug, emit as dbgEmit, setDebugLevel, getDebugStatus, tailDebug } from './debug.js';
|
|
8
9
|
import chalk from 'chalk';
|
|
9
10
|
import { loadConfig, saveConfig, configExists, getConfigDir } from './config.js';
|
|
10
11
|
import { resetClient } from './api.js';
|
|
@@ -146,7 +147,20 @@ async function setupWizard(rl) {
|
|
|
146
147
|
console.log(chalk.dim(' 2. auto — auto-approve reads, ask for destructive'));
|
|
147
148
|
console.log(chalk.dim(' 3. yolo — approve everything (fastest)\n'));
|
|
148
149
|
const permChoice = await rl.question(chalk.yellow(' Permission mode [1]: '));
|
|
149
|
-
|
|
150
|
+
// Accept either the number (1/2/3) OR the name (ask/auto/yolo) — users
|
|
151
|
+
// very naturally type the word they want instead of looking at the
|
|
152
|
+
// index. A previous version only parsed parseInt and silently
|
|
153
|
+
// defaulted to 'ask' for non-numeric input, which made yolo
|
|
154
|
+
// unreachable from the wizard for anyone who typed the obvious thing.
|
|
155
|
+
const raw = (permChoice || '1').trim().toLowerCase();
|
|
156
|
+
let permMode;
|
|
157
|
+
if (raw === 'ask' || raw === 'auto' || raw === 'yolo') {
|
|
158
|
+
permMode = raw;
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
const byNumber = ['ask', 'auto', 'yolo'][parseInt(raw, 10) - 1];
|
|
162
|
+
permMode = byNumber || 'ask';
|
|
163
|
+
}
|
|
150
164
|
// ── MemPalace memory setup ──────────────────────────────
|
|
151
165
|
// Featured capability, opt-out at setup time. Explain briefly so the
|
|
152
166
|
// user can make an informed choice — most users want this on.
|
|
@@ -531,6 +545,72 @@ export function handleSlashCommand(input, config, messages, session, mode) {
|
|
|
531
545
|
console.log(chalk.dim(` Sending ${result.length} chars from editor…`));
|
|
532
546
|
return { handled: true, injectPrompt: result };
|
|
533
547
|
}
|
|
548
|
+
// ── Debug — toggle instrumentation + tail event log ──
|
|
549
|
+
// Surface for the NDJSON debug stream written to
|
|
550
|
+
// ~/.compact-agent/debug/<sessionId>.jsonl. Used by reviewers
|
|
551
|
+
// driving the agent + by users diagnosing their own issues.
|
|
552
|
+
//
|
|
553
|
+
// /debug show current level + log path + event count
|
|
554
|
+
// /debug on [level] turn instrumentation on (default level: info)
|
|
555
|
+
// /debug off turn instrumentation off (existing log file is kept)
|
|
556
|
+
// /debug tail [N] print the last N events (default 20) inline
|
|
557
|
+
case '/debug': {
|
|
558
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
559
|
+
const sub = (parts[0] || '').toLowerCase();
|
|
560
|
+
if (!sub) {
|
|
561
|
+
const s = getDebugStatus();
|
|
562
|
+
console.log(chalk.dim(` Debug level: ${s.level}`));
|
|
563
|
+
console.log(chalk.dim(` Log file: ${s.logPath || '(no log — level is off)'}`));
|
|
564
|
+
console.log(chalk.dim(` Events: ${s.eventCount} this session`));
|
|
565
|
+
console.log(chalk.dim(` Uptime: ${(s.uptimeMs / 1000).toFixed(1)}s`));
|
|
566
|
+
console.log('');
|
|
567
|
+
console.log(chalk.dim(` /debug on [info|debug|trace]`));
|
|
568
|
+
console.log(chalk.dim(` /debug off`));
|
|
569
|
+
console.log(chalk.dim(` /debug tail [N]`));
|
|
570
|
+
return { handled: true };
|
|
571
|
+
}
|
|
572
|
+
if (sub === 'off') {
|
|
573
|
+
setDebugLevel('off');
|
|
574
|
+
console.log(chalk.green(' Debug: off'));
|
|
575
|
+
return { handled: true };
|
|
576
|
+
}
|
|
577
|
+
if (sub === 'on') {
|
|
578
|
+
const lvl = (parts[1] || 'info').toLowerCase();
|
|
579
|
+
if (lvl !== 'info' && lvl !== 'debug' && lvl !== 'trace') {
|
|
580
|
+
console.log(chalk.yellow(` Unknown level "${lvl}". Use info, debug, or trace.`));
|
|
581
|
+
return { handled: true };
|
|
582
|
+
}
|
|
583
|
+
setDebugLevel(lvl);
|
|
584
|
+
const s = getDebugStatus();
|
|
585
|
+
console.log(chalk.green(` Debug: ${lvl} — writing to ${s.logPath}`));
|
|
586
|
+
return { handled: true };
|
|
587
|
+
}
|
|
588
|
+
if (sub === 'tail') {
|
|
589
|
+
const n = parseInt(parts[1] || '20', 10);
|
|
590
|
+
const lines = tailDebug(Number.isFinite(n) && n > 0 ? n : 20);
|
|
591
|
+
if (lines.length === 0) {
|
|
592
|
+
console.log(chalk.dim(' (no events — turn on with /debug on)'));
|
|
593
|
+
return { handled: true };
|
|
594
|
+
}
|
|
595
|
+
console.log(chalk.dim(` Last ${lines.length} debug events:`));
|
|
596
|
+
for (const ln of lines) {
|
|
597
|
+
try {
|
|
598
|
+
const rec = JSON.parse(ln);
|
|
599
|
+
const ts = String(rec.rel || 0).padStart(6) + 'ms';
|
|
600
|
+
const lvl = (rec.lvl || '').toUpperCase().padEnd(5);
|
|
601
|
+
const ev = rec.ev || '';
|
|
602
|
+
const d = rec.data ? ' ' + JSON.stringify(rec.data).slice(0, 120) : '';
|
|
603
|
+
console.log(chalk.dim(` ${ts} ${lvl} ${ev}${d}`));
|
|
604
|
+
}
|
|
605
|
+
catch {
|
|
606
|
+
console.log(chalk.dim(` ${ln.slice(0, 200)}`));
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return { handled: true };
|
|
610
|
+
}
|
|
611
|
+
console.log(chalk.yellow(` Unknown /debug subcommand "${sub}". Try: /debug, /debug on, /debug off, /debug tail`));
|
|
612
|
+
return { handled: true };
|
|
613
|
+
}
|
|
534
614
|
// ── History ───────────────────────────────────────
|
|
535
615
|
case '/history': {
|
|
536
616
|
const stats = getCompactionStats(messages);
|
|
@@ -2190,6 +2270,19 @@ async function main() {
|
|
|
2190
2270
|
// Create session
|
|
2191
2271
|
const mode = { current: 'dev' };
|
|
2192
2272
|
const session = createSession(process.cwd(), config.model, config.provider, mode.current);
|
|
2273
|
+
// ── Debug instrumentation ─────────────────────────────────
|
|
2274
|
+
// Initialize early so subsequent emit() calls land in the right file.
|
|
2275
|
+
// Reads $COMPACT_AGENT_DEBUG which bin/crowcoder.js may have set from
|
|
2276
|
+
// the --debug CLI flag. Level 'off' is a no-op; non-off opens an
|
|
2277
|
+
// NDJSON log at ~/.compact-agent/debug/<sessionId>.jsonl.
|
|
2278
|
+
initDebug(session.id);
|
|
2279
|
+
dbgEmit('info', 'session.start', {
|
|
2280
|
+
cwd: process.cwd(),
|
|
2281
|
+
model: config.model,
|
|
2282
|
+
provider: config.provider,
|
|
2283
|
+
mode: mode.current,
|
|
2284
|
+
permissionMode: config.permissionMode,
|
|
2285
|
+
});
|
|
2193
2286
|
const messages = [];
|
|
2194
2287
|
// Session start hook + memory persistence
|
|
2195
2288
|
await runHooks({ event: 'SessionStart', sessionId: session.id, cwd: process.cwd(), permissionMode: config.permissionMode });
|
|
@@ -2855,6 +2948,8 @@ async function main() {
|
|
|
2855
2948
|
}
|
|
2856
2949
|
// Slash commands
|
|
2857
2950
|
if (trimmed.startsWith('/')) {
|
|
2951
|
+
// Truncate arg preview so debug logs don't blow up on /editor seeds etc.
|
|
2952
|
+
dbgEmit('debug', 'slash.dispatch', { input: trimmed.slice(0, 200) });
|
|
2858
2953
|
const result = handleSlashCommand(trimmed, config, messages, session, mode);
|
|
2859
2954
|
if (result.shouldExit)
|
|
2860
2955
|
break;
|