shiva-code 0.7.3 → 0.7.5
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/README.md +211 -0
- package/dist/{chunk-QQZRCJZK.js → chunk-J5IS642F.js} +28 -0
- package/dist/{chunk-LBTCSQAX.js → chunk-KUA6TMQJ.js} +1 -1
- package/dist/{chunk-UZKDLLPA.js → chunk-KW3LP3K3.js} +1 -1
- package/dist/{chunk-UAP4ZKEJ.js → chunk-RQ75X32M.js} +9 -9
- package/dist/{chunk-H5OFO4VS.js → chunk-W3DKHCXB.js} +5 -0
- package/dist/{client-GIGZFXT5.js → client-RPSJP4Z5.js} +1 -1
- package/dist/{hook-SZAVQGEA.js → hook-GIK5RFRC.js} +1 -1
- package/dist/index.js +633 -195
- package/dist/{login-ZEKMSKVH.js → login-Y6EJABSP.js} +2 -2
- package/dist/{manager-ZPQWG7E6.js → manager-CCRAV6A5.js} +1 -1
- package/dist/{package-manager-NHNQATBH.js → package-manager-UORON74F.js} +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
hookCommand,
|
|
4
4
|
packageScanner
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RQ75X32M.js";
|
|
6
6
|
import {
|
|
7
7
|
copyToClipboard,
|
|
8
8
|
getClipboardInstallInstructions,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
getPackageLaunchConfig,
|
|
18
18
|
getPackageStats,
|
|
19
19
|
removeProjectFromPackage
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-KUA6TMQJ.js";
|
|
21
21
|
import {
|
|
22
22
|
deviceTrustService,
|
|
23
23
|
displayBackupCodes,
|
|
@@ -26,14 +26,15 @@ import {
|
|
|
26
26
|
loginCommand,
|
|
27
27
|
logout,
|
|
28
28
|
twoFactorService
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-KW3LP3K3.js";
|
|
30
30
|
import {
|
|
31
31
|
colors,
|
|
32
32
|
log
|
|
33
33
|
} from "./chunk-Z6NXFC4Q.js";
|
|
34
34
|
import {
|
|
35
|
-
api
|
|
36
|
-
|
|
35
|
+
api,
|
|
36
|
+
enableDebug
|
|
37
|
+
} from "./chunk-J5IS642F.js";
|
|
37
38
|
import {
|
|
38
39
|
CONFIG_PATH,
|
|
39
40
|
clearAuth,
|
|
@@ -42,6 +43,7 @@ import {
|
|
|
42
43
|
getClaudeLaunchArgs,
|
|
43
44
|
getClaudeSkipPermissions,
|
|
44
45
|
getConfig,
|
|
46
|
+
getConfigPath,
|
|
45
47
|
getDefaultTerminal,
|
|
46
48
|
getExtendedConfig,
|
|
47
49
|
getToken,
|
|
@@ -93,6 +95,7 @@ import {
|
|
|
93
95
|
updateTimeControl
|
|
94
96
|
} from "./chunk-PMA6MGQW.js";
|
|
95
97
|
import {
|
|
98
|
+
containsShellMetacharacters,
|
|
96
99
|
encodeProjectPath,
|
|
97
100
|
findProject,
|
|
98
101
|
findProjectForCurrentDir,
|
|
@@ -114,7 +117,7 @@ import {
|
|
|
114
117
|
maskSecret,
|
|
115
118
|
sanitizeForLog,
|
|
116
119
|
saveRecoveredContext
|
|
117
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-W3DKHCXB.js";
|
|
118
121
|
import {
|
|
119
122
|
cache
|
|
120
123
|
} from "./chunk-HIQO2DBA.js";
|
|
@@ -123,7 +126,7 @@ import {
|
|
|
123
126
|
} from "./chunk-3RG5ZIWI.js";
|
|
124
127
|
|
|
125
128
|
// src/index.ts
|
|
126
|
-
import { Command as
|
|
129
|
+
import { Command as Command39 } from "commander";
|
|
127
130
|
import * as readline from "readline";
|
|
128
131
|
|
|
129
132
|
// src/services/onboarding/welcome.ts
|
|
@@ -261,7 +264,7 @@ async function promptLogin() {
|
|
|
261
264
|
log.newline();
|
|
262
265
|
log.info("\xD6ffne Browser f\xFCr Anmeldung...");
|
|
263
266
|
log.newline();
|
|
264
|
-
const { loginCommand: loginCommand2 } = await import("./login-
|
|
267
|
+
const { loginCommand: loginCommand2 } = await import("./login-Y6EJABSP.js");
|
|
265
268
|
await loginCommand2.parseAsync(["login"], { from: "user" });
|
|
266
269
|
return isAuthenticated();
|
|
267
270
|
}
|
|
@@ -333,7 +336,7 @@ async function promptHooks() {
|
|
|
333
336
|
if (installHooks) {
|
|
334
337
|
log.newline();
|
|
335
338
|
log.info("Installiere Hooks...");
|
|
336
|
-
const { hookCommand: hookCommand2 } = await import("./hook-
|
|
339
|
+
const { hookCommand: hookCommand2 } = await import("./hook-GIK5RFRC.js");
|
|
337
340
|
await hookCommand2.parseAsync(["hook", "install", "--all"], { from: "user" });
|
|
338
341
|
onboardingStore.set("hooksInstalled", true);
|
|
339
342
|
return true;
|
|
@@ -388,6 +391,86 @@ function getStartupStatus() {
|
|
|
388
391
|
};
|
|
389
392
|
}
|
|
390
393
|
|
|
394
|
+
// src/utils/fuzzy.ts
|
|
395
|
+
function levenshtein(a, b) {
|
|
396
|
+
const matrix = [];
|
|
397
|
+
for (let i = 0; i <= b.length; i++) {
|
|
398
|
+
matrix[i] = [i];
|
|
399
|
+
}
|
|
400
|
+
for (let j = 0; j <= a.length; j++) {
|
|
401
|
+
matrix[0][j] = j;
|
|
402
|
+
}
|
|
403
|
+
for (let i = 1; i <= b.length; i++) {
|
|
404
|
+
for (let j = 1; j <= a.length; j++) {
|
|
405
|
+
if (b[i - 1] === a[j - 1]) {
|
|
406
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
407
|
+
} else {
|
|
408
|
+
matrix[i][j] = Math.min(
|
|
409
|
+
matrix[i - 1][j - 1] + 1,
|
|
410
|
+
// substitution
|
|
411
|
+
matrix[i][j - 1] + 1,
|
|
412
|
+
// insertion
|
|
413
|
+
matrix[i - 1][j] + 1
|
|
414
|
+
// deletion
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return matrix[b.length][a.length];
|
|
420
|
+
}
|
|
421
|
+
function findSimilarCommands(input, commands, maxDistance = 3) {
|
|
422
|
+
return commands.map((cmd) => ({
|
|
423
|
+
cmd,
|
|
424
|
+
distance: levenshtein(input.toLowerCase(), cmd.toLowerCase())
|
|
425
|
+
})).filter(({ distance }) => distance <= maxDistance).sort((a, b) => a.distance - b.distance).slice(0, 3).map(({ cmd }) => cmd);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// src/commands/aliases.ts
|
|
429
|
+
var COMMAND_ALIASES = {
|
|
430
|
+
// Session management
|
|
431
|
+
sessions: ["ss", "sess"],
|
|
432
|
+
resume: ["res"],
|
|
433
|
+
restore: ["rst"],
|
|
434
|
+
start: ["st"],
|
|
435
|
+
// Memory commands
|
|
436
|
+
remember: ["rem", "r"],
|
|
437
|
+
search: ["s", "find", "f"],
|
|
438
|
+
forget: ["fg"],
|
|
439
|
+
// Project commands
|
|
440
|
+
init: ["i"],
|
|
441
|
+
sync: ["sy"],
|
|
442
|
+
status: ["stat"],
|
|
443
|
+
projects: ["proj", "p"],
|
|
444
|
+
config: ["cfg", "conf"],
|
|
445
|
+
// GitHub commands
|
|
446
|
+
github: ["gh"],
|
|
447
|
+
issues: ["iss"],
|
|
448
|
+
prs: ["pr"],
|
|
449
|
+
// Security
|
|
450
|
+
secrets: ["sec"],
|
|
451
|
+
scan: ["sc"],
|
|
452
|
+
// Advanced
|
|
453
|
+
package: ["pkg"],
|
|
454
|
+
docker: ["dk"],
|
|
455
|
+
sandbox: ["sb"],
|
|
456
|
+
workflow: ["wf"],
|
|
457
|
+
hook: ["hk"],
|
|
458
|
+
// System
|
|
459
|
+
doctor: ["doc", "dr"],
|
|
460
|
+
stats: ["analytics"],
|
|
461
|
+
upgrade: ["up"],
|
|
462
|
+
user: ["u"]
|
|
463
|
+
};
|
|
464
|
+
var aliasToCommand = /* @__PURE__ */ new Map();
|
|
465
|
+
for (const [command, aliases] of Object.entries(COMMAND_ALIASES)) {
|
|
466
|
+
for (const alias of aliases) {
|
|
467
|
+
aliasToCommand.set(alias, command);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
function getCommandFromAlias(alias) {
|
|
471
|
+
return aliasToCommand.get(alias.toLowerCase()) || null;
|
|
472
|
+
}
|
|
473
|
+
|
|
391
474
|
// src/commands/auth/logout.ts
|
|
392
475
|
import { Command } from "commander";
|
|
393
476
|
var logoutCommand = new Command("logout").description("Abmelden").action(() => {
|
|
@@ -1185,14 +1268,49 @@ import { resolve as resolve4 } from "path";
|
|
|
1185
1268
|
import ora2 from "ora";
|
|
1186
1269
|
|
|
1187
1270
|
// src/utils/errors.ts
|
|
1271
|
+
var ERROR_SUGGESTIONS = {
|
|
1272
|
+
// Network errors
|
|
1273
|
+
ENOTFOUND: "Netzwerkfehler. Pr\xFCfe deine Internetverbindung.",
|
|
1274
|
+
ECONNREFUSED: "Server nicht erreichbar. Versuche es sp\xE4ter erneut.",
|
|
1275
|
+
ETIMEDOUT: "Anfrage Timeout. Server antwortet nicht.",
|
|
1276
|
+
ECONNRESET: "Verbindung abgebrochen. Versuche es erneut.",
|
|
1277
|
+
CERT_HAS_EXPIRED: "SSL-Zertifikat abgelaufen. Pr\xFCfe die Systemzeit.",
|
|
1278
|
+
// HTTP errors
|
|
1279
|
+
"401": "Nicht autorisiert. Versuche: shiva login",
|
|
1280
|
+
"403": "Zugriff verweigert. Pr\xFCfe deine Berechtigungen.",
|
|
1281
|
+
"404": "Nicht gefunden. Pr\xFCfe ob die Resource existiert.",
|
|
1282
|
+
"429": "Rate Limit erreicht. Warte einen Moment.",
|
|
1283
|
+
"500": "Server Fehler. Versuche es sp\xE4ter erneut.",
|
|
1284
|
+
"502": "Bad Gateway. Server tempor\xE4r nicht erreichbar.",
|
|
1285
|
+
"503": "Service nicht verf\xFCgbar. Wartungsarbeiten m\xF6glich.",
|
|
1286
|
+
"504": "Gateway Timeout. Server \xFCberlastet.",
|
|
1287
|
+
// File system errors
|
|
1288
|
+
ENOENT: "Datei oder Verzeichnis nicht gefunden.",
|
|
1289
|
+
EACCES: "Keine Berechtigung. Pr\xFCfe die Dateirechte.",
|
|
1290
|
+
EPERM: "Operation nicht erlaubt.",
|
|
1291
|
+
EEXIST: "Datei oder Verzeichnis existiert bereits.",
|
|
1292
|
+
ENOSPC: "Kein Speicherplatz mehr verf\xFCgbar.",
|
|
1293
|
+
EMFILE: "Zu viele offene Dateien. Schlie\xDFe andere Programme."
|
|
1294
|
+
};
|
|
1295
|
+
function getErrorSuggestion(error) {
|
|
1296
|
+
const errorStr = error instanceof Error ? error.message : error;
|
|
1297
|
+
for (const [key, suggestion] of Object.entries(ERROR_SUGGESTIONS)) {
|
|
1298
|
+
if (errorStr.includes(key)) {
|
|
1299
|
+
return suggestion;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
return null;
|
|
1303
|
+
}
|
|
1188
1304
|
var ShivaError = class _ShivaError extends Error {
|
|
1189
1305
|
code;
|
|
1190
1306
|
suggestion;
|
|
1191
|
-
|
|
1307
|
+
context;
|
|
1308
|
+
constructor(code, message, suggestion, context) {
|
|
1192
1309
|
super(message);
|
|
1193
1310
|
this.name = "ShivaError";
|
|
1194
1311
|
this.code = code;
|
|
1195
|
-
this.suggestion = suggestion;
|
|
1312
|
+
this.suggestion = suggestion || getErrorSuggestion(message) || void 0;
|
|
1313
|
+
this.context = context;
|
|
1196
1314
|
Object.setPrototypeOf(this, _ShivaError.prototype);
|
|
1197
1315
|
}
|
|
1198
1316
|
/**
|
|
@@ -1206,6 +1324,18 @@ var ShivaError = class _ShivaError extends Error {
|
|
|
1206
1324
|
}
|
|
1207
1325
|
return result;
|
|
1208
1326
|
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Convert to a user-friendly message
|
|
1329
|
+
*/
|
|
1330
|
+
toUserMessage() {
|
|
1331
|
+
let msg = this.message;
|
|
1332
|
+
if (this.suggestion) {
|
|
1333
|
+
msg += `
|
|
1334
|
+
|
|
1335
|
+
${this.suggestion}`;
|
|
1336
|
+
}
|
|
1337
|
+
return msg;
|
|
1338
|
+
}
|
|
1209
1339
|
};
|
|
1210
1340
|
var Errors = {
|
|
1211
1341
|
// Authentication errors
|
|
@@ -2116,13 +2246,13 @@ claudeConfig.command("terminal").description("Standard-Terminal f\xFCr Multi-Pro
|
|
|
2116
2246
|
setDefaultTerminal(type2);
|
|
2117
2247
|
log.success(`Default Terminal: ${type2}`);
|
|
2118
2248
|
});
|
|
2119
|
-
claudeConfig.command("args").description("Custom Claude Argumente verwalten").argument("[args...]", "Argumente zum Hinzuf\xFCgen").option("--clear", "Alle Custom Args entfernen").option("--list", "Aktuelle Args anzeigen").action((
|
|
2249
|
+
claudeConfig.command("args").description("Custom Claude Argumente verwalten").argument("[args...]", "Argumente zum Hinzuf\xFCgen").option("--clear", "Alle Custom Args entfernen").option("--list", "Aktuelle Args anzeigen").action((args2, options) => {
|
|
2120
2250
|
if (options.clear) {
|
|
2121
2251
|
setClaudeArgs([]);
|
|
2122
2252
|
log.success("Custom Args entfernt");
|
|
2123
2253
|
return;
|
|
2124
2254
|
}
|
|
2125
|
-
if (options.list || !
|
|
2255
|
+
if (options.list || !args2 || args2.length === 0) {
|
|
2126
2256
|
const current2 = getClaudeArgs();
|
|
2127
2257
|
if (current2.length === 0) {
|
|
2128
2258
|
log.dim("Keine Custom Args gesetzt");
|
|
@@ -2135,7 +2265,7 @@ claudeConfig.command("args").description("Custom Claude Argumente verwalten").ar
|
|
|
2135
2265
|
return;
|
|
2136
2266
|
}
|
|
2137
2267
|
const current = getClaudeArgs();
|
|
2138
|
-
const newArgs = [...current, ...
|
|
2268
|
+
const newArgs = [...current, ...args2];
|
|
2139
2269
|
setClaudeArgs(newArgs);
|
|
2140
2270
|
log.success("Args hinzugef\xFCgt");
|
|
2141
2271
|
log.keyValue("Custom Args", newArgs.join(" "));
|
|
@@ -3620,30 +3750,30 @@ var DockerService = class {
|
|
|
3620
3750
|
*/
|
|
3621
3751
|
async createContainer(config) {
|
|
3622
3752
|
const cmd = this.getCommand();
|
|
3623
|
-
const
|
|
3753
|
+
const args2 = ["create"];
|
|
3624
3754
|
if (config.name) {
|
|
3625
3755
|
if (!this.isValidContainerNameInternal(config.name)) {
|
|
3626
3756
|
throw new Error(`Invalid container name: ${sanitizeForLog(config.name)}`);
|
|
3627
3757
|
}
|
|
3628
|
-
|
|
3758
|
+
args2.push("--name", config.name);
|
|
3629
3759
|
}
|
|
3630
3760
|
if (!isValidProjectPath(config.workdir)) {
|
|
3631
3761
|
throw new Error(`Invalid workdir: ${sanitizeForLog(config.workdir)}`);
|
|
3632
3762
|
}
|
|
3633
|
-
|
|
3763
|
+
args2.push("--workdir", config.workdir);
|
|
3634
3764
|
for (const mount of config.mounts) {
|
|
3635
3765
|
if (!isValidProjectPath(mount.host)) {
|
|
3636
3766
|
log.warn(`Skipping invalid mount path: ${sanitizeForLog(mount.host)}`);
|
|
3637
3767
|
continue;
|
|
3638
3768
|
}
|
|
3639
|
-
|
|
3769
|
+
args2.push("-v", `${mount.host}:${mount.container}:${mount.mode}`);
|
|
3640
3770
|
}
|
|
3641
3771
|
for (const [key, value] of Object.entries(config.env)) {
|
|
3642
3772
|
if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
|
|
3643
3773
|
log.warn(`Skipping invalid env var name: ${sanitizeForLog(key)}`);
|
|
3644
3774
|
continue;
|
|
3645
3775
|
}
|
|
3646
|
-
|
|
3776
|
+
args2.push("-e", `${key}=${value}`);
|
|
3647
3777
|
}
|
|
3648
3778
|
if (config.ports) {
|
|
3649
3779
|
for (const [host, container] of Object.entries(config.ports)) {
|
|
@@ -3651,21 +3781,21 @@ var DockerService = class {
|
|
|
3651
3781
|
log.warn(`Skipping invalid port mapping: ${host}:${container}`);
|
|
3652
3782
|
continue;
|
|
3653
3783
|
}
|
|
3654
|
-
|
|
3784
|
+
args2.push("-p", `${host}:${container}`);
|
|
3655
3785
|
}
|
|
3656
3786
|
}
|
|
3657
3787
|
if (config.interactive) {
|
|
3658
|
-
|
|
3788
|
+
args2.push("-it");
|
|
3659
3789
|
}
|
|
3660
3790
|
if (config.autoRemove) {
|
|
3661
|
-
|
|
3791
|
+
args2.push("--rm");
|
|
3662
3792
|
}
|
|
3663
3793
|
if (!this.isValidImage(config.image)) {
|
|
3664
3794
|
throw new Error(`Invalid image: ${sanitizeForLog(config.image)}`);
|
|
3665
3795
|
}
|
|
3666
|
-
|
|
3796
|
+
args2.push(config.image);
|
|
3667
3797
|
try {
|
|
3668
|
-
const result = spawnSync(cmd,
|
|
3798
|
+
const result = spawnSync(cmd, args2, {
|
|
3669
3799
|
encoding: "utf8",
|
|
3670
3800
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3671
3801
|
});
|
|
@@ -3746,13 +3876,13 @@ var DockerService = class {
|
|
|
3746
3876
|
return "";
|
|
3747
3877
|
}
|
|
3748
3878
|
const cmd = this.getCommand();
|
|
3749
|
-
const
|
|
3879
|
+
const args2 = ["logs"];
|
|
3750
3880
|
if (tail && tail > 0) {
|
|
3751
|
-
|
|
3881
|
+
args2.push("--tail", String(tail));
|
|
3752
3882
|
}
|
|
3753
|
-
|
|
3883
|
+
args2.push(containerId);
|
|
3754
3884
|
try {
|
|
3755
|
-
const result = spawnSync(cmd,
|
|
3885
|
+
const result = spawnSync(cmd, args2, {
|
|
3756
3886
|
encoding: "utf8",
|
|
3757
3887
|
stdio: ["pipe", "pipe", "pipe"]
|
|
3758
3888
|
});
|
|
@@ -3796,7 +3926,7 @@ var DockerService = class {
|
|
|
3796
3926
|
secrets = await api.getSecretsForInjection();
|
|
3797
3927
|
} catch {
|
|
3798
3928
|
}
|
|
3799
|
-
const
|
|
3929
|
+
const args2 = [
|
|
3800
3930
|
"run",
|
|
3801
3931
|
"-it",
|
|
3802
3932
|
"--rm",
|
|
@@ -3816,22 +3946,22 @@ var DockerService = class {
|
|
|
3816
3946
|
];
|
|
3817
3947
|
for (const [host, container] of Object.entries(settings.volumeMounts || {})) {
|
|
3818
3948
|
if (isValidProjectPath(host)) {
|
|
3819
|
-
|
|
3949
|
+
args2.push("-v", `${host}:${container}:rw`);
|
|
3820
3950
|
}
|
|
3821
3951
|
}
|
|
3822
3952
|
for (const [key, value] of Object.entries(settings.environment || {})) {
|
|
3823
3953
|
if (/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
|
|
3824
|
-
|
|
3954
|
+
args2.push("-e", `${key}=${value}`);
|
|
3825
3955
|
}
|
|
3826
3956
|
}
|
|
3827
3957
|
for (const [key, value] of Object.entries(secrets)) {
|
|
3828
3958
|
if (/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
|
|
3829
|
-
|
|
3959
|
+
args2.push("-e", `${key}=${value}`);
|
|
3830
3960
|
}
|
|
3831
3961
|
}
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
const dockerProcess = spawn(cmd,
|
|
3962
|
+
args2.push(image);
|
|
3963
|
+
args2.push("claude", ...claudeArgs);
|
|
3964
|
+
const dockerProcess = spawn(cmd, args2, {
|
|
3835
3965
|
stdio: "inherit"
|
|
3836
3966
|
});
|
|
3837
3967
|
return dockerProcess;
|
|
@@ -4110,7 +4240,7 @@ var DockerService = class {
|
|
|
4110
4240
|
secrets = await api.getSecretsForInjection();
|
|
4111
4241
|
} catch {
|
|
4112
4242
|
}
|
|
4113
|
-
const
|
|
4243
|
+
const args2 = [
|
|
4114
4244
|
"run",
|
|
4115
4245
|
"-it",
|
|
4116
4246
|
"--rm",
|
|
@@ -4120,42 +4250,42 @@ var DockerService = class {
|
|
|
4120
4250
|
"/workspace"
|
|
4121
4251
|
];
|
|
4122
4252
|
if (effectiveConfig.network === "none") {
|
|
4123
|
-
|
|
4253
|
+
args2.push("--network", "none");
|
|
4124
4254
|
} else if (effectiveConfig.network === "host") {
|
|
4125
|
-
|
|
4255
|
+
args2.push("--network", "host");
|
|
4126
4256
|
}
|
|
4127
4257
|
if (effectiveConfig.resources.cpuLimit && /^[\d.]+$/.test(effectiveConfig.resources.cpuLimit)) {
|
|
4128
|
-
|
|
4258
|
+
args2.push("--cpus", effectiveConfig.resources.cpuLimit);
|
|
4129
4259
|
}
|
|
4130
4260
|
if (effectiveConfig.resources.memoryLimit && /^[\d]+[kmgKMG]?$/.test(effectiveConfig.resources.memoryLimit)) {
|
|
4131
|
-
|
|
4261
|
+
args2.push("--memory", effectiveConfig.resources.memoryLimit);
|
|
4132
4262
|
}
|
|
4133
4263
|
for (const opt of effectiveConfig.securityOpts) {
|
|
4134
4264
|
if (/^[a-z:=_-]+$/i.test(opt)) {
|
|
4135
|
-
|
|
4265
|
+
args2.push("--security-opt", opt);
|
|
4136
4266
|
}
|
|
4137
4267
|
}
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4268
|
+
args2.push("-v", `${launch.projectPath}:/workspace:rw`);
|
|
4269
|
+
args2.push("-v", `${path.join(os.homedir(), ".claude")}:/root/.claude:rw`);
|
|
4270
|
+
args2.push("-v", `${path.join(os.homedir(), ".config", "shiva-code")}:/root/.config/shiva-code:rw`);
|
|
4141
4271
|
for (const mount of effectiveConfig.mounts) {
|
|
4142
4272
|
if (isValidProjectPath(mount.host)) {
|
|
4143
|
-
|
|
4273
|
+
args2.push("-v", `${mount.host}:${mount.container}:${mount.mode}`);
|
|
4144
4274
|
}
|
|
4145
4275
|
}
|
|
4146
4276
|
for (const [key, value] of Object.entries(effectiveConfig.environment)) {
|
|
4147
4277
|
if (/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
|
|
4148
|
-
|
|
4278
|
+
args2.push("-e", `${key}=${value}`);
|
|
4149
4279
|
}
|
|
4150
4280
|
}
|
|
4151
4281
|
for (const [key, value] of Object.entries(secrets)) {
|
|
4152
4282
|
if (/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
|
|
4153
|
-
|
|
4283
|
+
args2.push("-e", `${key}=${value}`);
|
|
4154
4284
|
}
|
|
4155
4285
|
}
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
const dockerProcess = spawn(cmd,
|
|
4286
|
+
args2.push(effectiveConfig.image);
|
|
4287
|
+
args2.push("claude", ...claudeArgs);
|
|
4288
|
+
const dockerProcess = spawn(cmd, args2, {
|
|
4159
4289
|
stdio: "inherit"
|
|
4160
4290
|
});
|
|
4161
4291
|
return dockerProcess;
|
|
@@ -4224,13 +4354,13 @@ function validateProject(project) {
|
|
|
4224
4354
|
return { valid: true };
|
|
4225
4355
|
}
|
|
4226
4356
|
function buildClaudeArgs(project) {
|
|
4227
|
-
const
|
|
4357
|
+
const args2 = [];
|
|
4228
4358
|
if (!project.newSession && project.sessionId) {
|
|
4229
|
-
|
|
4359
|
+
args2.push("--resume", project.sessionId);
|
|
4230
4360
|
}
|
|
4231
4361
|
const launchArgs = getClaudeLaunchArgs();
|
|
4232
|
-
|
|
4233
|
-
return
|
|
4362
|
+
args2.push(...launchArgs);
|
|
4363
|
+
return args2;
|
|
4234
4364
|
}
|
|
4235
4365
|
function sanitizeProjectName(name) {
|
|
4236
4366
|
return name.replace(/[^a-zA-Z0-9_.-]/g, "-").substring(0, 50);
|
|
@@ -4301,7 +4431,7 @@ async function spawnInTmux(projects, sessionName) {
|
|
|
4301
4431
|
}
|
|
4302
4432
|
}
|
|
4303
4433
|
async function spawnInGnomeTerminal(projects) {
|
|
4304
|
-
const
|
|
4434
|
+
const args2 = [];
|
|
4305
4435
|
for (const project of projects) {
|
|
4306
4436
|
const validation = validateProject(project);
|
|
4307
4437
|
if (!validation.valid) {
|
|
@@ -4311,7 +4441,7 @@ async function spawnInGnomeTerminal(projects) {
|
|
|
4311
4441
|
const claudeArgs = buildClaudeArgs(project);
|
|
4312
4442
|
const safeName = sanitizeProjectName(project.projectName);
|
|
4313
4443
|
const wrapperScript = `cd ${escapeShellArg(project.projectPath)} && exec claude ${claudeArgs.map(escapeShellArg).join(" ")}`;
|
|
4314
|
-
|
|
4444
|
+
args2.push(
|
|
4315
4445
|
"--tab",
|
|
4316
4446
|
"--title",
|
|
4317
4447
|
safeName,
|
|
@@ -4321,8 +4451,8 @@ async function spawnInGnomeTerminal(projects) {
|
|
|
4321
4451
|
wrapperScript
|
|
4322
4452
|
);
|
|
4323
4453
|
}
|
|
4324
|
-
if (
|
|
4325
|
-
spawn2("gnome-terminal",
|
|
4454
|
+
if (args2.length > 0) {
|
|
4455
|
+
spawn2("gnome-terminal", args2, {
|
|
4326
4456
|
stdio: "ignore",
|
|
4327
4457
|
detached: true
|
|
4328
4458
|
}).unref();
|
|
@@ -4493,7 +4623,7 @@ Attaching to: ${sanitizeForLog(firstProject.projectName)}`);
|
|
|
4493
4623
|
function buildSecureDockerArgs(project, settings, containerName) {
|
|
4494
4624
|
const cmd = dockerService.getDockerInfo().runtime === "podman" ? "podman" : "docker";
|
|
4495
4625
|
const homeDir = os2.homedir();
|
|
4496
|
-
const
|
|
4626
|
+
const args2 = [
|
|
4497
4627
|
cmd,
|
|
4498
4628
|
"run",
|
|
4499
4629
|
"-it",
|
|
@@ -4511,19 +4641,19 @@ function buildSecureDockerArgs(project, settings, containerName) {
|
|
|
4511
4641
|
];
|
|
4512
4642
|
for (const [hostPath, containerPath] of Object.entries(settings.volumeMounts || {})) {
|
|
4513
4643
|
if (isValidProjectPath(hostPath)) {
|
|
4514
|
-
|
|
4644
|
+
args2.push("-v", `${hostPath}:${containerPath}:rw`);
|
|
4515
4645
|
}
|
|
4516
4646
|
}
|
|
4517
4647
|
for (const [key, value] of Object.entries(settings.environment || {})) {
|
|
4518
4648
|
if (/^[A-Z_][A-Z0-9_]*$/.test(key)) {
|
|
4519
|
-
|
|
4649
|
+
args2.push("-e", `${key}=${value}`);
|
|
4520
4650
|
}
|
|
4521
4651
|
}
|
|
4522
|
-
|
|
4652
|
+
args2.push(settings.defaultImage, "claude");
|
|
4523
4653
|
if (project.sessionId && !project.newSession) {
|
|
4524
|
-
|
|
4654
|
+
args2.push("--resume", project.sessionId);
|
|
4525
4655
|
}
|
|
4526
|
-
return
|
|
4656
|
+
return args2;
|
|
4527
4657
|
}
|
|
4528
4658
|
function escapeShellArg(arg) {
|
|
4529
4659
|
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
@@ -4574,11 +4704,119 @@ function getTerminalName(terminal) {
|
|
|
4574
4704
|
}
|
|
4575
4705
|
|
|
4576
4706
|
// src/services/sandbox/sandbox.ts
|
|
4577
|
-
import { execSync as execSync2 } from "child_process";
|
|
4578
4707
|
import { existsSync as existsSync8, mkdirSync, rmSync, readdirSync as readdirSync2, copyFileSync, readFileSync as readFileSync4 } from "fs";
|
|
4579
4708
|
import { join as join4, dirname } from "path";
|
|
4580
4709
|
import { randomUUID } from "crypto";
|
|
4581
4710
|
import Conf3 from "conf";
|
|
4711
|
+
|
|
4712
|
+
// src/utils/secure-exec.ts
|
|
4713
|
+
import { spawnSync as spawnSync3, spawn as spawn3 } from "child_process";
|
|
4714
|
+
var ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
4715
|
+
// Git commands
|
|
4716
|
+
"git",
|
|
4717
|
+
// Docker commands
|
|
4718
|
+
"docker",
|
|
4719
|
+
"podman",
|
|
4720
|
+
// System commands
|
|
4721
|
+
"which",
|
|
4722
|
+
"tar",
|
|
4723
|
+
"claude",
|
|
4724
|
+
"gh",
|
|
4725
|
+
// Terminal emulators
|
|
4726
|
+
"tmux",
|
|
4727
|
+
"gnome-terminal",
|
|
4728
|
+
"kitty",
|
|
4729
|
+
"kitten",
|
|
4730
|
+
"alacritty",
|
|
4731
|
+
// Clipboard tools
|
|
4732
|
+
"wl-copy",
|
|
4733
|
+
"xclip",
|
|
4734
|
+
"xsel",
|
|
4735
|
+
"pbcopy",
|
|
4736
|
+
// Package managers (for version check)
|
|
4737
|
+
"npm",
|
|
4738
|
+
"yarn",
|
|
4739
|
+
"pnpm",
|
|
4740
|
+
"node"
|
|
4741
|
+
]);
|
|
4742
|
+
function isAllowedCommand(command) {
|
|
4743
|
+
return ALLOWED_COMMANDS.has(command);
|
|
4744
|
+
}
|
|
4745
|
+
function validateArgs(args2) {
|
|
4746
|
+
for (const arg of args2) {
|
|
4747
|
+
if (arg.includes("\0")) {
|
|
4748
|
+
return false;
|
|
4749
|
+
}
|
|
4750
|
+
if (!arg.startsWith("-") && !arg.startsWith("--")) {
|
|
4751
|
+
const sanitized = arg.replace(/[a-zA-Z0-9_\-./@ ]/g, "");
|
|
4752
|
+
if (sanitized.length > 0 && containsShellMetacharacters(sanitized)) {
|
|
4753
|
+
return false;
|
|
4754
|
+
}
|
|
4755
|
+
}
|
|
4756
|
+
}
|
|
4757
|
+
return true;
|
|
4758
|
+
}
|
|
4759
|
+
function secureExecSync(command, args2, options = {}) {
|
|
4760
|
+
if (!isAllowedCommand(command)) {
|
|
4761
|
+
return {
|
|
4762
|
+
success: false,
|
|
4763
|
+
stdout: "",
|
|
4764
|
+
stderr: `Command not allowed: ${command}`,
|
|
4765
|
+
exitCode: -1
|
|
4766
|
+
};
|
|
4767
|
+
}
|
|
4768
|
+
if (options.cwd && !isValidProjectPath(options.cwd)) {
|
|
4769
|
+
return {
|
|
4770
|
+
success: false,
|
|
4771
|
+
stdout: "",
|
|
4772
|
+
stderr: `Invalid working directory: ${options.cwd}`,
|
|
4773
|
+
exitCode: -1
|
|
4774
|
+
};
|
|
4775
|
+
}
|
|
4776
|
+
if (!validateArgs(args2)) {
|
|
4777
|
+
return {
|
|
4778
|
+
success: false,
|
|
4779
|
+
stdout: "",
|
|
4780
|
+
stderr: "Invalid arguments detected",
|
|
4781
|
+
exitCode: -1
|
|
4782
|
+
};
|
|
4783
|
+
}
|
|
4784
|
+
try {
|
|
4785
|
+
const result = spawnSync3(command, args2, {
|
|
4786
|
+
cwd: options.cwd,
|
|
4787
|
+
timeout: options.timeout || 3e4,
|
|
4788
|
+
encoding: options.encoding || "utf-8",
|
|
4789
|
+
env: options.env || process.env,
|
|
4790
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
4791
|
+
// CRITICAL: shell: false is the default, but we explicitly set it
|
|
4792
|
+
shell: false
|
|
4793
|
+
});
|
|
4794
|
+
return {
|
|
4795
|
+
success: result.status === 0,
|
|
4796
|
+
stdout: result.stdout?.toString() || "",
|
|
4797
|
+
stderr: result.stderr?.toString() || "",
|
|
4798
|
+
exitCode: result.status
|
|
4799
|
+
};
|
|
4800
|
+
} catch (error) {
|
|
4801
|
+
return {
|
|
4802
|
+
success: false,
|
|
4803
|
+
stdout: "",
|
|
4804
|
+
stderr: error instanceof Error ? error.message : "Unknown error",
|
|
4805
|
+
exitCode: -1
|
|
4806
|
+
};
|
|
4807
|
+
}
|
|
4808
|
+
}
|
|
4809
|
+
function gitExec(args2, cwd) {
|
|
4810
|
+
return secureExecSync("git", args2, { cwd });
|
|
4811
|
+
}
|
|
4812
|
+
function tarExec(args2, cwd) {
|
|
4813
|
+
return secureExecSync("tar", args2, { cwd });
|
|
4814
|
+
}
|
|
4815
|
+
function containerExec(runtime, args2, cwd) {
|
|
4816
|
+
return secureExecSync(runtime, args2, { cwd });
|
|
4817
|
+
}
|
|
4818
|
+
|
|
4819
|
+
// src/services/sandbox/sandbox.ts
|
|
4582
4820
|
var DEFAULT_SANDBOX_CONFIG = {
|
|
4583
4821
|
enabled: false,
|
|
4584
4822
|
defaultMode: "worktree",
|
|
@@ -4616,31 +4854,19 @@ var SandboxService = class {
|
|
|
4616
4854
|
* Check if a path is a git repository
|
|
4617
4855
|
*/
|
|
4618
4856
|
isGitRepo(path15) {
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
cwd: path15,
|
|
4622
|
-
stdio: "pipe"
|
|
4623
|
-
});
|
|
4624
|
-
return true;
|
|
4625
|
-
} catch {
|
|
4626
|
-
return false;
|
|
4627
|
-
}
|
|
4857
|
+
const result = gitExec(["rev-parse", "--git-dir"], path15);
|
|
4858
|
+
return result.success;
|
|
4628
4859
|
}
|
|
4629
4860
|
/**
|
|
4630
4861
|
* Check if Docker is available
|
|
4631
4862
|
*/
|
|
4632
4863
|
isDockerAvailable() {
|
|
4633
|
-
|
|
4634
|
-
|
|
4864
|
+
const dockerResult = containerExec("docker", ["info"]);
|
|
4865
|
+
if (dockerResult.success) {
|
|
4635
4866
|
return true;
|
|
4636
|
-
} catch {
|
|
4637
|
-
try {
|
|
4638
|
-
execSync2("podman info", { stdio: "pipe" });
|
|
4639
|
-
return true;
|
|
4640
|
-
} catch {
|
|
4641
|
-
return false;
|
|
4642
|
-
}
|
|
4643
4867
|
}
|
|
4868
|
+
const podmanResult = containerExec("podman", ["info"]);
|
|
4869
|
+
return podmanResult.success;
|
|
4644
4870
|
}
|
|
4645
4871
|
/**
|
|
4646
4872
|
* Detect the best sandbox mode for the current environment
|
|
@@ -4722,14 +4948,15 @@ var SandboxService = class {
|
|
|
4722
4948
|
const sandboxDir = this.getSandboxDir(projectPath);
|
|
4723
4949
|
const sandboxPath = join4(sandboxDir, `session-${sessionId}`);
|
|
4724
4950
|
mkdirSync(dirname(sandboxPath), { recursive: true });
|
|
4725
|
-
const
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
}
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4951
|
+
const headResult = gitExec(["rev-parse", "HEAD"], projectPath);
|
|
4952
|
+
if (!headResult.success) {
|
|
4953
|
+
throw new Error("Failed to get current HEAD");
|
|
4954
|
+
}
|
|
4955
|
+
const currentRef = headResult.stdout.trim();
|
|
4956
|
+
const worktreeResult = gitExec(["worktree", "add", "--detach", sandboxPath, currentRef], projectPath);
|
|
4957
|
+
if (!worktreeResult.success) {
|
|
4958
|
+
throw new Error(`Failed to create worktree: ${worktreeResult.stderr}`);
|
|
4959
|
+
}
|
|
4733
4960
|
await this.copyUntrackedFiles(projectPath, sandboxPath);
|
|
4734
4961
|
return sandboxPath;
|
|
4735
4962
|
}
|
|
@@ -4738,10 +4965,8 @@ var SandboxService = class {
|
|
|
4738
4965
|
*/
|
|
4739
4966
|
async copyUntrackedFiles(projectPath, sandboxPath) {
|
|
4740
4967
|
try {
|
|
4741
|
-
const
|
|
4742
|
-
|
|
4743
|
-
encoding: "utf-8"
|
|
4744
|
-
});
|
|
4968
|
+
const untrackedResult = gitExec(["ls-files", "--others", "--exclude-standard"], projectPath);
|
|
4969
|
+
const untrackedOutput = untrackedResult.stdout;
|
|
4745
4970
|
const untrackedFiles = untrackedOutput.split("\n").filter((f) => f.trim().length > 0);
|
|
4746
4971
|
for (const file of untrackedFiles) {
|
|
4747
4972
|
const srcPath = join4(projectPath, file);
|
|
@@ -4865,22 +5090,12 @@ var SandboxService = class {
|
|
|
4865
5090
|
throw new Error(`Sandbox ${sessionId} not found`);
|
|
4866
5091
|
}
|
|
4867
5092
|
if (session.mode === "worktree") {
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
cwd: session.projectPath,
|
|
4871
|
-
stdio: "pipe"
|
|
4872
|
-
});
|
|
4873
|
-
} catch {
|
|
5093
|
+
const removeResult = gitExec(["worktree", "remove", session.sandboxPath, "--force"], session.projectPath);
|
|
5094
|
+
if (!removeResult.success) {
|
|
4874
5095
|
if (existsSync8(session.sandboxPath)) {
|
|
4875
5096
|
rmSync(session.sandboxPath, { recursive: true, force: true });
|
|
4876
5097
|
}
|
|
4877
|
-
|
|
4878
|
-
execSync2("git worktree prune", {
|
|
4879
|
-
cwd: session.projectPath,
|
|
4880
|
-
stdio: "pipe"
|
|
4881
|
-
});
|
|
4882
|
-
} catch {
|
|
4883
|
-
}
|
|
5098
|
+
gitExec(["worktree", "prune"], session.projectPath);
|
|
4884
5099
|
}
|
|
4885
5100
|
} else {
|
|
4886
5101
|
if (existsSync8(session.sandboxPath)) {
|
|
@@ -4904,14 +5119,10 @@ var SandboxService = class {
|
|
|
4904
5119
|
}
|
|
4905
5120
|
const changes = [];
|
|
4906
5121
|
if (session.mode === "worktree") {
|
|
4907
|
-
const
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
const untrackedOutput = execSync2("git ls-files --others --exclude-standard", {
|
|
4912
|
-
cwd: session.sandboxPath,
|
|
4913
|
-
encoding: "utf-8"
|
|
4914
|
-
});
|
|
5122
|
+
const diffResult = gitExec(["diff", "--stat", "--numstat", "HEAD"], session.sandboxPath);
|
|
5123
|
+
const diffOutput = diffResult.stdout;
|
|
5124
|
+
const untrackedResult = gitExec(["ls-files", "--others", "--exclude-standard"], session.sandboxPath);
|
|
5125
|
+
const untrackedOutput = untrackedResult.stdout;
|
|
4915
5126
|
const lines = diffOutput.split("\n").filter((l) => l.trim().length > 0);
|
|
4916
5127
|
for (const line of lines) {
|
|
4917
5128
|
const match = line.match(/^(\d+)\t(\d+)\t(.+)$/);
|
|
@@ -5107,21 +5318,17 @@ var SandboxService = class {
|
|
|
5107
5318
|
throw new Error(`Sandbox ${sessionId} not found`);
|
|
5108
5319
|
}
|
|
5109
5320
|
if (session.mode === "worktree") {
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
if (existsSync8(sandboxFilePath2)) {
|
|
5119
|
-
const content = readFileSync4(sandboxFilePath2, "utf-8");
|
|
5120
|
-
return `+++ ${filePath} (new file)
|
|
5321
|
+
const diffResult = gitExec(["diff", "HEAD", "--", filePath], session.sandboxPath);
|
|
5322
|
+
if (diffResult.success && diffResult.stdout) {
|
|
5323
|
+
return diffResult.stdout;
|
|
5324
|
+
}
|
|
5325
|
+
const sandboxFilePath2 = join4(session.sandboxPath, filePath);
|
|
5326
|
+
if (existsSync8(sandboxFilePath2)) {
|
|
5327
|
+
const content = readFileSync4(sandboxFilePath2, "utf-8");
|
|
5328
|
+
return `+++ ${filePath} (new file)
|
|
5121
5329
|
${content.split("\n").map((l) => `+ ${l}`).join("\n")}`;
|
|
5122
|
-
}
|
|
5123
|
-
return "(file not found)";
|
|
5124
5330
|
}
|
|
5331
|
+
return "(no changes)";
|
|
5125
5332
|
}
|
|
5126
5333
|
const originalPath = join4(session.projectPath, filePath);
|
|
5127
5334
|
const sandboxFilePath = join4(session.sandboxPath, filePath);
|
|
@@ -5687,7 +5894,7 @@ function generatePRReviewContext(pr, repo) {
|
|
|
5687
5894
|
|
|
5688
5895
|
// src/commands/session/resume.ts
|
|
5689
5896
|
import { Command as Command11 } from "commander";
|
|
5690
|
-
import { spawn as
|
|
5897
|
+
import { spawn as spawn4 } from "child_process";
|
|
5691
5898
|
import inquirer3 from "inquirer";
|
|
5692
5899
|
import ora8 from "ora";
|
|
5693
5900
|
import * as fs2 from "fs";
|
|
@@ -5891,8 +6098,8 @@ function truncatePrompt(prompt, maxLength) {
|
|
|
5891
6098
|
}
|
|
5892
6099
|
function launchClaudeResume(projectPath, sessionId) {
|
|
5893
6100
|
const launchArgs = getClaudeLaunchArgs();
|
|
5894
|
-
const
|
|
5895
|
-
const child =
|
|
6101
|
+
const args2 = ["--resume", sessionId, ...launchArgs];
|
|
6102
|
+
const child = spawn4("claude", args2, {
|
|
5896
6103
|
cwd: projectPath,
|
|
5897
6104
|
stdio: "inherit",
|
|
5898
6105
|
shell: true
|
|
@@ -5910,7 +6117,7 @@ function launchClaudeResume(projectPath, sessionId) {
|
|
|
5910
6117
|
|
|
5911
6118
|
// src/commands/session/restore.ts
|
|
5912
6119
|
import { Command as Command12 } from "commander";
|
|
5913
|
-
import { spawn as
|
|
6120
|
+
import { spawn as spawn5 } from "child_process";
|
|
5914
6121
|
import inquirer4 from "inquirer";
|
|
5915
6122
|
import ora9 from "ora";
|
|
5916
6123
|
import * as fs3 from "fs";
|
|
@@ -6043,7 +6250,7 @@ var restoreCommand = new Command12("restore").description("Context aus crashed S
|
|
|
6043
6250
|
log.info("F\xFCge den Context am Anfang der neuen Session ein:");
|
|
6044
6251
|
log.dim(` cat "${outputPath}" | head -100`);
|
|
6045
6252
|
log.newline();
|
|
6046
|
-
const child =
|
|
6253
|
+
const child = spawn5("claude", [], {
|
|
6047
6254
|
cwd: project.absolutePath,
|
|
6048
6255
|
stdio: "inherit",
|
|
6049
6256
|
shell: true
|
|
@@ -6223,9 +6430,9 @@ function sessionHasAnyTag(sessionId, tags) {
|
|
|
6223
6430
|
|
|
6224
6431
|
// src/utils/command-wrapper.ts
|
|
6225
6432
|
function withCommandErrorHandling(commandName, fn) {
|
|
6226
|
-
return async (...
|
|
6433
|
+
return async (...args2) => {
|
|
6227
6434
|
try {
|
|
6228
|
-
await fn(...
|
|
6435
|
+
await fn(...args2);
|
|
6229
6436
|
} catch (error) {
|
|
6230
6437
|
const shivaError = fromError(error);
|
|
6231
6438
|
logErrorWithSuggestion(shivaError, commandName);
|
|
@@ -6348,7 +6555,7 @@ async function checkProjectExists(path15) {
|
|
|
6348
6555
|
}
|
|
6349
6556
|
}
|
|
6350
6557
|
sessionsCommand.command("push").description("Sessions in Cloud sichern").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
|
|
6351
|
-
const { api: api2 } = await import("./client-
|
|
6558
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6352
6559
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6353
6560
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6354
6561
|
if (!isAuthenticated2()) {
|
|
@@ -6408,7 +6615,7 @@ sessionsCommand.command("push").description("Sessions in Cloud sichern").option(
|
|
|
6408
6615
|
}
|
|
6409
6616
|
});
|
|
6410
6617
|
sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
6411
|
-
const { api: api2 } = await import("./client-
|
|
6618
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6412
6619
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6413
6620
|
if (!isAuthenticated2()) {
|
|
6414
6621
|
log.error("Nicht angemeldet");
|
|
@@ -6455,7 +6662,7 @@ sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("
|
|
|
6455
6662
|
}
|
|
6456
6663
|
});
|
|
6457
6664
|
sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
|
|
6458
|
-
const { api: api2 } = await import("./client-
|
|
6665
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6459
6666
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6460
6667
|
const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
|
|
6461
6668
|
if (!isAuthenticated2()) {
|
|
@@ -6508,7 +6715,7 @@ sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren"
|
|
|
6508
6715
|
log.dim("Sessions werden automatisch mit lokalen Claude Sessions verkn\xFCpft");
|
|
6509
6716
|
});
|
|
6510
6717
|
sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\xF6schen").action(async (sessionId) => {
|
|
6511
|
-
const { api: api2 } = await import("./client-
|
|
6718
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6512
6719
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6513
6720
|
if (!isAuthenticated2()) {
|
|
6514
6721
|
log.error("Nicht angemeldet");
|
|
@@ -6527,7 +6734,7 @@ sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\x
|
|
|
6527
6734
|
}
|
|
6528
6735
|
});
|
|
6529
6736
|
sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6530
|
-
const { api: api2 } = await import("./client-
|
|
6737
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6531
6738
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6532
6739
|
if (!isAuthenticated2()) {
|
|
6533
6740
|
log.error("Nicht angemeldet");
|
|
@@ -6564,7 +6771,7 @@ sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").
|
|
|
6564
6771
|
}
|
|
6565
6772
|
});
|
|
6566
6773
|
sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
|
|
6567
|
-
const { api: api2 } = await import("./client-
|
|
6774
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6568
6775
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6569
6776
|
if (!isAuthenticated2()) {
|
|
6570
6777
|
log.error("Nicht angemeldet");
|
|
@@ -6596,7 +6803,7 @@ sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen
|
|
|
6596
6803
|
}
|
|
6597
6804
|
});
|
|
6598
6805
|
sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortsetzen").action(async (sessionId) => {
|
|
6599
|
-
const { api: api2 } = await import("./client-
|
|
6806
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6600
6807
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6601
6808
|
if (!isAuthenticated2()) {
|
|
6602
6809
|
log.error("Nicht angemeldet");
|
|
@@ -6620,7 +6827,7 @@ sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortset
|
|
|
6620
6827
|
}
|
|
6621
6828
|
});
|
|
6622
6829
|
sessionsCommand.command("export <sessionId>").description("Cloud-Session exportieren").option("-o, --output <file>", "Ausgabedatei").action(async (sessionId, options) => {
|
|
6623
|
-
const { api: api2 } = await import("./client-
|
|
6830
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6624
6831
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6625
6832
|
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
6626
6833
|
if (!isAuthenticated2()) {
|
|
@@ -6644,7 +6851,7 @@ sessionsCommand.command("export <sessionId>").description("Cloud-Session exporti
|
|
|
6644
6851
|
}
|
|
6645
6852
|
});
|
|
6646
6853
|
sessionsCommand.command("update <sessionId>").description("Cloud-Session aktualisieren").option("--summary <text>", "Session-Zusammenfassung").option("--branch <name>", "Git Branch").action(async (sessionId, options) => {
|
|
6647
|
-
const { api: api2 } = await import("./client-
|
|
6854
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
6648
6855
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
6649
6856
|
if (!isAuthenticated2()) {
|
|
6650
6857
|
log.error("Nicht angemeldet");
|
|
@@ -7124,7 +7331,7 @@ sessionCommand.command("config").description("Sandbox-Konfiguration verwalten").
|
|
|
7124
7331
|
|
|
7125
7332
|
// src/commands/github/github-cmd.ts
|
|
7126
7333
|
import { Command as Command15 } from "commander";
|
|
7127
|
-
import { spawn as
|
|
7334
|
+
import { spawn as spawn6, spawnSync as spawnSync5 } from "child_process";
|
|
7128
7335
|
import * as fs5 from "fs";
|
|
7129
7336
|
import * as path5 from "path";
|
|
7130
7337
|
import inquirer5 from "inquirer";
|
|
@@ -7203,7 +7410,7 @@ function loginWithGh() {
|
|
|
7203
7410
|
log.newline();
|
|
7204
7411
|
log.info("\xD6ffne GitHub Login...");
|
|
7205
7412
|
log.newline();
|
|
7206
|
-
const child =
|
|
7413
|
+
const child = spawn6("gh", ["auth", "login"], {
|
|
7207
7414
|
stdio: "inherit"
|
|
7208
7415
|
});
|
|
7209
7416
|
child.on("error", (error) => {
|
|
@@ -7624,13 +7831,13 @@ githubCommand.command("map").description("Aktuellen Branch mit einer Session ver
|
|
|
7624
7831
|
initShivaDir(cwd);
|
|
7625
7832
|
}
|
|
7626
7833
|
if (!sessionId) {
|
|
7627
|
-
const { findProject: findProject3 } = await import("./manager-
|
|
7834
|
+
const { findProject: findProject3 } = await import("./manager-CCRAV6A5.js");
|
|
7628
7835
|
const project = await findProject3(cwd);
|
|
7629
7836
|
if (!project || project.sessions.length === 0) {
|
|
7630
7837
|
log.error("Keine Sessions f\xFCr dieses Projekt gefunden");
|
|
7631
7838
|
return;
|
|
7632
7839
|
}
|
|
7633
|
-
const { formatDate: formatDate2 } = await import("./manager-
|
|
7840
|
+
const { formatDate: formatDate2 } = await import("./manager-CCRAV6A5.js");
|
|
7634
7841
|
const choices = project.sessions.slice(0, 10).map((s) => {
|
|
7635
7842
|
const time = formatDate2(s.modified);
|
|
7636
7843
|
const msgs = `${s.messageCount} msgs`;
|
|
@@ -10220,7 +10427,7 @@ async function resolveSessionId(input) {
|
|
|
10220
10427
|
return null;
|
|
10221
10428
|
}
|
|
10222
10429
|
tagsCommand.command("cloud").description("Memory-Tags aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
|
|
10223
|
-
const { api: api2 } = await import("./client-
|
|
10430
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
10224
10431
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
10225
10432
|
if (!isAuthenticated2()) {
|
|
10226
10433
|
log.error("Nicht angemeldet");
|
|
@@ -10264,7 +10471,6 @@ import inquirer10 from "inquirer";
|
|
|
10264
10471
|
// src/services/session/export.ts
|
|
10265
10472
|
import * as fs9 from "fs";
|
|
10266
10473
|
import * as path10 from "path";
|
|
10267
|
-
import { execSync as execSync3 } from "child_process";
|
|
10268
10474
|
async function exportSession(sessionId, options = {}) {
|
|
10269
10475
|
const projects = await getAllClaudeProjects();
|
|
10270
10476
|
for (const project of projects) {
|
|
@@ -10375,11 +10581,9 @@ function createBackupArchive(outputPath, projectPaths) {
|
|
|
10375
10581
|
if (includePaths.length === 0) {
|
|
10376
10582
|
return false;
|
|
10377
10583
|
}
|
|
10378
|
-
const
|
|
10379
|
-
|
|
10380
|
-
|
|
10381
|
-
});
|
|
10382
|
-
return true;
|
|
10584
|
+
const args2 = ["-czf", outputPath, "-C", claudeDir, ...includePaths];
|
|
10585
|
+
const result = tarExec(args2);
|
|
10586
|
+
return result.success;
|
|
10383
10587
|
} catch {
|
|
10384
10588
|
return false;
|
|
10385
10589
|
}
|
|
@@ -10484,9 +10688,10 @@ function restoreFromArchive(archivePath, targetDir) {
|
|
|
10484
10688
|
if (!fs9.existsSync(extractTo)) {
|
|
10485
10689
|
fs9.mkdirSync(extractTo, { recursive: true });
|
|
10486
10690
|
}
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10691
|
+
const extractResult = tarExec(["-xzf", archivePath, "-C", extractTo]);
|
|
10692
|
+
if (!extractResult.success) {
|
|
10693
|
+
return false;
|
|
10694
|
+
}
|
|
10490
10695
|
return true;
|
|
10491
10696
|
} catch {
|
|
10492
10697
|
return false;
|
|
@@ -10786,20 +10991,20 @@ var rememberCommand = new Command26("remember").description("Memory in der Cloud
|
|
|
10786
10991
|
|
|
10787
10992
|
// src/commands/system/doctor.ts
|
|
10788
10993
|
import { Command as Command27 } from "commander";
|
|
10789
|
-
import { execSync as
|
|
10994
|
+
import { execSync as execSync2 } from "child_process";
|
|
10790
10995
|
import * as fs11 from "fs";
|
|
10791
10996
|
import * as path12 from "path";
|
|
10792
10997
|
import * as os5 from "os";
|
|
10793
10998
|
function tryExec(command) {
|
|
10794
10999
|
try {
|
|
10795
|
-
return
|
|
11000
|
+
return execSync2(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
10796
11001
|
} catch {
|
|
10797
11002
|
return null;
|
|
10798
11003
|
}
|
|
10799
11004
|
}
|
|
10800
11005
|
function commandExists2(cmd) {
|
|
10801
11006
|
try {
|
|
10802
|
-
|
|
11007
|
+
execSync2(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
|
|
10803
11008
|
return true;
|
|
10804
11009
|
} catch {
|
|
10805
11010
|
return false;
|
|
@@ -11113,7 +11318,7 @@ var doctorCommand = new Command27("doctor").description("System-Check f\xFCr SHI
|
|
|
11113
11318
|
|
|
11114
11319
|
// src/commands/system/upgrade.ts
|
|
11115
11320
|
import { Command as Command28 } from "commander";
|
|
11116
|
-
import { execSync as
|
|
11321
|
+
import { execSync as execSync3, spawn as spawn7 } from "child_process";
|
|
11117
11322
|
import * as fs12 from "fs";
|
|
11118
11323
|
import * as path13 from "path";
|
|
11119
11324
|
import * as os6 from "os";
|
|
@@ -11133,17 +11338,17 @@ function detectInstallationType() {
|
|
|
11133
11338
|
}
|
|
11134
11339
|
}
|
|
11135
11340
|
try {
|
|
11136
|
-
const npmGlobal =
|
|
11341
|
+
const npmGlobal = execSync3("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
|
|
11137
11342
|
if (npmGlobal.includes(PACKAGE_NAME)) return "npm";
|
|
11138
11343
|
} catch {
|
|
11139
11344
|
}
|
|
11140
11345
|
try {
|
|
11141
|
-
const yarnGlobal =
|
|
11346
|
+
const yarnGlobal = execSync3("yarn global list 2>/dev/null", { encoding: "utf-8" });
|
|
11142
11347
|
if (yarnGlobal.includes(PACKAGE_NAME)) return "yarn";
|
|
11143
11348
|
} catch {
|
|
11144
11349
|
}
|
|
11145
11350
|
try {
|
|
11146
|
-
const pnpmGlobal =
|
|
11351
|
+
const pnpmGlobal = execSync3("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
|
|
11147
11352
|
if (pnpmGlobal.includes(PACKAGE_NAME)) return "pnpm";
|
|
11148
11353
|
} catch {
|
|
11149
11354
|
}
|
|
@@ -11159,7 +11364,7 @@ function getCurrentVersion() {
|
|
|
11159
11364
|
} catch {
|
|
11160
11365
|
}
|
|
11161
11366
|
try {
|
|
11162
|
-
const output =
|
|
11367
|
+
const output = execSync3(`"${process.execPath}" --version 2>/dev/null`, { encoding: "utf-8" }).trim();
|
|
11163
11368
|
return output || "0.0.0";
|
|
11164
11369
|
} catch {
|
|
11165
11370
|
return "0.7.0";
|
|
@@ -11332,7 +11537,7 @@ del "${backupBinary}" 2>nul
|
|
|
11332
11537
|
del "%~f0"
|
|
11333
11538
|
`;
|
|
11334
11539
|
fs12.writeFileSync(updateScript, scriptContent);
|
|
11335
|
-
|
|
11540
|
+
spawn7("cmd", ["/c", updateScript], { detached: true, stdio: "ignore" }).unref();
|
|
11336
11541
|
log.success("Update wird nach Beenden angewendet");
|
|
11337
11542
|
log.info("Bitte starte SHIVA neu.");
|
|
11338
11543
|
} else {
|
|
@@ -11375,11 +11580,11 @@ function getUpgradeCommand(pm) {
|
|
|
11375
11580
|
}
|
|
11376
11581
|
async function runPackageManagerUpgrade(pm) {
|
|
11377
11582
|
const command = getUpgradeCommand(pm);
|
|
11378
|
-
const [cmd, ...
|
|
11583
|
+
const [cmd, ...args2] = command.split(" ");
|
|
11379
11584
|
return new Promise((resolve14) => {
|
|
11380
11585
|
log.info(`F\xFChre aus: ${command}`);
|
|
11381
11586
|
log.newline();
|
|
11382
|
-
const proc =
|
|
11587
|
+
const proc = spawn7(cmd, args2, {
|
|
11383
11588
|
stdio: "inherit",
|
|
11384
11589
|
shell: true
|
|
11385
11590
|
});
|
|
@@ -11458,6 +11663,7 @@ var selfUpdateCommand = new Command28("self-update").description('Alias f\xFCr "
|
|
|
11458
11663
|
|
|
11459
11664
|
// src/commands/system/telemetry.ts
|
|
11460
11665
|
import { Command as Command29 } from "commander";
|
|
11666
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
11461
11667
|
import Conf4 from "conf";
|
|
11462
11668
|
var telemetryConfig = new Conf4({
|
|
11463
11669
|
projectName: "shiva-code",
|
|
@@ -11473,11 +11679,7 @@ var telemetryConfig = new Conf4({
|
|
|
11473
11679
|
}
|
|
11474
11680
|
});
|
|
11475
11681
|
function generateAnonymousId() {
|
|
11476
|
-
return
|
|
11477
|
-
const r = Math.random() * 16 | 0;
|
|
11478
|
-
const v = c === "x" ? r : r & 3 | 8;
|
|
11479
|
-
return v.toString(16);
|
|
11480
|
-
});
|
|
11682
|
+
return randomUUID2();
|
|
11481
11683
|
}
|
|
11482
11684
|
var DATA_COLLECTED = [
|
|
11483
11685
|
'Verwendete Commands (z.B. "shiva sessions", "shiva start")',
|
|
@@ -12137,7 +12339,7 @@ function formatNumber(n) {
|
|
|
12137
12339
|
return String(n);
|
|
12138
12340
|
}
|
|
12139
12341
|
statsCommand.command("sessions").description("Session Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
12140
|
-
const { api: api2 } = await import("./client-
|
|
12342
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
12141
12343
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
12142
12344
|
if (!isAuthenticated2()) {
|
|
12143
12345
|
log.error("Nicht angemeldet");
|
|
@@ -12189,7 +12391,7 @@ statsCommand.command("sessions").description("Session Analytics (Pro Feature)").
|
|
|
12189
12391
|
}
|
|
12190
12392
|
});
|
|
12191
12393
|
statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
12192
|
-
const { api: api2 } = await import("./client-
|
|
12394
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
12193
12395
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
12194
12396
|
if (!isAuthenticated2()) {
|
|
12195
12397
|
log.error("Nicht angemeldet");
|
|
@@ -12237,7 +12439,7 @@ statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)"
|
|
|
12237
12439
|
}
|
|
12238
12440
|
});
|
|
12239
12441
|
statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
|
|
12240
|
-
const { api: api2 } = await import("./client-
|
|
12442
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
12241
12443
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
12242
12444
|
if (!isAuthenticated2()) {
|
|
12243
12445
|
log.error("Nicht angemeldet");
|
|
@@ -12281,7 +12483,7 @@ statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").
|
|
|
12281
12483
|
}
|
|
12282
12484
|
});
|
|
12283
12485
|
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) => {
|
|
12284
|
-
const { api: api2 } = await import("./client-
|
|
12486
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
12285
12487
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
12286
12488
|
const { writeFileSync: writeFileSync11 } = await import("fs");
|
|
12287
12489
|
if (!isAuthenticated2()) {
|
|
@@ -12316,7 +12518,7 @@ statsCommand.command("export").description("Analytics-Daten exportieren (Pro Fea
|
|
|
12316
12518
|
}
|
|
12317
12519
|
});
|
|
12318
12520
|
statsCommand.command("track").description("Analytics Event tracken").argument("<type>", "Event-Typ").argument("[data]", "Event-Daten als JSON").action(async (type2, data) => {
|
|
12319
|
-
const { api: api2 } = await import("./client-
|
|
12521
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
12320
12522
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
12321
12523
|
if (!isAuthenticated2()) {
|
|
12322
12524
|
log.error("Nicht angemeldet");
|
|
@@ -12648,10 +12850,218 @@ var welcomeCommand = new Command33("welcome").description("Onboarding erneut sta
|
|
|
12648
12850
|
await runOnboarding();
|
|
12649
12851
|
});
|
|
12650
12852
|
|
|
12651
|
-
// src/commands/
|
|
12853
|
+
// src/commands/system/validate.ts
|
|
12652
12854
|
import { Command as Command34 } from "commander";
|
|
12855
|
+
import { existsSync as existsSync22, readFileSync as readFileSync11 } from "fs";
|
|
12856
|
+
import { homedir as homedir7 } from "os";
|
|
12857
|
+
import { join as join13 } from "path";
|
|
12858
|
+
async function checkConfigFile() {
|
|
12859
|
+
try {
|
|
12860
|
+
const configPath = getConfigPath();
|
|
12861
|
+
if (!existsSync22(configPath)) {
|
|
12862
|
+
return {
|
|
12863
|
+
ok: false,
|
|
12864
|
+
message: "Konfigurationsdatei nicht gefunden",
|
|
12865
|
+
suggestion: "shiva init um Projekt zu initialisieren"
|
|
12866
|
+
};
|
|
12867
|
+
}
|
|
12868
|
+
const content = readFileSync11(configPath, "utf-8");
|
|
12869
|
+
JSON.parse(content);
|
|
12870
|
+
return {
|
|
12871
|
+
ok: true,
|
|
12872
|
+
message: "Konfigurationsdatei OK"
|
|
12873
|
+
};
|
|
12874
|
+
} catch (error) {
|
|
12875
|
+
return {
|
|
12876
|
+
ok: false,
|
|
12877
|
+
message: "Konfigurationsdatei besch\xE4digt",
|
|
12878
|
+
suggestion: "shiva config reset um zur\xFCckzusetzen"
|
|
12879
|
+
};
|
|
12880
|
+
}
|
|
12881
|
+
}
|
|
12882
|
+
async function checkAuth() {
|
|
12883
|
+
const token = getToken();
|
|
12884
|
+
if (!token) {
|
|
12885
|
+
return {
|
|
12886
|
+
ok: false,
|
|
12887
|
+
message: "Nicht angemeldet",
|
|
12888
|
+
suggestion: "shiva login um dich anzumelden"
|
|
12889
|
+
};
|
|
12890
|
+
}
|
|
12891
|
+
return {
|
|
12892
|
+
ok: true,
|
|
12893
|
+
message: "Authentifiziert"
|
|
12894
|
+
};
|
|
12895
|
+
}
|
|
12896
|
+
async function checkClaude2() {
|
|
12897
|
+
if (!isClaudeInstalled()) {
|
|
12898
|
+
return {
|
|
12899
|
+
ok: false,
|
|
12900
|
+
message: "Claude Code nicht installiert",
|
|
12901
|
+
suggestion: "curl -fsSL https://claude.ai/install.sh | bash"
|
|
12902
|
+
};
|
|
12903
|
+
}
|
|
12904
|
+
return {
|
|
12905
|
+
ok: true,
|
|
12906
|
+
message: "Claude Code installiert"
|
|
12907
|
+
};
|
|
12908
|
+
}
|
|
12909
|
+
async function checkHooks() {
|
|
12910
|
+
try {
|
|
12911
|
+
const claudeDir = join13(homedir7(), ".claude");
|
|
12912
|
+
const settingsPath = join13(claudeDir, "settings.json");
|
|
12913
|
+
if (!existsSync22(settingsPath)) {
|
|
12914
|
+
return {
|
|
12915
|
+
ok: true,
|
|
12916
|
+
message: "Keine Hooks konfiguriert (optional)"
|
|
12917
|
+
};
|
|
12918
|
+
}
|
|
12919
|
+
const content = readFileSync11(settingsPath, "utf-8");
|
|
12920
|
+
const settings = JSON.parse(content);
|
|
12921
|
+
if (settings.hooks && Object.keys(settings.hooks).length > 0) {
|
|
12922
|
+
const hookCount = Object.values(settings.hooks).flat().length;
|
|
12923
|
+
return {
|
|
12924
|
+
ok: true,
|
|
12925
|
+
message: `${hookCount} Hook(s) konfiguriert`
|
|
12926
|
+
};
|
|
12927
|
+
}
|
|
12928
|
+
return {
|
|
12929
|
+
ok: true,
|
|
12930
|
+
message: "Keine Hooks konfiguriert (optional)"
|
|
12931
|
+
};
|
|
12932
|
+
} catch (error) {
|
|
12933
|
+
return {
|
|
12934
|
+
ok: false,
|
|
12935
|
+
message: "Hooks-Konfiguration fehlerhaft",
|
|
12936
|
+
suggestion: "shiva hook list um Hooks zu pr\xFCfen"
|
|
12937
|
+
};
|
|
12938
|
+
}
|
|
12939
|
+
}
|
|
12940
|
+
async function checkNetwork() {
|
|
12941
|
+
try {
|
|
12942
|
+
const controller = new AbortController();
|
|
12943
|
+
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
12944
|
+
const response = await fetch("https://api.shiva.li/health", {
|
|
12945
|
+
signal: controller.signal
|
|
12946
|
+
});
|
|
12947
|
+
clearTimeout(timeout);
|
|
12948
|
+
if (response.ok) {
|
|
12949
|
+
return {
|
|
12950
|
+
ok: true,
|
|
12951
|
+
message: "Server erreichbar"
|
|
12952
|
+
};
|
|
12953
|
+
}
|
|
12954
|
+
return {
|
|
12955
|
+
ok: false,
|
|
12956
|
+
message: `Server antwortet mit ${response.status}`,
|
|
12957
|
+
suggestion: "Sp\xE4ter erneut versuchen"
|
|
12958
|
+
};
|
|
12959
|
+
} catch (error) {
|
|
12960
|
+
return {
|
|
12961
|
+
ok: false,
|
|
12962
|
+
message: "Server nicht erreichbar",
|
|
12963
|
+
suggestion: "Internetverbindung pr\xFCfen"
|
|
12964
|
+
};
|
|
12965
|
+
}
|
|
12966
|
+
}
|
|
12967
|
+
async function checkProject() {
|
|
12968
|
+
const shivaDir = join13(process.cwd(), ".shiva");
|
|
12969
|
+
const claudeMd = join13(process.cwd(), "CLAUDE.md");
|
|
12970
|
+
if (!existsSync22(shivaDir)) {
|
|
12971
|
+
return {
|
|
12972
|
+
ok: false,
|
|
12973
|
+
message: "Kein SHIVA-Projekt",
|
|
12974
|
+
suggestion: "shiva init um Projekt zu initialisieren"
|
|
12975
|
+
};
|
|
12976
|
+
}
|
|
12977
|
+
if (!existsSync22(claudeMd)) {
|
|
12978
|
+
return {
|
|
12979
|
+
ok: false,
|
|
12980
|
+
message: "CLAUDE.md fehlt",
|
|
12981
|
+
suggestion: "shiva sync um CLAUDE.md zu generieren"
|
|
12982
|
+
};
|
|
12983
|
+
}
|
|
12984
|
+
return {
|
|
12985
|
+
ok: true,
|
|
12986
|
+
message: "Projekt konfiguriert"
|
|
12987
|
+
};
|
|
12988
|
+
}
|
|
12989
|
+
async function checkNodeVersion() {
|
|
12990
|
+
const version = process.version;
|
|
12991
|
+
const major = parseInt(version.slice(1).split(".")[0], 10);
|
|
12992
|
+
if (major < 18) {
|
|
12993
|
+
return {
|
|
12994
|
+
ok: false,
|
|
12995
|
+
message: `Node.js ${version} (min. v18 erforderlich)`,
|
|
12996
|
+
suggestion: "Node.js aktualisieren: https://nodejs.org"
|
|
12997
|
+
};
|
|
12998
|
+
}
|
|
12999
|
+
return {
|
|
13000
|
+
ok: true,
|
|
13001
|
+
message: `Node.js ${version}`
|
|
13002
|
+
};
|
|
13003
|
+
}
|
|
13004
|
+
var validateCommand = new Command34("validate").description("Konfiguration und System validieren").option("--json", "Ausgabe als JSON").action(async (options) => {
|
|
13005
|
+
const checks = [
|
|
13006
|
+
{ name: "Node.js", check: checkNodeVersion },
|
|
13007
|
+
{ name: "Konfiguration", check: checkConfigFile },
|
|
13008
|
+
{ name: "Authentifizierung", check: checkAuth },
|
|
13009
|
+
{ name: "Claude Code", check: checkClaude2 },
|
|
13010
|
+
{ name: "Hooks", check: checkHooks },
|
|
13011
|
+
{ name: "Netzwerk", check: checkNetwork },
|
|
13012
|
+
{ name: "Projekt", check: checkProject }
|
|
13013
|
+
];
|
|
13014
|
+
const results = [];
|
|
13015
|
+
let allPassed = true;
|
|
13016
|
+
if (!options.json) {
|
|
13017
|
+
log.header("SHIVA Configuration Check");
|
|
13018
|
+
log.newline();
|
|
13019
|
+
}
|
|
13020
|
+
for (const { name, check } of checks) {
|
|
13021
|
+
const result = await check();
|
|
13022
|
+
results.push({ name, result });
|
|
13023
|
+
if (!result.ok) {
|
|
13024
|
+
allPassed = false;
|
|
13025
|
+
}
|
|
13026
|
+
if (!options.json) {
|
|
13027
|
+
const icon = result.ok ? colors.green("\u2713") : colors.red("\u2717");
|
|
13028
|
+
console.log(` ${icon} ${name}: ${result.message}`);
|
|
13029
|
+
if (!result.ok && result.suggestion) {
|
|
13030
|
+
console.log(colors.dim(` \u2192 ${result.suggestion}`));
|
|
13031
|
+
}
|
|
13032
|
+
}
|
|
13033
|
+
}
|
|
13034
|
+
if (options.json) {
|
|
13035
|
+
console.log(
|
|
13036
|
+
JSON.stringify(
|
|
13037
|
+
{
|
|
13038
|
+
success: allPassed,
|
|
13039
|
+
checks: results.map(({ name, result }) => ({
|
|
13040
|
+
name,
|
|
13041
|
+
ok: result.ok,
|
|
13042
|
+
message: result.message,
|
|
13043
|
+
suggestion: result.suggestion
|
|
13044
|
+
}))
|
|
13045
|
+
},
|
|
13046
|
+
null,
|
|
13047
|
+
2
|
|
13048
|
+
)
|
|
13049
|
+
);
|
|
13050
|
+
} else {
|
|
13051
|
+
log.newline();
|
|
13052
|
+
if (allPassed) {
|
|
13053
|
+
log.success("Alle Checks bestanden!");
|
|
13054
|
+
} else {
|
|
13055
|
+
log.warn("Einige Checks fehlgeschlagen");
|
|
13056
|
+
}
|
|
13057
|
+
}
|
|
13058
|
+
process.exit(allPassed ? 0 : 1);
|
|
13059
|
+
});
|
|
13060
|
+
|
|
13061
|
+
// src/commands/advanced/docker.ts
|
|
13062
|
+
import { Command as Command35 } from "commander";
|
|
12653
13063
|
import ora21 from "ora";
|
|
12654
|
-
var dockerCommand = new
|
|
13064
|
+
var dockerCommand = new Command35("docker").description("Docker-Integration verwalten");
|
|
12655
13065
|
dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
|
|
12656
13066
|
log.brand();
|
|
12657
13067
|
log.header("Docker Status");
|
|
@@ -12881,7 +13291,7 @@ dockerCommand.action(() => {
|
|
|
12881
13291
|
});
|
|
12882
13292
|
|
|
12883
13293
|
// src/commands/advanced/workflow.ts
|
|
12884
|
-
import { Command as
|
|
13294
|
+
import { Command as Command36 } from "commander";
|
|
12885
13295
|
import * as fs13 from "fs";
|
|
12886
13296
|
import * as path14 from "path";
|
|
12887
13297
|
import * as os7 from "os";
|
|
@@ -12905,7 +13315,7 @@ var builtInWorkflows = {
|
|
|
12905
13315
|
]
|
|
12906
13316
|
}
|
|
12907
13317
|
};
|
|
12908
|
-
var workflowCommand = new
|
|
13318
|
+
var workflowCommand = new Command36("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
|
|
12909
13319
|
await listWorkflows();
|
|
12910
13320
|
});
|
|
12911
13321
|
workflowCommand.command("list").alias("ls").description("Verf\xFCgbare Workflows anzeigen").action(async () => {
|
|
@@ -13160,11 +13570,11 @@ async function executeStep(step) {
|
|
|
13160
13570
|
}
|
|
13161
13571
|
|
|
13162
13572
|
// src/commands/advanced/package.ts
|
|
13163
|
-
import { Command as
|
|
13573
|
+
import { Command as Command37 } from "commander";
|
|
13164
13574
|
import * as fs14 from "fs";
|
|
13165
13575
|
import inquirer12 from "inquirer";
|
|
13166
13576
|
import ora23 from "ora";
|
|
13167
|
-
var packageCommand = new
|
|
13577
|
+
var packageCommand = new Command37("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
|
|
13168
13578
|
listPackages();
|
|
13169
13579
|
});
|
|
13170
13580
|
packageCommand.command("list").description("Alle Packages auflisten").option("--json", "JSON Output").action((options) => {
|
|
@@ -13309,7 +13719,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
|
|
|
13309
13719
|
}
|
|
13310
13720
|
});
|
|
13311
13721
|
packageCommand.command("push").description("Packages in Cloud sichern").option("-n, --name <name>", "Nur ein bestimmtes Package").action(async (options) => {
|
|
13312
|
-
const { api: api2 } = await import("./client-
|
|
13722
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
13313
13723
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13314
13724
|
if (!isAuthenticated2()) {
|
|
13315
13725
|
log.error("Nicht angemeldet");
|
|
@@ -13355,7 +13765,7 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
|
|
|
13355
13765
|
}
|
|
13356
13766
|
});
|
|
13357
13767
|
packageCommand.command("pull").description("Packages aus Cloud laden").option("-f, --force", "Lokale Packages \xFCberschreiben").option("--json", "JSON Output").action(async (options) => {
|
|
13358
|
-
const { api: api2 } = await import("./client-
|
|
13768
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
13359
13769
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13360
13770
|
if (!isAuthenticated2()) {
|
|
13361
13771
|
log.error("Nicht angemeldet");
|
|
@@ -13417,7 +13827,7 @@ packageCommand.command("pull").description("Packages aus Cloud laden").option("-
|
|
|
13417
13827
|
}
|
|
13418
13828
|
});
|
|
13419
13829
|
packageCommand.command("sync").description("Packages mit Cloud synchronisieren").action(async () => {
|
|
13420
|
-
const { api: api2 } = await import("./client-
|
|
13830
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
13421
13831
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13422
13832
|
if (!isAuthenticated2()) {
|
|
13423
13833
|
log.error("Nicht angemeldet");
|
|
@@ -13470,7 +13880,7 @@ packageCommand.command("sync").description("Packages mit Cloud synchronisieren")
|
|
|
13470
13880
|
log.tree.item(`${localPackages.length + pulledCount} Packages total`);
|
|
13471
13881
|
});
|
|
13472
13882
|
packageCommand.command("cloud-delete <name>").description("Package aus Cloud l\xF6schen").action(async (name) => {
|
|
13473
|
-
const { api: api2 } = await import("./client-
|
|
13883
|
+
const { api: api2 } = await import("./client-RPSJP4Z5.js");
|
|
13474
13884
|
const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
|
|
13475
13885
|
if (!isAuthenticated2()) {
|
|
13476
13886
|
log.error("Nicht angemeldet");
|
|
@@ -13527,9 +13937,9 @@ function listPackages() {
|
|
|
13527
13937
|
}
|
|
13528
13938
|
|
|
13529
13939
|
// src/commands/advanced/sandbox.ts
|
|
13530
|
-
import { Command as
|
|
13940
|
+
import { Command as Command38 } from "commander";
|
|
13531
13941
|
import ora24 from "ora";
|
|
13532
|
-
var sandboxCommand = new
|
|
13942
|
+
var sandboxCommand = new Command38("sandbox").description("Sandbox-Management mit Cloud-Sync");
|
|
13533
13943
|
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) => {
|
|
13534
13944
|
const spinner = ora24("Lade Sandboxes...").start();
|
|
13535
13945
|
try {
|
|
@@ -13880,8 +14290,13 @@ sandboxCommand.command("delete <id>").description("Sandbox l\xF6schen").option("
|
|
|
13880
14290
|
});
|
|
13881
14291
|
|
|
13882
14292
|
// src/index.ts
|
|
13883
|
-
var program = new
|
|
13884
|
-
program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.7.
|
|
14293
|
+
var program = new Command39();
|
|
14294
|
+
program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.7.5").option("--debug", "Debug-Modus aktivieren").hook("preAction", (thisCommand) => {
|
|
14295
|
+
const opts = thisCommand.opts();
|
|
14296
|
+
if (opts.debug) {
|
|
14297
|
+
enableDebug();
|
|
14298
|
+
}
|
|
14299
|
+
});
|
|
13885
14300
|
program.addCommand(loginCommand);
|
|
13886
14301
|
program.addCommand(logoutCommand);
|
|
13887
14302
|
program.addCommand(sessionsCommand);
|
|
@@ -13924,6 +14339,7 @@ program.addCommand(packageCommand);
|
|
|
13924
14339
|
program.addCommand(sandboxCommand);
|
|
13925
14340
|
program.addCommand(userCommand);
|
|
13926
14341
|
program.addCommand(welcomeCommand);
|
|
14342
|
+
program.addCommand(validateCommand);
|
|
13927
14343
|
program.action(async () => {
|
|
13928
14344
|
if (needsOnboarding()) {
|
|
13929
14345
|
await runOnboarding();
|
|
@@ -14108,7 +14524,7 @@ async function showDashboard() {
|
|
|
14108
14524
|
const packageName = selected.data;
|
|
14109
14525
|
log.newline();
|
|
14110
14526
|
log.success(`Starte Package ${packageName}...`);
|
|
14111
|
-
const { getPackageLaunchConfig: getPackageLaunchConfig2 } = await import("./package-manager-
|
|
14527
|
+
const { getPackageLaunchConfig: getPackageLaunchConfig2 } = await import("./package-manager-UORON74F.js");
|
|
14112
14528
|
const launches = await getPackageLaunchConfig2(packageName);
|
|
14113
14529
|
if (launches.length > 0) {
|
|
14114
14530
|
await spawnProjects(launches, detectTerminal());
|
|
@@ -14195,5 +14611,27 @@ program.exitOverride((err) => {
|
|
|
14195
14611
|
}
|
|
14196
14612
|
process.exit(1);
|
|
14197
14613
|
});
|
|
14614
|
+
program.on("command:*", (operands) => {
|
|
14615
|
+
const unknown = operands[0];
|
|
14616
|
+
const allCommands = program.commands.map((c) => c.name());
|
|
14617
|
+
const suggestions = findSimilarCommands(unknown, allCommands);
|
|
14618
|
+
log.error(`Unbekannter Befehl: ${unknown}`);
|
|
14619
|
+
if (suggestions.length > 0) {
|
|
14620
|
+
log.newline();
|
|
14621
|
+
log.info("Meintest du vielleicht:");
|
|
14622
|
+
suggestions.forEach((s) => log.plain(` shiva ${s}`));
|
|
14623
|
+
}
|
|
14624
|
+
log.newline();
|
|
14625
|
+
log.dim("Hilfe: shiva --help");
|
|
14626
|
+
process.exit(1);
|
|
14627
|
+
});
|
|
14198
14628
|
migrateConfig();
|
|
14629
|
+
var args = process.argv.slice(2);
|
|
14630
|
+
if (args.length > 0 && !args[0].startsWith("-")) {
|
|
14631
|
+
const firstArg = args[0];
|
|
14632
|
+
const resolved = getCommandFromAlias(firstArg);
|
|
14633
|
+
if (resolved) {
|
|
14634
|
+
process.argv[2] = resolved;
|
|
14635
|
+
}
|
|
14636
|
+
}
|
|
14199
14637
|
program.parse();
|