@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 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
- thinkingLevel: "off"
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.thinkingLevel !== "off") {
400
- settings.thinkingLevel = "off";
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(_width) {
792
- const logo = theme.bold(theme.fg("accent", " kyma"));
793
- const tagline = theme.fg("dim", " one account \xB7 many models \xB7 kymaapi.com");
794
- const accountLine = loggedIn ? theme.fg("dim", ` ${email}${balanceStr ? ` \xB7 ${balanceStr}` : ""} \xB7 /models`) : theme.fg("dim", " not connected \xB7 /connect");
795
- return [logo, tagline, accountLine];
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 modelId = ctx.model?.id || "qwen-3-32b";
882
+ const modelId2 = ctx.model?.id || "qwen-3-32b";
836
883
  ctx.ui.setWidget?.("kyma-hint", [
837
- ` ${modelId} \xB7 /models to switch \xB7 /help for commands`
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: "Connect your Kyma account",
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 Connect your Kyma account",
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, and diagnostics",
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 connected. Run /connect to sign in.", "info");
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 disconnect: using KYMA_API_KEY environment variable.", "warning");
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("Disconnect", `Sign out from ${email}?`);
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("Disconnected. Run /connect to sign in again.", "info");
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kyma-api/agent",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Kyma coding agent — one account, many models. AI-powered coding assistant backed by Kyma API.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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": "darkGray",
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": "gray",
47
+ "toolOutput": "#C8CCD8",
46
48
 
47
- "mdHeading": "#E8D48B",
48
- "mdLink": "accentLight",
49
+ "mdHeading": "#F0E4A8",
50
+ "mdLink": "teal",
49
51
  "mdLinkUrl": "dimGray",
50
- "mdCode": "accent",
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": "#D4B96A",
65
+ "syntaxKeyword": "purple",
64
66
  "syntaxFunction": "#E2C87A",
65
67
  "syntaxVariable": "#C8BFA0",
66
68
  "syntaxString": "#9BE9A8",
67
69
  "syntaxNumber": "#B5CEA8",
68
- "syntaxType": "#8DBAB2",
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",