kentutai 1.7.2 → 1.7.4

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.
@@ -1,45 +1,49 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- const { execSync } = require("child_process");
4
3
  const path = require("path");
5
4
  const fs = require("fs");
5
+ const { execSync } = require("child_process");
6
6
 
7
- const appDir = path.join(__dirname, "..", "app");
8
- const serverPath = path.join(appDir, "server.js");
9
- const nodeModulesDir = path.join(appDir, "node_modules");
7
+ const cliDir = path.resolve(__dirname, "..");
8
+ const appDir = path.join(cliDir, "app");
9
+ const tarball = path.join(cliDir, "kentutai-1.3.2.tgz");
10
10
 
11
- if (!fs.existsSync(serverPath)) {
12
- console.log("[kentutai] Standalone build not found. Skipping postinstall.");
11
+ if (fs.existsSync(path.join(appDir, "server.js"))) {
12
+ console.log("[kentutai] Standalone build already exists.");
13
13
  process.exit(0);
14
14
  }
15
15
 
16
- const nodeModulesExists = fs.existsSync(nodeModulesDir);
17
- const hasPackages = nodeModulesExists && fs.readdirSync(nodeModulesDir).length > 0;
18
-
19
- if (hasPackages) {
20
- console.log("[kentutai] Dependencies already installed.");
16
+ if (!fs.existsSync(tarball)) {
17
+ console.log("[kentutai] Tarball not found. Skipping extraction.");
21
18
  process.exit(0);
22
19
  }
23
20
 
24
- console.log("[kentutai] Installing runtime dependencies...");
21
+ console.log("[kentutai] Extracting standalone build...");
25
22
 
26
23
  try {
27
- const packageJson = path.join(appDir, "package.json");
28
- if (!fs.existsSync(packageJson)) {
29
- console.log("[kentutai] No package.json found. Skipping.");
30
- process.exit(0);
24
+ const tempDir = path.join(cliDir, ".kentutai-extract");
25
+ if (fs.existsSync(tempDir)) {
26
+ fs.rmSync(tempDir, { recursive: true, force: true });
27
+ }
28
+ fs.mkdirSync(tempDir, { recursive: true });
29
+
30
+ execSync(`tar -xzf "${tarball}" -C "${tempDir}"`, { stdio: "pipe" });
31
+
32
+ // Tarball structure: package/app/ contains server.js and node_modules
33
+ const extractedApp = path.join(tempDir, "package", "app");
34
+ if (fs.existsSync(path.join(extractedApp, "server.js"))) {
35
+ if (fs.existsSync(appDir)) {
36
+ fs.rmSync(appDir, { recursive: true, force: true });
37
+ }
38
+ fs.renameSync(extractedApp, appDir);
39
+ console.log("[kentutai] Standalone build extracted successfully!");
40
+ } else {
41
+ console.log("[kentutai] Could not find app/server.js in tarball.");
31
42
  }
32
43
 
33
- execSync("npm install --production --ignore-scripts", {
34
- cwd: appDir,
35
- stdio: "inherit",
36
- timeout: 120000
37
- });
38
-
39
- console.log("[kentutai] Dependencies installed successfully!");
44
+ fs.rmSync(tempDir, { recursive: true, force: true });
40
45
  } catch (err) {
41
- console.warn("[kentutai] Failed to install dependencies:", err.message);
42
- console.warn("[kentutai] Server may not work. Try: cd cli/app && npm install");
46
+ console.warn("[kentutai] Extraction failed:", err.message);
43
47
  }
44
48
 
45
49
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kentutai",
3
- "version": "1.7.2",
3
+ "version": "1.7.4",
4
4
  "description": "KentutAI - AI Router & Token Saver CLI",
5
5
  "private": false,
6
6
  "bin": {
@@ -334,99 +334,108 @@ export default function KeysTab() {
334
334
  </div>
335
335
 
336
336
  {/* RTK/Caveman Settings */}
337
- <div className="flex items-center gap-3 shrink-0 flex-wrap">
338
- <Select
339
- value={
340
- key.rtkEnabled === null
341
- ? ""
342
- : key.rtkEnabled
343
- ? "on"
344
- : "off"
345
- }
346
- onChange={(e) => {
347
- const val =
348
- e.target.value === ""
349
- ? null
350
- : e.target.value === "on";
351
- handlePatchKey(key.id, { rtkEnabled: val });
352
- }}
353
- placeholder={
354
- globalSettings
355
- ? `Use Global (${globalSettings.rtkEnabled !== false ? "On" : "Off"})`
356
- : "Use Global"
357
- }
358
- options={[
359
- {
360
- value: "",
361
- label: `Use Global${globalSettings ? ` (${globalSettings.rtkEnabled !== false ? "On" : "Off"})` : ""}`,
362
- },
363
- { value: "on", label: "Enabled" },
364
- { value: "off", label: "Disabled" },
365
- ]}
366
- className="min-w-[140px]"
367
- selectClassName="!py-1.5 !text-xs"
368
- title="RTK: Reduce input tokens for git/grep/ls/tree/logs"
369
- />
370
- <Select
371
- value={
372
- key.cavemanEnabled === null
373
- ? ""
374
- : key.cavemanEnabled
375
- ? "on"
376
- : "off"
377
- }
378
- onChange={(e) => {
379
- const val =
380
- e.target.value === ""
381
- ? null
382
- : e.target.value === "on";
383
- handlePatchKey(key.id, { cavemanEnabled: val });
384
- }}
385
- placeholder={
386
- globalSettings
387
- ? `Use Global (${globalSettings.cavemanEnabled ? "On" : "Off"})`
388
- : "Use Global"
389
- }
390
- options={[
391
- {
392
- value: "",
393
- label: `Use Global${globalSettings ? ` (${globalSettings.cavemanEnabled ? "On" : "Off"})` : ""}`,
394
- },
395
- { value: "on", label: "Enabled" },
396
- { value: "off", label: "Disabled" },
397
- ]}
398
- className="min-w-[140px]"
399
- selectClassName="!py-1.5 !text-xs"
400
- title="Caveman: Compress LLM output tokens"
401
- />
402
- {(key.cavemanEnabled === true ||
403
- (key.cavemanEnabled === null &&
404
- globalSettings?.cavemanEnabled)) && (
337
+ <div className="flex items-center gap-2 shrink-0 flex-wrap">
338
+ <div className="flex flex-col gap-0.5">
339
+ <span className="text-[10px] text-text-muted uppercase">RTK</span>
405
340
  <Select
406
- value={key.cavemanLevel ?? ""}
341
+ value={
342
+ key.rtkEnabled === null
343
+ ? ""
344
+ : key.rtkEnabled
345
+ ? "on"
346
+ : "off"
347
+ }
407
348
  onChange={(e) => {
408
- handlePatchKey(key.id, {
409
- cavemanLevel: e.target.value || null,
410
- });
349
+ const val =
350
+ e.target.value === ""
351
+ ? null
352
+ : e.target.value === "on";
353
+ handlePatchKey(key.id, { rtkEnabled: val });
411
354
  }}
412
355
  placeholder={
413
- globalSettings?.cavemanLevel
414
- ? `Use Global (${globalSettings.cavemanLevel})`
415
- : "Use Global (full)"
356
+ globalSettings
357
+ ? `Global (${globalSettings.rtkEnabled !== false ? "On" : "Off"})`
358
+ : "Global"
416
359
  }
417
360
  options={[
418
361
  {
419
362
  value: "",
420
- label: `Use Global${globalSettings?.cavemanLevel ? ` (${globalSettings.cavemanLevel})` : " (full)"}`,
363
+ label: `Global${globalSettings ? ` (${globalSettings.rtkEnabled !== false ? "On" : "Off"})` : ""}`,
421
364
  },
422
- { value: "lite", label: "Lite" },
423
- { value: "full", label: "Full" },
424
- { value: "ultra", label: "Ultra" },
365
+ { value: "on", label: "Enabled" },
366
+ { value: "off", label: "Disabled" },
425
367
  ]}
426
- className="min-w-[120px]"
368
+ className="min-w-[110px]"
427
369
  selectClassName="!py-1.5 !text-xs"
428
- title="Caveman compression level"
370
+ title="RTK: Reduce input tokens for git/grep/ls/tree/logs"
429
371
  />
372
+ </div>
373
+ <div className="flex flex-col gap-0.5">
374
+ <span className="text-[10px] text-text-muted uppercase">Caveman</span>
375
+ <Select
376
+ value={
377
+ key.cavemanEnabled === null
378
+ ? ""
379
+ : key.cavemanEnabled
380
+ ? "on"
381
+ : "off"
382
+ }
383
+ onChange={(e) => {
384
+ const val =
385
+ e.target.value === ""
386
+ ? null
387
+ : e.target.value === "on";
388
+ handlePatchKey(key.id, { cavemanEnabled: val });
389
+ }}
390
+ placeholder={
391
+ globalSettings
392
+ ? `Global (${globalSettings.cavemanEnabled ? "On" : "Off"})`
393
+ : "Global"
394
+ }
395
+ options={[
396
+ {
397
+ value: "",
398
+ label: `Global${globalSettings ? ` (${globalSettings.cavemanEnabled ? "On" : "Off"})` : ""}`,
399
+ },
400
+ { value: "on", label: "Enabled" },
401
+ { value: "off", label: "Disabled" },
402
+ ]}
403
+ className="min-w-[110px]"
404
+ selectClassName="!py-1.5 !text-xs"
405
+ title="Caveman: Compress LLM output tokens"
406
+ />
407
+ </div>
408
+ {(key.cavemanEnabled === true ||
409
+ (key.cavemanEnabled === null &&
410
+ globalSettings?.cavemanEnabled)) && (
411
+ <div className="flex flex-col gap-0.5">
412
+ <span className="text-[10px] text-text-muted uppercase">Level</span>
413
+ <Select
414
+ value={key.cavemanLevel ?? ""}
415
+ onChange={(e) => {
416
+ handlePatchKey(key.id, {
417
+ cavemanLevel: e.target.value || null,
418
+ });
419
+ }}
420
+ placeholder={
421
+ globalSettings?.cavemanLevel
422
+ ? `Global (${globalSettings.cavemanLevel})`
423
+ : "Global (full)"
424
+ }
425
+ options={[
426
+ {
427
+ value: "",
428
+ label: `Global${globalSettings?.cavemanLevel ? ` (${globalSettings.cavemanLevel})` : " (full)"}`,
429
+ },
430
+ { value: "lite", label: "Lite" },
431
+ { value: "full", label: "Full" },
432
+ { value: "ultra", label: "Ultra" },
433
+ ]}
434
+ className="min-w-[100px]"
435
+ selectClassName="!py-1.5 !text-xs"
436
+ title="Caveman compression level"
437
+ />
438
+ </div>
430
439
  )}
431
440
  </div>
432
441
 
@@ -387,18 +387,15 @@ export default function UserDetailPage() {
387
387
  >
388
388
  Set Custom Limits
389
389
  </Button>
390
- </div>
391
- )}
392
- </div>
393
-
394
- <div className="border-t border-border my-4"></div>
395
-
396
- {/* Subscription Package Section */}
397
- <div>
398
- <p className="text-sm font-medium text-text-main mb-3">Subscription Package</p>
390
+ </div>
391
+ )}
392
+ </Card>
399
393
 
394
+ {/* Subscription Package */}
395
+ <Card title="Subscription Package" icon="inventory_2" data-testid="package-card">
396
+ <div className="flex flex-col gap-4">
400
397
  {userPackage ? (
401
- <div className="flex flex-col gap-4">
398
+ <>
402
399
  <div className="flex items-center justify-between">
403
400
  <div className="flex items-center gap-3">
404
401
  <div className="p-2 rounded-lg bg-primary/10">
@@ -474,7 +471,7 @@ export default function UserDetailPage() {
474
471
  </span>
475
472
  )}
476
473
  </div>
477
- </div>
474
+ </>
478
475
  ) : (
479
476
  <div className="flex flex-col items-center justify-center py-8 text-center">
480
477
  <span className="material-symbols-outlined text-[48px] text-text-muted/30 mb-4">workspace_premium</span>