kritya 0.8.30-beta → 0.8.31-beta

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/index.js CHANGED
@@ -316,6 +316,8 @@ async function promptApiKeySetup(providerName, envVarName) {
316
316
  async function main() {
317
317
  const config = loadConfig();
318
318
  const privacyMode = args.privacy || privacyModeFor(config);
319
+ // The ASCII banner renders on every launch regardless — this only decides
320
+ // whether to also show the first-run "Try asking:" hints.
319
321
  const firstLaunch = !isBannerSeen(workspace);
320
322
  if (!isAiDisclosureShown(workspace)) {
321
323
  await showAiDisclosureNotice();
@@ -4,9 +4,13 @@ import { CONFIG_DIR } from "../config/config.js";
4
4
  import { hardenWindowsDir } from "../config/winAcl.js";
5
5
  import { debugLog } from "../config/debug.js";
6
6
  /**
7
- * Tracks which workspaces have already shown the full ASCII banner once, so
8
- * repeat launches (which cost real vertical space in a terminal) can fall
9
- * back to a compact one-line header instead. Same shape and persistence
7
+ * Tracks which workspaces have already been opened once.
8
+ *
9
+ * The full ASCII banner itself no longer consults this — it renders on every
10
+ * launch, because the compact one-line fallback it used to select made repeat
11
+ * launches look broken. What remains gated on it is the first-run
12
+ * "Try asking:" hint block in App.tsx, which is genuine onboarding text and
13
+ * would be noise on every subsequent launch. Same shape and persistence
10
14
  * pattern as aiDisclosure.ts's ai-disclosure.json.
11
15
  */
12
16
  const BANNER_FILE = path.join(CONFIG_DIR, "banner-seen.json");
@@ -22,11 +26,11 @@ function loadStore(storeFile) {
22
26
  return {};
23
27
  }
24
28
  }
25
- /** Whether the full ASCII banner has already been shown for this workspace. */
29
+ /** Whether this workspace has been opened before (drives the first-run hints). */
26
30
  export function isBannerSeen(workspace, storeFile = BANNER_FILE) {
27
31
  return typeof loadStore(storeFile)[path.resolve(workspace)] === "string";
28
32
  }
29
- /** Record that the full ASCII banner has been shown for this workspace, now. */
33
+ /** Record that this workspace has been opened, now. */
30
34
  export function markBannerSeen(workspace, storeFile = BANNER_FILE) {
31
35
  const store = loadStore(storeFile);
32
36
  store[path.resolve(workspace)] = new Date().toISOString();
package/dist/ui/App.js CHANGED
@@ -123,7 +123,6 @@ export function App({ agent, workspace, modelRef, providerRef, config, resumedCo
123
123
  resumeSessions,
124
124
  refreshFileList,
125
125
  onSwitchClient,
126
- firstLaunch,
127
126
  });
128
127
  useEffect(() => {
129
128
  onRequestPermissionReady?.(requestPermission);
package/dist/ui/Banner.js CHANGED
@@ -41,27 +41,37 @@ function letterOffsets(text, pixelLen) {
41
41
  function letterWidth(ch, pixelLen) {
42
42
  return (GLYPHS[ch] ?? GLYPHS["-"])[0].length * pixelLen;
43
43
  }
44
- // Vertical gradient: cyan at the top fading into NVIDIA green.
44
+ // The banner's palette: cyan at the top of the glyphs fading into NVIDIA green.
45
45
  const TOP_RGB = [0x00, 0xd9, 0xff];
46
46
  const BOTTOM_RGB = [0x76, 0xb9, 0x00];
47
- function rowColor(row) {
48
- const t = row / (ROWS - 1);
47
+ /** One step of the cyan→green ramp, where t=0 is the cyan end and t=1 the green end. */
48
+ function ramp(t) {
49
49
  const [r, g, b] = TOP_RGB.map((c, i) => Math.round(c + (BOTTOM_RGB[i] - c) * t));
50
50
  return `#${[r, g, b].map((c) => c.toString(16).padStart(2, "0")).join("")}`;
51
51
  }
52
+ function rowColor(row) {
53
+ return ramp(row / (ROWS - 1));
54
+ }
55
+ /**
56
+ * The tagline walks the glyphs' own cyan→green ramp, but left-to-right instead
57
+ * of top-to-bottom, so it reads as the bottom edge of the same object rather
58
+ * than an unrelated third colour. Ink has no text gradient, so this is applied
59
+ * one character at a time.
60
+ */
61
+ export function sweepColor(index, length) {
62
+ return ramp(length <= 1 ? 0 : index / (length - 1));
63
+ }
52
64
  const BETA_LABEL = "beta";
53
65
  /** Product tagline shown under the banner on launch. */
54
66
  export const TAGLINE = "Superintelligence at your command line";
55
- export function Banner({ tagline, subtitle, compact, }) {
56
- if (compact) {
57
- return (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: subtitle }) }));
58
- }
67
+ export function Banner({ tagline, subtitle }) {
59
68
  const columns = terminalColumns(process.stdout);
60
69
  const wide = bannerLines("KRITYA", "░░");
61
70
  const narrow = bannerLines("KRITYA", "░");
62
71
  const pixelLen = wide[0].length <= columns ? 2 : narrow[0].length <= columns ? 1 : 0;
63
72
  const lines = pixelLen === 2 ? wide : pixelLen === 1 ? narrow : null;
64
- const center = (text) => " ".repeat(Math.max(0, Math.floor((columns - text.length) / 2))) + text;
73
+ const pad = (text) => " ".repeat(Math.max(0, Math.floor((columns - text.length) / 2)));
74
+ const center = (text) => pad(text) + text;
65
75
  // Right-align "beta" under the final "A" of KRITYA, one line below the glyph.
66
76
  const betaLine = (() => {
67
77
  if (!lines)
@@ -72,5 +82,5 @@ export function Banner({ tagline, subtitle, compact, }) {
72
82
  const indent = leftPad + aStart + Math.max(0, aWidth - BETA_LABEL.length);
73
83
  return " ".repeat(indent) + BETA_LABEL;
74
84
  })();
75
- return (_jsxs(Box, { flexDirection: "column", marginTop: 2, marginBottom: 1, children: [lines ? (lines.map((line, i) => (_jsx(Text, { color: rowColor(i), children: center(line) }, i)))) : (_jsx(Text, { bold: true, color: "cyan", children: center("KRITYA") })), betaLine ? _jsx(Text, { dimColor: true, children: betaLine }) : null, tagline ? _jsx(Text, { children: center(tagline) }) : null, _jsx(Box, { marginTop: 2, children: subtitle ? _jsx(Text, { dimColor: true, children: center(subtitle) }) : null }), _jsx(Text, { dimColor: true, children: center("AI can make mistakes. Verify important output.") })] }));
85
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 2, marginBottom: 1, children: [lines ? (lines.map((line, i) => (_jsx(Text, { color: rowColor(i), children: center(line) }, i)))) : (_jsx(Text, { bold: true, color: "cyan", children: center("KRITYA") })), betaLine ? _jsx(Text, { dimColor: true, children: betaLine }) : null, tagline ? (_jsxs(Text, { children: [pad(tagline), [...tagline].map((ch, i) => (_jsx(Text, { color: sweepColor(i, tagline.length), children: ch }, i)))] })) : null, _jsx(Box, { marginTop: 2, children: subtitle ? _jsx(Text, { dimColor: true, children: center(subtitle) }) : null }), _jsx(Text, { dimColor: true, children: center("AI can make mistakes. Verify important output.") })] }));
76
86
  }
@@ -10,5 +10,5 @@ export function TranscriptItem({ item, verbose, contentWidth }) {
10
10
  return (_jsxs(Box, { marginBottom: item.kind === "tool" ? 0 : 1, flexDirection: "column", children: [item.kind === "user" && (_jsxs(Text, { children: [_jsxs(Text, { bold: true, color: "green", children: ["\u276F", " "] }), item.text] })), item.kind === "assistant" && _jsx(Markdown, { text: item.text, width: contentWidth }), item.kind === "tool" && (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { dimColor: true, children: [item.error ? _jsx(Text, { color: "red", children: "\u2717" }) : _jsx(Text, { color: "green", children: "\u2713" }), " ", item.summary, item.resultSummary && !verbose ? ` — ${item.resultSummary}` : ""] }), item.output && item.output.trim() && (item.resultSummary === undefined || verbose) && (_jsx(Text, { dimColor: true, children: toolOutputPreview(item.output, verbose, Math.max(20, contentWidth - TOOL_INDENT), item.error)
11
11
  .split("\n")
12
12
  .map((l) => ` ${l}`)
13
- .join("\n") }))] })), item.kind === "info" && _jsx(Text, { dimColor: true, children: item.text }), item.kind === "banner" && (_jsx(Banner, { tagline: item.tagline, subtitle: item.subtitle, compact: item.compact })), item.kind === "summary" && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [_jsx(Text, { bold: true, color: "green", children: "\u2713 Completed" }), item.files.length > 0 ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Changed:" }), item.files.map((f) => (_jsxs(Text, { children: [" ", f] }, f)))] })) : (_jsx(Text, { dimColor: true, children: "No files changed." })), _jsxs(Text, { dimColor: true, children: ["Next: ", item.nextStep] })] }))] }));
13
+ .join("\n") }))] })), item.kind === "info" && _jsx(Text, { dimColor: true, children: item.text }), item.kind === "banner" && _jsx(Banner, { tagline: item.tagline, subtitle: item.subtitle }), item.kind === "summary" && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1, children: [_jsx(Text, { bold: true, color: "green", children: "\u2713 Completed" }), item.files.length > 0 ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { dimColor: true, children: "Changed:" }), item.files.map((f) => (_jsxs(Text, { children: [" ", f] }, f)))] })) : (_jsx(Text, { dimColor: true, children: "No files changed." })), _jsxs(Text, { dimColor: true, children: ["Next: ", item.nextStep] })] }))] }));
14
14
  }
@@ -45,7 +45,7 @@ function initialToolStatus(name) {
45
45
  * permission state, usage/cost tracking, and session resume. Input handling
46
46
  * (text box, slash-command suggestions, @mention autocomplete) stays in App.
47
47
  */
48
- export function useAgent({ agent, workspace, modelRef, providerRef, config, uiBridge, resumedCount, initialTasks, resumeSessions, refreshFileList, onSwitchClient, firstLaunch, }) {
48
+ export function useAgent({ agent, workspace, modelRef, providerRef, config, uiBridge, resumedCount, initialTasks, resumeSessions, refreshFileList, onSwitchClient, }) {
49
49
  const nextId = useRef(0);
50
50
  const [items, setItems] = useState(() => {
51
51
  const initial = [
@@ -54,7 +54,6 @@ export function useAgent({ agent, workspace, modelRef, providerRef, config, uiBr
54
54
  kind: "banner",
55
55
  tagline: TAGLINE,
56
56
  subtitle: `${path.basename(workspace)} · ${modelRef.current} · type a request, or /help for commands`,
57
- compact: !firstLaunch,
58
57
  },
59
58
  ];
60
59
  if (resumedCount > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kritya",
3
- "version": "0.8.30-beta",
3
+ "version": "0.8.31-beta",
4
4
  "description": "Kritya — Superintelligence at your command line",
5
5
  "type": "module",
6
6
  "publishConfig": {