azclaude-copilot 0.5.2 → 0.5.4
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 +2 -2
- package/package.json +1 -1
- package/templates/hooks/user-prompt.js +42 -0
- package/templates/scripts/statusline.js +37 -0
package/README.md
CHANGED
|
@@ -758,11 +758,11 @@ An agent is a sub-process. Use one when work must happen **in parallel** or **in
|
|
|
758
758
|
|
|
759
759
|
## Verified
|
|
760
760
|
|
|
761
|
-
|
|
761
|
+
1775 tests. Every template, command, capability, agent, hook, and CLI feature verified.
|
|
762
762
|
|
|
763
763
|
```bash
|
|
764
764
|
bash tests/test-features.sh
|
|
765
|
-
# Results:
|
|
765
|
+
# Results: 1775 passed, 0 failed, 1775 total
|
|
766
766
|
```
|
|
767
767
|
|
|
768
768
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "azclaude-copilot",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "AI coding environment — 39 commands, 10 skills, 15 agents, memory, reflexes, evolution. Install: npx azclaude-copilot@latest, then open Claude Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"azclaude": "bin/cli.js",
|
|
@@ -195,6 +195,48 @@ try {
|
|
|
195
195
|
}
|
|
196
196
|
} catch (_) {}
|
|
197
197
|
|
|
198
|
+
// ── Compaction Guard — auto-snapshot before context is lost ─────────────────
|
|
199
|
+
// Reads context % signal from statusline (written to temp file after each turn).
|
|
200
|
+
// At >= 70%: warns Claude to save state. At >= 85%: auto-saves checkpoint.
|
|
201
|
+
try {
|
|
202
|
+
const ctxSignalPath = path.join(os.tmpdir(), `.azclaude-ctx-${process.ppid || process.pid}`);
|
|
203
|
+
if (fs.existsSync(ctxSignalPath)) {
|
|
204
|
+
const ctxSignal = JSON.parse(fs.readFileSync(ctxSignalPath, 'utf8'));
|
|
205
|
+
const pct = ctxSignal.ctxPct || 0;
|
|
206
|
+
|
|
207
|
+
if (pct >= 85) {
|
|
208
|
+
// AUTO-SAVE: context is critically high — save checkpoint before compaction wipes it
|
|
209
|
+
const checkpointDir = path.join(cfg, 'memory', 'checkpoints');
|
|
210
|
+
try { fs.mkdirSync(checkpointDir, { recursive: true }); } catch (_) {}
|
|
211
|
+
const ts = new Date().toISOString().replace(/[:.]/g, '-').slice(0, 16);
|
|
212
|
+
const cpPath = path.join(checkpointDir, `${ts}-auto-compaction.md`);
|
|
213
|
+
|
|
214
|
+
// Only auto-save once per threshold crossing (check if already saved)
|
|
215
|
+
const autoSaveMarker = path.join(os.tmpdir(), `.azclaude-autosave-${process.ppid || process.pid}`);
|
|
216
|
+
if (!fs.existsSync(autoSaveMarker)) {
|
|
217
|
+
// Copy goals.md as checkpoint
|
|
218
|
+
if (fs.existsSync(goalsPath)) {
|
|
219
|
+
const goalsContent = fs.readFileSync(goalsPath, 'utf8');
|
|
220
|
+
const header = `---\ndate: ${new Date().toISOString()}\nlabel: auto-compaction-guard-${pct}pct\nfiles_in_progress: []\n---\n\n`;
|
|
221
|
+
fs.writeFileSync(cpPath, header + '## Auto-saved before compaction\n\n' + goalsContent);
|
|
222
|
+
fs.writeFileSync(autoSaveMarker, '');
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
console.log('');
|
|
226
|
+
console.log(`--- COMPACTION GUARD (${pct}%) ---`);
|
|
227
|
+
console.log(`Context at ${pct}% — AUTO-SAVED checkpoint to ${path.basename(cpPath)}`);
|
|
228
|
+
console.log('Run /snapshot NOW to save your reasoning and decisions (goals.md alone is not enough).');
|
|
229
|
+
console.log('--- END GUARD ---');
|
|
230
|
+
}
|
|
231
|
+
} else if (pct >= 70) {
|
|
232
|
+
console.log('');
|
|
233
|
+
console.log(`--- COMPACTION WARNING (${pct}%) ---`);
|
|
234
|
+
console.log(`Context at ${pct}% — compaction approaching. Run /snapshot to save session state.`);
|
|
235
|
+
console.log('--- END WARNING ---');
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
} catch (_) {}
|
|
239
|
+
|
|
198
240
|
// ── First message only — inject full context ────────────────────────────────
|
|
199
241
|
if (!isFirstMessage) process.exit(0);
|
|
200
242
|
|
|
@@ -33,6 +33,30 @@ process.stdin.on('end', () => {
|
|
|
33
33
|
const cachWrite = data.context_window?.current_usage?.cache_creation_input_tokens || 0;
|
|
34
34
|
const cachRead = data.context_window?.current_usage?.cache_read_input_tokens || 0;
|
|
35
35
|
|
|
36
|
+
// ── Agent + Skill usage (from observations.jsonl — tracked by post-tool-use hook) ──
|
|
37
|
+
const fs = require('fs');
|
|
38
|
+
const path = require('path');
|
|
39
|
+
const projectDir = data.workspace?.current_dir || data.workspace?.project_dir || process.cwd();
|
|
40
|
+
const sessionPid = process.ppid || process.pid;
|
|
41
|
+
let agentCount = 0, skillCount = 0;
|
|
42
|
+
try {
|
|
43
|
+
const obsPath = path.join(projectDir, '.claude', 'memory', 'reflexes', 'observations.jsonl');
|
|
44
|
+
if (fs.existsSync(obsPath)) {
|
|
45
|
+
const lines = fs.readFileSync(obsPath, 'utf8').split('\n').filter(Boolean);
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
try {
|
|
48
|
+
const obs = JSON.parse(line);
|
|
49
|
+
// Count only this session's observations
|
|
50
|
+
if (String(obs.session) !== String(sessionPid)) continue;
|
|
51
|
+
if (obs.tool === 'Agent' || obs.tool === 'Task') agentCount++;
|
|
52
|
+
if (obs.tool === 'Skill') skillCount++;
|
|
53
|
+
// Also count Read calls on SKILL.md files as skill usage
|
|
54
|
+
if (obs.tool === 'Read' && obs.file && /skills\/.*SKILL\.md/.test(obs.file)) skillCount++;
|
|
55
|
+
} catch (_) {}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch (_) {}
|
|
59
|
+
|
|
36
60
|
// ── Format helpers ──
|
|
37
61
|
const durSec = Math.floor(durMs / 1000);
|
|
38
62
|
const mins = Math.floor(durSec / 60);
|
|
@@ -93,6 +117,13 @@ process.stdin.on('end', () => {
|
|
|
93
117
|
const empty = 10 - filled;
|
|
94
118
|
const bar = '\u2593'.repeat(filled) + '\u2591'.repeat(empty);
|
|
95
119
|
|
|
120
|
+
// ── Compaction signal — write context % to temp file for hook to read ──
|
|
121
|
+
// This enables the UserPromptSubmit hook to auto-snapshot before compaction.
|
|
122
|
+
try {
|
|
123
|
+
const signalPath = path.join(require('os').tmpdir(), `.azclaude-ctx-${process.ppid || process.pid}`);
|
|
124
|
+
fs.writeFileSync(signalPath, JSON.stringify({ ctxPct, turnsLeft: compactHint ? parseInt(compactHint.replace(/[^0-9]/g,'')) : 999 }));
|
|
125
|
+
} catch (_) {}
|
|
126
|
+
|
|
96
127
|
// ── Color thresholds ──
|
|
97
128
|
let ctxColor, ctxWarn = '';
|
|
98
129
|
if (ctxPct >= 80) { ctxColor = RED; ctxWarn = ' COMPACT SOON'; }
|
|
@@ -134,6 +165,12 @@ process.stdin.on('end', () => {
|
|
|
134
165
|
line2 += `${DIM}In:${fmtTok(inputTok)} Out:${fmtTok(outputTok)}${RESET} `;
|
|
135
166
|
}
|
|
136
167
|
|
|
168
|
+
// Agent + Skill counts (only show if > 0 — means AZCLAUDE is being used)
|
|
169
|
+
if (agentCount > 0 || skillCount > 0) {
|
|
170
|
+
if (agentCount > 0) line2 += `${CYAN}A:${agentCount}${RESET} `;
|
|
171
|
+
if (skillCount > 0) line2 += `${CYAN}S:${skillCount}${RESET} `;
|
|
172
|
+
}
|
|
173
|
+
|
|
137
174
|
// Duration
|
|
138
175
|
line2 += `${DIM}${mins}m${secs}s${RESET}`;
|
|
139
176
|
|