shiva-code 0.5.4 → 0.6.0
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 +1344 -321
- 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";
|
|
@@ -6775,7 +6670,7 @@ async function checkProjectExists(path15) {
|
|
|
6775
6670
|
}
|
|
6776
6671
|
}
|
|
6777
6672
|
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-
|
|
6673
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6779
6674
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6780
6675
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6781
6676
|
if (!isAuthenticated2()) {
|
|
@@ -6835,7 +6730,7 @@ sessionsCommand.command("push").description("Sessions in Cloud sichern").option(
|
|
|
6835
6730
|
}
|
|
6836
6731
|
});
|
|
6837
6732
|
sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
6838
|
-
const { api: api2 } = await import("./client-
|
|
6733
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6839
6734
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6840
6735
|
if (!isAuthenticated2()) {
|
|
6841
6736
|
log.error("Nicht angemeldet");
|
|
@@ -6882,7 +6777,7 @@ sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("
|
|
|
6882
6777
|
}
|
|
6883
6778
|
});
|
|
6884
6779
|
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-
|
|
6780
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6886
6781
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6887
6782
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6888
6783
|
if (!isAuthenticated2()) {
|
|
@@ -6935,7 +6830,7 @@ sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren"
|
|
|
6935
6830
|
log.dim("Sessions werden automatisch mit lokalen Claude Sessions verkn\xFCpft");
|
|
6936
6831
|
});
|
|
6937
6832
|
sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\xF6schen").action(async (sessionId) => {
|
|
6938
|
-
const { api: api2 } = await import("./client-
|
|
6833
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6939
6834
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6940
6835
|
if (!isAuthenticated2()) {
|
|
6941
6836
|
log.error("Nicht angemeldet");
|
|
@@ -6953,6 +6848,152 @@ sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\x
|
|
|
6953
6848
|
log.error(error instanceof Error ? error.message : "Fehler beim L\xF6schen");
|
|
6954
6849
|
}
|
|
6955
6850
|
});
|
|
6851
|
+
sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6852
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6853
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6854
|
+
if (!isAuthenticated2()) {
|
|
6855
|
+
log.error("Nicht angemeldet");
|
|
6856
|
+
log.info("Anmelden mit: shiva login");
|
|
6857
|
+
return;
|
|
6858
|
+
}
|
|
6859
|
+
const spinner = ora9("Lade aktive Sessions...").start();
|
|
6860
|
+
try {
|
|
6861
|
+
const sessions = await api2.getActiveSessions();
|
|
6862
|
+
spinner.stop();
|
|
6863
|
+
if (options.json) {
|
|
6864
|
+
console.log(JSON.stringify(sessions, null, 2));
|
|
6865
|
+
return;
|
|
6866
|
+
}
|
|
6867
|
+
log.newline();
|
|
6868
|
+
console.log(colors.orange.bold("Active Cloud Sessions"));
|
|
6869
|
+
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"));
|
|
6870
|
+
log.newline();
|
|
6871
|
+
if (sessions.length === 0) {
|
|
6872
|
+
log.dim("Keine aktiven Cloud-Sessions");
|
|
6873
|
+
return;
|
|
6874
|
+
}
|
|
6875
|
+
for (const session of sessions) {
|
|
6876
|
+
console.log(` ${colors.green("\u25CF")} ${colors.bold(session.sessionId)}`);
|
|
6877
|
+
console.log(` ${colors.dim("Project ID:")} ${session.projectId}`);
|
|
6878
|
+
console.log(` ${colors.dim("Started:")} ${session.startedAt}`);
|
|
6879
|
+
console.log(` ${colors.dim("Last Activity:")} ${session.lastActivity}`);
|
|
6880
|
+
console.log(` ${colors.dim("Messages:")} ${session.messageCount}`);
|
|
6881
|
+
log.newline();
|
|
6882
|
+
}
|
|
6883
|
+
} catch (error) {
|
|
6884
|
+
spinner.fail("Fehler beim Laden");
|
|
6885
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6886
|
+
}
|
|
6887
|
+
});
|
|
6888
|
+
sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6889
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6890
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6891
|
+
if (!isAuthenticated2()) {
|
|
6892
|
+
log.error("Nicht angemeldet");
|
|
6893
|
+
log.info("Anmelden mit: shiva login");
|
|
6894
|
+
return;
|
|
6895
|
+
}
|
|
6896
|
+
const spinner = ora9("Lade Session-Statistiken...").start();
|
|
6897
|
+
try {
|
|
6898
|
+
const stats = await api2.getSessionStats();
|
|
6899
|
+
spinner.stop();
|
|
6900
|
+
if (options.json) {
|
|
6901
|
+
console.log(JSON.stringify(stats, null, 2));
|
|
6902
|
+
return;
|
|
6903
|
+
}
|
|
6904
|
+
log.newline();
|
|
6905
|
+
console.log(colors.orange.bold("Session Statistics"));
|
|
6906
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
6907
|
+
log.newline();
|
|
6908
|
+
log.keyValue("Total Sessions", String(stats.totalSessions));
|
|
6909
|
+
log.keyValue("Active Sessions", String(stats.activeSessions));
|
|
6910
|
+
log.keyValue("Total Messages", String(stats.totalMessages));
|
|
6911
|
+
log.keyValue("Avg Session Length", `${stats.averageSessionLength} min`);
|
|
6912
|
+
log.newline();
|
|
6913
|
+
log.keyValue("Sessions (Last 7 Days)", String(stats.sessionsLast7Days));
|
|
6914
|
+
log.keyValue("Sessions (Last 30 Days)", String(stats.sessionsLast30Days));
|
|
6915
|
+
} catch (error) {
|
|
6916
|
+
spinner.fail("Fehler beim Laden");
|
|
6917
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6918
|
+
}
|
|
6919
|
+
});
|
|
6920
|
+
sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortsetzen").action(async (sessionId) => {
|
|
6921
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6922
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6923
|
+
if (!isAuthenticated2()) {
|
|
6924
|
+
log.error("Nicht angemeldet");
|
|
6925
|
+
log.info("Anmelden mit: shiva login");
|
|
6926
|
+
return;
|
|
6927
|
+
}
|
|
6928
|
+
const spinner = ora9("Lade Session...").start();
|
|
6929
|
+
try {
|
|
6930
|
+
const result = await api2.resumeSession(sessionId);
|
|
6931
|
+
if (result.success) {
|
|
6932
|
+
spinner.succeed("Session geladen");
|
|
6933
|
+
log.newline();
|
|
6934
|
+
log.info("Session kann jetzt fortgesetzt werden");
|
|
6935
|
+
log.plain(` claude --session ${sessionId}`);
|
|
6936
|
+
} else {
|
|
6937
|
+
spinner.fail(result.message || "Fehler beim Laden");
|
|
6938
|
+
}
|
|
6939
|
+
} catch (error) {
|
|
6940
|
+
spinner.fail("Fehler beim Laden");
|
|
6941
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6942
|
+
}
|
|
6943
|
+
});
|
|
6944
|
+
sessionsCommand.command("export <sessionId>").description("Cloud-Session exportieren").option("-o, --output <file>", "Ausgabedatei").action(async (sessionId, options) => {
|
|
6945
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6946
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6947
|
+
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
6948
|
+
if (!isAuthenticated2()) {
|
|
6949
|
+
log.error("Nicht angemeldet");
|
|
6950
|
+
log.info("Anmelden mit: shiva login");
|
|
6951
|
+
return;
|
|
6952
|
+
}
|
|
6953
|
+
const spinner = ora9("Exportiere Session...").start();
|
|
6954
|
+
try {
|
|
6955
|
+
const exportData = await api2.exportSession(sessionId);
|
|
6956
|
+
spinner.stop();
|
|
6957
|
+
if (options.output) {
|
|
6958
|
+
writeFileSync11(options.output, JSON.stringify(exportData, null, 2));
|
|
6959
|
+
log.success(`Session exportiert: ${options.output}`);
|
|
6960
|
+
} else {
|
|
6961
|
+
console.log(JSON.stringify(exportData, null, 2));
|
|
6962
|
+
}
|
|
6963
|
+
} catch (error) {
|
|
6964
|
+
spinner.fail("Fehler beim Exportieren");
|
|
6965
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6966
|
+
}
|
|
6967
|
+
});
|
|
6968
|
+
sessionsCommand.command("update <sessionId>").description("Cloud-Session aktualisieren").option("--summary <text>", "Session-Zusammenfassung").option("--branch <name>", "Git Branch").action(async (sessionId, options) => {
|
|
6969
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
6970
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6971
|
+
if (!isAuthenticated2()) {
|
|
6972
|
+
log.error("Nicht angemeldet");
|
|
6973
|
+
log.info("Anmelden mit: shiva login");
|
|
6974
|
+
return;
|
|
6975
|
+
}
|
|
6976
|
+
if (!options.summary && !options.branch) {
|
|
6977
|
+
log.error("Keine \xC4nderungen angegeben");
|
|
6978
|
+
log.info("Verf\xFCgbare Optionen: --summary, --branch");
|
|
6979
|
+
return;
|
|
6980
|
+
}
|
|
6981
|
+
const spinner = ora9("Aktualisiere Session...").start();
|
|
6982
|
+
try {
|
|
6983
|
+
const result = await api2.updateSession(sessionId, {
|
|
6984
|
+
summary: options.summary,
|
|
6985
|
+
gitBranch: options.branch
|
|
6986
|
+
});
|
|
6987
|
+
if (result.success) {
|
|
6988
|
+
spinner.succeed("Session aktualisiert");
|
|
6989
|
+
} else {
|
|
6990
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
6991
|
+
}
|
|
6992
|
+
} catch (error) {
|
|
6993
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
6994
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
6995
|
+
}
|
|
6996
|
+
});
|
|
6956
6997
|
|
|
6957
6998
|
// src/commands/session/session.ts
|
|
6958
6999
|
import { Command as Command14 } from "commander";
|
|
@@ -10389,67 +10430,6 @@ import inquirer8 from "inquirer";
|
|
|
10389
10430
|
import ora13 from "ora";
|
|
10390
10431
|
import * as fs6 from "fs";
|
|
10391
10432
|
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
10433
|
var SECURE_FILE_MODE = 384;
|
|
10454
10434
|
var secretsCommand = new Command20("secrets").description("API Keys und Secrets verwalten (Cloud Vault)").action(async () => {
|
|
10455
10435
|
await listSecrets();
|
|
@@ -11802,7 +11782,8 @@ function getColorFunction(color) {
|
|
|
11802
11782
|
case "yellow":
|
|
11803
11783
|
return colors.yellow;
|
|
11804
11784
|
case "magenta":
|
|
11805
|
-
return colors.
|
|
11785
|
+
return colors.cyan;
|
|
11786
|
+
// magenta not available, use cyan
|
|
11806
11787
|
case "cyan":
|
|
11807
11788
|
return colors.cyan;
|
|
11808
11789
|
default:
|
|
@@ -11830,6 +11811,40 @@ async function resolveSessionId(input) {
|
|
|
11830
11811
|
}
|
|
11831
11812
|
return null;
|
|
11832
11813
|
}
|
|
11814
|
+
tagsCommand.command("cloud").description("Memory-Tags aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
11815
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
11816
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
11817
|
+
if (!isAuthenticated2()) {
|
|
11818
|
+
log.error("Nicht angemeldet");
|
|
11819
|
+
log.info("Anmelden mit: shiva login");
|
|
11820
|
+
return;
|
|
11821
|
+
}
|
|
11822
|
+
const ora24 = (await import("ora")).default;
|
|
11823
|
+
const spinner = ora24("Lade Memory-Tags aus Cloud...").start();
|
|
11824
|
+
try {
|
|
11825
|
+
const cloudTags = await api2.getMemoryTags();
|
|
11826
|
+
spinner.stop();
|
|
11827
|
+
if (options.json) {
|
|
11828
|
+
console.log(JSON.stringify(cloudTags, null, 2));
|
|
11829
|
+
return;
|
|
11830
|
+
}
|
|
11831
|
+
log.newline();
|
|
11832
|
+
console.log(colors.orange.bold("Memory Tags (Cloud)"));
|
|
11833
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
11834
|
+
log.newline();
|
|
11835
|
+
if (cloudTags.length === 0) {
|
|
11836
|
+
log.dim("Keine Memory-Tags in Cloud");
|
|
11837
|
+
return;
|
|
11838
|
+
}
|
|
11839
|
+
for (const { tag, count } of cloudTags) {
|
|
11840
|
+
console.log(` ${colors.cyan(`[${tag}]`)} ${colors.dim(`(${count} Memories)`)}`);
|
|
11841
|
+
}
|
|
11842
|
+
log.newline();
|
|
11843
|
+
} catch (error) {
|
|
11844
|
+
spinner.fail("Fehler beim Laden");
|
|
11845
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
11846
|
+
}
|
|
11847
|
+
});
|
|
11833
11848
|
|
|
11834
11849
|
// src/commands/memory/export.ts
|
|
11835
11850
|
import { Command as Command25 } from "commander";
|
|
@@ -11841,7 +11856,7 @@ import inquirer11 from "inquirer";
|
|
|
11841
11856
|
// src/services/session/export.ts
|
|
11842
11857
|
import * as fs9 from "fs";
|
|
11843
11858
|
import * as path10 from "path";
|
|
11844
|
-
import { execSync as
|
|
11859
|
+
import { execSync as execSync2 } from "child_process";
|
|
11845
11860
|
async function exportSession(sessionId, options = {}) {
|
|
11846
11861
|
const projects = await getAllClaudeProjects();
|
|
11847
11862
|
for (const project of projects) {
|
|
@@ -11953,7 +11968,7 @@ function createBackupArchive(outputPath, projectPaths) {
|
|
|
11953
11968
|
return false;
|
|
11954
11969
|
}
|
|
11955
11970
|
const tarArgs = includePaths.join(" ");
|
|
11956
|
-
|
|
11971
|
+
execSync2(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
|
|
11957
11972
|
stdio: "ignore"
|
|
11958
11973
|
});
|
|
11959
11974
|
return true;
|
|
@@ -12061,7 +12076,7 @@ function restoreFromArchive(archivePath, targetDir) {
|
|
|
12061
12076
|
if (!fs9.existsSync(extractTo)) {
|
|
12062
12077
|
fs9.mkdirSync(extractTo, { recursive: true });
|
|
12063
12078
|
}
|
|
12064
|
-
|
|
12079
|
+
execSync2(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
|
|
12065
12080
|
stdio: "ignore"
|
|
12066
12081
|
});
|
|
12067
12082
|
return true;
|
|
@@ -12340,20 +12355,20 @@ var rememberCommand = new Command26("remember").description("Memory in der Cloud
|
|
|
12340
12355
|
|
|
12341
12356
|
// src/commands/system/doctor.ts
|
|
12342
12357
|
import { Command as Command27 } from "commander";
|
|
12343
|
-
import { execSync as
|
|
12358
|
+
import { execSync as execSync3 } from "child_process";
|
|
12344
12359
|
import * as fs11 from "fs";
|
|
12345
12360
|
import * as path12 from "path";
|
|
12346
12361
|
import * as os5 from "os";
|
|
12347
12362
|
function tryExec(command) {
|
|
12348
12363
|
try {
|
|
12349
|
-
return
|
|
12364
|
+
return execSync3(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
12350
12365
|
} catch {
|
|
12351
12366
|
return null;
|
|
12352
12367
|
}
|
|
12353
12368
|
}
|
|
12354
|
-
function
|
|
12369
|
+
function commandExists2(cmd) {
|
|
12355
12370
|
try {
|
|
12356
|
-
|
|
12371
|
+
execSync3(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
|
|
12357
12372
|
return true;
|
|
12358
12373
|
} catch {
|
|
12359
12374
|
return false;
|
|
@@ -12366,7 +12381,7 @@ function getVersion(cmd, versionFlag = "--version") {
|
|
|
12366
12381
|
return match ? match[0] : output.split("\n")[0];
|
|
12367
12382
|
}
|
|
12368
12383
|
function checkClaude() {
|
|
12369
|
-
const exists =
|
|
12384
|
+
const exists = commandExists2("claude");
|
|
12370
12385
|
if (!exists) {
|
|
12371
12386
|
return {
|
|
12372
12387
|
name: "Claude CLI",
|
|
@@ -12383,7 +12398,7 @@ function checkClaude() {
|
|
|
12383
12398
|
};
|
|
12384
12399
|
}
|
|
12385
12400
|
function checkGitHub() {
|
|
12386
|
-
const exists =
|
|
12401
|
+
const exists = commandExists2("gh");
|
|
12387
12402
|
if (!exists) {
|
|
12388
12403
|
return {
|
|
12389
12404
|
name: "GitHub CLI (gh)",
|
|
@@ -12404,7 +12419,7 @@ function checkGitHub() {
|
|
|
12404
12419
|
};
|
|
12405
12420
|
}
|
|
12406
12421
|
function checkDocker() {
|
|
12407
|
-
const dockerExists =
|
|
12422
|
+
const dockerExists = commandExists2("docker");
|
|
12408
12423
|
if (dockerExists) {
|
|
12409
12424
|
const version = getVersion("docker");
|
|
12410
12425
|
const isRunning = tryExec("docker info 2>/dev/null") !== null;
|
|
@@ -12416,7 +12431,7 @@ function checkDocker() {
|
|
|
12416
12431
|
hint: isRunning ? void 0 : "Starte Docker Desktop oder: sudo systemctl start docker"
|
|
12417
12432
|
};
|
|
12418
12433
|
}
|
|
12419
|
-
const podmanExists =
|
|
12434
|
+
const podmanExists = commandExists2("podman");
|
|
12420
12435
|
if (podmanExists) {
|
|
12421
12436
|
const version = getVersion("podman");
|
|
12422
12437
|
return {
|
|
@@ -12433,7 +12448,7 @@ function checkDocker() {
|
|
|
12433
12448
|
};
|
|
12434
12449
|
}
|
|
12435
12450
|
function checkGit() {
|
|
12436
|
-
const exists =
|
|
12451
|
+
const exists = commandExists2("git");
|
|
12437
12452
|
if (!exists) {
|
|
12438
12453
|
return {
|
|
12439
12454
|
name: "Git",
|
|
@@ -12461,7 +12476,7 @@ function checkGit() {
|
|
|
12461
12476
|
};
|
|
12462
12477
|
}
|
|
12463
12478
|
function checkNode() {
|
|
12464
|
-
const exists =
|
|
12479
|
+
const exists = commandExists2("node");
|
|
12465
12480
|
if (!exists) {
|
|
12466
12481
|
return {
|
|
12467
12482
|
name: "Node.js",
|
|
@@ -12488,7 +12503,7 @@ function checkNode() {
|
|
|
12488
12503
|
};
|
|
12489
12504
|
}
|
|
12490
12505
|
function checkNpm() {
|
|
12491
|
-
const exists =
|
|
12506
|
+
const exists = commandExists2("npm");
|
|
12492
12507
|
if (!exists) {
|
|
12493
12508
|
return {
|
|
12494
12509
|
name: "npm",
|
|
@@ -12556,7 +12571,7 @@ function checkClaudeProjects() {
|
|
|
12556
12571
|
}
|
|
12557
12572
|
}
|
|
12558
12573
|
function checkTmux() {
|
|
12559
|
-
const exists =
|
|
12574
|
+
const exists = commandExists2("tmux");
|
|
12560
12575
|
if (!exists) {
|
|
12561
12576
|
return {
|
|
12562
12577
|
name: "tmux",
|
|
@@ -12667,7 +12682,7 @@ var doctorCommand = new Command27("doctor").description("System-Check f\xFCr SHI
|
|
|
12667
12682
|
|
|
12668
12683
|
// src/commands/system/upgrade.ts
|
|
12669
12684
|
import { Command as Command28 } from "commander";
|
|
12670
|
-
import { execSync as
|
|
12685
|
+
import { execSync as execSync4, spawn as spawn6 } from "child_process";
|
|
12671
12686
|
import * as fs12 from "fs";
|
|
12672
12687
|
import * as path13 from "path";
|
|
12673
12688
|
import { fileURLToPath } from "url";
|
|
@@ -12693,7 +12708,7 @@ async function getLatestVersion() {
|
|
|
12693
12708
|
return data["dist-tags"]?.latest || null;
|
|
12694
12709
|
} catch {
|
|
12695
12710
|
try {
|
|
12696
|
-
const output =
|
|
12711
|
+
const output = execSync4(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
|
|
12697
12712
|
encoding: "utf-8"
|
|
12698
12713
|
}).trim();
|
|
12699
12714
|
return output || null;
|
|
@@ -12724,17 +12739,17 @@ async function checkForUpdates() {
|
|
|
12724
12739
|
}
|
|
12725
12740
|
function detectPackageManager2() {
|
|
12726
12741
|
try {
|
|
12727
|
-
const npmGlobal =
|
|
12742
|
+
const npmGlobal = execSync4("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
|
|
12728
12743
|
if (npmGlobal.includes(PACKAGE_NAME)) return "npm";
|
|
12729
12744
|
} catch {
|
|
12730
12745
|
}
|
|
12731
12746
|
try {
|
|
12732
|
-
const yarnGlobal =
|
|
12747
|
+
const yarnGlobal = execSync4("yarn global list 2>/dev/null", { encoding: "utf-8" });
|
|
12733
12748
|
if (yarnGlobal.includes(PACKAGE_NAME)) return "yarn";
|
|
12734
12749
|
} catch {
|
|
12735
12750
|
}
|
|
12736
12751
|
try {
|
|
12737
|
-
const pnpmGlobal =
|
|
12752
|
+
const pnpmGlobal = execSync4("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
|
|
12738
12753
|
if (pnpmGlobal.includes(PACKAGE_NAME)) return "pnpm";
|
|
12739
12754
|
} catch {
|
|
12740
12755
|
}
|
|
@@ -13499,32 +13514,511 @@ function formatNumber(n) {
|
|
|
13499
13514
|
}
|
|
13500
13515
|
return String(n);
|
|
13501
13516
|
}
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
|
|
13508
|
-
log.brand();
|
|
13509
|
-
log.header("Docker Status");
|
|
13510
|
-
log.newline();
|
|
13511
|
-
const info = dockerService.getDockerInfo();
|
|
13512
|
-
const settings = settingsSync.getDockerSettings();
|
|
13513
|
-
if (info.available) {
|
|
13514
|
-
log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
|
|
13515
|
-
log.keyValue("Socket", info.socket || colors.dim("default"));
|
|
13516
|
-
log.keyValue("Status", colors.green("Verf\xFCgbar"));
|
|
13517
|
-
} else {
|
|
13518
|
-
log.keyValue("Runtime", colors.dim("nicht gefunden"));
|
|
13519
|
-
log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
|
|
13520
|
-
log.newline();
|
|
13521
|
-
log.warn("Docker oder Podman ist nicht installiert");
|
|
13522
|
-
log.dim("Installation:");
|
|
13523
|
-
log.dim(" Docker: https://docs.docker.com/get-docker/");
|
|
13524
|
-
log.dim(" Podman: https://podman.io/get-started");
|
|
13517
|
+
statsCommand.command("sessions").description("Session Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13518
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13519
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13520
|
+
if (!isAuthenticated2()) {
|
|
13521
|
+
log.error("Nicht angemeldet");
|
|
13522
|
+
log.info("Anmelden mit: shiva login");
|
|
13525
13523
|
return;
|
|
13526
13524
|
}
|
|
13527
|
-
|
|
13525
|
+
const spinner = ora18("Lade Session Analytics...").start();
|
|
13526
|
+
try {
|
|
13527
|
+
const analytics = await api2.getSessionAnalytics();
|
|
13528
|
+
spinner.stop();
|
|
13529
|
+
if (options.json) {
|
|
13530
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13531
|
+
return;
|
|
13532
|
+
}
|
|
13533
|
+
log.newline();
|
|
13534
|
+
console.log(colors.orange.bold("Session Analytics"));
|
|
13535
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13536
|
+
log.newline();
|
|
13537
|
+
log.keyValue("Avg Session Length", `${analytics.averageSessionLength} min`);
|
|
13538
|
+
log.newline();
|
|
13539
|
+
console.log(colors.bold("Peak Hours:"));
|
|
13540
|
+
const sortedHours = analytics.peakHours.sort((a, b) => b.count - a.count).slice(0, 5);
|
|
13541
|
+
for (const { hour, count } of sortedHours) {
|
|
13542
|
+
console.log(` ${String(hour).padStart(2)}:00 - ${count} sessions`);
|
|
13543
|
+
}
|
|
13544
|
+
log.newline();
|
|
13545
|
+
console.log(colors.bold("Top Projects by Sessions:"));
|
|
13546
|
+
for (const proj of analytics.topProjects.slice(0, 5)) {
|
|
13547
|
+
console.log(` ${proj.projectName.padEnd(25)} ${proj.sessionCount} sessions`);
|
|
13548
|
+
}
|
|
13549
|
+
log.newline();
|
|
13550
|
+
if (analytics.dailySessions.length > 0) {
|
|
13551
|
+
console.log(colors.bold("Sessions (Last 7 Days):"));
|
|
13552
|
+
for (const { date, count } of analytics.dailySessions.slice(-7)) {
|
|
13553
|
+
const barLength = Math.min(20, count);
|
|
13554
|
+
const bar = colors.green("\u2588".repeat(barLength));
|
|
13555
|
+
console.log(` ${date.slice(5)} ${bar} ${count}`);
|
|
13556
|
+
}
|
|
13557
|
+
}
|
|
13558
|
+
} catch (error) {
|
|
13559
|
+
spinner.fail("Fehler beim Laden");
|
|
13560
|
+
const err = error;
|
|
13561
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13562
|
+
log.warn("Session Analytics ist ein Pro-Feature");
|
|
13563
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13564
|
+
} else {
|
|
13565
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13566
|
+
}
|
|
13567
|
+
}
|
|
13568
|
+
});
|
|
13569
|
+
statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13570
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13571
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13572
|
+
if (!isAuthenticated2()) {
|
|
13573
|
+
log.error("Nicht angemeldet");
|
|
13574
|
+
log.info("Anmelden mit: shiva login");
|
|
13575
|
+
return;
|
|
13576
|
+
}
|
|
13577
|
+
const spinner = ora18("Lade Token Analytics...").start();
|
|
13578
|
+
try {
|
|
13579
|
+
const analytics = await api2.getTokenAnalytics();
|
|
13580
|
+
spinner.stop();
|
|
13581
|
+
if (options.json) {
|
|
13582
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13583
|
+
return;
|
|
13584
|
+
}
|
|
13585
|
+
log.newline();
|
|
13586
|
+
console.log(colors.orange.bold("Token Usage Analytics"));
|
|
13587
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13588
|
+
log.newline();
|
|
13589
|
+
log.keyValue("Total Tokens", formatNumber(analytics.totalTokens));
|
|
13590
|
+
log.keyValue("This Month", formatNumber(analytics.tokensThisMonth));
|
|
13591
|
+
log.newline();
|
|
13592
|
+
console.log(colors.bold("Token Usage by Project:"));
|
|
13593
|
+
for (const proj of analytics.byProject.slice(0, 5)) {
|
|
13594
|
+
console.log(` ${proj.projectName.padEnd(25)} ${formatNumber(proj.tokens)}`);
|
|
13595
|
+
}
|
|
13596
|
+
log.newline();
|
|
13597
|
+
if (analytics.dailyUsage.length > 0) {
|
|
13598
|
+
console.log(colors.bold("Daily Usage (Last 7 Days):"));
|
|
13599
|
+
const maxTokens = Math.max(...analytics.dailyUsage.slice(-7).map((d) => d.tokens), 1);
|
|
13600
|
+
for (const { date, tokens } of analytics.dailyUsage.slice(-7)) {
|
|
13601
|
+
const barLength = Math.round(tokens / maxTokens * 20);
|
|
13602
|
+
const bar = colors.cyan("\u2588".repeat(barLength)) + colors.dim("\u2591".repeat(20 - barLength));
|
|
13603
|
+
console.log(` ${date.slice(5)} ${bar} ${formatNumber(tokens)}`);
|
|
13604
|
+
}
|
|
13605
|
+
}
|
|
13606
|
+
} catch (error) {
|
|
13607
|
+
spinner.fail("Fehler beim Laden");
|
|
13608
|
+
const err = error;
|
|
13609
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13610
|
+
log.warn("Token Analytics ist ein Pro-Feature");
|
|
13611
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13612
|
+
} else {
|
|
13613
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13614
|
+
}
|
|
13615
|
+
}
|
|
13616
|
+
});
|
|
13617
|
+
statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
13618
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13619
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13620
|
+
if (!isAuthenticated2()) {
|
|
13621
|
+
log.error("Nicht angemeldet");
|
|
13622
|
+
log.info("Anmelden mit: shiva login");
|
|
13623
|
+
return;
|
|
13624
|
+
}
|
|
13625
|
+
const spinner = ora18("Lade Tool Analytics...").start();
|
|
13626
|
+
try {
|
|
13627
|
+
const analytics = await api2.getToolAnalytics();
|
|
13628
|
+
spinner.stop();
|
|
13629
|
+
if (options.json) {
|
|
13630
|
+
console.log(JSON.stringify(analytics, null, 2));
|
|
13631
|
+
return;
|
|
13632
|
+
}
|
|
13633
|
+
log.newline();
|
|
13634
|
+
console.log(colors.orange.bold("Tool Usage Analytics"));
|
|
13635
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13636
|
+
log.newline();
|
|
13637
|
+
log.keyValue("Total Tool Calls", formatNumber(analytics.totalToolCalls));
|
|
13638
|
+
log.newline();
|
|
13639
|
+
console.log(colors.bold("Most Used Tools:"));
|
|
13640
|
+
for (const tool of analytics.mostUsedTools.slice(0, 10)) {
|
|
13641
|
+
const bar = colors.yellow("\u2588".repeat(Math.min(20, Math.round(tool.count / 10))));
|
|
13642
|
+
console.log(` ${tool.tool.padEnd(20)} ${bar} ${formatNumber(tool.count)}`);
|
|
13643
|
+
}
|
|
13644
|
+
log.newline();
|
|
13645
|
+
console.log(colors.bold("Tool Performance (Avg Duration):"));
|
|
13646
|
+
const sorted = analytics.byTool.sort((a, b) => b.avgDuration - a.avgDuration).slice(0, 5);
|
|
13647
|
+
for (const tool of sorted) {
|
|
13648
|
+
console.log(` ${tool.tool.padEnd(20)} ${tool.avgDuration.toFixed(0)}ms`);
|
|
13649
|
+
}
|
|
13650
|
+
} catch (error) {
|
|
13651
|
+
spinner.fail("Fehler beim Laden");
|
|
13652
|
+
const err = error;
|
|
13653
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13654
|
+
log.warn("Tool Analytics ist ein Pro-Feature");
|
|
13655
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13656
|
+
} else {
|
|
13657
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13658
|
+
}
|
|
13659
|
+
}
|
|
13660
|
+
});
|
|
13661
|
+
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) => {
|
|
13662
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13663
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13664
|
+
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
13665
|
+
if (!isAuthenticated2()) {
|
|
13666
|
+
log.error("Nicht angemeldet");
|
|
13667
|
+
log.info("Anmelden mit: shiva login");
|
|
13668
|
+
return;
|
|
13669
|
+
}
|
|
13670
|
+
const spinner = ora18("Exportiere Analytics...").start();
|
|
13671
|
+
try {
|
|
13672
|
+
const result = await api2.exportAnalytics({
|
|
13673
|
+
startDate: options.start,
|
|
13674
|
+
endDate: options.end,
|
|
13675
|
+
format: options.format
|
|
13676
|
+
});
|
|
13677
|
+
spinner.stop();
|
|
13678
|
+
if (options.output) {
|
|
13679
|
+
const content = options.format === "json" ? JSON.stringify(result.data, null, 2) : String(result.data);
|
|
13680
|
+
writeFileSync11(options.output, content);
|
|
13681
|
+
log.success(`Analytics exportiert: ${options.output}`);
|
|
13682
|
+
} else {
|
|
13683
|
+
console.log(JSON.stringify(result, null, 2));
|
|
13684
|
+
}
|
|
13685
|
+
} catch (error) {
|
|
13686
|
+
spinner.fail("Fehler beim Exportieren");
|
|
13687
|
+
const err = error;
|
|
13688
|
+
if (err.message?.includes("403") || err.message?.includes("forbidden")) {
|
|
13689
|
+
log.warn("Analytics Export ist ein Pro-Feature");
|
|
13690
|
+
log.info("Upgrade auf Pro: https://shiva.li/pricing");
|
|
13691
|
+
} else {
|
|
13692
|
+
log.error(err.message || "Unbekannter Fehler");
|
|
13693
|
+
}
|
|
13694
|
+
}
|
|
13695
|
+
});
|
|
13696
|
+
statsCommand.command("track").description("Analytics Event tracken").argument("<type>", "Event-Typ").argument("[data]", "Event-Daten als JSON").action(async (type2, data) => {
|
|
13697
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
13698
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13699
|
+
if (!isAuthenticated2()) {
|
|
13700
|
+
log.error("Nicht angemeldet");
|
|
13701
|
+
log.info("Anmelden mit: shiva login");
|
|
13702
|
+
return;
|
|
13703
|
+
}
|
|
13704
|
+
try {
|
|
13705
|
+
const eventData = data ? JSON.parse(data) : {};
|
|
13706
|
+
const result = await api2.trackAnalyticsEvent({
|
|
13707
|
+
type: type2,
|
|
13708
|
+
data: eventData
|
|
13709
|
+
});
|
|
13710
|
+
if (result.success) {
|
|
13711
|
+
log.success("Event getrackt");
|
|
13712
|
+
} else {
|
|
13713
|
+
log.error("Event konnte nicht getrackt werden");
|
|
13714
|
+
}
|
|
13715
|
+
} catch (error) {
|
|
13716
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13717
|
+
}
|
|
13718
|
+
});
|
|
13719
|
+
|
|
13720
|
+
// src/commands/system/user.ts
|
|
13721
|
+
import { Command as Command32 } from "commander";
|
|
13722
|
+
import ora19 from "ora";
|
|
13723
|
+
var userCommand = new Command32("user").description("User Account Verwaltung");
|
|
13724
|
+
userCommand.command("profile").description("User-Profil anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13725
|
+
if (!isAuthenticated()) {
|
|
13726
|
+
log.error("Nicht angemeldet");
|
|
13727
|
+
log.info("Anmelden mit: shiva login");
|
|
13728
|
+
return;
|
|
13729
|
+
}
|
|
13730
|
+
const spinner = ora19("Lade Profil...").start();
|
|
13731
|
+
try {
|
|
13732
|
+
const profile = await api.getUserProfile();
|
|
13733
|
+
spinner.stop();
|
|
13734
|
+
if (options.json) {
|
|
13735
|
+
console.log(JSON.stringify(profile, null, 2));
|
|
13736
|
+
return;
|
|
13737
|
+
}
|
|
13738
|
+
log.newline();
|
|
13739
|
+
console.log(colors.orange.bold("User Profile"));
|
|
13740
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13741
|
+
log.newline();
|
|
13742
|
+
log.keyValue("ID", String(profile.id));
|
|
13743
|
+
log.keyValue("Email", profile.email);
|
|
13744
|
+
if (profile.name) {
|
|
13745
|
+
log.keyValue("Name", profile.name);
|
|
13746
|
+
}
|
|
13747
|
+
const tierColor = profile.tier === "pro" ? colors.cyan : profile.tier === "team" ? colors.green : colors.dim;
|
|
13748
|
+
log.keyValue("Tier", tierColor(profile.tier.toUpperCase()));
|
|
13749
|
+
log.keyValue("Seit", new Date(profile.createdAt).toLocaleDateString("de-DE"));
|
|
13750
|
+
} catch (error) {
|
|
13751
|
+
spinner.fail("Fehler beim Laden");
|
|
13752
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13753
|
+
}
|
|
13754
|
+
});
|
|
13755
|
+
userCommand.command("update").description("User-Profil aktualisieren").option("--name <name>", "Name setzen").action(async (options) => {
|
|
13756
|
+
if (!isAuthenticated()) {
|
|
13757
|
+
log.error("Nicht angemeldet");
|
|
13758
|
+
log.info("Anmelden mit: shiva login");
|
|
13759
|
+
return;
|
|
13760
|
+
}
|
|
13761
|
+
if (!options.name) {
|
|
13762
|
+
log.error("Keine \xC4nderungen angegeben");
|
|
13763
|
+
log.info("Verf\xFCgbare Optionen:");
|
|
13764
|
+
log.plain(" --name <name> Name setzen");
|
|
13765
|
+
return;
|
|
13766
|
+
}
|
|
13767
|
+
const spinner = ora19("Aktualisiere Profil...").start();
|
|
13768
|
+
try {
|
|
13769
|
+
const result = await api.updateUserProfile({
|
|
13770
|
+
name: options.name
|
|
13771
|
+
});
|
|
13772
|
+
if (result.success) {
|
|
13773
|
+
spinner.succeed("Profil aktualisiert");
|
|
13774
|
+
} else {
|
|
13775
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
13776
|
+
}
|
|
13777
|
+
} catch (error) {
|
|
13778
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
13779
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13780
|
+
}
|
|
13781
|
+
});
|
|
13782
|
+
userCommand.command("usage").description("Resource-Nutzung und Limits anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13783
|
+
if (!isAuthenticated()) {
|
|
13784
|
+
log.error("Nicht angemeldet");
|
|
13785
|
+
log.info("Anmelden mit: shiva login");
|
|
13786
|
+
return;
|
|
13787
|
+
}
|
|
13788
|
+
const spinner = ora19("Lade Usage...").start();
|
|
13789
|
+
try {
|
|
13790
|
+
const usage = await api.getUserUsage();
|
|
13791
|
+
spinner.stop();
|
|
13792
|
+
if (options.json) {
|
|
13793
|
+
console.log(JSON.stringify(usage, null, 2));
|
|
13794
|
+
return;
|
|
13795
|
+
}
|
|
13796
|
+
log.newline();
|
|
13797
|
+
console.log(colors.orange.bold("Resource Usage"));
|
|
13798
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13799
|
+
log.newline();
|
|
13800
|
+
const progressBar = (current, limit, label, unit) => {
|
|
13801
|
+
const percentage = Math.min(100, Math.round(current / limit * 100));
|
|
13802
|
+
const barWidth = 20;
|
|
13803
|
+
const filled = Math.round(current / limit * barWidth);
|
|
13804
|
+
const empty = barWidth - filled;
|
|
13805
|
+
const barColor = percentage >= 90 ? colors.red : percentage >= 70 ? colors.yellow : colors.green;
|
|
13806
|
+
const bar = barColor("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
|
|
13807
|
+
const unitStr = unit ? ` ${unit}` : "";
|
|
13808
|
+
console.log(` ${label.padEnd(12)} [${bar}] ${current}/${limit}${unitStr} (${percentage}%)`);
|
|
13809
|
+
};
|
|
13810
|
+
progressBar(usage.projects.current, usage.projects.limit, "Projects");
|
|
13811
|
+
progressBar(usage.sessions.current, usage.sessions.limit, "Sessions");
|
|
13812
|
+
progressBar(usage.storage.current, usage.storage.limit, "Storage", usage.storage.unit);
|
|
13813
|
+
progressBar(usage.apiCalls.current, usage.apiCalls.limit, "API Calls", `/${usage.apiCalls.period}`);
|
|
13814
|
+
log.newline();
|
|
13815
|
+
const nearLimit = (current, limit) => current / limit >= 0.9;
|
|
13816
|
+
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)) {
|
|
13817
|
+
log.warn("Du erreichst bald deine Limits");
|
|
13818
|
+
log.info("Upgrade auf Pro: shiva user subscription");
|
|
13819
|
+
}
|
|
13820
|
+
} catch (error) {
|
|
13821
|
+
spinner.fail("Fehler beim Laden");
|
|
13822
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13823
|
+
}
|
|
13824
|
+
});
|
|
13825
|
+
userCommand.command("subscription").description("Subscription-Status anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
13826
|
+
if (!isAuthenticated()) {
|
|
13827
|
+
log.error("Nicht angemeldet");
|
|
13828
|
+
log.info("Anmelden mit: shiva login");
|
|
13829
|
+
return;
|
|
13830
|
+
}
|
|
13831
|
+
const spinner = ora19("Lade Subscription...").start();
|
|
13832
|
+
try {
|
|
13833
|
+
const sub = await api.getSubscription();
|
|
13834
|
+
spinner.stop();
|
|
13835
|
+
if (options.json) {
|
|
13836
|
+
console.log(JSON.stringify(sub, null, 2));
|
|
13837
|
+
return;
|
|
13838
|
+
}
|
|
13839
|
+
log.newline();
|
|
13840
|
+
console.log(colors.orange.bold("Subscription"));
|
|
13841
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
13842
|
+
log.newline();
|
|
13843
|
+
const tierColor = sub.tier === "pro" ? colors.cyan : sub.tier === "team" ? colors.green : colors.dim;
|
|
13844
|
+
log.keyValue("Tier", tierColor(sub.tier.toUpperCase()));
|
|
13845
|
+
const statusColor = sub.status === "active" ? colors.green : sub.status === "trialing" ? colors.yellow : colors.red;
|
|
13846
|
+
log.keyValue("Status", statusColor(sub.status));
|
|
13847
|
+
if (sub.billingCycle) {
|
|
13848
|
+
log.keyValue("Billing", sub.billingCycle);
|
|
13849
|
+
}
|
|
13850
|
+
if (sub.currentPeriodEnd) {
|
|
13851
|
+
const endDate = new Date(sub.currentPeriodEnd);
|
|
13852
|
+
const label = sub.cancelAtPeriodEnd ? "Endet am" : "Renewal";
|
|
13853
|
+
log.keyValue(label, endDate.toLocaleDateString("de-DE"));
|
|
13854
|
+
}
|
|
13855
|
+
if (sub.cancelAtPeriodEnd) {
|
|
13856
|
+
log.newline();
|
|
13857
|
+
log.warn("Subscription endet am Ende der aktuellen Periode");
|
|
13858
|
+
}
|
|
13859
|
+
log.newline();
|
|
13860
|
+
console.log(colors.bold("Features:"));
|
|
13861
|
+
for (const feature of sub.features) {
|
|
13862
|
+
console.log(` ${colors.green("\u2713")} ${feature}`);
|
|
13863
|
+
}
|
|
13864
|
+
if (sub.tier === "free") {
|
|
13865
|
+
log.newline();
|
|
13866
|
+
log.info("Upgrade auf Pro f\xFCr mehr Features:");
|
|
13867
|
+
log.plain(" https://shiva.li/pricing");
|
|
13868
|
+
}
|
|
13869
|
+
} catch (error) {
|
|
13870
|
+
spinner.fail("Fehler beim Laden");
|
|
13871
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13872
|
+
}
|
|
13873
|
+
});
|
|
13874
|
+
userCommand.command("token").description("Neuen CLI-Token generieren").option("--copy", "Token in Zwischenablage kopieren").action(async (options) => {
|
|
13875
|
+
if (!isAuthenticated()) {
|
|
13876
|
+
log.error("Nicht angemeldet");
|
|
13877
|
+
log.info("Anmelden mit: shiva login");
|
|
13878
|
+
return;
|
|
13879
|
+
}
|
|
13880
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
13881
|
+
const { confirm } = await inquirer14.prompt([{
|
|
13882
|
+
type: "confirm",
|
|
13883
|
+
name: "confirm",
|
|
13884
|
+
message: "Neuen Token generieren? Der alte Token wird ung\xFCltig.",
|
|
13885
|
+
default: false
|
|
13886
|
+
}]);
|
|
13887
|
+
if (!confirm) {
|
|
13888
|
+
log.dim("Abgebrochen");
|
|
13889
|
+
return;
|
|
13890
|
+
}
|
|
13891
|
+
const spinner = ora19("Generiere Token...").start();
|
|
13892
|
+
try {
|
|
13893
|
+
const result = await api.generateCliToken();
|
|
13894
|
+
spinner.stop();
|
|
13895
|
+
log.newline();
|
|
13896
|
+
log.success("Token generiert");
|
|
13897
|
+
log.newline();
|
|
13898
|
+
log.warn("Dieser Token wird nur einmal angezeigt!");
|
|
13899
|
+
log.newline();
|
|
13900
|
+
console.log(colors.dim("Token:"));
|
|
13901
|
+
console.log(colors.cyan(result.token));
|
|
13902
|
+
log.newline();
|
|
13903
|
+
log.keyValue("G\xFCltig bis", new Date(result.expiresAt).toLocaleDateString("de-DE"));
|
|
13904
|
+
if (options.copy) {
|
|
13905
|
+
try {
|
|
13906
|
+
const { copyToClipboard: copyToClipboard2 } = await import("./clipboard-ET53HNUB.js");
|
|
13907
|
+
await copyToClipboard2(result.token);
|
|
13908
|
+
log.success("Token in Zwischenablage kopiert");
|
|
13909
|
+
} catch {
|
|
13910
|
+
log.dim("Konnte nicht in Zwischenablage kopieren");
|
|
13911
|
+
}
|
|
13912
|
+
}
|
|
13913
|
+
log.newline();
|
|
13914
|
+
log.info("Verwendung:");
|
|
13915
|
+
log.plain(` export SHIVA_TOKEN="${result.token}"`);
|
|
13916
|
+
log.plain(" # oder in ~/.bashrc / ~/.zshrc");
|
|
13917
|
+
} catch (error) {
|
|
13918
|
+
spinner.fail("Fehler beim Generieren");
|
|
13919
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13920
|
+
}
|
|
13921
|
+
});
|
|
13922
|
+
userCommand.command("delete").description("Account unwiderruflich l\xF6schen").action(async () => {
|
|
13923
|
+
if (!isAuthenticated()) {
|
|
13924
|
+
log.error("Nicht angemeldet");
|
|
13925
|
+
return;
|
|
13926
|
+
}
|
|
13927
|
+
log.newline();
|
|
13928
|
+
log.warn("ACHTUNG: Account l\xF6schen ist IRREVERSIBEL!");
|
|
13929
|
+
log.newline();
|
|
13930
|
+
log.plain("Folgende Daten werden unwiderruflich gel\xF6scht:");
|
|
13931
|
+
log.plain(" \u2022 Alle Projekte und Memories");
|
|
13932
|
+
log.plain(" \u2022 Alle Sessions und Sandboxes");
|
|
13933
|
+
log.plain(" \u2022 Alle Secrets und Einstellungen");
|
|
13934
|
+
log.plain(" \u2022 Subscription und Zahlungsdaten");
|
|
13935
|
+
log.newline();
|
|
13936
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
13937
|
+
const { confirm1 } = await inquirer14.prompt([{
|
|
13938
|
+
type: "confirm",
|
|
13939
|
+
name: "confirm1",
|
|
13940
|
+
message: "Bist du sicher, dass du deinen Account l\xF6schen m\xF6chtest?",
|
|
13941
|
+
default: false
|
|
13942
|
+
}]);
|
|
13943
|
+
if (!confirm1) {
|
|
13944
|
+
log.dim("Abgebrochen");
|
|
13945
|
+
return;
|
|
13946
|
+
}
|
|
13947
|
+
const { confirmText } = await inquirer14.prompt([{
|
|
13948
|
+
type: "input",
|
|
13949
|
+
name: "confirmText",
|
|
13950
|
+
message: 'Tippe "DELETE" um zu best\xE4tigen:'
|
|
13951
|
+
}]);
|
|
13952
|
+
if (confirmText !== "DELETE") {
|
|
13953
|
+
log.dim("Abgebrochen (falscher Best\xE4tigungstext)");
|
|
13954
|
+
return;
|
|
13955
|
+
}
|
|
13956
|
+
const spinner = ora19("L\xF6sche Account...").start();
|
|
13957
|
+
try {
|
|
13958
|
+
const result = await api.deleteAccount("DELETE");
|
|
13959
|
+
if (result.success) {
|
|
13960
|
+
spinner.succeed("Account gel\xF6scht");
|
|
13961
|
+
log.newline();
|
|
13962
|
+
clearAuth();
|
|
13963
|
+
log.info("Lokale Anmeldedaten wurden entfernt");
|
|
13964
|
+
log.plain("Auf Wiedersehen!");
|
|
13965
|
+
} else {
|
|
13966
|
+
spinner.fail(result.message || "Fehler beim L\xF6schen");
|
|
13967
|
+
}
|
|
13968
|
+
} catch (error) {
|
|
13969
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
13970
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
13971
|
+
}
|
|
13972
|
+
});
|
|
13973
|
+
userCommand.command("whoami").description("Aktuelle Anmeldung anzeigen").action(async () => {
|
|
13974
|
+
const config = getConfig();
|
|
13975
|
+
if (!isAuthenticated()) {
|
|
13976
|
+
log.info("Nicht angemeldet");
|
|
13977
|
+
log.plain("Anmelden mit: shiva login");
|
|
13978
|
+
return;
|
|
13979
|
+
}
|
|
13980
|
+
log.newline();
|
|
13981
|
+
log.keyValue("Email", config.email || "Unbekannt");
|
|
13982
|
+
log.keyValue("Tier", config.tier || "Unbekannt");
|
|
13983
|
+
log.keyValue("User ID", String(config.userId) || "Unbekannt");
|
|
13984
|
+
if (config.tokenExpiry) {
|
|
13985
|
+
const expiry = new Date(config.tokenExpiry);
|
|
13986
|
+
const now = /* @__PURE__ */ new Date();
|
|
13987
|
+
const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
|
|
13988
|
+
if (daysLeft > 0) {
|
|
13989
|
+
log.keyValue("Token g\xFCltig", `${daysLeft} Tage`);
|
|
13990
|
+
} else {
|
|
13991
|
+
log.warn("Token abgelaufen");
|
|
13992
|
+
log.info("Neu anmelden mit: shiva login");
|
|
13993
|
+
}
|
|
13994
|
+
}
|
|
13995
|
+
});
|
|
13996
|
+
|
|
13997
|
+
// src/commands/advanced/docker.ts
|
|
13998
|
+
import { Command as Command33 } from "commander";
|
|
13999
|
+
import ora20 from "ora";
|
|
14000
|
+
var dockerCommand = new Command33("docker").description("Docker-Integration verwalten");
|
|
14001
|
+
dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
|
|
14002
|
+
log.brand();
|
|
14003
|
+
log.header("Docker Status");
|
|
14004
|
+
log.newline();
|
|
14005
|
+
const info = dockerService.getDockerInfo();
|
|
14006
|
+
const settings = settingsSync.getDockerSettings();
|
|
14007
|
+
if (info.available) {
|
|
14008
|
+
log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
|
|
14009
|
+
log.keyValue("Socket", info.socket || colors.dim("default"));
|
|
14010
|
+
log.keyValue("Status", colors.green("Verf\xFCgbar"));
|
|
14011
|
+
} else {
|
|
14012
|
+
log.keyValue("Runtime", colors.dim("nicht gefunden"));
|
|
14013
|
+
log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
|
|
14014
|
+
log.newline();
|
|
14015
|
+
log.warn("Docker oder Podman ist nicht installiert");
|
|
14016
|
+
log.dim("Installation:");
|
|
14017
|
+
log.dim(" Docker: https://docs.docker.com/get-docker/");
|
|
14018
|
+
log.dim(" Podman: https://podman.io/get-started");
|
|
14019
|
+
return;
|
|
14020
|
+
}
|
|
14021
|
+
log.newline();
|
|
13528
14022
|
log.keyValue("Docker-Modus", settings.enabled ? colors.green("aktiviert") : colors.yellow("deaktiviert"));
|
|
13529
14023
|
log.keyValue("Standard-Image", settings.defaultImage);
|
|
13530
14024
|
log.keyValue("Auto-Start", settings.autoStart ? "ja" : "nein");
|
|
@@ -13568,7 +14062,7 @@ dockerCommand.command("enable").description("Docker-Modus aktivieren").action(as
|
|
|
13568
14062
|
return;
|
|
13569
14063
|
}
|
|
13570
14064
|
const image = dockerService.getDefaultImage();
|
|
13571
|
-
const spinner =
|
|
14065
|
+
const spinner = ora20(`Pr\xFCfe Image: ${image}...`).start();
|
|
13572
14066
|
if (!dockerService.imageExists(image)) {
|
|
13573
14067
|
spinner.text = `Lade Image herunter: ${image}...`;
|
|
13574
14068
|
try {
|
|
@@ -13627,7 +14121,7 @@ dockerCommand.command("logs").description("Container-Logs anzeigen").argument("<
|
|
|
13627
14121
|
console.log(logs);
|
|
13628
14122
|
});
|
|
13629
14123
|
dockerCommand.command("stop").description("Container stoppen").argument("<name>", "Container-Name oder ID").action(async (name) => {
|
|
13630
|
-
const spinner =
|
|
14124
|
+
const spinner = ora20(`Stoppe Container ${name}...`).start();
|
|
13631
14125
|
try {
|
|
13632
14126
|
await dockerService.stopContainer(name);
|
|
13633
14127
|
spinner.succeed(`Container gestoppt: ${name}`);
|
|
@@ -13637,7 +14131,7 @@ dockerCommand.command("stop").description("Container stoppen").argument("<name>"
|
|
|
13637
14131
|
}
|
|
13638
14132
|
});
|
|
13639
14133
|
dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").action(async () => {
|
|
13640
|
-
const spinner =
|
|
14134
|
+
const spinner = ora20("R\xE4ume Container auf...").start();
|
|
13641
14135
|
try {
|
|
13642
14136
|
const count = await dockerService.cleanContainers();
|
|
13643
14137
|
spinner.succeed(`${count} Container entfernt`);
|
|
@@ -13648,7 +14142,7 @@ dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").a
|
|
|
13648
14142
|
});
|
|
13649
14143
|
dockerCommand.command("pull").description("Docker-Image herunterladen").argument("[image]", "Image-Name (default: shiva/claude-runner:latest)").action(async (image) => {
|
|
13650
14144
|
const targetImage = image || dockerService.getDefaultImage();
|
|
13651
|
-
const spinner =
|
|
14145
|
+
const spinner = ora20(`Lade Image herunter: ${targetImage}...`).start();
|
|
13652
14146
|
try {
|
|
13653
14147
|
await dockerService.pullImage(targetImage);
|
|
13654
14148
|
spinner.succeed(`Image heruntergeladen: ${targetImage}`);
|
|
@@ -13733,11 +14227,11 @@ dockerCommand.action(() => {
|
|
|
13733
14227
|
});
|
|
13734
14228
|
|
|
13735
14229
|
// src/commands/advanced/workflow.ts
|
|
13736
|
-
import { Command as
|
|
14230
|
+
import { Command as Command34 } from "commander";
|
|
13737
14231
|
import * as fs13 from "fs";
|
|
13738
14232
|
import * as path14 from "path";
|
|
13739
14233
|
import * as os6 from "os";
|
|
13740
|
-
import
|
|
14234
|
+
import ora21 from "ora";
|
|
13741
14235
|
import inquirer12 from "inquirer";
|
|
13742
14236
|
var builtInWorkflows = {
|
|
13743
14237
|
morning: {
|
|
@@ -13757,7 +14251,7 @@ var builtInWorkflows = {
|
|
|
13757
14251
|
]
|
|
13758
14252
|
}
|
|
13759
14253
|
};
|
|
13760
|
-
var workflowCommand = new
|
|
14254
|
+
var workflowCommand = new Command34("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
|
|
13761
14255
|
await listWorkflows();
|
|
13762
14256
|
});
|
|
13763
14257
|
workflowCommand.command("list").alias("ls").description("Verf\xFCgbare Workflows anzeigen").action(async () => {
|
|
@@ -13926,7 +14420,7 @@ function deleteCustomWorkflow(name) {
|
|
|
13926
14420
|
fs13.writeFileSync(filepath, JSON.stringify(workflows, null, 2));
|
|
13927
14421
|
}
|
|
13928
14422
|
async function executeStep(step) {
|
|
13929
|
-
const spinner =
|
|
14423
|
+
const spinner = ora21("Ausf\xFChren...").start();
|
|
13930
14424
|
try {
|
|
13931
14425
|
switch (step.type) {
|
|
13932
14426
|
case "issues": {
|
|
@@ -14012,7 +14506,7 @@ async function executeStep(step) {
|
|
|
14012
14506
|
}
|
|
14013
14507
|
|
|
14014
14508
|
// src/commands/advanced/hook.ts
|
|
14015
|
-
import { Command as
|
|
14509
|
+
import { Command as Command35 } from "commander";
|
|
14016
14510
|
import { existsSync as existsSync21, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6 } from "fs";
|
|
14017
14511
|
import { homedir as homedir7 } from "os";
|
|
14018
14512
|
import { join as join12 } from "path";
|
|
@@ -14047,7 +14541,7 @@ function removeShivaHooks(eventHooks) {
|
|
|
14047
14541
|
(entry) => !entry.hooks?.some((h) => h.command?.includes("shiva"))
|
|
14048
14542
|
);
|
|
14049
14543
|
}
|
|
14050
|
-
var hookCommand = new
|
|
14544
|
+
var hookCommand = new Command35("hook").description("Claude Code Hook Integration verwalten");
|
|
14051
14545
|
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
14546
|
log.brand();
|
|
14053
14547
|
const claudePath = join12(homedir7(), ".claude");
|
|
@@ -14382,7 +14876,7 @@ hookCommand.command("scan-command").description("Scanne Bash-Befehle auf Package
|
|
|
14382
14876
|
}
|
|
14383
14877
|
});
|
|
14384
14878
|
hookCommand.command("push").description("Hooks in Cloud sichern").action(async () => {
|
|
14385
|
-
const { api: api2 } = await import("./client-
|
|
14879
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14386
14880
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14387
14881
|
if (!isAuthenticated2()) {
|
|
14388
14882
|
log.error("Nicht angemeldet");
|
|
@@ -14395,78 +14889,252 @@ hookCommand.command("push").description("Hooks in Cloud sichern").action(async (
|
|
|
14395
14889
|
return;
|
|
14396
14890
|
}
|
|
14397
14891
|
try {
|
|
14398
|
-
await api2.updateHooks(settings.hooks);
|
|
14399
|
-
log.success("Hooks in Cloud gesichert");
|
|
14892
|
+
await api2.updateHooks(settings.hooks);
|
|
14893
|
+
log.success("Hooks in Cloud gesichert");
|
|
14894
|
+
} catch (error) {
|
|
14895
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
|
|
14896
|
+
}
|
|
14897
|
+
});
|
|
14898
|
+
hookCommand.command("pull").description("Hooks aus Cloud laden").option("-f, --force", "Lokale Hooks \xFCberschreiben").action(async (options) => {
|
|
14899
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14900
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14901
|
+
if (!isAuthenticated2()) {
|
|
14902
|
+
log.error("Nicht angemeldet");
|
|
14903
|
+
log.info("Anmelden mit: shiva login");
|
|
14904
|
+
return;
|
|
14905
|
+
}
|
|
14906
|
+
const settings = getClaudeSettings();
|
|
14907
|
+
if (settings.hooks && !options.force) {
|
|
14908
|
+
log.warn("Lokale Hooks existieren bereits");
|
|
14909
|
+
log.info("Mit --force \xFCberschreiben");
|
|
14910
|
+
return;
|
|
14911
|
+
}
|
|
14912
|
+
try {
|
|
14913
|
+
const result = await api2.getHooks();
|
|
14914
|
+
if (!result.hooks || Object.keys(result.hooks).length === 0) {
|
|
14915
|
+
log.info("Keine Hooks in Cloud gefunden");
|
|
14916
|
+
return;
|
|
14917
|
+
}
|
|
14918
|
+
settings.hooks = result.hooks;
|
|
14919
|
+
saveClaudeSettings(settings);
|
|
14920
|
+
log.success("Hooks aus Cloud geladen");
|
|
14921
|
+
log.newline();
|
|
14922
|
+
log.info("Aktive Hooks:");
|
|
14923
|
+
for (const [event, hooks] of Object.entries(result.hooks)) {
|
|
14924
|
+
log.tree.item(`${event}: ${Array.isArray(hooks) ? hooks.length : 1} Hook(s)`);
|
|
14925
|
+
}
|
|
14926
|
+
} catch (error) {
|
|
14927
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Laden");
|
|
14928
|
+
}
|
|
14929
|
+
});
|
|
14930
|
+
hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
|
|
14931
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14932
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14933
|
+
if (!isAuthenticated2()) {
|
|
14934
|
+
log.error("Nicht angemeldet");
|
|
14935
|
+
log.info("Anmelden mit: shiva login");
|
|
14936
|
+
return;
|
|
14937
|
+
}
|
|
14938
|
+
const settings = getClaudeSettings();
|
|
14939
|
+
try {
|
|
14940
|
+
if (settings.hooks) {
|
|
14941
|
+
await api2.updateHooks(settings.hooks);
|
|
14942
|
+
log.success("Lokale Hooks \u2192 Cloud");
|
|
14943
|
+
}
|
|
14944
|
+
const result = await api2.getHooks();
|
|
14945
|
+
if (result.hooks && Object.keys(result.hooks).length > 0) {
|
|
14946
|
+
const merged = { ...result.hooks, ...settings.hooks };
|
|
14947
|
+
settings.hooks = merged;
|
|
14948
|
+
saveClaudeSettings(settings);
|
|
14949
|
+
log.success("Cloud Hooks \u2192 Lokal (merged)");
|
|
14950
|
+
}
|
|
14951
|
+
log.newline();
|
|
14952
|
+
log.success("Hooks synchronisiert");
|
|
14953
|
+
} catch (error) {
|
|
14954
|
+
log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
|
|
14955
|
+
}
|
|
14956
|
+
});
|
|
14957
|
+
hookCommand.command("cloud-list").description("Cloud-Hooks auflisten").option("--event <type>", "Nach Event-Typ filtern").option("--json", "JSON Output").action(async (options) => {
|
|
14958
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14959
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14960
|
+
const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
|
|
14961
|
+
if (!isAuthenticated2()) {
|
|
14962
|
+
log.error("Nicht angemeldet");
|
|
14963
|
+
log.info("Anmelden mit: shiva login");
|
|
14964
|
+
return;
|
|
14965
|
+
}
|
|
14966
|
+
const ora24 = (await import("ora")).default;
|
|
14967
|
+
const spinner = ora24("Lade Cloud-Hooks...").start();
|
|
14968
|
+
try {
|
|
14969
|
+
let hooks;
|
|
14970
|
+
if (options.event) {
|
|
14971
|
+
hooks = await api2.getHooksForEvent(options.event);
|
|
14972
|
+
} else {
|
|
14973
|
+
const result = await api2.getHooks();
|
|
14974
|
+
hooks = result.hooks || [];
|
|
14975
|
+
}
|
|
14976
|
+
spinner.stop();
|
|
14977
|
+
if (options.json) {
|
|
14978
|
+
console.log(JSON.stringify(hooks, null, 2));
|
|
14979
|
+
return;
|
|
14980
|
+
}
|
|
14981
|
+
log.newline();
|
|
14982
|
+
console.log(colors3.orange.bold("Cloud Hooks"));
|
|
14983
|
+
console.log(colors3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
14984
|
+
log.newline();
|
|
14985
|
+
if (!hooks || Array.isArray(hooks) && hooks.length === 0) {
|
|
14986
|
+
log.dim("Keine Cloud-Hooks konfiguriert");
|
|
14987
|
+
return;
|
|
14988
|
+
}
|
|
14989
|
+
const hooksArray = Array.isArray(hooks) ? hooks : Object.values(hooks).flat();
|
|
14990
|
+
for (const hook of hooksArray) {
|
|
14991
|
+
const enabledIcon = hook.enabled !== false ? colors3.green("\u25CF") : colors3.dim("\u25CB");
|
|
14992
|
+
console.log(` ${enabledIcon} ${colors3.bold(hook.id || hook.event)}`);
|
|
14993
|
+
console.log(` ${colors3.dim("Event:")} ${hook.event}`);
|
|
14994
|
+
if (hook.matcher) {
|
|
14995
|
+
console.log(` ${colors3.dim("Matcher:")} ${hook.matcher}`);
|
|
14996
|
+
}
|
|
14997
|
+
console.log(` ${colors3.dim("Type:")} ${hook.type}`);
|
|
14998
|
+
console.log(` ${colors3.dim("Command:")} ${hook.command}`);
|
|
14999
|
+
log.newline();
|
|
15000
|
+
}
|
|
15001
|
+
} catch (error) {
|
|
15002
|
+
spinner.fail("Fehler beim Laden");
|
|
15003
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15004
|
+
}
|
|
15005
|
+
});
|
|
15006
|
+
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) => {
|
|
15007
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
15008
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
15009
|
+
if (!isAuthenticated2()) {
|
|
15010
|
+
log.error("Nicht angemeldet");
|
|
15011
|
+
log.info("Anmelden mit: shiva login");
|
|
15012
|
+
return;
|
|
15013
|
+
}
|
|
15014
|
+
const ora24 = (await import("ora")).default;
|
|
15015
|
+
const spinner = ora24("Erstelle Cloud-Hook...").start();
|
|
15016
|
+
try {
|
|
15017
|
+
const result = await api2.createHook({
|
|
15018
|
+
event: options.event,
|
|
15019
|
+
command: options.command,
|
|
15020
|
+
matcher: options.matcher,
|
|
15021
|
+
type: options.type,
|
|
15022
|
+
timeout: options.timeout ? parseInt(options.timeout) : void 0
|
|
15023
|
+
});
|
|
15024
|
+
if (result.success) {
|
|
15025
|
+
spinner.succeed(`Hook erstellt: ${result.hookId}`);
|
|
15026
|
+
} else {
|
|
15027
|
+
spinner.fail(result.message || "Fehler beim Erstellen");
|
|
15028
|
+
}
|
|
15029
|
+
} catch (error) {
|
|
15030
|
+
spinner.fail("Fehler beim Erstellen");
|
|
15031
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15032
|
+
}
|
|
15033
|
+
});
|
|
15034
|
+
hookCommand.command("cloud-test").description("Cloud-Hook testen").argument("<hook-id>", "Hook ID").action(async (hookId) => {
|
|
15035
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
15036
|
+
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
15037
|
+
const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
|
|
15038
|
+
if (!isAuthenticated2()) {
|
|
15039
|
+
log.error("Nicht angemeldet");
|
|
15040
|
+
log.info("Anmelden mit: shiva login");
|
|
15041
|
+
return;
|
|
15042
|
+
}
|
|
15043
|
+
const ora24 = (await import("ora")).default;
|
|
15044
|
+
const spinner = ora24("Teste Hook...").start();
|
|
15045
|
+
try {
|
|
15046
|
+
const result = await api2.testHook(hookId);
|
|
15047
|
+
spinner.stop();
|
|
15048
|
+
log.newline();
|
|
15049
|
+
if (result.success) {
|
|
15050
|
+
log.success(`Hook erfolgreich (${result.duration}ms)`);
|
|
15051
|
+
if (result.output) {
|
|
15052
|
+
log.newline();
|
|
15053
|
+
console.log(colors3.dim("Output:"));
|
|
15054
|
+
console.log(result.output);
|
|
15055
|
+
}
|
|
15056
|
+
} else {
|
|
15057
|
+
log.error(`Hook fehlgeschlagen (${result.duration}ms)`);
|
|
15058
|
+
if (result.error) {
|
|
15059
|
+
log.newline();
|
|
15060
|
+
console.log(colors3.dim("Error:"));
|
|
15061
|
+
console.log(colors3.red(result.error));
|
|
15062
|
+
}
|
|
15063
|
+
}
|
|
14400
15064
|
} catch (error) {
|
|
14401
|
-
|
|
15065
|
+
spinner.fail("Fehler beim Testen");
|
|
15066
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14402
15067
|
}
|
|
14403
15068
|
});
|
|
14404
|
-
hookCommand.command("
|
|
14405
|
-
const { api: api2 } = await import("./client-
|
|
15069
|
+
hookCommand.command("cloud-delete").description("Cloud-Hook l\xF6schen").argument("<hook-id>", "Hook ID").option("-y, --yes", "Ohne Best\xE4tigung").action(async (hookId, options) => {
|
|
15070
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14406
15071
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14407
15072
|
if (!isAuthenticated2()) {
|
|
14408
15073
|
log.error("Nicht angemeldet");
|
|
14409
15074
|
log.info("Anmelden mit: shiva login");
|
|
14410
15075
|
return;
|
|
14411
15076
|
}
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
if (!
|
|
14421
|
-
log.
|
|
15077
|
+
if (!options.yes) {
|
|
15078
|
+
const inquirer14 = (await import("inquirer")).default;
|
|
15079
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15080
|
+
type: "confirm",
|
|
15081
|
+
name: "confirm",
|
|
15082
|
+
message: `Hook ${hookId} l\xF6schen?`,
|
|
15083
|
+
default: false
|
|
15084
|
+
}]);
|
|
15085
|
+
if (!confirm) {
|
|
15086
|
+
log.dim("Abgebrochen");
|
|
14422
15087
|
return;
|
|
14423
15088
|
}
|
|
14424
|
-
|
|
14425
|
-
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
14430
|
-
|
|
15089
|
+
}
|
|
15090
|
+
const ora24 = (await import("ora")).default;
|
|
15091
|
+
const spinner = ora24("L\xF6sche Hook...").start();
|
|
15092
|
+
try {
|
|
15093
|
+
const result = await api2.deleteHook(hookId);
|
|
15094
|
+
if (result.success) {
|
|
15095
|
+
spinner.succeed("Hook gel\xF6scht");
|
|
15096
|
+
} else {
|
|
15097
|
+
spinner.fail(result.message || "Fehler beim L\xF6schen");
|
|
14431
15098
|
}
|
|
14432
15099
|
} catch (error) {
|
|
14433
|
-
|
|
15100
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
15101
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14434
15102
|
}
|
|
14435
15103
|
});
|
|
14436
|
-
hookCommand.command("
|
|
14437
|
-
const { api: api2 } = await import("./client-
|
|
15104
|
+
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) => {
|
|
15105
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14438
15106
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14439
15107
|
if (!isAuthenticated2()) {
|
|
14440
15108
|
log.error("Nicht angemeldet");
|
|
14441
15109
|
log.info("Anmelden mit: shiva login");
|
|
14442
15110
|
return;
|
|
14443
15111
|
}
|
|
14444
|
-
const
|
|
15112
|
+
const enabled = options.enable ? true : options.disable ? false : void 0;
|
|
15113
|
+
if (enabled === void 0) {
|
|
15114
|
+
log.error("Bitte --enable oder --disable angeben");
|
|
15115
|
+
return;
|
|
15116
|
+
}
|
|
15117
|
+
const ora24 = (await import("ora")).default;
|
|
15118
|
+
const spinner = ora24("Aktualisiere Hook...").start();
|
|
14445
15119
|
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)");
|
|
15120
|
+
const result = await api2.updateHook(hookId, { enabled });
|
|
15121
|
+
if (result.success) {
|
|
15122
|
+
spinner.succeed(`Hook ${enabled ? "aktiviert" : "deaktiviert"}`);
|
|
15123
|
+
} else {
|
|
15124
|
+
spinner.fail(result.message || "Fehler beim Aktualisieren");
|
|
14456
15125
|
}
|
|
14457
|
-
log.newline();
|
|
14458
|
-
log.success("Hooks synchronisiert");
|
|
14459
15126
|
} catch (error) {
|
|
14460
|
-
|
|
15127
|
+
spinner.fail("Fehler beim Aktualisieren");
|
|
15128
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
14461
15129
|
}
|
|
14462
15130
|
});
|
|
14463
15131
|
|
|
14464
15132
|
// src/commands/advanced/package.ts
|
|
14465
|
-
import { Command as
|
|
15133
|
+
import { Command as Command36 } from "commander";
|
|
14466
15134
|
import * as fs14 from "fs";
|
|
14467
15135
|
import inquirer13 from "inquirer";
|
|
14468
|
-
import
|
|
14469
|
-
var packageCommand = new
|
|
15136
|
+
import ora22 from "ora";
|
|
15137
|
+
var packageCommand = new Command36("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
|
|
14470
15138
|
listPackages();
|
|
14471
15139
|
});
|
|
14472
15140
|
packageCommand.command("list").description("Alle Packages auflisten").option("--json", "JSON Output").action((options) => {
|
|
@@ -14582,7 +15250,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
|
|
|
14582
15250
|
log.error(`Package "${pkg.name}" hat keine Projekte.`);
|
|
14583
15251
|
return;
|
|
14584
15252
|
}
|
|
14585
|
-
const spinner =
|
|
15253
|
+
const spinner = ora22("Bereite Projekte vor...").start();
|
|
14586
15254
|
try {
|
|
14587
15255
|
const launches = await getPackageLaunchConfig(name, options.new);
|
|
14588
15256
|
spinner.stop();
|
|
@@ -14611,7 +15279,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
|
|
|
14611
15279
|
}
|
|
14612
15280
|
});
|
|
14613
15281
|
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-
|
|
15282
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14615
15283
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14616
15284
|
if (!isAuthenticated2()) {
|
|
14617
15285
|
log.error("Nicht angemeldet");
|
|
@@ -14632,7 +15300,7 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
|
|
|
14632
15300
|
log.warn("Keine Packages zum Synchronisieren gefunden");
|
|
14633
15301
|
return;
|
|
14634
15302
|
}
|
|
14635
|
-
const spinner =
|
|
15303
|
+
const spinner = ora22("Synchronisiere Packages...").start();
|
|
14636
15304
|
let syncedCount = 0;
|
|
14637
15305
|
let errorCount = 0;
|
|
14638
15306
|
for (const pkg of packages) {
|
|
@@ -14657,14 +15325,14 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
|
|
|
14657
15325
|
}
|
|
14658
15326
|
});
|
|
14659
15327
|
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-
|
|
15328
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14661
15329
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14662
15330
|
if (!isAuthenticated2()) {
|
|
14663
15331
|
log.error("Nicht angemeldet");
|
|
14664
15332
|
log.info("Anmelden mit: shiva login");
|
|
14665
15333
|
return;
|
|
14666
15334
|
}
|
|
14667
|
-
const spinner =
|
|
15335
|
+
const spinner = ora22("Lade Packages aus Cloud...").start();
|
|
14668
15336
|
try {
|
|
14669
15337
|
const cloudPackages = await api2.getPackages();
|
|
14670
15338
|
spinner.stop();
|
|
@@ -14719,14 +15387,14 @@ packageCommand.command("pull").description("Packages aus Cloud laden").option("-
|
|
|
14719
15387
|
}
|
|
14720
15388
|
});
|
|
14721
15389
|
packageCommand.command("sync").description("Packages mit Cloud synchronisieren").action(async () => {
|
|
14722
|
-
const { api: api2 } = await import("./client-
|
|
15390
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14723
15391
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14724
15392
|
if (!isAuthenticated2()) {
|
|
14725
15393
|
log.error("Nicht angemeldet");
|
|
14726
15394
|
log.info("Anmelden mit: shiva login");
|
|
14727
15395
|
return;
|
|
14728
15396
|
}
|
|
14729
|
-
const spinner =
|
|
15397
|
+
const spinner = ora22("Synchronisiere Packages...").start();
|
|
14730
15398
|
const localPackages = getAllPackages();
|
|
14731
15399
|
let pushedCount = 0;
|
|
14732
15400
|
for (const pkg of localPackages) {
|
|
@@ -14772,7 +15440,7 @@ packageCommand.command("sync").description("Packages mit Cloud synchronisieren")
|
|
|
14772
15440
|
log.tree.item(`${localPackages.length + pulledCount} Packages total`);
|
|
14773
15441
|
});
|
|
14774
15442
|
packageCommand.command("cloud-delete <name>").description("Package aus Cloud l\xF6schen").action(async (name) => {
|
|
14775
|
-
const { api: api2 } = await import("./client-
|
|
15443
|
+
const { api: api2 } = await import("./client-UPSJM4FM.js");
|
|
14776
15444
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
14777
15445
|
if (!isAuthenticated2()) {
|
|
14778
15446
|
log.error("Nicht angemeldet");
|
|
@@ -14828,8 +15496,361 @@ function listPackages() {
|
|
|
14828
15496
|
log.newline();
|
|
14829
15497
|
}
|
|
14830
15498
|
|
|
15499
|
+
// src/commands/advanced/sandbox.ts
|
|
15500
|
+
import { Command as Command37 } from "commander";
|
|
15501
|
+
import ora23 from "ora";
|
|
15502
|
+
var sandboxCommand = new Command37("sandbox").description("Sandbox-Management mit Cloud-Sync");
|
|
15503
|
+
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) => {
|
|
15504
|
+
const spinner = ora23("Lade Sandboxes...").start();
|
|
15505
|
+
try {
|
|
15506
|
+
const results = [];
|
|
15507
|
+
if (!options.cloud) {
|
|
15508
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15509
|
+
for (const sandbox of localSandboxes) {
|
|
15510
|
+
if (!options.status || sandbox.status === options.status) {
|
|
15511
|
+
results.push({
|
|
15512
|
+
id: sandbox.id,
|
|
15513
|
+
source: "local",
|
|
15514
|
+
status: sandbox.status,
|
|
15515
|
+
mode: sandbox.mode,
|
|
15516
|
+
projectPath: sandbox.projectPath,
|
|
15517
|
+
createdAt: sandbox.createdAt
|
|
15518
|
+
});
|
|
15519
|
+
}
|
|
15520
|
+
}
|
|
15521
|
+
}
|
|
15522
|
+
if (!options.local && isAuthenticated()) {
|
|
15523
|
+
try {
|
|
15524
|
+
const cloudSandboxes = await api.getSandboxes(
|
|
15525
|
+
options.status ? { status: options.status } : void 0
|
|
15526
|
+
);
|
|
15527
|
+
for (const sandbox of cloudSandboxes) {
|
|
15528
|
+
results.push({
|
|
15529
|
+
id: sandbox.id,
|
|
15530
|
+
source: "cloud",
|
|
15531
|
+
status: sandbox.status,
|
|
15532
|
+
mode: sandbox.mode,
|
|
15533
|
+
projectId: sandbox.projectId,
|
|
15534
|
+
createdAt: sandbox.createdAt,
|
|
15535
|
+
title: sandbox.title
|
|
15536
|
+
});
|
|
15537
|
+
}
|
|
15538
|
+
} catch {
|
|
15539
|
+
}
|
|
15540
|
+
}
|
|
15541
|
+
spinner.stop();
|
|
15542
|
+
if (options.json) {
|
|
15543
|
+
console.log(JSON.stringify(results, null, 2));
|
|
15544
|
+
return;
|
|
15545
|
+
}
|
|
15546
|
+
log.newline();
|
|
15547
|
+
console.log(colors.orange.bold("Sandboxes"));
|
|
15548
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15549
|
+
log.newline();
|
|
15550
|
+
if (results.length === 0) {
|
|
15551
|
+
log.dim("Keine Sandboxes gefunden");
|
|
15552
|
+
return;
|
|
15553
|
+
}
|
|
15554
|
+
for (const sandbox of results) {
|
|
15555
|
+
const statusColor = sandbox.status === "active" ? colors.green : sandbox.status === "pending-review" ? colors.yellow : colors.dim;
|
|
15556
|
+
const sourceIcon = sandbox.source === "cloud" ? colors.cyan("\u2601") : colors.dim("\u{1F4BB}");
|
|
15557
|
+
console.log(` ${sourceIcon} ${colors.bold(sandbox.id)} ${statusColor(`[${sandbox.status}]`)}`);
|
|
15558
|
+
console.log(` ${colors.dim("Mode:")} ${sandbox.mode}`);
|
|
15559
|
+
if (sandbox.title) {
|
|
15560
|
+
console.log(` ${colors.dim("Title:")} ${sandbox.title}`);
|
|
15561
|
+
}
|
|
15562
|
+
if (sandbox.projectPath) {
|
|
15563
|
+
console.log(` ${colors.dim("Project:")} ${sandbox.projectPath}`);
|
|
15564
|
+
}
|
|
15565
|
+
console.log(` ${colors.dim("Created:")} ${sandbox.createdAt}`);
|
|
15566
|
+
log.newline();
|
|
15567
|
+
}
|
|
15568
|
+
} catch (error) {
|
|
15569
|
+
spinner.fail("Fehler beim Laden");
|
|
15570
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15571
|
+
}
|
|
15572
|
+
});
|
|
15573
|
+
sandboxCommand.command("pending").description("Sandboxes mit Pending Review Status").option("--json", "JSON Output").action(async (options) => {
|
|
15574
|
+
const spinner = ora23("Lade Pending Sandboxes...").start();
|
|
15575
|
+
try {
|
|
15576
|
+
const localPending = sandboxService.listPendingReview();
|
|
15577
|
+
let cloudPending = [];
|
|
15578
|
+
if (isAuthenticated()) {
|
|
15579
|
+
try {
|
|
15580
|
+
cloudPending = await api.getPendingSandboxes();
|
|
15581
|
+
} catch {
|
|
15582
|
+
}
|
|
15583
|
+
}
|
|
15584
|
+
spinner.stop();
|
|
15585
|
+
if (options.json) {
|
|
15586
|
+
console.log(JSON.stringify({ local: localPending, cloud: cloudPending }, null, 2));
|
|
15587
|
+
return;
|
|
15588
|
+
}
|
|
15589
|
+
log.newline();
|
|
15590
|
+
console.log(colors.orange.bold("Pending Review"));
|
|
15591
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15592
|
+
log.newline();
|
|
15593
|
+
if (localPending.length === 0 && cloudPending.length === 0) {
|
|
15594
|
+
log.dim("Keine Sandboxes zum Review");
|
|
15595
|
+
return;
|
|
15596
|
+
}
|
|
15597
|
+
if (localPending.length > 0) {
|
|
15598
|
+
console.log(colors.dim("Local:"));
|
|
15599
|
+
for (const sandbox of localPending) {
|
|
15600
|
+
console.log(` ${colors.yellow("\u25CB")} ${sandbox.id} - ${sandbox.projectPath}`);
|
|
15601
|
+
}
|
|
15602
|
+
log.newline();
|
|
15603
|
+
}
|
|
15604
|
+
if (cloudPending.length > 0) {
|
|
15605
|
+
console.log(colors.dim("Cloud:"));
|
|
15606
|
+
for (const sandbox of cloudPending) {
|
|
15607
|
+
console.log(` ${colors.cyan("\u2601")} ${sandbox.id} - ${sandbox.title || sandbox.baseBranch}`);
|
|
15608
|
+
}
|
|
15609
|
+
log.newline();
|
|
15610
|
+
}
|
|
15611
|
+
log.info("Review mit: shiva session review <id>");
|
|
15612
|
+
} catch (error) {
|
|
15613
|
+
spinner.fail("Fehler beim Laden");
|
|
15614
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15615
|
+
}
|
|
15616
|
+
});
|
|
15617
|
+
sandboxCommand.command("stats").description("Sandbox-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
15618
|
+
const spinner = ora23("Lade Statistiken...").start();
|
|
15619
|
+
try {
|
|
15620
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15621
|
+
const localStats = {
|
|
15622
|
+
total: localSandboxes.length,
|
|
15623
|
+
active: localSandboxes.filter((s) => s.status === "active").length,
|
|
15624
|
+
pendingReview: localSandboxes.filter((s) => s.status === "pending-review").length,
|
|
15625
|
+
applied: localSandboxes.filter((s) => s.status === "applied").length,
|
|
15626
|
+
discarded: localSandboxes.filter((s) => s.status === "discarded").length
|
|
15627
|
+
};
|
|
15628
|
+
let cloudStats = { total: 0, active: 0, pendingReview: 0, applied: 0, discarded: 0 };
|
|
15629
|
+
if (isAuthenticated()) {
|
|
15630
|
+
try {
|
|
15631
|
+
cloudStats = await api.getSandboxStats();
|
|
15632
|
+
} catch {
|
|
15633
|
+
}
|
|
15634
|
+
}
|
|
15635
|
+
spinner.stop();
|
|
15636
|
+
if (options.json) {
|
|
15637
|
+
console.log(JSON.stringify({ local: localStats, cloud: cloudStats }, null, 2));
|
|
15638
|
+
return;
|
|
15639
|
+
}
|
|
15640
|
+
log.newline();
|
|
15641
|
+
console.log(colors.orange.bold("Sandbox Statistics"));
|
|
15642
|
+
console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
15643
|
+
log.newline();
|
|
15644
|
+
console.log(colors.bold("Local:"));
|
|
15645
|
+
console.log(` ${colors.dim("Total:")} ${localStats.total}`);
|
|
15646
|
+
console.log(` ${colors.green("Active:")} ${localStats.active}`);
|
|
15647
|
+
console.log(` ${colors.yellow("Pending:")} ${localStats.pendingReview}`);
|
|
15648
|
+
console.log(` ${colors.dim("Applied:")} ${localStats.applied}`);
|
|
15649
|
+
console.log(` ${colors.dim("Discarded:")} ${localStats.discarded}`);
|
|
15650
|
+
log.newline();
|
|
15651
|
+
if (isAuthenticated()) {
|
|
15652
|
+
console.log(colors.bold("Cloud:"));
|
|
15653
|
+
console.log(` ${colors.dim("Total:")} ${cloudStats.total}`);
|
|
15654
|
+
console.log(` ${colors.green("Active:")} ${cloudStats.active}`);
|
|
15655
|
+
console.log(` ${colors.yellow("Pending:")} ${cloudStats.pendingReview}`);
|
|
15656
|
+
console.log(` ${colors.dim("Applied:")} ${cloudStats.applied}`);
|
|
15657
|
+
console.log(` ${colors.dim("Discarded:")} ${cloudStats.discarded}`);
|
|
15658
|
+
} else {
|
|
15659
|
+
log.dim("Cloud-Statistiken: Nicht angemeldet");
|
|
15660
|
+
}
|
|
15661
|
+
} catch (error) {
|
|
15662
|
+
spinner.fail("Fehler beim Laden");
|
|
15663
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15664
|
+
}
|
|
15665
|
+
});
|
|
15666
|
+
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) => {
|
|
15667
|
+
if (!isAuthenticated()) {
|
|
15668
|
+
log.error("Nicht angemeldet");
|
|
15669
|
+
log.info("Anmelden mit: shiva login");
|
|
15670
|
+
return;
|
|
15671
|
+
}
|
|
15672
|
+
const spinner = ora23("Synchronisiere Sandbox...").start();
|
|
15673
|
+
try {
|
|
15674
|
+
if (id) {
|
|
15675
|
+
await api.syncSandbox(id, {
|
|
15676
|
+
status: options.status
|
|
15677
|
+
});
|
|
15678
|
+
spinner.succeed(`Sandbox ${id} synchronisiert`);
|
|
15679
|
+
} else {
|
|
15680
|
+
const localSandboxes = sandboxService.listSandboxes();
|
|
15681
|
+
let synced = 0;
|
|
15682
|
+
for (const sandbox of localSandboxes) {
|
|
15683
|
+
try {
|
|
15684
|
+
await api.syncSandbox(sandbox.id, {
|
|
15685
|
+
status: sandbox.status === "active" ? void 0 : sandbox.status
|
|
15686
|
+
});
|
|
15687
|
+
synced++;
|
|
15688
|
+
} catch {
|
|
15689
|
+
}
|
|
15690
|
+
}
|
|
15691
|
+
spinner.succeed(`${synced}/${localSandboxes.length} Sandboxes synchronisiert`);
|
|
15692
|
+
}
|
|
15693
|
+
} catch (error) {
|
|
15694
|
+
spinner.fail("Fehler beim Synchronisieren");
|
|
15695
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15696
|
+
}
|
|
15697
|
+
});
|
|
15698
|
+
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) => {
|
|
15699
|
+
const days = parseInt(options.days);
|
|
15700
|
+
if (!options.yes) {
|
|
15701
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
15702
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15703
|
+
type: "confirm",
|
|
15704
|
+
name: "confirm",
|
|
15705
|
+
message: `Sandboxes \xE4lter als ${days} Tage l\xF6schen?`,
|
|
15706
|
+
default: false
|
|
15707
|
+
}]);
|
|
15708
|
+
if (!confirm) {
|
|
15709
|
+
log.dim("Abgebrochen");
|
|
15710
|
+
return;
|
|
15711
|
+
}
|
|
15712
|
+
}
|
|
15713
|
+
const spinner = ora23("R\xE4ume Sandboxes auf...").start();
|
|
15714
|
+
try {
|
|
15715
|
+
let localDeleted = 0;
|
|
15716
|
+
let cloudDeleted = 0;
|
|
15717
|
+
if (!options.cloud) {
|
|
15718
|
+
localDeleted = await sandboxService.cleanupOldSandboxes(days);
|
|
15719
|
+
}
|
|
15720
|
+
if (!options.local && isAuthenticated()) {
|
|
15721
|
+
try {
|
|
15722
|
+
const result = await api.cleanupSandboxes({ olderThanDays: days });
|
|
15723
|
+
cloudDeleted = result.deletedCount;
|
|
15724
|
+
} catch {
|
|
15725
|
+
}
|
|
15726
|
+
}
|
|
15727
|
+
spinner.stop();
|
|
15728
|
+
log.success("Cleanup abgeschlossen");
|
|
15729
|
+
log.newline();
|
|
15730
|
+
log.keyValue("Lokal gel\xF6scht", String(localDeleted));
|
|
15731
|
+
if (!options.local) {
|
|
15732
|
+
log.keyValue("Cloud gel\xF6scht", String(cloudDeleted));
|
|
15733
|
+
}
|
|
15734
|
+
} catch (error) {
|
|
15735
|
+
spinner.fail("Fehler beim Aufr\xE4umen");
|
|
15736
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15737
|
+
}
|
|
15738
|
+
});
|
|
15739
|
+
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) => {
|
|
15740
|
+
if (options.pull && isAuthenticated()) {
|
|
15741
|
+
const spinner = ora23("Lade Konfiguration aus Cloud...").start();
|
|
15742
|
+
try {
|
|
15743
|
+
const cloudConfig = await api.getSandboxConfig();
|
|
15744
|
+
sandboxService.updateConfig({
|
|
15745
|
+
defaultMode: cloudConfig.defaultMode,
|
|
15746
|
+
keepDays: cloudConfig.autoCleanupDays,
|
|
15747
|
+
maxSandboxes: cloudConfig.maxActiveSandboxes
|
|
15748
|
+
});
|
|
15749
|
+
spinner.succeed("Konfiguration aus Cloud geladen");
|
|
15750
|
+
return;
|
|
15751
|
+
} catch (error) {
|
|
15752
|
+
spinner.fail("Fehler beim Laden aus Cloud");
|
|
15753
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15754
|
+
return;
|
|
15755
|
+
}
|
|
15756
|
+
}
|
|
15757
|
+
if (options.push && isAuthenticated()) {
|
|
15758
|
+
const spinner = ora23("Speichere Konfiguration in Cloud...").start();
|
|
15759
|
+
try {
|
|
15760
|
+
const localConfig = sandboxService.getConfig();
|
|
15761
|
+
const cloudMode = localConfig.defaultMode === "none" ? "worktree" : localConfig.defaultMode;
|
|
15762
|
+
await api.updateSandboxConfig({
|
|
15763
|
+
defaultMode: cloudMode,
|
|
15764
|
+
autoCleanupDays: localConfig.keepDays,
|
|
15765
|
+
maxActiveSandboxes: localConfig.maxSandboxes,
|
|
15766
|
+
requireReview: options.requireReview ?? true
|
|
15767
|
+
});
|
|
15768
|
+
spinner.succeed("Konfiguration in Cloud gespeichert");
|
|
15769
|
+
return;
|
|
15770
|
+
} catch (error) {
|
|
15771
|
+
spinner.fail("Fehler beim Speichern in Cloud");
|
|
15772
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15773
|
+
return;
|
|
15774
|
+
}
|
|
15775
|
+
}
|
|
15776
|
+
if (options.show || !options.mode && !options.cleanupDays && !options.max && options.requireReview === void 0) {
|
|
15777
|
+
const config = sandboxService.getConfig();
|
|
15778
|
+
log.newline();
|
|
15779
|
+
console.log(colors.orange.bold("Sandbox Configuration"));
|
|
15780
|
+
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"));
|
|
15781
|
+
log.newline();
|
|
15782
|
+
log.keyValue("Enabled", config.enabled ? colors.green("Yes") : colors.red("No"));
|
|
15783
|
+
log.keyValue("Default Mode", config.defaultMode);
|
|
15784
|
+
log.keyValue("Auto Cleanup", config.autoCleanup ? "Yes" : "No");
|
|
15785
|
+
log.keyValue("Keep Days", String(config.keepDays));
|
|
15786
|
+
log.keyValue("Max Sandboxes", String(config.maxSandboxes));
|
|
15787
|
+
log.newline();
|
|
15788
|
+
if (isAuthenticated()) {
|
|
15789
|
+
try {
|
|
15790
|
+
const cloudConfig = await api.getSandboxConfig();
|
|
15791
|
+
console.log(colors.bold("Cloud Config:"));
|
|
15792
|
+
log.keyValue(" Default Mode", cloudConfig.defaultMode);
|
|
15793
|
+
log.keyValue(" Cleanup Days", String(cloudConfig.autoCleanupDays));
|
|
15794
|
+
log.keyValue(" Max Active", String(cloudConfig.maxActiveSandboxes));
|
|
15795
|
+
log.keyValue(" Require Review", cloudConfig.requireReview ? "Yes" : "No");
|
|
15796
|
+
} catch {
|
|
15797
|
+
log.dim("Cloud-Konfiguration nicht verf\xFCgbar");
|
|
15798
|
+
}
|
|
15799
|
+
}
|
|
15800
|
+
return;
|
|
15801
|
+
}
|
|
15802
|
+
const updates = {};
|
|
15803
|
+
if (options.mode) {
|
|
15804
|
+
updates.defaultMode = options.mode;
|
|
15805
|
+
}
|
|
15806
|
+
if (options.cleanupDays) {
|
|
15807
|
+
updates.keepDays = parseInt(options.cleanupDays);
|
|
15808
|
+
}
|
|
15809
|
+
if (options.max) {
|
|
15810
|
+
updates.maxSandboxes = parseInt(options.max);
|
|
15811
|
+
}
|
|
15812
|
+
sandboxService.updateConfig(updates);
|
|
15813
|
+
log.success("Konfiguration aktualisiert");
|
|
15814
|
+
});
|
|
15815
|
+
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) => {
|
|
15816
|
+
if (!options.yes) {
|
|
15817
|
+
const { default: inquirer14 } = await import("inquirer");
|
|
15818
|
+
const { confirm } = await inquirer14.prompt([{
|
|
15819
|
+
type: "confirm",
|
|
15820
|
+
name: "confirm",
|
|
15821
|
+
message: `Sandbox ${id} l\xF6schen?`,
|
|
15822
|
+
default: false
|
|
15823
|
+
}]);
|
|
15824
|
+
if (!confirm) {
|
|
15825
|
+
log.dim("Abgebrochen");
|
|
15826
|
+
return;
|
|
15827
|
+
}
|
|
15828
|
+
}
|
|
15829
|
+
const spinner = ora23("L\xF6sche Sandbox...").start();
|
|
15830
|
+
try {
|
|
15831
|
+
try {
|
|
15832
|
+
await sandboxService.deleteSandbox(id);
|
|
15833
|
+
spinner.text = "Lokal gel\xF6scht";
|
|
15834
|
+
} catch {
|
|
15835
|
+
}
|
|
15836
|
+
if (options.cloud || isAuthenticated()) {
|
|
15837
|
+
try {
|
|
15838
|
+
await api.deleteSandbox(id);
|
|
15839
|
+
spinner.succeed("Sandbox gel\xF6scht (lokal + cloud)");
|
|
15840
|
+
} catch {
|
|
15841
|
+
spinner.succeed("Sandbox gel\xF6scht (lokal)");
|
|
15842
|
+
}
|
|
15843
|
+
} else {
|
|
15844
|
+
spinner.succeed("Sandbox gel\xF6scht");
|
|
15845
|
+
}
|
|
15846
|
+
} catch (error) {
|
|
15847
|
+
spinner.fail("Fehler beim L\xF6schen");
|
|
15848
|
+
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
15849
|
+
}
|
|
15850
|
+
});
|
|
15851
|
+
|
|
14831
15852
|
// src/index.ts
|
|
14832
|
-
var program = new
|
|
15853
|
+
var program = new Command38();
|
|
14833
15854
|
program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.5.4");
|
|
14834
15855
|
program.addCommand(loginCommand);
|
|
14835
15856
|
program.addCommand(logoutCommand);
|
|
@@ -14869,6 +15890,8 @@ program.addCommand(dockerCommand);
|
|
|
14869
15890
|
program.addCommand(workflowCommand);
|
|
14870
15891
|
program.addCommand(hookCommand);
|
|
14871
15892
|
program.addCommand(packageCommand);
|
|
15893
|
+
program.addCommand(sandboxCommand);
|
|
15894
|
+
program.addCommand(userCommand);
|
|
14872
15895
|
program.action(async () => {
|
|
14873
15896
|
await showDashboard();
|
|
14874
15897
|
});
|