@kryvenaiofficial/kryven 0.2.2 → 0.2.3

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/cli.mjs CHANGED
@@ -37700,9 +37700,18 @@ function renderInline(s) {
37700
37700
  return s.replace(/`([^`]+)`/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1");
37701
37701
  }
37702
37702
 
37703
+ // src/tui/MessageList.tsx
37704
+ var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
37705
+ var MessageList = ({ message: m }) => {
37706
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
37707
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { bold: true, color: m.role === "user" ? "blue" : "green", children: m.role === "user" ? "you" : "kryven" }),
37708
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { paddingLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Markdown, { text: m.content ?? "" }) })
37709
+ ] });
37710
+ };
37711
+
37703
37712
  // src/tui/MarkdownStream.tsx
37704
37713
  var import_react22 = __toESM(require_react(), 1);
37705
- var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
37714
+ var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
37706
37715
  var LIVE_LINE_COUNT = 6;
37707
37716
  var MAX_FPS = 20;
37708
37717
  var FRAME_INTERVAL_MS = Math.floor(1e3 / MAX_FPS);
@@ -37780,55 +37789,21 @@ var MarkdownStream = ({
37780
37789
  }
37781
37790
  };
37782
37791
  }, []);
37783
- const { stableChunks, liveText } = (0, import_react22.useMemo)(() => {
37784
- if (!displayText) return { stableChunks: [], liveText: "" };
37785
- const { stable, live } = splitAtBoundary(displayText);
37786
- const chunks = [];
37787
- let carry = "";
37788
- if (stable) {
37789
- const paragraphs = stable.split(/\n{2,}/);
37790
- const carryIdx = paragraphs.length - 1;
37791
- carry = paragraphs[carryIdx] ?? "";
37792
- let offset = 0;
37793
- for (let i2 = 0; i2 < carryIdx; i2++) {
37794
- const para = paragraphs[i2];
37795
- if (para.trim()) {
37796
- chunks.push({ id: `s-${offset}`, text: para });
37797
- }
37798
- offset += para.length + 2;
37799
- }
37800
- }
37801
- const liveText2 = carry ? `${carry}
37802
- ${live}` : live;
37803
- return { stableChunks: chunks, liveText: liveText2 };
37804
- }, [displayText]);
37792
+ const liveText = (0, import_react22.useMemo)(
37793
+ () => displayText ? splitAtBoundary(displayText).live : "",
37794
+ [displayText]
37795
+ );
37805
37796
  const liveInsideFence = (0, import_react22.useMemo)(() => isInsideCodeFence(liveText), [liveText]);
37806
37797
  if (streamingText === void 0) return null;
37807
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", children: [
37808
- stableChunks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Static, { items: stableChunks, children: (chunk) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box_default, { flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Markdown, { text: chunk.text }) }, chunk.id) }),
37809
- liveText ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box_default, { flexDirection: "column", children: [
37810
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Markdown, { text: liveText }),
37811
- liveInsideFence && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Text, { color: "gray", dimColor: true, children: [
37798
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", children: [
37799
+ liveText ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", children: [
37800
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Markdown, { text: liveText }),
37801
+ liveInsideFence && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "gray", dimColor: true, children: [
37812
37802
  "```",
37813
37803
  " "
37814
37804
  ] })
37815
37805
  ] }) : null,
37816
- !done && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Text, { color: "magentaBright", dimColor: true, children: "\u258B" })
37817
- ] });
37818
- };
37819
-
37820
- // src/tui/MessageList.tsx
37821
- var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
37822
- var MessageList = ({ messages, streaming }) => {
37823
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
37824
- messages.map((m, i2) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
37825
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: true, color: m.role === "user" ? "blue" : "green", children: m.role === "user" ? "you" : "kryven" }),
37826
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { paddingLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Markdown, { text: m.content ?? "" }) })
37827
- ] }, i2)),
37828
- streaming !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
37829
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { bold: true, color: "green", children: "kryven" }),
37830
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { paddingLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(MarkdownStream, { streamingText: streaming }) })
37831
- ] })
37806
+ !done && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "magentaBright", dimColor: true, children: "\u258B" })
37832
37807
  ] });
37833
37808
  };
37834
37809
 
@@ -43637,7 +43612,7 @@ async function runBgAgent(id) {
43637
43612
  apiKey: cfg.apiKey,
43638
43613
  baseUrl: cfg.apiBaseUrl,
43639
43614
  clientType: "ide",
43640
- userAgent: `kryven-cli-bg/${"0.2.2"}`
43615
+ userAgent: `kryven-cli-bg/${"0.2.3"}`
43641
43616
  });
43642
43617
  const transcriptPath = join25(dir, "transcript.jsonl");
43643
43618
  const appendTranscript = async (m) => {
@@ -44571,6 +44546,47 @@ function handleVimKey(state, buffer, key) {
44571
44546
 
44572
44547
  // src/tui/REPL.tsx
44573
44548
  init_modes();
44549
+
44550
+ // src/utils/update-check.ts
44551
+ var PACKAGE = "@kryvenaiofficial/kryven";
44552
+ var REGISTRY_LATEST = `https://registry.npmjs.org/${PACKAGE}/latest`;
44553
+ var SEMVER = /^(\d+)\.(\d+)\.(\d+)/;
44554
+ function compareSemver(a2, b) {
44555
+ const pa = SEMVER.exec(a2);
44556
+ const pb = SEMVER.exec(b);
44557
+ if (!pa || !pb) return 0;
44558
+ for (let i2 = 1; i2 <= 3; i2++) {
44559
+ const da = Number(pa[i2]);
44560
+ const db = Number(pb[i2]);
44561
+ if (da !== db) return da - db;
44562
+ }
44563
+ return 0;
44564
+ }
44565
+ async function checkForUpdate(current, timeoutMs = 2500) {
44566
+ if (!current || !SEMVER.test(current)) return null;
44567
+ try {
44568
+ const ac = new AbortController();
44569
+ const timer = setTimeout(() => ac.abort(), timeoutMs);
44570
+ let res;
44571
+ try {
44572
+ res = await fetch(REGISTRY_LATEST, {
44573
+ signal: ac.signal,
44574
+ headers: { accept: "application/json" }
44575
+ });
44576
+ } finally {
44577
+ clearTimeout(timer);
44578
+ }
44579
+ if (!res.ok) return null;
44580
+ const j = await res.json();
44581
+ const latest = String(j?.version ?? "");
44582
+ if (!SEMVER.test(latest)) return null;
44583
+ return { updateAvailable: compareSemver(latest, current) > 0, latest };
44584
+ } catch {
44585
+ return null;
44586
+ }
44587
+ }
44588
+
44589
+ // src/tui/REPL.tsx
44574
44590
  var import_jsx_runtime36 = __toESM(require_jsx_runtime(), 1);
44575
44591
  import fs4 from "node:fs";
44576
44592
  import path8 from "node:path";
@@ -44622,6 +44638,7 @@ var REPL = ({
44622
44638
  const abortRef = (0, import_react27.useRef)(null);
44623
44639
  const permissionResolveRef = (0, import_react27.useRef)(null);
44624
44640
  const readPathsRef = (0, import_react27.useRef)(/* @__PURE__ */ new Set());
44641
+ const toolMetaRef = (0, import_react27.useRef)(/* @__PURE__ */ new Map());
44625
44642
  (0, import_react27.useEffect)(() => {
44626
44643
  if (isGuest) return;
44627
44644
  const cfg = resolveConfig();
@@ -44652,6 +44669,8 @@ var REPL = ({
44652
44669
  const [sessionTokens, setSessionTokens] = (0, import_react27.useState)(0);
44653
44670
  const [toolEntries, setToolEntries] = (0, import_react27.useState)([]);
44654
44671
  const [permissionReq, setPermissionReq] = (0, import_react27.useState)(null);
44672
+ const [staticGen, setStaticGen] = (0, import_react27.useState)(0);
44673
+ const prevCommittedCountRef = (0, import_react27.useRef)(0);
44655
44674
  const cfgRef = (0, import_react27.useRef)(resolveConfig());
44656
44675
  const vimEnabledRef = (0, import_react27.useRef)(cfgRef.current.vim === true);
44657
44676
  const vimRef = (0, import_react27.useRef)(initialVim());
@@ -44694,6 +44713,18 @@ var REPL = ({
44694
44713
  }, []);
44695
44714
  const toolsEnabled = (0, import_react27.useMemo)(() => listTools().length > 0, []);
44696
44715
  (0, import_react27.useEffect)(() => {
44716
+ void checkForUpdate("0.2.3").then((info) => {
44717
+ if (info?.updateAvailable) {
44718
+ setNotes((p) => [
44719
+ ...p,
44720
+ {
44721
+ kind: "system",
44722
+ text: `Update available: ${"0.2.3"} \u2192 ${info.latest}. Run \`kryven update\` to update.`
44723
+ }
44724
+ ]);
44725
+ }
44726
+ }).catch(() => {
44727
+ });
44697
44728
  void (async () => {
44698
44729
  if (resumeMessages?.length) {
44699
44730
  for (const m of resumeMessages) conversationRef.current.append(m);
@@ -44950,6 +44981,8 @@ var REPL = ({
44950
44981
  ts: Date.now()
44951
44982
  };
44952
44983
  conversationRef.current.append(assistant);
44984
+ setStreaming(null);
44985
+ forceRender((n2) => n2 + 1);
44953
44986
  void sessionRef.current.appendMessage(assistant);
44954
44987
  const remaining = res.kryven_guest?.messagesRemaining;
44955
44988
  if (typeof remaining === "number") {
@@ -44987,6 +45020,8 @@ var REPL = ({
44987
45020
  usage
44988
45021
  };
44989
45022
  conversationRef.current.append(assistant);
45023
+ setStreaming(null);
45024
+ forceRender((n2) => n2 + 1);
44990
45025
  void sessionRef.current.appendMessage(assistant);
44991
45026
  if (remoteSessionRef.current) {
44992
45027
  void remoteSessionRef.current.appendMessage(assistant).catch(() => {
@@ -45042,44 +45077,58 @@ var REPL = ({
45042
45077
  setStreaming(null);
45043
45078
  streamAcc = "";
45044
45079
  flushPersistableTurns();
45045
- setToolEntries((prev) => [
45046
- ...prev,
45047
- {
45080
+ {
45081
+ const entry = {
45048
45082
  callId: ev.call.id,
45049
45083
  toolName: ev.call.function.name,
45050
45084
  argsPreview: shortArgs(ev.call.function.arguments),
45051
45085
  status: "running",
45052
45086
  risk: ev.risk
45053
- }
45054
- ]);
45055
- break;
45056
- case "tool_result":
45057
- setToolEntries(
45058
- (prev) => prev.map(
45059
- (e) => e.callId === ev.callId ? { ...e, status: ev.ok ? "ok" : "error", output: ev.output, truncated: ev.truncated, renderHint: ev.renderHint } : e
45060
- )
45061
- );
45062
- {
45063
- const toolMsg = {
45064
- role: "tool",
45065
- content: ev.output,
45066
- tool_call_id: ev.callId,
45067
- ts: Date.now()
45068
45087
  };
45069
- void sessionRef.current.appendMessage(toolMsg);
45070
- if (remoteSessionRef.current) {
45071
- void remoteSessionRef.current.appendMessage(toolMsg).catch(() => {
45072
- });
45073
- }
45088
+ toolMetaRef.current.set(entry.callId, entry);
45089
+ setToolEntries((prev) => [...prev, entry]);
45074
45090
  }
45075
45091
  break;
45076
- case "tool_blocked":
45077
- setToolEntries(
45078
- (prev) => prev.map(
45079
- (e) => e.callId === ev.callId ? { ...e, status: "blocked", output: ev.reason } : e
45080
- )
45081
- );
45092
+ case "tool_result": {
45093
+ const finalStatus = ev.ok ? "ok" : "error";
45094
+ const prevMeta = toolMetaRef.current.get(ev.callId);
45095
+ toolMetaRef.current.set(ev.callId, {
45096
+ callId: ev.callId,
45097
+ toolName: prevMeta?.toolName ?? ev.toolName,
45098
+ argsPreview: prevMeta?.argsPreview ?? "",
45099
+ risk: prevMeta?.risk,
45100
+ status: finalStatus,
45101
+ output: ev.output,
45102
+ truncated: ev.truncated,
45103
+ renderHint: ev.renderHint
45104
+ });
45105
+ setToolEntries((prev) => prev.filter((e) => e.callId !== ev.callId));
45106
+ const toolMsg = {
45107
+ role: "tool",
45108
+ content: ev.output,
45109
+ tool_call_id: ev.callId,
45110
+ ts: Date.now()
45111
+ };
45112
+ void sessionRef.current.appendMessage(toolMsg);
45113
+ if (remoteSessionRef.current) {
45114
+ void remoteSessionRef.current.appendMessage(toolMsg).catch(() => {
45115
+ });
45116
+ }
45117
+ break;
45118
+ }
45119
+ case "tool_blocked": {
45120
+ const prevMeta = toolMetaRef.current.get(ev.callId);
45121
+ toolMetaRef.current.set(ev.callId, {
45122
+ callId: ev.callId,
45123
+ toolName: prevMeta?.toolName ?? ev.toolName,
45124
+ argsPreview: prevMeta?.argsPreview ?? "",
45125
+ risk: prevMeta?.risk,
45126
+ status: "blocked",
45127
+ output: ev.reason
45128
+ });
45129
+ setToolEntries((prev) => prev.filter((e) => e.callId !== ev.callId));
45082
45130
  break;
45131
+ }
45083
45132
  case "end_turn":
45084
45133
  endedNormally = true;
45085
45134
  setStreaming(null);
@@ -45115,6 +45164,7 @@ var REPL = ({
45115
45164
  logger.debug("tools turn ended without end_turn event");
45116
45165
  }
45117
45166
  };
45167
+ const convSize = conversationRef.current.size();
45118
45168
  const status = {
45119
45169
  model,
45120
45170
  mood,
@@ -45122,28 +45172,75 @@ var REPL = ({
45122
45172
  branch: git.branch,
45123
45173
  dirty: git.dirty,
45124
45174
  sessionTokens,
45125
- sessionMessages: conversationRef.current.size(),
45175
+ sessionMessages: convSize,
45126
45176
  costUsd: sessionCostUsd(conversationRef.current.all(), model),
45127
45177
  mode: getPermissionMode()
45128
45178
  };
45129
- return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", children: [
45130
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
45131
- KRYVEN_PIXEL_WORDMARK.map((line) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { color: "magentaBright", children: line }, line)),
45132
- /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Text, { bold: true, color: "cyan", children: [
45133
- "Kryven CLI ",
45134
- "0.2.2",
45135
- toolsEnabled ? " \xB7 tools enabled" : ""
45136
- ] }),
45137
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { color: "gray", children: "Powered by KRY-5.2 Extended \xB7 type /help \xB7 Ctrl+D to exit" })
45138
- ] }),
45139
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
45140
- MessageList,
45179
+ const staticItems = (0, import_react27.useMemo)(() => {
45180
+ const gen = `g${staticGen}`;
45181
+ const items = [
45141
45182
  {
45142
- messages: conversationRef.current.all().filter((m) => m.role !== "tool"),
45143
- streaming: streaming ?? void 0
45183
+ id: `${gen}-header`,
45184
+ node: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
45185
+ KRYVEN_PIXEL_WORDMARK.map((line) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { color: "magentaBright", children: line }, line)),
45186
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Text, { bold: true, color: "cyan", children: [
45187
+ "Kryven CLI ",
45188
+ "0.2.3",
45189
+ toolsEnabled ? " \xB7 tools enabled" : ""
45190
+ ] }),
45191
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { color: "gray", children: "Powered by KRY-5.2 Extended \xB7 type /help \xB7 Ctrl+D to exit" })
45192
+ ] })
45144
45193
  }
45145
- ),
45146
- /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToolCallList, { entries: toolEntries, collapseCompleted: false }),
45194
+ ];
45195
+ const all = conversationRef.current.all();
45196
+ const callInfo = /* @__PURE__ */ new Map();
45197
+ for (const mm of all) {
45198
+ if (mm.role === "assistant" && Array.isArray(mm.tool_calls)) {
45199
+ for (const c3 of mm.tool_calls) {
45200
+ callInfo.set(c3.id, {
45201
+ toolName: c3.function?.name ?? "tool",
45202
+ argsPreview: shortArgs(c3.function?.arguments ?? "")
45203
+ });
45204
+ }
45205
+ }
45206
+ }
45207
+ for (let i2 = 0; i2 < all.length; i2++) {
45208
+ const m = all[i2];
45209
+ if (m.role === "user") {
45210
+ items.push({ id: `${gen}-m${i2}`, node: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MessageList, { message: m }) });
45211
+ } else if (m.role === "assistant") {
45212
+ if (typeof m.content === "string" && m.content.trim().length > 0) {
45213
+ items.push({ id: `${gen}-m${i2}`, node: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MessageList, { message: m }) });
45214
+ }
45215
+ } else if (m.role === "tool") {
45216
+ const meta = m.tool_call_id ? toolMetaRef.current.get(m.tool_call_id) : void 0;
45217
+ const info = m.tool_call_id ? callInfo.get(m.tool_call_id) : void 0;
45218
+ const entry = meta ?? {
45219
+ callId: m.tool_call_id ?? `t${i2}`,
45220
+ toolName: info?.toolName ?? "tool",
45221
+ argsPreview: info?.argsPreview ?? "",
45222
+ status: "ok",
45223
+ output: typeof m.content === "string" ? m.content : ""
45224
+ };
45225
+ items.push({ id: `${gen}-t${i2}`, node: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToolCall, { ...entry }) });
45226
+ }
45227
+ }
45228
+ return items;
45229
+ }, [convSize, staticGen, toolsEnabled]);
45230
+ const committedCount = staticItems.length;
45231
+ (0, import_react27.useEffect)(() => {
45232
+ if (committedCount < prevCommittedCountRef.current) {
45233
+ setStaticGen((g) => g + 1);
45234
+ }
45235
+ prevCommittedCountRef.current = committedCount;
45236
+ }, [committedCount]);
45237
+ return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", children: [
45238
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Static, { items: staticItems, children: (item) => /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Box_default, { flexDirection: "column", children: item.node }, item.id) }, staticGen),
45239
+ streaming != null && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, children: [
45240
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { bold: true, color: "green", children: "kryven" }),
45241
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Box_default, { paddingLeft: 2, flexDirection: "column", children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MarkdownStream, { streamingText: streaming, done: !busy }) })
45242
+ ] }),
45243
+ /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ToolCallList, { entries: toolEntries }),
45147
45244
  permissionReq && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Box_default, { flexDirection: "column", marginBottom: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [
45148
45245
  /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(Text, { bold: true, children: "Permission required" }),
45149
45246
  /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(Text, { children: [
@@ -45467,7 +45564,7 @@ async function chatCommand(opts = {}) {
45467
45564
  client = new GuestKryvenClient({
45468
45565
  baseUrl: cfg.apiBaseUrl,
45469
45566
  shareFingerprint: cfg.shareFingerprint !== false,
45470
- userAgent: `kryven-cli/${"0.2.2"}`
45567
+ userAgent: `kryven-cli/${"0.2.3"}`
45471
45568
  });
45472
45569
  console.log(source_default.cyan("Guest mode \u2014 3 free prompts. Run `kryven login` for unlimited chat."));
45473
45570
  } else {
@@ -45475,7 +45572,7 @@ async function chatCommand(opts = {}) {
45475
45572
  apiKey: cfg.apiKey,
45476
45573
  baseUrl: cfg.apiBaseUrl,
45477
45574
  clientType: "ide",
45478
- userAgent: `kryven-cli/${"0.2.2"}`
45575
+ userAgent: `kryven-cli/${"0.2.3"}`
45479
45576
  });
45480
45577
  }
45481
45578
  let resumeMessages;
@@ -45559,6 +45656,38 @@ async function chatCommand(opts = {}) {
45559
45656
  await waitUntilExit();
45560
45657
  }
45561
45658
 
45659
+ // src/commands/update.ts
45660
+ init_execa();
45661
+
45662
+ // src/shims/version.ts
45663
+ var KRYVEN_VERSION = "0.2.3";
45664
+
45665
+ // src/commands/update.ts
45666
+ var PACKAGE2 = "@kryvenaiofficial/kryven";
45667
+ async function updateCommand() {
45668
+ console.log(source_default.bold(`Updating ${PACKAGE2} to the latest version\u2026`));
45669
+ console.log(source_default.dim(` current: ${KRYVEN_VERSION}`));
45670
+ try {
45671
+ await execa("npm", ["install", "-g", `${PACKAGE2}@latest`], { stdio: "inherit" });
45672
+ console.log(
45673
+ source_default.green(`
45674
+ \u2713 Update complete. Run `) + source_default.bold(`kryven --version`) + source_default.green(` to confirm, then start with `) + source_default.bold(`kryven`) + source_default.green(`.`)
45675
+ );
45676
+ } catch (err) {
45677
+ console.error(source_default.red(`
45678
+ \u2717 Update failed: ${err.message}`));
45679
+ console.error(
45680
+ source_default.yellow(
45681
+ `Update manually with:
45682
+ npm install -g ${PACKAGE2}@latest
45683
+ On macOS/Linux a global install may need sudo:
45684
+ sudo npm install -g ${PACKAGE2}@latest`
45685
+ )
45686
+ );
45687
+ process.exit(1);
45688
+ }
45689
+ }
45690
+
45562
45691
  // src/commands/skills.ts
45563
45692
  import { writeFile as writeFile11, mkdir as mkdir13 } from "node:fs/promises";
45564
45693
  import { existsSync as existsSync23 } from "node:fs";
@@ -45839,9 +45968,6 @@ async function bgWait(id, timeoutMs = 30 * 60 * 1e3) {
45839
45968
  process.exit(124);
45840
45969
  }
45841
45970
 
45842
- // src/shims/version.ts
45843
- var KRYVEN_VERSION = "0.2.2";
45844
-
45845
45971
  // src/main.tsx
45846
45972
  async function main(argv2) {
45847
45973
  const bgRunIdx = argv2.indexOf("--bg-run");
@@ -45863,6 +45989,9 @@ async function main(argv2) {
45863
45989
  program2.command("models").description("List models exposed by /v1/models").action(async () => {
45864
45990
  await modelsCommand();
45865
45991
  });
45992
+ program2.command("update").description("Update the Kryven CLI to the latest published version").action(async () => {
45993
+ await updateCommand();
45994
+ });
45866
45995
  program2.command("chat", { isDefault: true }).description("Launch the chat REPL (default subcommand)").argument("[prompt...]", "Optional inline prompt to seed the session").action(async (promptParts, _options, cmd) => {
45867
45996
  const opts = cmd.optsWithGlobals();
45868
45997
  const seed = promptParts && promptParts.length ? promptParts.join(" ") : void 0;
@@ -45912,13 +46041,13 @@ async function main(argv2) {
45912
46041
  var argv = process.argv.slice(2);
45913
46042
  var first = argv[0];
45914
46043
  if (first === "--version" || first === "-v" || first === "-V") {
45915
- const v = "0.2.2";
46044
+ const v = "0.2.3";
45916
46045
  process.stdout.write(v + "\n");
45917
46046
  process.exit(0);
45918
46047
  }
45919
46048
  if (first === "--help" || first === "-h") {
45920
46049
  process.stdout.write(
45921
- "Usage: kryven [command] [options]\n\nCommands:\n kryven Launch chat REPL in current directory\n kryven login Save your kry_sk_* API key\n kryven logout Remove stored key\n kryven status Show config + model availability\n kryven models List /v1/models\n\nOptions:\n -v, --version Print version\n -h, --help Show this help\n --api-key <key> Override stored key for this run\n --model <id> Override default model\n --mood <name> Override default mood\n --resume <id> Resume a prior session\n\nDocs: https://kryven.cc/docs/cli\n"
46050
+ "Usage: kryven [command] [options]\n\nCommands:\n kryven Launch chat REPL in current directory\n kryven login Save your kry_sk_* API key\n kryven logout Remove stored key\n kryven status Show config + model availability\n kryven models List /v1/models\n kryven update Update the CLI to the latest version\n\nOptions:\n -v, --version Print version\n -h, --help Show this help\n --api-key <key> Override stored key for this run\n --model <id> Override default model\n --mood <name> Override default mood\n --resume <id> Resume a prior session\n\nDocs: https://kryven.cc/docs/cli\n"
45922
46051
  );
45923
46052
  process.exit(0);
45924
46053
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kryvenaiofficial/kryven",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Kryven Agent CLI — terminal AI coding assistant powered by the Kryven platform.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  },
9
9
  "files": [
10
10
  "dist/cli.mjs",
11
+ "scripts/postinstall.cjs",
11
12
  "README.md",
12
13
  "LICENSE"
13
14
  ],
@@ -21,6 +22,7 @@
21
22
  "typecheck": "tsc --noEmit",
22
23
  "smoke:offline": "tsx scripts/smoke-offline.ts",
23
24
  "smoke:online": "tsx scripts/smoke-online.ts",
25
+ "postinstall": "node scripts/postinstall.cjs",
24
26
  "prepublishOnly": "npm run build && npm run smoke:offline"
25
27
  },
26
28
  "dependencies": {
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Post-install banner for the Kryven CLI.
4
+ *
5
+ * Shown only after a GLOBAL install (`npm install -g @kryvenaiofficial/kryven`)
6
+ * — the case the kryven.cc/agent install command uses. Scoped to global so the
7
+ * banner never spams users who pull the package in as a dependency or in CI.
8
+ *
9
+ * Bulletproof by design: any failure is swallowed and the process still exits 0
10
+ * so a cosmetic banner can never break `npm install`.
11
+ */
12
+ 'use strict';
13
+
14
+ try {
15
+ // npm sets npm_config_global=true for `-g` installs. yarn/pnpm globals also
16
+ // set it. If it's anything else (local dep install, CI), stay silent.
17
+ const isGlobal = String(process.env.npm_config_global || '').toLowerCase() === 'true';
18
+ // Allow forcing the banner for manual testing.
19
+ const forced = process.env.KRYVEN_FORCE_POSTINSTALL === '1';
20
+ if (!isGlobal && !forced) return;
21
+
22
+ // Only colorize when attached to a TTY that isn't explicitly NO_COLOR.
23
+ const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
24
+ const wrap = (code, s) => (useColor ? `\x1b[${code}m${s}\x1b[0m` : s);
25
+ const purple = (s) => wrap('38;5;141', s);
26
+ const bold = (s) => wrap('1', s);
27
+ const dim = (s) => wrap('2', s);
28
+ const green = (s) => wrap('32', s);
29
+
30
+ const out = [
31
+ '',
32
+ ' ' + purple('────────────────────────────────────────────'),
33
+ ' ' + green('✓') + ' ' + bold('Kryven CLI installed.'),
34
+ '',
35
+ ' Run ' + bold(purple('kryven')) + ' in your terminal to enable the CLI.',
36
+ ' ' + purple('────────────────────────────────────────────'),
37
+ '',
38
+ ' ' + bold('kryven') + ' ' + dim('start chatting + coding (3 free prompts)'),
39
+ ' ' + bold('kryven login') + ' ' + dim('save your API key (kry_sk_…)'),
40
+ ' ' + bold('kryven --help') + ' ' + dim('all commands'),
41
+ '',
42
+ ' ' + dim('Docs: https://kryven.cc/docs/cli'),
43
+ '',
44
+ ];
45
+ process.stdout.write(out.join('\n') + '\n');
46
+ } catch {
47
+ /* never fail an install over a banner */
48
+ }