krims-code-cli 1.5.2__py3-none-any.whl

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 (43) hide show
  1. krims_code_cli-1.5.2.dist-info/METADATA +336 -0
  2. krims_code_cli-1.5.2.dist-info/RECORD +43 -0
  3. krims_code_cli-1.5.2.dist-info/WHEEL +5 -0
  4. krims_code_cli-1.5.2.dist-info/entry_points.txt +2 -0
  5. krims_code_cli-1.5.2.dist-info/licenses/LICENSE +21 -0
  6. krims_code_cli-1.5.2.dist-info/top_level.txt +1 -0
  7. krims_pip/__init__.py +1 -0
  8. krims_pip/cli.py +50 -0
  9. krims_pip/node_project/bin/krims-code.js +10 -0
  10. krims_pip/node_project/package-lock.json +793 -0
  11. krims_pip/node_project/package.json +46 -0
  12. krims_pip/node_project/src/agent.js +415 -0
  13. krims_pip/node_project/src/ai/fallback.js +239 -0
  14. krims_pip/node_project/src/ai/google.js +87 -0
  15. krims_pip/node_project/src/ai/providers.js +203 -0
  16. krims_pip/node_project/src/ai/router.js +146 -0
  17. krims_pip/node_project/src/ai/search.js +94 -0
  18. krims_pip/node_project/src/ai/telemetry.js +125 -0
  19. krims_pip/node_project/src/ai/tokens.js +101 -0
  20. krims_pip/node_project/src/ai/universal.js +507 -0
  21. krims_pip/node_project/src/ai/xai.js +50 -0
  22. krims_pip/node_project/src/chat.js +2543 -0
  23. krims_pip/node_project/src/cli.js +632 -0
  24. krims_pip/node_project/src/commands/commit.js +157 -0
  25. krims_pip/node_project/src/commands/dashboard.js +59 -0
  26. krims_pip/node_project/src/commands/github.js +349 -0
  27. krims_pip/node_project/src/commands/index.js +67 -0
  28. krims_pip/node_project/src/commands/status.js +66 -0
  29. krims_pip/node_project/src/commands/teamwork-preview.js +326 -0
  30. krims_pip/node_project/src/commands/theme.js +42 -0
  31. krims_pip/node_project/src/commands/themes.js +30 -0
  32. krims_pip/node_project/src/config.js +400 -0
  33. krims_pip/node_project/src/dashboard.js +112 -0
  34. krims_pip/node_project/src/file-parser.js +164 -0
  35. krims_pip/node_project/src/git.js +41 -0
  36. krims_pip/node_project/src/mic.js +220 -0
  37. krims_pip/node_project/src/modes.js +92 -0
  38. krims_pip/node_project/src/telemetry-server.js +855 -0
  39. krims_pip/node_project/src/ui/banner.js +204 -0
  40. krims_pip/node_project/src/ui/dashboard.html +834 -0
  41. krims_pip/node_project/src/ui/spinner.js +43 -0
  42. krims_pip/node_project/src/ui/theme.js +624 -0
  43. krims_pip/node_project/src/updater.js +196 -0
@@ -0,0 +1,66 @@
1
+ import { getAIConfig, configExists, getConfigPath } from "../config.js";
2
+ import { getActiveProviders } from "../ai/providers.js";
3
+ import { colors, separator, keyValue, label, getActiveTheme } from "../ui/theme.js";
4
+ import { readFileSync } from "node:fs";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const pkg = JSON.parse(readFileSync(join(__dirname, "../../package.json"), "utf8"));
11
+ const VERSION = pkg.version;
12
+
13
+ export default {
14
+ name: "status",
15
+ description: "Show system status & configured providers",
16
+ aliases: [],
17
+ options: [],
18
+ async executeCLI(args, options) {
19
+ const aiConfig = await getAIConfig();
20
+ const exists = await configExists();
21
+ const active = getActiveProviders(aiConfig);
22
+
23
+ console.log("");
24
+ console.log(colors.brand(" ⚡ Krims Code SYSTEM STATUS"));
25
+ console.log(separator("─"));
26
+ console.log(keyValue(" Version", `v${VERSION}`));
27
+ console.log(keyValue(" Config", exists ? colors.success("✓ Found") : colors.warning("✗ Not found")));
28
+ console.log(keyValue(" Location", getConfigPath()));
29
+
30
+ console.log("");
31
+ console.log(colors.accent(" ◈ Active Providers:"));
32
+ if (active.length === 0) {
33
+ console.log(" " + colors.warning(" No providers configured. Run `Krims Code setup` to get started."));
34
+ } else {
35
+ for (const { id, provider } of active) {
36
+ console.log(" " + colors.success(" ✓ ") + colors.text(provider.name) + colors.dim(` (${provider.defaultModel})`));
37
+ }
38
+ }
39
+
40
+ console.log("");
41
+ console.log(colors.accent(" ◈ Local Fallbacks:"));
42
+ console.log(keyValue(" Math Solver", colors.success("✓ Active")));
43
+ console.log(keyValue(" Krylo Companion", colors.success("✓ Standing By")));
44
+
45
+ console.log("");
46
+ console.log(colors.accent(" ◈ Failover Mesh:"));
47
+ const totalNodes = 1 + active.length; // +1 for local offline fallback
48
+ console.log(keyValue(" Active Nodes", `${totalNodes}`));
49
+ console.log(keyValue(" Mesh Status", active.length > 0 ? colors.success("✓ Online") : colors.warning("⚠ Local Only")));
50
+ console.log("");
51
+ },
52
+ async executeChat(args, ctx) {
53
+ const active = getActiveProviders(ctx.aiConfig);
54
+
55
+ console.log("");
56
+ console.log(colors.brand(" ◈ SESSION STATUS"));
57
+ console.log(separator("─"));
58
+ console.log(keyValue(" Theme", getActiveTheme().toUpperCase()));
59
+ console.log(keyValue(" Mode", ctx.currentMode.label));
60
+ console.log(keyValue(" Layer", ctx.currentMode.layer));
61
+ console.log(keyValue(" Exchanges", String(Math.floor(ctx.history.length / 2))));
62
+ console.log(keyValue(" Files", String(ctx.attachedFiles.length)));
63
+ console.log(keyValue(" Providers", String(active.length)));
64
+ console.log("");
65
+ }
66
+ };
@@ -0,0 +1,326 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { colors, separator, label } from '../ui/theme.js';
4
+
5
+ export function parseArgs(args) {
6
+ const options = { watch: false, agent: null };
7
+ for (let i = 0; i < args.length; i++) {
8
+ const arg = args[i];
9
+ if (arg === '-w' || arg === '--watch') {
10
+ options.watch = true;
11
+ } else if (arg === '-a' || arg === '--agent') {
12
+ options.agent = args[i + 1] || null;
13
+ i++;
14
+ } else if (arg.startsWith('--agent=')) {
15
+ options.agent = arg.split('=')[1] || null;
16
+ }
17
+ }
18
+ return options;
19
+ }
20
+
21
+ export function parseAgentState(name, agentPath, currentTime = new Date()) {
22
+ let mission = 'Unknown';
23
+ let lastVisited = null;
24
+ let status = 'STALE';
25
+ let heartbeatText = 'Never';
26
+
27
+ const briefingPath = path.join(agentPath, 'BRIEFING.md');
28
+ if (fs.existsSync(briefingPath)) {
29
+ const content = fs.readFileSync(briefingPath, 'utf8');
30
+ const lines = content.split(/\r?\n/);
31
+ const missionIdx = lines.findIndex(l => l.trim().startsWith('## Mission'));
32
+ if (missionIdx !== -1) {
33
+ for (let i = missionIdx + 1; i < lines.length; i++) {
34
+ const line = lines[i].trim();
35
+ if (line.startsWith('#')) break;
36
+ if (line) {
37
+ mission = line;
38
+ break;
39
+ }
40
+ }
41
+ }
42
+ if (mission === 'Unknown' || mission.includes('[') || mission.includes('TBD')) {
43
+ const milestoneMatch = content.match(/-\s*Milestone:\s*([^\r\n]+)/i);
44
+ if (milestoneMatch) {
45
+ mission = milestoneMatch[1].trim();
46
+ } else {
47
+ const focusMatch = content.match(/-\s*Focus:\s*([^\r\n]+)/i);
48
+ if (focusMatch) {
49
+ mission = focusMatch[1].trim();
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ const progressPath = path.join(agentPath, 'progress.md');
56
+ if (fs.existsSync(progressPath)) {
57
+ const content = fs.readFileSync(progressPath, 'utf8');
58
+ const match = content.match(/Last visited:\s*([^\r\n]+)/i);
59
+ if (match) {
60
+ const parsedDate = new Date(match[1].trim());
61
+ if (!isNaN(parsedDate.getTime())) {
62
+ lastVisited = parsedDate;
63
+ }
64
+ }
65
+ }
66
+
67
+ const hasHandoff = fs.existsSync(path.join(agentPath, 'handoff.md'));
68
+
69
+ if (lastVisited) {
70
+ const diffMs = currentTime.getTime() - lastVisited.getTime();
71
+ const diffMins = Math.floor(diffMs / 60000);
72
+ if (diffMs > 10 * 60 * 1000) {
73
+ status = 'STALE';
74
+ } else {
75
+ status = 'ACTIVE';
76
+ }
77
+ if (diffMins <= 0) {
78
+ heartbeatText = 'Just now';
79
+ } else {
80
+ heartbeatText = `${diffMins}m ago`;
81
+ }
82
+ } else {
83
+ status = 'STALE';
84
+ heartbeatText = 'Never';
85
+ }
86
+
87
+ if (hasHandoff) {
88
+ status = 'COMPLETED';
89
+ }
90
+
91
+ return {
92
+ name,
93
+ status,
94
+ heartbeat: heartbeatText,
95
+ mission
96
+ };
97
+ }
98
+
99
+ export function scanAgents(agentsDir, currentTime = new Date()) {
100
+ if (!fs.existsSync(agentsDir)) {
101
+ return [];
102
+ }
103
+ const files = fs.readdirSync(agentsDir, { withFileTypes: true });
104
+ const agents = [];
105
+ for (const file of files) {
106
+ if (!file.isDirectory()) continue;
107
+ if (file.name.startsWith('.')) continue;
108
+
109
+ const agentPath = path.join(agentsDir, file.name);
110
+ const hasProgress = fs.existsSync(path.join(agentPath, 'progress.md'));
111
+ const hasBriefing = fs.existsSync(path.join(agentPath, 'BRIEFING.md'));
112
+ const hasHandoff = fs.existsSync(path.join(agentPath, 'handoff.md'));
113
+
114
+ if (!hasProgress && !hasBriefing && !hasHandoff) {
115
+ continue;
116
+ }
117
+
118
+ agents.push(parseAgentState(file.name, agentPath, currentTime));
119
+ }
120
+ return agents;
121
+ }
122
+
123
+ export function printAgentDetails(agentName, agentsDir) {
124
+ const agentPath = path.join(agentsDir, agentName);
125
+ if (!fs.existsSync(agentPath)) {
126
+ console.log(label.error + ` Agent "${agentName}" not found.`);
127
+ return false;
128
+ }
129
+
130
+ console.log("");
131
+ console.log(colors.brand(` ⚡ AGENT PROFILE: ${agentName.toUpperCase()}`));
132
+ console.log(separator("─"));
133
+
134
+ const planPath = path.join(agentPath, 'plan.md');
135
+ if (fs.existsSync(planPath)) {
136
+ console.log("");
137
+ console.log(colors.accent(` ◈ PLAN (plan.md):`));
138
+ console.log(separator("─"));
139
+ console.log(fs.readFileSync(planPath, 'utf8'));
140
+ } else {
141
+ console.log("");
142
+ console.log(colors.warning(` Plan file (plan.md) not found for ${agentName}.`));
143
+ }
144
+
145
+ const handoffPath = path.join(agentPath, 'handoff.md');
146
+ if (fs.existsSync(handoffPath)) {
147
+ console.log("");
148
+ console.log(colors.accent(` ◈ HANDOFF (handoff.md):`));
149
+ console.log(separator("─"));
150
+ console.log(fs.readFileSync(handoffPath, 'utf8'));
151
+ } else {
152
+ console.log("");
153
+ console.log(colors.warning(` Handoff file (handoff.md) not found for ${agentName}.`));
154
+ }
155
+ return true;
156
+ }
157
+
158
+ export function renderTable(agents) {
159
+ const colWidths = [35, 11, 12, 45];
160
+ const borderChar = '│';
161
+
162
+ console.log(' ┌' + colWidths.map(w => '─'.repeat(w)).join('┬') + '┐');
163
+
164
+ const headers = ['AGENT NAME', 'STATUS', 'HEARTBEAT', 'ACTIVE GOAL / MILESTONE'];
165
+ const headerRow = ' ' + borderChar + headers.map((h, i) => {
166
+ const text = h.padEnd(colWidths[i]);
167
+ return colors.brand(text);
168
+ }).join(borderChar) + borderChar;
169
+ console.log(headerRow);
170
+
171
+ console.log(' ├' + colWidths.map(w => '─'.repeat(w)).join('┼') + '┤');
172
+
173
+ for (const agent of agents) {
174
+ const nameStr = padString(agent.name, colWidths[0]);
175
+ const heartbeatStr = padString(agent.heartbeat, colWidths[2]);
176
+ const missionStr = padString(agent.mission, colWidths[3]);
177
+
178
+ let statusColored = '';
179
+ if (agent.status === 'COMPLETED') {
180
+ statusColored = colors.success(padString('COMPLETED', colWidths[1]));
181
+ } else if (agent.status === 'ACTIVE') {
182
+ statusColored = colors.accent3(padString('ACTIVE', colWidths[1]));
183
+ } else {
184
+ statusColored = colors.warning(padString('STALE', colWidths[1]));
185
+ }
186
+
187
+ const row = ' ' + borderChar +
188
+ colors.text(nameStr) + borderChar +
189
+ statusColored + borderChar +
190
+ colors.muted(heartbeatStr) + borderChar +
191
+ colors.text(missionStr) + borderChar;
192
+ console.log(row);
193
+ }
194
+
195
+ console.log(' └' + colWidths.map(w => '─'.repeat(w)).join('┴') + '┘');
196
+ }
197
+
198
+ function padString(str, length) {
199
+ if (str.length > length) {
200
+ return str.slice(0, length - 3) + '...';
201
+ }
202
+ return str.padEnd(length);
203
+ }
204
+
205
+ export default {
206
+ name: "teamwork-preview",
207
+ description: "View status and heartbeat of subagents",
208
+ aliases: ["teamwork"],
209
+ signature: "teamwork-preview",
210
+ options: [
211
+ {
212
+ flags: "-w, --watch",
213
+ description: "Automatically refresh the status matrix every 3 seconds"
214
+ },
215
+ {
216
+ flags: "-a, --agent <name>",
217
+ description: "Show detailed profile of a specific agent"
218
+ }
219
+ ],
220
+ async executeCLI(args, options) {
221
+ const agentsDir = path.join(process.cwd(), '.agents');
222
+ const parsed = {
223
+ watch: !!(options.watch || args.includes('-w') || args.includes('--watch')),
224
+ agent: options.agent || null
225
+ };
226
+ if (!parsed.agent) {
227
+ const manual = parseArgs(args);
228
+ if (manual.agent) parsed.agent = manual.agent;
229
+ if (manual.watch) parsed.watch = true;
230
+ }
231
+
232
+ if (parsed.agent) {
233
+ printAgentDetails(parsed.agent, agentsDir);
234
+ return;
235
+ }
236
+
237
+ if (parsed.watch) {
238
+ const isTest = process.env.NODE_ENV === 'test' || options.testOnce;
239
+ const runTick = () => {
240
+ process.stdout.write("\x1b[2J\x1b[3J\x1b[H");
241
+ console.log("");
242
+ console.log(colors.brand(" ⚡ Krims Code TEAMWORK DASHBOARD [WATCH MODE]"));
243
+ console.log(separator("─"));
244
+ console.log("");
245
+
246
+ const agents = scanAgents(agentsDir);
247
+ if (agents.length === 0) {
248
+ console.log(" " + colors.warning("No agent workspace directories detected."));
249
+ } else {
250
+ renderTable(agents);
251
+ }
252
+
253
+ if (options.onTick) {
254
+ options.onTick();
255
+ }
256
+
257
+ if (!isTest) {
258
+ setTimeout(runTick, 3000);
259
+ }
260
+ };
261
+ runTick();
262
+ } else {
263
+ console.log("");
264
+ console.log(colors.brand(" ⚡ Krims Code TEAMWORK DASHBOARD"));
265
+ console.log(separator("─"));
266
+ console.log("");
267
+
268
+ const agents = scanAgents(agentsDir);
269
+ if (agents.length === 0) {
270
+ console.log(" " + colors.warning("No agent workspace directories detected."));
271
+ } else {
272
+ renderTable(agents);
273
+ }
274
+ console.log("");
275
+ }
276
+ },
277
+ async executeChat(args, ctx) {
278
+ const agentsDir = path.join(process.cwd(), '.agents');
279
+ const parsed = parseArgs(args);
280
+
281
+ if (parsed.agent) {
282
+ printAgentDetails(parsed.agent, agentsDir);
283
+ return;
284
+ }
285
+
286
+ if (parsed.watch) {
287
+ const isTest = process.env.NODE_ENV === 'test' || args.includes('--test-once') || ctx.testOnce;
288
+ const runTick = () => {
289
+ process.stdout.write("\x1b[2J\x1b[3J\x1b[H");
290
+ console.log("");
291
+ console.log(colors.brand(" ⚡ Krims Code TEAMWORK DASHBOARD [WATCH MODE]"));
292
+ console.log(separator("─"));
293
+ console.log("");
294
+
295
+ const agents = scanAgents(agentsDir);
296
+ if (agents.length === 0) {
297
+ console.log(" " + colors.warning("No agent workspace directories detected."));
298
+ } else {
299
+ renderTable(agents);
300
+ }
301
+
302
+ if (ctx.onTick) {
303
+ ctx.onTick();
304
+ }
305
+
306
+ if (!isTest) {
307
+ setTimeout(runTick, 3000);
308
+ }
309
+ };
310
+ runTick();
311
+ } else {
312
+ console.log("");
313
+ console.log(colors.brand(" ⚡ Krims Code TEAMWORK DASHBOARD"));
314
+ console.log(separator("─"));
315
+ console.log("");
316
+
317
+ const agents = scanAgents(agentsDir);
318
+ if (agents.length === 0) {
319
+ console.log(" " + colors.warning("No agent workspace directories detected."));
320
+ } else {
321
+ renderTable(agents);
322
+ }
323
+ console.log("");
324
+ }
325
+ }
326
+ };
@@ -0,0 +1,42 @@
1
+ import { getAIConfig, setConfigValue } from "../config.js";
2
+ import { colors, label, setTheme, getThemesList } from "../ui/theme.js";
3
+
4
+ export default {
5
+ name: "theme",
6
+ signature: "theme [name]",
7
+ description: "Show active visual theme or switch to a new theme",
8
+ aliases: [],
9
+ options: [],
10
+ async executeCLI(args, options) {
11
+ const name = args[0];
12
+ if (!name) {
13
+ const aiConfig = await getAIConfig();
14
+ const theme = aiConfig.THEME || "cyberpunk";
15
+ console.log("\n" + label.config + " " + colors.muted("Active Theme: ") + colors.accent(theme.toUpperCase()) + "\n");
16
+ } else {
17
+ const success = setTheme(name);
18
+ if (success) {
19
+ await setConfigValue("THEME", name.toLowerCase().trim());
20
+ console.log("\n" + label.config + " " + colors.success(`✓ Switched theme to ${name.toUpperCase()}`) + "\n");
21
+ } else {
22
+ console.log("\n" + label.error + " " + colors.danger(`Unknown theme: "${name}".`) + colors.muted(` Available: ${getThemesList().join(", ")}\n`));
23
+ }
24
+ }
25
+ },
26
+ async executeChat(args, ctx) {
27
+ const themeName = args[0];
28
+ if (!themeName) {
29
+ console.log("\n" + label.system + " " + colors.warning("Usage: /theme <theme-name>. Type /themes to list themes.\n"));
30
+ return;
31
+ }
32
+
33
+ const success = setTheme(themeName);
34
+ if (success) {
35
+ await setConfigValue("THEME", themeName.toLowerCase().trim());
36
+ console.log("\n" + label.system + " " + colors.success(`✓ Theme switched to ${themeName.toUpperCase()}`));
37
+ console.log(" " + colors.muted("Visual grid modulates synchronized.\n"));
38
+ } else {
39
+ console.log("\n" + label.system + " " + colors.danger(`Unknown theme: "${themeName}".`) + " " + colors.muted(`Available: ${getThemesList().join(", ")}\n`));
40
+ }
41
+ }
42
+ };
@@ -0,0 +1,30 @@
1
+ import { getThemesList, getActiveTheme, bullet, colors, separator } from "../ui/theme.js";
2
+
3
+ export default {
4
+ name: "themes",
5
+ description: "List all available color themes",
6
+ aliases: [],
7
+ options: [],
8
+ async executeCLI(args, options) {
9
+ console.log("");
10
+ console.log(colors.brand(" ◈ AVAILABLE COLOR THEMES"));
11
+ console.log(separator("─"));
12
+ const active = getActiveTheme();
13
+ for (const t of getThemesList()) {
14
+ const isAct = t === active ? colors.success("★ ACTIVE") : "";
15
+ console.log(bullet(t.toUpperCase().padEnd(14) + isAct));
16
+ }
17
+ console.log("");
18
+ },
19
+ async executeChat(args, ctx) {
20
+ console.log("");
21
+ console.log(colors.brand(" ◈ AVAILABLE COLOR THEMES"));
22
+ console.log(separator("─"));
23
+ const active = getActiveTheme();
24
+ for (const t of getThemesList()) {
25
+ const activeText = t === active ? colors.success("★ ACTIVE") : "";
26
+ console.log(bullet(t.toUpperCase().padEnd(14) + activeText));
27
+ }
28
+ console.log("");
29
+ }
30
+ };