@mjasnikovs/pi-task 0.14.13 → 0.14.15
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.
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { getKeybindings, visibleWidth, wrapTextWithAnsi } from '@earendil-works/pi-tui';
|
|
19
19
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
20
|
-
/** Left gutter: two columns reserved for the
|
|
20
|
+
/** Left gutter: two columns reserved for the cursor bar so boxes stay aligned. */
|
|
21
21
|
const GUTTER = 2;
|
|
22
|
+
/** Cap the dialog at a readable column count. Without this the boxes stretch the
|
|
23
|
+
* full terminal width on wide/ultrawide screens — long question lines become
|
|
24
|
+
* hard to scan and short answers leave a huge empty right margin inside the box. */
|
|
25
|
+
const MAX_CONTENT_WIDTH = 96;
|
|
22
26
|
const RECOMMENDED_TAG = 'RECOMMENDED';
|
|
23
27
|
/** Smallest box that still fits "┌─ RECOMMENDED ─┐". Below this we drop the tag. */
|
|
24
28
|
const TAG_MIN_BOX_WIDTH = visibleWidth(`┌─ ${RECOMMENDED_TAG} ─┐`);
|
|
@@ -49,9 +53,10 @@ function renderCard(card, selected, boxWidth, c) {
|
|
|
49
53
|
const bodyLines = wrapTextWithAnsi(card.label, innerWidth);
|
|
50
54
|
const body = (bodyLines.length > 0 ? bodyLines : ['']).map(line => borderFn('│ ') + padTo(line, innerWidth) + borderFn(' │'));
|
|
51
55
|
const bottom = borderFn(`└${dash(boxWidth - 2)}┘`);
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
// A full-height accent bar in the gutter marks the selected card — far more
|
|
57
|
+
// visible than a single "▸" glyph on the top border alone.
|
|
58
|
+
const cursor = selected ? c.arrow('▌') + ' ' : ' ';
|
|
59
|
+
return [cursor + top, ...body.map(b => cursor + b), cursor + bottom];
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Lay the whole dialog out for `width` columns: a QUESTION label + wrapped
|
|
@@ -59,7 +64,7 @@ function renderCard(card, selected, boxWidth, c) {
|
|
|
59
64
|
* highlighted with an accent border and "▸" arrow), and a key-hint footer.
|
|
60
65
|
*/
|
|
61
66
|
export function renderQuestionBox(width, question, cards, selected, c, hintText = HINT_TEXT) {
|
|
62
|
-
const W = Math.max(width, 12);
|
|
67
|
+
const W = Math.min(Math.max(width, 12), MAX_CONTENT_WIDTH);
|
|
63
68
|
const boxWidth = Math.max(6, W - GUTTER);
|
|
64
69
|
const out = [''];
|
|
65
70
|
out.push(' ' + c.questionLabel(QUESTION_LABEL));
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-line startup hint shown when no Brave Search key is configured.
|
|
3
|
+
*
|
|
4
|
+
* pi-task's web-search worker needs BRAVE_SEARCH_API_KEY (or BRAVE_API_KEY).
|
|
5
|
+
* When neither is set we surface a single, unobtrusive widget line on session
|
|
6
|
+
* start so the user knows search is disabled — it never blocks work and clears
|
|
7
|
+
* itself on the first interaction (any keystroke).
|
|
8
|
+
*/
|
|
9
|
+
import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
|
|
10
|
+
export declare function registerBraveKeyWarning(pi: ExtensionAPI): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-line startup hint shown when no Brave Search key is configured.
|
|
3
|
+
*
|
|
4
|
+
* pi-task's web-search worker needs BRAVE_SEARCH_API_KEY (or BRAVE_API_KEY).
|
|
5
|
+
* When neither is set we surface a single, unobtrusive widget line on session
|
|
6
|
+
* start so the user knows search is disabled — it never blocks work and clears
|
|
7
|
+
* itself on the first interaction (any keystroke).
|
|
8
|
+
*/
|
|
9
|
+
const WIDGET_KEY = 'pi-task-brave-warning';
|
|
10
|
+
const WARNING = '⚠ pi-task: BRAVE_SEARCH_API_KEY not set — web search is disabled. '
|
|
11
|
+
+ 'Get a free key at https://api.search.brave.com/app/keys';
|
|
12
|
+
/** Mirrors the lookup in search-core so the hint matches what the worker reads. */
|
|
13
|
+
function hasBraveKey() {
|
|
14
|
+
return Boolean(process.env.BRAVE_SEARCH_API_KEY ?? process.env.BRAVE_API_KEY);
|
|
15
|
+
}
|
|
16
|
+
export function registerBraveKeyWarning(pi) {
|
|
17
|
+
pi.on('session_start', (_event, ctx) => {
|
|
18
|
+
// Terminal-only hint: needs an interactive TUI to render and to catch the
|
|
19
|
+
// keystroke that dismisses it. Skip when a key is already present.
|
|
20
|
+
if (ctx.mode !== 'tui' || hasBraveKey())
|
|
21
|
+
return;
|
|
22
|
+
let unsubscribe = null;
|
|
23
|
+
const clear = () => {
|
|
24
|
+
try {
|
|
25
|
+
ctx.ui.setWidget(WIDGET_KEY, undefined);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
/* stale ctx after a session switch — nothing to clear */
|
|
29
|
+
}
|
|
30
|
+
unsubscribe?.();
|
|
31
|
+
unsubscribe = null;
|
|
32
|
+
};
|
|
33
|
+
try {
|
|
34
|
+
ctx.ui.setWidget(WIDGET_KEY, [ctx.ui.theme.fg('warning', WARNING)]);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Disappear on any interaction — the first raw keystroke clears it.
|
|
40
|
+
// Returning undefined leaves the input untouched (we only observe it).
|
|
41
|
+
unsubscribe = ctx.ui.onTerminalInput(() => {
|
|
42
|
+
clear();
|
|
43
|
+
return undefined;
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
package/dist/workers/index.js
CHANGED
|
@@ -2,9 +2,11 @@ import { registerPiWorker } from './pi-worker.js';
|
|
|
2
2
|
import { registerPiWorkerSearch } from './pi-worker-search.js';
|
|
3
3
|
import { registerPiWorkerFetch } from './pi-worker-fetch.js';
|
|
4
4
|
import { registerPiWorkerDocs } from './pi-worker-docs.js';
|
|
5
|
+
import { registerBraveKeyWarning } from './brave-warning.js';
|
|
5
6
|
export function registerWorkers(pi) {
|
|
6
7
|
registerPiWorker(pi);
|
|
7
8
|
registerPiWorkerSearch(pi);
|
|
8
9
|
registerPiWorkerFetch(pi);
|
|
9
10
|
registerPiWorkerDocs(pi);
|
|
11
|
+
registerBraveKeyWarning(pi);
|
|
10
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mjasnikovs/pi-task",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.15",
|
|
4
4
|
"description": "Deterministic spec-orchestration for local models, with a bundled real-time remote web view and web/docs/fetch/worker subagent tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|