eklavya 1.54.0 → 1.54.2
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eklavya",
|
|
3
3
|
"displayName": "Eklavya",
|
|
4
|
-
"version": "1.54.
|
|
4
|
+
"version": "1.54.2",
|
|
5
5
|
"description": "Learn while your agent works. Turns coding-agent generation time into adaptive, Socratic learning grounded in the code being written.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Ajay Kumar"
|
|
@@ -74,6 +74,20 @@ export function logoRows(grid: readonly string[] = LOGO_GRID, palette: Record<st
|
|
|
74
74
|
return out
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/** The grid as rows of boxes for a host whose font cannot tile glyphs: runs of one colour (or none) and their width in cells. */
|
|
78
|
+
export function boxRows(grid: readonly string[] = LOGO_GRID, palette: Record<string, string> = LOGO_PALETTE): { width: number; color?: string }[][] {
|
|
79
|
+
return grid.map(row => {
|
|
80
|
+
const runs: { width: number; color?: string }[] = []
|
|
81
|
+
for (const c of row) {
|
|
82
|
+
const color = c === '.' ? undefined : palette[c]
|
|
83
|
+
const last = runs[runs.length - 1]
|
|
84
|
+
if (last && last.color === color) last.width++
|
|
85
|
+
else runs.push({ width: 1, color })
|
|
86
|
+
}
|
|
87
|
+
return runs
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
77
91
|
/** The name as the header sets it: spaced capitals, the nearest a terminal gets to a larger type size. */
|
|
78
92
|
/** A call such as `tester.tap(find.byType(X))`, nested up to three deep, a lowerCamelCase name or a snake_case name. */
|
|
79
93
|
const CODE_LIKE = /[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*\((?:[^()\n]|\((?:[^()\n]|\([^()\n]*\))*\))*\)|\b[a-z]{2,}(?:[A-Z][a-z0-9]+)+\b|\b[a-z0-9]+(?:_[a-z0-9]+)+\b/g
|
|
@@ -90,6 +104,17 @@ export function codify(text: string): string {
|
|
|
90
104
|
.join('')
|
|
91
105
|
}
|
|
92
106
|
|
|
107
|
+
/** Block Markdown that bold marks around it would break: a fence, heading, list, quote, or bold already in it. */
|
|
108
|
+
const NOT_BOLDABLE = /```|\*\*|^\s*(?:#|[-*+>]|\d+[.)])\s/m
|
|
109
|
+
|
|
110
|
+
/** Bolds each plain paragraph of a question, so a blank line never sits inside a bold span. */
|
|
111
|
+
export function boldParagraphs(text: string): string {
|
|
112
|
+
return text
|
|
113
|
+
.split(/\n{2,}/)
|
|
114
|
+
.map(p => (p.trim() && !NOT_BOLDABLE.test(p) ? `**${p.trim()}**` : p))
|
|
115
|
+
.join('\n\n')
|
|
116
|
+
}
|
|
117
|
+
|
|
93
118
|
/** What a Button label can show of Markdown: it keeps the words and drops the code and bold marks. */
|
|
94
119
|
export function plainLabel(text: string): string {
|
|
95
120
|
return text.replace(/`|\*\*/g, '')
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
codify,
|
|
17
17
|
gradingRequest,
|
|
18
18
|
logoRows,
|
|
19
|
+
boxRows,
|
|
20
|
+
boldParagraphs,
|
|
19
21
|
plainLabel,
|
|
20
22
|
levelLine,
|
|
21
23
|
parseVerdict,
|
|
@@ -349,20 +351,38 @@ export const register: Register = on => {
|
|
|
349
351
|
const s: PanelState = await read($, quiz)
|
|
350
352
|
const q = s.question
|
|
351
353
|
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
354
|
+
// Any surface but the terminal is the desktop app's: it sets the question bold, spaces the answers
|
|
355
|
+
// apart and draws the mark in boxes. The terminal keeps its text layout.
|
|
356
|
+
const app = e.surface !== 'terminal'
|
|
357
|
+
// The mark is drawn in text, as Claude Code draws its own, so it shows in every terminal. The
|
|
358
|
+
// desktop app sets text in a proportional font with its own line height, so glyph cells do not
|
|
359
|
+
// tile there: it gets the same grid as filled boxes, one per run of a colour. A cell is one unit
|
|
360
|
+
// wide and half a unit tall, which is square in the app (checked live there; the host's
|
|
361
|
+
// fractional-height support is not documented, so a failure shows as a stretched mark).
|
|
362
|
+
const logo =
|
|
363
|
+
!app ? (
|
|
364
|
+
<Box flexDirection="column" flexShrink={0}>
|
|
365
|
+
{logoRows().map((runs, y) => (
|
|
366
|
+
<Box key={`logo-${y}`} flexDirection="row" flexShrink={0}>
|
|
367
|
+
{runs.map((run, x) => (
|
|
368
|
+
<Text key={`logo-${y}-${x}`} color={run.fg} backgroundColor={run.bg} wrap="truncate">
|
|
369
|
+
{run.text}
|
|
370
|
+
</Text>
|
|
371
|
+
))}
|
|
372
|
+
</Box>
|
|
373
|
+
))}
|
|
374
|
+
</Box>
|
|
375
|
+
) : (
|
|
376
|
+
<Box flexDirection="column" flexShrink={0}>
|
|
377
|
+
{boxRows().map((runs, y) => (
|
|
378
|
+
<Box key={`logo-${y}`} flexDirection="row" flexShrink={0} height={0.5}>
|
|
379
|
+
{runs.map((run, x) => (
|
|
380
|
+
<Box key={`logo-${y}-${x}`} width={run.width} height={0.5} flexShrink={0} backgroundColor={run.color} />
|
|
381
|
+
))}
|
|
382
|
+
</Box>
|
|
383
|
+
))}
|
|
384
|
+
</Box>
|
|
385
|
+
)
|
|
366
386
|
// A list tile: the mark on the left; the name over the topic beside it.
|
|
367
387
|
const head = (subtitle?: string) => (
|
|
368
388
|
<Box flexDirection="row" alignItems="center" gap={2}>
|
|
@@ -385,13 +405,14 @@ export const register: Register = on => {
|
|
|
385
405
|
</Box>
|
|
386
406
|
)
|
|
387
407
|
// One answer: a bordered block. The Button holds the whole answer text, so a press anywhere on it
|
|
388
|
-
// selects; the border and a tick show the pick, and nothing implies it is right.
|
|
408
|
+
// selects; the border and a tick show the pick, and nothing implies it is right. The desktop app gives
|
|
409
|
+
// the text more room inside the border; the terminal keeps its tight cards.
|
|
389
410
|
const card = (id: string, selected: boolean, button: unknown, body: unknown[], roomy = false) => (
|
|
390
411
|
<Box
|
|
391
412
|
key={`card-${id}`}
|
|
392
413
|
flexDirection="column"
|
|
393
|
-
paddingX={1}
|
|
394
|
-
paddingY={roomy ? 1 : 0}
|
|
414
|
+
paddingX={app ? 2 : 1}
|
|
415
|
+
paddingY={app || roomy ? 1 : 0}
|
|
395
416
|
gap={roomy ? 1 : 0}
|
|
396
417
|
borderStyle="single"
|
|
397
418
|
borderColor={selected ? BRAND : 'inactive'}
|
|
@@ -419,7 +440,7 @@ export const register: Register = on => {
|
|
|
419
440
|
)
|
|
420
441
|
}
|
|
421
442
|
|
|
422
|
-
const stem = <Markdown text={codify(q.stem)} />
|
|
443
|
+
const stem = <Markdown text={app ? boldParagraphs(codify(q.stem)) : codify(q.stem)} />
|
|
423
444
|
|
|
424
445
|
if (s.step === 'feedback' || s.step === 'skipped') {
|
|
425
446
|
const r = s.result
|
|
@@ -469,7 +490,7 @@ export const register: Register = on => {
|
|
|
469
490
|
|
|
470
491
|
return frame(
|
|
471
492
|
stem,
|
|
472
|
-
<Box flexDirection="column">
|
|
493
|
+
<Box flexDirection="column" gap={app ? 1 : 0}>
|
|
473
494
|
{options}
|
|
474
495
|
{card(
|
|
475
496
|
'other',
|
package/package.json
CHANGED