shiva-code 0.5.4 → 0.6.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.
- package/dist/{chunk-XVFDKDRZ.js → chunk-2DKDGG4A.js} +288 -0
- package/dist/chunk-WWGAGUNY.js +69 -0
- package/dist/chunk-Z6NXFC4Q.js +118 -0
- package/dist/{client-2L7NWNCZ.js → client-UPSJM4FM.js} +1 -1
- package/dist/clipboard-ET53HNUB.js +13 -0
- package/dist/index.js +1364 -320
- package/dist/logger-E7SC5KUO.js +9 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
addProjectToPackage,
|
|
4
|
+
createPackage,
|
|
5
|
+
deletePackage,
|
|
6
|
+
getAllPackages,
|
|
7
|
+
getPackage,
|
|
8
|
+
getPackageLaunchConfig,
|
|
9
|
+
getPackageStats,
|
|
10
|
+
removeProjectFromPackage
|
|
11
|
+
} from "./chunk-LBTCSQAX.js";
|
|
2
12
|
import {
|
|
3
13
|
api
|
|
4
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-2DKDGG4A.js";
|
|
5
15
|
import {
|
|
6
16
|
CONFIG_PATH,
|
|
7
17
|
clearAuth,
|
|
@@ -21,6 +31,33 @@ import {
|
|
|
21
31
|
setConfig,
|
|
22
32
|
setDefaultTerminal
|
|
23
33
|
} from "./chunk-OP4HYQZZ.js";
|
|
34
|
+
import {
|
|
35
|
+
colors,
|
|
36
|
+
log
|
|
37
|
+
} from "./chunk-Z6NXFC4Q.js";
|
|
38
|
+
import {
|
|
39
|
+
encodeProjectPath,
|
|
40
|
+
findProject,
|
|
41
|
+
findProjectForCurrentDir,
|
|
42
|
+
findProjectFromArray,
|
|
43
|
+
findSessionByBranch,
|
|
44
|
+
formatDate,
|
|
45
|
+
formatRelativeTime,
|
|
46
|
+
getAllClaudeProjects,
|
|
47
|
+
getClaudeProjectsPath,
|
|
48
|
+
getProjectName,
|
|
49
|
+
getRecoveredContext,
|
|
50
|
+
getSessionStats,
|
|
51
|
+
invalidateSessionsCache,
|
|
52
|
+
isSessionActive,
|
|
53
|
+
isSessionCorrupted,
|
|
54
|
+
isSessionCorruptedQuick,
|
|
55
|
+
isValidProjectPath,
|
|
56
|
+
isValidSessionId,
|
|
57
|
+
maskSecret,
|
|
58
|
+
sanitizeForLog,
|
|
59
|
+
saveRecoveredContext
|
|
60
|
+
} from "./chunk-H5OFO4VS.js";
|
|
24
61
|
import {
|
|
25
62
|
SECURITY_PRESETS,
|
|
26
63
|
addDockerMount,
|
|
@@ -62,168 +99,26 @@ import {
|
|
|
62
99
|
isGhInstalled,
|
|
63
100
|
isGitRepo
|
|
64
101
|
} from "./chunk-IVFCZLBX.js";
|
|
65
|
-
import {
|
|
66
|
-
addProjectToPackage,
|
|
67
|
-
createPackage,
|
|
68
|
-
deletePackage,
|
|
69
|
-
getAllPackages,
|
|
70
|
-
getPackage,
|
|
71
|
-
getPackageLaunchConfig,
|
|
72
|
-
getPackageStats,
|
|
73
|
-
removeProjectFromPackage
|
|
74
|
-
} from "./chunk-LBTCSQAX.js";
|
|
75
|
-
import {
|
|
76
|
-
encodeProjectPath,
|
|
77
|
-
findProject,
|
|
78
|
-
findProjectForCurrentDir,
|
|
79
|
-
findProjectFromArray,
|
|
80
|
-
findSessionByBranch,
|
|
81
|
-
formatDate,
|
|
82
|
-
formatRelativeTime,
|
|
83
|
-
getAllClaudeProjects,
|
|
84
|
-
getClaudeProjectsPath,
|
|
85
|
-
getProjectName,
|
|
86
|
-
getRecoveredContext,
|
|
87
|
-
getSessionStats,
|
|
88
|
-
invalidateSessionsCache,
|
|
89
|
-
isSessionActive,
|
|
90
|
-
isSessionCorrupted,
|
|
91
|
-
isSessionCorruptedQuick,
|
|
92
|
-
isValidProjectPath,
|
|
93
|
-
isValidSessionId,
|
|
94
|
-
maskSecret,
|
|
95
|
-
sanitizeForLog,
|
|
96
|
-
saveRecoveredContext
|
|
97
|
-
} from "./chunk-H5OFO4VS.js";
|
|
98
102
|
import {
|
|
99
103
|
cache
|
|
100
104
|
} from "./chunk-HIQO2DBA.js";
|
|
105
|
+
import {
|
|
106
|
+
copyToClipboard,
|
|
107
|
+
getClipboardInstallInstructions,
|
|
108
|
+
isClipboardAvailable
|
|
109
|
+
} from "./chunk-WWGAGUNY.js";
|
|
101
110
|
import {
|
|
102
111
|
__require
|
|
103
112
|
} from "./chunk-3RG5ZIWI.js";
|
|
104
113
|
|
|
105
114
|
// src/index.ts
|
|
106
|
-
import { Command as
|
|
115
|
+
import { Command as Command38 } from "commander";
|
|
107
116
|
import * as readline from "readline";
|
|
108
117
|
|
|
109
118
|
// src/commands/auth/login.ts
|
|
110
119
|
import { Command } from "commander";
|
|
111
120
|
import inquirer2 from "inquirer";
|
|
112
121
|
|
|
113
|
-
// src/utils/logger.ts
|
|
114
|
-
import chalk from "chalk";
|
|
115
|
-
var log = {
|
|
116
|
-
// Success messages
|
|
117
|
-
success: (message) => console.log(chalk.green("\u2713"), message),
|
|
118
|
-
// Error messages
|
|
119
|
-
error: (message) => console.log(chalk.red("\u2717"), message),
|
|
120
|
-
// Warning messages
|
|
121
|
-
warn: (message) => console.log(chalk.yellow("\u26A0"), message),
|
|
122
|
-
// Info messages
|
|
123
|
-
info: (message) => console.log(chalk.blue("\u2139"), message),
|
|
124
|
-
// Plain message
|
|
125
|
-
plain: (message) => console.log(message),
|
|
126
|
-
// Dimmed text
|
|
127
|
-
dim: (message) => console.log(chalk.dim(message)),
|
|
128
|
-
// Bold text
|
|
129
|
-
bold: (message) => console.log(chalk.bold(message)),
|
|
130
|
-
// Newline
|
|
131
|
-
newline: () => console.log(),
|
|
132
|
-
// Header
|
|
133
|
-
header: (title) => {
|
|
134
|
-
console.log();
|
|
135
|
-
console.log(chalk.bold(title));
|
|
136
|
-
console.log(chalk.dim("\u2500".repeat(title.length)));
|
|
137
|
-
},
|
|
138
|
-
// Key-value pair
|
|
139
|
-
keyValue: (key, value, indent = 0) => {
|
|
140
|
-
const spaces = " ".repeat(indent);
|
|
141
|
-
console.log(`${spaces}${chalk.dim(key + ":")} ${value}`);
|
|
142
|
-
},
|
|
143
|
-
// List item
|
|
144
|
-
listItem: (text, status) => {
|
|
145
|
-
let icon = "\u2022";
|
|
146
|
-
if (status === "synced") icon = chalk.green("\u2713");
|
|
147
|
-
if (status === "pending") icon = chalk.yellow("\u25CB");
|
|
148
|
-
if (status === "error") icon = chalk.red("\u2717");
|
|
149
|
-
console.log(` ${icon} ${text}`);
|
|
150
|
-
},
|
|
151
|
-
// Tree structure
|
|
152
|
-
tree: {
|
|
153
|
-
item: (text, isLast = false) => {
|
|
154
|
-
const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
155
|
-
console.log(chalk.dim(prefix), text);
|
|
156
|
-
}
|
|
157
|
-
},
|
|
158
|
-
// Branded header
|
|
159
|
-
brand: () => {
|
|
160
|
-
console.log();
|
|
161
|
-
console.log(chalk.hex("#FF6B2C").bold("SHIVA Code"));
|
|
162
|
-
console.log(chalk.dim("Makes Claude Code Persistent"));
|
|
163
|
-
console.log();
|
|
164
|
-
},
|
|
165
|
-
// Error with suggestion (for ShivaError)
|
|
166
|
-
errorWithSuggestion: (error) => {
|
|
167
|
-
console.log(chalk.red("\u2717"), error.message);
|
|
168
|
-
if (error.suggestion) {
|
|
169
|
-
console.log(chalk.dim(` \u2192 ${error.suggestion}`));
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
// Progress bar
|
|
173
|
-
progress: (current, total, label) => {
|
|
174
|
-
const percentage = Math.round(current / total * 100);
|
|
175
|
-
const barWidth = 20;
|
|
176
|
-
const filled = Math.round(current / total * barWidth);
|
|
177
|
-
const empty = barWidth - filled;
|
|
178
|
-
const bar = chalk.green("\u2588".repeat(filled)) + chalk.dim("\u2591".repeat(empty));
|
|
179
|
-
const counts = chalk.dim(`${current}/${total}`);
|
|
180
|
-
const labelStr = label ? ` ${label}` : "";
|
|
181
|
-
process.stdout.write(`\r[${bar}] ${counts}${labelStr}`);
|
|
182
|
-
if (current >= total) {
|
|
183
|
-
console.log();
|
|
184
|
-
}
|
|
185
|
-
},
|
|
186
|
-
// Status line (inline update)
|
|
187
|
-
status: (message) => {
|
|
188
|
-
process.stdout.write(`\r${chalk.dim("\u2192")} ${message}`.padEnd(60));
|
|
189
|
-
},
|
|
190
|
-
// Clear the current line
|
|
191
|
-
clearLine: () => {
|
|
192
|
-
process.stdout.write("\r" + " ".repeat(80) + "\r");
|
|
193
|
-
},
|
|
194
|
-
// Box with title
|
|
195
|
-
box: (title, content) => {
|
|
196
|
-
const maxLen = Math.max(title.length, ...content.map((l) => l.length));
|
|
197
|
-
const border = "\u2500".repeat(maxLen + 2);
|
|
198
|
-
console.log(chalk.dim(`\u250C${border}\u2510`));
|
|
199
|
-
console.log(chalk.dim("\u2502 ") + chalk.bold(title.padEnd(maxLen)) + chalk.dim(" \u2502"));
|
|
200
|
-
console.log(chalk.dim(`\u251C${border}\u2524`));
|
|
201
|
-
for (const line of content) {
|
|
202
|
-
console.log(chalk.dim("\u2502 ") + line.padEnd(maxLen) + chalk.dim(" \u2502"));
|
|
203
|
-
}
|
|
204
|
-
console.log(chalk.dim(`\u2514${border}\u2518`));
|
|
205
|
-
},
|
|
206
|
-
// Table row
|
|
207
|
-
tableRow: (columns, widths) => {
|
|
208
|
-
const padded = columns.map((col, i) => col.padEnd(widths[i] || col.length));
|
|
209
|
-
console.log(" " + padded.join(" "));
|
|
210
|
-
},
|
|
211
|
-
// Separator line
|
|
212
|
-
separator: (char = "\u2500", length = 40) => {
|
|
213
|
-
console.log(chalk.dim(char.repeat(length)));
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
var colors = {
|
|
217
|
-
orange: chalk.hex("#FF6B2C"),
|
|
218
|
-
cyan: chalk.hex("#00D4FF"),
|
|
219
|
-
green: chalk.green,
|
|
220
|
-
red: chalk.red,
|
|
221
|
-
yellow: chalk.yellow,
|
|
222
|
-
blue: chalk.blue,
|
|
223
|
-
dim: chalk.dim,
|
|
224
|
-
bold: chalk.bold
|
|
225
|
-
};
|
|
226
|
-
|
|
227
122
|
// src/services/auth/auth.ts
|
|
228
123
|
import inquirer from "inquirer";
|
|
229
124
|
import open from "open";
|
|
@@ -1246,6 +1141,27 @@ function generateClaudeMd(scanned, project) {
|
|
|
1246
1141
|
lines.push("- **Last Sync**: Never");
|
|
1247
1142
|
}
|
|
1248
1143
|
lines.push("");
|
|
1144
|
+
lines.push("### SHIVA Instructions");
|
|
1145
|
+
lines.push("");
|
|
1146
|
+
lines.push("IMPORTANT: Du MUSST diese Befehle nutzen um Informationen \xFCber Sessions hinweg zu speichern!");
|
|
1147
|
+
lines.push("");
|
|
1148
|
+
lines.push("**Memory speichern** - Wenn der User dich bittet etwas zu merken oder wichtige Infos auftauchen:");
|
|
1149
|
+
lines.push("```bash");
|
|
1150
|
+
lines.push('shiva remember "Die wichtige Information die gemerkt werden soll"');
|
|
1151
|
+
lines.push("```");
|
|
1152
|
+
lines.push("");
|
|
1153
|
+
lines.push("**Memories durchsuchen** - Um gespeicherte Informationen zu finden:");
|
|
1154
|
+
lines.push("```bash");
|
|
1155
|
+
lines.push('shiva search "suchbegriff"');
|
|
1156
|
+
lines.push("```");
|
|
1157
|
+
lines.push("");
|
|
1158
|
+
lines.push("**Wann Memories speichern:**");
|
|
1159
|
+
lines.push('- User sagt "merk dir...", "speicher...", "erinner dich..."');
|
|
1160
|
+
lines.push("- Wichtige Projektentscheidungen");
|
|
1161
|
+
lines.push("- API Keys, Secrets, Konfigurationen (nutze `shiva secrets add`)");
|
|
1162
|
+
lines.push("- Wichtige Code-Patterns oder Konventionen");
|
|
1163
|
+
lines.push("- Alles was in zuk\xFCnftigen Sessions relevant sein k\xF6nnte");
|
|
1164
|
+
lines.push("");
|
|
1249
1165
|
lines.push("## Memories");
|
|
1250
1166
|
lines.push("");
|
|
1251
1167
|
if (project?.memories && project.memories.length > 0) {
|
|
@@ -6775,7 +6691,7 @@ async function checkProjectExists(path15) {
|
|
|
6775
6691
|
}
|
|
6776
6692
|
}
|
|
6777
6693
|
sessionsCommand.command("push").description("Sessions in Cloud sichern").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
|
|
6778
|
-
const { api: api2 } = await import("./client-
|
|
6694
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6779
6695
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6780
6696
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6781
6697
|
if (!isAuthenticated2()) {
|
|
@@ -6835,7 +6751,7 @@ sessionsCommand.command("push").description("Sessions in Cloud sichern").option(
|
|
|
6835
6751
|
}
|
|
6836
6752
|
});
|
|
6837
6753
|
sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
6838
|
-
const { api: api2 } = await import("./client-
|
|
6754
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6839
6755
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6840
6756
|
if (!isAuthenticated2()) {
|
|
6841
6757
|
log.error("Nicht angemeldet");
|
|
@@ -6882,7 +6798,7 @@ sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("
|
|
|
6882
6798
|
}
|
|
6883
6799
|
});
|
|
6884
6800
|
sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
|
|
6885
|
-
const { api: api2 } = await import("./client-
|
|
6801
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6886
6802
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6887
6803
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6888
6804
|
if (!isAuthenticated2()) {
|
|
@@ -6935,7 +6851,7 @@ sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren"
|
|
|
6935
6851
|
log.dim("Sessions werden automatisch mit lokalen Claude Sessions verkn\xFCpft");
|
|
6936
6852
|
});
|
|
6937
6853
|
sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\xF6schen").action(async (sessionId) => {
|
|
6938
|
-
const { api: api2 } = await import("./client-
|
|
6854
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6939
6855
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6940
6856
|
if (!isAuthenticated2()) {
|
|
6941
6857
|
log.error("Nicht angemeldet");
|
|
@@ -6953,6 +6869,152 @@ sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\x
|
|
|
6953
6869
|
log.error(error instanceof Error ? error.message : "Fehler beim L\xF6schen");
|
|
6954
6870
|
}
|
|
6955
6871
|
});
|
|
6872
|
+
sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6873
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6874
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6875
|
+
if (!isAuthenticated2()) {
|
|
6876
|
+
log.error("Nicht angemeldet");
|
|
6877
|
+
log.info("Anmelden mit: shiva login");
|
|
6878
|
+
return;
|
|
6879
|
+
}
|
|
6880
|
+
const spinner = ora9("Lade aktive Sessions...").start();
|
|
6881
|
+
try {
|
|
6882
|
+
const sessions = await api2.getActiveSessions();
|
|
6883
|
+
spinner.stop();
|
|
6884
|
+
if (options.json) {
|
|
6885
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
6886
|
+
return;
|
|
6887
|
+
}
|
|
6888
|
+
log.newline();
|
|
6889
|
+
console.log(colors.orange.bold("Active Cloud Sessions"));
|
|
6890
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
6891
|
+
log.newline();
|
|
6892
|
+
if (sessions.length === 0) {
|
|
6893
|
+
log.dim("Keine aktiven Cloud-Sessions");
|
|
6894
|
+
return;
|
|
6895
|
+
}
|
|
6896
|
+
for (const session of sessions) {
|
|
6897
|
+
console.log(` ${colors.green("\u25CF")} ${colors.bold(session.sessionId)}`);
|
|
6898
|
+
console.log(` ${colors.dim("Project ID:")} ${session.projectId}`);
|
|
6899
|
+
console.log(` ${colors.dim("Started:")} ${session.startedAt}`);
|
|
6900
|
+
console.log(` ${colors.dim("Last Activity:")} ${session.lastActivity}`);
|
|
6901
|
+
console.log(` ${colors.dim("Messages:")} ${session.messageCount}`);
|
|
6902
|
+
log.newline();
|
|
6903
|
+
}
|
|
6904
|
+
} catch (error) {
|
|
6905
|
+
spinner.fail("Fehler beim Laden");
|
|
6906
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6907
|
+
}
|
|
6908
|
+
});
|
|
6909
|
+
sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6910
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6911
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6912
|
+
if (!isAuthenticated2()) {
|
|
6913
|
+
log.error("Nicht angemeldet");
|
|
6914
|
+
log.info("Anmelden mit: shiva login");
|
|
6915
|
+
return;
|
|
6916
|
+
}
|
|
6917
|
+
const spinner = ora9("Lade Session-Statistiken...").start();
|
|
6918
|
+
try {
|
|
6919
|
+
const stats = await api2.getSessionStats();
|
|
6920
|
+
spinner.stop();
|
|
6921
|
+
if (options.json) {
|
|
6922
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
6923
|
+
return;
|
|
6924
|
+
}
|
|
6925
|
+
log.newline();
|
|
6926
|
+
console.log(colors.orange.bold("Session Statistics"));
|
|
6927
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
6928
|
+
log.newline();
|
|
6929
|
+
log.keyValue("Total Sessions", String(stats.totalSessions));
|
|
6930
|
+
log.keyValue("Active Sessions", String(stats.activeSessions));
|
|
6931
|
+
log.keyValue("Total Messages", String(stats.totalMessages));
|
|
6932
|
+
log.keyValue("Avg Session Length", `${stats.averageSessionLength} min`);
|
|
6933
|
+
log.newline();
|
|
6934
|
+
log.keyValue("Sessions (Last 7 Days)", String(stats.sessionsLast7Days));
|
|
6935
|
+
log.keyValue("Sessions (Last 30 Days)", String(stats.sessionsLast30Days));
|
|
6936
|
+
} catch (error) {
|
|
6937
|
+
spinner.fail("Fehler beim Laden");
|
|
6938
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6939
|
+
}
|
|
6940
|
+
});
|
|
6941
|
+
sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortsetzen").action(async (sessionId) => {
|
|
6942
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6943
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6944
|
+
if (!isAuthenticated2()) {
|
|
6945
|
+
log.error("Nicht angemeldet");
|
|
6946
|
+
log.info("Anmelden mit: shiva login");
|
|
6947
|
+
return;
|
|
6948
|
+
}
|
|
6949
|
+
const spinner = ora9("Lade Session...").start();
|
|
6950
|
+
try {
|
|
6951
|
+
const result = await api2.resumeSession(sessionId);
|
|
6952
|
+
if (result.success) {
|
|
6953
|
+
spinner.succeed("Session geladen");
|
|
6954
|
+
log.newline();
|
|
6955
|
+
log.info("Session kann jetzt fortgesetzt werden");
|
|
6956
|
+
log.plain(` claude --session ${sessionId}`);
|
|
6957
|
+
} else {
|
|
6958
|
+
spinner.fail(result.message || "Fehler beim Laden");
|
|
6959
|
+
}
|
|
6960
|
+
} catch (error) {
|
|
6961
|
+
spinner.fail("Fehler beim Laden");
|
|
6962
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6963
|
+
}
|
|
6964
|
+
});
|
|
6965
|
+
sessionsCommand.command("export <sessionId>").description("Cloud-Session exportieren").option("-o, --output <file>", "Ausgabedatei").action(async (sessionId, options) => {
|
|
6966
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6967
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6968
|
+
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
6969
|
+
if (!isAuthenticated2()) {
|
|
6970
|
+
log.error("Nicht angemeldet");
|
|
6971
|
+
log.info("Anmelden mit: shiva login");
|
|
6972
|
+
return;
|
|
6973
|
+
}
|
|
6974
|
+
const spinner = ora9("Exportiere Session...").start();
|
|
6975
|
+
try {
|
|
6976
|
+
const exportData = await api2.exportSession(sessionId);
|
|
6977
|
+
spinner.stop();
|
|
6978
|
+
if (options.output) {
|
|
6979
|
+
writeFileSync11(options.output, JSON.stringify(exportData, null, 2));
|
|
6980
|
+
log.success(`Session exportiert: ${options.output}`);
|
|
6981
|
+
} else {
|
|
6982
|
+
console.log(JSON.stringify(exportData, null, 2));
|
|
6983
|
+
}
|
|
6984
|
+
} catch (error) {
|
|
6985
|
+
spinner.fail("Fehler beim Exportieren");
|
|
6986
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6987
|
+
}
|
|
6988
|
+
});
|
|
6989
|
+
sessionsCommand.command("update <sessionId>").description("Cloud-Session aktualisieren").option("--summary <text>", "Session-Zusammenfassung").option("--branch <name>", "Git Branch").action(async (sessionId, options) => {
|
|
6990
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6991
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6992
|
+
if (!isAuthenticated2()) {
|
|
6993
|
+
log.error("Nicht angemeldet");
|
|
6994
|
+
log.info("Anmelden mit: shiva login");
|
|
6995
|
+
return;
|
|
6996
|
+
}
|
|
6997
|
+
if (!options.summary && !options.branch) {
|
|
6998
|
+
log.error("Keine \xC4nderungen angegeben");
|
|
6999
|
+
log.info("Verf\xFCgbare Optionen: --summary, --branch");
|
|
7000
|
+
return;
|
|
7001
|
+
}
|
|
7002
|
+
const spinner = ora9("Aktualisiere Session...").start();
|
|
7003
|
+
try {
|
|
7004
|
+
const result = await api2.updateSession(sessionId, {
|
|
7005
|
+
summary: options.summary,
|
|
7006
|
+
gitBranch: options.branch
|
|
7007
|
+
});
|
|
7008
|
+
if (result.success) {
|
|
7009
|
+
spinner.succeed("Session aktualisiert");
|
|
7010
|
+
} else {
|
|
7011
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
7012
|
+
}
|
|
7013
|
+
} catch (error) {
|
|
7014
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
7015
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
7016
|
+
}
|
|
7017
|
+
});
|
|
6956
7018
|
|
|
6957
7019
|
// src/commands/session/session.ts
|
|
6958
7020
|
import { Command as Command14 } from "commander";
|
|
@@ -10389,67 +10451,6 @@ import inquirer8 from "inquirer";
|
|
|
10389
10451
|
import ora13 from "ora";
|
|
10390
10452
|
import * as fs6 from "fs";
|
|
10391
10453
|
import * as path6 from "path";
|
|
10392
|
-
|
|
10393
|
-
// src/utils/clipboard.ts
|
|
10394
|
-
import { execSync as execSync2, spawnSync as spawnSync6 } from "child_process";
|
|
10395
|
-
var CLIPBOARD_COMMANDS = [
|
|
10396
|
-
// Wayland (modern Linux)
|
|
10397
|
-
{ command: "wl-copy", args: [], check: "wl-copy" },
|
|
10398
|
-
// X11 - xclip
|
|
10399
|
-
{ command: "xclip", args: ["-selection", "clipboard"], check: "xclip" },
|
|
10400
|
-
// X11 - xsel
|
|
10401
|
-
{ command: "xsel", args: ["--clipboard", "--input"], check: "xsel" },
|
|
10402
|
-
// macOS
|
|
10403
|
-
{ command: "pbcopy", args: [], check: "pbcopy" }
|
|
10404
|
-
];
|
|
10405
|
-
function commandExists2(command) {
|
|
10406
|
-
try {
|
|
10407
|
-
execSync2(`which ${command}`, { stdio: "ignore" });
|
|
10408
|
-
return true;
|
|
10409
|
-
} catch {
|
|
10410
|
-
return false;
|
|
10411
|
-
}
|
|
10412
|
-
}
|
|
10413
|
-
function findClipboardCommand() {
|
|
10414
|
-
for (const cmd of CLIPBOARD_COMMANDS) {
|
|
10415
|
-
if (commandExists2(cmd.check)) {
|
|
10416
|
-
return cmd;
|
|
10417
|
-
}
|
|
10418
|
-
}
|
|
10419
|
-
return null;
|
|
10420
|
-
}
|
|
10421
|
-
function copyToClipboard(text) {
|
|
10422
|
-
const clipboardCmd = findClipboardCommand();
|
|
10423
|
-
if (!clipboardCmd) {
|
|
10424
|
-
return false;
|
|
10425
|
-
}
|
|
10426
|
-
try {
|
|
10427
|
-
const result = spawnSync6(clipboardCmd.command, clipboardCmd.args, {
|
|
10428
|
-
input: text,
|
|
10429
|
-
stdio: ["pipe", "ignore", "ignore"]
|
|
10430
|
-
});
|
|
10431
|
-
return result.status === 0;
|
|
10432
|
-
} catch {
|
|
10433
|
-
return false;
|
|
10434
|
-
}
|
|
10435
|
-
}
|
|
10436
|
-
function isClipboardAvailable() {
|
|
10437
|
-
return findClipboardCommand() !== null;
|
|
10438
|
-
}
|
|
10439
|
-
function getClipboardInstallInstructions() {
|
|
10440
|
-
const isWayland = process.env.WAYLAND_DISPLAY || process.env.XDG_SESSION_TYPE === "wayland";
|
|
10441
|
-
const isX11 = process.env.DISPLAY && !isWayland;
|
|
10442
|
-
if (isWayland) {
|
|
10443
|
-
return "F\xFCr Wayland: sudo apt install wl-clipboard";
|
|
10444
|
-
} else if (isX11) {
|
|
10445
|
-
return "F\xFCr X11: sudo apt install xclip";
|
|
10446
|
-
} else if (process.platform === "darwin") {
|
|
10447
|
-
return "pbcopy sollte bereits verf\xFCgbar sein";
|
|
10448
|
-
}
|
|
10449
|
-
return "sudo apt install wl-clipboard (Wayland) oder xclip (X11)";
|
|
10450
|
-
}
|
|
10451
|
-
|
|
10452
|
-
// src/commands/security/secrets.ts
|
|
10453
10454
|
var SECURE_FILE_MODE = 384;
|
|
10454
10455
|
var secretsCommand = new Command20("secrets").description("API Keys und Secrets verwalten (Cloud Vault)").action(async () => {
|
|
10455
10456
|
await listSecrets();
|
|
@@ -11802,7 +11803,8 @@ function getColorFunction(color) {
|
|
|
11802
11803
|
case "yellow":
|
|
11803
11804
|
return colors.yellow;
|
|
11804
11805
|
case "magenta":
|
|
11805
|
-
return colors.
|
|
11806
|
+
return colors.cyan;
|
|
11807
|
+
// magenta not available, use cyan
|
|
11806
11808
|
case "cyan":
|
|
11807
11809
|
return colors.cyan;
|
|
11808
11810
|
default:
|
|
@@ -11830,6 +11832,40 @@ async function resolveSessionId(input) {
|
|
|
11830
11832
|
}
|
|
11831
11833
|
return null;
|
|
11832
11834
|
}
|
|
11835
|
+
tagsCommand.command("cloud").description("Memory-Tags aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
11836
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
11837
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
11838
|
+
if (!isAuthenticated2()) {
|
|
11839
|
+
log.error("Nicht angemeldet");
|
|
11840
|
+
log.info("Anmelden mit: shiva login");
|
|
11841
|
+
return;
|
|
11842
|
+
}
|
|
11843
|
+
const ora24 = (await import("ora")).default;
|
|
11844
|
+
const spinner = ora24("Lade Memory-Tags aus Cloud...").start();
|
|
11845
|
+
try {
|
|
11846
|
+
const cloudTags = await api2.getMemoryTags();
|
|
11847
|
+
spinner.stop();
|
|
11848
|
+
if (options.json) {
|
|
11849
|
+
console.log(JSON.stringify(cloudTags, null, 2));
|
|
11850
|
+
return;
|
|
11851
|
+
}
|
|
11852
|
+
log.newline();
|
|
11853
|
+
console.log(colors.orange.bold("Memory Tags (Cloud)"));
|
|
11854
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
11855
|
+
log.newline();
|
|
11856
|
+
if (cloudTags.length === 0) {
|
|
11857
|
+
log.dim("Keine Memory-Tags in Cloud");
|
|
11858
|
+
return;
|
|
11859
|
+
}
|
|
11860
|
+
for (const { tag, count } of cloudTags) {
|
|
11861
|
+
console.log(` ${colors.cyan(`[${tag}]`)} ${colors.dim(`(${count} Memories)`)}`);
|
|
11862
|
+
}
|
|
11863
|
+
log.newline();
|
|
11864
|
+
} catch (error) {
|
|
11865
|
+
spinner.fail("Fehler beim Laden");
|
|
11866
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
11867
|
+
}
|
|
11868
|
+
});
|
|
11833
11869
|
|
|
11834
11870
|
// src/commands/memory/export.ts
|
|
11835
11871
|
import { Command as Command25 } from "commander";
|
|
@@ -11841,7 +11877,7 @@ import inquirer11 from "inquirer";
|
|
|
11841
11877
|
// src/services/session/export.ts
|
|
11842
11878
|
import * as fs9 from "fs";
|
|
11843
11879
|
import * as path10 from "path";
|
|
11844
|
-
import { execSync as
|
|
11880
|
+
import { execSync as execSync2 } from "child_process";
|
|
11845
11881
|
async function exportSession(sessionId, options = {}) {
|
|
11846
11882
|
const projects = await getAllClaudeProjects();
|
|
11847
11883
|
for (const project of projects) {
|
|
@@ -11953,7 +11989,7 @@ function createBackupArchive(outputPath, projectPaths) {
|
|
|
11953
11989
|
return false;
|
|
11954
11990
|
}
|
|
11955
11991
|
const tarArgs = includePaths.join(" ");
|
|
11956
|
-
|
|
11992
|
+
execSync2(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
|
|
11957
11993
|
stdio: "ignore"
|
|
11958
11994
|
});
|
|
11959
11995
|
return true;
|
|
@@ -12061,7 +12097,7 @@ function restoreFromArchive(archivePath, targetDir) {
|
|
|
12061
12097
|
if (!fs9.existsSync(extractTo)) {
|
|
12062
12098
|
fs9.mkdirSync(extractTo, { recursive: true });
|
|
12063
12099
|
}
|
|
12064
|
-
|
|
12100
|
+
execSync2(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
|
|
12065
12101
|
stdio: "ignore"
|
|
12066
12102
|
});
|
|
12067
12103
|
return true;
|
|
@@ -12340,20 +12376,20 @@ var rememberCommand = new Command26("remember").description("Memory in der Cloud
|
|
|
12340
12376
|
|
|
12341
12377
|
// src/commands/system/doctor.ts
|
|
12342
12378
|
import { Command as Command27 } from "commander";
|
|
12343
|
-
import { execSync as
|
|
12379
|
+
import { execSync as execSync3 } from "child_process";
|
|
12344
12380
|
import * as fs11 from "fs";
|
|
12345
12381
|
import * as path12 from "path";
|
|
12346
12382
|
import * as os5 from "os";
|
|
12347
12383
|
function tryExec(command) {
|
|
12348
12384
|
try {
|
|
12349
|
-
return
|
|
12385
|
+
return execSync3(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
12350
12386
|
} catch {
|
|
12351
12387
|
return null;
|
|
12352
12388
|
}
|
|
12353
12389
|
}
|
|
12354
|
-
function
|
|
12390
|
+
function commandExists2(cmd) {
|
|
12355
12391
|
try {
|
|
12356
|
-
|
|
12392
|
+
execSync3(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
|
|
12357
12393
|
return true;
|
|
12358
12394
|
} catch {
|
|
12359
12395
|
return false;
|
|
@@ -12366,7 +12402,7 @@ function getVersion(cmd, versionFlag = "--version") {
|
|
|
12366
12402
|
return match ? match[0] : output.split("\n")[0];
|
|
12367
12403
|
}
|
|
12368
12404
|
function checkClaude() {
|
|
12369
|
-
const exists =
|
|
12405
|
+
const exists = commandExists2("claude");
|
|
12370
12406
|
if (!exists) {
|
|
12371
12407
|
return {
|
|
12372
12408
|
name: "Claude CLI",
|
|
@@ -12383,7 +12419,7 @@ function checkClaude() {
|
|
|
12383
12419
|
};
|
|
12384
12420
|
}
|
|
12385
12421
|
function checkGitHub() {
|
|
12386
|
-
const exists =
|
|
12422
|
+
const exists = commandExists2("gh");
|
|
12387
12423
|
if (!exists) {
|
|
12388
12424
|
return {
|
|
12389
12425
|
name: "GitHub CLI (gh)",
|
|
@@ -12404,7 +12440,7 @@ function checkGitHub() {
|
|
|
12404
12440
|
};
|
|
12405
12441
|
}
|
|
12406
12442
|
function checkDocker() {
|
|
12407
|
-
const dockerExists =
|
|
12443
|
+
const dockerExists = commandExists2("docker");
|
|
12408
12444
|
if (dockerExists) {
|
|
12409
12445
|
const version = getVersion("docker");
|
|
12410
12446
|
const isRunning = tryExec("docker info 2>/dev/null") !== null;
|
|
@@ -12416,7 +12452,7 @@ function checkDocker() {
|
|
|
12416
12452
|
hint: isRunning ? void 0 : "Starte Docker Desktop oder: sudo systemctl start docker"
|
|
12417
12453
|
};
|
|
12418
12454
|
}
|
|
12419
|
-
const podmanExists =
|
|
12455
|
+
const podmanExists = commandExists2("podman");
|
|
12420
12456
|
if (podmanExists) {
|
|
12421
12457
|
const version = getVersion("podman");
|
|
12422
12458
|
return {
|
|
@@ -12433,7 +12469,7 @@ function checkDocker() {
|
|
|
12433
12469
|
};
|
|
12434
12470
|
}
|
|
12435
12471
|
function checkGit() {
|
|
12436
|
-
const exists =
|
|
12472
|
+
const exists = commandExists2("git");
|
|
12437
12473
|
if (!exists) {
|
|
12438
12474
|
return {
|
|
12439
12475
|
name: "Git",
|
|
@@ -12461,7 +12497,7 @@ function checkGit() {
|
|
|
12461
12497
|
};
|
|
12462
12498
|
}
|
|
12463
12499
|
function checkNode() {
|
|
12464
|
-
const exists =
|
|
12500
|
+
const exists = commandExists2("node");
|
|
12465
12501
|
if (!exists) {
|
|
12466
12502
|
return {
|
|
12467
12503
|
name: "Node.js",
|
|
@@ -12488,7 +12524,7 @@ function checkNode() {
|
|
|
12488
12524
|
};
|
|
12489
12525
|
}
|
|
12490
12526
|
function checkNpm() {
|
|
12491
|
-
const exists =
|
|
12527
|
+
const exists = commandExists2("npm");
|
|
12492
12528
|
if (!exists) {
|
|
12493
12529
|
return {
|
|
12494
12530
|
name: "npm",
|
|
@@ -12556,7 +12592,7 @@ function checkClaudeProjects() {
|
|
|
12556
12592
|
}
|
|
12557
12593
|
}
|
|
12558
12594
|
function checkTmux() {
|
|
12559
|
-
const exists =
|
|
12595
|
+
const exists = commandExists2("tmux");
|
|
12560
12596
|
if (!exists) {
|
|
12561
12597
|
return {
|
|
12562
12598
|
name: "tmux",
|
|
@@ -12667,7 +12703,7 @@ var doctorCommand = new Command27("doctor").description("System-Check f\xFCr SHI
|
|
|
12667
12703
|
|
|
12668
12704
|
// src/commands/system/upgrade.ts
|
|
12669
12705
|
import { Command as Command28 } from "commander";
|
|
12670
|
-
import { execSync as
|
|
12706
|
+
import { execSync as execSync4, spawn as spawn6 } from "child_process";
|
|
12671
12707
|
import * as fs12 from "fs";
|
|
12672
12708
|
import * as path13 from "path";
|
|
12673
12709
|
import { fileURLToPath } from "url";
|
|
@@ -12693,7 +12729,7 @@ async function getLatestVersion() {
|
|
|
12693
12729
|
return data["dist-tags"]?.latest || null;
|
|
12694
12730
|
} catch {
|
|
12695
12731
|
try {
|
|
12696
|
-
const output =
|
|
12732
|
+
const output = execSync4(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
|
|
12697
12733
|
encoding: "utf-8"
|
|
12698
12734
|
}).trim();
|
|
12699
12735
|
return output || null;
|
|
@@ -12724,17 +12760,17 @@ async function checkForUpdates() {
|
|
|
12724
12760
|
}
|
|
12725
12761
|
function detectPackageManager2() {
|
|
12726
12762
|
try {
|
|
12727
|
-
const npmGlobal =
|
|
12763
|
+
const npmGlobal = execSync4("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
|
|
12728
12764
|
if (npmGlobal.includes(PACKAGE_NAME)) return "npm";
|
|
12729
12765
|
} catch {
|
|
12730
12766
|
}
|
|
12731
12767
|
try {
|
|
12732
|
-
const yarnGlobal =
|
|
12768
|
+
const yarnGlobal = execSync4("yarn global list 2>/dev/null", { encoding: "utf-8" });
|
|
12733
12769
|
if (yarnGlobal.includes(PACKAGE_NAME)) return "yarn";
|
|
12734
12770
|
} catch {
|
|
12735
12771
|
}
|
|
12736
12772
|
try {
|
|
12737
|
-
const pnpmGlobal =
|
|
12773
|
+
const pnpmGlobal = execSync4("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
|
|
12738
12774
|
if (pnpmGlobal.includes(PACKAGE_NAME)) return "pnpm";
|
|
12739
12775
|
} catch {
|
|
12740
12776
|
}
|
|
@@ -13499,29 +13535,508 @@ function formatNumber(n) {
|
|
|
13499
13535
|
}
|
|
13500
13536
|
return String(n);
|
|
13501
13537
|
}
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
|
|
13514
|
-
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
log.
|
|
13519
|
-
log
|
|
13520
|
-
log.
|
|
13521
|
-
log.
|
|
13522
|
-
log.
|
|
13523
|
-
log.
|
|
13524
|
-
log.
|
|
13538
|
+
statsCommand.command("sessions").description("Session Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13539
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13540
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13541
|
+
if (!isAuthenticated2()) {
|
|
13542
|
+
log.error("Nicht angemeldet");
|
|
13543
|
+
log.info("Anmelden mit: shiva login");
|
|
13544
|
+
return;
|
|
13545
|
+
}
|
|
13546
|
+
const spinner = ora18("Lade Session Analytics...").start();
|
|
13547
|
+
try {
|
|
13548
|
+
const analytics = await api2.getSessionAnalytics();
|
|
13549
|
+
spinner.stop();
|
|
13550
|
+
if (options.json) {
|
|
13551
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13552
|
+
return;
|
|
13553
|
+
}
|
|
13554
|
+
log.newline();
|
|
13555
|
+
console.log(colors.orange.bold("Session Analytics"));
|
|
13556
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13557
|
+
log.newline();
|
|
13558
|
+
log.keyValue("Avg Session Length", `${analytics.averageSessionLength} min`);
|
|
13559
|
+
log.newline();
|
|
13560
|
+
console.log(colors.bold("Peak Hours:"));
|
|
13561
|
+
const sortedHours = analytics.peakHours.sort((a, b) => b.count - a.count).slice(0, 5);
|
|
13562
|
+
for (const { hour, count } of sortedHours) {
|
|
13563
|
+
console.log(` ${String(hour).padStart(2)}:00 - ${count} sessions`);
|
|
13564
|
+
}
|
|
13565
|
+
log.newline();
|
|
13566
|
+
console.log(colors.bold("Top Projects by Sessions:"));
|
|
13567
|
+
for (const proj of analytics.topProjects.slice(0, 5)) {
|
|
13568
|
+
console.log(` ${proj.projectName.padEnd(25)} ${proj.sessionCount} sessions`);
|
|
13569
|
+
}
|
|
13570
|
+
log.newline();
|
|
13571
|
+
if (analytics.dailySessions.length > 0) {
|
|
13572
|
+
console.log(colors.bold("Sessions (Last 7 Days):"));
|
|
13573
|
+
for (const { date, count } of analytics.dailySessions.slice(-7)) {
|
|
13574
|
+
const barLength = Math.min(20, count);
|
|
13575
|
+
const bar = colors.green("\u2588".repeat(barLength));
|
|
13576
|
+
console.log(` ${date.slice(5)} ${bar} ${count}`);
|
|
13577
|
+
}
|
|
13578
|
+
}
|
|
13579
|
+
} catch (error) {
|
|
13580
|
+
spinner.fail("Fehler beim Laden");
|
|
13581
|
+
const err = error;
|
|
13582
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13583
|
+
log.warn("Session Analytics ist ein Pro-Feature");
|
|
13584
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13585
|
+
} else {
|
|
13586
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13587
|
+
}
|
|
13588
|
+
}
|
|
13589
|
+
});
|
|
13590
|
+
statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13591
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13592
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13593
|
+
if (!isAuthenticated2()) {
|
|
13594
|
+
log.error("Nicht angemeldet");
|
|
13595
|
+
log.info("Anmelden mit: shiva login");
|
|
13596
|
+
return;
|
|
13597
|
+
}
|
|
13598
|
+
const spinner = ora18("Lade Token Analytics...").start();
|
|
13599
|
+
try {
|
|
13600
|
+
const analytics = await api2.getTokenAnalytics();
|
|
13601
|
+
spinner.stop();
|
|
13602
|
+
if (options.json) {
|
|
13603
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13604
|
+
return;
|
|
13605
|
+
}
|
|
13606
|
+
log.newline();
|
|
13607
|
+
console.log(colors.orange.bold("Token Usage Analytics"));
|
|
13608
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13609
|
+
log.newline();
|
|
13610
|
+
log.keyValue("Total Tokens", formatNumber(analytics.totalTokens));
|
|
13611
|
+
log.keyValue("This Month", formatNumber(analytics.tokensThisMonth));
|
|
13612
|
+
log.newline();
|
|
13613
|
+
console.log(colors.bold("Token Usage by Project:"));
|
|
13614
|
+
for (const proj of analytics.byProject.slice(0, 5)) {
|
|
13615
|
+
console.log(` ${proj.projectName.padEnd(25)} ${formatNumber(proj.tokens)}`);
|
|
13616
|
+
}
|
|
13617
|
+
log.newline();
|
|
13618
|
+
if (analytics.dailyUsage.length > 0) {
|
|
13619
|
+
console.log(colors.bold("Daily Usage (Last 7 Days):"));
|
|
13620
|
+
const maxTokens = Math.max(...analytics.dailyUsage.slice(-7).map((d) => d.tokens), 1);
|
|
13621
|
+
for (const { date, tokens } of analytics.dailyUsage.slice(-7)) {
|
|
13622
|
+
const barLength = Math.round(tokens / maxTokens * 20);
|
|
13623
|
+
const bar = colors.cyan("\u2588".repeat(barLength)) + colors.dim("\u2591".repeat(20 - barLength));
|
|
13624
|
+
console.log(` ${date.slice(5)} ${bar} ${formatNumber(tokens)}`);
|
|
13625
|
+
}
|
|
13626
|
+
}
|
|
13627
|
+
} catch (error) {
|
|
13628
|
+
spinner.fail("Fehler beim Laden");
|
|
13629
|
+
const err = error;
|
|
13630
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13631
|
+
log.warn("Token Analytics ist ein Pro-Feature");
|
|
13632
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13633
|
+
} else {
|
|
13634
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13635
|
+
}
|
|
13636
|
+
}
|
|
13637
|
+
});
|
|
13638
|
+
statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13639
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13640
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13641
|
+
if (!isAuthenticated2()) {
|
|
13642
|
+
log.error("Nicht angemeldet");
|
|
13643
|
+
log.info("Anmelden mit: shiva login");
|
|
13644
|
+
return;
|
|
13645
|
+
}
|
|
13646
|
+
const spinner = ora18("Lade Tool Analytics...").start();
|
|
13647
|
+
try {
|
|
13648
|
+
const analytics = await api2.getToolAnalytics();
|
|
13649
|
+
spinner.stop();
|
|
13650
|
+
if (options.json) {
|
|
13651
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13652
|
+
return;
|
|
13653
|
+
}
|
|
13654
|
+
log.newline();
|
|
13655
|
+
console.log(colors.orange.bold("Tool Usage Analytics"));
|
|
13656
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13657
|
+
log.newline();
|
|
13658
|
+
log.keyValue("Total Tool Calls", formatNumber(analytics.totalToolCalls));
|
|
13659
|
+
log.newline();
|
|
13660
|
+
console.log(colors.bold("Most Used Tools:"));
|
|
13661
|
+
for (const tool of analytics.mostUsedTools.slice(0, 10)) {
|
|
13662
|
+
const bar = colors.yellow("\u2588".repeat(Math.min(20, Math.round(tool.count / 10))));
|
|
13663
|
+
console.log(` ${tool.tool.padEnd(20)} ${bar} ${formatNumber(tool.count)}`);
|
|
13664
|
+
}
|
|
13665
|
+
log.newline();
|
|
13666
|
+
console.log(colors.bold("Tool Performance (Avg Duration):"));
|
|
13667
|
+
const sorted = analytics.byTool.sort((a, b) => b.avgDuration - a.avgDuration).slice(0, 5);
|
|
13668
|
+
for (const tool of sorted) {
|
|
13669
|
+
console.log(` ${tool.tool.padEnd(20)} ${tool.avgDuration.toFixed(0)}ms`);
|
|
13670
|
+
}
|
|
13671
|
+
} catch (error) {
|
|
13672
|
+
spinner.fail("Fehler beim Laden");
|
|
13673
|
+
const err = error;
|
|
13674
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13675
|
+
log.warn("Tool Analytics ist ein Pro-Feature");
|
|
13676
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13677
|
+
} else {
|
|
13678
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13679
|
+
}
|
|
13680
|
+
}
|
|
13681
|
+
});
|
|
13682
|
+
statsCommand.command("export").description("Analytics-Daten exportieren (Pro Feature)").option("--start <date>", "Start-Datum (YYYY-MM-DD)").option("--end <date>", "End-Datum (YYYY-MM-DD)").option("--format <format>", "Format: json, csv", "json").option("-o, --output <file>", "Ausgabedatei").action(async (options) => {
|
|
13683
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13684
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13685
|
+
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
13686
|
+
if (!isAuthenticated2()) {
|
|
13687
|
+
log.error("Nicht angemeldet");
|
|
13688
|
+
log.info("Anmelden mit: shiva login");
|
|
13689
|
+
return;
|
|
13690
|
+
}
|
|
13691
|
+
const spinner = ora18("Exportiere Analytics...").start();
|
|
13692
|
+
try {
|
|
13693
|
+
const result = await api2.exportAnalytics({
|
|
13694
|
+
startDate: options.start,
|
|
13695
|
+
endDate: options.end,
|
|
13696
|
+
format: options.format
|
|
13697
|
+
});
|
|
13698
|
+
spinner.stop();
|
|
13699
|
+
if (options.output) {
|
|
13700
|
+
const content = options.format === "json" ? JSON.stringify(result.data, null, 2) : String(result.data);
|
|
13701
|
+
writeFileSync11(options.output, content);
|
|
13702
|
+
log.success(`Analytics exportiert: ${options.output}`);
|
|
13703
|
+
} else {
|
|
13704
|
+
console.log(JSON.stringify(result, null, 2));
|
|
13705
|
+
}
|
|
13706
|
+
} catch (error) {
|
|
13707
|
+
spinner.fail("Fehler beim Exportieren");
|
|
13708
|
+
const err = error;
|
|
13709
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13710
|
+
log.warn("Analytics Export ist ein Pro-Feature");
|
|
13711
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13712
|
+
} else {
|
|
13713
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
});
|
|
13717
|
+
statsCommand.command("track").description("Analytics Event tracken").argument("<type>", "Event-Typ").argument("[data]", "Event-Daten als JSON").action(async (type2, data) => {
|
|
13718
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13719
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13720
|
+
if (!isAuthenticated2()) {
|
|
13721
|
+
log.error("Nicht angemeldet");
|
|
13722
|
+
log.info("Anmelden mit: shiva login");
|
|
13723
|
+
return;
|
|
13724
|
+
}
|
|
13725
|
+
try {
|
|
13726
|
+
const eventData = data ? JSON.parse(data) : {};
|
|
13727
|
+
const result = await api2.trackAnalyticsEvent({
|
|
13728
|
+
type: type2,
|
|
13729
|
+
data: eventData
|
|
13730
|
+
});
|
|
13731
|
+
if (result.success) {
|
|
13732
|
+
log.success("Event getrackt");
|
|
13733
|
+
} else {
|
|
13734
|
+
log.error("Event konnte nicht getrackt werden");
|
|
13735
|
+
}
|
|
13736
|
+
} catch (error) {
|
|
13737
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13738
|
+
}
|
|
13739
|
+
});
|
|
13740
|
+
|
|
13741
|
+
// src/commands/system/user.ts
|
|
13742
|
+
import { Command as Command32 } from "commander";
|
|
13743
|
+
import ora19 from "ora";
|
|
13744
|
+
var userCommand = new Command32("user").description("User Account Verwaltung");
|
|
13745
|
+
userCommand.command("profile").description("User-Profil anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13746
|
+
if (!isAuthenticated()) {
|
|
13747
|
+
log.error("Nicht angemeldet");
|
|
13748
|
+
log.info("Anmelden mit: shiva login");
|
|
13749
|
+
return;
|
|
13750
|
+
}
|
|
13751
|
+
const spinner = ora19("Lade Profil...").start();
|
|
13752
|
+
try {
|
|
13753
|
+
const profile = await api.getUserProfile();
|
|
13754
|
+
spinner.stop();
|
|
13755
|
+
if (options.json) {
|
|
13756
|
+
console.log(JSON.stringify(profile, null, 2));
|
|
13757
|
+
return;
|
|
13758
|
+
}
|
|
13759
|
+
log.newline();
|
|
13760
|
+
console.log(colors.orange.bold("User Profile"));
|
|
13761
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13762
|
+
log.newline();
|
|
13763
|
+
log.keyValue("ID", String(profile.id));
|
|
13764
|
+
log.keyValue("Email", profile.email);
|
|
13765
|
+
if (profile.name) {
|
|
13766
|
+
log.keyValue("Name", profile.name);
|
|
13767
|
+
}
|
|
13768
|
+
const tierColor = profile.tier === "pro" ? colors.cyan : profile.tier === "team" ? colors.green : colors.dim;
|
|
13769
|
+
log.keyValue("Tier", tierColor(profile.tier.toUpperCase()));
|
|
13770
|
+
log.keyValue("Seit", new Date(profile.createdAt).toLocaleDateString("de-DE"));
|
|
13771
|
+
} catch (error) {
|
|
13772
|
+
spinner.fail("Fehler beim Laden");
|
|
13773
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13774
|
+
}
|
|
13775
|
+
});
|
|
13776
|
+
userCommand.command("update").description("User-Profil aktualisieren").option("--name <name>", "Name setzen").action(async (options) => {
|
|
13777
|
+
if (!isAuthenticated()) {
|
|
13778
|
+
log.error("Nicht angemeldet");
|
|
13779
|
+
log.info("Anmelden mit: shiva login");
|
|
13780
|
+
return;
|
|
13781
|
+
}
|
|
13782
|
+
if (!options.name) {
|
|
13783
|
+
log.error("Keine \xC4nderungen angegeben");
|
|
13784
|
+
log.info("Verf\xFCgbare Optionen:");
|
|
13785
|
+
log.plain(" --name <name> Name setzen");
|
|
13786
|
+
return;
|
|
13787
|
+
}
|
|
13788
|
+
const spinner = ora19("Aktualisiere Profil...").start();
|
|
13789
|
+
try {
|
|
13790
|
+
const result = await api.updateUserProfile({
|
|
13791
|
+
name: options.name
|
|
13792
|
+
});
|
|
13793
|
+
if (result.success) {
|
|
13794
|
+
spinner.succeed("Profil aktualisiert");
|
|
13795
|
+
} else {
|
|
13796
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
13797
|
+
}
|
|
13798
|
+
} catch (error) {
|
|
13799
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
13800
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13801
|
+
}
|
|
13802
|
+
});
|
|
13803
|
+
userCommand.command("usage").description("Resource-Nutzung und Limits anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13804
|
+
if (!isAuthenticated()) {
|
|
13805
|
+
log.error("Nicht angemeldet");
|
|
13806
|
+
log.info("Anmelden mit: shiva login");
|
|
13807
|
+
return;
|
|
13808
|
+
}
|
|
13809
|
+
const spinner = ora19("Lade Usage...").start();
|
|
13810
|
+
try {
|
|
13811
|
+
const usage = await api.getUserUsage();
|
|
13812
|
+
spinner.stop();
|
|
13813
|
+
if (options.json) {
|
|
13814
|
+
console.log(JSON.stringify(usage, null, 2));
|
|
13815
|
+
return;
|
|
13816
|
+
}
|
|
13817
|
+
log.newline();
|
|
13818
|
+
console.log(colors.orange.bold("Resource Usage"));
|
|
13819
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13820
|
+
log.newline();
|
|
13821
|
+
const progressBar = (current, limit, label, unit) => {
|
|
13822
|
+
const percentage = Math.min(100, Math.round(current / limit * 100));
|
|
13823
|
+
const barWidth = 20;
|
|
13824
|
+
const filled = Math.round(current / limit * barWidth);
|
|
13825
|
+
const empty = barWidth - filled;
|
|
13826
|
+
const barColor = percentage >= 90 ? colors.red : percentage >= 70 ? colors.yellow : colors.green;
|
|
13827
|
+
const bar = barColor("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
|
|
13828
|
+
const unitStr = unit ? ` ${unit}` : "";
|
|
13829
|
+
console.log(` ${label.padEnd(12)} [${bar}] ${current}/${limit}${unitStr} (${percentage}%)`);
|
|
13830
|
+
};
|
|
13831
|
+
progressBar(usage.projects.current, usage.projects.limit, "Projects");
|
|
13832
|
+
progressBar(usage.sessions.current, usage.sessions.limit, "Sessions");
|
|
13833
|
+
progressBar(usage.storage.current, usage.storage.limit, "Storage", usage.storage.unit);
|
|
13834
|
+
progressBar(usage.apiCalls.current, usage.apiCalls.limit, "API Calls", `/${usage.apiCalls.period}`);
|
|
13835
|
+
log.newline();
|
|
13836
|
+
const nearLimit = (current, limit) => current / limit >= 0.9;
|
|
13837
|
+
if (nearLimit(usage.projects.current, usage.projects.limit) || nearLimit(usage.sessions.current, usage.sessions.limit) || nearLimit(usage.storage.current, usage.storage.limit) || nearLimit(usage.apiCalls.current, usage.apiCalls.limit)) {
|
|
13838
|
+
log.warn("Du erreichst bald deine Limits");
|
|
13839
|
+
log.info("Upgrade auf Pro: shiva user subscription");
|
|
13840
|
+
}
|
|
13841
|
+
} catch (error) {
|
|
13842
|
+
spinner.fail("Fehler beim Laden");
|
|
13843
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13844
|
+
}
|
|
13845
|
+
});
|
|
13846
|
+
userCommand.command("subscription").description("Subscription-Status anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13847
|
+
if (!isAuthenticated()) {
|
|
13848
|
+
log.error("Nicht angemeldet");
|
|
13849
|
+
log.info("Anmelden mit: shiva login");
|
|
13850
|
+
return;
|
|
13851
|
+
}
|
|
13852
|
+
const spinner = ora19("Lade Subscription...").start();
|
|
13853
|
+
try {
|
|
13854
|
+
const sub = await api.getSubscription();
|
|
13855
|
+
spinner.stop();
|
|
13856
|
+
if (options.json) {
|
|
13857
|
+
console.log(JSON.stringify(sub, null, 2));
|
|
13858
|
+
return;
|
|
13859
|
+
}
|
|
13860
|
+
log.newline();
|
|
13861
|
+
console.log(colors.orange.bold("Subscription"));
|
|
13862
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13863
|
+
log.newline();
|
|
13864
|
+
const tierColor = sub.tier === "pro" ? colors.cyan : sub.tier === "team" ? colors.green : colors.dim;
|
|
13865
|
+
log.keyValue("Tier", tierColor(sub.tier.toUpperCase()));
|
|
13866
|
+
const statusColor = sub.status === "active" ? colors.green : sub.status === "trialing" ? colors.yellow : colors.red;
|
|
13867
|
+
log.keyValue("Status", statusColor(sub.status));
|
|
13868
|
+
if (sub.billingCycle) {
|
|
13869
|
+
log.keyValue("Billing", sub.billingCycle);
|
|
13870
|
+
}
|
|
13871
|
+
if (sub.currentPeriodEnd) {
|
|
13872
|
+
const endDate = new Date(sub.currentPeriodEnd);
|
|
13873
|
+
const label = sub.cancelAtPeriodEnd ? "Endet am" : "Renewal";
|
|
13874
|
+
log.keyValue(label, endDate.toLocaleDateString("de-DE"));
|
|
13875
|
+
}
|
|
13876
|
+
if (sub.cancelAtPeriodEnd) {
|
|
13877
|
+
log.newline();
|
|
13878
|
+
log.warn("Subscription endet am Ende der aktuellen Periode");
|
|
13879
|
+
}
|
|
13880
|
+
log.newline();
|
|
13881
|
+
console.log(colors.bold("Features:"));
|
|
13882
|
+
for (const feature of sub.features) {
|
|
13883
|
+
console.log(` ${colors.green("\u2713")} ${feature}`);
|
|
13884
|
+
}
|
|
13885
|
+
if (sub.tier === "free") {
|
|
13886
|
+
log.newline();
|
|
13887
|
+
log.info("Upgrade auf Pro f\xFCr mehr Features:");
|
|
13888
|
+
log.plain(" https://shiva.li/pricing");
|
|
13889
|
+
}
|
|
13890
|
+
} catch (error) {
|
|
13891
|
+
spinner.fail("Fehler beim Laden");
|
|
13892
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13893
|
+
}
|
|
13894
|
+
});
|
|
13895
|
+
userCommand.command("token").description("Neuen CLI-Token generieren").option("--copy", "Token in Zwischenablage kopieren").action(async (options) => {
|
|
13896
|
+
if (!isAuthenticated()) {
|
|
13897
|
+
log.error("Nicht angemeldet");
|
|
13898
|
+
log.info("Anmelden mit: shiva login");
|
|
13899
|
+
return;
|
|
13900
|
+
}
|
|
13901
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
13902
|
+
const { confirm } = await inquirer14.prompt([{
|
|
13903
|
+
type: "confirm",
|
|
13904
|
+
name: "confirm",
|
|
13905
|
+
message: "Neuen Token generieren? Der alte Token wird ung\xFCltig.",
|
|
13906
|
+
default: false
|
|
13907
|
+
}]);
|
|
13908
|
+
if (!confirm) {
|
|
13909
|
+
log.dim("Abgebrochen");
|
|
13910
|
+
return;
|
|
13911
|
+
}
|
|
13912
|
+
const spinner = ora19("Generiere Token...").start();
|
|
13913
|
+
try {
|
|
13914
|
+
const result = await api.generateCliToken();
|
|
13915
|
+
spinner.stop();
|
|
13916
|
+
log.newline();
|
|
13917
|
+
log.success("Token generiert");
|
|
13918
|
+
log.newline();
|
|
13919
|
+
log.warn("Dieser Token wird nur einmal angezeigt!");
|
|
13920
|
+
log.newline();
|
|
13921
|
+
console.log(colors.dim("Token:"));
|
|
13922
|
+
console.log(colors.cyan(result.token));
|
|
13923
|
+
log.newline();
|
|
13924
|
+
log.keyValue("G\xFCltig bis", new Date(result.expiresAt).toLocaleDateString("de-DE"));
|
|
13925
|
+
if (options.copy) {
|
|
13926
|
+
try {
|
|
13927
|
+
const { copyToClipboard: copyToClipboard2 } = await import("./clipboard-ET53HNUB.js");
|
|
13928
|
+
await copyToClipboard2(result.token);
|
|
13929
|
+
log.success("Token in Zwischenablage kopiert");
|
|
13930
|
+
} catch {
|
|
13931
|
+
log.dim("Konnte nicht in Zwischenablage kopieren");
|
|
13932
|
+
}
|
|
13933
|
+
}
|
|
13934
|
+
log.newline();
|
|
13935
|
+
log.info("Verwendung:");
|
|
13936
|
+
log.plain(` export SHIVA_TOKEN="${result.token}"`);
|
|
13937
|
+
log.plain(" # oder in ~/.bashrc / ~/.zshrc");
|
|
13938
|
+
} catch (error) {
|
|
13939
|
+
spinner.fail("Fehler beim Generieren");
|
|
13940
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13941
|
+
}
|
|
13942
|
+
});
|
|
13943
|
+
userCommand.command("delete").description("Account unwiderruflich l\xF6schen").action(async () => {
|
|
13944
|
+
if (!isAuthenticated()) {
|
|
13945
|
+
log.error("Nicht angemeldet");
|
|
13946
|
+
return;
|
|
13947
|
+
}
|
|
13948
|
+
log.newline();
|
|
13949
|
+
log.warn("ACHTUNG: Account l\xF6schen ist IRREVERSIBEL!");
|
|
13950
|
+
log.newline();
|
|
13951
|
+
log.plain("Folgende Daten werden unwiderruflich gel\xF6scht:");
|
|
13952
|
+
log.plain(" \u2022 Alle Projekte und Memories");
|
|
13953
|
+
log.plain(" \u2022 Alle Sessions und Sandboxes");
|
|
13954
|
+
log.plain(" \u2022 Alle Secrets und Einstellungen");
|
|
13955
|
+
log.plain(" \u2022 Subscription und Zahlungsdaten");
|
|
13956
|
+
log.newline();
|
|
13957
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
13958
|
+
const { confirm1 } = await inquirer14.prompt([{
|
|
13959
|
+
type: "confirm",
|
|
13960
|
+
name: "confirm1",
|
|
13961
|
+
message: "Bist du sicher, dass du deinen Account l\xF6schen m\xF6chtest?",
|
|
13962
|
+
default: false
|
|
13963
|
+
}]);
|
|
13964
|
+
if (!confirm1) {
|
|
13965
|
+
log.dim("Abgebrochen");
|
|
13966
|
+
return;
|
|
13967
|
+
}
|
|
13968
|
+
const { confirmText } = await inquirer14.prompt([{
|
|
13969
|
+
type: "input",
|
|
13970
|
+
name: "confirmText",
|
|
13971
|
+
message: 'Tippe "DELETE" um zu best\xE4tigen:'
|
|
13972
|
+
}]);
|
|
13973
|
+
if (confirmText !== "DELETE") {
|
|
13974
|
+
log.dim("Abgebrochen (falscher Best\xE4tigungstext)");
|
|
13975
|
+
return;
|
|
13976
|
+
}
|
|
13977
|
+
const spinner = ora19("L\xF6sche Account...").start();
|
|
13978
|
+
try {
|
|
13979
|
+
const result = await api.deleteAccount("DELETE");
|
|
13980
|
+
if (result.success) {
|
|
13981
|
+
spinner.succeed("Account gel\xF6scht");
|
|
13982
|
+
log.newline();
|
|
13983
|
+
clearAuth();
|
|
13984
|
+
log.info("Lokale Anmeldedaten wurden entfernt");
|
|
13985
|
+
log.plain("Auf Wiedersehen!");
|
|
13986
|
+
} else {
|
|
13987
|
+
spinner.fail(result.message || "Fehler beim L\xF6schen");
|
|
13988
|
+
}
|
|
13989
|
+
} catch (error) {
|
|
13990
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
13991
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13992
|
+
}
|
|
13993
|
+
});
|
|
13994
|
+
userCommand.command("whoami").description("Aktuelle Anmeldung anzeigen").action(async () => {
|
|
13995
|
+
const config = getConfig();
|
|
13996
|
+
if (!isAuthenticated()) {
|
|
13997
|
+
log.info("Nicht angemeldet");
|
|
13998
|
+
log.plain("Anmelden mit: shiva login");
|
|
13999
|
+
return;
|
|
14000
|
+
}
|
|
14001
|
+
log.newline();
|
|
14002
|
+
log.keyValue("Email", config.email || "Unbekannt");
|
|
14003
|
+
log.keyValue("Tier", config.tier || "Unbekannt");
|
|
14004
|
+
log.keyValue("User ID", String(config.userId) || "Unbekannt");
|
|
14005
|
+
if (config.tokenExpiry) {
|
|
14006
|
+
const expiry = new Date(config.tokenExpiry);
|
|
14007
|
+
const now = /* @__PURE__ */ new Date();
|
|
14008
|
+
const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
14009
|
+
if (daysLeft > 0) {
|
|
14010
|
+
log.keyValue("Token g\xFCltig", `${daysLeft} Tage`);
|
|
14011
|
+
} else {
|
|
14012
|
+
log.warn("Token abgelaufen");
|
|
14013
|
+
log.info("Neu anmelden mit: shiva login");
|
|
14014
|
+
}
|
|
14015
|
+
}
|
|
14016
|
+
});
|
|
14017
|
+
|
|
14018
|
+
// src/commands/advanced/docker.ts
|
|
14019
|
+
import { Command as Command33 } from "commander";
|
|
14020
|
+
import ora20 from "ora";
|
|
14021
|
+
var dockerCommand = new Command33("docker").description("Docker-Integration verwalten");
|
|
14022
|
+
dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
|
|
14023
|
+
log.brand();
|
|
14024
|
+
log.header("Docker Status");
|
|
14025
|
+
log.newline();
|
|
14026
|
+
const info = dockerService.getDockerInfo();
|
|
14027
|
+
const settings = settingsSync.getDockerSettings();
|
|
14028
|
+
if (info.available) {
|
|
14029
|
+
log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
|
|
14030
|
+
log.keyValue("Socket", info.socket || colors.dim("default"));
|
|
14031
|
+
log.keyValue("Status", colors.green("Verf\xFCgbar"));
|
|
14032
|
+
} else {
|
|
14033
|
+
log.keyValue("Runtime", colors.dim("nicht gefunden"));
|
|
14034
|
+
log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
|
|
14035
|
+
log.newline();
|
|
14036
|
+
log.warn("Docker oder Podman ist nicht installiert");
|
|
14037
|
+
log.dim("Installation:");
|
|
14038
|
+
log.dim(" Docker: https://docs.docker.com/get-docker/");
|
|
14039
|
+
log.dim(" Podman: https://podman.io/get-started");
|
|
13525
14040
|
return;
|
|
13526
14041
|
}
|
|
13527
14042
|
log.newline();
|
|
@@ -13568,7 +14083,7 @@ dockerCommand.command("enable").description("Docker-Modus aktivieren").action(as
|
|
|
13568
14083
|
return;
|
|
13569
14084
|
}
|
|
13570
14085
|
const image = dockerService.getDefaultImage();
|
|
13571
|
-
const spinner =
|
|
14086
|
+
const spinner = ora20(`Pr\xFCfe Image: ${image}...`).start();
|
|
13572
14087
|
if (!dockerService.imageExists(image)) {
|
|
13573
14088
|
spinner.text = `Lade Image herunter: ${image}...`;
|
|
13574
14089
|
try {
|
|
@@ -13627,7 +14142,7 @@ dockerCommand.command("logs").description("Container-Logs anzeigen").argument("<
|
|
|
13627
14142
|
console.log(logs);
|
|
13628
14143
|
});
|
|
13629
14144
|
dockerCommand.command("stop").description("Container stoppen").argument("<name>", "Container-Name oder ID").action(async (name) => {
|
|
13630
|
-
const spinner =
|
|
14145
|
+
const spinner = ora20(`Stoppe Container ${name}...`).start();
|
|
13631
14146
|
try {
|
|
13632
14147
|
await dockerService.stopContainer(name);
|
|
13633
14148
|
spinner.succeed(`Container gestoppt: ${name}`);
|
|
@@ -13637,7 +14152,7 @@ dockerCommand.command("stop").description("Container stoppen").argument("<name>"
|
|
|
13637
14152
|
}
|
|
13638
14153
|
});
|
|
13639
14154
|
dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").action(async () => {
|
|
13640
|
-
const spinner =
|
|
14155
|
+
const spinner = ora20("R\xE4ume Container auf...").start();
|
|
13641
14156
|
try {
|
|
13642
14157
|
const count = await dockerService.cleanContainers();
|
|
13643
14158
|
spinner.succeed(`${count} Container entfernt`);
|
|
@@ -13648,7 +14163,7 @@ dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").a
|
|
|
13648
14163
|
});
|
|
13649
14164
|
dockerCommand.command("pull").description("Docker-Image herunterladen").argument("[image]", "Image-Name (default: shiva/claude-runner:latest)").action(async (image) => {
|
|
13650
14165
|
const targetImage = image || dockerService.getDefaultImage();
|
|
13651
|
-
const spinner =
|
|
14166
|
+
const spinner = ora20(`Lade Image herunter: ${targetImage}...`).start();
|
|
13652
14167
|
try {
|
|
13653
14168
|
await dockerService.pullImage(targetImage);
|
|
13654
14169
|
spinner.succeed(`Image heruntergeladen: ${targetImage}`);
|
|
@@ -13733,11 +14248,11 @@ dockerCommand.action(() => {
|
|
|
13733
14248
|
});
|
|
13734
14249
|
|
|
13735
14250
|
// src/commands/advanced/workflow.ts
|
|
13736
|
-
import { Command as
|
|
14251
|
+
import { Command as Command34 } from "commander";
|
|
13737
14252
|
import * as fs13 from "fs";
|
|
13738
14253
|
import * as path14 from "path";
|
|
13739
14254
|
import * as os6 from "os";
|
|
13740
|
-
import
|
|
14255
|
+
import ora21 from "ora";
|
|
13741
14256
|
import inquirer12 from "inquirer";
|
|
13742
14257
|
var builtInWorkflows = {
|
|
13743
14258
|
morning: {
|
|
@@ -13757,7 +14272,7 @@ var builtInWorkflows = {
|
|
|
13757
14272
|
]
|
|
13758
14273
|
}
|
|
13759
14274
|
};
|
|
13760
|
-
var workflowCommand = new
|
|
14275
|
+
var workflowCommand = new Command34("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
|
|
13761
14276
|
await listWorkflows();
|
|
13762
14277
|
});
|
|
13763
14278
|
workflowCommand.command("list").alias("ls").description("Verf\xFCgbare Workflows anzeigen").action(async () => {
|
|
@@ -13926,7 +14441,7 @@ function deleteCustomWorkflow(name) {
|
|
|
13926
14441
|
fs13.writeFileSync(filepath, JSON.stringify(workflows, null, 2));
|
|
13927
14442
|
}
|
|
13928
14443
|
async function executeStep(step) {
|
|
13929
|
-
const spinner =
|
|
14444
|
+
const spinner = ora21("Ausf\xFChren...").start();
|
|
13930
14445
|
try {
|
|
13931
14446
|
switch (step.type) {
|
|
13932
14447
|
case "issues": {
|
|
@@ -14012,7 +14527,7 @@ async function executeStep(step) {
|
|
|
14012
14527
|
}
|
|
14013
14528
|
|
|
14014
14529
|
// src/commands/advanced/hook.ts
|
|
14015
|
-
import { Command as
|
|
14530
|
+
import { Command as Command35 } from "commander";
|
|
14016
14531
|
import { existsSync as existsSync21, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6 } from "fs";
|
|
14017
14532
|
import { homedir as homedir7 } from "os";
|
|
14018
14533
|
import { join as join12 } from "path";
|
|
@@ -14047,7 +14562,7 @@ function removeShivaHooks(eventHooks) {
|
|
|
14047
14562
|
(entry) => !entry.hooks?.some((h) => h.command?.includes("shiva"))
|
|
14048
14563
|
);
|
|
14049
14564
|
}
|
|
14050
|
-
var hookCommand = new
|
|
14565
|
+
var hookCommand = new Command35("hook").description("Claude Code Hook Integration verwalten");
|
|
14051
14566
|
hookCommand.command("install").description("SHIVA Hooks in Claude Code installieren").option("--github", "GitHub Context Injection aktivieren").option("--sync", "Cloud Sync Hooks aktivieren (Standard)").option("--scan", "Package Security Scanning aktivieren").option("--all", "Alle Hooks aktivieren").action((options) => {
|
|
14052
14567
|
log.brand();
|
|
14053
14568
|
const claudePath = join12(homedir7(), ".claude");
|
|
@@ -14382,7 +14897,7 @@ hookCommand.command("scan-command").description("Scanne Bash-Befehle auf Package
|
|
|
14382
14897
|
}
|
|
14383
14898
|
});
|
|
14384
14899
|
hookCommand.command("push").description("Hooks in Cloud sichern").action(async () => {
|
|
14385
|
-
const { api: api2 } = await import("./client-
|
|
14900
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14386
14901
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14387
14902
|
if (!isAuthenticated2()) {
|
|
14388
14903
|
log.error("Nicht angemeldet");
|
|
@@ -14395,78 +14910,252 @@ hookCommand.command("push").description("Hooks in Cloud sichern").action(async (
|
|
|
14395
14910
|
return;
|
|
14396
14911
|
}
|
|
14397
14912
|
try {
|
|
14398
|
-
await api2.updateHooks(settings.hooks);
|
|
14399
|
-
log.success("Hooks in Cloud gesichert");
|
|
14913
|
+
await api2.updateHooks(settings.hooks);
|
|
14914
|
+
log.success("Hooks in Cloud gesichert");
|
|
14915
|
+
} catch (error) {
|
|
14916
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
|
|
14917
|
+
}
|
|
14918
|
+
});
|
|
14919
|
+
hookCommand.command("pull").description("Hooks aus Cloud laden").option("-f, --force", "Lokale Hooks \xFCberschreiben").action(async (options) => {
|
|
14920
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14921
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14922
|
+
if (!isAuthenticated2()) {
|
|
14923
|
+
log.error("Nicht angemeldet");
|
|
14924
|
+
log.info("Anmelden mit: shiva login");
|
|
14925
|
+
return;
|
|
14926
|
+
}
|
|
14927
|
+
const settings = getClaudeSettings();
|
|
14928
|
+
if (settings.hooks && !options.force) {
|
|
14929
|
+
log.warn("Lokale Hooks existieren bereits");
|
|
14930
|
+
log.info("Mit --force \xFCberschreiben");
|
|
14931
|
+
return;
|
|
14932
|
+
}
|
|
14933
|
+
try {
|
|
14934
|
+
const result = await api2.getHooks();
|
|
14935
|
+
if (!result.hooks || Object.keys(result.hooks).length === 0) {
|
|
14936
|
+
log.info("Keine Hooks in Cloud gefunden");
|
|
14937
|
+
return;
|
|
14938
|
+
}
|
|
14939
|
+
settings.hooks = result.hooks;
|
|
14940
|
+
saveClaudeSettings(settings);
|
|
14941
|
+
log.success("Hooks aus Cloud geladen");
|
|
14942
|
+
log.newline();
|
|
14943
|
+
log.info("Aktive Hooks:");
|
|
14944
|
+
for (const [event, hooks] of Object.entries(result.hooks)) {
|
|
14945
|
+
log.tree.item(`${event}: ${Array.isArray(hooks) ? hooks.length : 1} Hook(s)`);
|
|
14946
|
+
}
|
|
14947
|
+
} catch (error) {
|
|
14948
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Laden");
|
|
14949
|
+
}
|
|
14950
|
+
});
|
|
14951
|
+
hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
|
|
14952
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14953
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14954
|
+
if (!isAuthenticated2()) {
|
|
14955
|
+
log.error("Nicht angemeldet");
|
|
14956
|
+
log.info("Anmelden mit: shiva login");
|
|
14957
|
+
return;
|
|
14958
|
+
}
|
|
14959
|
+
const settings = getClaudeSettings();
|
|
14960
|
+
try {
|
|
14961
|
+
if (settings.hooks) {
|
|
14962
|
+
await api2.updateHooks(settings.hooks);
|
|
14963
|
+
log.success("Lokale Hooks \u2192 Cloud");
|
|
14964
|
+
}
|
|
14965
|
+
const result = await api2.getHooks();
|
|
14966
|
+
if (result.hooks && Object.keys(result.hooks).length > 0) {
|
|
14967
|
+
const merged = { ...result.hooks, ...settings.hooks };
|
|
14968
|
+
settings.hooks = merged;
|
|
14969
|
+
saveClaudeSettings(settings);
|
|
14970
|
+
log.success("Cloud Hooks \u2192 Lokal (merged)");
|
|
14971
|
+
}
|
|
14972
|
+
log.newline();
|
|
14973
|
+
log.success("Hooks synchronisiert");
|
|
14974
|
+
} catch (error) {
|
|
14975
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
|
|
14976
|
+
}
|
|
14977
|
+
});
|
|
14978
|
+
hookCommand.command("cloud-list").description("Cloud-Hooks auflisten").option("--event <type>", "Nach Event-Typ filtern").option("--json", "JSON Output").action(async (options) => {
|
|
14979
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14980
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14981
|
+
const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
|
|
14982
|
+
if (!isAuthenticated2()) {
|
|
14983
|
+
log.error("Nicht angemeldet");
|
|
14984
|
+
log.info("Anmelden mit: shiva login");
|
|
14985
|
+
return;
|
|
14986
|
+
}
|
|
14987
|
+
const ora24 = (await import("ora")).default;
|
|
14988
|
+
const spinner = ora24("Lade Cloud-Hooks...").start();
|
|
14989
|
+
try {
|
|
14990
|
+
let hooks;
|
|
14991
|
+
if (options.event) {
|
|
14992
|
+
hooks = await api2.getHooksForEvent(options.event);
|
|
14993
|
+
} else {
|
|
14994
|
+
const result = await api2.getHooks();
|
|
14995
|
+
hooks = result.hooks || [];
|
|
14996
|
+
}
|
|
14997
|
+
spinner.stop();
|
|
14998
|
+
if (options.json) {
|
|
14999
|
+
console.log(JSON.stringify(hooks, null, 2));
|
|
15000
|
+
return;
|
|
15001
|
+
}
|
|
15002
|
+
log.newline();
|
|
15003
|
+
console.log(colors3.orange.bold("Cloud Hooks"));
|
|
15004
|
+
console.log(colors3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15005
|
+
log.newline();
|
|
15006
|
+
if (!hooks || Array.isArray(hooks) && hooks.length === 0) {
|
|
15007
|
+
log.dim("Keine Cloud-Hooks konfiguriert");
|
|
15008
|
+
return;
|
|
15009
|
+
}
|
|
15010
|
+
const hooksArray = Array.isArray(hooks) ? hooks : Object.values(hooks).flat();
|
|
15011
|
+
for (const hook of hooksArray) {
|
|
15012
|
+
const enabledIcon = hook.enabled !== false ? colors3.green("\u25CF") : colors3.dim("\u25CB");
|
|
15013
|
+
console.log(` ${enabledIcon} ${colors3.bold(hook.id || hook.event)}`);
|
|
15014
|
+
console.log(` ${colors3.dim("Event:")} ${hook.event}`);
|
|
15015
|
+
if (hook.matcher) {
|
|
15016
|
+
console.log(` ${colors3.dim("Matcher:")} ${hook.matcher}`);
|
|
15017
|
+
}
|
|
15018
|
+
console.log(` ${colors3.dim("Type:")} ${hook.type}`);
|
|
15019
|
+
console.log(` ${colors3.dim("Command:")} ${hook.command}`);
|
|
15020
|
+
log.newline();
|
|
15021
|
+
}
|
|
15022
|
+
} catch (error) {
|
|
15023
|
+
spinner.fail("Fehler beim Laden");
|
|
15024
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15025
|
+
}
|
|
15026
|
+
});
|
|
15027
|
+
hookCommand.command("cloud-create").description("Neuen Cloud-Hook erstellen").requiredOption("--event <event>", "Event-Typ (PreToolUse, PostToolUse, etc.)").requiredOption("--command <cmd>", "Auszuf\xFChrender Befehl").option("--matcher <pattern>", "Tool-Matcher Pattern").option("--type <type>", "Hook-Typ (command, script)", "command").option("--timeout <ms>", "Timeout in Millisekunden").action(async (options) => {
|
|
15028
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
15029
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
15030
|
+
if (!isAuthenticated2()) {
|
|
15031
|
+
log.error("Nicht angemeldet");
|
|
15032
|
+
log.info("Anmelden mit: shiva login");
|
|
15033
|
+
return;
|
|
15034
|
+
}
|
|
15035
|
+
const ora24 = (await import("ora")).default;
|
|
15036
|
+
const spinner = ora24("Erstelle Cloud-Hook...").start();
|
|
15037
|
+
try {
|
|
15038
|
+
const result = await api2.createHook({
|
|
15039
|
+
event: options.event,
|
|
15040
|
+
command: options.command,
|
|
15041
|
+
matcher: options.matcher,
|
|
15042
|
+
type: options.type,
|
|
15043
|
+
timeout: options.timeout ? parseInt(options.timeout) : void 0
|
|
15044
|
+
});
|
|
15045
|
+
if (result.success) {
|
|
15046
|
+
spinner.succeed(`Hook erstellt: ${result.hookId}`);
|
|
15047
|
+
} else {
|
|
15048
|
+
spinner.fail(result.message || "Fehler beim Erstellen");
|
|
15049
|
+
}
|
|
15050
|
+
} catch (error) {
|
|
15051
|
+
spinner.fail("Fehler beim Erstellen");
|
|
15052
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15053
|
+
}
|
|
15054
|
+
});
|
|
15055
|
+
hookCommand.command("cloud-test").description("Cloud-Hook testen").argument("<hook-id>", "Hook ID").action(async (hookId) => {
|
|
15056
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
15057
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
15058
|
+
const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
|
|
15059
|
+
if (!isAuthenticated2()) {
|
|
15060
|
+
log.error("Nicht angemeldet");
|
|
15061
|
+
log.info("Anmelden mit: shiva login");
|
|
15062
|
+
return;
|
|
15063
|
+
}
|
|
15064
|
+
const ora24 = (await import("ora")).default;
|
|
15065
|
+
const spinner = ora24("Teste Hook...").start();
|
|
15066
|
+
try {
|
|
15067
|
+
const result = await api2.testHook(hookId);
|
|
15068
|
+
spinner.stop();
|
|
15069
|
+
log.newline();
|
|
15070
|
+
if (result.success) {
|
|
15071
|
+
log.success(`Hook erfolgreich (${result.duration}ms)`);
|
|
15072
|
+
if (result.output) {
|
|
15073
|
+
log.newline();
|
|
15074
|
+
console.log(colors3.dim("Output:"));
|
|
15075
|
+
console.log(result.output);
|
|
15076
|
+
}
|
|
15077
|
+
} else {
|
|
15078
|
+
log.error(`Hook fehlgeschlagen (${result.duration}ms)`);
|
|
15079
|
+
if (result.error) {
|
|
15080
|
+
log.newline();
|
|
15081
|
+
console.log(colors3.dim("Error:"));
|
|
15082
|
+
console.log(colors3.red(result.error));
|
|
15083
|
+
}
|
|
15084
|
+
}
|
|
14400
15085
|
} catch (error) {
|
|
14401
|
-
|
|
15086
|
+
spinner.fail("Fehler beim Testen");
|
|
15087
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14402
15088
|
}
|
|
14403
15089
|
});
|
|
14404
|
-
hookCommand.command("
|
|
14405
|
-
const { api: api2 } = await import("./client-
|
|
15090
|
+
hookCommand.command("cloud-delete").description("Cloud-Hook l\xF6schen").argument("<hook-id>", "Hook ID").option("-y, --yes", "Ohne Best\xE4tigung").action(async (hookId, options) => {
|
|
15091
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14406
15092
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14407
15093
|
if (!isAuthenticated2()) {
|
|
14408
15094
|
log.error("Nicht angemeldet");
|
|
14409
15095
|
log.info("Anmelden mit: shiva login");
|
|
14410
15096
|
return;
|
|
14411
15097
|
}
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
if (!
|
|
14421
|
-
log.
|
|
15098
|
+
if (!options.yes) {
|
|
15099
|
+
const inquirer14 = (await import("inquirer")).default;
|
|
15100
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15101
|
+
type: "confirm",
|
|
15102
|
+
name: "confirm",
|
|
15103
|
+
message: `Hook ${hookId} l\xF6schen?`,
|
|
15104
|
+
default: false
|
|
15105
|
+
}]);
|
|
15106
|
+
if (!confirm) {
|
|
15107
|
+
log.dim("Abgebrochen");
|
|
14422
15108
|
return;
|
|
14423
15109
|
}
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
15110
|
+
}
|
|
15111
|
+
const ora24 = (await import("ora")).default;
|
|
15112
|
+
const spinner = ora24("L\xF6sche Hook...").start();
|
|
15113
|
+
try {
|
|
15114
|
+
const result = await api2.deleteHook(hookId);
|
|
15115
|
+
if (result.success) {
|
|
15116
|
+
spinner.succeed("Hook gel\xF6scht");
|
|
15117
|
+
} else {
|
|
15118
|
+
spinner.fail(result.message || "Fehler beim L\xF6schen");
|
|
14431
15119
|
}
|
|
14432
15120
|
} catch (error) {
|
|
14433
|
-
|
|
15121
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
15122
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14434
15123
|
}
|
|
14435
15124
|
});
|
|
14436
|
-
hookCommand.command("
|
|
14437
|
-
const { api: api2 } = await import("./client-
|
|
15125
|
+
hookCommand.command("cloud-toggle").description("Cloud-Hook aktivieren/deaktivieren").argument("<hook-id>", "Hook ID").option("--enable", "Hook aktivieren").option("--disable", "Hook deaktivieren").action(async (hookId, options) => {
|
|
15126
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14438
15127
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14439
15128
|
if (!isAuthenticated2()) {
|
|
14440
15129
|
log.error("Nicht angemeldet");
|
|
14441
15130
|
log.info("Anmelden mit: shiva login");
|
|
14442
15131
|
return;
|
|
14443
15132
|
}
|
|
14444
|
-
const
|
|
15133
|
+
const enabled = options.enable ? true : options.disable ? false : void 0;
|
|
15134
|
+
if (enabled === void 0) {
|
|
15135
|
+
log.error("Bitte --enable oder --disable angeben");
|
|
15136
|
+
return;
|
|
15137
|
+
}
|
|
15138
|
+
const ora24 = (await import("ora")).default;
|
|
15139
|
+
const spinner = ora24("Aktualisiere Hook...").start();
|
|
14445
15140
|
try {
|
|
14446
|
-
|
|
14447
|
-
|
|
14448
|
-
|
|
14449
|
-
}
|
|
14450
|
-
|
|
14451
|
-
if (result.hooks && Object.keys(result.hooks).length > 0) {
|
|
14452
|
-
const merged = { ...result.hooks, ...settings.hooks };
|
|
14453
|
-
settings.hooks = merged;
|
|
14454
|
-
saveClaudeSettings(settings);
|
|
14455
|
-
log.success("Cloud Hooks \u2192 Lokal (merged)");
|
|
15141
|
+
const result = await api2.updateHook(hookId, { enabled });
|
|
15142
|
+
if (result.success) {
|
|
15143
|
+
spinner.succeed(`Hook ${enabled ? "aktiviert" : "deaktiviert"}`);
|
|
15144
|
+
} else {
|
|
15145
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
14456
15146
|
}
|
|
14457
|
-
log.newline();
|
|
14458
|
-
log.success("Hooks synchronisiert");
|
|
14459
15147
|
} catch (error) {
|
|
14460
|
-
|
|
15148
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
15149
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14461
15150
|
}
|
|
14462
15151
|
});
|
|
14463
15152
|
|
|
14464
15153
|
// src/commands/advanced/package.ts
|
|
14465
|
-
import { Command as
|
|
15154
|
+
import { Command as Command36 } from "commander";
|
|
14466
15155
|
import * as fs14 from "fs";
|
|
14467
15156
|
import inquirer13 from "inquirer";
|
|
14468
|
-
import
|
|
14469
|
-
var packageCommand = new
|
|
15157
|
+
import ora22 from "ora";
|
|
15158
|
+
var packageCommand = new Command36("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
|
|
14470
15159
|
listPackages();
|
|
14471
15160
|
});
|
|
14472
15161
|
packageCommand.command("list").description("Alle Packages auflisten").option("--json", "JSON Output").action((options) => {
|
|
@@ -14582,7 +15271,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
|
|
|
14582
15271
|
log.error(`Package "${pkg.name}" hat keine Projekte.`);
|
|
14583
15272
|
return;
|
|
14584
15273
|
}
|
|
14585
|
-
const spinner =
|
|
15274
|
+
const spinner = ora22("Bereite Projekte vor...").start();
|
|
14586
15275
|
try {
|
|
14587
15276
|
const launches = await getPackageLaunchConfig(name, options.new);
|
|
14588
15277
|
spinner.stop();
|
|
@@ -14611,7 +15300,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
|
|
|
14611
15300
|
}
|
|
14612
15301
|
});
|
|
14613
15302
|
packageCommand.command("push").description("Packages in Cloud sichern").option("-n, --name <name>", "Nur ein bestimmtes Package").action(async (options) => {
|
|
14614
|
-
const { api: api2 } = await import("./client-
|
|
15303
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14615
15304
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14616
15305
|
if (!isAuthenticated2()) {
|
|
14617
15306
|
log.error("Nicht angemeldet");
|
|
@@ -14632,7 +15321,7 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
|
|
|
14632
15321
|
log.warn("Keine Packages zum Synchronisieren gefunden");
|
|
14633
15322
|
return;
|
|
14634
15323
|
}
|
|
14635
|
-
const spinner =
|
|
15324
|
+
const spinner = ora22("Synchronisiere Packages...").start();
|
|
14636
15325
|
let syncedCount = 0;
|
|
14637
15326
|
let errorCount = 0;
|
|
14638
15327
|
for (const pkg of packages) {
|
|
@@ -14657,14 +15346,14 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
|
|
|
14657
15346
|
}
|
|
14658
15347
|
});
|
|
14659
15348
|
packageCommand.command("pull").description("Packages aus Cloud laden").option("-f, --force", "Lokale Packages \xFCberschreiben").option("--json", "JSON Output").action(async (options) => {
|
|
14660
|
-
const { api: api2 } = await import("./client-
|
|
15349
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14661
15350
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14662
15351
|
if (!isAuthenticated2()) {
|
|
14663
15352
|
log.error("Nicht angemeldet");
|
|
14664
15353
|
log.info("Anmelden mit: shiva login");
|
|
14665
15354
|
return;
|
|
14666
15355
|
}
|
|
14667
|
-
const spinner =
|
|
15356
|
+
const spinner = ora22("Lade Packages aus Cloud...").start();
|
|
14668
15357
|
try {
|
|
14669
15358
|
const cloudPackages = await api2.getPackages();
|
|
14670
15359
|
spinner.stop();
|
|
@@ -14719,14 +15408,14 @@ packageCommand.command("pull").description("Packages aus Cloud laden").option("-
|
|
|
14719
15408
|
}
|
|
14720
15409
|
});
|
|
14721
15410
|
packageCommand.command("sync").description("Packages mit Cloud synchronisieren").action(async () => {
|
|
14722
|
-
const { api: api2 } = await import("./client-
|
|
15411
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14723
15412
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14724
15413
|
if (!isAuthenticated2()) {
|
|
14725
15414
|
log.error("Nicht angemeldet");
|
|
14726
15415
|
log.info("Anmelden mit: shiva login");
|
|
14727
15416
|
return;
|
|
14728
15417
|
}
|
|
14729
|
-
const spinner =
|
|
15418
|
+
const spinner = ora22("Synchronisiere Packages...").start();
|
|
14730
15419
|
const localPackages = getAllPackages();
|
|
14731
15420
|
let pushedCount = 0;
|
|
14732
15421
|
for (const pkg of localPackages) {
|
|
@@ -14772,7 +15461,7 @@ packageCommand.command("sync").description("Packages mit Cloud synchronisieren")
|
|
|
14772
15461
|
log.tree.item(`${localPackages.length + pulledCount} Packages total`);
|
|
14773
15462
|
});
|
|
14774
15463
|
packageCommand.command("cloud-delete <name>").description("Package aus Cloud l\xF6schen").action(async (name) => {
|
|
14775
|
-
const { api: api2 } = await import("./client-
|
|
15464
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14776
15465
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14777
15466
|
if (!isAuthenticated2()) {
|
|
14778
15467
|
log.error("Nicht angemeldet");
|
|
@@ -14828,8 +15517,361 @@ function listPackages() {
|
|
|
14828
15517
|
log.newline();
|
|
14829
15518
|
}
|
|
14830
15519
|
|
|
15520
|
+
// src/commands/advanced/sandbox.ts
|
|
15521
|
+
import { Command as Command37 } from "commander";
|
|
15522
|
+
import ora23 from "ora";
|
|
15523
|
+
var sandboxCommand = new Command37("sandbox").description("Sandbox-Management mit Cloud-Sync");
|
|
15524
|
+
sandboxCommand.command("list").description("Alle Sandboxes auflisten").option("--local", "Nur lokale Sandboxes").option("--cloud", "Nur Cloud Sandboxes").option("--status <status>", "Nach Status filtern: active, pending-review, applied, discarded").option("--json", "JSON Output").action(async (options) => {
|
|
15525
|
+
const spinner = ora23("Lade Sandboxes...").start();
|
|
15526
|
+
try {
|
|
15527
|
+
const results = [];
|
|
15528
|
+
if (!options.cloud) {
|
|
15529
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15530
|
+
for (const sandbox of localSandboxes) {
|
|
15531
|
+
if (!options.status || sandbox.status === options.status) {
|
|
15532
|
+
results.push({
|
|
15533
|
+
id: sandbox.id,
|
|
15534
|
+
source: "local",
|
|
15535
|
+
status: sandbox.status,
|
|
15536
|
+
mode: sandbox.mode,
|
|
15537
|
+
projectPath: sandbox.projectPath,
|
|
15538
|
+
createdAt: sandbox.createdAt
|
|
15539
|
+
});
|
|
15540
|
+
}
|
|
15541
|
+
}
|
|
15542
|
+
}
|
|
15543
|
+
if (!options.local && isAuthenticated()) {
|
|
15544
|
+
try {
|
|
15545
|
+
const cloudSandboxes = await api.getSandboxes(
|
|
15546
|
+
options.status ? { status: options.status } : void 0
|
|
15547
|
+
);
|
|
15548
|
+
for (const sandbox of cloudSandboxes) {
|
|
15549
|
+
results.push({
|
|
15550
|
+
id: sandbox.id,
|
|
15551
|
+
source: "cloud",
|
|
15552
|
+
status: sandbox.status,
|
|
15553
|
+
mode: sandbox.mode,
|
|
15554
|
+
projectId: sandbox.projectId,
|
|
15555
|
+
createdAt: sandbox.createdAt,
|
|
15556
|
+
title: sandbox.title
|
|
15557
|
+
});
|
|
15558
|
+
}
|
|
15559
|
+
} catch {
|
|
15560
|
+
}
|
|
15561
|
+
}
|
|
15562
|
+
spinner.stop();
|
|
15563
|
+
if (options.json) {
|
|
15564
|
+
console.log(JSON.stringify(results, null, 2));
|
|
15565
|
+
return;
|
|
15566
|
+
}
|
|
15567
|
+
log.newline();
|
|
15568
|
+
console.log(colors.orange.bold("Sandboxes"));
|
|
15569
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15570
|
+
log.newline();
|
|
15571
|
+
if (results.length === 0) {
|
|
15572
|
+
log.dim("Keine Sandboxes gefunden");
|
|
15573
|
+
return;
|
|
15574
|
+
}
|
|
15575
|
+
for (const sandbox of results) {
|
|
15576
|
+
const statusColor = sandbox.status === "active" ? colors.green : sandbox.status === "pending-review" ? colors.yellow : colors.dim;
|
|
15577
|
+
const sourceIcon = sandbox.source === "cloud" ? colors.cyan("\u2601") : colors.dim("\u{1F4BB}");
|
|
15578
|
+
console.log(` ${sourceIcon} ${colors.bold(sandbox.id)} ${statusColor(`[${sandbox.status}]`)}`);
|
|
15579
|
+
console.log(` ${colors.dim("Mode:")} ${sandbox.mode}`);
|
|
15580
|
+
if (sandbox.title) {
|
|
15581
|
+
console.log(` ${colors.dim("Title:")} ${sandbox.title}`);
|
|
15582
|
+
}
|
|
15583
|
+
if (sandbox.projectPath) {
|
|
15584
|
+
console.log(` ${colors.dim("Project:")} ${sandbox.projectPath}`);
|
|
15585
|
+
}
|
|
15586
|
+
console.log(` ${colors.dim("Created:")} ${sandbox.createdAt}`);
|
|
15587
|
+
log.newline();
|
|
15588
|
+
}
|
|
15589
|
+
} catch (error) {
|
|
15590
|
+
spinner.fail("Fehler beim Laden");
|
|
15591
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15592
|
+
}
|
|
15593
|
+
});
|
|
15594
|
+
sandboxCommand.command("pending").description("Sandboxes mit Pending Review Status").option("--json", "JSON Output").action(async (options) => {
|
|
15595
|
+
const spinner = ora23("Lade Pending Sandboxes...").start();
|
|
15596
|
+
try {
|
|
15597
|
+
const localPending = sandboxService.listPendingReview();
|
|
15598
|
+
let cloudPending = [];
|
|
15599
|
+
if (isAuthenticated()) {
|
|
15600
|
+
try {
|
|
15601
|
+
cloudPending = await api.getPendingSandboxes();
|
|
15602
|
+
} catch {
|
|
15603
|
+
}
|
|
15604
|
+
}
|
|
15605
|
+
spinner.stop();
|
|
15606
|
+
if (options.json) {
|
|
15607
|
+
console.log(JSON.stringify({ local: localPending, cloud: cloudPending }, null, 2));
|
|
15608
|
+
return;
|
|
15609
|
+
}
|
|
15610
|
+
log.newline();
|
|
15611
|
+
console.log(colors.orange.bold("Pending Review"));
|
|
15612
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15613
|
+
log.newline();
|
|
15614
|
+
if (localPending.length === 0 && cloudPending.length === 0) {
|
|
15615
|
+
log.dim("Keine Sandboxes zum Review");
|
|
15616
|
+
return;
|
|
15617
|
+
}
|
|
15618
|
+
if (localPending.length > 0) {
|
|
15619
|
+
console.log(colors.dim("Local:"));
|
|
15620
|
+
for (const sandbox of localPending) {
|
|
15621
|
+
console.log(` ${colors.yellow("\u25CB")} ${sandbox.id} - ${sandbox.projectPath}`);
|
|
15622
|
+
}
|
|
15623
|
+
log.newline();
|
|
15624
|
+
}
|
|
15625
|
+
if (cloudPending.length > 0) {
|
|
15626
|
+
console.log(colors.dim("Cloud:"));
|
|
15627
|
+
for (const sandbox of cloudPending) {
|
|
15628
|
+
console.log(` ${colors.cyan("\u2601")} ${sandbox.id} - ${sandbox.title || sandbox.baseBranch}`);
|
|
15629
|
+
}
|
|
15630
|
+
log.newline();
|
|
15631
|
+
}
|
|
15632
|
+
log.info("Review mit: shiva session review <id>");
|
|
15633
|
+
} catch (error) {
|
|
15634
|
+
spinner.fail("Fehler beim Laden");
|
|
15635
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15636
|
+
}
|
|
15637
|
+
});
|
|
15638
|
+
sandboxCommand.command("stats").description("Sandbox-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
15639
|
+
const spinner = ora23("Lade Statistiken...").start();
|
|
15640
|
+
try {
|
|
15641
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15642
|
+
const localStats = {
|
|
15643
|
+
total: localSandboxes.length,
|
|
15644
|
+
active: localSandboxes.filter((s) => s.status === "active").length,
|
|
15645
|
+
pendingReview: localSandboxes.filter((s) => s.status === "pending-review").length,
|
|
15646
|
+
applied: localSandboxes.filter((s) => s.status === "applied").length,
|
|
15647
|
+
discarded: localSandboxes.filter((s) => s.status === "discarded").length
|
|
15648
|
+
};
|
|
15649
|
+
let cloudStats = { total: 0, active: 0, pendingReview: 0, applied: 0, discarded: 0 };
|
|
15650
|
+
if (isAuthenticated()) {
|
|
15651
|
+
try {
|
|
15652
|
+
cloudStats = await api.getSandboxStats();
|
|
15653
|
+
} catch {
|
|
15654
|
+
}
|
|
15655
|
+
}
|
|
15656
|
+
spinner.stop();
|
|
15657
|
+
if (options.json) {
|
|
15658
|
+
console.log(JSON.stringify({ local: localStats, cloud: cloudStats }, null, 2));
|
|
15659
|
+
return;
|
|
15660
|
+
}
|
|
15661
|
+
log.newline();
|
|
15662
|
+
console.log(colors.orange.bold("Sandbox Statistics"));
|
|
15663
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15664
|
+
log.newline();
|
|
15665
|
+
console.log(colors.bold("Local:"));
|
|
15666
|
+
console.log(` ${colors.dim("Total:")} ${localStats.total}`);
|
|
15667
|
+
console.log(` ${colors.green("Active:")} ${localStats.active}`);
|
|
15668
|
+
console.log(` ${colors.yellow("Pending:")} ${localStats.pendingReview}`);
|
|
15669
|
+
console.log(` ${colors.dim("Applied:")} ${localStats.applied}`);
|
|
15670
|
+
console.log(` ${colors.dim("Discarded:")} ${localStats.discarded}`);
|
|
15671
|
+
log.newline();
|
|
15672
|
+
if (isAuthenticated()) {
|
|
15673
|
+
console.log(colors.bold("Cloud:"));
|
|
15674
|
+
console.log(` ${colors.dim("Total:")} ${cloudStats.total}`);
|
|
15675
|
+
console.log(` ${colors.green("Active:")} ${cloudStats.active}`);
|
|
15676
|
+
console.log(` ${colors.yellow("Pending:")} ${cloudStats.pendingReview}`);
|
|
15677
|
+
console.log(` ${colors.dim("Applied:")} ${cloudStats.applied}`);
|
|
15678
|
+
console.log(` ${colors.dim("Discarded:")} ${cloudStats.discarded}`);
|
|
15679
|
+
} else {
|
|
15680
|
+
log.dim("Cloud-Statistiken: Nicht angemeldet");
|
|
15681
|
+
}
|
|
15682
|
+
} catch (error) {
|
|
15683
|
+
spinner.fail("Fehler beim Laden");
|
|
15684
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15685
|
+
}
|
|
15686
|
+
});
|
|
15687
|
+
sandboxCommand.command("sync").description("Sandbox mit Cloud synchronisieren").argument("[id]", "Sandbox ID (optional)").option("--status <status>", "Status setzen: pending-review, applied, discarded").action(async (id, options) => {
|
|
15688
|
+
if (!isAuthenticated()) {
|
|
15689
|
+
log.error("Nicht angemeldet");
|
|
15690
|
+
log.info("Anmelden mit: shiva login");
|
|
15691
|
+
return;
|
|
15692
|
+
}
|
|
15693
|
+
const spinner = ora23("Synchronisiere Sandbox...").start();
|
|
15694
|
+
try {
|
|
15695
|
+
if (id) {
|
|
15696
|
+
await api.syncSandbox(id, {
|
|
15697
|
+
status: options.status
|
|
15698
|
+
});
|
|
15699
|
+
spinner.succeed(`Sandbox ${id} synchronisiert`);
|
|
15700
|
+
} else {
|
|
15701
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15702
|
+
let synced = 0;
|
|
15703
|
+
for (const sandbox of localSandboxes) {
|
|
15704
|
+
try {
|
|
15705
|
+
await api.syncSandbox(sandbox.id, {
|
|
15706
|
+
status: sandbox.status === "active" ? void 0 : sandbox.status
|
|
15707
|
+
});
|
|
15708
|
+
synced++;
|
|
15709
|
+
} catch {
|
|
15710
|
+
}
|
|
15711
|
+
}
|
|
15712
|
+
spinner.succeed(`${synced}/${localSandboxes.length} Sandboxes synchronisiert`);
|
|
15713
|
+
}
|
|
15714
|
+
} catch (error) {
|
|
15715
|
+
spinner.fail("Fehler beim Synchronisieren");
|
|
15716
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15717
|
+
}
|
|
15718
|
+
});
|
|
15719
|
+
sandboxCommand.command("cleanup").description("Alte Sandboxes aufr\xE4umen").option("--days <days>", "\xC4lter als X Tage", "30").option("--local", "Nur lokal aufr\xE4umen").option("--cloud", "Nur Cloud aufr\xE4umen").option("-y, --yes", "Ohne Best\xE4tigung").action(async (options) => {
|
|
15720
|
+
const days = parseInt(options.days);
|
|
15721
|
+
if (!options.yes) {
|
|
15722
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
15723
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15724
|
+
type: "confirm",
|
|
15725
|
+
name: "confirm",
|
|
15726
|
+
message: `Sandboxes \xE4lter als ${days} Tage l\xF6schen?`,
|
|
15727
|
+
default: false
|
|
15728
|
+
}]);
|
|
15729
|
+
if (!confirm) {
|
|
15730
|
+
log.dim("Abgebrochen");
|
|
15731
|
+
return;
|
|
15732
|
+
}
|
|
15733
|
+
}
|
|
15734
|
+
const spinner = ora23("R\xE4ume Sandboxes auf...").start();
|
|
15735
|
+
try {
|
|
15736
|
+
let localDeleted = 0;
|
|
15737
|
+
let cloudDeleted = 0;
|
|
15738
|
+
if (!options.cloud) {
|
|
15739
|
+
localDeleted = await sandboxService.cleanupOldSandboxes(days);
|
|
15740
|
+
}
|
|
15741
|
+
if (!options.local && isAuthenticated()) {
|
|
15742
|
+
try {
|
|
15743
|
+
const result = await api.cleanupSandboxes({ olderThanDays: days });
|
|
15744
|
+
cloudDeleted = result.deletedCount;
|
|
15745
|
+
} catch {
|
|
15746
|
+
}
|
|
15747
|
+
}
|
|
15748
|
+
spinner.stop();
|
|
15749
|
+
log.success("Cleanup abgeschlossen");
|
|
15750
|
+
log.newline();
|
|
15751
|
+
log.keyValue("Lokal gel\xF6scht", String(localDeleted));
|
|
15752
|
+
if (!options.local) {
|
|
15753
|
+
log.keyValue("Cloud gel\xF6scht", String(cloudDeleted));
|
|
15754
|
+
}
|
|
15755
|
+
} catch (error) {
|
|
15756
|
+
spinner.fail("Fehler beim Aufr\xE4umen");
|
|
15757
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15758
|
+
}
|
|
15759
|
+
});
|
|
15760
|
+
sandboxCommand.command("config").description("Sandbox-Konfiguration verwalten").option("--show", "Konfiguration anzeigen").option("--mode <mode>", "Standard-Modus: worktree, copy, docker-overlay").option("--cleanup-days <days>", "Auto-Cleanup nach X Tagen").option("--max <n>", "Maximale aktive Sandboxes").option("--require-review", "Review vor Apply erforderlich").option("--no-require-review", "Review nicht erforderlich").option("--pull", "Konfiguration aus Cloud laden").option("--push", "Konfiguration in Cloud speichern").action(async (options) => {
|
|
15761
|
+
if (options.pull && isAuthenticated()) {
|
|
15762
|
+
const spinner = ora23("Lade Konfiguration aus Cloud...").start();
|
|
15763
|
+
try {
|
|
15764
|
+
const cloudConfig = await api.getSandboxConfig();
|
|
15765
|
+
sandboxService.updateConfig({
|
|
15766
|
+
defaultMode: cloudConfig.defaultMode,
|
|
15767
|
+
keepDays: cloudConfig.autoCleanupDays,
|
|
15768
|
+
maxSandboxes: cloudConfig.maxActiveSandboxes
|
|
15769
|
+
});
|
|
15770
|
+
spinner.succeed("Konfiguration aus Cloud geladen");
|
|
15771
|
+
return;
|
|
15772
|
+
} catch (error) {
|
|
15773
|
+
spinner.fail("Fehler beim Laden aus Cloud");
|
|
15774
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15775
|
+
return;
|
|
15776
|
+
}
|
|
15777
|
+
}
|
|
15778
|
+
if (options.push && isAuthenticated()) {
|
|
15779
|
+
const spinner = ora23("Speichere Konfiguration in Cloud...").start();
|
|
15780
|
+
try {
|
|
15781
|
+
const localConfig = sandboxService.getConfig();
|
|
15782
|
+
const cloudMode = localConfig.defaultMode === "none" ? "worktree" : localConfig.defaultMode;
|
|
15783
|
+
await api.updateSandboxConfig({
|
|
15784
|
+
defaultMode: cloudMode,
|
|
15785
|
+
autoCleanupDays: localConfig.keepDays,
|
|
15786
|
+
maxActiveSandboxes: localConfig.maxSandboxes,
|
|
15787
|
+
requireReview: options.requireReview ?? true
|
|
15788
|
+
});
|
|
15789
|
+
spinner.succeed("Konfiguration in Cloud gespeichert");
|
|
15790
|
+
return;
|
|
15791
|
+
} catch (error) {
|
|
15792
|
+
spinner.fail("Fehler beim Speichern in Cloud");
|
|
15793
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15794
|
+
return;
|
|
15795
|
+
}
|
|
15796
|
+
}
|
|
15797
|
+
if (options.show || !options.mode && !options.cleanupDays && !options.max && options.requireReview === void 0) {
|
|
15798
|
+
const config = sandboxService.getConfig();
|
|
15799
|
+
log.newline();
|
|
15800
|
+
console.log(colors.orange.bold("Sandbox Configuration"));
|
|
15801
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15802
|
+
log.newline();
|
|
15803
|
+
log.keyValue("Enabled", config.enabled ? colors.green("Yes") : colors.red("No"));
|
|
15804
|
+
log.keyValue("Default Mode", config.defaultMode);
|
|
15805
|
+
log.keyValue("Auto Cleanup", config.autoCleanup ? "Yes" : "No");
|
|
15806
|
+
log.keyValue("Keep Days", String(config.keepDays));
|
|
15807
|
+
log.keyValue("Max Sandboxes", String(config.maxSandboxes));
|
|
15808
|
+
log.newline();
|
|
15809
|
+
if (isAuthenticated()) {
|
|
15810
|
+
try {
|
|
15811
|
+
const cloudConfig = await api.getSandboxConfig();
|
|
15812
|
+
console.log(colors.bold("Cloud Config:"));
|
|
15813
|
+
log.keyValue(" Default Mode", cloudConfig.defaultMode);
|
|
15814
|
+
log.keyValue(" Cleanup Days", String(cloudConfig.autoCleanupDays));
|
|
15815
|
+
log.keyValue(" Max Active", String(cloudConfig.maxActiveSandboxes));
|
|
15816
|
+
log.keyValue(" Require Review", cloudConfig.requireReview ? "Yes" : "No");
|
|
15817
|
+
} catch {
|
|
15818
|
+
log.dim("Cloud-Konfiguration nicht verf\xFCgbar");
|
|
15819
|
+
}
|
|
15820
|
+
}
|
|
15821
|
+
return;
|
|
15822
|
+
}
|
|
15823
|
+
const updates = {};
|
|
15824
|
+
if (options.mode) {
|
|
15825
|
+
updates.defaultMode = options.mode;
|
|
15826
|
+
}
|
|
15827
|
+
if (options.cleanupDays) {
|
|
15828
|
+
updates.keepDays = parseInt(options.cleanupDays);
|
|
15829
|
+
}
|
|
15830
|
+
if (options.max) {
|
|
15831
|
+
updates.maxSandboxes = parseInt(options.max);
|
|
15832
|
+
}
|
|
15833
|
+
sandboxService.updateConfig(updates);
|
|
15834
|
+
log.success("Konfiguration aktualisiert");
|
|
15835
|
+
});
|
|
15836
|
+
sandboxCommand.command("delete <id>").description("Sandbox l\xF6schen").option("--cloud", "Auch aus Cloud l\xF6schen").option("-y, --yes", "Ohne Best\xE4tigung").action(async (id, options) => {
|
|
15837
|
+
if (!options.yes) {
|
|
15838
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
15839
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15840
|
+
type: "confirm",
|
|
15841
|
+
name: "confirm",
|
|
15842
|
+
message: `Sandbox ${id} l\xF6schen?`,
|
|
15843
|
+
default: false
|
|
15844
|
+
}]);
|
|
15845
|
+
if (!confirm) {
|
|
15846
|
+
log.dim("Abgebrochen");
|
|
15847
|
+
return;
|
|
15848
|
+
}
|
|
15849
|
+
}
|
|
15850
|
+
const spinner = ora23("L\xF6sche Sandbox...").start();
|
|
15851
|
+
try {
|
|
15852
|
+
try {
|
|
15853
|
+
await sandboxService.deleteSandbox(id);
|
|
15854
|
+
spinner.text = "Lokal gel\xF6scht";
|
|
15855
|
+
} catch {
|
|
15856
|
+
}
|
|
15857
|
+
if (options.cloud || isAuthenticated()) {
|
|
15858
|
+
try {
|
|
15859
|
+
await api.deleteSandbox(id);
|
|
15860
|
+
spinner.succeed("Sandbox gel\xF6scht (lokal + cloud)");
|
|
15861
|
+
} catch {
|
|
15862
|
+
spinner.succeed("Sandbox gel\xF6scht (lokal)");
|
|
15863
|
+
}
|
|
15864
|
+
} else {
|
|
15865
|
+
spinner.succeed("Sandbox gel\xF6scht");
|
|
15866
|
+
}
|
|
15867
|
+
} catch (error) {
|
|
15868
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
15869
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15870
|
+
}
|
|
15871
|
+
});
|
|
15872
|
+
|
|
14831
15873
|
// src/index.ts
|
|
14832
|
-
var program = new
|
|
15874
|
+
var program = new Command38();
|
|
14833
15875
|
program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.5.4");
|
|
14834
15876
|
program.addCommand(loginCommand);
|
|
14835
15877
|
program.addCommand(logoutCommand);
|
|
@@ -14869,6 +15911,8 @@ program.addCommand(dockerCommand);
|
|
|
14869
15911
|
program.addCommand(workflowCommand);
|
|
14870
15912
|
program.addCommand(hookCommand);
|
|
14871
15913
|
program.addCommand(packageCommand);
|
|
15914
|
+
program.addCommand(sandboxCommand);
|
|
15915
|
+
program.addCommand(userCommand);
|
|
14872
15916
|
program.action(async () => {
|
|
14873
15917
|
await showDashboard();
|
|
14874
15918
|
});
|