0xkobold 0.0.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/.agents/skills/nextjs-best-practices/SKILL.md +208 -0
- package/.agents/skills/sql-optimization-patterns/SKILL.md +509 -0
- package/HEARTBEAT.md +45 -0
- package/README.md +197 -0
- package/USAGE.md +191 -0
- package/dist/package.json +77 -0
- package/dist/src/agent/pi-adapter.js +307 -0
- package/dist/src/agent/pi-adapter.js.map +1 -0
- package/dist/src/agent/tool-adapter.js +86 -0
- package/dist/src/agent/tool-adapter.js.map +1 -0
- package/dist/src/approval/queue.js +114 -0
- package/dist/src/approval/queue.js.map +1 -0
- package/dist/src/ascii-kobold.js +76 -0
- package/dist/src/ascii-kobold.js.map +1 -0
- package/dist/src/cli/client.js +217 -0
- package/dist/src/cli/client.js.map +1 -0
- package/dist/src/cli/commands/agent.js +272 -0
- package/dist/src/cli/commands/agent.js.map +1 -0
- package/dist/src/cli/commands/chat.js +234 -0
- package/dist/src/cli/commands/chat.js.map +1 -0
- package/dist/src/cli/commands/config.js +202 -0
- package/dist/src/cli/commands/config.js.map +1 -0
- package/dist/src/cli/commands/daemon.js +203 -0
- package/dist/src/cli/commands/daemon.js.map +1 -0
- package/dist/src/cli/commands/gateway.js +184 -0
- package/dist/src/cli/commands/gateway.js.map +1 -0
- package/dist/src/cli/commands/init.js +175 -0
- package/dist/src/cli/commands/init.js.map +1 -0
- package/dist/src/cli/commands/kobold.js +21 -0
- package/dist/src/cli/commands/kobold.js.map +1 -0
- package/dist/src/cli/commands/logs.js +27 -0
- package/dist/src/cli/commands/logs.js.map +1 -0
- package/dist/src/cli/commands/mode.js +121 -0
- package/dist/src/cli/commands/mode.js.map +1 -0
- package/dist/src/cli/commands/persona.js +261 -0
- package/dist/src/cli/commands/persona.js.map +1 -0
- package/dist/src/cli/commands/start.js +66 -0
- package/dist/src/cli/commands/start.js.map +1 -0
- package/dist/src/cli/commands/status.js +117 -0
- package/dist/src/cli/commands/status.js.map +1 -0
- package/dist/src/cli/commands/stop.js +27 -0
- package/dist/src/cli/commands/stop.js.map +1 -0
- package/dist/src/cli/commands/system.js +128 -0
- package/dist/src/cli/commands/system.js.map +1 -0
- package/dist/src/cli/commands/tui.js +103 -0
- package/dist/src/cli/commands/tui.js.map +1 -0
- package/dist/src/cli/commands/update.js +133 -0
- package/dist/src/cli/commands/update.js.map +1 -0
- package/dist/src/cli/extensions/discord.js +113 -0
- package/dist/src/cli/extensions/discord.js.map +1 -0
- package/dist/src/cli/extensions/env.js +91 -0
- package/dist/src/cli/extensions/env.js.map +1 -0
- package/dist/src/cli/extensions/heartbeat.js +78 -0
- package/dist/src/cli/extensions/heartbeat.js.map +1 -0
- package/dist/src/cli/index.js +24 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/program.js +70 -0
- package/dist/src/cli/program.js.map +1 -0
- package/dist/src/cli/repl.js +184 -0
- package/dist/src/cli/repl.js.map +1 -0
- package/dist/src/cli/shared/discord-service.js +102 -0
- package/dist/src/cli/shared/discord-service.js.map +1 -0
- package/dist/src/config/index.js +10 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/config/loader.js +401 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/config/paths.js +84 -0
- package/dist/src/config/paths.js.map +1 -0
- package/dist/src/config/types.js +8 -0
- package/dist/src/config/types.js.map +1 -0
- package/dist/src/context-detector.js +60 -0
- package/dist/src/context-detector.js.map +1 -0
- package/dist/src/discord/index.js +376 -0
- package/dist/src/discord/index.js.map +1 -0
- package/dist/src/event-bus/index.js +97 -0
- package/dist/src/event-bus/index.js.map +1 -0
- package/dist/src/extensions/command-args.js +68 -0
- package/dist/src/extensions/command-args.js.map +1 -0
- package/dist/src/extensions/core/agent-registry-extension.js +541 -0
- package/dist/src/extensions/core/agent-registry-extension.js.map +1 -0
- package/dist/src/extensions/core/agent-worker.js +148 -0
- package/dist/src/extensions/core/agent-worker.js.map +1 -0
- package/dist/src/extensions/core/compaction-safeguard.js +154 -0
- package/dist/src/extensions/core/compaction-safeguard.js.map +1 -0
- package/dist/src/extensions/core/confirm-destructive.js +43 -0
- package/dist/src/extensions/core/confirm-destructive.js.map +1 -0
- package/dist/src/extensions/core/context-aware-extension.js +124 -0
- package/dist/src/extensions/core/context-aware-extension.js.map +1 -0
- package/dist/src/extensions/core/context-pruning/extension.js +124 -0
- package/dist/src/extensions/core/context-pruning/extension.js.map +1 -0
- package/dist/src/extensions/core/context-pruning/pruner.js +312 -0
- package/dist/src/extensions/core/context-pruning/pruner.js.map +1 -0
- package/dist/src/extensions/core/context-pruning/runtime.js +48 -0
- package/dist/src/extensions/core/context-pruning/runtime.js.map +1 -0
- package/dist/src/extensions/core/context-pruning/settings.js +105 -0
- package/dist/src/extensions/core/context-pruning/settings.js.map +1 -0
- package/dist/src/extensions/core/dirty-repo-guard.js +42 -0
- package/dist/src/extensions/core/dirty-repo-guard.js.map +1 -0
- package/dist/src/extensions/core/discord-channel-extension.js +205 -0
- package/dist/src/extensions/core/discord-channel-extension.js.map +1 -0
- package/dist/src/extensions/core/discord-extension.js +142 -0
- package/dist/src/extensions/core/discord-extension.js.map +1 -0
- package/dist/src/extensions/core/env-loader-extension.js +157 -0
- package/dist/src/extensions/core/env-loader-extension.js.map +1 -0
- package/dist/src/extensions/core/fileops-extension.js +699 -0
- package/dist/src/extensions/core/fileops-extension.js.map +1 -0
- package/dist/src/extensions/core/gateway-extension.js +730 -0
- package/dist/src/extensions/core/gateway-extension.js.map +1 -0
- package/dist/src/extensions/core/git-checkpoint.js +46 -0
- package/dist/src/extensions/core/git-checkpoint.js.map +1 -0
- package/dist/src/extensions/core/handoff-extension.js +206 -0
- package/dist/src/extensions/core/handoff-extension.js.map +1 -0
- package/dist/src/extensions/core/heartbeat-extension.js +373 -0
- package/dist/src/extensions/core/heartbeat-extension.js.map +1 -0
- package/dist/src/extensions/core/mcp-extension.js +413 -0
- package/dist/src/extensions/core/mcp-extension.js.map +1 -0
- package/dist/src/extensions/core/mode-manager-extension.js +562 -0
- package/dist/src/extensions/core/mode-manager-extension.js.map +1 -0
- package/dist/src/extensions/core/multi-channel-extension.js +435 -0
- package/dist/src/extensions/core/multi-channel-extension.js.map +1 -0
- package/dist/src/extensions/core/ollama-provider-extension.js +66 -0
- package/dist/src/extensions/core/ollama-provider-extension.js.map +1 -0
- package/dist/src/extensions/core/onboarding-extension.js +122 -0
- package/dist/src/extensions/core/onboarding-extension.js.map +1 -0
- package/dist/src/extensions/core/persona-loader-extension.js +139 -0
- package/dist/src/extensions/core/persona-loader-extension.js.map +1 -0
- package/dist/src/extensions/core/pi-notify-extension.js +70 -0
- package/dist/src/extensions/core/pi-notify-extension.js.map +1 -0
- package/dist/src/extensions/core/protected-paths.js +24 -0
- package/dist/src/extensions/core/protected-paths.js.map +1 -0
- package/dist/src/extensions/core/questionnaire-extension.js +242 -0
- package/dist/src/extensions/core/questionnaire-extension.js.map +1 -0
- package/dist/src/extensions/core/self-update-extension.js +181 -0
- package/dist/src/extensions/core/self-update-extension.js.map +1 -0
- package/dist/src/extensions/core/session-bridge-extension.js +78 -0
- package/dist/src/extensions/core/session-bridge-extension.js.map +1 -0
- package/dist/src/extensions/core/session-manager-extension.js +319 -0
- package/dist/src/extensions/core/session-manager-extension.js.map +1 -0
- package/dist/src/extensions/core/session-name-extension.js +88 -0
- package/dist/src/extensions/core/session-name-extension.js.map +1 -0
- package/dist/src/extensions/core/session-pruning-extension.js +480 -0
- package/dist/src/extensions/core/session-pruning-extension.js.map +1 -0
- package/dist/src/extensions/core/task-manager-extension.js +661 -0
- package/dist/src/extensions/core/task-manager-extension.js.map +1 -0
- package/dist/src/extensions/core/update-extension.js +438 -0
- package/dist/src/extensions/core/update-extension.js.map +1 -0
- package/dist/src/extensions/core/websearch-extension.js +463 -0
- package/dist/src/extensions/core/websearch-extension.js.map +1 -0
- package/dist/src/extensions/index.js +5 -0
- package/dist/src/extensions/index.js.map +1 -0
- package/dist/src/extensions/loader.js +80 -0
- package/dist/src/extensions/loader.js.map +1 -0
- package/dist/src/gateway/index.js +353 -0
- package/dist/src/gateway/index.js.map +1 -0
- package/dist/src/index.js +150 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/llm/anthropic.js +86 -0
- package/dist/src/llm/anthropic.js.map +1 -0
- package/dist/src/llm/index.js +9 -0
- package/dist/src/llm/index.js.map +1 -0
- package/dist/src/llm/ollama.js +113 -0
- package/dist/src/llm/ollama.js.map +1 -0
- package/dist/src/llm/router.js +145 -0
- package/dist/src/llm/router.js.map +1 -0
- package/dist/src/llm/types.js +7 -0
- package/dist/src/llm/types.js.map +1 -0
- package/dist/src/memory/index.js +5 -0
- package/dist/src/memory/index.js.map +1 -0
- package/dist/src/memory/store.js +91 -0
- package/dist/src/memory/store.js.map +1 -0
- package/dist/src/pi-config.js +80 -0
- package/dist/src/pi-config.js.map +1 -0
- package/dist/src/skills/builtin/file.js +184 -0
- package/dist/src/skills/builtin/file.js.map +1 -0
- package/dist/src/skills/builtin/shell.js +100 -0
- package/dist/src/skills/builtin/shell.js.map +1 -0
- package/dist/src/skills/builtin/subagent.js +62 -0
- package/dist/src/skills/builtin/subagent.js.map +1 -0
- package/dist/src/skills/hello.js +42 -0
- package/dist/src/skills/hello.js.map +1 -0
- package/dist/src/skills/index.js +11 -0
- package/dist/src/skills/index.js.map +1 -0
- package/dist/src/skills/loader.js +382 -0
- package/dist/src/skills/loader.js.map +1 -0
- package/dist/src/skills/types.js +8 -0
- package/dist/src/skills/types.js.map +1 -0
- package/dist/src/utils/working-dir.js +71 -0
- package/dist/src/utils/working-dir.js.map +1 -0
- package/package.json +77 -0
- package/skills/1password/SKILL.md +70 -0
- package/skills/1password/references/cli-examples.md +29 -0
- package/skills/1password/references/get-started.md +17 -0
- package/skills/apple-notes/SKILL.md +77 -0
- package/skills/apple-reminders/SKILL.md +118 -0
- package/skills/bear-notes/SKILL.md +107 -0
- package/skills/blogwatcher/SKILL.md +69 -0
- package/skills/blucli/SKILL.md +47 -0
- package/skills/bluebubbles/SKILL.md +131 -0
- package/skills/camsnap/SKILL.md +45 -0
- package/skills/canvas/SKILL.md +198 -0
- package/skills/clawhub/SKILL.md +77 -0
- package/skills/coding-agent/SKILL.md +284 -0
- package/skills/discord/SKILL.md +197 -0
- package/skills/eightctl/SKILL.md +50 -0
- package/skills/food-order/SKILL.md +48 -0
- package/skills/gemini/SKILL.md +43 -0
- package/skills/gh-issues/SKILL.md +865 -0
- package/skills/gifgrep/SKILL.md +79 -0
- package/skills/github/SKILL.md +163 -0
- package/skills/gog/SKILL.md +116 -0
- package/skills/goplaces/SKILL.md +52 -0
- package/skills/healthcheck/SKILL.md +245 -0
- package/skills/himalaya/SKILL.md +257 -0
- package/skills/himalaya/references/configuration.md +184 -0
- package/skills/himalaya/references/message-composition.md +199 -0
- package/skills/imsg/SKILL.md +122 -0
- package/skills/mcporter/SKILL.md +61 -0
- package/skills/model-usage/SKILL.md +69 -0
- package/skills/model-usage/references/codexbar-cli.md +33 -0
- package/skills/model-usage/scripts/model_usage.py +310 -0
- package/skills/nano-banana-pro/SKILL.md +58 -0
- package/skills/nano-banana-pro/scripts/generate_image.py +184 -0
- package/skills/nano-pdf/SKILL.md +38 -0
- package/skills/notion/SKILL.md +172 -0
- package/skills/obsidian/SKILL.md +81 -0
- package/skills/openai-image-gen/SKILL.md +89 -0
- package/skills/openai-image-gen/scripts/gen.py +240 -0
- package/skills/openai-whisper/SKILL.md +38 -0
- package/skills/openai-whisper-api/SKILL.md +52 -0
- package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
- package/skills/openhue/SKILL.md +112 -0
- package/skills/oracle/SKILL.md +125 -0
- package/skills/ordercli/SKILL.md +78 -0
- package/skills/peekaboo/SKILL.md +190 -0
- package/skills/sag/SKILL.md +87 -0
- package/skills/session-logs/SKILL.md +115 -0
- package/skills/sherpa-onnx-tts/SKILL.md +103 -0
- package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
- package/skills/skill-creator/SKILL.md +370 -0
- package/skills/skill-creator/license.txt +202 -0
- package/skills/skill-creator/scripts/init_skill.py +378 -0
- package/skills/skill-creator/scripts/package_skill.py +111 -0
- package/skills/skill-creator/scripts/quick_validate.py +101 -0
- package/skills/slack/SKILL.md +144 -0
- package/skills/songsee/SKILL.md +49 -0
- package/skills/sonoscli/SKILL.md +46 -0
- package/skills/spotify-player/SKILL.md +64 -0
- package/skills/summarize/SKILL.md +87 -0
- package/skills/things-mac/SKILL.md +86 -0
- package/skills/tmux/SKILL.md +153 -0
- package/skills/tmux/scripts/find-sessions.sh +112 -0
- package/skills/tmux/scripts/wait-for-text.sh +83 -0
- package/skills/trello/SKILL.md +95 -0
- package/skills/video-frames/SKILL.md +46 -0
- package/skills/video-frames/scripts/frame.sh +81 -0
- package/skills/voice-call/SKILL.md +45 -0
- package/skills/wacli/SKILL.md +72 -0
- package/skills/weather/SKILL.md +112 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session naming extension.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* User: /session-name [new-name]
|
|
6
|
+
* Agent: set_session_name tool
|
|
7
|
+
*/
|
|
8
|
+
export default function sessionNameExtension(pi) {
|
|
9
|
+
// ═══════════════════════════════════════════════════════════════
|
|
10
|
+
// USER COMMANDS
|
|
11
|
+
// ═══════════════════════════════════════════════════════════════
|
|
12
|
+
pi.registerCommand("session-name", {
|
|
13
|
+
description: "Set or show session name (usage: /session-name [new name])",
|
|
14
|
+
handler: async (args, ctx) => {
|
|
15
|
+
const name = args.trim();
|
|
16
|
+
if (name) {
|
|
17
|
+
pi.setSessionName(name);
|
|
18
|
+
ctx.ui.notify(`Session named: ${name}`, "info");
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const current = pi.getSessionName();
|
|
22
|
+
ctx.ui.notify(current ? `Session: ${current}` : "No session name set", "info");
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
// ═══════════════════════════════════════════════════════════════
|
|
27
|
+
// AGENT TOOLS
|
|
28
|
+
// ═══════════════════════════════════════════════════════════════
|
|
29
|
+
// Tool: set_session_name
|
|
30
|
+
pi.registerTool({
|
|
31
|
+
name: "set_session_name",
|
|
32
|
+
label: "set_session_name",
|
|
33
|
+
description: "Set a friendly name for the current session. Use when you want to label what you are working on.",
|
|
34
|
+
// @ts-ignore TSchema mismatch
|
|
35
|
+
parameters: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
name: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "The friendly name to give this session (e.g., 'Refactor Auth System', 'Bug Fix #123')",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
required: ["name"],
|
|
44
|
+
},
|
|
45
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
46
|
+
const { name } = params;
|
|
47
|
+
if (!name.trim()) {
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: "Error: Session name cannot be empty" }],
|
|
50
|
+
details: { success: false },
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
pi.setSessionName(name.trim());
|
|
54
|
+
if (ctx.ui?.notify) {
|
|
55
|
+
ctx.ui.notify(`Session named: ${name}`, "info");
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "text", text: `Session named: ${name}` }],
|
|
59
|
+
details: { success: true, name: name.trim() },
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
// Tool: get_session_name
|
|
64
|
+
pi.registerTool({
|
|
65
|
+
name: "get_session_name",
|
|
66
|
+
label: "get_session_name",
|
|
67
|
+
description: "Get the current session name, if one is set.",
|
|
68
|
+
// @ts-ignore TSchema mismatch
|
|
69
|
+
parameters: {
|
|
70
|
+
type: "object",
|
|
71
|
+
properties: {},
|
|
72
|
+
},
|
|
73
|
+
async execute(_toolCallId, _params, _signal, _onUpdate, _ctx) {
|
|
74
|
+
const current = pi.getSessionName();
|
|
75
|
+
return {
|
|
76
|
+
content: [{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: current
|
|
79
|
+
? `Current session name: ${current}`
|
|
80
|
+
: "No session name set"
|
|
81
|
+
}],
|
|
82
|
+
details: { success: true, name: current },
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
console.log("[SessionName] Extension loaded with commands + tools");
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=session-name-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-name-extension.js","sourceRoot":"","sources":["../../../../src/extensions/core/session-name-extension.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Pruning Extension - OpenClaw Style
|
|
3
|
+
*
|
|
4
|
+
* Manages context window limits and memory compaction
|
|
5
|
+
* Features:
|
|
6
|
+
* - History limiting (DM vs group contexts)
|
|
7
|
+
* - Context pruning based on cache TTL
|
|
8
|
+
* - Automatic compaction before hitting limits
|
|
9
|
+
* - Token counting for context windows
|
|
10
|
+
* - Branch support for multi-turn conversations
|
|
11
|
+
*/
|
|
12
|
+
import { Database } from "bun:sqlite";
|
|
13
|
+
import { join } from "path";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
import { existsSync, mkdirSync } from "fs";
|
|
16
|
+
import { parseArgs } from "../command-args.js";
|
|
17
|
+
const KOBOLD_DIR = join(homedir(), ".0xkobold");
|
|
18
|
+
const PRUNING_DB = join(KOBOLD_DIR, "pruning.db");
|
|
19
|
+
let db = null;
|
|
20
|
+
let currentConfig = null;
|
|
21
|
+
/**
|
|
22
|
+
* Initialize pruning database
|
|
23
|
+
*/
|
|
24
|
+
function initDatabase() {
|
|
25
|
+
if (db)
|
|
26
|
+
return db;
|
|
27
|
+
if (!existsSync(KOBOLD_DIR)) {
|
|
28
|
+
mkdirSync(KOBOLD_DIR, { recursive: true });
|
|
29
|
+
}
|
|
30
|
+
db = new Database(PRUNING_DB);
|
|
31
|
+
db.run("PRAGMA journal_mode = WAL;");
|
|
32
|
+
// Session configurations
|
|
33
|
+
db.run(`
|
|
34
|
+
CREATE TABLE IF NOT EXISTS session_configs (
|
|
35
|
+
id TEXT PRIMARY KEY,
|
|
36
|
+
max_history_messages INTEGER DEFAULT 100,
|
|
37
|
+
max_context_tokens INTEGER DEFAULT 8000,
|
|
38
|
+
compaction_threshold INTEGER DEFAULT 80, -- 80%
|
|
39
|
+
channel_type TEXT DEFAULT 'dm' -- dm or group
|
|
40
|
+
)
|
|
41
|
+
`);
|
|
42
|
+
// Messages with pruning metadata
|
|
43
|
+
db.run(`
|
|
44
|
+
CREATE TABLE IF NOT EXISTS message_entries (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
session_id TEXT NOT NULL,
|
|
47
|
+
role TEXT NOT NULL,
|
|
48
|
+
content TEXT NOT NULL,
|
|
49
|
+
timestamp INTEGER NOT NULL,
|
|
50
|
+
token_count INTEGER DEFAULT 0,
|
|
51
|
+
cache_ttl INTEGER, -- NULL = no cache (always keep)
|
|
52
|
+
preserved INTEGER DEFAULT 0,
|
|
53
|
+
turn_number INTEGER
|
|
54
|
+
)
|
|
55
|
+
`);
|
|
56
|
+
// Compaction rules (summaries)
|
|
57
|
+
db.run(`
|
|
58
|
+
CREATE TABLE IF NOT EXISTS compaction_rules (
|
|
59
|
+
id TEXT PRIMARY KEY,
|
|
60
|
+
session_id TEXT NOT NULL,
|
|
61
|
+
turn_start INTEGER NOT NULL,
|
|
62
|
+
turn_end INTEGER NOT NULL,
|
|
63
|
+
summary TEXT NOT NULL,
|
|
64
|
+
original_size INTEGER NOT NULL,
|
|
65
|
+
created_at INTEGER NOT NULL
|
|
66
|
+
)
|
|
67
|
+
`);
|
|
68
|
+
// Cache TTL tracking
|
|
69
|
+
db.run(`
|
|
70
|
+
CREATE TABLE IF NOT EXISTS cache_ttl (
|
|
71
|
+
message_id TEXT PRIMARY KEY,
|
|
72
|
+
ttl INTEGER NOT NULL,
|
|
73
|
+
last_accessed INTEGER NOT NULL
|
|
74
|
+
)
|
|
75
|
+
`);
|
|
76
|
+
// Indexes
|
|
77
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_messages_session ON message_entries(session_id, timestamp)`);
|
|
78
|
+
db.run(`CREATE INDEX IF NOT EXISTS idx_cache_ttl ON cache_ttl(ttl)`);
|
|
79
|
+
console.log("[SessionPruning] Database initialized");
|
|
80
|
+
return db;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Estimate token count (approximate)
|
|
84
|
+
*/
|
|
85
|
+
function estimateTokens(text) {
|
|
86
|
+
// Rough estimate: ~4 chars per token for English
|
|
87
|
+
return Math.ceil(text.length / 4);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get messages for session with TTL checking
|
|
91
|
+
*/
|
|
92
|
+
function getPrunableMessages(database, sessionId, beforeTurn) {
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
let query = `
|
|
95
|
+
SELECT m.* FROM message_entries m
|
|
96
|
+
LEFT JOIN cache_ttl c ON m.id = c.message_id
|
|
97
|
+
WHERE m.session_id = ?
|
|
98
|
+
AND m.preserved = 0
|
|
99
|
+
AND (c.ttl IS NULL OR c.ttl < ?)
|
|
100
|
+
`;
|
|
101
|
+
const params = [sessionId, now];
|
|
102
|
+
if (beforeTurn) {
|
|
103
|
+
query += " AND m.turn_number <= ?";
|
|
104
|
+
params.push(beforeTurn);
|
|
105
|
+
}
|
|
106
|
+
query += " ORDER BY m.timestamp";
|
|
107
|
+
const rows = database.query(query).all(...params);
|
|
108
|
+
return rows.map(r => ({
|
|
109
|
+
id: r.id,
|
|
110
|
+
sessionId: r.session_id,
|
|
111
|
+
role: r.role,
|
|
112
|
+
content: r.content,
|
|
113
|
+
timestamp: r.timestamp,
|
|
114
|
+
tokenCount: r.token_count,
|
|
115
|
+
cacheTTL: r.cache_ttl,
|
|
116
|
+
preserved: r.preserved === 1,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Compact old messages into summary
|
|
121
|
+
*/
|
|
122
|
+
async function compactMessages(database, sessionId, startTurn, endTurn, aiSummary) {
|
|
123
|
+
const id = `compact-${Date.now()}`;
|
|
124
|
+
const now = Date.now();
|
|
125
|
+
// Calculate original size
|
|
126
|
+
const messages = database.query("SELECT SUM(token_count) as total FROM message_entries WHERE session_id = ? AND turn_number >= ? AND turn_number <= ?"
|
|
127
|
+
// @ts-ignore SQLite binding
|
|
128
|
+
).get([sessionId, startTurn, endTurn]);
|
|
129
|
+
const originalSize = messages?.total || 0;
|
|
130
|
+
// Store compaction rule
|
|
131
|
+
// @ts-ignore SQLite binding
|
|
132
|
+
database.run(`INSERT INTO compaction_rules (id, session_id, turn_start, turn_end, summary, original_size, created_at)
|
|
133
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, sessionId, startTurn, endTurn, aiSummary, originalSize, now]);
|
|
134
|
+
// Mark original messages as compacted (soft delete)
|
|
135
|
+
// @ts-ignore SQLite binding
|
|
136
|
+
database.run("UPDATE message_entries SET preserved = -1 WHERE session_id = ? AND turn_number >= ? AND turn_number <= ?", [sessionId, startTurn, endTurn]);
|
|
137
|
+
console.log(`[SessionPruning] Compacted turns ${startTurn}-${endTurn} → ${estimateTokens(aiSummary)} tokens`);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Check if compaction needed
|
|
141
|
+
*/
|
|
142
|
+
function shouldCompact(database, sessionId, threshold) {
|
|
143
|
+
const stats = database.query("SELECT SUM(token_count) as total FROM message_entries WHERE session_id = ? AND preserved >= 0"
|
|
144
|
+
// @ts-ignore SQLite binding
|
|
145
|
+
).get([sessionId]);
|
|
146
|
+
const currentTokens = stats?.total || 0;
|
|
147
|
+
// @ts-ignore SQLite binding
|
|
148
|
+
const config = database.query("SELECT max_context_tokens FROM session_configs WHERE id = ?").get([sessionId]);
|
|
149
|
+
const maxTokens = config?.max_context_tokens || 8000;
|
|
150
|
+
const percentage = (currentTokens / maxTokens) * 100;
|
|
151
|
+
if (percentage > threshold) {
|
|
152
|
+
console.log(`[SessionPruning] Context at ${percentage.toFixed(1)}% (threshold: ${threshold}%)`);
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get effective history for session (respecting compactions)
|
|
159
|
+
*/
|
|
160
|
+
function getEffectiveHistory(database, sessionId) {
|
|
161
|
+
// Get compaction summaries first
|
|
162
|
+
const compactions = database.query("SELECT * FROM compaction_rules WHERE session_id = ? ORDER BY turn_start").all(sessionId);
|
|
163
|
+
// Get remaining messages
|
|
164
|
+
const messages = database.query("SELECT * FROM message_entries WHERE session_id = ? AND preserved >= 0 ORDER BY timestamp").all(sessionId);
|
|
165
|
+
// Merge: summaries + remaining messages
|
|
166
|
+
const result = [];
|
|
167
|
+
for (const compaction of compactions) {
|
|
168
|
+
result.push({
|
|
169
|
+
role: "system",
|
|
170
|
+
content: `[Previous conversation summary (turns ${compaction.turn_start}-${compaction.turn_end}): ${compaction.summary}]`,
|
|
171
|
+
type: "compaction",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
for (const msg of messages) {
|
|
175
|
+
result.push({
|
|
176
|
+
role: msg.role,
|
|
177
|
+
content: msg.content,
|
|
178
|
+
timestamp: msg.timestamp,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Session Pruning Extension
|
|
185
|
+
*/
|
|
186
|
+
export default function sessionPruningExtension(pi) {
|
|
187
|
+
const database = initDatabase();
|
|
188
|
+
let currentSessionId = null;
|
|
189
|
+
let turnNumber = 0;
|
|
190
|
+
// ═══════════════════════════════════════════════════════════════
|
|
191
|
+
// EVENT HANDLERS
|
|
192
|
+
// ═══════════════════════════════════════════════════════════════
|
|
193
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
194
|
+
currentSessionId = process.env.KOBOLD_SESSION_ID || null;
|
|
195
|
+
turnNumber = 0;
|
|
196
|
+
if (!currentSessionId)
|
|
197
|
+
return;
|
|
198
|
+
// Initialize config for this session
|
|
199
|
+
// @ts-ignore SQLite binding
|
|
200
|
+
const existing = database.query("SELECT * FROM session_configs WHERE id = ?").get([currentSessionId]);
|
|
201
|
+
if (!existing) {
|
|
202
|
+
const channelType = process.env.KOBOLD_CHANNEL_TYPE || "dm";
|
|
203
|
+
const maxMessages = channelType === "group" ? 50 : 100; // Groups get less history
|
|
204
|
+
// @ts-ignore SQLite binding
|
|
205
|
+
database.run(`INSERT INTO session_configs (id, max_history_messages, max_context_tokens, compaction_threshold, channel_type)
|
|
206
|
+
VALUES (?, ?, ?, ?, ?)`, [currentSessionId,
|
|
207
|
+
maxMessages,
|
|
208
|
+
8000,
|
|
209
|
+
80,
|
|
210
|
+
channelType]);
|
|
211
|
+
console.log(`[SessionPruning] Configured session ${currentSessionId.slice(0, 8)}... as ${channelType}`);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
pi.on("turn_start", async () => {
|
|
215
|
+
turnNumber++;
|
|
216
|
+
if (!currentSessionId)
|
|
217
|
+
return;
|
|
218
|
+
// Check if we need compaction before this turn
|
|
219
|
+
// @ts-ignore SQLite binding
|
|
220
|
+
const config = database.query("SELECT compaction_threshold FROM session_configs WHERE id = ?")
|
|
221
|
+
// @ts-ignore SQLite binding
|
|
222
|
+
.get([currentSessionId]);
|
|
223
|
+
if (config && shouldCompact(database, currentSessionId, config.compaction_threshold)) {
|
|
224
|
+
// Signal that compaction is needed
|
|
225
|
+
// @ts-ignore sendMessage type
|
|
226
|
+
pi.sendMessage({
|
|
227
|
+
customType: "session.compaction_needed",
|
|
228
|
+
content: [{ type: "text", text: "Context window approaching limit" }],
|
|
229
|
+
// @ts-ignore Content type
|
|
230
|
+
display: { type: "text", text: "⚠️ Context window approaching limit" },
|
|
231
|
+
details: { sessionId: currentSessionId, turn: turnNumber },
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
// ═══════════════════════════════════════════════════════════════
|
|
236
|
+
// COMMANDS
|
|
237
|
+
// ═══════════════════════════════════════════════════════════════
|
|
238
|
+
pi.registerCommand("session-config", {
|
|
239
|
+
description: "Show or set session pruning config",
|
|
240
|
+
// @ts-ignore Command args property
|
|
241
|
+
args: [
|
|
242
|
+
{ name: "max-messages", description: "Max history messages", required: false },
|
|
243
|
+
{ name: "max-tokens", description: "Max context tokens", required: false },
|
|
244
|
+
],
|
|
245
|
+
handler: async (args, ctx) => {
|
|
246
|
+
const parsed = parseArgs(args, [
|
|
247
|
+
{ name: "max-messages", description: "Max history messages", required: false },
|
|
248
|
+
{ name: "max-tokens", description: "Max context tokens", required: false },
|
|
249
|
+
]);
|
|
250
|
+
if (!currentSessionId) {
|
|
251
|
+
ctx.ui?.notify?.("No active session", "warning");
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (parsed["max-messages"] || parsed["max-tokens"]) {
|
|
255
|
+
// Update config
|
|
256
|
+
if (parsed["max-messages"]) {
|
|
257
|
+
// @ts-ignore SQLite binding
|
|
258
|
+
database.run("UPDATE session_configs SET max_history_messages = ? WHERE id = ?", [parseInt(String(parsed["max-messages"])),
|
|
259
|
+
currentSessionId]);
|
|
260
|
+
}
|
|
261
|
+
if (parsed["max-tokens"]) {
|
|
262
|
+
// @ts-ignore SQLite binding
|
|
263
|
+
database.run("UPDATE session_configs SET max_context_tokens = ? WHERE id = ?", [parseInt(String(parsed["max-tokens"])),
|
|
264
|
+
currentSessionId]);
|
|
265
|
+
}
|
|
266
|
+
// @ts-ignore Notify type
|
|
267
|
+
ctx.ui?.notify?.("Session config updated", "success");
|
|
268
|
+
}
|
|
269
|
+
// Show current config
|
|
270
|
+
// @ts-ignore SQLite binding
|
|
271
|
+
const config = database.query("SELECT * FROM session_configs WHERE id = ?").get([currentSessionId]);
|
|
272
|
+
if (!config) {
|
|
273
|
+
ctx.ui?.notify?.("Session config not found", "error");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const usage = database.query("SELECT SUM(token_count) as total FROM message_entries WHERE session_id = ? AND preserved >= 0"
|
|
277
|
+
// @ts-ignore SQLite binding
|
|
278
|
+
).get([currentSessionId]);
|
|
279
|
+
const lines = [
|
|
280
|
+
"📊 Session Pruning Config",
|
|
281
|
+
"",
|
|
282
|
+
`Max Messages: ${config.max_history_messages}`,
|
|
283
|
+
`Max Tokens: ${config.max_context_tokens}`,
|
|
284
|
+
`Compaction Threshold: ${config.compaction_threshold}%`,
|
|
285
|
+
`Channel Type: ${config.channel_type}`,
|
|
286
|
+
"",
|
|
287
|
+
`Current Usage: ${usage?.total || 0} tokens`,
|
|
288
|
+
];
|
|
289
|
+
ctx.ui?.notify?.(lines.join("\n"), "info");
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
pi.registerCommand("compact", {
|
|
293
|
+
description: "Manually compact old messages",
|
|
294
|
+
// @ts-ignore Command args property
|
|
295
|
+
args: [
|
|
296
|
+
{ name: "turns", description: "Number of recent turns to keep", required: true },
|
|
297
|
+
],
|
|
298
|
+
handler: async (args, ctx) => {
|
|
299
|
+
if (!currentSessionId) {
|
|
300
|
+
ctx.ui?.notify?.("No active session", "warning");
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const parsed = parseArgs(args, [
|
|
304
|
+
{ name: "turns", description: "Number of recent turns to keep", required: true },
|
|
305
|
+
]);
|
|
306
|
+
const keepTurns = parseInt(String(parsed.turns)) || 10;
|
|
307
|
+
if (turnNumber <= keepTurns) {
|
|
308
|
+
ctx.ui?.notify?.("Not enough turns to compact", "warning");
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const compactStart = 1;
|
|
312
|
+
const compactEnd = turnNumber - keepTurns;
|
|
313
|
+
ctx.ui?.notify?.(`Compacting turns ${compactStart}-${compactEnd}...`, "info");
|
|
314
|
+
// In real implementation, would call AI to summarize
|
|
315
|
+
const summary = `Previous conversation with ${compactEnd} turns`;
|
|
316
|
+
await compactMessages(database, currentSessionId, compactStart, compactEnd, summary);
|
|
317
|
+
// @ts-ignore Notify type
|
|
318
|
+
ctx.ui?.notify?.(`Compacted turns ${compactStart}-${compactEnd}. Kept last ${keepTurns} turns.`, "success");
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
pi.registerCommand("prune-cache", {
|
|
322
|
+
description: "Remove expired cached messages",
|
|
323
|
+
handler: async (_args, ctx) => {
|
|
324
|
+
if (!currentSessionId) {
|
|
325
|
+
ctx.ui?.notify?.("No active session", "warning");
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
// Delete expired cached messages
|
|
330
|
+
// @ts-ignore SQLite binding
|
|
331
|
+
const result = database.run(`DELETE FROM message_entries
|
|
332
|
+
WHERE session_id = ?
|
|
333
|
+
AND id IN (SELECT message_id FROM cache_ttl WHERE ttl < ?)`, [currentSessionId,
|
|
334
|
+
now]);
|
|
335
|
+
// Clean up cache_ttl table
|
|
336
|
+
// @ts-ignore SQLite binding
|
|
337
|
+
database.run("DELETE FROM cache_ttl WHERE ttl < ?", now);
|
|
338
|
+
// @ts-ignore Notify type
|
|
339
|
+
ctx.ui?.notify?.(`Pruned ${result.changes} expired messages from cache`, "success");
|
|
340
|
+
},
|
|
341
|
+
});
|
|
342
|
+
pi.registerCommand("compactions", {
|
|
343
|
+
description: "List compaction summaries",
|
|
344
|
+
handler: async (_args, ctx) => {
|
|
345
|
+
if (!currentSessionId) {
|
|
346
|
+
ctx.ui?.notify?.("No active session", "warning");
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const compactions = database.query("SELECT * FROM compaction_rules WHERE session_id = ? ORDER BY turn_start").all(currentSessionId);
|
|
350
|
+
if (compactions.length === 0) {
|
|
351
|
+
ctx.ui?.notify?.("No compactions yet", "info");
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
const lines = ["📦 Compaction History\n"];
|
|
355
|
+
for (const c of compactions) {
|
|
356
|
+
lines.push(`Turns ${c.turn_start}-${c.turn_end}: ${c.summary.slice(0, 60)}...`);
|
|
357
|
+
lines.push(` Original: ${c.original_size} tokens → Summary: ${estimateTokens(c.summary)} tokens`);
|
|
358
|
+
}
|
|
359
|
+
ctx.ui?.notify?.(lines.join("\n"), "info");
|
|
360
|
+
},
|
|
361
|
+
});
|
|
362
|
+
// ═══════════════════════════════════════════════════════════════
|
|
363
|
+
// TOOLS
|
|
364
|
+
// ═══════════════════════════════════════════════════════════════
|
|
365
|
+
pi.registerTool({
|
|
366
|
+
name: "session_compact",
|
|
367
|
+
description: "Compact old conversation history to save context window space",
|
|
368
|
+
// @ts-ignore TSchema mismatch
|
|
369
|
+
parameters: {
|
|
370
|
+
type: "object",
|
|
371
|
+
properties: {
|
|
372
|
+
preserve_turns: {
|
|
373
|
+
type: "number",
|
|
374
|
+
description: "Number of recent turns to preserve (default: 10)",
|
|
375
|
+
default: 10,
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
},
|
|
379
|
+
async execute(args) {
|
|
380
|
+
if (!currentSessionId) {
|
|
381
|
+
return {
|
|
382
|
+
content: [{ type: "text", text: "No active session" }],
|
|
383
|
+
details: { error: "no_session" },
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const preserve = args.preserve_turns || 10;
|
|
387
|
+
if (turnNumber <= preserve) {
|
|
388
|
+
return {
|
|
389
|
+
content: [{ type: "text", text: "Not enough turns to compact" }],
|
|
390
|
+
details: { current_turns: turnNumber },
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
// AI would generate actual summary
|
|
394
|
+
const summary = `Summary of turns 1-${turnNumber - preserve}`;
|
|
395
|
+
await compactMessages(database, currentSessionId, 1, turnNumber - preserve, summary);
|
|
396
|
+
return {
|
|
397
|
+
content: [
|
|
398
|
+
{ type: "text", text: `Compacted to ${preserve} turns. Old history summarized.` },
|
|
399
|
+
],
|
|
400
|
+
details: {
|
|
401
|
+
preserved: preserve,
|
|
402
|
+
compacted: turnNumber - preserve,
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
},
|
|
406
|
+
});
|
|
407
|
+
pi.registerTool({
|
|
408
|
+
name: "session_stats",
|
|
409
|
+
description: "Get session context window statistics",
|
|
410
|
+
// @ts-ignore TSchema type mismatch
|
|
411
|
+
// @ts-ignore TSchema mismatch
|
|
412
|
+
parameters: { type: "object", properties: {} },
|
|
413
|
+
async execute() {
|
|
414
|
+
if (!currentSessionId) {
|
|
415
|
+
return {
|
|
416
|
+
content: [{ type: "text", text: "No active session" }],
|
|
417
|
+
details: { error: "no_session" },
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
// @ts-ignore SQLite binding
|
|
421
|
+
const config = database.query("SELECT * FROM session_configs WHERE id = ?")
|
|
422
|
+
// @ts-ignore SQLite binding
|
|
423
|
+
.get([currentSessionId]);
|
|
424
|
+
const usage = database.query("SELECT COUNT(*) as count, SUM(token_count) as tokens FROM message_entries WHERE session_id = ? AND preserved >= 0")
|
|
425
|
+
// @ts-ignore SQLite binding
|
|
426
|
+
.get([currentSessionId]);
|
|
427
|
+
const compactCount = database.query("SELECT COUNT(*) as count FROM compaction_rules WHERE session_id = ?")
|
|
428
|
+
// @ts-ignore SQLite binding
|
|
429
|
+
.get([currentSessionId]);
|
|
430
|
+
const percentage = config?.max_context_tokens
|
|
431
|
+
? Math.round((usage?.tokens / config.max_context_tokens) * 100)
|
|
432
|
+
: 0;
|
|
433
|
+
return {
|
|
434
|
+
content: [
|
|
435
|
+
{ type: "text", text: `Session Context:\n` +
|
|
436
|
+
`Messages: ${usage?.count || 0}\n` +
|
|
437
|
+
`Tokens: ${usage?.tokens || 0} / ${config?.max_context_tokens || 8000} (${percentage}%)\n` +
|
|
438
|
+
`Compactions: ${compactCount?.count || 0}\n` +
|
|
439
|
+
`Turn: ${turnNumber}`
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
details: {
|
|
443
|
+
messages: usage?.count,
|
|
444
|
+
tokens: usage?.tokens,
|
|
445
|
+
max_tokens: config?.max_context_tokens,
|
|
446
|
+
percentage,
|
|
447
|
+
compactions: compactCount?.count,
|
|
448
|
+
turn: turnNumber,
|
|
449
|
+
},
|
|
450
|
+
};
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
// Status bar
|
|
454
|
+
// @ts-ignore ExtensionAPI property
|
|
455
|
+
// pi.registerStatusBarItem("context", {
|
|
456
|
+
// render() {
|
|
457
|
+
// if (!currentSessionId) return "";
|
|
458
|
+
//
|
|
459
|
+
// // @ts-ignore SQLite binding
|
|
460
|
+
// const config = database.query("SELECT max_context_tokens FROM session_configs WHERE id = ?")
|
|
461
|
+
// // @ts-ignore SQLite binding
|
|
462
|
+
// .get([currentSessionId]) as any;
|
|
463
|
+
// const usage = database.query(
|
|
464
|
+
// "SELECT SUM(token_count) as total FROM message_entries WHERE session_id = ? AND preserved >= 0"
|
|
465
|
+
// )
|
|
466
|
+
// // @ts-ignore SQLite binding
|
|
467
|
+
// .get([currentSessionId]) as any;
|
|
468
|
+
//
|
|
469
|
+
// if (!config) return "";
|
|
470
|
+
//
|
|
471
|
+
// const percentage = Math.round(((usage?.total || 0) / config.max_context_tokens) * 100);
|
|
472
|
+
// const icon = percentage > 90 ? "🔴" : percentage > 75 ? "🟡" : "🟢";
|
|
473
|
+
//
|
|
474
|
+
// return `${icon} ${percentage}%`;
|
|
475
|
+
// },
|
|
476
|
+
// });
|
|
477
|
+
console.log("[SessionPruning] OpenClaw-style context management loaded");
|
|
478
|
+
console.log("[SessionPruning] Commands: /session-config, /compact, /prune-cache, /compactions");
|
|
479
|
+
}
|
|
480
|
+
//# sourceMappingURL=session-pruning-extension.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-pruning-extension.js","sourceRoot":"","sources":["../../../../src/extensions/core/session-pruning-extension.ts"],"names":[],"mappings":"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"}
|