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.
Files changed (258) hide show
  1. package/.agents/skills/nextjs-best-practices/SKILL.md +208 -0
  2. package/.agents/skills/sql-optimization-patterns/SKILL.md +509 -0
  3. package/HEARTBEAT.md +45 -0
  4. package/README.md +197 -0
  5. package/USAGE.md +191 -0
  6. package/dist/package.json +77 -0
  7. package/dist/src/agent/pi-adapter.js +307 -0
  8. package/dist/src/agent/pi-adapter.js.map +1 -0
  9. package/dist/src/agent/tool-adapter.js +86 -0
  10. package/dist/src/agent/tool-adapter.js.map +1 -0
  11. package/dist/src/approval/queue.js +114 -0
  12. package/dist/src/approval/queue.js.map +1 -0
  13. package/dist/src/ascii-kobold.js +76 -0
  14. package/dist/src/ascii-kobold.js.map +1 -0
  15. package/dist/src/cli/client.js +217 -0
  16. package/dist/src/cli/client.js.map +1 -0
  17. package/dist/src/cli/commands/agent.js +272 -0
  18. package/dist/src/cli/commands/agent.js.map +1 -0
  19. package/dist/src/cli/commands/chat.js +234 -0
  20. package/dist/src/cli/commands/chat.js.map +1 -0
  21. package/dist/src/cli/commands/config.js +202 -0
  22. package/dist/src/cli/commands/config.js.map +1 -0
  23. package/dist/src/cli/commands/daemon.js +203 -0
  24. package/dist/src/cli/commands/daemon.js.map +1 -0
  25. package/dist/src/cli/commands/gateway.js +184 -0
  26. package/dist/src/cli/commands/gateway.js.map +1 -0
  27. package/dist/src/cli/commands/init.js +175 -0
  28. package/dist/src/cli/commands/init.js.map +1 -0
  29. package/dist/src/cli/commands/kobold.js +21 -0
  30. package/dist/src/cli/commands/kobold.js.map +1 -0
  31. package/dist/src/cli/commands/logs.js +27 -0
  32. package/dist/src/cli/commands/logs.js.map +1 -0
  33. package/dist/src/cli/commands/mode.js +121 -0
  34. package/dist/src/cli/commands/mode.js.map +1 -0
  35. package/dist/src/cli/commands/persona.js +261 -0
  36. package/dist/src/cli/commands/persona.js.map +1 -0
  37. package/dist/src/cli/commands/start.js +66 -0
  38. package/dist/src/cli/commands/start.js.map +1 -0
  39. package/dist/src/cli/commands/status.js +117 -0
  40. package/dist/src/cli/commands/status.js.map +1 -0
  41. package/dist/src/cli/commands/stop.js +27 -0
  42. package/dist/src/cli/commands/stop.js.map +1 -0
  43. package/dist/src/cli/commands/system.js +128 -0
  44. package/dist/src/cli/commands/system.js.map +1 -0
  45. package/dist/src/cli/commands/tui.js +103 -0
  46. package/dist/src/cli/commands/tui.js.map +1 -0
  47. package/dist/src/cli/commands/update.js +133 -0
  48. package/dist/src/cli/commands/update.js.map +1 -0
  49. package/dist/src/cli/extensions/discord.js +113 -0
  50. package/dist/src/cli/extensions/discord.js.map +1 -0
  51. package/dist/src/cli/extensions/env.js +91 -0
  52. package/dist/src/cli/extensions/env.js.map +1 -0
  53. package/dist/src/cli/extensions/heartbeat.js +78 -0
  54. package/dist/src/cli/extensions/heartbeat.js.map +1 -0
  55. package/dist/src/cli/index.js +24 -0
  56. package/dist/src/cli/index.js.map +1 -0
  57. package/dist/src/cli/program.js +70 -0
  58. package/dist/src/cli/program.js.map +1 -0
  59. package/dist/src/cli/repl.js +184 -0
  60. package/dist/src/cli/repl.js.map +1 -0
  61. package/dist/src/cli/shared/discord-service.js +102 -0
  62. package/dist/src/cli/shared/discord-service.js.map +1 -0
  63. package/dist/src/config/index.js +10 -0
  64. package/dist/src/config/index.js.map +1 -0
  65. package/dist/src/config/loader.js +401 -0
  66. package/dist/src/config/loader.js.map +1 -0
  67. package/dist/src/config/paths.js +84 -0
  68. package/dist/src/config/paths.js.map +1 -0
  69. package/dist/src/config/types.js +8 -0
  70. package/dist/src/config/types.js.map +1 -0
  71. package/dist/src/context-detector.js +60 -0
  72. package/dist/src/context-detector.js.map +1 -0
  73. package/dist/src/discord/index.js +376 -0
  74. package/dist/src/discord/index.js.map +1 -0
  75. package/dist/src/event-bus/index.js +97 -0
  76. package/dist/src/event-bus/index.js.map +1 -0
  77. package/dist/src/extensions/command-args.js +68 -0
  78. package/dist/src/extensions/command-args.js.map +1 -0
  79. package/dist/src/extensions/core/agent-registry-extension.js +541 -0
  80. package/dist/src/extensions/core/agent-registry-extension.js.map +1 -0
  81. package/dist/src/extensions/core/agent-worker.js +148 -0
  82. package/dist/src/extensions/core/agent-worker.js.map +1 -0
  83. package/dist/src/extensions/core/compaction-safeguard.js +154 -0
  84. package/dist/src/extensions/core/compaction-safeguard.js.map +1 -0
  85. package/dist/src/extensions/core/confirm-destructive.js +43 -0
  86. package/dist/src/extensions/core/confirm-destructive.js.map +1 -0
  87. package/dist/src/extensions/core/context-aware-extension.js +124 -0
  88. package/dist/src/extensions/core/context-aware-extension.js.map +1 -0
  89. package/dist/src/extensions/core/context-pruning/extension.js +124 -0
  90. package/dist/src/extensions/core/context-pruning/extension.js.map +1 -0
  91. package/dist/src/extensions/core/context-pruning/pruner.js +312 -0
  92. package/dist/src/extensions/core/context-pruning/pruner.js.map +1 -0
  93. package/dist/src/extensions/core/context-pruning/runtime.js +48 -0
  94. package/dist/src/extensions/core/context-pruning/runtime.js.map +1 -0
  95. package/dist/src/extensions/core/context-pruning/settings.js +105 -0
  96. package/dist/src/extensions/core/context-pruning/settings.js.map +1 -0
  97. package/dist/src/extensions/core/dirty-repo-guard.js +42 -0
  98. package/dist/src/extensions/core/dirty-repo-guard.js.map +1 -0
  99. package/dist/src/extensions/core/discord-channel-extension.js +205 -0
  100. package/dist/src/extensions/core/discord-channel-extension.js.map +1 -0
  101. package/dist/src/extensions/core/discord-extension.js +142 -0
  102. package/dist/src/extensions/core/discord-extension.js.map +1 -0
  103. package/dist/src/extensions/core/env-loader-extension.js +157 -0
  104. package/dist/src/extensions/core/env-loader-extension.js.map +1 -0
  105. package/dist/src/extensions/core/fileops-extension.js +699 -0
  106. package/dist/src/extensions/core/fileops-extension.js.map +1 -0
  107. package/dist/src/extensions/core/gateway-extension.js +730 -0
  108. package/dist/src/extensions/core/gateway-extension.js.map +1 -0
  109. package/dist/src/extensions/core/git-checkpoint.js +46 -0
  110. package/dist/src/extensions/core/git-checkpoint.js.map +1 -0
  111. package/dist/src/extensions/core/handoff-extension.js +206 -0
  112. package/dist/src/extensions/core/handoff-extension.js.map +1 -0
  113. package/dist/src/extensions/core/heartbeat-extension.js +373 -0
  114. package/dist/src/extensions/core/heartbeat-extension.js.map +1 -0
  115. package/dist/src/extensions/core/mcp-extension.js +413 -0
  116. package/dist/src/extensions/core/mcp-extension.js.map +1 -0
  117. package/dist/src/extensions/core/mode-manager-extension.js +562 -0
  118. package/dist/src/extensions/core/mode-manager-extension.js.map +1 -0
  119. package/dist/src/extensions/core/multi-channel-extension.js +435 -0
  120. package/dist/src/extensions/core/multi-channel-extension.js.map +1 -0
  121. package/dist/src/extensions/core/ollama-provider-extension.js +66 -0
  122. package/dist/src/extensions/core/ollama-provider-extension.js.map +1 -0
  123. package/dist/src/extensions/core/onboarding-extension.js +122 -0
  124. package/dist/src/extensions/core/onboarding-extension.js.map +1 -0
  125. package/dist/src/extensions/core/persona-loader-extension.js +139 -0
  126. package/dist/src/extensions/core/persona-loader-extension.js.map +1 -0
  127. package/dist/src/extensions/core/pi-notify-extension.js +70 -0
  128. package/dist/src/extensions/core/pi-notify-extension.js.map +1 -0
  129. package/dist/src/extensions/core/protected-paths.js +24 -0
  130. package/dist/src/extensions/core/protected-paths.js.map +1 -0
  131. package/dist/src/extensions/core/questionnaire-extension.js +242 -0
  132. package/dist/src/extensions/core/questionnaire-extension.js.map +1 -0
  133. package/dist/src/extensions/core/self-update-extension.js +181 -0
  134. package/dist/src/extensions/core/self-update-extension.js.map +1 -0
  135. package/dist/src/extensions/core/session-bridge-extension.js +78 -0
  136. package/dist/src/extensions/core/session-bridge-extension.js.map +1 -0
  137. package/dist/src/extensions/core/session-manager-extension.js +319 -0
  138. package/dist/src/extensions/core/session-manager-extension.js.map +1 -0
  139. package/dist/src/extensions/core/session-name-extension.js +88 -0
  140. package/dist/src/extensions/core/session-name-extension.js.map +1 -0
  141. package/dist/src/extensions/core/session-pruning-extension.js +480 -0
  142. package/dist/src/extensions/core/session-pruning-extension.js.map +1 -0
  143. package/dist/src/extensions/core/task-manager-extension.js +661 -0
  144. package/dist/src/extensions/core/task-manager-extension.js.map +1 -0
  145. package/dist/src/extensions/core/update-extension.js +438 -0
  146. package/dist/src/extensions/core/update-extension.js.map +1 -0
  147. package/dist/src/extensions/core/websearch-extension.js +463 -0
  148. package/dist/src/extensions/core/websearch-extension.js.map +1 -0
  149. package/dist/src/extensions/index.js +5 -0
  150. package/dist/src/extensions/index.js.map +1 -0
  151. package/dist/src/extensions/loader.js +80 -0
  152. package/dist/src/extensions/loader.js.map +1 -0
  153. package/dist/src/gateway/index.js +353 -0
  154. package/dist/src/gateway/index.js.map +1 -0
  155. package/dist/src/index.js +150 -0
  156. package/dist/src/index.js.map +1 -0
  157. package/dist/src/llm/anthropic.js +86 -0
  158. package/dist/src/llm/anthropic.js.map +1 -0
  159. package/dist/src/llm/index.js +9 -0
  160. package/dist/src/llm/index.js.map +1 -0
  161. package/dist/src/llm/ollama.js +113 -0
  162. package/dist/src/llm/ollama.js.map +1 -0
  163. package/dist/src/llm/router.js +145 -0
  164. package/dist/src/llm/router.js.map +1 -0
  165. package/dist/src/llm/types.js +7 -0
  166. package/dist/src/llm/types.js.map +1 -0
  167. package/dist/src/memory/index.js +5 -0
  168. package/dist/src/memory/index.js.map +1 -0
  169. package/dist/src/memory/store.js +91 -0
  170. package/dist/src/memory/store.js.map +1 -0
  171. package/dist/src/pi-config.js +80 -0
  172. package/dist/src/pi-config.js.map +1 -0
  173. package/dist/src/skills/builtin/file.js +184 -0
  174. package/dist/src/skills/builtin/file.js.map +1 -0
  175. package/dist/src/skills/builtin/shell.js +100 -0
  176. package/dist/src/skills/builtin/shell.js.map +1 -0
  177. package/dist/src/skills/builtin/subagent.js +62 -0
  178. package/dist/src/skills/builtin/subagent.js.map +1 -0
  179. package/dist/src/skills/hello.js +42 -0
  180. package/dist/src/skills/hello.js.map +1 -0
  181. package/dist/src/skills/index.js +11 -0
  182. package/dist/src/skills/index.js.map +1 -0
  183. package/dist/src/skills/loader.js +382 -0
  184. package/dist/src/skills/loader.js.map +1 -0
  185. package/dist/src/skills/types.js +8 -0
  186. package/dist/src/skills/types.js.map +1 -0
  187. package/dist/src/utils/working-dir.js +71 -0
  188. package/dist/src/utils/working-dir.js.map +1 -0
  189. package/package.json +77 -0
  190. package/skills/1password/SKILL.md +70 -0
  191. package/skills/1password/references/cli-examples.md +29 -0
  192. package/skills/1password/references/get-started.md +17 -0
  193. package/skills/apple-notes/SKILL.md +77 -0
  194. package/skills/apple-reminders/SKILL.md +118 -0
  195. package/skills/bear-notes/SKILL.md +107 -0
  196. package/skills/blogwatcher/SKILL.md +69 -0
  197. package/skills/blucli/SKILL.md +47 -0
  198. package/skills/bluebubbles/SKILL.md +131 -0
  199. package/skills/camsnap/SKILL.md +45 -0
  200. package/skills/canvas/SKILL.md +198 -0
  201. package/skills/clawhub/SKILL.md +77 -0
  202. package/skills/coding-agent/SKILL.md +284 -0
  203. package/skills/discord/SKILL.md +197 -0
  204. package/skills/eightctl/SKILL.md +50 -0
  205. package/skills/food-order/SKILL.md +48 -0
  206. package/skills/gemini/SKILL.md +43 -0
  207. package/skills/gh-issues/SKILL.md +865 -0
  208. package/skills/gifgrep/SKILL.md +79 -0
  209. package/skills/github/SKILL.md +163 -0
  210. package/skills/gog/SKILL.md +116 -0
  211. package/skills/goplaces/SKILL.md +52 -0
  212. package/skills/healthcheck/SKILL.md +245 -0
  213. package/skills/himalaya/SKILL.md +257 -0
  214. package/skills/himalaya/references/configuration.md +184 -0
  215. package/skills/himalaya/references/message-composition.md +199 -0
  216. package/skills/imsg/SKILL.md +122 -0
  217. package/skills/mcporter/SKILL.md +61 -0
  218. package/skills/model-usage/SKILL.md +69 -0
  219. package/skills/model-usage/references/codexbar-cli.md +33 -0
  220. package/skills/model-usage/scripts/model_usage.py +310 -0
  221. package/skills/nano-banana-pro/SKILL.md +58 -0
  222. package/skills/nano-banana-pro/scripts/generate_image.py +184 -0
  223. package/skills/nano-pdf/SKILL.md +38 -0
  224. package/skills/notion/SKILL.md +172 -0
  225. package/skills/obsidian/SKILL.md +81 -0
  226. package/skills/openai-image-gen/SKILL.md +89 -0
  227. package/skills/openai-image-gen/scripts/gen.py +240 -0
  228. package/skills/openai-whisper/SKILL.md +38 -0
  229. package/skills/openai-whisper-api/SKILL.md +52 -0
  230. package/skills/openai-whisper-api/scripts/transcribe.sh +85 -0
  231. package/skills/openhue/SKILL.md +112 -0
  232. package/skills/oracle/SKILL.md +125 -0
  233. package/skills/ordercli/SKILL.md +78 -0
  234. package/skills/peekaboo/SKILL.md +190 -0
  235. package/skills/sag/SKILL.md +87 -0
  236. package/skills/session-logs/SKILL.md +115 -0
  237. package/skills/sherpa-onnx-tts/SKILL.md +103 -0
  238. package/skills/sherpa-onnx-tts/bin/sherpa-onnx-tts +178 -0
  239. package/skills/skill-creator/SKILL.md +370 -0
  240. package/skills/skill-creator/license.txt +202 -0
  241. package/skills/skill-creator/scripts/init_skill.py +378 -0
  242. package/skills/skill-creator/scripts/package_skill.py +111 -0
  243. package/skills/skill-creator/scripts/quick_validate.py +101 -0
  244. package/skills/slack/SKILL.md +144 -0
  245. package/skills/songsee/SKILL.md +49 -0
  246. package/skills/sonoscli/SKILL.md +46 -0
  247. package/skills/spotify-player/SKILL.md +64 -0
  248. package/skills/summarize/SKILL.md +87 -0
  249. package/skills/things-mac/SKILL.md +86 -0
  250. package/skills/tmux/SKILL.md +153 -0
  251. package/skills/tmux/scripts/find-sessions.sh +112 -0
  252. package/skills/tmux/scripts/wait-for-text.sh +83 -0
  253. package/skills/trello/SKILL.md +95 -0
  254. package/skills/video-frames/SKILL.md +46 -0
  255. package/skills/video-frames/scripts/frame.sh +81 -0
  256. package/skills/voice-call/SKILL.md +45 -0
  257. package/skills/wacli/SKILL.md +72 -0
  258. package/skills/weather/SKILL.md +112 -0
@@ -0,0 +1,148 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Agent Worker Process
4
+ *
5
+ * This is spawned as a subprocess by agent-registry-extension.ts
6
+ * Connects to gateway, authenticates, executes task, reports completion.
7
+ */
8
+ const AGENT_ID = process.env.KOBOLD_AGENT_ID;
9
+ const AGENT_TYPE = process.env.KOBOLD_AGENT_TYPE;
10
+ const AGENT_TASK = process.env.KOBOLD_AGENT_TASK;
11
+ const SESSION_KEY = process.env.KOBOLD_SESSION_KEY;
12
+ const PARENT_ID = process.env.KOBOLD_PARENT_ID || "";
13
+ const WORKSPACE = process.env.KOBOLD_WORKSPACE;
14
+ const GATEWAY_PORT = parseInt(process.env.KOBOLD_GATEWAY_PORT || "18789");
15
+ if (!AGENT_ID || !SESSION_KEY) {
16
+ console.error("[AgentWorker] Missing required environment variables");
17
+ process.exit(1);
18
+ }
19
+ console.log(`[AgentWorker] ${AGENT_ID} starting...`);
20
+ console.log(`[AgentWorker] Type: ${AGENT_TYPE}`);
21
+ console.log(`[AgentWorker] Task: ${AGENT_TASK?.slice(0, 100)}...`);
22
+ console.log(`[AgentWorker] Workspace: ${WORKSPACE}`);
23
+ // Results tracking
24
+ let tokensInput = 0;
25
+ let tokensOutput = 0;
26
+ let result = "";
27
+ let exitCode = 0;
28
+ // Main execution
29
+ async function main() {
30
+ try {
31
+ // Connect to gateway
32
+ await connectToGateway();
33
+ // Execute the task
34
+ await executeTask();
35
+ // Report completion
36
+ await reportCompletion("success");
37
+ console.log("[AgentWorker] Completed successfully");
38
+ process.exit(0);
39
+ }
40
+ catch (error) {
41
+ console.error("[AgentWorker] Error:", error);
42
+ await reportCompletion("error", String(error));
43
+ process.exit(1);
44
+ }
45
+ }
46
+ async function connectToGateway() {
47
+ return new Promise((resolve, reject) => {
48
+ const ws = new WebSocket(`ws://127.0.0.1:${GATEWAY_PORT}`);
49
+ ws.onopen = () => {
50
+ console.log("[AgentWorker] Connected to gateway");
51
+ // Send connect frame with authentication
52
+ const connectFrame = {
53
+ type: "connect",
54
+ id: `conn-${Date.now()}`,
55
+ params: {
56
+ role: "node",
57
+ client: AGENT_ID,
58
+ caps: ["subagent"],
59
+ device: { id: AGENT_ID, platform: "bun-subprocess" },
60
+ sessionKey: SESSION_KEY,
61
+ },
62
+ };
63
+ ws.send(JSON.stringify(connectFrame));
64
+ // Wait for response
65
+ const onMessage = (data) => {
66
+ try {
67
+ const frame = JSON.parse(data.data);
68
+ if (frame.type === "res" && frame.ok) {
69
+ console.log("[AgentWorker] Authenticated with gateway");
70
+ ws.removeEventListener("message", onMessage);
71
+ resolve();
72
+ }
73
+ else if (frame.type === "res" && !frame.ok) {
74
+ reject(new Error(frame.error || "Authentication failed"));
75
+ }
76
+ }
77
+ catch { }
78
+ };
79
+ ws.addEventListener("message", onMessage);
80
+ };
81
+ ws.onerror = (err) => {
82
+ reject(new Error(`WebSocket error: ${err}`));
83
+ };
84
+ // Timeout after 10 seconds
85
+ setTimeout(() => reject(new Error("Gateway connection timeout")), 10000);
86
+ });
87
+ }
88
+ async function executeTask() {
89
+ const task = AGENT_TASK || "";
90
+ // Simulate work - in real implementation, this would:
91
+ // - Initialize the pi-coding-agent framework
92
+ // - Execute the task using available tools
93
+ // - Track token usage
94
+ // - Generate output
95
+ console.log("[AgentWorker] Executing task...");
96
+ // Simulate processing time
97
+ await delay(2000 + Math.random() * 3000);
98
+ // Simulate token counting
99
+ tokensInput = task.length * 2;
100
+ tokensOutput = Math.floor(Math.random() * 500) + 100;
101
+ // Generate result
102
+ result = `Task completed by ${AGENT_ID}\\n` +
103
+ `Type: ${AGENT_TYPE}\\n` +
104
+ `Task: ${task.slice(0, 50)}...\\n` +
105
+ `Output: ${tokensOutput} tokens generated`;
106
+ console.log("[AgentWorker] Task complete");
107
+ console.log(`[AgentWorker] Input tokens: ${tokensInput}`);
108
+ console.log(`[AgentWorker] Output tokens: ${tokensOutput}`);
109
+ }
110
+ async function reportCompletion(status, errorMessage) {
111
+ const ws = new WebSocket(`ws://127.0.0.1:${GATEWAY_PORT}`);
112
+ return new Promise((resolve) => {
113
+ ws.onopen = () => {
114
+ const announceFrame = {
115
+ type: "req",
116
+ id: `announce-${Date.now()}`,
117
+ method: "agent.announce",
118
+ params: {
119
+ sessionKey: SESSION_KEY,
120
+ source: "subagent",
121
+ childSessionKey: SESSION_KEY,
122
+ taskLabel: AGENT_TASK?.slice(0, 50),
123
+ status: status === "success" ? "success" : "error",
124
+ result: errorMessage || result,
125
+ tokens: { input: tokensInput, output: tokensOutput },
126
+ runtime: Date.now() - startTime,
127
+ exitCode: status === "success" ? 0 : 1,
128
+ },
129
+ };
130
+ ws.send(JSON.stringify(announceFrame));
131
+ // Close after sending
132
+ setTimeout(() => {
133
+ ws.close();
134
+ resolve();
135
+ }, 500);
136
+ };
137
+ ws.onerror = () => {
138
+ console.error("[AgentWorker] Failed to report completion");
139
+ resolve();
140
+ };
141
+ });
142
+ }
143
+ function delay(ms) {
144
+ return new Promise(resolve => setTimeout(resolve, ms));
145
+ }
146
+ const startTime = Date.now();
147
+ main();
148
+ //# sourceMappingURL=agent-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-worker.js","sourceRoot":"","sources":["../../../../src/extensions/core/agent-worker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Compaction Safeguard Extension
3
+ *
4
+ * Adapted from OpenClaw - protects context during message compaction
5
+ * Features:
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)
11
+ */
12
+ const FALLBACK_SUMMARY = "Summary unavailable due to context limits. Older messages were truncated.";
13
+ const TURN_PREFIX_INSTRUCTIONS = "This summary covers the prefix of a split turn. Focus on the original request," +
14
+ " early progress, and any details needed to understand the retained suffix.";
15
+ const MAX_TOOL_FAILURES = 8;
16
+ const MAX_TOOL_FAILURE_CHARS = 240;
17
+ function normalizeFailureText(text) {
18
+ return text.replace(/\s+/g, " ").trim();
19
+ }
20
+ function truncateFailureText(text, maxChars) {
21
+ if (text.length <= maxChars) {
22
+ return text;
23
+ }
24
+ return `${text.slice(0, Math.max(0, maxChars - 3))}...`;
25
+ }
26
+ function formatToolFailureMeta(details) {
27
+ if (!details || typeof details !== "object") {
28
+ return undefined;
29
+ }
30
+ const record = details;
31
+ const status = typeof record.status === "string" ? record.status : undefined;
32
+ const exitCode = typeof record.exitCode === "number" && Number.isFinite(record.exitCode)
33
+ ? record.exitCode
34
+ : undefined;
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;
43
+ }
44
+ function extractToolResultText(content) {
45
+ if (!Array.isArray(content)) {
46
+ return "";
47
+ }
48
+ const parts = [];
49
+ for (const block of content) {
50
+ if (!block || typeof block !== "object") {
51
+ continue;
52
+ }
53
+ const rec = block;
54
+ if (rec.type === "text" && typeof rec.text === "string") {
55
+ parts.push(rec.text);
56
+ }
57
+ }
58
+ return parts.join("\n");
59
+ }
60
+ function collectToolFailures(messages) {
61
+ const failures = [];
62
+ const seen = new Set();
63
+ for (const message of messages) {
64
+ if (!message || typeof message !== "object") {
65
+ continue;
66
+ }
67
+ const role = message.role;
68
+ if (role !== "toolResult") {
69
+ continue;
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 });
88
+ }
89
+ return failures;
90
+ }
91
+ function formatToolFailuresSection(failures) {
92
+ if (failures.length === 0) {
93
+ return "";
94
+ }
95
+ const lines = failures.slice(0, MAX_TOOL_FAILURES).map((failure) => {
96
+ const meta = failure.meta ? ` (${failure.meta})` : "";
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`);
101
+ }
102
+ return `\n\n## Tool Failures\n${lines.join("\n")}`;
103
+ }
104
+ function computeFileLists(fileOps) {
105
+ const modified = new Set([...fileOps.edited, ...fileOps.written]);
106
+ const readFiles = [...fileOps.read].filter((f) => !modified.has(f)).toSorted();
107
+ const modifiedFiles = [...modified].toSorted();
108
+ return { readFiles, modifiedFiles };
109
+ }
110
+ function formatFileOperations(readFiles, modifiedFiles) {
111
+ const sections = [];
112
+ if (readFiles.length > 0) {
113
+ sections.push(`<read-files>\n${readFiles.join("\n")}\n</read-files>`);
114
+ }
115
+ if (modifiedFiles.length > 0) {
116
+ sections.push(`<modified-files>\n${modifiedFiles.join("\n")}\n</modified-files>`);
117
+ }
118
+ if (sections.length === 0) {
119
+ return "";
120
+ }
121
+ return `\n\n${sections.join("\n\n")}`;
122
+ }
123
+ export default function compactionSafeguardExtension(api) {
124
+ console.log("[CompactionSafeguard] Extension loaded");
125
+ api.on("session_before_compact", async (event, ctx) => {
126
+ const { preparation } = event;
127
+ const { readFiles, modifiedFiles } = computeFileLists(preparation.fileOps);
128
+ const fileOpsSummary = formatFileOperations(readFiles, modifiedFiles);
129
+ const toolFailures = collectToolFailures([
130
+ ...preparation.messagesToSummarize,
131
+ ...preparation.turnPrefixMessages,
132
+ ]);
133
+ const toolFailureSection = formatToolFailuresSection(toolFailures);
134
+ const fallbackSummary = `${FALLBACK_SUMMARY}${toolFailureSection}${fileOpsSummary}`;
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
+ });
149
+ }
150
+ export const __testing = {
151
+ collectToolFailures,
152
+ formatToolFailuresSection,
153
+ };
154
+ //# sourceMappingURL=compaction-safeguard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction-safeguard.js","sourceRoot":"","sources":["../../../../src/extensions/core/compaction-safeguard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Confirm Destructive Actions Extension
3
+ *
4
+ * Prompts for confirmation before destructive session actions (clear, switch, branch).
5
+ * Demonstrates how to cancel session events using the before_* events.
6
+ */
7
+ export default function (pi) {
8
+ pi.on("session_before_switch", async (event, ctx) => {
9
+ if (!ctx.hasUI)
10
+ return;
11
+ if (event.reason === "new") {
12
+ const confirmed = await ctx.ui.confirm("Clear session?", "This will delete all messages in the current session.");
13
+ if (!confirmed) {
14
+ ctx.ui.notify("Clear cancelled", "info");
15
+ return { cancel: true };
16
+ }
17
+ return;
18
+ }
19
+ // reason === "resume" - check if there are unsaved changes (messages since last assistant response)
20
+ const entries = ctx.sessionManager.getEntries();
21
+ const hasUnsavedWork = entries.some((e) => e.type === "message" && e.message.role === "user");
22
+ if (hasUnsavedWork) {
23
+ const confirmed = await ctx.ui.confirm("Switch session?", "You have messages in the current session. Switch anyway?");
24
+ if (!confirmed) {
25
+ ctx.ui.notify("Switch cancelled", "info");
26
+ return { cancel: true };
27
+ }
28
+ }
29
+ });
30
+ pi.on("session_before_fork", async (event, ctx) => {
31
+ if (!ctx.hasUI)
32
+ return;
33
+ const choice = await ctx.ui.select(`Fork from entry ${event.entryId.slice(0, 8)}?`, [
34
+ "Yes, create fork",
35
+ "No, stay in current session",
36
+ ]);
37
+ if (choice !== "Yes, create fork") {
38
+ ctx.ui.notify("Fork cancelled", "info");
39
+ return { cancel: true };
40
+ }
41
+ });
42
+ }
43
+ //# sourceMappingURL=confirm-destructive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm-destructive.js","sourceRoot":"","sources":["../../../../src/extensions/core/confirm-destructive.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,OAAO,WAAW,EAAgB;IACxC,EAAE,CAAC,EAAE,CAAC,uBAAuB,EAAE,KAAK,EAAE,KAA+B,EAAE,GAAG,EAAE,EAAE;QAC7E,IAAI,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO;QAEvB,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;YAC5B,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,OAAO,CACrC,gBAAgB,EAChB,uDAAuD,CACvD,CAAC;YAEF,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;gBACzC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACzB,CAAC;YACD,OAAO;QACR,CAAC;QAED,oGAAoG;QACpG,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;QAChD,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAClC,CAAC,CAAC,EAA4B,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,CAClF,CAAC;QAEF,IAAI,cAAc,EAAE,CAAC;YACpB,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,OAAO,CACrC,iBAAiB,EACjB,0DAA0D,CAC1D,CAAC;YAEF,IAAI,CAAC,SAAS,EAAE,CAAC;gBAChB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;gBAC1C,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACzB,CAAC;QACF,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,EAAE,CAAC,qBAAqB,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QACjD,IAAI,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO;QAEvB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,mBAAmB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE;YACnF,kBAAkB;YAClB,6BAA6B;SAC7B,CAAC,CAAC;QAEH,IAAI,MAAM,KAAK,kBAAkB,EAAE,CAAC;YACnC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;YACxC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACzB,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,124 @@
1
+ import { existsSync, readFileSync } from "fs";
2
+ import { join, basename } from "path";
3
+ import { homedir } from "os";
4
+ const CONTEXT_FILE = join(homedir(), ".0xkobold", ".active-context");
5
+ /**
6
+ * Context-Aware Extension
7
+ *
8
+ * Reads the active context file and updates TUI display
9
+ * to show the actual working directory with --local mode.
10
+ */
11
+ export default function contextAwareExtension(pi) {
12
+ let activeContext = null;
13
+ /**
14
+ * Load active context from file
15
+ */
16
+ function loadContext() {
17
+ try {
18
+ if (!existsSync(CONTEXT_FILE)) {
19
+ return null;
20
+ }
21
+ const content = readFileSync(CONTEXT_FILE, "utf-8");
22
+ const parsed = JSON.parse(content);
23
+ // Check if context is fresh (within 5 minutes)
24
+ const age = Date.now() - parsed.timestamp;
25
+ if (age > 5 * 60 * 1000) {
26
+ return null; // Too old
27
+ }
28
+ return parsed;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ /**
35
+ * Get git branch from a directory
36
+ */
37
+ function getGitBranch(dir) {
38
+ try {
39
+ const { execSync } = require("child_process");
40
+ const result = execSync("git rev-parse --abbrev-ref HEAD", {
41
+ cwd: dir,
42
+ encoding: "utf-8",
43
+ });
44
+ return result.trim();
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ // Load context on startup
51
+ activeContext = loadContext();
52
+ if (activeContext?.isLocal) {
53
+ console.log(`[Context-Aware] Local mode active: ${activeContext.workingDir}`);
54
+ }
55
+ // Hook into session start
56
+ pi.on("session_start", async (_event, ctx) => {
57
+ activeContext = loadContext();
58
+ // Only apply local context if:
59
+ // 1. Context file says it's local
60
+ // 2. KOBOLD_WORKING_DIR env var is set (confirms --local was used)
61
+ if (!activeContext?.isLocal) {
62
+ return; // Not in local mode
63
+ }
64
+ const envWorkingDir = process.env.KOBOLD_WORKING_DIR;
65
+ if (!envWorkingDir || envWorkingDir === process.cwd()) {
66
+ return; // Not actually in local mode (env var missing or matches cwd)
67
+ }
68
+ ;
69
+ const { workingDir } = activeContext;
70
+ const gitBranch = getGitBranch(workingDir);
71
+ const dirName = basename(workingDir);
72
+ // Replace the footer to show actual working directory
73
+ ctx.ui?.setFooter?.((tui, theme, footerData) => ({
74
+ invalidate() { },
75
+ render(width) {
76
+ // Build status line with actual working directory
77
+ const parts = [];
78
+ // Working directory (the key fix!)
79
+ const workingDirDisplay = `${workingDir}`;
80
+ parts.push(theme.fg("dim", workingDirDisplay));
81
+ // Git branch if available
82
+ if (gitBranch) {
83
+ parts.push(theme.fg("accent", `(${gitBranch})`));
84
+ }
85
+ // Mode indicator
86
+ parts.push(theme.fg("dim", "• local mode"));
87
+ // Original footer data
88
+ const extensionStatuses = footerData.getExtensionStatuses?.() || new Map();
89
+ const statusItems = Array.from(extensionStatuses.values()).filter(Boolean);
90
+ if (statusItems.length > 0) {
91
+ parts.push(theme.fg("dim", "• " + statusItems.slice(0, 2).join(" ")));
92
+ }
93
+ // Combine parts and truncate to width
94
+ const line = parts.join(" ");
95
+ if (line.length > width) {
96
+ return [line.slice(0, width - 3) + "..."];
97
+ }
98
+ return [line];
99
+ },
100
+ dispose: footerData.onBranchChange?.(() => tui.requestRender()),
101
+ }));
102
+ // Add a status bar item showing we're in local mode
103
+ ctx.ui?.setStatus?.("workspace", `🗂️ ${dirName}`);
104
+ // Log for debugging
105
+ console.log(`[Context-Aware] Footer updated for: ${workingDir}`);
106
+ });
107
+ // Register a command
108
+ pi.registerCommand("context", {
109
+ description: "Show current workspace context",
110
+ handler: async (_args, ctx) => {
111
+ activeContext = loadContext();
112
+ if (!activeContext) {
113
+ ctx.ui?.notify?.("No active context. Not in local mode.", "info");
114
+ return;
115
+ }
116
+ ctx.ui?.notify?.(`🗂️ Current Context:\n` +
117
+ ` Working: ${activeContext.workingDir}\n` +
118
+ ` Mode: ${activeContext.isLocal ? "local" : "global"}\n` +
119
+ ` From: ${new Date(activeContext.timestamp).toLocaleTimeString()}`, "info");
120
+ },
121
+ });
122
+ console.log("[Context-Aware] Extension loaded");
123
+ }
124
+ //# sourceMappingURL=context-aware-extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-aware-extension.js","sourceRoot":"","sources":["../../../../src/extensions/core/context-aware-extension.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Context Pruning Extension
3
+ *
4
+ * Adapted from OpenClaw - intelligent context window management
5
+ * Features:
6
+ * - Soft trimming: keeps head+tail of large tool results
7
+ * - Hard clearing: removes old tool results entirely
8
+ * - Image protection: never prunes results with images
9
+ * - Cache TTL: avoids unnecessary pruning
10
+ *
11
+ * NOTE: This extension uses @ts-ignore for SessionManager methods that exist
12
+ * at runtime but are missing from type definitions:
13
+ * - ExtensionContext.sessionManager.getCurrentSession(): Returns current session
14
+ * - Session.getConfig(key): Gets session-specific config
15
+ * - Session.setConfig(key, value): Sets session-specific config
16
+ * - Session.getExtensionRuntime(key): Gets extension runtime state
17
+ * - Session.setExtensionRuntime(key, value): Sets extension runtime state
18
+ *
19
+ * These are available in pi-coding-agent runtime but types are incomplete.
20
+ * Tracked: Extension API needs ReadonlySessionManager → Session type cast.
21
+ */
22
+ import { pruneContextMessages } from "./pruner.js";
23
+ import { getContextPruningRuntime, setContextPruningRuntime } from "./runtime.js";
24
+ import { computeEffectiveSettings } from "./settings.js";
25
+ export { pruneContextMessages } from "./pruner.js";
26
+ export { computeEffectiveSettings, DEFAULT_CONTEXT_PRUNING_SETTINGS, } from "./settings.js";
27
+ export default function contextPruningExtension(api) {
28
+ console.log("[ContextPruning] Extension loaded");
29
+ api.on("context", (event, ctx) => {
30
+ // Get or initialize runtime
31
+ // @ts-ignore - sessionManager type mismatch
32
+ let runtime = getContextPruningRuntime(ctx.sessionManager);
33
+ // First time - try to load from session config
34
+ if (!runtime) {
35
+ // @ts-ignore - getCurrentSession doesn't exist on ReadonlySessionManager
36
+ const session = ctx.sessionManager.getCurrentSession?.();
37
+ // @ts-ignore - getConfig doesn't exist
38
+ const rawConfig = session?.getConfig?.("contextPruning") ?? session?.contextPruning;
39
+ const settings = computeEffectiveSettings(rawConfig);
40
+ if (!settings) {
41
+ return undefined; // Pruning disabled
42
+ }
43
+ runtime = { settings };
44
+ // @ts-ignore - sessionManager type mismatch
45
+ setContextPruningRuntime(ctx.sessionManager, runtime);
46
+ }
47
+ // Check TTL cache mode
48
+ if (runtime.settings.mode === "cache-ttl") {
49
+ const ttlMs = runtime.settings.ttlMs;
50
+ const lastTouch = runtime.lastCacheTouchAt ?? null;
51
+ if (!lastTouch || ttlMs <= 0) {
52
+ return undefined;
53
+ }
54
+ if (ttlMs > 0 && Date.now() - lastTouch < ttlMs) {
55
+ return undefined; // Cache still valid, skip pruning
56
+ }
57
+ }
58
+ // Perform pruning
59
+ const next = pruneContextMessages({
60
+ messages: event.messages,
61
+ settings: runtime.settings,
62
+ ctx,
63
+ contextWindowTokensOverride: runtime.contextWindowTokens ?? undefined,
64
+ });
65
+ // No changes needed
66
+ if (next === event.messages) {
67
+ return undefined;
68
+ }
69
+ // Update cache timestamp
70
+ if (runtime.settings.mode === "cache-ttl") {
71
+ runtime.lastCacheTouchAt = Date.now();
72
+ // @ts-ignore - sessionManager type mismatch
73
+ setContextPruningRuntime(ctx.sessionManager, runtime);
74
+ }
75
+ return { messages: next };
76
+ });
77
+ // Command to configure pruning
78
+ api.registerCommand?.("pruning-config", {
79
+ description: "Configure context pruning settings",
80
+ // @ts-ignore - handler return type
81
+ handler: async (args, ctx) => {
82
+ const parts = args.trim().split(" ");
83
+ const subcommand = parts[0];
84
+ if (subcommand === "status") {
85
+ // @ts-ignore - sessionManager type mismatch
86
+ const runtime = getContextPruningRuntime(ctx.sessionManager);
87
+ if (!runtime) {
88
+ ctx.ui.notify("Context pruning: disabled", "info");
89
+ return;
90
+ }
91
+ const s = runtime.settings;
92
+ const lines = [
93
+ "Context Pruning Status:",
94
+ ` Mode: ${s.mode}`,
95
+ ` TTL: ${s.ttlMs / 1000}s`,
96
+ ` Keep last assistants: ${s.keepLastAssistants}`,
97
+ ` Soft trim ratio: ${(s.softTrimRatio * 100).toFixed(0)}%`,
98
+ ` Hard clear ratio: ${(s.hardClearRatio * 100).toFixed(0)}%`,
99
+ ];
100
+ ctx.ui.notify(lines.join("\n"), "info");
101
+ return;
102
+ }
103
+ if (subcommand === "disable") {
104
+ // @ts-ignore - getCurrentSession doesn't exist
105
+ const session = ctx.sessionManager.getCurrentSession?.();
106
+ if (session?.setConfig) {
107
+ session.setConfig("contextPruning", { mode: "off" });
108
+ }
109
+ // @ts-ignore - sessionManager type mismatch
110
+ const runtime = getContextPruningRuntime(ctx.sessionManager);
111
+ if (runtime) {
112
+ // @ts-ignore - sessionManager type mismatch
113
+ setContextPruningRuntime(ctx.sessionManager, {
114
+ settings: { ...runtime.settings, mode: "cache-ttl" }
115
+ });
116
+ }
117
+ ctx.ui.notify("Context pruning disabled", "info");
118
+ return;
119
+ }
120
+ ctx.ui.notify("Usage: /pruning-config [status|disable]", "error");
121
+ },
122
+ });
123
+ }
124
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../../../../../src/extensions/core/context-pruning/extension.ts"],"names":[],"mappings":"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"}