@llmtune/cli 0.1.0 → 0.1.2

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 (198) hide show
  1. package/README.md +1 -1
  2. package/dist/agent/conversation.d.ts +42 -0
  3. package/dist/agent/conversation.js +105 -0
  4. package/dist/agent/loop.d.ts +19 -0
  5. package/dist/agent/loop.js +185 -0
  6. package/dist/agent/planner.d.ts +8 -0
  7. package/dist/agent/planner.js +43 -0
  8. package/dist/auth/client.d.ts +4 -0
  9. package/dist/auth/client.js +24 -0
  10. package/dist/auth/config.d.ts +21 -0
  11. package/dist/auth/config.js +83 -0
  12. package/dist/commands/chat.d.ts +5 -0
  13. package/dist/commands/chat.js +27 -0
  14. package/dist/commands/config.d.ts +2 -0
  15. package/dist/commands/config.js +37 -0
  16. package/dist/commands/login.d.ts +2 -0
  17. package/dist/commands/login.js +93 -0
  18. package/dist/commands/marketplace.d.ts +6 -0
  19. package/dist/commands/marketplace.js +213 -0
  20. package/dist/commands/models.d.ts +2 -0
  21. package/dist/commands/models.js +53 -0
  22. package/dist/compact/history-store.d.ts +29 -0
  23. package/dist/compact/history-store.js +110 -0
  24. package/dist/compact/microcompact.d.ts +10 -0
  25. package/dist/compact/microcompact.js +43 -0
  26. package/dist/compact/service.d.ts +13 -0
  27. package/dist/compact/service.js +156 -0
  28. package/dist/context/analyzer.d.ts +26 -0
  29. package/dist/context/analyzer.js +99 -0
  30. package/dist/context/builder.d.ts +13 -0
  31. package/dist/context/builder.js +144 -0
  32. package/dist/context/cache.d.ts +6 -0
  33. package/dist/context/cache.js +8 -0
  34. package/dist/context/git-context.d.ts +9 -0
  35. package/dist/context/git-context.js +39 -0
  36. package/dist/context/llmtune-md.d.ts +6 -0
  37. package/dist/context/llmtune-md.js +73 -0
  38. package/dist/context/workspace.d.ts +11 -0
  39. package/dist/context/workspace.js +115 -0
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.js +3 -2
  42. package/dist/marketplace/client.d.ts +52 -0
  43. package/dist/marketplace/client.js +86 -0
  44. package/dist/memory/files.d.ts +14 -0
  45. package/dist/memory/files.js +116 -0
  46. package/dist/memory/service.d.ts +22 -0
  47. package/dist/memory/service.js +146 -0
  48. package/dist/repl/repl.d.ts +8 -0
  49. package/dist/repl/repl.js +375 -0
  50. package/dist/skills/args.d.ts +10 -0
  51. package/dist/skills/args.js +37 -0
  52. package/dist/skills/frontmatter.d.ts +6 -0
  53. package/dist/skills/frontmatter.js +44 -0
  54. package/dist/skills/loader.d.ts +5 -0
  55. package/dist/skills/loader.js +59 -0
  56. package/dist/skills/registry.d.ts +27 -0
  57. package/dist/skills/registry.js +162 -0
  58. package/dist/skills/signing/signer.d.ts +19 -0
  59. package/dist/skills/signing/signer.js +110 -0
  60. package/dist/skills/trust.d.ts +11 -0
  61. package/dist/skills/trust.js +42 -0
  62. package/dist/telemetry/logger.d.ts +51 -0
  63. package/dist/telemetry/logger.js +135 -0
  64. package/dist/tools/permissions.d.ts +20 -0
  65. package/dist/tools/permissions.js +58 -0
  66. package/dist/tools/protocol.d.ts +22 -0
  67. package/dist/tools/protocol.js +3 -0
  68. package/dist/tools/registry.d.ts +20 -0
  69. package/dist/tools/registry.js +77 -0
  70. package/dist/tools/sandbox/docker.d.ts +16 -0
  71. package/dist/tools/sandbox/docker.js +240 -0
  72. package/dist/tools/sandbox/index.d.ts +18 -0
  73. package/dist/tools/sandbox/index.js +80 -0
  74. package/dist/tools/tools/ask-user.d.ts +3 -0
  75. package/dist/tools/tools/ask-user.js +56 -0
  76. package/dist/tools/tools/bash.d.ts +3 -0
  77. package/dist/tools/tools/bash.js +85 -0
  78. package/dist/tools/tools/edit.d.ts +3 -0
  79. package/dist/tools/tools/edit.js +138 -0
  80. package/dist/tools/tools/glob.d.ts +3 -0
  81. package/dist/tools/tools/glob.js +63 -0
  82. package/dist/tools/tools/grep.d.ts +3 -0
  83. package/dist/tools/tools/grep.js +148 -0
  84. package/dist/tools/tools/read.d.ts +3 -0
  85. package/dist/tools/tools/read.js +85 -0
  86. package/dist/tools/tools/web-fetch.d.ts +3 -0
  87. package/dist/tools/tools/web-fetch.js +143 -0
  88. package/dist/tools/tools/write.d.ts +3 -0
  89. package/dist/tools/tools/write.js +84 -0
  90. package/dist/tools/validation.d.ts +13 -0
  91. package/dist/tools/validation.js +142 -0
  92. package/dist/utils/markdown.d.ts +9 -0
  93. package/dist/utils/markdown.js +89 -0
  94. package/dist/utils/streaming.d.ts +10 -0
  95. package/dist/utils/streaming.js +63 -0
  96. package/dist/utils/tokens.d.ts +12 -0
  97. package/dist/utils/tokens.js +44 -0
  98. package/dist/version.d.ts +2 -0
  99. package/dist/version.js +9 -0
  100. package/package.json +2 -2
  101. package/dist/agent/conversation.d.ts.map +0 -1
  102. package/dist/agent/loop.d.ts.map +0 -1
  103. package/dist/agent/planner.d.ts.map +0 -1
  104. package/dist/auth/client.d.ts.map +0 -1
  105. package/dist/auth/config.d.ts.map +0 -1
  106. package/dist/commands/chat.d.ts.map +0 -1
  107. package/dist/commands/config.d.ts.map +0 -1
  108. package/dist/commands/login.d.ts.map +0 -1
  109. package/dist/commands/marketplace.d.ts.map +0 -1
  110. package/dist/commands/models.d.ts.map +0 -1
  111. package/dist/compact/history-store.d.ts.map +0 -1
  112. package/dist/compact/microcompact.d.ts.map +0 -1
  113. package/dist/compact/service.d.ts.map +0 -1
  114. package/dist/context/analyzer.d.ts.map +0 -1
  115. package/dist/context/builder.d.ts.map +0 -1
  116. package/dist/context/cache.d.ts.map +0 -1
  117. package/dist/context/git-context.d.ts.map +0 -1
  118. package/dist/context/llmtune-md.d.ts.map +0 -1
  119. package/dist/context/workspace.d.ts.map +0 -1
  120. package/dist/index.d.ts.map +0 -1
  121. package/dist/marketplace/client.d.ts.map +0 -1
  122. package/dist/memory/files.d.ts.map +0 -1
  123. package/dist/memory/service.d.ts.map +0 -1
  124. package/dist/repl/repl.d.ts.map +0 -1
  125. package/dist/skills/args.d.ts.map +0 -1
  126. package/dist/skills/frontmatter.d.ts.map +0 -1
  127. package/dist/skills/loader.d.ts.map +0 -1
  128. package/dist/skills/registry.d.ts.map +0 -1
  129. package/dist/skills/signing/signer.d.ts.map +0 -1
  130. package/dist/skills/trust.d.ts.map +0 -1
  131. package/dist/telemetry/logger.d.ts.map +0 -1
  132. package/dist/tools/permissions.d.ts.map +0 -1
  133. package/dist/tools/protocol.d.ts.map +0 -1
  134. package/dist/tools/registry.d.ts.map +0 -1
  135. package/dist/tools/sandbox/docker.d.ts.map +0 -1
  136. package/dist/tools/sandbox/index.d.ts.map +0 -1
  137. package/dist/tools/tools/ask-user.d.ts.map +0 -1
  138. package/dist/tools/tools/bash.d.ts.map +0 -1
  139. package/dist/tools/tools/edit.d.ts.map +0 -1
  140. package/dist/tools/tools/glob.d.ts.map +0 -1
  141. package/dist/tools/tools/grep.d.ts.map +0 -1
  142. package/dist/tools/tools/read.d.ts.map +0 -1
  143. package/dist/tools/tools/web-fetch.d.ts.map +0 -1
  144. package/dist/tools/tools/write.d.ts.map +0 -1
  145. package/dist/tools/validation.d.ts.map +0 -1
  146. package/dist/utils/markdown.d.ts.map +0 -1
  147. package/dist/utils/streaming.d.ts.map +0 -1
  148. package/dist/utils/tokens.d.ts.map +0 -1
  149. package/src/agent/conversation.ts +0 -140
  150. package/src/agent/loop.ts +0 -215
  151. package/src/agent/planner.ts +0 -55
  152. package/src/auth/client.ts +0 -19
  153. package/src/auth/config.ts +0 -89
  154. package/src/commands/chat.ts +0 -28
  155. package/src/commands/config.ts +0 -36
  156. package/src/commands/login.ts +0 -63
  157. package/src/commands/marketplace.ts +0 -190
  158. package/src/commands/models.ts +0 -74
  159. package/src/compact/history-store.ts +0 -101
  160. package/src/compact/microcompact.ts +0 -49
  161. package/src/compact/service.ts +0 -154
  162. package/src/context/analyzer.ts +0 -127
  163. package/src/context/builder.ts +0 -123
  164. package/src/context/cache.ts +0 -11
  165. package/src/context/git-context.ts +0 -58
  166. package/src/context/llmtune-md.ts +0 -48
  167. package/src/context/workspace.ts +0 -139
  168. package/src/index.ts +0 -100
  169. package/src/marketplace/client.ts +0 -118
  170. package/src/memory/files.ts +0 -81
  171. package/src/memory/service.ts +0 -124
  172. package/src/repl/repl.ts +0 -400
  173. package/src/skills/args.ts +0 -35
  174. package/src/skills/builtin/explain-code/SKILL.md +0 -30
  175. package/src/skills/frontmatter.ts +0 -47
  176. package/src/skills/loader.ts +0 -25
  177. package/src/skills/registry.ts +0 -155
  178. package/src/skills/signing/signer.ts +0 -101
  179. package/src/skills/trust.ts +0 -50
  180. package/src/telemetry/logger.ts +0 -108
  181. package/src/tools/permissions.ts +0 -83
  182. package/src/tools/protocol.ts +0 -24
  183. package/src/tools/registry.ts +0 -93
  184. package/src/tools/sandbox/docker.ts +0 -225
  185. package/src/tools/sandbox/index.ts +0 -91
  186. package/src/tools/tools/ask-user.ts +0 -60
  187. package/src/tools/tools/bash.ts +0 -97
  188. package/src/tools/tools/edit.ts +0 -111
  189. package/src/tools/tools/glob.ts +0 -68
  190. package/src/tools/tools/grep.ts +0 -121
  191. package/src/tools/tools/read.ts +0 -57
  192. package/src/tools/tools/web-fetch.ts +0 -158
  193. package/src/tools/tools/write.ts +0 -52
  194. package/src/tools/validation.ts +0 -164
  195. package/src/utils/markdown.ts +0 -96
  196. package/src/utils/streaming.ts +0 -63
  197. package/src/utils/tokens.ts +0 -41
  198. package/tsconfig.json +0 -20
@@ -0,0 +1,375 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.startRepl = startRepl;
40
+ const chalk_1 = __importDefault(require("chalk"));
41
+ const readline_1 = require("readline");
42
+ const conversation_1 = require("../agent/conversation");
43
+ const registry_1 = require("../tools/registry");
44
+ const loop_1 = require("../agent/loop");
45
+ const read_1 = require("../tools/tools/read");
46
+ const write_1 = require("../tools/tools/write");
47
+ const edit_1 = require("../tools/tools/edit");
48
+ const bash_1 = require("../tools/tools/bash");
49
+ const glob_1 = require("../tools/tools/glob");
50
+ const grep_1 = require("../tools/tools/grep");
51
+ const web_fetch_1 = require("../tools/tools/web-fetch");
52
+ const ask_user_1 = require("../tools/tools/ask-user");
53
+ const service_1 = require("../compact/service");
54
+ const analyzer_1 = require("../context/analyzer");
55
+ const loader_1 = require("../skills/loader");
56
+ const trust_1 = require("../skills/trust");
57
+ const service_2 = require("../memory/service");
58
+ const logger_1 = require("../telemetry/logger");
59
+ const config_1 = require("../auth/config");
60
+ const version_1 = require("../version");
61
+ const fs = __importStar(require("fs"));
62
+ const path = __importStar(require("path"));
63
+ const HELP_TEXT = `
64
+ ${chalk_1.default.bold("LLMTune CLI - Commands:")}
65
+
66
+ ${chalk_1.default.cyan("/help")} Show this help
67
+ ${chalk_1.default.cyan("/clear")} Clear conversation history
68
+ ${chalk_1.default.cyan("/context")} Show detailed context usage breakdown
69
+ ${chalk_1.default.cyan("/compact")} Compact conversation (LLM summary)
70
+ ${chalk_1.default.cyan("/uncompact")} Restore conversation from before compaction
71
+ ${chalk_1.default.cyan("/model <name>")} Switch model
72
+ ${chalk_1.default.cyan("/stream")} Toggle streaming mode
73
+ ${chalk_1.default.cyan("/verbose")} Toggle verbose tool output
74
+ ${chalk_1.default.cyan("/trust <tool>")} Trust a tool (skip confirmations)
75
+ ${chalk_1.default.cyan("/skills")} List available skills
76
+ ${chalk_1.default.cyan("/memory")} Show memory contents
77
+ ${chalk_1.default.cyan("/save")} Save conversation to file
78
+ ${chalk_1.default.cyan("/exit")} Exit REPL
79
+
80
+ ${chalk_1.default.gray("Type your message and press Enter to chat.")}
81
+ ${chalk_1.default.gray("Multi-line: end a line with '\\' to continue.")}
82
+ `.trim();
83
+ async function startRepl(options) {
84
+ const registry = new registry_1.ToolRegistry();
85
+ const cwd = process.cwd();
86
+ const trustedTools = new Set();
87
+ registry.register(read_1.readTool);
88
+ registry.register(write_1.writeTool);
89
+ registry.register(edit_1.editTool);
90
+ registry.register(bash_1.bashTool);
91
+ registry.register(glob_1.globTool);
92
+ registry.register(grep_1.grepTool);
93
+ registry.register(web_fetch_1.webFetchTool);
94
+ registry.register(ask_user_1.askUserTool);
95
+ const conversation = new conversation_1.Conversation(options.model);
96
+ // Load skills
97
+ const skills = (0, loader_1.loadAllSkills)(cwd);
98
+ const skillList = skills.listUserInvocable();
99
+ // Initialize memory
100
+ (0, service_2.initMemoryFiles)();
101
+ // Start telemetry
102
+ (0, logger_1.startSessionLog)(conversation.id, {
103
+ model: options.model,
104
+ tools: registry.listSpecs().map((s) => s.name),
105
+ cwd,
106
+ });
107
+ let currentModel = options.model;
108
+ let streamMode = options.stream;
109
+ let verbose = false;
110
+ console.log(chalk_1.default.cyan(`\nLLMTune CLI v${version_1.CLI_VERSION}`));
111
+ console.log(chalk_1.default.dim(`Model: ${currentModel}`));
112
+ console.log(chalk_1.default.dim(`Tools: ${registry.listSpecs().map((s) => s.name).join(", ")}`));
113
+ if (skillList.length > 0) {
114
+ console.log(chalk_1.default.dim(`Skills: ${skillList.map((s) => s.name).join(", ")}`));
115
+ }
116
+ console.log(chalk_1.default.dim(`Type /help for commands, /exit to quit.\n`));
117
+ const rl = (0, readline_1.createInterface)({
118
+ input: process.stdin,
119
+ output: process.stdout,
120
+ prompt: chalk_1.default.blue("> "),
121
+ });
122
+ rl.prompt();
123
+ let multiLineBuffer = "";
124
+ rl.on("line", async (line) => {
125
+ const trimmed = line.trim();
126
+ if (trimmed.endsWith("\\")) {
127
+ multiLineBuffer += trimmed.slice(0, -1) + "\n";
128
+ process.stdout.write(chalk_1.default.dim("... "));
129
+ return;
130
+ }
131
+ const fullInput = multiLineBuffer + trimmed;
132
+ multiLineBuffer = "";
133
+ if (!fullInput) {
134
+ rl.prompt();
135
+ return;
136
+ }
137
+ // Check for skill execution: /skill-name [args]
138
+ if (fullInput.startsWith("/") && !fullInput.startsWith("/help") && !fullInput.startsWith("/exit") && !fullInput.startsWith("/quit") && !fullInput.startsWith("/clear") && !fullInput.startsWith("/context") && !fullInput.startsWith("/compact") && !fullInput.startsWith("/uncompact") && !fullInput.startsWith("/model") && !fullInput.startsWith("/stream") && !fullInput.startsWith("/verbose") && !fullInput.startsWith("/trust") && !fullInput.startsWith("/skills") && !fullInput.startsWith("/memory") && !fullInput.startsWith("/save")) {
139
+ const parts = fullInput.slice(1).split(/\s+/);
140
+ const skillName = parts[0];
141
+ const skillArgs = parts.slice(1);
142
+ const execution = skills.prepareExecution(skillName, skillArgs);
143
+ if (execution) {
144
+ const skill = skills.get(skillName);
145
+ console.log(chalk_1.default.magenta(`Executing skill: ${skill.name}`));
146
+ const trustLevel = (0, trust_1.resolveTrustLevel)(skill);
147
+ const toolNames = registry.listSpecs().map((s) => s.name);
148
+ for (const toolName of toolNames) {
149
+ if (!(0, trust_1.isToolAllowedForSkill)(toolName, trustLevel)) {
150
+ console.log(chalk_1.default.yellow(` Warning: tool "${toolName}" not allowed for skill trust level "${trustLevel}"`));
151
+ }
152
+ }
153
+ // Add skill system prompt and user message
154
+ conversation.addSystemMessage(execution.systemPrompt);
155
+ conversation.addUserMessage(execution.userMessage);
156
+ try {
157
+ const result = await (0, loop_1.runAgentLoop)(options.client, conversation, registry, execution.userMessage, {
158
+ model: currentModel,
159
+ maxTurns: 50,
160
+ verbose,
161
+ cwd,
162
+ workspaceRoot: cwd,
163
+ });
164
+ (0, logger_1.logEvent)({ event: "tool_call", tool: skillName, latency_ms: 0 });
165
+ }
166
+ catch (err) {
167
+ const msg = err instanceof Error ? err.message : String(err);
168
+ console.log(chalk_1.default.red(`\nSkill error: ${msg}`));
169
+ }
170
+ console.log("");
171
+ rl.prompt();
172
+ return;
173
+ }
174
+ }
175
+ if (fullInput.startsWith("/")) {
176
+ await handleCommand(fullInput, {
177
+ rl,
178
+ conversation,
179
+ registry,
180
+ skills,
181
+ trustedTools,
182
+ cwd,
183
+ client: options.client,
184
+ getModel: () => currentModel,
185
+ setModel: (m) => {
186
+ currentModel = m;
187
+ },
188
+ getStream: () => streamMode,
189
+ setStream: (s) => {
190
+ streamMode = s;
191
+ },
192
+ getVerbose: () => verbose,
193
+ setVerbose: (v) => {
194
+ verbose = v;
195
+ },
196
+ });
197
+ rl.prompt();
198
+ return;
199
+ }
200
+ // Normal chat
201
+ try {
202
+ const result = await (0, loop_1.runAgentLoop)(options.client, conversation, registry, fullInput, {
203
+ model: currentModel,
204
+ maxTurns: 50,
205
+ verbose,
206
+ cwd,
207
+ workspaceRoot: cwd,
208
+ });
209
+ if (result.totalTokensIn > 0 || result.totalTokensOut > 0) {
210
+ const cost = estimateCostFromUsage(result.totalTokensIn, result.totalTokensOut);
211
+ console.log(chalk_1.default.dim(` [${result.turns} turn${result.turns !== 1 ? "s" : ""} | ` +
212
+ `${result.totalToolCalls} tool calls | ` +
213
+ `${result.totalTokensIn + result.totalTokensOut} tokens | ` +
214
+ `~$${cost.toFixed(4)}]`));
215
+ (0, logger_1.logEvent)({
216
+ event: "llm_response",
217
+ model: currentModel,
218
+ tokens_in: result.totalTokensIn,
219
+ tokens_out: result.totalTokensOut,
220
+ cost,
221
+ latency_ms: 0,
222
+ });
223
+ }
224
+ }
225
+ catch (err) {
226
+ const msg = err instanceof Error ? err.message : String(err);
227
+ console.log(chalk_1.default.red(`\nError: ${msg}`));
228
+ (0, logger_1.logEvent)({ event: "error", source: "agent_loop", error: msg });
229
+ }
230
+ console.log("");
231
+ rl.prompt();
232
+ });
233
+ rl.on("close", () => {
234
+ (0, logger_1.endSessionLog)({ totalToolCalls: 0, totalTokens: 0 });
235
+ console.log(chalk_1.default.dim("\nGoodbye!"));
236
+ process.exit(0);
237
+ });
238
+ }
239
+ async function handleCommand(input, ctx) {
240
+ const parts = input.split(/\s+/);
241
+ const cmd = parts[0].toLowerCase();
242
+ const args = parts.slice(1);
243
+ switch (cmd) {
244
+ case "/help":
245
+ case "/h":
246
+ case "/?":
247
+ console.log(HELP_TEXT);
248
+ break;
249
+ case "/exit":
250
+ case "/quit":
251
+ case "/q":
252
+ console.log(chalk_1.default.dim("Goodbye!"));
253
+ process.exit(0);
254
+ case "/clear":
255
+ ctx.conversation.messages.length = 0;
256
+ console.log(chalk_1.default.green("Conversation cleared."));
257
+ break;
258
+ case "/context": {
259
+ const analysis = (0, analyzer_1.analyzeContextUsage)({
260
+ systemPrompt: "LLMTune coding agent",
261
+ toolSpecs: ctx.registry.listSpecs(),
262
+ messages: ctx.conversation.getApiMessages().map((m) => ({
263
+ role: m.role,
264
+ content: m.content,
265
+ })),
266
+ skillsContent: ctx.skills.list().map((s) => s.content).join("\n") || undefined,
267
+ memoryContent: (0, service_2.buildMemoryPrompt)() || undefined,
268
+ model: ctx.getModel(),
269
+ });
270
+ console.log((0, analyzer_1.formatContextAnalysis)(analysis));
271
+ break;
272
+ }
273
+ case "/compact": {
274
+ if (ctx.conversation.messages.length < 3) {
275
+ console.log(chalk_1.default.yellow("Not enough messages to compact (need at least 3)."));
276
+ break;
277
+ }
278
+ console.log(chalk_1.default.dim("Compacting conversation..."));
279
+ try {
280
+ const result = await (0, service_1.compactConversation)(ctx.client, ctx.getModel(), ctx.conversation);
281
+ console.log(chalk_1.default.green(`\nCompacted: ${result.preCompactMessages} -> ${result.postCompactMessages} messages`));
282
+ console.log(chalk_1.default.dim(` Tokens saved: ~${result.tokensSaved.toLocaleString()}`));
283
+ console.log(chalk_1.default.dim(` Use /uncompact to restore full history.`));
284
+ (0, logger_1.logEvent)({ event: "compaction", tokens_saved: result.tokensSaved, messages_before: result.preCompactMessages, messages_after: result.postCompactMessages, trigger: "manual" });
285
+ }
286
+ catch (err) {
287
+ const msg = err instanceof Error ? err.message : String(err);
288
+ console.log(chalk_1.default.red(`Compaction failed: ${msg}`));
289
+ }
290
+ break;
291
+ }
292
+ case "/uncompact": {
293
+ const restored = (0, service_1.uncompactConversation)(ctx.conversation);
294
+ if (restored) {
295
+ console.log(chalk_1.default.green(`Restored conversation from before compaction (${ctx.conversation.messages.length} messages).`));
296
+ }
297
+ else {
298
+ console.log(chalk_1.default.yellow("No raw history found to restore."));
299
+ }
300
+ break;
301
+ }
302
+ case "/model":
303
+ if (args[0]) {
304
+ ctx.setModel(args[0]);
305
+ console.log(chalk_1.default.green(`Model set to: ${args[0]}`));
306
+ }
307
+ else {
308
+ console.log(chalk_1.default.dim(`Current model: ${ctx.getModel()}`));
309
+ }
310
+ break;
311
+ case "/stream":
312
+ ctx.setStream(!ctx.getStream());
313
+ console.log(chalk_1.default.green(`Streaming: ${ctx.getStream() ? "on" : "off"}`));
314
+ break;
315
+ case "/verbose":
316
+ ctx.setVerbose(!ctx.getVerbose());
317
+ console.log(chalk_1.default.green(`Verbose: ${ctx.getVerbose() ? "on" : "off"}`));
318
+ break;
319
+ case "/trust":
320
+ if (args[0]) {
321
+ ctx.trustedTools.add(args[0].toLowerCase());
322
+ console.log(chalk_1.default.green(`Trusting tool: ${args[0]} (no confirmation needed)`));
323
+ }
324
+ else {
325
+ console.log(chalk_1.default.dim("Usage: /trust <tool-name>"));
326
+ }
327
+ break;
328
+ case "/skills": {
329
+ const allSkills = ctx.skills.listUserInvocable();
330
+ if (allSkills.length === 0) {
331
+ console.log(chalk_1.default.dim("No skills loaded. Create skills in ~/.llmtune/skills/ or .llmtune/skills/"));
332
+ console.log(chalk_1.default.dim("Each skill is a directory with a SKILL.md file."));
333
+ }
334
+ else {
335
+ console.log(chalk_1.default.bold("\nAvailable Skills:"));
336
+ for (const skill of allSkills) {
337
+ const trustLabel = skill.trustLevel;
338
+ console.log(` ${chalk_1.default.cyan(`/${skill.name}`)} - ${skill.description} ${chalk_1.default.dim(`[${trustLabel}]`)}`);
339
+ }
340
+ console.log("");
341
+ }
342
+ break;
343
+ }
344
+ case "/memory": {
345
+ const entries = (0, service_2.readAllMemory)();
346
+ if (entries.length === 0) {
347
+ console.log(chalk_1.default.dim("\nNo memory entries. The agent will auto-populate memory as you chat."));
348
+ console.log(chalk_1.default.dim(`Memory directory: ${(0, config_1.getConfigDir)()}/memory/\n`));
349
+ }
350
+ else {
351
+ console.log(chalk_1.default.bold("\nMemory:"));
352
+ for (const entry of entries) {
353
+ if (entry.content.trim()) {
354
+ const preview = entry.content.slice(0, 100).replace(/\n/g, " ");
355
+ console.log(` ${chalk_1.default.cyan(entry.category)}: ${chalk_1.default.dim(preview)}${entry.content.length > 100 ? "..." : ""}`);
356
+ }
357
+ }
358
+ console.log("");
359
+ }
360
+ break;
361
+ }
362
+ case "/save": {
363
+ const savePath = path.join(process.cwd(), `llmtune-session-${Date.now()}.json`);
364
+ fs.writeFileSync(savePath, JSON.stringify(ctx.conversation.getApiMessages(), null, 2), "utf-8");
365
+ console.log(chalk_1.default.green(`Session saved to: ${savePath}`));
366
+ break;
367
+ }
368
+ default:
369
+ console.log(chalk_1.default.yellow(`Unknown command: ${cmd}. Type /help for available commands.`));
370
+ }
371
+ }
372
+ function estimateCostFromUsage(inputTokens, outputTokens) {
373
+ return (inputTokens * 3 + outputTokens * 15) / 1_000_000;
374
+ }
375
+ //# sourceMappingURL=repl.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Parse argument names from a skill's frontmatter "arguments" field.
3
+ * Supports: "arg1 arg2", "arg1, arg2", "$arg1 $arg2"
4
+ */
5
+ export declare function parseArgumentNames(raw: unknown): string[];
6
+ /**
7
+ * Substitute {{arg}} placeholders in skill content with provided values.
8
+ */
9
+ export declare function substituteArguments(content: string, args: Record<string, string>): string;
10
+ //# sourceMappingURL=args.d.ts.map
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseArgumentNames = parseArgumentNames;
4
+ exports.substituteArguments = substituteArguments;
5
+ /**
6
+ * Parse argument names from a skill's frontmatter "arguments" field.
7
+ * Supports: "arg1 arg2", "arg1, arg2", "$arg1 $arg2"
8
+ */
9
+ function parseArgumentNames(raw) {
10
+ if (!raw)
11
+ return [];
12
+ const str = String(raw).trim();
13
+ if (!str)
14
+ return [];
15
+ // Split by comma or space, strip $ prefixes
16
+ return str
17
+ .split(/[,\s]+/)
18
+ .map((s) => s.trim().replace(/^\$/, ""))
19
+ .filter(Boolean);
20
+ }
21
+ /**
22
+ * Substitute {{arg}} placeholders in skill content with provided values.
23
+ */
24
+ function substituteArguments(content, args) {
25
+ let result = content;
26
+ for (const [key, value] of Object.entries(args)) {
27
+ const patterns = [
28
+ new RegExp(`\\{\\{${key}\\}\\}`, "g"),
29
+ new RegExp(`\\$\\{${key}\\}`, "g"),
30
+ ];
31
+ for (const pattern of patterns) {
32
+ result = result.replace(pattern, value);
33
+ }
34
+ }
35
+ return result;
36
+ }
37
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1,6 @@
1
+ export interface FrontmatterResult {
2
+ frontmatter: Record<string, unknown>;
3
+ body: string;
4
+ }
5
+ export declare function parseFrontmatter(content: string): FrontmatterResult;
6
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseFrontmatter = parseFrontmatter;
4
+ function parseFrontmatter(content) {
5
+ const trimmed = content.trimStart();
6
+ if (!trimmed.startsWith("---")) {
7
+ return { frontmatter: {}, body: content };
8
+ }
9
+ const endMatch = trimmed.indexOf("---", 3);
10
+ if (endMatch === -1 || endMatch < 4) {
11
+ return { frontmatter: {}, body: content };
12
+ }
13
+ const frontmatterStr = trimmed.slice(3, endMatch).trim();
14
+ const body = trimmed.slice(endMatch + 3).trimStart();
15
+ const frontmatter = {};
16
+ for (const line of frontmatterStr.split("\n")) {
17
+ const colonIdx = line.indexOf(":");
18
+ if (colonIdx === -1)
19
+ continue;
20
+ const key = line.slice(0, colonIdx).trim();
21
+ let value = line.slice(colonIdx + 1).trim();
22
+ if (typeof value === "string") {
23
+ if (value === "true")
24
+ value = true;
25
+ else if (value === "false")
26
+ value = false;
27
+ else if (/^\d+$/.test(value))
28
+ value = Number(value);
29
+ else if (value.startsWith("[") && value.endsWith("]")) {
30
+ value = value
31
+ .slice(1, -1)
32
+ .split(",")
33
+ .map((s) => s.trim())
34
+ .filter(Boolean);
35
+ }
36
+ else {
37
+ value = value.replace(/^["']|["']$/g, "");
38
+ }
39
+ }
40
+ frontmatter[key] = value;
41
+ }
42
+ return { frontmatter, body };
43
+ }
44
+ //# sourceMappingURL=frontmatter.js.map
@@ -0,0 +1,5 @@
1
+ import { SkillRegistry } from "./registry";
2
+ export declare function loadAllSkills(projectRoot?: string): SkillRegistry;
3
+ export declare function getDefaultSkillsDirs(): string[];
4
+ export declare function getProjectSkillsDir(projectRoot: string): string;
5
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.loadAllSkills = loadAllSkills;
37
+ exports.getDefaultSkillsDirs = getDefaultSkillsDirs;
38
+ exports.getProjectSkillsDir = getProjectSkillsDir;
39
+ const path = __importStar(require("path"));
40
+ const os = __importStar(require("os"));
41
+ const registry_1 = require("./registry");
42
+ function loadAllSkills(projectRoot) {
43
+ const registry = new registry_1.SkillRegistry();
44
+ registry.loadAll(projectRoot);
45
+ return registry;
46
+ }
47
+ function getDefaultSkillsDirs() {
48
+ const dirs = [];
49
+ const home = os.homedir();
50
+ const envDir = process.env.LLMTUNE_SKILLS_DIR;
51
+ if (envDir)
52
+ dirs.push(path.resolve(envDir));
53
+ dirs.push(path.join(home, ".llmtune", "skills"));
54
+ return dirs;
55
+ }
56
+ function getProjectSkillsDir(projectRoot) {
57
+ return path.join(projectRoot, ".llmtune", "skills");
58
+ }
59
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1,27 @@
1
+ export interface Skill {
2
+ name: string;
3
+ description: string;
4
+ content: string;
5
+ loadedFrom: "user" | "project" | "managed";
6
+ userInvocable: boolean;
7
+ allowedTools: string[];
8
+ argNames: string[];
9
+ trustLevel: TrustLevel;
10
+ skillRoot: string;
11
+ }
12
+ export type TrustLevel = "local" | "community" | "verified" | "signed";
13
+ export interface SkillExecution {
14
+ systemPrompt: string;
15
+ userMessage: string;
16
+ allowedTools?: string[];
17
+ }
18
+ export declare class SkillRegistry {
19
+ private skills;
20
+ loadAll(projectRoot?: string): void;
21
+ private loadFromDir;
22
+ get(name: string): Skill | undefined;
23
+ list(): Skill[];
24
+ listUserInvocable(): Skill[];
25
+ prepareExecution(name: string, args: string[]): SkillExecution | null;
26
+ }
27
+ //# sourceMappingURL=registry.d.ts.map