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,113 @@
1
+ /**
2
+ * Ollama Provider
3
+ *
4
+ * Local LLM via Ollama HTTP API.
5
+ */
6
+ const OLLAMA_BASE_URL = process.env.OLLAMA_URL ?? 'http://localhost:11434';
7
+ /**
8
+ * Check if Ollama is running
9
+ */
10
+ export async function isOllamaRunning() {
11
+ try {
12
+ const res = await fetch(`${OLLAMA_BASE_URL}/api/tags`, {
13
+ method: 'GET',
14
+ });
15
+ return res.ok;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ /**
22
+ * List available Ollama models
23
+ */
24
+ export async function listOllamaModels() {
25
+ try {
26
+ const res = await fetch(`${OLLAMA_BASE_URL}/api/tags`);
27
+ if (!res.ok)
28
+ return [];
29
+ const data = await res.json();
30
+ return (data.models ?? []).map((m) => m.name);
31
+ }
32
+ catch {
33
+ return [];
34
+ }
35
+ }
36
+ /**
37
+ * Ollama LLM Provider
38
+ */
39
+ export class OllamaProvider {
40
+ name = 'ollama';
41
+ baseUrl;
42
+ constructor(baseUrl = OLLAMA_BASE_URL) {
43
+ this.baseUrl = baseUrl;
44
+ }
45
+ async chat(options) {
46
+ const model = options.model.replace('ollama/', '');
47
+ // Convert messages to Ollama format
48
+ const messages = options.messages.map((m) => ({
49
+ role: m.role,
50
+ content: m.content,
51
+ tool_calls: m.toolCalls?.map(tc => ({
52
+ function: {
53
+ name: tc.function.name,
54
+ arguments: tc.function.arguments,
55
+ },
56
+ })),
57
+ }));
58
+ // Build request
59
+ const body = {
60
+ model,
61
+ messages,
62
+ stream: options.stream ?? false,
63
+ options: {
64
+ temperature: options.temperature ?? 0.7,
65
+ num_predict: options.maxTokens ?? 4096,
66
+ },
67
+ };
68
+ // Add tools if provided
69
+ if (options.tools && options.tools.length > 0) {
70
+ body.tools = options.tools.map(t => ({
71
+ type: t.type,
72
+ function: t.function,
73
+ }));
74
+ }
75
+ const res = await fetch(`${this.baseUrl}/api/chat`, {
76
+ method: 'POST',
77
+ headers: { 'Content-Type': 'application/json' },
78
+ body: JSON.stringify(body),
79
+ });
80
+ if (!res.ok) {
81
+ const err = await res.text();
82
+ throw new Error(`Ollama error: ${err}`);
83
+ }
84
+ const data = await res.json();
85
+ // Parse tool calls from response
86
+ const toolCalls = data.message?.tool_calls?.map((tc) => ({
87
+ id: `call-${Date.now()}`,
88
+ function: {
89
+ name: tc.function?.name ?? tc.function,
90
+ arguments: tc.function?.arguments ?? {},
91
+ },
92
+ }));
93
+ return {
94
+ content: data.message?.content ?? '',
95
+ toolCalls,
96
+ model: options.model,
97
+ usage: {
98
+ inputTokens: data.prompt_eval_count ?? 0,
99
+ outputTokens: data.eval_count ?? 0,
100
+ },
101
+ };
102
+ }
103
+ async listModels() {
104
+ return listOllamaModels();
105
+ }
106
+ }
107
+ /**
108
+ * Create default Ollama provider
109
+ */
110
+ export function createOllamaProvider() {
111
+ return new OllamaProvider();
112
+ }
113
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/llm/ollama.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Model Router
3
+ *
4
+ * Smart model selection based on task complexity.
5
+ * Uses fast models for simple tasks, switches to smart models for complex reasoning.
6
+ */
7
+ export class ModelRouter {
8
+ models = new Map();
9
+ defaultModel;
10
+ constructor(defaultModel) {
11
+ this.defaultModel = defaultModel ?? 'ollama/llama3.2';
12
+ }
13
+ /**
14
+ * Register a model
15
+ */
16
+ register(config) {
17
+ this.models.set(config.name, config);
18
+ }
19
+ /**
20
+ * Select model based on message and context
21
+ */
22
+ selectModel(message, history) {
23
+ const complexity = this.assessComplexity(message, history);
24
+ // Simple queries → fast model
25
+ if (complexity < 3) {
26
+ const fast = this.findModel({ speed: 'fast' });
27
+ if (fast)
28
+ return fast.name;
29
+ }
30
+ // Medium complexity → balanced
31
+ if (complexity < 6) {
32
+ const medium = this.findModel({ speed: 'medium' });
33
+ if (medium)
34
+ return medium.name;
35
+ }
36
+ // Complex reasoning → smart model
37
+ const smart = this.findModel({ speed: 'slow' });
38
+ if (smart)
39
+ return smart.name;
40
+ return this.defaultModel;
41
+ }
42
+ /**
43
+ * Assess complexity of a task (0-10 scale)
44
+ */
45
+ assessComplexity(message, history) {
46
+ let score = 0;
47
+ // Length factor
48
+ if (message.length > 500)
49
+ score += 2;
50
+ if (message.length > 1000)
51
+ score += 2;
52
+ // Keywords indicating complexity
53
+ const complexKeywords = [
54
+ 'analyze', 'compare', 'evaluate', 'synthesize',
55
+ 'explain in detail', 'step by step', 'reasoning',
56
+ 'architecture', 'design', 'implement',
57
+ 'debug', 'optimize', 'refactor',
58
+ ];
59
+ for (const keyword of complexKeywords) {
60
+ if (message.toLowerCase().includes(keyword)) {
61
+ score += 1;
62
+ }
63
+ }
64
+ // Code indicators
65
+ if (message.includes('```'))
66
+ score += 1;
67
+ if (/\b(function|class|interface|async|await)\b/.test(message))
68
+ score += 1;
69
+ // Conversation depth
70
+ if (history && history.length > 10)
71
+ score += 1;
72
+ return Math.min(score, 10);
73
+ }
74
+ /**
75
+ * Find model matching criteria
76
+ */
77
+ findModel(criteria) {
78
+ for (const model of this.models.values()) {
79
+ let matches = true;
80
+ if (criteria.speed && model.speed !== criteria.speed)
81
+ matches = false;
82
+ if (criteria.cost && model.cost !== criteria.cost)
83
+ matches = false;
84
+ if (matches)
85
+ return model;
86
+ }
87
+ // Return first available as fallback
88
+ return this.models.values().next().value;
89
+ }
90
+ /**
91
+ * Get provider for a model
92
+ */
93
+ getProvider(modelName) {
94
+ const model = this.models.get(modelName);
95
+ return model?.provider;
96
+ }
97
+ /**
98
+ * Get default model
99
+ */
100
+ getDefaultModel() {
101
+ return this.defaultModel;
102
+ }
103
+ /**
104
+ * List available models
105
+ */
106
+ listModels() {
107
+ return Array.from(this.models.keys());
108
+ }
109
+ }
110
+ /**
111
+ * Create default router with Ollama models
112
+ */
113
+ export function createOllamaRouter(provider) {
114
+ const router = new ModelRouter('ollama/llama3.2');
115
+ // Fast model for simple queries
116
+ router.register({
117
+ name: 'ollama/llama3.2:3b',
118
+ provider,
119
+ speed: 'fast',
120
+ cost: 'free',
121
+ capabilities: ['chat', 'simple'],
122
+ contextWindow: 8192,
123
+ });
124
+ // Medium model for most tasks
125
+ router.register({
126
+ name: 'ollama/llama3.2',
127
+ provider,
128
+ speed: 'medium',
129
+ cost: 'free',
130
+ capabilities: ['chat', 'code', 'reasoning'],
131
+ contextWindow: 128000,
132
+ });
133
+ // Smart model for complex reasoning
134
+ router.register({
135
+ name: 'ollama/llama3.2:70b',
136
+ provider,
137
+ speed: 'slow',
138
+ cost: 'free',
139
+ capabilities: ['chat', 'code', 'reasoning', 'analysis'],
140
+ contextWindow: 128000,
141
+ });
142
+ return router;
143
+ }
144
+ export default ModelRouter;
145
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/llm/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * LLM Provider Types
3
+ *
4
+ * Unified interface for different LLM providers.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/llm/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Memory Module
3
+ */
4
+ export * from './store';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/memory/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Memory Store
3
+ *
4
+ * Simple JSON-based persistence for conversation history.
5
+ */
6
+ import { readFile, writeFile, mkdir } from 'fs/promises';
7
+ import { existsSync } from 'fs';
8
+ import { join } from 'path';
9
+ import { homedir } from 'os';
10
+ const MEMORY_DIR = join(homedir(), '.0xkobold', 'memory');
11
+ /**
12
+ * JSON file-based memory store
13
+ */
14
+ export class JSONMemoryStore {
15
+ dir;
16
+ constructor(dir = MEMORY_DIR) {
17
+ this.dir = dir;
18
+ }
19
+ getPath(sessionKey) {
20
+ // Sanitize session key for filename
21
+ const safeKey = sessionKey.replace(/[^a-zA-Z0-9_-]/g, '_');
22
+ return join(this.dir, `${safeKey}.json`);
23
+ }
24
+ async ensureDir() {
25
+ if (!existsSync(this.dir)) {
26
+ await mkdir(this.dir, { recursive: true });
27
+ }
28
+ }
29
+ async load(sessionKey) {
30
+ try {
31
+ await this.ensureDir();
32
+ const path = this.getPath(sessionKey);
33
+ if (!existsSync(path)) {
34
+ return [];
35
+ }
36
+ const data = await readFile(path, 'utf-8');
37
+ const messages = JSON.parse(data);
38
+ return Array.isArray(messages) ? messages : [];
39
+ }
40
+ catch (err) {
41
+ console.error(`[Memory] Failed to load ${sessionKey}:`, err);
42
+ return [];
43
+ }
44
+ }
45
+ async save(sessionKey, messages) {
46
+ try {
47
+ await this.ensureDir();
48
+ const path = this.getPath(sessionKey);
49
+ // Keep only last N messages to manage size
50
+ const maxMessages = 100;
51
+ const trimmed = messages.slice(-maxMessages);
52
+ await writeFile(path, JSON.stringify(trimmed, null, 2));
53
+ }
54
+ catch (err) {
55
+ console.error(`[Memory] Failed to save ${sessionKey}:`, err);
56
+ }
57
+ }
58
+ async clear(sessionKey) {
59
+ try {
60
+ const path = this.getPath(sessionKey);
61
+ if (existsSync(path)) {
62
+ await writeFile(path, '[]');
63
+ }
64
+ }
65
+ catch (err) {
66
+ console.error(`[Memory] Failed to clear ${sessionKey}:`, err);
67
+ }
68
+ }
69
+ }
70
+ /**
71
+ * In-memory store (non-persistent)
72
+ */
73
+ export class InMemoryStore {
74
+ store = new Map();
75
+ async load(sessionKey) {
76
+ return this.store.get(sessionKey) ?? [];
77
+ }
78
+ async save(sessionKey, messages) {
79
+ this.store.set(sessionKey, messages);
80
+ }
81
+ async clear(sessionKey) {
82
+ this.store.delete(sessionKey);
83
+ }
84
+ }
85
+ /**
86
+ * Create default memory store
87
+ */
88
+ export function createMemoryStore(persistent = true) {
89
+ return persistent ? new JSONMemoryStore() : new InMemoryStore();
90
+ }
91
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/memory/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Pi-Framework Configuration for 0xKobold
3
+ *
4
+ * Configures pi-coding-agent with 0xKobold extensions and settings
5
+ */
6
+ export const config = {
7
+ // Use pi-tui for terminal UI
8
+ ui: 'tui',
9
+ // Load extensions (paths resolved from project root)
10
+ // Order matters: infrastructure first, then features, then integrations
11
+ extensions: [
12
+ // Infrastructure
13
+ './src/extensions/core/ollama-provider-extension.ts', // Register Ollama models
14
+ './src/extensions/core/session-bridge-extension.ts', // Bridge pi-coding-agent sessions to KOBOLD_SESSION_ID
15
+ // Core Features
16
+ './src/extensions/core/persona-loader-extension.ts', // Load identity files
17
+ './src/extensions/core/context-aware-extension.ts', // Local mode context
18
+ './src/extensions/core/onboarding-extension.ts', // First-run setup
19
+ './src/extensions/core/mode-manager-extension.ts', // Plan/Build mode switching
20
+ './src/extensions/core/questionnaire-extension.ts', // Question/questionnaire tools
21
+ './src/extensions/core/session-name-extension.ts', // Session naming
22
+ './src/extensions/core/handoff-extension.ts', // Context handoff to new session
23
+ './src/extensions/core/pi-notify-extension.ts', // Native desktop notifications
24
+ './src/extensions/core/task-manager-extension.ts', // Task board and workflow
25
+ './src/extensions/core/heartbeat-extension.ts', // Koclaw-style heartbeat monitoring
26
+ // Note: pi-coding-agent has built-in compaction, no need for custom pruning
27
+ // Multi-Channel (for future Discord/Web)
28
+ './src/extensions/core/multi-channel-extension.ts', // Unified channel management
29
+ './src/extensions/core/discord-extension.ts', // Discord bot integration
30
+ // pi-mono safety extensions
31
+ './src/extensions/core/protected-paths.ts', // Block writes to sensitive paths
32
+ './src/extensions/core/confirm-destructive.ts', // Confirm clear/switch/fork
33
+ './src/extensions/core/dirty-repo-guard.ts', // Prevent losing uncommitted work
34
+ './src/extensions/core/git-checkpoint.ts', // Git stash checkpoints for fork
35
+ // Integrations
36
+ './src/extensions/core/mcp-extension.ts', // Model Context Protocol support
37
+ './src/extensions/core/gateway-extension.ts', // WebSocket gateway
38
+ './src/extensions/core/agent-registry-extension.ts', // OpenClaw-style multi-agent
39
+ './src/extensions/core/websearch-extension.ts', // Ollama web search
40
+ './src/extensions/core/update-extension.ts', // Framework update functionality
41
+ './src/extensions/core/self-update-extension.ts', // 0xKobold self-update
42
+ ],
43
+ // Custom keybindings
44
+ keybindings: {
45
+ 'ctrl+c': 'interrupt',
46
+ 'ctrl+d': 'shutdown',
47
+ 'ctrl+l': 'clear',
48
+ 'f1': 'help',
49
+ 'f2': 'toggle_mode', // Toggle between plan/build modes
50
+ 'ctrl+t': 'toggle_tree',
51
+ 'ctrl+n': 'new_chat',
52
+ },
53
+ // 0xKobold-specific settings
54
+ settings: {
55
+ // Gateway settings
56
+ '0xkobold.gateway.port': 18789,
57
+ '0xkobold.gateway.host': '127.0.0.1',
58
+ // Discord settings
59
+ '0xkobold.discord.enabled': true,
60
+ '0xkobold.discord.autoReply': true,
61
+ // Memory settings
62
+ '0xkobold.memory.persist': true,
63
+ '0xkobold.memory.dbPath': '~/.0xkobold/memory.db',
64
+ // Agent settings
65
+ '0xkobold.agents.workdir': '~/.0xkobold/agents',
66
+ // Model settings
67
+ '0xkobold.model.provider': 'ollama',
68
+ '0xkobold.model.name': 'kimi-k2.5:cloud',
69
+ // Update settings
70
+ '0xkobold.update.checkOnStartup': true,
71
+ '0xkobold.update.autoInstall': true,
72
+ // Heartbeat settings (koclaw-style)
73
+ // Configure via environment variables:
74
+ // HEARTBEAT_ENABLED=true|false (default: true)
75
+ // HEARTBEAT_EVERY=30m|1h|2h30m (default: 30m)
76
+ // HEARTBEAT_ACK_MAX_CHARS=300 (default: 300)
77
+ // See HEARTBEAT.md in workspace for checklist contents
78
+ },
79
+ };
80
+ //# sourceMappingURL=pi-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-config.js","sourceRoot":"","sources":["../../src/pi-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,6BAA6B;IAC7B,EAAE,EAAE,KAAK;IAET,qDAAqD;IACrD,wEAAwE;IACxE,UAAU,EAAE;QACV,iBAAiB;QACjB,oDAAoD,EAAE,yBAAyB;QAC/E,mDAAmD,EAAE,uDAAuD;QAE5G,gBAAgB;QAChB,mDAAmD,EAAE,sBAAsB;QAC3E,kDAAkD,EAAE,qBAAqB;QACzE,+CAA+C,EAAE,kBAAkB;QACnE,iDAAiD,EAAK,4BAA4B;QAClF,kDAAkD,EAAE,+BAA+B;QACnF,iDAAiD,EAAE,iBAAiB;QACpE,4CAA4C,EAAE,iCAAiC;QAC/E,8CAA8C,EAAE,+BAA+B;QAC/E,iDAAiD,EAAE,0BAA0B;QAC7E,8CAA8C,EAAQ,oCAAoC;QAC1F,4EAA4E;QAE5E,yCAAyC;QACzC,kDAAkD,EAAE,6BAA6B;QACjF,4CAA4C,EAAS,0BAA0B;QAE/E,4BAA4B;QAC5B,0CAA0C,EAAE,kCAAkC;QAC9E,8CAA8C,EAAE,4BAA4B;QAC5E,2CAA2C,EAAE,kCAAkC;QAC/E,yCAAyC,EAAE,iCAAiC;QAE5E,eAAe;QACf,wCAAwC,EAAE,iCAAiC;QAC3E,4CAA4C,EAAW,oBAAoB;QAC3E,mDAAmD,EAAG,6BAA6B;QACnF,8CAA8C,EAAS,oBAAoB;QAC3E,2CAA2C,EAAY,iCAAiC;QACxF,gDAAgD,EAAS,uBAAuB;KACjF;IAED,qBAAqB;IACrB,WAAW,EAAE;QACX,QAAQ,EAAE,WAAW;QACrB,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,OAAO;QACjB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,aAAa,EAAG,kCAAkC;QACxD,QAAQ,EAAE,aAAa;QACvB,QAAQ,EAAE,UAAU;KACrB;IAED,6BAA6B;IAC7B,QAAQ,EAAE;QACR,mBAAmB;QACnB,uBAAuB,EAAE,KAAK;QAC9B,uBAAuB,EAAE,WAAW;QACpC,mBAAmB;QACnB,0BAA0B,EAAE,IAAI;QAChC,4BAA4B,EAAE,IAAI;QAClC,kBAAkB;QAClB,yBAAyB,EAAE,IAAI;QAC/B,wBAAwB,EAAE,uBAAuB;QACjD,iBAAiB;QACjB,yBAAyB,EAAE,oBAAoB;QAC/C,iBAAiB;QACjB,yBAAyB,EAAE,QAAQ;QACnC,qBAAqB,EAAE,iBAAiB;QACxC,kBAAkB;QAClB,gCAAgC,EAAE,IAAI;QACtC,6BAA6B,EAAE,IAAI;QACnC,oCAAoC;QACpC,uCAAuC;QACvC,iDAAiD;QACjD,gDAAgD;QAChD,+CAA+C;QAC/C,uDAAuD;KACxD;CACF,CAAC"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * File Skills
3
+ *
4
+ * Read and write files with safety controls.
5
+ */
6
+ import { readFile, writeFile } from 'fs/promises';
7
+ import { join, resolve } from 'path';
8
+ // Blocked paths (security)
9
+ const BLOCKED_PATHS = [
10
+ '~/.ssh',
11
+ '~/.aws',
12
+ '~/.kube',
13
+ '/etc/shadow',
14
+ '/etc/passwd',
15
+ process.env.SSH_KEY_PATH,
16
+ ].filter(Boolean);
17
+ // Allowed paths (whitelist)
18
+ const ALLOWED_PATHS = [
19
+ process.cwd(),
20
+ '~/.0xkobold',
21
+ '~/.openclaw',
22
+ ];
23
+ function expandPath(path) {
24
+ if (path.startsWith('~/')) {
25
+ return join(process.env.HOME ?? '', path.slice(2));
26
+ }
27
+ return resolve(path);
28
+ }
29
+ function isPathAllowed(path) {
30
+ const expanded = expandPath(path);
31
+ // Check blocked paths
32
+ for (const blocked of BLOCKED_PATHS) {
33
+ if (blocked && expanded.startsWith(expandPath(blocked))) {
34
+ return false;
35
+ }
36
+ }
37
+ return true;
38
+ }
39
+ export const readFileSkill = {
40
+ name: 'read_file',
41
+ description: 'Read the contents of a file',
42
+ risk: 'safe',
43
+ toolDefinition: {
44
+ type: 'function',
45
+ function: {
46
+ name: 'read_file',
47
+ description: 'Read a file from the filesystem',
48
+ parameters: {
49
+ type: 'object',
50
+ properties: {
51
+ path: {
52
+ type: 'string',
53
+ description: 'Path to the file (relative or absolute)',
54
+ },
55
+ offset: {
56
+ type: 'number',
57
+ description: 'Optional: line offset to start reading',
58
+ },
59
+ limit: {
60
+ type: 'number',
61
+ description: 'Optional: maximum lines to read (default: 100)',
62
+ },
63
+ },
64
+ required: ['path'],
65
+ },
66
+ },
67
+ },
68
+ async execute(args) {
69
+ const path = expandPath(args.path);
70
+ const offset = args.offset ?? 0;
71
+ const limit = args.limit ?? 100;
72
+ if (!isPathAllowed(path)) {
73
+ return { error: 'Path not allowed for security', path };
74
+ }
75
+ try {
76
+ const content = await readFile(path, 'utf-8');
77
+ const lines = content.split('\n');
78
+ const selected = lines.slice(offset, offset + limit);
79
+ return {
80
+ path,
81
+ content: selected.join('\n'),
82
+ totalLines: lines.length,
83
+ returnedLines: selected.length,
84
+ };
85
+ }
86
+ catch (err) {
87
+ return { error: err.message, path };
88
+ }
89
+ },
90
+ };
91
+ export const writeFileSkill = {
92
+ name: 'write_file',
93
+ description: 'Write content to a file (creates if not exists)',
94
+ risk: 'medium',
95
+ toolDefinition: {
96
+ type: 'function',
97
+ function: {
98
+ name: 'write_file',
99
+ description: 'Write content to a file',
100
+ parameters: {
101
+ type: 'object',
102
+ properties: {
103
+ path: {
104
+ type: 'string',
105
+ description: 'Path to the file',
106
+ },
107
+ content: {
108
+ type: 'string',
109
+ description: 'Content to write',
110
+ },
111
+ append: {
112
+ type: 'boolean',
113
+ description: 'Append instead of overwrite',
114
+ },
115
+ },
116
+ required: ['path', 'content'],
117
+ },
118
+ },
119
+ },
120
+ async execute(args) {
121
+ const path = expandPath(args.path);
122
+ const content = args.content;
123
+ const append = args.append;
124
+ if (!isPathAllowed(path)) {
125
+ return { error: 'Path not allowed for security', path };
126
+ }
127
+ try {
128
+ await writeFile(path, content, { flag: append ? 'a' : 'w' });
129
+ return { path, written: content.length, append };
130
+ }
131
+ catch (err) {
132
+ return { error: err.message, path };
133
+ }
134
+ },
135
+ };
136
+ export const listFilesSkill = {
137
+ name: 'list_files',
138
+ description: 'List files in a directory',
139
+ risk: 'safe',
140
+ toolDefinition: {
141
+ type: 'function',
142
+ function: {
143
+ name: 'list_files',
144
+ description: 'List files in a directory',
145
+ parameters: {
146
+ type: 'object',
147
+ properties: {
148
+ path: {
149
+ type: 'string',
150
+ description: 'Directory path (default: current)',
151
+ },
152
+ recursive: {
153
+ type: 'boolean',
154
+ description: 'List recursively',
155
+ },
156
+ },
157
+ },
158
+ },
159
+ },
160
+ async execute(args) {
161
+ const { readdir } = await import('fs/promises');
162
+ const path = expandPath(args.path ?? '.');
163
+ const recursive = args.recursive;
164
+ if (!isPathAllowed(path)) {
165
+ return { error: 'Path not allowed for security', path };
166
+ }
167
+ try {
168
+ const entries = await readdir(path, { recursive, withFileTypes: true });
169
+ return {
170
+ path,
171
+ files: entries.map(e => ({
172
+ name: e.name,
173
+ isDirectory: e.isDirectory(),
174
+ isFile: e.isFile(),
175
+ })),
176
+ };
177
+ }
178
+ catch (err) {
179
+ return { error: err.message, path };
180
+ }
181
+ },
182
+ };
183
+ export default [readFileSkill, writeFileSkill, listFilesSkill];
184
+ //# sourceMappingURL=file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file.js","sourceRoot":"","sources":["../../../../src/skills/builtin/file.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAgB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGrC,2BAA2B;AAC3B,MAAM,aAAa,GAAG;IACpB,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,aAAa;IACb,aAAa;IACb,OAAO,CAAC,GAAG,CAAC,YAAY;CACzB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAElB,4BAA4B;AAC5B,MAAM,aAAa,GAAG;IACpB,OAAO,CAAC,GAAG,EAAE;IACb,aAAa;IACb,aAAa;CACd,CAAC;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAElC,sBAAsB;IACtB,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,IAAI,OAAO,IAAI,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAU;IAClC,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,6BAA6B;IAC1C,IAAI,EAAE,MAAM;IAEZ,cAAc,EAAE;QACd,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,iCAAiC;YAC9C,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,yCAAyC;qBACvD;oBACD,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,wCAAwC;qBACtD;oBACD,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,gDAAgD;qBAC9D;iBACF;gBACD,QAAQ,EAAE,CAAC,MAAM,CAAC;aACnB;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAI,IAAI,CAAC,MAA6B,IAAI,CAAC,CAAC;QACxD,MAAM,KAAK,GAAI,IAAI,CAAC,KAA4B,IAAI,GAAG,CAAC;QAExD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,KAAK,EAAE,+BAA+B,EAAE,IAAI,EAAE,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;YAErD,OAAO;gBACL,IAAI;gBACJ,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC5B,UAAU,EAAE,KAAK,CAAC,MAAM;gBACxB,aAAa,EAAE,QAAQ,CAAC,MAAM;aAC/B,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAU;IACnC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,iDAAiD;IAC9D,IAAI,EAAE,QAAQ;IAEd,cAAc,EAAE;QACd,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,yBAAyB;YACtC,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,kBAAkB;qBAChC;oBACD,OAAO,EAAE;wBACP,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,kBAAkB;qBAChC;oBACD,MAAM,EAAE;wBACN,IAAI,EAAE,SAAS;wBACf,WAAW,EAAE,6BAA6B;qBAC3C;iBACF;gBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;aAC9B;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,IAAc,CAAC,CAAC;QAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAiB,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAA6B,CAAC;QAElD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,KAAK,EAAE,+BAA+B,EAAE,IAAI,EAAE,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;YAC7D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACnD,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAU;IACnC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,2BAA2B;IACxC,IAAI,EAAE,MAAM;IAEZ,cAAc,EAAE;QACd,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE;YACR,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,2BAA2B;YACxC,UAAU,EAAE;gBACV,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,IAAI,EAAE;wBACJ,IAAI,EAAE,QAAQ;wBACd,WAAW,EAAE,mCAAmC;qBACjD;oBACD,SAAS,EAAE;wBACT,IAAI,EAAE,SAAS;wBACf,WAAW,EAAE,kBAAkB;qBAChC;iBACF;aACF;SACF;KACF;IAED,KAAK,CAAC,OAAO,CAAC,IAA6B;QACzC,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,IAAI,GAAG,UAAU,CAAE,IAAI,CAAC,IAAe,IAAI,GAAG,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAgC,CAAC;QAExD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,KAAK,EAAE,+BAA+B,EAAE,IAAI,EAAE,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YACxE,OAAO;gBACL,IAAI;gBACJ,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBACvB,IAAI,EAAE,CAAC,CAAC,IAAI;oBACZ,WAAW,EAAE,CAAC,CAAC,WAAW,EAAE;oBAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;iBACnB,CAAC,CAAC;aACJ,CAAC;QACJ,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QACtC,CAAC;IACH,CAAC;CACF,CAAC;AAEF,eAAe,CAAC,aAAa,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC"}