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