eklavya 1.88.0 → 1.90.0
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/README.md +3 -3
- package/dist/assets/tutor/references/panel.md +1 -0
- package/dist/cli.js +1 -0
- package/dist/cli.js.map +1 -1
- package/dist/config-path.js +1 -0
- package/dist/config-path.js.map +1 -1
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard.js +2 -0
- package/dist/dashboard.js.map +1 -1
- package/dist/hooks/checkpoint-quiz.js +7 -3
- package/dist/hooks/checkpoint-quiz.js.map +1 -1
- package/dist/hooks/delegation-lib.js +1 -1
- package/dist/hooks/delegation-lib.js.map +1 -1
- package/dist/hooks/quiz-text-lib.js +1 -1
- package/dist/hooks/quiz-text-lib.js.map +1 -1
- package/dist/hooks/stop-quiz-check.js +6 -3
- package/dist/hooks/stop-quiz-check.js.map +1 -1
- package/dist/migrations/033_panel_question_card.sql +7 -0
- package/dist/panel.js +3 -2
- package/dist/panel.js.map +1 -1
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/hooks/CLAUDE.md +2 -2
- package/dist/plugin/hooks/panel/card.tsx +26 -7
- package/dist/plugin/hooks/panel/model.ts +15 -1
- package/dist/plugin/hooks/panel/pill.tsx +38 -0
- package/dist/plugin/hooks/panel/register.tsx +99 -24
- package/dist/plugin/hooks/panel/types/index.d.ts +5 -1
- package/dist/plugin/skills/tutor/references/panel.md +1 -0
- package/dist/session.js +33 -5
- package/dist/session.js.map +1 -1
- package/dist/tools/config_tools.js +1 -0
- package/dist/tools/config_tools.js.map +1 -1
- package/dist/tools/get_session_quiz_plan.js +7 -2
- package/dist/tools/get_session_quiz_plan.js.map +1 -1
- package/dist/tools/panel_tools.js +7 -1
- package/dist/tools/panel_tools.js.map +1 -1
- package/dist/user-skill/eklavya/SKILL.md +1 -1
- package/package.json +1 -1
package/dist/panel.js
CHANGED
|
@@ -117,8 +117,8 @@ export function presentQuestion(db, args) {
|
|
|
117
117
|
// `more` only stands for a question outside one.
|
|
118
118
|
const more = advanceRound(db, sessionId, concept.slug) ?? Boolean(args.more);
|
|
119
119
|
const id = randomUUID();
|
|
120
|
-
db.prepare(`INSERT INTO panel_questions (id, session_id, repo, concept_id, tier, stem, options, key, explanation, more)
|
|
121
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, sessionId, repo, concept.id, args.difficulty, stem, JSON.stringify(options), JSON.stringify(key), args.explanation, more ? 1 : 0);
|
|
120
|
+
db.prepare(`INSERT INTO panel_questions (id, session_id, repo, concept_id, tier, stem, options, key, explanation, more, card)
|
|
121
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(id, sessionId, repo, concept.id, args.difficulty, stem, JSON.stringify(options), JSON.stringify(key), args.explanation, more ? 1 : 0, args.did_you_know ? JSON.stringify(args.did_you_know) : null);
|
|
122
122
|
return {
|
|
123
123
|
question_id: id,
|
|
124
124
|
status: 'presented',
|
|
@@ -196,6 +196,7 @@ function syncReply(db, args) {
|
|
|
196
196
|
concept_name: concept.name,
|
|
197
197
|
tier: row.tier,
|
|
198
198
|
more: row.more === 1,
|
|
199
|
+
...(row.card ? { card: JSON.parse(row.card) } : {}),
|
|
199
200
|
};
|
|
200
201
|
}
|
|
201
202
|
/**
|
package/dist/panel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eklavya",
|
|
3
3
|
"displayName": "Eklavya",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.90.0",
|
|
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"
|
|
@@ -51,12 +51,12 @@ the next sync. The rules it is validated against: static relative imports only,
|
|
|
51
51
|
every `$` call inline or in a function declared at the top of the file, literal
|
|
52
52
|
event names, render only its own pane, and never hold the answer key (the server
|
|
53
53
|
grades; the mod draws and relays). On a headerless host `panel_sync` also carries a `greeting` the mod toasts once (the SessionStart `systemMessage` never reaches Desktop; the terminal is never sent it, and `hooks/session-start.ts` is untouched). It is opt-in: with `quiz.panel` off, `panel_sync`
|
|
54
|
-
returns `{disabled: true}` and the mod opens and draws nothing. `presentation` in
|
|
54
|
+
returns `{disabled: true}` and the mod opens and draws nothing. A question that carries a Did You Know `card` (`panel_questions.card`, required by the `present_question` schema) opens on the `card` step: **I knew this** and **Got it** move to `awaiting`, **I want to learn more** sets `learn` to show the details; neither calls the server, so neither records anything. `presentation` in
|
|
55
55
|
`get_session_quiz_plan` is the one source for which tool asks; the checkpoint,
|
|
56
56
|
the Stop sweep and the delegation lines (`delegation-lib.ts`) read it, and an
|
|
57
57
|
open panel question silences the checkpoint and the Stop sweep. Read
|
|
58
58
|
`docs/verified-schemas.md` (mods section) before changing anything it records.
|
|
59
|
-
`/eklavya-panel-demo` (`DEMO_COMMAND`) is the maintainer's shortcut for trying the pane: it seeds `PanelState.demo` with a mock question and never calls the server, so it works with `quiz.panel` off. While `demo` is set the heartbeat (`beat`) does not sync, `submit` grades locally with `demoResult` (no `panel_answer`, grader or explainer) and Next restarts the mock; `/eklavya-panel` and a real `present_question` sync replace it.
|
|
59
|
+
`/eklavya-panel-demo` (`DEMO_COMMAND`) is the maintainer's shortcut for trying the pane: it seeds `PanelState.demo` with a mock question and never calls the server, so it works with `quiz.panel` off. While `demo` is set the heartbeat (`beat`) does not sync, `submit` grades locally with `demoResult` (no `panel_answer`, grader or explainer) and Next restarts the mock; `/eklavya-panel` and a real `present_question` sync replace it. Only the desktop draws `Client` regions (VS Code has `Svg` but no `Client`, and a tree holding an element its surface lacks is replaced whole): there every answer is a numbered whole-card region from `card.tsx`, Teach me is a compact `pill.tsx` region, the Other header is a `bare` card over an `Input` of three rows, and the header mark is `MASCOT_FACE` as an `Svg`; they post `{pick}` or `{press}` to the `ui.message` hook, which accepts only an id of the open question, `other`, or `teach`. VS Code and the terminal keep native `Button`s (VS Code numbers the labels itself, the terminal's plain Button draws `1:`). The demo's Answer cards switch (desktop only) compares the whole-card default with the native buttons. Under the Teach me button the demo also draws an experiment box (`experiment` in `register.tsx`): `Image` with `DEMO_PNG` on the terminal, two `Svg` (`demoSvg`, `demoSvgWithPng`) on every other surface, never both, because a tree holding an element its surface lacks is replaced whole by the host's own pane.
|
|
60
60
|
Run `scripts/test-panel-mod.sh`: it stages the mod as its own plugin, validates
|
|
61
61
|
it, runs `claude plugin test`, then validates the distributed plugin.
|
|
62
62
|
|
|
@@ -2,19 +2,25 @@ import type { ClientModule } from 'claude-code'
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* One answer card drawn as a `Client` region, so a press anywhere on it (border,
|
|
5
|
-
* padding, title or note) picks it. A `Button` is only as large as its label, and a
|
|
5
|
+
* padding, number, title or note) picks it. A `Button` is only as large as its label, and a
|
|
6
6
|
* `Box` takes no press, so this is the one way to make the whole card the target.
|
|
7
7
|
*
|
|
8
8
|
* It gets no mods API: it holds only its hover and posts `{ pick: id }` to the hooks
|
|
9
9
|
* module, whose `ui.message` hook validates the id and records the pick. The colours
|
|
10
10
|
* come in as props, so the module imports nothing.
|
|
11
|
+
*
|
|
12
|
+
* `bare` draws only the pressable header (padding and text, no border or fill): the Other
|
|
13
|
+
* card's frame and its text box belong to the hooks module, and this is the row that selects it.
|
|
11
14
|
*/
|
|
12
15
|
export type CardProps = {
|
|
13
16
|
id: string
|
|
14
17
|
label: string
|
|
15
18
|
note: string
|
|
19
|
+
/** The answer's number, drawn before the text; absent for Other. */
|
|
20
|
+
n?: number
|
|
16
21
|
chosen: boolean
|
|
17
22
|
locked: boolean
|
|
23
|
+
bare?: boolean
|
|
18
24
|
brand: string
|
|
19
25
|
fill: string
|
|
20
26
|
text: string
|
|
@@ -30,16 +36,29 @@ const Card: ClientModule<CardProps, { hover: boolean }> = (p, s) => {
|
|
|
30
36
|
else if (e.type === 'leave' && hover) s.setState({ hover: false })
|
|
31
37
|
else if (e.type === 'up' && !p.locked && (e.button === undefined || e.button === 'left')) s.post({ pick: p.id })
|
|
32
38
|
})
|
|
33
|
-
|
|
39
|
+
const words = Box({
|
|
34
40
|
flexDirection: 'column',
|
|
41
|
+
flexShrink: 1,
|
|
42
|
+
children: [
|
|
43
|
+
Text({ wrap: 'wrap', bold: p.chosen && !p.bare, color: p.chosen && !p.bare ? p.text : undefined, children: [p.label] }),
|
|
44
|
+
...(p.note ? [Text({ wrap: 'wrap', dimColor: !p.chosen, color: p.chosen ? p.noteText : undefined, children: [p.note] })] : []),
|
|
45
|
+
],
|
|
46
|
+
})
|
|
47
|
+
return Box({
|
|
48
|
+
flexDirection: p.n === undefined ? 'column' : 'row',
|
|
49
|
+
gap: 2,
|
|
35
50
|
paddingX: 2,
|
|
36
51
|
paddingY: 1,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
...(p.bare
|
|
53
|
+
? {}
|
|
54
|
+
: {
|
|
55
|
+
borderStyle: p.chosen ? 'bold' : 'single',
|
|
56
|
+
borderColor: p.chosen || (hover && !p.locked) ? p.brand : 'inactive',
|
|
57
|
+
backgroundColor: p.chosen ? p.fill : undefined,
|
|
58
|
+
}),
|
|
40
59
|
children: [
|
|
41
|
-
Text({
|
|
42
|
-
|
|
60
|
+
...(p.n === undefined ? [] : [Text({ bold: true, dimColor: !p.chosen, color: p.chosen ? p.text : undefined, children: [String(p.n)] })]),
|
|
61
|
+
words,
|
|
43
62
|
],
|
|
44
63
|
})
|
|
45
64
|
}
|
|
@@ -23,7 +23,7 @@ export const BRAND = '#79D5C4'
|
|
|
23
23
|
/** The fill and text of the picked answer: set together so the contrast holds in a light or a dark theme. */
|
|
24
24
|
export const PICKED = { bg: '#1E5A52', text: '#FFFFFF', note: '#C9E8E3' }
|
|
25
25
|
/** Teach me is Claude's orange (the logo's mascot), fill and border. The text is dark, as white on that orange is too faint at body size. */
|
|
26
|
-
export const TEACH = { bg: '#D97757', text: '#1F1E1D' }
|
|
26
|
+
export const TEACH = { bg: '#D97757', text: '#1F1E1D', hover: '#E48866' }
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* The logo: the Claude mascot (orange) holding an Eklavya bow and arrow (white), drawn on a
|
|
@@ -134,6 +134,10 @@ export const STR = {
|
|
|
134
134
|
brand: 'Eklavya',
|
|
135
135
|
submit: 'Submit answer',
|
|
136
136
|
skip: 'Skip question',
|
|
137
|
+
dyk: 'Did you know?',
|
|
138
|
+
knew: 'Oh, I knew this',
|
|
139
|
+
learnMore: 'I want to learn more',
|
|
140
|
+
gotIt: 'Got it, ask me',
|
|
137
141
|
teach: 'New to me — Teach me',
|
|
138
142
|
next: 'Next question',
|
|
139
143
|
done: 'Done',
|
|
@@ -171,9 +175,11 @@ export const STR = {
|
|
|
171
175
|
demoStyleClient: 'Whole card',
|
|
172
176
|
demoExplanation: 'A rename inside one folder is atomic: the poller sees the finished file or none, never half of it. (This is a mock, so it was not recorded.)',
|
|
173
177
|
demoTyped: 'Typed answers are not graded in the demo. (Nothing was sent or recorded.)',
|
|
178
|
+
mascotAlt: 'The Eklavya mascot',
|
|
174
179
|
experimentBanner: 'EXPERIMENT · picture test. Nothing here is part of a real question.',
|
|
175
180
|
experimentTerminal: 'Image: a PNG, drawn as a picture in kitty, Ghostty and iTerm2 (fullscreen); other terminals show the dim text instead. SVG is not drawn in the terminal.',
|
|
176
181
|
experimentImageAlt: 'The Eklavya mark: the Claude mascot holding a bow and arrow',
|
|
182
|
+
experimentNone: 'This surface draws neither an SVG nor an image, so there is nothing to test here.',
|
|
177
183
|
experimentSvg: 'SVG: the mark drawn as vector rectangles.',
|
|
178
184
|
experimentSvgPng: 'Image: the same mark as a PNG inside an SVG (Desktop has no Image element).',
|
|
179
185
|
} as const
|
|
@@ -246,6 +252,14 @@ export function demoResult(kind: 'choice' | 'text' | 'skip' | 'dont_know', optio
|
|
|
246
252
|
return { phase: 'answered', attempt_id: 0, correct, correct_label: right, explanation: kind === 'text' ? STR.demoTyped : STR.demoExplanation }
|
|
247
253
|
}
|
|
248
254
|
|
|
255
|
+
/**
|
|
256
|
+
* The mascot's neutral face, the header mark on every surface that draws `Svg`. A copy of
|
|
257
|
+
* `web/public/brand/mascot/expressions/neutral-face.svg` (the mod has no filesystem); a test keeps the two equal,
|
|
258
|
+
* so regenerate with `npm run mascot:generate` and paste the file. The terminal keeps the block-character logo.
|
|
259
|
+
*/
|
|
260
|
+
export const MASCOT_FACE =
|
|
261
|
+
"<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"30 12 126 128\" width=\"200\" height=\"200\" class=\"ek-mascot\" data-expression=\"neutral\" data-variant=\"face\" role=\"img\"><style>:root {/* ---------- MASCOT IDENTITY ----------\n Archer Cloak artwork keeps its approved identity across both grounds.\n UI chrome continues to use the surface, text and accent roles below. */\n --mascot-coral: #ef9875;\n --mascot-coral-dark: #c96d51;\n --mascot-highlight: #ffc8a6;\n --mascot-cloak: #0E6E66;\n --mascot-cloak-dark: #07403C;\n --mascot-thread: #C4EDE4;\n --mascot-ink: #302c2a;\n --mascot-metal: #5b7c73;\n --mascot-wood: #bc9569;\n --mascot-wood-dark: #74583f;\n --mascot-string: #EAE7E1;\n --mascot-shadow: #26262a;\n /* ---------- END MASCOT IDENTITY ---------- */}/* Identity colours and UI surfaces use Eklavya's semantic tokens. */\neklavya-mascot { display:inline-flex; flex-shrink:0; vertical-align:middle; line-height:0; }\n.ek-mascot { display:block; overflow:visible; flex-shrink:0; }\n.ek-mascot[data-variant=\"face\"] { overflow:hidden; }\n.ek-mascot__face path:not([fill]) { fill:none; }\n.ek-companion { display:flex;align-items:center;gap:12px;color:var(--dim);font:13px/1.5 var(--font-body); }\n.ek-companion--hero { margin-bottom:16px; }\n.ek-companion--hero b { display:block;color:var(--ink);font-weight:600; }\n.ek-mascot-message { display:flex;align-items:center;gap:16px;padding:16px 0; }\n.ek-mascot-message p {margin:0}\n/* Secondary loader: draws and releases an arrow over 2.8 s. */\n.ek-mascot--draw .ek-mascot__character { animation:ek-breathe 2.8s ease-in-out infinite; transform-origin:95px 185px; }\n.ek-mascot--draw .ek-mascot__arrow { animation:ek-release 2.8s cubic-bezier(.3,0,.3,1) infinite; }\n.ek-mascot--draw .ek-mascot__string { animation:ek-draw 2.8s ease-in-out infinite; transform-origin:157px 125px; }\n.ek-mascot--draw .ek-mascot__ripple { animation:ek-hit 2.8s ease-out infinite; transform-origin:196px 128px; opacity:0; }\n@keyframes ek-breathe { 0%,100% {transform:translateY(0)} 35%,55% {transform:translateY(-3px) rotate(-1deg)} }\n@keyframes ek-release { 0%,12% {transform:translateX(0);opacity:1} 40%,52% {transform:translateX(-10px);opacity:1} 68% {transform:translateX(22px);opacity:0} 69%,85% {transform:translateX(0);opacity:0} 100% {transform:translateX(0);opacity:1} }\n@keyframes ek-draw { 0%,100% {transform:scaleX(1)} 40%,52% {transform:scaleX(1.11)} 60% {transform:scaleX(.08)} 68% {transform:scaleX(1)} }\n@keyframes ek-hit { 0%,60%,100% {opacity:0;transform:scale(.4)} 68% {opacity:.8;transform:scale(.7)} 88% {opacity:0;transform:scale(1.7)} }\n/* Loader: walking toward the viewer, a 1.2 s stride (two steps). Ground rungs recede on an ease-out, as perspective slows them near the horizon. */\n.ek-mascot--loading .ek-mascot__walker { animation:ek-sway 1.2s ease-in-out infinite; transform-origin:95px 185px; }\n.ek-mascot--loading .ek-mascot__torso { animation:ek-bob .6s ease-in-out infinite; }\n.ek-mascot--loading .ek-mascot__leg, .ek-mascot--loading .ek-mascot__hand { animation:ek-step 1.2s ease-in-out infinite; }\n.ek-mascot--loading .ek-mascot__leg--r, .ek-mascot--loading .ek-mascot__hand--arrow { animation-delay:-.6s; }\n.ek-mascot--loading .ek-mascot__shadow { animation:ek-shadow .6s ease-in-out infinite; transform-origin:95px 186px; }\n.ek-mascot--loading .ek-mascot__rung { animation:ek-recede 1.2s cubic-bezier(.15,.6,.4,1) infinite; transform-origin:95px 162px; }\n.ek-mascot--loading .ek-mascot__rung:nth-child(3) { animation-delay:-.3s; }\n.ek-mascot--loading .ek-mascot__rung:nth-child(4) { animation-delay:-.6s; }\n.ek-mascot--loading .ek-mascot__rung:nth-child(5) { animation-delay:-.9s; }\n@keyframes ek-sway { 0%,100% {transform:rotate(-1.5deg)} 50% {transform:rotate(1.5deg)} }\n@keyframes ek-bob { 0%,100% {transform:translateY(1px)} 50% {transform:translateY(-3px)} }\n@keyframes ek-step { 0%,50%,100% {transform:translateY(0)} 25% {transform:translateY(-6px)} }\n@keyframes ek-shadow { 0%,100% {transform:scaleX(1)} 50% {transform:scaleX(.92)} }\n@keyframes ek-recede { 0% {transform:translateY(56px) scaleX(1);opacity:0} 10% {opacity:1} 85% {opacity:1} 100% {transform:translateY(0) scaleX(.4);opacity:0} }\n@media (prefers-reduced-motion:reduce) { .ek-mascot * {animation:none !important;transition:none !important} }\n\n.ek-companion--rail { padding:12px 20px; text-decoration:none; }\n.ek-mascot-message > :last-child { min-width:0; overflow-wrap:break-word; }\n.ek-mascot-status { display:inline-flex; align-items:center; gap:6px; }\n</style><title>Eklavya, calm and attentive</title><path d=\"M48 109q44-19 88 0l-8 30-33-15-31 15Z\" fill=\"var(--mascot-cloak)\"/><g class=\"ek-mascot__head\">\n <path d=\"M46 43h18V29h19V18h23v12h20v14h17v19h8v29h-8v16q0 12-16 15H62q-18-3-18-17V91h-9V63h11Z\" fill=\"var(--mascot-coral)\" stroke=\"var(--mascot-coral-dark)\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n <path d=\"M48 45h18V32h18V21h19\" fill=\"none\" stroke=\"var(--mascot-highlight)\" stroke-width=\"3\" stroke-linejoin=\"round\"/>\n <g class=\"ek-mascot__face\" fill=\"var(--mascot-ink)\" stroke=\"var(--mascot-ink)\" stroke-width=\"3.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"64\" y=\"64\" width=\"10\" height=\"19\" rx=\"5\"/><rect x=\"110\" y=\"64\" width=\"10\" height=\"19\" rx=\"5\"/><path d=\"M84 89q8 6 16 0\"/></g>\n </g><circle cx=\"95\" cy=\"126\" r=\"6\" fill=\"var(--mascot-metal)\"/></svg>"
|
|
262
|
+
|
|
249
263
|
/** The logo as a PNG (208 by 96, one grid cell is 8 pixels), for the demo's picture test: the mod has no filesystem. */
|
|
250
264
|
export const DEMO_PNG =
|
|
251
265
|
'iVBORw0KGgoAAAANSUhEUgAAANAAAABgCAYAAABsbvwBAAABcElEQVR42u3dwQ2DMBBFQXdJKdRKNaYDDqDFu+t50j8mUpDnZCUZQ3pofswTFEAASQBJAEkASQABJAEkASTlBJL9/SWAJIAAEkAASQBJAEkAASSAAJJyHnDABBBAAgggCSAJIIAEEEACCCAJoLpd5zFt3aof4O2BOcQAAQQQQAABBBBAABlAABlAAAEEEEAAAQRQY0Ddga5+ftUPaHtgAAEEEEAAAQQQQAABBBBAAAEEEEAAAQQQQAAB5CLUXk7BfyDmkAEkgAwggAwggAwggAwgAWQEAGQAJQbkHskX6lykuogFCCCADCCADCCAAAIIIIAAAgggAwggAwigCGDRr9/98/lhRYAAAggggAACCCCAAHLAAAIIIIAAAggggAACCCCA1LPVBxQQAQSQAAJIAkgCCCABBJAAAkgCSKp5gAERQABJAEkASQABJIAAkgCSAJJqAgNEAkgCSAJIAgggCSAJIAkgSZIkSZIkSZIk6dduN5j9QcRn8BgAAAAASUVORK5CYII='
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ClientModule } from 'claude-code'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A compact filled button drawn as a `Client` region, so a press anywhere on it (fill, padding or
|
|
5
|
+
* text) counts. A `Button` takes no fill, and a `Box` takes no press, so a coloured button whose
|
|
6
|
+
* whole body is pressable has to be a region of its own. It sizes to its text and posts
|
|
7
|
+
* `{ press: id }` to the hooks module, which validates it. Colours come in as props.
|
|
8
|
+
*/
|
|
9
|
+
export type PillProps = {
|
|
10
|
+
id: string
|
|
11
|
+
label: string
|
|
12
|
+
locked: boolean
|
|
13
|
+
fill: string
|
|
14
|
+
hoverFill: string
|
|
15
|
+
text: string
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Pill: ClientModule<PillProps, { hover: boolean }> = (p, s) => {
|
|
19
|
+
const { Box, Text } = s.elements
|
|
20
|
+
const hover = s.state?.hover ?? false
|
|
21
|
+
s.onPointer(e => {
|
|
22
|
+
if (e.type === 'enter' && !hover) s.setState({ hover: true })
|
|
23
|
+
else if (e.type === 'leave' && hover) s.setState({ hover: false })
|
|
24
|
+
else if (e.type === 'up' && !p.locked && (e.button === undefined || e.button === 'left')) s.post({ press: p.id })
|
|
25
|
+
})
|
|
26
|
+
const fill = hover && !p.locked ? p.hoverFill : p.fill
|
|
27
|
+
return Box({
|
|
28
|
+
flexDirection: 'row',
|
|
29
|
+
paddingX: 2,
|
|
30
|
+
paddingY: 0.5,
|
|
31
|
+
borderStyle: 'round',
|
|
32
|
+
borderColor: fill,
|
|
33
|
+
backgroundColor: fill,
|
|
34
|
+
children: [Text({ color: p.text, children: [p.label] })],
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export default Pill
|
|
@@ -4,6 +4,7 @@ import type { EngineInterface, Register } from 'claude-code'
|
|
|
4
4
|
import {
|
|
5
5
|
BRAND,
|
|
6
6
|
DEMO_PNG,
|
|
7
|
+
MASCOT_FACE,
|
|
7
8
|
PICKED,
|
|
8
9
|
TEACH,
|
|
9
10
|
EMPTY,
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
} from './model'
|
|
38
39
|
import type { PanelPending, PanelQuestion, PanelState } from './types'
|
|
39
40
|
import type { CardProps } from './card'
|
|
41
|
+
import type { PillProps } from './pill'
|
|
40
42
|
|
|
41
43
|
/**
|
|
42
44
|
* The Eklavya quiz panel: a pane that shows the question the tutor model handed
|
|
@@ -144,7 +146,7 @@ async function sync($: EngineInterface): Promise<'disabled' | 'none' | 'question
|
|
|
144
146
|
// a lost reply leaves nothing to Retry (Retry returns the stored result).
|
|
145
147
|
if (!busy) {
|
|
146
148
|
await update($, quiz, (s: PanelState) =>
|
|
147
|
-
s.step === 'awaiting' || s.step === 'grading' || s.step === 'loading' ? { ...EMPTY, message: s.step === 'loading' ? null : s.message } : s,
|
|
149
|
+
s.step === 'card' || s.step === 'awaiting' || s.step === 'grading' || s.step === 'loading' ? { ...EMPTY, message: s.step === 'loading' ? null : s.message } : s,
|
|
148
150
|
)
|
|
149
151
|
}
|
|
150
152
|
return 'none'
|
|
@@ -154,7 +156,7 @@ async function sync($: EngineInterface): Promise<'disabled' | 'none' | 'question
|
|
|
154
156
|
await update($, quiz, (s: PanelState) =>
|
|
155
157
|
s.question?.question_id === question.question_id && s.step !== 'none' && s.step !== 'loading'
|
|
156
158
|
? { ...s, question }
|
|
157
|
-
: { ...EMPTY, step: 'awaiting', question },
|
|
159
|
+
: { ...EMPTY, step: question.card ? 'card' : 'awaiting', question },
|
|
158
160
|
)
|
|
159
161
|
|
|
160
162
|
// Seat the pane once per question. Opened unasked it sits from 144 columns and
|
|
@@ -406,21 +408,24 @@ export const register: Register = on => {
|
|
|
406
408
|
// The mock question: opens at once, answered on this machine, so a card or a click can be tried with no real question waiting.
|
|
407
409
|
on('command.run', { command: 'eklavya-panel-demo' }, async $ => {
|
|
408
410
|
try {
|
|
409
|
-
await startDemo($, '
|
|
411
|
+
await startDemo($, 'client')
|
|
410
412
|
return { text: STR.demoOpened }
|
|
411
413
|
} catch {
|
|
412
414
|
return { text: STR.demoFailed }
|
|
413
415
|
}
|
|
414
416
|
})
|
|
415
417
|
|
|
416
|
-
// A press on a
|
|
418
|
+
// A press on a `Client` region (card.tsx, pill.tsx) arrives here as data, never as a fact: only an id of the open question, Other, or Teach me counts.
|
|
417
419
|
on('ui.message', { component: 'Pane' }, async ($, e, next) => {
|
|
418
420
|
if (e.requestId === PANE) {
|
|
419
421
|
try {
|
|
420
422
|
const started = Date.now()
|
|
421
|
-
const
|
|
423
|
+
const data = e.data as { pick?: unknown; press?: unknown } | null
|
|
424
|
+
const id = data?.pick
|
|
422
425
|
const s: PanelState = (await $.state.get(REF)).value ?? EMPTY
|
|
423
|
-
if (
|
|
426
|
+
if (id === 'other') await chooseOther($)
|
|
427
|
+
else if (typeof id === 'string' && s.question?.options.some(o => o.id === id)) await pick($, id, 'whole card', started)
|
|
428
|
+
else if (data?.press === 'teach' && s.question && (s.step === 'awaiting' || s.step === 'error')) await teach($)
|
|
424
429
|
} catch {
|
|
425
430
|
/* Fail open: the card stays as it was. */
|
|
426
431
|
}
|
|
@@ -449,6 +454,11 @@ export const register: Register = on => {
|
|
|
449
454
|
// Any surface but the terminal is the desktop app's: it sets the question as a heading, spaces the
|
|
450
455
|
// answers apart and draws the mark in boxes. The terminal keeps its text layout.
|
|
451
456
|
const app = e.surface !== 'terminal'
|
|
457
|
+
// Only the desktop app draws a `Client` (the whole-card answers, the Teach me pill, the Other row). VS Code has `Svg` but no `Client`:
|
|
458
|
+
// a tree holding an element its surface lacks is replaced whole, so VS Code keeps the native buttons.
|
|
459
|
+
const desktop = e.surface === 'desktop'
|
|
460
|
+
// `Svg` is drawn by the desktop app and VS Code only (the elements table lists no other surface), so any other surface keeps the grid mark.
|
|
461
|
+
const vector = desktop || e.surface === 'vscode'
|
|
452
462
|
// The mark is drawn in text, as Claude Code draws its own, so it shows in every terminal. The
|
|
453
463
|
// desktop app sets text in a proportional font with its own line height, so glyph cells do not
|
|
454
464
|
// tile there: it gets the same grid as filled boxes, one per run of a colour. A cell is one unit
|
|
@@ -467,6 +477,11 @@ export const register: Register = on => {
|
|
|
467
477
|
</Box>
|
|
468
478
|
))}
|
|
469
479
|
</Box>
|
|
480
|
+
) : vector ? (
|
|
481
|
+
// The mascot's own neutral face, as the vector artwork the brand ships (the block grid is for the terminal's cells).
|
|
482
|
+
<Box flexDirection="column" flexShrink={0}>
|
|
483
|
+
<Svg alt={STR.mascotAlt} width={72} height={73} source={MASCOT_FACE} />
|
|
484
|
+
</Box>
|
|
470
485
|
) : (
|
|
471
486
|
<Box flexDirection="column" flexShrink={0}>
|
|
472
487
|
{boxRows().map((runs, y) => (
|
|
@@ -528,7 +543,7 @@ export const register: Register = on => {
|
|
|
528
543
|
<Box key="demo-bar" flexDirection="column" gap={app ? 1 : 0}>
|
|
529
544
|
<Text color="warning">{STR.demoBanner}</Text>
|
|
530
545
|
<Text dimColor>{s.demo.last}</Text>
|
|
531
|
-
{
|
|
546
|
+
{desktop ? (
|
|
532
547
|
<Box flexDirection="row" gap={2} alignItems="center">
|
|
533
548
|
<Text dimColor>{STR.demoStyleLabel}</Text>
|
|
534
549
|
<Button key="style-button" label={STR.demoStyleButton} variant={s.demo.style === 'button' ? 'primary' : 'secondary'} onPress={() => setStyle($, 'button')} />
|
|
@@ -557,6 +572,18 @@ export const register: Register = on => {
|
|
|
557
572
|
)
|
|
558
573
|
}
|
|
559
574
|
|
|
575
|
+
if (s.step === 'card' && q.card) {
|
|
576
|
+
return frame(
|
|
577
|
+
<Text bold color={BRAND}>{STR.dyk}</Text>,
|
|
578
|
+
<Markdown text={codify(q.card.fact)} />,
|
|
579
|
+
s.learn ? <Markdown text={codify(q.card.details)} /> : null,
|
|
580
|
+
<Box flexDirection="row" gap={2}>
|
|
581
|
+
{s.learn ? null : <Button key="knew" label={STR.knew} hotkey={hk('i')} onPress={() => askQuestion($)} />}
|
|
582
|
+
<Button key="learn" label={s.learn ? STR.gotIt : STR.learnMore} variant="primary" hotkey={hk('m')} onPress={() => (s.learn ? askQuestion($) : learnMore($))} />
|
|
583
|
+
</Box>,
|
|
584
|
+
)
|
|
585
|
+
}
|
|
586
|
+
|
|
560
587
|
const stem = <Markdown text={app ? headingParagraphs(codify(q.stem)) : codify(q.stem)} />
|
|
561
588
|
|
|
562
589
|
if (s.step === 'feedback' || s.step === 'skipped') {
|
|
@@ -604,18 +631,21 @@ export const register: Register = on => {
|
|
|
604
631
|
{note && !app ? <Text wrap="wrap" dimColor={!chosen} color={chosen ? PICKED.note : undefined}>{`\n ${note}`}</Text> : null}
|
|
605
632
|
</Button>
|
|
606
633
|
)
|
|
607
|
-
|
|
634
|
+
// The desktop app draws each answer as one pressable region, so a click on its padding or note picks too (card.tsx);
|
|
635
|
+
// the demo can switch back to the native buttons to compare.
|
|
636
|
+
const wholeCard = desktop && (s.demo ? s.demo.style === 'client' : true)
|
|
637
|
+
const cardProps = (id: string, over: Partial<CardProps>): CardProps => ({ id, label: '', note: '', chosen: false, locked, brand: BRAND, fill: PICKED.bg, text: PICKED.text, noteText: PICKED.note, ...over })
|
|
608
638
|
const options = q.options.map((o, i) => {
|
|
609
639
|
const chosen = !s.draft.other && s.draft.picked === o.id
|
|
610
|
-
// The whole card is one pressable region, so a click on its padding or note picks too (card.tsx).
|
|
611
640
|
if (wholeCard) {
|
|
612
|
-
const props
|
|
641
|
+
const props = cardProps(o.id, { label: plainLabel(o.label), note: o.note ? plainLabel(o.note) : '', n: i + 1, chosen })
|
|
613
642
|
return <Client key={`card-${o.id}`} module="./card.tsx" width="100%" props={props} />
|
|
614
643
|
}
|
|
615
644
|
return card(
|
|
616
645
|
o.id,
|
|
617
646
|
chosen,
|
|
618
|
-
|
|
647
|
+
// The terminal's plain Button draws its own `1:`; the other surfaces number the label themselves.
|
|
648
|
+
answer(o.id, `opt-${o.id}`, String(i + 1), app ? `${i + 1} ${plainLabel(o.label)}` : plainLabel(o.label), chosen, o.note ? plainLabel(o.note) : undefined),
|
|
619
649
|
// The desktop app draws only a Button's label, not its inline children, so there the note sits under the button.
|
|
620
650
|
app && o.note
|
|
621
651
|
? [<Text key={`note-${o.id}`} wrap="wrap" dimColor={!chosen} color={chosen ? PICKED.note : undefined}>{plainLabel(o.note)}</Text>]
|
|
@@ -630,13 +660,17 @@ export const register: Register = on => {
|
|
|
630
660
|
<Text color="warning" bold>
|
|
631
661
|
{STR.experimentBanner}
|
|
632
662
|
</Text>
|
|
633
|
-
{
|
|
663
|
+
{vector ? (
|
|
634
664
|
<Box flexDirection="column" gap={1}>
|
|
635
665
|
<Text dimColor>{STR.experimentSvg}</Text>
|
|
636
666
|
<Svg alt={STR.experimentImageAlt} width={208} height={96} source={demoSvg()} />
|
|
637
667
|
<Text dimColor>{STR.experimentSvgPng}</Text>
|
|
638
668
|
<Svg alt={STR.experimentImageAlt} width={208} height={96} source={demoSvgWithPng()} />
|
|
639
669
|
</Box>
|
|
670
|
+
) : app ? (
|
|
671
|
+
<Text dimColor wrap="wrap">
|
|
672
|
+
{STR.experimentNone}
|
|
673
|
+
</Text>
|
|
640
674
|
) : (
|
|
641
675
|
<Box flexDirection="column">
|
|
642
676
|
<Text dimColor wrap="wrap">
|
|
@@ -652,26 +686,48 @@ export const register: Register = on => {
|
|
|
652
686
|
stem,
|
|
653
687
|
<Box flexDirection="column" gap={app ? 2 : 0} marginTop={app ? 1 : 0}>
|
|
654
688
|
{options}
|
|
655
|
-
{
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
s.draft.other ? (
|
|
661
|
-
<Box key="other-box"
|
|
689
|
+
{wholeCard ? (
|
|
690
|
+
// The header row is the pressable region; the frame and the text box are ours. Three lines tall, saved on every keystroke,
|
|
691
|
+
// so the button the field draws beside itself has nothing to do: its label is left empty to try to hide it.
|
|
692
|
+
<Box key="card-other" flexDirection="column" borderStyle={s.draft.other ? 'bold' : 'single'} borderColor={s.draft.other ? BRAND : 'inactive'}>
|
|
693
|
+
<Client key="other-head" module="./card.tsx" width="100%" props={cardProps('other', { label: STR.other, chosen: s.draft.other, bare: true })} />
|
|
694
|
+
{s.draft.other ? (
|
|
695
|
+
<Box key="other-box" paddingX={2} paddingBottom={1}>
|
|
662
696
|
<Input
|
|
663
697
|
key="other-text"
|
|
664
698
|
autoFocus
|
|
699
|
+
rows={3}
|
|
665
700
|
placeholder={STR.otherPlaceholder}
|
|
666
701
|
value={s.draft.text}
|
|
667
|
-
submitLabel="
|
|
702
|
+
submitLabel=""
|
|
668
703
|
onInput={(value: string) => (locked ? undefined : typeOther($, value))}
|
|
669
704
|
onSubmit={() => (locked ? undefined : keepOther($))}
|
|
670
705
|
/>
|
|
671
706
|
</Box>
|
|
672
|
-
) : null
|
|
673
|
-
|
|
674
|
-
|
|
707
|
+
) : null}
|
|
708
|
+
</Box>
|
|
709
|
+
) : (
|
|
710
|
+
card(
|
|
711
|
+
'other',
|
|
712
|
+
s.draft.other,
|
|
713
|
+
answer('other', 'opt-other', 'o', STR.other, s.draft.other),
|
|
714
|
+
[
|
|
715
|
+
s.draft.other ? (
|
|
716
|
+
<Box key="other-box" paddingLeft={3}>
|
|
717
|
+
<Input
|
|
718
|
+
key="other-text"
|
|
719
|
+
autoFocus
|
|
720
|
+
placeholder={STR.otherPlaceholder}
|
|
721
|
+
value={s.draft.text}
|
|
722
|
+
submitLabel="keep"
|
|
723
|
+
onInput={(value: string) => (locked ? undefined : typeOther($, value))}
|
|
724
|
+
onSubmit={() => (locked ? undefined : keepOther($))}
|
|
725
|
+
/>
|
|
726
|
+
</Box>
|
|
727
|
+
) : null,
|
|
728
|
+
],
|
|
729
|
+
s.draft.other,
|
|
730
|
+
)
|
|
675
731
|
)}
|
|
676
732
|
</Box>,
|
|
677
733
|
locked ? <Text dimColor>{STR.grading}</Text> : null,
|
|
@@ -689,7 +745,16 @@ export const register: Register = on => {
|
|
|
689
745
|
// Teach me has a row of its own, under Submit. A Button takes no fill, and a desktop draws a plain
|
|
690
746
|
// one without its grey chrome: the orange box is the button's body, and as a column it
|
|
691
747
|
// stretches the Button across its width, so all but the thin padding is pressable.
|
|
692
|
-
locked ? null :
|
|
748
|
+
locked ? null : desktop ? (
|
|
749
|
+
// A compact pill whose whole body is pressable (pill.tsx), sized to its text instead of the pane's width.
|
|
750
|
+
<Box key="teach-row" flexDirection="row">
|
|
751
|
+
<Client
|
|
752
|
+
key="teach-client"
|
|
753
|
+
module="./pill.tsx"
|
|
754
|
+
props={{ id: 'teach', label: STR.teach, locked, fill: TEACH.bg, hoverFill: TEACH.hover, text: TEACH.text } satisfies PillProps}
|
|
755
|
+
/>
|
|
756
|
+
</Box>
|
|
757
|
+
) : app ? (
|
|
693
758
|
<Box key="teach-box" flexDirection="column" backgroundColor={TEACH.bg} borderStyle="round" borderColor={TEACH.bg} paddingX={1} paddingY={0.5}>
|
|
694
759
|
<Button key="teach" plain label={STR.teach} onPress={() => teach($)}>
|
|
695
760
|
<Text color={TEACH.text}>{STR.teach}</Text>
|
|
@@ -750,6 +815,16 @@ async function keepOther($: EngineInterface): Promise<void> {
|
|
|
750
815
|
}
|
|
751
816
|
}
|
|
752
817
|
|
|
818
|
+
/** "I knew this" and "Got it": the card is done, the question follows. */
|
|
819
|
+
async function askQuestion($: EngineInterface): Promise<void> {
|
|
820
|
+
await update($, quiz, (s: PanelState) => (s.step === 'card' ? { ...s, step: 'awaiting', learn: false } : s))
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/** "I want to learn more": the longer version shows under the fact, and the card stays until Got it. */
|
|
824
|
+
async function learnMore($: EngineInterface): Promise<void> {
|
|
825
|
+
await update($, quiz, (s: PanelState) => (s.step === 'card' ? { ...s, learn: true } : s))
|
|
826
|
+
}
|
|
827
|
+
|
|
753
828
|
/** "Teach me": a blank the learner asks to have taught. Recorded as dont_know; the explainer starts like it does for a miss. */
|
|
754
829
|
async function teach($: EngineInterface): Promise<void> {
|
|
755
830
|
await submit($, { kind: 'dont_know' })
|
|
@@ -15,6 +15,8 @@ export type PanelQuestion = {
|
|
|
15
15
|
tier: number
|
|
16
16
|
/** More questions of this round follow: the pane offers Next. */
|
|
17
17
|
more: boolean
|
|
18
|
+
/** The Did You Know card shown before the question; absent on a question without one. */
|
|
19
|
+
card?: { fact: string; details: string }
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/** The learner's unsent answer. Selecting writes here and never submits. */
|
|
@@ -45,7 +47,7 @@ export type PanelResult = {
|
|
|
45
47
|
explain?: { instruction: string; attempt_id: number }
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
export type PanelStep = 'none' | 'loading' | 'awaiting' | 'grading' | 'feedback' | 'skipped' | 'error'
|
|
50
|
+
export type PanelStep = 'none' | 'loading' | 'card' | 'awaiting' | 'grading' | 'feedback' | 'skipped' | 'error'
|
|
49
51
|
|
|
50
52
|
export type PanelState = {
|
|
51
53
|
step: PanelStep
|
|
@@ -55,6 +57,8 @@ export type PanelState = {
|
|
|
55
57
|
result: PanelResult | null
|
|
56
58
|
/** Words for the learner: why the pane is in `error`, or a one-line notice in `none`. */
|
|
57
59
|
message: string | null
|
|
60
|
+
/** On the card step: "I want to learn more" was pressed, so the longer version shows. */
|
|
61
|
+
learn?: boolean
|
|
58
62
|
/**
|
|
59
63
|
* Set only by `/eklavya-panel-demo`: the question is a mock, answered on this machine and never sent to the
|
|
60
64
|
* server. `style` is how the desktop draws the answer cards; `last` is the latest click, for the tester.
|
|
@@ -26,6 +26,7 @@ Make one call to `present_question` instead:
|
|
|
26
26
|
shape of the idea (rows two and four of the table), **1** for one built on a
|
|
27
27
|
misconception (rows one and three). Grade 3 is not available to a pick: only
|
|
28
28
|
typed words can show a hesitant "right".
|
|
29
|
+
- `did_you_know`: `{fact, details}`, the card the panel shows before the question. `fact` is two or three plain sentences teaching the concept itself, tied to this project when it can be; `details` is what "I want to learn more" opens: the mechanism, one concrete example, the usual pitfall. Teach, never quiz: neither may give away the answer to the question, and neither repeats the `explanation`. Mark code in backticks as below.
|
|
29
30
|
- `more: true` only in an explicit round (the plan has more items after this one, as for `/eklavya:quiz`): the panel then offers a Next button. Leave it out otherwise. Once a round is planned the server tracks it: the last question's `more` is set false for you, and Next arrives as a prompt telling you to call `get_session_quiz_plan` with `resume_round: true`.
|
|
30
31
|
- **Mark the code.** The panel draws the stem, each `description` and the `explanation` as Markdown, so
|
|
31
32
|
put every function, call, class, file and flag in backticks (`` `tester.pumpWidget(widget)` ``,
|
package/dist/session.js
CHANGED
|
@@ -56,7 +56,8 @@ export function setCurrentSession(db, sessionId, cwd) {
|
|
|
56
56
|
* pointer) and every work tool call (stamped by the checkpoint hook): an agent
|
|
57
57
|
* working alone for seventy minutes after one prompt is not idle, and measuring
|
|
58
58
|
* from prompts alone made that whole task stale the moment the developer typed
|
|
59
|
-
* a follow-up.
|
|
59
|
+
* a follow-up. With `quietMinutes` the stretch also starts no earlier than that
|
|
60
|
+
* long after the session's first activity.
|
|
60
61
|
*/
|
|
61
62
|
const ACTIVITY_PREFIX = 'activity:';
|
|
62
63
|
export function noteActivity(db, sessionId, at = new Date()) {
|
|
@@ -67,20 +68,47 @@ export function noteActivity(db, sessionId, at = new Date()) {
|
|
|
67
68
|
// boundary, because work logged before it (a session that predates this
|
|
68
69
|
// stamp, or whose first stamp is a tool call) is still this stretch's work.
|
|
69
70
|
// Only a real break starts a bounded stretch.
|
|
70
|
-
const [last, since = ''] = row ? row.value.split('|') : [];
|
|
71
|
+
const [last, since = '', first = ''] = row ? row.value.split('|') : [];
|
|
71
72
|
const lastMs = parseStamp(last);
|
|
72
73
|
const broke = lastMs !== null && at.getTime() - lastMs > IDLE_BREAK_MINUTES * 60_000;
|
|
73
74
|
if (!row) {
|
|
74
75
|
db.prepare(`DELETE FROM meta WHERE key LIKE ? AND substr(value, 1, 10) < date('now', '-7 day')`).run(`${ACTIVITY_PREFIX}%`);
|
|
75
76
|
}
|
|
76
77
|
db.prepare(`INSERT INTO meta (key, value) VALUES (?, ?)
|
|
77
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(key, `${now}|${broke ? now : since}`);
|
|
78
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(key, `${now}|${broke ? now : since}|${row ? first : now}`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Minutes left of the quiet start of a session: `quietMinutes` after its first
|
|
82
|
+
* activity. 0 when the period is over, switched off, or the session's first
|
|
83
|
+
* activity is unknown (a record from before it was kept): any doubt asks.
|
|
84
|
+
*/
|
|
85
|
+
export function quietMinutesLeft(db, sessionId, quietMinutes) {
|
|
86
|
+
if (quietMinutes <= 0)
|
|
87
|
+
return 0;
|
|
88
|
+
try {
|
|
89
|
+
const row = db.prepare('SELECT value FROM meta WHERE key = ?').get(`${ACTIVITY_PREFIX}${sessionId}`);
|
|
90
|
+
const first = parseStamp(row?.value.split('|')[2]);
|
|
91
|
+
return first === null ? 0 : Math.max(0, Math.ceil(quietMinutes - (Date.now() - first) / 60_000));
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
78
96
|
}
|
|
79
97
|
/** The start of the session's current stretch of work, or null for "since it began". */
|
|
80
|
-
export function workSince(db, sessionId) {
|
|
98
|
+
export function workSince(db, sessionId, quietMinutes = 0) {
|
|
81
99
|
try {
|
|
82
100
|
const row = db.prepare('SELECT value FROM meta WHERE key = ?').get(`${ACTIVITY_PREFIX}${sessionId}`);
|
|
83
|
-
|
|
101
|
+
const [, since = '', first = ''] = row ? row.value.split('|') : [];
|
|
102
|
+
// Work logged inside the quiet start is setup (a worktree, a branch): it is
|
|
103
|
+
// never asked, even after the quiet is over. So the stretch begins at its end
|
|
104
|
+
// when that is later than the idle-break boundary.
|
|
105
|
+
const firstMs = parseStamp(first);
|
|
106
|
+
if (quietMinutes > 0 && firstMs !== null) {
|
|
107
|
+
const quietEnd = firstMs + quietMinutes * 60_000;
|
|
108
|
+
if ((parseStamp(since) ?? 0) < quietEnd)
|
|
109
|
+
return new Date(quietEnd).toISOString();
|
|
110
|
+
}
|
|
111
|
+
return since || null;
|
|
84
112
|
}
|
|
85
113
|
catch {
|
|
86
114
|
return null;
|