@kyma-api/agent 0.1.2 → 0.1.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.
- package/dist/main.js +117 -39
- package/package.json +1 -1
- package/themes/kyma-dark.json +15 -8
package/dist/main.js
CHANGED
|
@@ -123,7 +123,7 @@ var KYMA_AGENT_DIR = join(KYMA_DIR, "agent");
|
|
|
123
123
|
var KYMA_AUTH_PATH = join(KYMA_AGENT_DIR, "auth.json");
|
|
124
124
|
var KYMA_SETTINGS_PATH = join(KYMA_AGENT_DIR, "settings.json");
|
|
125
125
|
var KYMA_ONBOARDED_PATH = join(KYMA_AGENT_DIR, ".onboarded");
|
|
126
|
-
var KYMA_BASE_URL = "https://kymaapi.com";
|
|
126
|
+
var KYMA_BASE_URL = process.env.KYMA_BASE_URL || "https://kymaapi.com";
|
|
127
127
|
|
|
128
128
|
// src/sdk/auth.ts
|
|
129
129
|
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
@@ -374,7 +374,8 @@ function ensureAgentDir() {
|
|
|
374
374
|
defaultModel: "qwen-3-32b",
|
|
375
375
|
quietStartup: true,
|
|
376
376
|
theme: "kyma-dark",
|
|
377
|
-
|
|
377
|
+
hideThinkingBlock: false,
|
|
378
|
+
defaultThinkingLevel: "low"
|
|
378
379
|
}, null, 2), { mode: 384 });
|
|
379
380
|
} else {
|
|
380
381
|
try {
|
|
@@ -396,8 +397,12 @@ function ensureAgentDir() {
|
|
|
396
397
|
settings.theme = "kyma-dark";
|
|
397
398
|
changed = true;
|
|
398
399
|
}
|
|
399
|
-
if (settings.
|
|
400
|
-
settings.
|
|
400
|
+
if (settings.defaultThinkingLevel !== "low") {
|
|
401
|
+
settings.defaultThinkingLevel = "low";
|
|
402
|
+
changed = true;
|
|
403
|
+
}
|
|
404
|
+
if (settings.hideThinkingBlock !== false) {
|
|
405
|
+
settings.hideThinkingBlock = false;
|
|
401
406
|
changed = true;
|
|
402
407
|
}
|
|
403
408
|
if (changed) {
|
|
@@ -507,7 +512,12 @@ async function createKymaSession(options) {
|
|
|
507
512
|
extensionFactories,
|
|
508
513
|
additionalExtensionPaths: [],
|
|
509
514
|
// no file-based extensions
|
|
510
|
-
additionalThemePaths: [KYMA_THEMES_DIR]
|
|
515
|
+
additionalThemePaths: [KYMA_THEMES_DIR],
|
|
516
|
+
appendSystemPrompt: [
|
|
517
|
+
"IMPORTANT: You are running inside Kyma, NOT pi. Never mention pi, Pi SDK, or pi documentation.",
|
|
518
|
+
"If the user asks about the tool they are using, say 'Kyma' (kymaapi.com).",
|
|
519
|
+
"Never reveal internal file paths or node_modules paths."
|
|
520
|
+
].join("\n")
|
|
511
521
|
}
|
|
512
522
|
});
|
|
513
523
|
const result = await createAgentSessionFromServices({
|
|
@@ -755,6 +765,7 @@ var kymaProviderFactory = (pi) => {
|
|
|
755
765
|
apiKey: "KYMA_API_KEY",
|
|
756
766
|
api: "openai-completions",
|
|
757
767
|
authHeader: true,
|
|
768
|
+
headers: { "X-Kyma-Think": "show" },
|
|
758
769
|
oauth: {
|
|
759
770
|
name: "Kyma",
|
|
760
771
|
login: loginKyma,
|
|
@@ -774,8 +785,9 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
774
785
|
sessionCost = 0;
|
|
775
786
|
sessionTokens = 0;
|
|
776
787
|
turnCount = 0;
|
|
777
|
-
pi.setThinkingLevel?.("off");
|
|
778
788
|
if (!ctx.hasUI) return;
|
|
789
|
+
ctx.ui.setHideThinkingBlock?.(false);
|
|
790
|
+
ctx.ui.setHiddenThinkingLabel?.("Thinking... (Ctrl+T to expand)");
|
|
779
791
|
const email = getKymaEmail();
|
|
780
792
|
const apiKey = getKymaApiKey();
|
|
781
793
|
const loggedIn = !!apiKey;
|
|
@@ -787,12 +799,47 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
787
799
|
} catch {
|
|
788
800
|
}
|
|
789
801
|
}
|
|
802
|
+
const repoName = ctx.cwd.replace(/^.*\//, "");
|
|
803
|
+
const modelId = ctx.model?.id || "qwen-3-32b";
|
|
790
804
|
ctx.ui.setHeader((_tui, theme) => ({
|
|
791
|
-
render(
|
|
792
|
-
const
|
|
793
|
-
const
|
|
794
|
-
|
|
795
|
-
|
|
805
|
+
render(width) {
|
|
806
|
+
const strip = (s) => s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
807
|
+
const truncate = (s, maxW2) => {
|
|
808
|
+
let visible = 0;
|
|
809
|
+
let i = 0;
|
|
810
|
+
while (i < s.length && visible < maxW2) {
|
|
811
|
+
if (s[i] === "\x1B") {
|
|
812
|
+
const end = s.indexOf("m", i);
|
|
813
|
+
if (end !== -1) {
|
|
814
|
+
i = end + 1;
|
|
815
|
+
continue;
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
visible++;
|
|
819
|
+
i++;
|
|
820
|
+
}
|
|
821
|
+
return i < s.length ? s.slice(0, i) : s;
|
|
822
|
+
};
|
|
823
|
+
const maxW = Math.max(width, 30);
|
|
824
|
+
const logo = theme.bold(theme.fg("accent", ` \u03A8 kyma`)) + theme.fg("dim", ` v${VERSION}`);
|
|
825
|
+
const url = ` https://kymaapi.com`;
|
|
826
|
+
const accountStr = loggedIn ? `${email || "connected"}${balanceStr ? ` \xB7 ${balanceStr}` : ""}` : "not connected";
|
|
827
|
+
const dirLine = `~/${repoName}`;
|
|
828
|
+
const connectLine = loggedIn ? null : `${theme.bold("/connect")} to sign in`;
|
|
829
|
+
const contentLines = [accountStr, dirLine];
|
|
830
|
+
if (connectLine) contentLines.push(connectLine);
|
|
831
|
+
const visibleWidths = contentLines.map((l) => strip(l).length);
|
|
832
|
+
const contentMax = Math.max(...visibleWidths);
|
|
833
|
+
const innerW = Math.min(maxW - 4, Math.max(contentMax + 4, 24));
|
|
834
|
+
const boxTop = theme.fg("dim", ` \u256D${"\u2500".repeat(innerW)}\u256E`);
|
|
835
|
+
const boxBot = theme.fg("dim", ` \u2570${"\u2500".repeat(innerW)}\u256F`);
|
|
836
|
+
const boxRow = (s) => {
|
|
837
|
+
const visLen = strip(s).length;
|
|
838
|
+
const pad = Math.max(0, innerW - visLen - 4);
|
|
839
|
+
const row = theme.fg("dim", " \u2502") + ` ${s}${" ".repeat(pad)} ` + theme.fg("dim", "\u2502");
|
|
840
|
+
return truncate(row, maxW);
|
|
841
|
+
};
|
|
842
|
+
return [truncate(logo, maxW), truncate(url, maxW), boxTop, ...contentLines.map(boxRow), boxBot];
|
|
796
843
|
},
|
|
797
844
|
invalidate() {
|
|
798
845
|
}
|
|
@@ -832,9 +879,9 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
832
879
|
const freshLogin = !!process.env.KYMA_FRESH_LOGIN;
|
|
833
880
|
delete process.env.KYMA_FRESH_LOGIN;
|
|
834
881
|
if (loggedIn && isOnboarded && !freshLogin) {
|
|
835
|
-
const
|
|
882
|
+
const modelId2 = ctx.model?.id || "qwen-3-32b";
|
|
836
883
|
ctx.ui.setWidget?.("kyma-hint", [
|
|
837
|
-
` ${
|
|
884
|
+
` ${modelId2} \xB7 /models to switch \xB7 /help for commands`
|
|
838
885
|
], { placement: "aboveEditor" });
|
|
839
886
|
}
|
|
840
887
|
});
|
|
@@ -860,9 +907,6 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
860
907
|
if (turnCount === 1 && ctx.hasUI) {
|
|
861
908
|
ctx.ui.setWidget?.("kyma-hint", void 0);
|
|
862
909
|
}
|
|
863
|
-
if (ctx.hasUI) {
|
|
864
|
-
ctx.ui.setStatus("kyma-cost", `$${sessionCost.toFixed(4)} \xB7 ${formatTokens(sessionTokens)} tokens`);
|
|
865
|
-
}
|
|
866
910
|
}
|
|
867
911
|
if (!ctx.hasUI || postLoginShown) return;
|
|
868
912
|
const nowLoggedIn = !!getKymaApiKey();
|
|
@@ -870,25 +914,12 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
870
914
|
wasLoggedIn = true;
|
|
871
915
|
postLoginShown = true;
|
|
872
916
|
const postKey = getKymaApiKey();
|
|
873
|
-
const postEmail = getKymaEmail();
|
|
917
|
+
const postEmail = getKymaEmail() || "connected";
|
|
874
918
|
try {
|
|
875
919
|
const bal = await kymaApi("/v1/credits/balance", postKey);
|
|
876
|
-
ctx.ui.notify(`Authorized \xB7 ${postEmail} \xB7 $${bal.balance.toFixed(2)}`, "info");
|
|
920
|
+
ctx.ui.notify(`Authorized \xB7 ${postEmail} \xB7 $${bal.balance.toFixed(2)} \u2014 /mode to switch`, "info");
|
|
877
921
|
} catch {
|
|
878
|
-
ctx.ui.notify(`Authorized \xB7 ${postEmail}`, "info");
|
|
879
|
-
}
|
|
880
|
-
const modeOptions = [...MODE_TO_MODEL.entries()].map(
|
|
881
|
-
([mode, m]) => `${mode.padEnd(12)} ${m.name.padEnd(20)} ${m.tag}`
|
|
882
|
-
);
|
|
883
|
-
modeOptions.push("Keep default (fast)");
|
|
884
|
-
const modeChoice = await ctx.ui.select("Choose a mode for this session", modeOptions);
|
|
885
|
-
if (modeChoice && !modeChoice.startsWith("Keep")) {
|
|
886
|
-
const modeName = modeChoice.split(/\s+/)[0];
|
|
887
|
-
const modeModel = MODE_TO_MODEL.get(modeName);
|
|
888
|
-
if (modeModel) {
|
|
889
|
-
const ok = await pi.setModel(toRuntimeModel(modeModel, `${KYMA_BASE_URL}/v1`));
|
|
890
|
-
if (ok) ctx.ui.notify(`Mode: ${modeName} \u2192 ${modeModel.name}`, "info");
|
|
891
|
-
}
|
|
922
|
+
ctx.ui.notify(`Authorized \xB7 ${postEmail} \u2014 /mode to switch`, "info");
|
|
892
923
|
}
|
|
893
924
|
}
|
|
894
925
|
});
|
|
@@ -1160,7 +1191,7 @@ var kymaRuntimeFactory = (pi) => {
|
|
|
1160
1191
|
}
|
|
1161
1192
|
});
|
|
1162
1193
|
pi.registerCommand("connect", {
|
|
1163
|
-
description: "
|
|
1194
|
+
description: "Sign in to your Kyma account",
|
|
1164
1195
|
async handler(_args, ctx) {
|
|
1165
1196
|
if (getKymaApiKey()) {
|
|
1166
1197
|
const email = getKymaEmail();
|
|
@@ -1199,17 +1230,19 @@ URL: ${url}`, "info");
|
|
|
1199
1230
|
"Kyma Commands",
|
|
1200
1231
|
DIV,
|
|
1201
1232
|
"",
|
|
1202
|
-
" /connect
|
|
1233
|
+
" /connect Sign in to Kyma",
|
|
1203
1234
|
" /disconnect Sign out",
|
|
1204
1235
|
" /models Browse and switch models",
|
|
1205
1236
|
" /mode Switch model by task type",
|
|
1206
|
-
" /status Account, credits,
|
|
1237
|
+
" /status Account, credits, diagnostics",
|
|
1207
1238
|
" /balance Credits and rate limits",
|
|
1208
1239
|
" /usage Session cost and tokens",
|
|
1209
1240
|
" /upgrade View tiers and upgrade",
|
|
1210
1241
|
" /dashboard Open dashboard in browser",
|
|
1211
1242
|
" /billing Open billing page",
|
|
1212
1243
|
" /feedback Report issues or give feedback",
|
|
1244
|
+
" /clear Clear the screen",
|
|
1245
|
+
" /exit Exit kyma",
|
|
1213
1246
|
" /help Show this help",
|
|
1214
1247
|
"",
|
|
1215
1248
|
"Keyboard",
|
|
@@ -1223,25 +1256,37 @@ URL: ${url}`, "info");
|
|
|
1223
1256
|
].join("\n"), "info");
|
|
1224
1257
|
}
|
|
1225
1258
|
});
|
|
1259
|
+
pi.registerCommand("exit", {
|
|
1260
|
+
description: "Exit kyma",
|
|
1261
|
+
async handler(_args, _ctx) {
|
|
1262
|
+
process.exit(0);
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1226
1265
|
pi.registerCommand("disconnect", {
|
|
1227
1266
|
description: "Sign out of Kyma",
|
|
1228
1267
|
async handler(_args, ctx) {
|
|
1229
1268
|
const apiKey = getKymaApiKey();
|
|
1230
1269
|
if (!apiKey) {
|
|
1231
|
-
ctx.ui.notify("Not
|
|
1270
|
+
ctx.ui.notify("Not signed in. Run /connect to sign in.", "info");
|
|
1232
1271
|
return;
|
|
1233
1272
|
}
|
|
1234
1273
|
if (process.env.KYMA_API_KEY) {
|
|
1235
|
-
ctx.ui.notify("Cannot
|
|
1274
|
+
ctx.ui.notify("Cannot sign out: using KYMA_API_KEY environment variable.", "warning");
|
|
1236
1275
|
return;
|
|
1237
1276
|
}
|
|
1238
1277
|
const email = getKymaEmail();
|
|
1239
|
-
const confirm = await ctx.ui.confirm("
|
|
1278
|
+
const confirm = await ctx.ui.confirm("Sign out", `Sign out from ${email}?`);
|
|
1240
1279
|
if (!confirm) return;
|
|
1241
1280
|
clearKymaCredentials();
|
|
1242
1281
|
wasLoggedIn = false;
|
|
1243
1282
|
postLoginShown = false;
|
|
1244
|
-
ctx.ui.notify("
|
|
1283
|
+
ctx.ui.notify("Signed out. Run /connect to sign in again.", "info");
|
|
1284
|
+
}
|
|
1285
|
+
});
|
|
1286
|
+
pi.registerCommand("clear", {
|
|
1287
|
+
description: "Clear the screen",
|
|
1288
|
+
async handler(_args, ctx) {
|
|
1289
|
+
process.stdout.write("\x1B[2J\x1B[H");
|
|
1245
1290
|
}
|
|
1246
1291
|
});
|
|
1247
1292
|
};
|
|
@@ -1336,6 +1381,27 @@ function parseArgs(argv) {
|
|
|
1336
1381
|
}
|
|
1337
1382
|
return result;
|
|
1338
1383
|
}
|
|
1384
|
+
async function checkAndUpdate() {
|
|
1385
|
+
try {
|
|
1386
|
+
const res = await fetch("https://registry.npmjs.org/@kyma-api/agent/latest", {
|
|
1387
|
+
signal: AbortSignal.timeout(3e3)
|
|
1388
|
+
});
|
|
1389
|
+
if (!res.ok) return false;
|
|
1390
|
+
const data = await res.json();
|
|
1391
|
+
const latest = data.version;
|
|
1392
|
+
if (!latest || latest === VERSION2) return false;
|
|
1393
|
+
const parse = (v) => v.split(".").map(Number);
|
|
1394
|
+
const [cM, cm, cp] = parse(VERSION2);
|
|
1395
|
+
const [lM, lm, lp] = parse(latest);
|
|
1396
|
+
if (lM < cM || lM === cM && lm < cm || lM === cM && lm === cm && lp <= cp) return false;
|
|
1397
|
+
console.log(` ${term.dim(`Updating kyma v${VERSION2} \u2192 v${latest}...`)}`);
|
|
1398
|
+
execSync("npm install -g @kyma-api/agent@latest", { stdio: "ignore", timeout: 6e4 });
|
|
1399
|
+
console.log(` ${term.dim(`Updated to v${latest}. Restarting...`)}`);
|
|
1400
|
+
return true;
|
|
1401
|
+
} catch {
|
|
1402
|
+
return false;
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1339
1405
|
async function main(argv) {
|
|
1340
1406
|
const parsed = parseArgs(argv);
|
|
1341
1407
|
if (parsed.help) {
|
|
@@ -1349,6 +1415,18 @@ async function main(argv) {
|
|
|
1349
1415
|
if (parsed.verbose || process.env.KYMA_DEBUG === "1") {
|
|
1350
1416
|
process.env.KYMA_VERBOSE = "1";
|
|
1351
1417
|
}
|
|
1418
|
+
if (!process.env.KYMA_SKIP_UPDATE) {
|
|
1419
|
+
const updated = await checkAndUpdate();
|
|
1420
|
+
if (updated) {
|
|
1421
|
+
const { spawn } = await import("child_process");
|
|
1422
|
+
const child = spawn("kyma", process.argv.slice(2), {
|
|
1423
|
+
stdio: "inherit",
|
|
1424
|
+
env: { ...process.env, KYMA_SKIP_UPDATE: "1" }
|
|
1425
|
+
});
|
|
1426
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
1427
|
+
return;
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1352
1430
|
ensureAgentDir();
|
|
1353
1431
|
await runOnboarding();
|
|
1354
1432
|
if (process.env.KYMA_VERBOSE) {
|
package/package.json
CHANGED
package/themes/kyma-dark.json
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
"accent": "#C9A84C",
|
|
6
6
|
"accentLight": "#DDBF6F",
|
|
7
7
|
"accentSoft": "#A89060",
|
|
8
|
+
"teal": "#7DCFCF",
|
|
9
|
+
"purple": "#B4A7D6",
|
|
8
10
|
"green": "#00B894",
|
|
9
11
|
"red": "#E17055",
|
|
10
12
|
"yellow": "#FDCB6E",
|
|
@@ -30,7 +32,7 @@
|
|
|
30
32
|
"muted": "gray",
|
|
31
33
|
"dim": "dimGray",
|
|
32
34
|
"text": "",
|
|
33
|
-
"thinkingText": "
|
|
35
|
+
"thinkingText": "dimGray",
|
|
34
36
|
|
|
35
37
|
"selectedBg": "selectedBg",
|
|
36
38
|
"userMessageBg": "userMsgBg",
|
|
@@ -42,12 +44,12 @@
|
|
|
42
44
|
"toolSuccessBg": "toolSuccessBg",
|
|
43
45
|
"toolErrorBg": "toolErrorBg",
|
|
44
46
|
"toolTitle": "",
|
|
45
|
-
"toolOutput": "
|
|
47
|
+
"toolOutput": "#C8CCD8",
|
|
46
48
|
|
|
47
|
-
"mdHeading": "#
|
|
48
|
-
"mdLink": "
|
|
49
|
+
"mdHeading": "#F0E4A8",
|
|
50
|
+
"mdLink": "teal",
|
|
49
51
|
"mdLinkUrl": "dimGray",
|
|
50
|
-
"mdCode": "
|
|
52
|
+
"mdCode": "teal",
|
|
51
53
|
"mdCodeBlock": "gray",
|
|
52
54
|
"mdCodeBlockBorder": "dimGray",
|
|
53
55
|
"mdQuote": "gray",
|
|
@@ -60,12 +62,12 @@
|
|
|
60
62
|
"toolDiffContext": "gray",
|
|
61
63
|
|
|
62
64
|
"syntaxComment": "#6A9955",
|
|
63
|
-
"syntaxKeyword": "
|
|
65
|
+
"syntaxKeyword": "purple",
|
|
64
66
|
"syntaxFunction": "#E2C87A",
|
|
65
67
|
"syntaxVariable": "#C8BFA0",
|
|
66
68
|
"syntaxString": "#9BE9A8",
|
|
67
69
|
"syntaxNumber": "#B5CEA8",
|
|
68
|
-
"syntaxType": "
|
|
70
|
+
"syntaxType": "teal",
|
|
69
71
|
"syntaxOperator": "#D4D4D4",
|
|
70
72
|
"syntaxPunctuation": "#D4D4D4",
|
|
71
73
|
|
|
@@ -76,7 +78,12 @@
|
|
|
76
78
|
"thinkingHigh": "#8B7A5F",
|
|
77
79
|
"thinkingXhigh": "accentSoft",
|
|
78
80
|
|
|
79
|
-
"bashMode": "green"
|
|
81
|
+
"bashMode": "green",
|
|
82
|
+
|
|
83
|
+
"modeCode": "#5B9CF5",
|
|
84
|
+
"modeReason": "#B4A7D6",
|
|
85
|
+
"modeFast": "#00B894",
|
|
86
|
+
"modeCreative": "#E17055"
|
|
80
87
|
},
|
|
81
88
|
"export": {
|
|
82
89
|
"pageBg": "#13141C",
|