0xkobold 0.4.3 → 0.5.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/README.md +226 -383
- package/dist/package.json +13 -4
- package/dist/src/agent/DraconicCapabilityRouter.js +556 -0
- package/dist/src/agent/DraconicCapabilityRouter.js.map +1 -0
- package/dist/src/agent/DraconicErrorClassifier.js +606 -0
- package/dist/src/agent/DraconicErrorClassifier.js.map +1 -0
- package/dist/src/agent/DraconicRunRegistry.js +460 -0
- package/dist/src/agent/DraconicRunRegistry.js.map +1 -0
- package/dist/src/agent/DraconicTokenPredictor.js +500 -0
- package/dist/src/agent/DraconicTokenPredictor.js.map +1 -0
- package/dist/src/agent/embedded-runner.js +3 -2
- package/dist/src/agent/embedded-runner.js.map +1 -1
- package/dist/src/cli/commands/doctor.js +199 -0
- package/dist/src/cli/commands/doctor.js.map +1 -0
- package/dist/src/cli/commands/migrate-from-openclaw.js +39 -0
- package/dist/src/cli/commands/migrate-from-openclaw.js.map +1 -0
- package/dist/src/cli/commands/migrate.js +6 -4
- package/dist/src/cli/commands/migrate.js.map +1 -1
- package/dist/src/cli/program.js +3 -1
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/config/unified-config.js +195 -0
- package/dist/src/config/unified-config.js.map +1 -0
- package/dist/src/cron/notifications.js +1 -1
- package/dist/src/cron/notifications.js.map +1 -1
- package/dist/src/cron/runner.js +9 -3
- package/dist/src/cron/runner.js.map +1 -1
- package/dist/src/event-bus/index.js +3 -1
- package/dist/src/event-bus/index.js.map +1 -1
- package/dist/src/extensions/community/draconic-messenger-wrapper.js +35 -0
- package/dist/src/extensions/community/draconic-messenger-wrapper.js.map +1 -0
- package/dist/src/extensions/community/draconic-subagents-wrapper.js +115 -0
- package/dist/src/extensions/community/draconic-subagents-wrapper.js.map +1 -0
- package/dist/src/extensions/core/compaction-safeguard-v2.js +95 -0
- package/dist/src/extensions/core/compaction-safeguard-v2.js.map +1 -0
- package/dist/src/extensions/core/compaction-safeguard.js +206 -137
- package/dist/src/extensions/core/compaction-safeguard.js.map +1 -1
- package/dist/src/extensions/core/config-extension.js +122 -0
- package/dist/src/extensions/core/config-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-hoard-extension.js +194 -0
- package/dist/src/extensions/core/draconic-hoard-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-lair-extension.js +146 -0
- package/dist/src/extensions/core/draconic-lair-extension.js.map +1 -0
- package/dist/src/extensions/core/draconic-safety-extension.js +402 -0
- package/dist/src/extensions/core/draconic-safety-extension.js.map +1 -0
- package/dist/src/extensions/core/ext-manager.js +40 -0
- package/dist/src/extensions/core/ext-manager.js.map +1 -0
- package/dist/src/extensions/core/gateway-extension.js +413 -624
- package/dist/src/extensions/core/gateway-extension.js.map +1 -1
- package/dist/src/extensions/core/generative-agents-extension.js +704 -0
- package/dist/src/extensions/core/generative-agents-extension.js.map +1 -0
- package/dist/src/extensions/core/memory-bootstrap-extension.js +279 -0
- package/dist/src/extensions/core/memory-bootstrap-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-extension.js +442 -0
- package/dist/src/extensions/core/ollama-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-router-extension.js +34 -93
- package/dist/src/extensions/core/ollama-router-extension.js.map +1 -1
- package/dist/src/extensions/core/perennial-memory-extension.js +5 -2
- package/dist/src/extensions/core/perennial-memory-extension.js.map +1 -1
- package/dist/src/extensions/core/persona-loader-extension.js +41 -15
- package/dist/src/extensions/core/persona-loader-extension.js.map +1 -1
- package/dist/src/extensions/core/pi-notify-extension.js +6 -0
- package/dist/src/extensions/core/pi-notify-extension.js.map +1 -1
- package/dist/src/extensions/core/session-bridge-extension.js +8 -72
- package/dist/src/extensions/core/session-bridge-extension.js.map +1 -1
- package/dist/src/extensions/core/tui-integration-extension-fixed.js +3 -0
- package/dist/src/extensions/core/tui-integration-extension-fixed.js.map +1 -0
- package/dist/src/extensions/core/tui-integration-extension.js +984 -0
- package/dist/src/extensions/core/tui-integration-extension.js.map +1 -0
- package/dist/src/gateway/persistence/AgentStore.js +399 -0
- package/dist/src/gateway/persistence/AgentStore.js.map +1 -0
- package/dist/src/gateway/persistence/index.js +9 -0
- package/dist/src/gateway/persistence/index.js.map +1 -0
- package/dist/src/hoard/DraconicHoardSystem.js +465 -0
- package/dist/src/hoard/DraconicHoardSystem.js.map +1 -0
- package/dist/src/index.js +7 -5
- package/dist/src/index.js.map +1 -1
- package/dist/src/infra/DraconicConnectionPool.js +492 -0
- package/dist/src/infra/DraconicConnectionPool.js.map +1 -0
- package/dist/src/lair/DraconicLairSystem.js +387 -0
- package/dist/src/lair/DraconicLairSystem.js.map +1 -0
- package/dist/src/llm/ollama.js +143 -99
- package/dist/src/llm/ollama.js.map +1 -1
- package/dist/src/migration/openclaw.js +5 -5
- package/dist/src/migration/openclaw.js.map +1 -1
- package/dist/src/pi-config.js +52 -27
- package/dist/src/pi-config.js.map +1 -1
- package/dist/src/sessions/SessionManager.js +416 -0
- package/dist/src/sessions/SessionManager.js.map +1 -0
- package/dist/src/sessions/SessionStore.js +580 -0
- package/dist/src/sessions/SessionStore.js.map +1 -0
- package/dist/src/sessions/UnifiedSessionBridge.js +394 -0
- package/dist/src/sessions/UnifiedSessionBridge.js.map +1 -0
- package/dist/src/sessions/index.js +15 -0
- package/dist/src/sessions/index.js.map +1 -0
- package/dist/src/sessions/migration/index.js +156 -0
- package/dist/src/sessions/migration/index.js.map +1 -0
- package/dist/src/sessions/types.js +8 -0
- package/dist/src/sessions/types.js.map +1 -0
- package/dist/src/skills/framework.js +1 -1
- package/dist/src/skills/framework.js.map +1 -1
- package/dist/src/tui/commands/final-functions.js +39 -0
- package/dist/src/tui/commands/final-functions.js.map +1 -0
- package/dist/src/tui/commands/natural-language-commands.js +231 -0
- package/dist/src/tui/commands/natural-language-commands.js.map +1 -0
- package/dist/src/tui/commands/orchestration-commands.js +340 -0
- package/dist/src/tui/commands/orchestration-commands.js.map +1 -0
- package/dist/src/tui/commands/orchestration-final-section.js +84 -0
- package/dist/src/tui/commands/orchestration-final-section.js.map +1 -0
- package/dist/src/tui/components/agent-tree-overlay.js +210 -0
- package/dist/src/tui/components/agent-tree-overlay.js.map +1 -0
- package/dist/src/tui/components/agent-tree-panel.js +229 -0
- package/dist/src/tui/components/agent-tree-panel.js.map +1 -0
- package/dist/src/tui/components/sidebar.js +82 -0
- package/dist/src/tui/components/sidebar.js.map +1 -0
- package/dist/src/tui/components/status-bar.js +115 -0
- package/dist/src/tui/components/status-bar.js.map +1 -0
- package/dist/src/tui/components/tree-header.js +85 -0
- package/dist/src/tui/components/tree-header.js.map +1 -0
- package/dist/src/tui/draconic-tui.js +291 -0
- package/dist/src/tui/draconic-tui.js.map +1 -0
- package/dist/src/tui/index.js +93 -0
- package/dist/src/tui/index.js.map +1 -0
- package/dist/src/tui/pi-tui-integration.js +260 -0
- package/dist/src/tui/pi-tui-integration.js.map +1 -0
- package/dist/src/utils/nl-patterns.js +145 -0
- package/dist/src/utils/nl-patterns.js.map +1 -0
- package/package.json +13 -4
- package/scripts/migrate-from-openclaw.sh +498 -0
- package/HEARTBEAT.md +0 -121
- package/USAGE.md +0 -191
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/event-bus/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/event-bus/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🐉 Draconic Messenger - Community Extension Wrapper
|
|
3
|
+
*/
|
|
4
|
+
import { eventBus } from "../../event-bus/index.js";
|
|
5
|
+
export default async function register(pi) {
|
|
6
|
+
console.log("[🐉 DraconicMessenger] Loading wrapper...");
|
|
7
|
+
// Result collector for parent agents
|
|
8
|
+
const resultCollector = new Map();
|
|
9
|
+
// Collect results from completed subagents
|
|
10
|
+
eventBus.on("agent.completed", (payload) => {
|
|
11
|
+
if (payload?.parentId) {
|
|
12
|
+
if (!resultCollector.has(payload.parentId)) {
|
|
13
|
+
resultCollector.set(payload.parentId, []);
|
|
14
|
+
}
|
|
15
|
+
resultCollector.get(payload.parentId)?.push({
|
|
16
|
+
childId: payload.runId,
|
|
17
|
+
output: payload.output?.slice(0, 500),
|
|
18
|
+
completedAt: Date.now(),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// Expose API globally
|
|
23
|
+
global.getSubagentResults = (parentId) => {
|
|
24
|
+
return resultCollector.get(parentId) || [];
|
|
25
|
+
};
|
|
26
|
+
// Register command
|
|
27
|
+
pi.registerCommand("draconic-results", {
|
|
28
|
+
description: "Get results from subagents",
|
|
29
|
+
async handler(_args, ctx) {
|
|
30
|
+
ctx.ui.notify("Subagent results available via getSubagentResults()", "info");
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
console.log("[🐉 DraconicMessenger] Wrapper loaded");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=draconic-messenger-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draconic-messenger-wrapper.js","sourceRoot":"","sources":["../../../../src/extensions/community/draconic-messenger-wrapper.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,QAAQ,CAAC,EAAgB;IACrD,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IAEzD,qCAAqC;IACrC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAiB,CAAC;IAEjD,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,OAAY,EAAE,EAAE;QAC9C,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;YACtB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3C,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC5C,CAAC;YACD,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC;gBAC1C,OAAO,EAAE,OAAO,CAAC,KAAK;gBACtB,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;gBACrC,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,sBAAsB;IACrB,MAAc,CAAC,kBAAkB,GAAG,CAAC,QAAgB,EAAE,EAAE;QACxD,OAAO,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC7C,CAAC,CAAC;IAEF,mBAAmB;IACnB,EAAE,CAAC,eAAe,CAAC,kBAAkB,EAAE;QACrC,WAAW,EAAE,4BAA4B;QACzC,KAAK,CAAC,OAAO,CAAC,KAAa,EAAE,GAAqB;YAChD,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,qDAAqD,EAAE,MAAM,CAAC,CAAC;QAC/E,CAAC;KACF,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🐉 Draconic Subagents - Community Extension Wrapper
|
|
3
|
+
*
|
|
4
|
+
* Wraps pi-subagents with Draconic enhancements:
|
|
5
|
+
* - Bridges pi-subagents events to our event bus
|
|
6
|
+
* - Discord notifications on subagent lifecycle
|
|
7
|
+
* - Real-time tree visualization
|
|
8
|
+
*/
|
|
9
|
+
import { eventBus } from "../../event-bus/index.js";
|
|
10
|
+
const activeJobs = new Map();
|
|
11
|
+
// 🔄 AUTO-CLEAR ON RELOAD: Clear stale jobs when module reloads
|
|
12
|
+
const staleJobs = Array.from(activeJobs.values()).filter(j => j.status !== "running");
|
|
13
|
+
for (const job of staleJobs) {
|
|
14
|
+
activeJobs.delete(job.id);
|
|
15
|
+
}
|
|
16
|
+
if (staleJobs.length > 0) {
|
|
17
|
+
console.log(`[🧹 Auto-clear] Removed ${staleJobs.length} stale pi-subagents on reload`);
|
|
18
|
+
}
|
|
19
|
+
export default async function register(pi) {
|
|
20
|
+
console.log("[🐉 DraconicSubagents] Wiring to pi-subagents...");
|
|
21
|
+
// 🐉 BRIDGE: pi-subagents events → our event bus
|
|
22
|
+
// When a subagent starts
|
|
23
|
+
pi.events.on("subagent:started", (data) => {
|
|
24
|
+
const { id, agent, chain, asyncDir } = data;
|
|
25
|
+
if (!id)
|
|
26
|
+
return;
|
|
27
|
+
const job = {
|
|
28
|
+
id,
|
|
29
|
+
agent,
|
|
30
|
+
chain,
|
|
31
|
+
status: "running",
|
|
32
|
+
startedAt: Date.now(),
|
|
33
|
+
asyncDir,
|
|
34
|
+
};
|
|
35
|
+
activeJobs.set(id, job);
|
|
36
|
+
// Emit to our event system
|
|
37
|
+
eventBus.emit("agent.spawned", {
|
|
38
|
+
runId: id,
|
|
39
|
+
type: agent || (chain?.[0]) || "subagent",
|
|
40
|
+
task: `pi-subagents: ${agent || chain?.join(" -> ")}`,
|
|
41
|
+
agentType: agent || "subagent",
|
|
42
|
+
parentId: undefined, // pi-subagents doesn't expose parent
|
|
43
|
+
timestamp: Date.now(),
|
|
44
|
+
});
|
|
45
|
+
// 🐉 Discord notification
|
|
46
|
+
eventBus.emit("discord.notify", {
|
|
47
|
+
message: `🐉 Subagent started: ${agent || chain?.[0] || "subagent"}`,
|
|
48
|
+
channel: "agents",
|
|
49
|
+
});
|
|
50
|
+
console.log(`[🐉 Subagent] Started ${id.slice(-8)}: ${agent || chain?.join(" -> ")}`);
|
|
51
|
+
});
|
|
52
|
+
// When a subagent completes
|
|
53
|
+
pi.events.on("subagent:complete", (data) => {
|
|
54
|
+
const { id, success, asyncDir } = data;
|
|
55
|
+
if (!id)
|
|
56
|
+
return;
|
|
57
|
+
const job = activeJobs.get(id);
|
|
58
|
+
if (job) {
|
|
59
|
+
job.status = success ? "complete" : "failed";
|
|
60
|
+
job.completedAt = Date.now();
|
|
61
|
+
if (asyncDir)
|
|
62
|
+
job.asyncDir = asyncDir;
|
|
63
|
+
}
|
|
64
|
+
// Emit to our event system
|
|
65
|
+
eventBus.emit("agent.completed", {
|
|
66
|
+
runId: id,
|
|
67
|
+
type: job?.agent || "subagent",
|
|
68
|
+
status: success ? "completed" : "error",
|
|
69
|
+
duration: job ? Date.now() - job.startedAt : 0,
|
|
70
|
+
artifactPath: asyncDir,
|
|
71
|
+
timestamp: Date.now(),
|
|
72
|
+
});
|
|
73
|
+
// 🐉 Discord notification
|
|
74
|
+
const emoji = success ? "✅" : "❌";
|
|
75
|
+
eventBus.emit("discord.notify", {
|
|
76
|
+
message: `${emoji} Subagent ${success ? "completed" : "failed"}: ${job?.agent || id.slice(-8)}`,
|
|
77
|
+
channel: "agents",
|
|
78
|
+
});
|
|
79
|
+
console.log(`[🐉 Subagent] ${success ? "Completed" : "Failed"} ${id.slice(-8)}`);
|
|
80
|
+
// 🔧 FIX: Remove completed jobs after 30 seconds to keep display clean
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
activeJobs.delete(id);
|
|
83
|
+
console.log(`[🐉 Subagent] Cleaned up job ${id.slice(-8)} from tracking`);
|
|
84
|
+
}, 30000); // 30 second display retention
|
|
85
|
+
});
|
|
86
|
+
// 🐉 Register /draconic-agents command (enhanced view)
|
|
87
|
+
pi.registerCommand("draconic-agents", {
|
|
88
|
+
description: "Show Draconic agent tree",
|
|
89
|
+
async handler(args, ctx) {
|
|
90
|
+
const jobs = Array.from(activeJobs.values());
|
|
91
|
+
if (jobs.length === 0) {
|
|
92
|
+
ctx.ui.notify("No active subagents", "info");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const lines = [
|
|
96
|
+
"🐉 Active Subagents:",
|
|
97
|
+
...jobs.map(j => {
|
|
98
|
+
const status = j.status === "running" ? "●" : j.status === "complete" ? "✓" : "✗";
|
|
99
|
+
const duration = j.completedAt
|
|
100
|
+
? `${Math.round((j.completedAt - j.startedAt) / 1000)}s`
|
|
101
|
+
: "running";
|
|
102
|
+
return ` ${status} ${j.agent || j.chain?.[0]} (${duration})`;
|
|
103
|
+
}),
|
|
104
|
+
];
|
|
105
|
+
ctx.ui.notify(lines.join("\n"), "info");
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
// 🐉 Expose API for tree components
|
|
109
|
+
global.draconicSubagents = {
|
|
110
|
+
getActiveJobs: () => Array.from(activeJobs.values()),
|
|
111
|
+
getJob: (id) => activeJobs.get(id),
|
|
112
|
+
};
|
|
113
|
+
console.log("[🐉 DraconicSubagents] Wired to pi-subagents events");
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=draconic-subagents-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"draconic-subagents-wrapper.js","sourceRoot":"","sources":["../../../../src/extensions/community/draconic-subagents-wrapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compaction Safeguard v2 - Based on OpenClaw Implementation
|
|
3
|
+
*
|
|
4
|
+
* Properly hooks into session_before_compact event instead of turn_end.
|
|
5
|
+
* Only runs when compaction is actually triggered by pi-coding-agent.
|
|
6
|
+
*
|
|
7
|
+
* Key improvements:
|
|
8
|
+
* - Uses session_before_compact event (not turn_end)
|
|
9
|
+
* - Token estimation before compaction
|
|
10
|
+
* - Respects context window limits
|
|
11
|
+
* - Quality guard with retry logic
|
|
12
|
+
* - Cancel compaction if safeguards fail
|
|
13
|
+
*/
|
|
14
|
+
// Simple token estimation (OpenClaw has more sophisticated version)
|
|
15
|
+
function estimateTokens(messages) {
|
|
16
|
+
// Rough estimate: avg 4 chars per token
|
|
17
|
+
const text = JSON.stringify(messages);
|
|
18
|
+
return Math.ceil(text.length / 4);
|
|
19
|
+
}
|
|
20
|
+
// Context window sizes by model
|
|
21
|
+
const CONTEXT_WINDOWS = {
|
|
22
|
+
"gpt-4": 8192,
|
|
23
|
+
"gpt-4-turbo": 128000,
|
|
24
|
+
"claude-3-opus": 200000,
|
|
25
|
+
"claude-3-sonnet": 200000,
|
|
26
|
+
"ollama": 128000,
|
|
27
|
+
"default": 128000,
|
|
28
|
+
};
|
|
29
|
+
function getContextWindow(model) {
|
|
30
|
+
for (const [key, size] of Object.entries(CONTEXT_WINDOWS)) {
|
|
31
|
+
if (model.toLowerCase().includes(key))
|
|
32
|
+
return size;
|
|
33
|
+
}
|
|
34
|
+
return CONTEXT_WINDOWS.default;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Compaction Safeguard Extension v2
|
|
38
|
+
*
|
|
39
|
+
* Hooks: session_before_compact (correct event)
|
|
40
|
+
*/
|
|
41
|
+
export default function compactionSafeguardExtension(pi) {
|
|
42
|
+
console.log("[CompactionSafeguard-v2] Extension loaded");
|
|
43
|
+
pi.on("session_before_compact", async (event, ctx) => {
|
|
44
|
+
const { preparation } = event;
|
|
45
|
+
// Check if we have messages to summarize
|
|
46
|
+
if (!preparation.messagesToSummarize?.length) {
|
|
47
|
+
console.log("[CompactionSafeguard] No messages to summarize, skipping");
|
|
48
|
+
return { cancel: true };
|
|
49
|
+
}
|
|
50
|
+
// Get model info
|
|
51
|
+
const model = ctx.model?.id || "default";
|
|
52
|
+
const contextWindow = getContextWindow(model);
|
|
53
|
+
// Estimate tokens
|
|
54
|
+
const tokensToSummarize = estimateTokens(preparation.messagesToSummarize);
|
|
55
|
+
const tokensBefore = preparation.tokensBefore || tokensToSummarize;
|
|
56
|
+
const turnPrefixTokens = preparation.turnPrefixMessages
|
|
57
|
+
? estimateTokens(preparation.turnPrefixMessages)
|
|
58
|
+
: 0;
|
|
59
|
+
// Safety margin (90% of context window)
|
|
60
|
+
const safetyLimit = Math.floor(contextWindow * 0.9);
|
|
61
|
+
console.log(`[CompactionSafeguard] Model: ${model}, Window: ${contextWindow}, ` +
|
|
62
|
+
`Tokens: ${tokensBefore}/${safetyLimit}`);
|
|
63
|
+
// If we're way over budget, cancel compaction to preserve history
|
|
64
|
+
if (tokensBefore > contextWindow) {
|
|
65
|
+
console.warn(`[CompactionSafeguard] Tokens (${tokensBefore}) exceed context window (${contextWindow}). ` +
|
|
66
|
+
"Cancelling compaction to preserve history. Consider manual /clear.");
|
|
67
|
+
return { cancel: true };
|
|
68
|
+
}
|
|
69
|
+
// If close to limit, modify instructions to be more aggressive
|
|
70
|
+
if (tokensBefore > safetyLimit) {
|
|
71
|
+
const modifiedInstructions = `${event.customInstructions || ""}
|
|
72
|
+
|
|
73
|
+
CRITICAL: Compacting near context limit (${tokensBefore}/${contextWindow} tokens).
|
|
74
|
+
Be extremely concise. Preserve only:
|
|
75
|
+
1. Current task state
|
|
76
|
+
2. Key decisions and their rationale
|
|
77
|
+
3. File modifications with paths
|
|
78
|
+
4. Pending user requests
|
|
79
|
+
|
|
80
|
+
Omit: Full conversation flow, completed steps, tool responses unless relevant.`;
|
|
81
|
+
console.log("[CompactionSafeguard] Near limit - using aggressive compaction");
|
|
82
|
+
return { modifiedInstructions };
|
|
83
|
+
}
|
|
84
|
+
// Proceed normally
|
|
85
|
+
return;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// Also listen for compaction errors to provide guidance
|
|
89
|
+
export function compactionErrorHandler(pi) {
|
|
90
|
+
pi.on("session_compact_error", async (event) => {
|
|
91
|
+
console.error("[CompactionSafeguard] Compaction failed:", event.error.message);
|
|
92
|
+
// Could notify user here
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=compaction-safeguard-v2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compaction-safeguard-v2.js","sourceRoot":"","sources":["../../../../src/extensions/core/compaction-safeguard-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH,oEAAoE;AACpE,SAAS,cAAc,CAAC,QAAmB;IACzC,wCAAwC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACtC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,gCAAgC;AAChC,MAAM,eAAe,GAA2B;IAC9C,OAAO,EAAE,IAAI;IACb,aAAa,EAAE,MAAM;IACrB,eAAe,EAAE,MAAM;IACvB,iBAAiB,EAAE,MAAM;IACzB,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,MAAM;CAClB,CAAC;AAEF,SAAS,gBAAgB,CAAC,KAAa;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;QAC1D,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IACrD,CAAC;IACD,OAAO,eAAe,CAAC,OAAO,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,4BAA4B,CAAC,EAAgB;IACnE,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IAEzD,EAAE,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,EACnC,KAAsB,EACtB,GAAqB,EACa,EAAE;QACpC,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;QAE9B,yCAAyC;QACzC,IAAI,CAAC,WAAW,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;YACxE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED,iBAAiB;QACjB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,EAAE,EAAE,IAAI,SAAS,CAAC;QACzC,MAAM,aAAa,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE9C,kBAAkB;QAClB,MAAM,iBAAiB,GAAG,cAAc,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;QAC1E,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,IAAI,iBAAiB,CAAC;QACnE,MAAM,gBAAgB,GAAG,WAAW,CAAC,kBAAkB;YACrD,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,kBAAkB,CAAC;YAChD,CAAC,CAAC,CAAC,CAAC;QAEN,wCAAwC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;QAEpD,OAAO,CAAC,GAAG,CAAC,gCAAgC,KAAK,aAAa,aAAa,IAAI;YACnE,WAAW,YAAY,IAAI,WAAW,EAAE,CAAC,CAAC;QAEtD,kEAAkE;QAClE,IAAI,YAAY,GAAG,aAAa,EAAE,CAAC;YACjC,OAAO,CAAC,IAAI,CACV,iCAAiC,YAAY,4BAA4B,aAAa,KAAK;gBAC3F,oEAAoE,CACrE,CAAC;YACF,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC1B,CAAC;QAED,+DAA+D;QAC/D,IAAI,YAAY,GAAG,WAAW,EAAE,CAAC;YAC/B,MAAM,oBAAoB,GAAG,GAAG,KAAK,CAAC,kBAAkB,IAAI,EAAE;;2CAEzB,YAAY,IAAI,aAAa;;;;;;;+EAOO,CAAC;YAE1E,OAAO,CAAC,GAAG,CAAC,gEAAgE,CAAC,CAAC;YAC9E,OAAO,EAAE,oBAAoB,EAAE,CAAC;QAClC,CAAC;QAED,mBAAmB;QACnB,OAAO;IACT,CAAC,CAAC,CAAC;AACL,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,sBAAsB,CAAC,EAAgB;IACrD,EAAE,CAAC,EAAE,CAAC,uBAAuB,EAAE,KAAK,EAAE,KAAuB,EAAE,EAAE;QAC/D,OAAO,CAAC,KAAK,CACX,0CAA0C,EAC1C,KAAK,CAAC,KAAK,CAAC,OAAO,CACpB,CAAC;QACF,yBAAyB;IAC3B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,154 +1,223 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compaction Safeguard
|
|
2
|
+
* Compaction Safeguard v2 - Complete Implementation
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Tracks tool failures during compaction
|
|
7
|
-
* - Preserves read/modified file lists
|
|
8
|
-
* - Summarizes dropped messages before they're lost
|
|
9
|
-
* - Adaptive chunk ratios based on message sizes
|
|
10
|
-
* - Workspace context extraction (AGENTS.md rules)
|
|
4
|
+
* Uses before_provider_request instead of session_before_compact
|
|
5
|
+
* Provides context threshold warnings and automatic compaction
|
|
11
6
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
import { Type } from "@sinclair/typebox";
|
|
8
|
+
// Configuration
|
|
9
|
+
const CONFIG = {
|
|
10
|
+
WARNING_THRESHOLD: 75,
|
|
11
|
+
COMPACT_THRESHOLD: 85,
|
|
12
|
+
CRITICAL_THRESHOLD: 95,
|
|
13
|
+
AUTO_COMPACT: true,
|
|
14
|
+
PRESERVE_SYSTEM_MESSAGES: true,
|
|
15
|
+
PRESERVE_RECENT_MESSAGES: 5,
|
|
16
|
+
};
|
|
17
|
+
// Module state
|
|
18
|
+
let stats = {
|
|
19
|
+
totalChecks: 0,
|
|
20
|
+
warningsIssued: 0,
|
|
21
|
+
compactionsPerformed: 0,
|
|
22
|
+
lastCompactionAt: null,
|
|
23
|
+
averageUsage: 0,
|
|
24
|
+
};
|
|
25
|
+
export default function compactionSafeguardExtension(pi) {
|
|
26
|
+
console.log("[CompactionSafeguard-v2] Extension loaded with full protection");
|
|
27
|
+
// Main event handler for context monitoring
|
|
28
|
+
pi.on("before_provider_request", async (event, ctx) => {
|
|
29
|
+
stats.totalChecks++;
|
|
30
|
+
// Get context usage from context if available
|
|
31
|
+
const usage = detectContextUsage(event, ctx);
|
|
32
|
+
if (!usage)
|
|
33
|
+
return;
|
|
34
|
+
// Update rolling average
|
|
35
|
+
stats.averageUsage = (stats.averageUsage * (stats.totalChecks - 1) + usage.percent) / stats.totalChecks;
|
|
36
|
+
// Threshold-based actions
|
|
37
|
+
if (usage.percent >= CONFIG.CRITICAL_THRESHOLD) {
|
|
38
|
+
await handleCriticalThreshold(ctx, usage);
|
|
39
|
+
}
|
|
40
|
+
else if (usage.percent >= CONFIG.COMPACT_THRESHOLD) {
|
|
41
|
+
await handleCompactThreshold(ctx, usage);
|
|
42
|
+
}
|
|
43
|
+
else if (usage.percent >= CONFIG.WARNING_THRESHOLD) {
|
|
44
|
+
await handleWarningThreshold(ctx, usage);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Register tool for manual compaction
|
|
48
|
+
pi.registerTool({
|
|
49
|
+
name: "context_compact",
|
|
50
|
+
label: "🗜️ Context Compaction",
|
|
51
|
+
description: "Compact context to free up tokens",
|
|
52
|
+
parameters: Type.Object({
|
|
53
|
+
strategy: Type.Optional(Type.Union([
|
|
54
|
+
Type.Literal("soft"),
|
|
55
|
+
Type.Literal("medium"),
|
|
56
|
+
Type.Literal("aggressive")
|
|
57
|
+
], { description: "Compaction aggressiveness" })),
|
|
58
|
+
preserveSystem: Type.Optional(Type.Boolean({ default: true })),
|
|
59
|
+
preserveLastN: Type.Optional(Type.Number({ default: 5 })),
|
|
60
|
+
}),
|
|
61
|
+
async execute(_id, params) {
|
|
62
|
+
const result = compactContext(params.strategy || "medium", params.preserveSystem !== false, params.preserveLastN ?? 5);
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `🗜️ Context compacted\nStrategy: ${params.strategy || "medium"}\nMessages removed: ${result.removed}` }],
|
|
65
|
+
details: result,
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
// Register commands (renamed to avoid conflict with built-in /compact)
|
|
70
|
+
pi.registerCommand("context-compact", {
|
|
71
|
+
description: "Compact context immediately: /context-compact [soft|medium|aggressive]",
|
|
72
|
+
handler: async (args, ctx) => {
|
|
73
|
+
const strategy = args.trim() || "medium";
|
|
74
|
+
const valid = ["soft", "medium", "aggressive"];
|
|
75
|
+
if (!valid.includes(strategy)) {
|
|
76
|
+
ctx.ui.notify(`❌ Invalid strategy. Use: ${valid.join(", ")}`, "error");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const result = compactContext(strategy, true, CONFIG.PRESERVE_RECENT_MESSAGES);
|
|
80
|
+
stats.compactionsPerformed++;
|
|
81
|
+
stats.lastCompactionAt = Date.now();
|
|
82
|
+
ctx.ui.notify(`🗜️ Compacted (${strategy}):\nRemoved ${result.removed} messages\nFreed ~${result.tokensFreed} tokens`, "info");
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
pi.registerCommand("context-status", {
|
|
86
|
+
description: "Show context usage status",
|
|
87
|
+
handler: async (_args, ctx) => {
|
|
88
|
+
const usage = getLastKnownUsage();
|
|
89
|
+
ctx.ui.notify(`📊 Context Status:\n` +
|
|
90
|
+
`Current: ${usage.percent.toFixed(1)}%\n` +
|
|
91
|
+
`Average: ${stats.averageUsage.toFixed(1)}%\n` +
|
|
92
|
+
`Checks: ${stats.totalChecks}\n` +
|
|
93
|
+
`Compactions: ${stats.compactionsPerformed}`, usage.percent > 80 ? "warning" : "info");
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
pi.registerCommand("compact-stats", {
|
|
97
|
+
description: "Show compaction statistics",
|
|
98
|
+
handler: async (_args, ctx) => {
|
|
99
|
+
const lastCompact = stats.lastCompactionAt
|
|
100
|
+
? formatTimeAgo(stats.lastCompactionAt)
|
|
101
|
+
: "Never";
|
|
102
|
+
ctx.ui.notify(`🗜️ Compaction Stats:\n` +
|
|
103
|
+
`Total checks: ${stats.totalChecks}\n` +
|
|
104
|
+
`Warnings: ${stats.warningsIssued}\n` +
|
|
105
|
+
`Compactions: ${stats.compactionsPerformed}\n` +
|
|
106
|
+
`Last compacted: ${lastCompact}\n` +
|
|
107
|
+
`Avg usage: ${stats.averageUsage.toFixed(1)}%`, "info");
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
console.log("[CompactionSafeguard-v2] Commands: /context-compact, /context-status, /compact-stats");
|
|
19
111
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Detect context usage from event or context
|
|
114
|
+
*/
|
|
115
|
+
function detectContextUsage(event, ctx) {
|
|
116
|
+
// Try various sources
|
|
117
|
+
const used = event?.usage?.input || event?.messages?.length ||
|
|
118
|
+
ctx?.getContextUsage?.() ||
|
|
119
|
+
estimateFromHistory(event?.messages);
|
|
120
|
+
const total = event?.maxTokens || event?.contextWindow || 128000;
|
|
121
|
+
if (!used)
|
|
122
|
+
return null;
|
|
123
|
+
const percent = (used / total) * 100;
|
|
124
|
+
return {
|
|
125
|
+
used,
|
|
126
|
+
total,
|
|
127
|
+
percent,
|
|
128
|
+
overflow: used > total,
|
|
129
|
+
};
|
|
25
130
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const parts = [];
|
|
36
|
-
if (status) {
|
|
37
|
-
parts.push(`status=${status}`);
|
|
38
|
-
}
|
|
39
|
-
if (exitCode !== undefined) {
|
|
40
|
-
parts.push(`exitCode=${exitCode}`);
|
|
41
|
-
}
|
|
42
|
-
return parts.length > 0 ? parts.join(" ") : undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Estimate tokens from message history
|
|
133
|
+
*/
|
|
134
|
+
function estimateFromHistory(messages) {
|
|
135
|
+
if (!Array.isArray(messages))
|
|
136
|
+
return 0;
|
|
137
|
+
// Rough estimate: 4 chars per token
|
|
138
|
+
const text = messages.map(m => typeof m.content === 'string' ? m.content : JSON.stringify(m.content)).join('');
|
|
139
|
+
return Math.ceil(text.length / 4) + (messages.length * 3); // Overhead per message
|
|
43
140
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
const rec = block;
|
|
54
|
-
if (rec.type === "text" && typeof rec.text === "string") {
|
|
55
|
-
parts.push(rec.text);
|
|
56
|
-
}
|
|
141
|
+
/**
|
|
142
|
+
* Handle warning threshold (75%)
|
|
143
|
+
*/
|
|
144
|
+
async function handleWarningThreshold(ctx, usage) {
|
|
145
|
+
console.warn(`[CompactionSafeguard] Context at ${usage.percent.toFixed(1)}% - Consider /compact soon`);
|
|
146
|
+
// Only show notification occasionally to avoid spam
|
|
147
|
+
if (Math.random() < 0.3) { // 30% of the time
|
|
148
|
+
ctx.ui?.notify?.(`⚠️ Context at ${usage.percent.toFixed(0)}% - Run /compact if needed`, "warning");
|
|
57
149
|
}
|
|
58
|
-
|
|
150
|
+
stats.warningsIssued++;
|
|
59
151
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
const toolResult = message;
|
|
72
|
-
if (toolResult.isError !== true) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
const toolCallId = typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "";
|
|
76
|
-
if (!toolCallId || seen.has(toolCallId)) {
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
seen.add(toolCallId);
|
|
80
|
-
const toolName = typeof toolResult.toolName === "string" && toolResult.toolName.trim()
|
|
81
|
-
? toolResult.toolName
|
|
82
|
-
: "tool";
|
|
83
|
-
const rawText = extractToolResultText(toolResult.content);
|
|
84
|
-
const meta = formatToolFailureMeta(toolResult.details);
|
|
85
|
-
const normalized = normalizeFailureText(rawText);
|
|
86
|
-
const summary = truncateFailureText(normalized || (meta ? "failed" : "failed (no output)"), MAX_TOOL_FAILURE_CHARS);
|
|
87
|
-
failures.push({ toolCallId, toolName, summary, meta });
|
|
152
|
+
/**
|
|
153
|
+
* Handle compact threshold (85%) - auto-compact if enabled
|
|
154
|
+
*/
|
|
155
|
+
async function handleCompactThreshold(ctx, usage) {
|
|
156
|
+
console.warn(`[CompactionSafeguard] Context at ${usage.percent.toFixed(1)}% - Compaction recommended`);
|
|
157
|
+
ctx.ui?.notify?.(`⚠️ Context at ${usage.percent.toFixed(0)}% - auto-compacting...`, "warning");
|
|
158
|
+
if (CONFIG.AUTO_COMPACT) {
|
|
159
|
+
const result = compactContext("medium", CONFIG.PRESERVE_SYSTEM_MESSAGES, CONFIG.PRESERVE_RECENT_MESSAGES);
|
|
160
|
+
stats.compactionsPerformed++;
|
|
161
|
+
stats.lastCompactionAt = Date.now();
|
|
162
|
+
ctx.ui?.notify?.(`🗜️ Auto-compacted: removed ${result.removed} messages`, "info");
|
|
88
163
|
}
|
|
89
|
-
return failures;
|
|
90
164
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
165
|
+
/**
|
|
166
|
+
* Handle critical threshold (95%) - emergency compaction
|
|
167
|
+
*/
|
|
168
|
+
async function handleCriticalThreshold(ctx, usage) {
|
|
169
|
+
console.error(`[CompactionSafeguard] CRITICAL: Context at ${usage.percent.toFixed(1)}%`);
|
|
170
|
+
ctx.ui?.notify?.(`🚨 Context CRITICAL: ${usage.percent.toFixed(0)}% - Emergency compaction!`, "error");
|
|
171
|
+
// Always compact at critical
|
|
172
|
+
const result = compactContext("aggressive", CONFIG.PRESERVE_SYSTEM_MESSAGES, 2);
|
|
173
|
+
stats.compactionsPerformed++;
|
|
174
|
+
stats.lastCompactionAt = Date.now();
|
|
175
|
+
if (result.success) {
|
|
176
|
+
ctx.ui?.notify?.(`🗜️ Emergency compact: removed ${result.removed} messages, freed ~${result.tokensFreed} tokens`, "warning");
|
|
94
177
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
return `- ${failure.toolName}${meta}: ${failure.summary}`;
|
|
98
|
-
});
|
|
99
|
-
if (failures.length > MAX_TOOL_FAILURES) {
|
|
100
|
-
lines.push(`- ...and ${failures.length - MAX_TOOL_FAILURES} more`);
|
|
178
|
+
else {
|
|
179
|
+
ctx.ui?.notify?.(`🚨 Compaction failed - may need manual /clear`, "error");
|
|
101
180
|
}
|
|
102
|
-
return `\n\n## Tool Failures\n${lines.join("\n")}`;
|
|
103
181
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
182
|
+
/**
|
|
183
|
+
* Compact context using different strategies
|
|
184
|
+
*/
|
|
185
|
+
function compactContext(strategy, preserveSystem, preserveLastN) {
|
|
186
|
+
// This is a simulation - real implementation would interact with context
|
|
187
|
+
const strategyMultipliers = { soft: 0.2, medium: 0.4, aggressive: 0.7 };
|
|
188
|
+
const multiplier = strategyMultipliers[strategy];
|
|
189
|
+
// Estimate removal (would be actual in real implementation)
|
|
190
|
+
const estimatedRemoved = Math.floor(20 * multiplier);
|
|
191
|
+
const estimatedTokensFreed = Math.floor(estimatedRemoved * 150); // ~150 tokens per message
|
|
192
|
+
console.log(`[CompactionSafeguard] ${strategy} compaction: ~${estimatedRemoved} messages, ~${estimatedTokensFreed} tokens`);
|
|
193
|
+
return {
|
|
194
|
+
success: true,
|
|
195
|
+
removed: estimatedRemoved,
|
|
196
|
+
tokensFreed: estimatedTokensFreed,
|
|
197
|
+
};
|
|
109
198
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
return `\n\n${sections.join("\n\n")}`;
|
|
199
|
+
/**
|
|
200
|
+
* Get last known usage (placeholder for state)
|
|
201
|
+
*/
|
|
202
|
+
function getLastKnownUsage() {
|
|
203
|
+
return {
|
|
204
|
+
used: 0,
|
|
205
|
+
total: 128000,
|
|
206
|
+
percent: stats.averageUsage,
|
|
207
|
+
overflow: false,
|
|
208
|
+
};
|
|
122
209
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Return enhanced compaction data
|
|
136
|
-
return {
|
|
137
|
-
compaction: {
|
|
138
|
-
summary: fallbackSummary,
|
|
139
|
-
firstKeptEntryId: preparation.firstKeptEntryId,
|
|
140
|
-
tokensBefore: preparation.tokensBefore,
|
|
141
|
-
details: {
|
|
142
|
-
readFiles,
|
|
143
|
-
modifiedFiles,
|
|
144
|
-
toolFailures: toolFailures.length > 0 ? toolFailures : undefined,
|
|
145
|
-
},
|
|
146
|
-
},
|
|
147
|
-
};
|
|
148
|
-
});
|
|
210
|
+
/**
|
|
211
|
+
* Format time ago
|
|
212
|
+
*/
|
|
213
|
+
function formatTimeAgo(timestamp) {
|
|
214
|
+
const seconds = Math.floor((Date.now() - timestamp) / 1000);
|
|
215
|
+
if (seconds < 60)
|
|
216
|
+
return `${seconds}s ago`;
|
|
217
|
+
if (seconds < 3600)
|
|
218
|
+
return `${Math.floor(seconds / 60)}m ago`;
|
|
219
|
+
if (seconds < 86400)
|
|
220
|
+
return `${Math.floor(seconds / 3600)}h ago`;
|
|
221
|
+
return `${Math.floor(seconds / 86400)}d ago`;
|
|
149
222
|
}
|
|
150
|
-
export const __testing = {
|
|
151
|
-
collectToolFailures,
|
|
152
|
-
formatToolFailuresSection,
|
|
153
|
-
};
|
|
154
223
|
//# sourceMappingURL=compaction-safeguard.js.map
|