kaizen-agent 1.44.0 → 1.46.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/cli/settings.test.ts +8 -0
- package/cli/settings.ts +2 -0
- package/commands/kaizen-lite.md +1 -1
- package/package.json +3 -1
- package/skills/kaizen/SKILL.md +10 -5
- package/skills/kaizen/config.default.yml +8 -0
- package/skills/kaizen/settings.md +3 -1
- package/skills/kaizen/spec-main.md +1 -1
- package/skills/kaizen/spec.md +1 -0
- package/skills/kaizen-help/SKILL.md +2 -1
- package/web/board/api.ts +10 -0
- package/web/board/cards.ts +2 -2
- package/web/board/terms.ts +59 -5
- package/web/board/toast.ts +3 -2
- package/web/board.html +7 -2
- package/web/board.js +26 -25
- package/web/notebook.js +1 -1
- package/web/term.js +61 -35
- package/web/term.ts +59 -0
package/web/term.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import { Terminal } from "@xterm/xterm";
|
|
5
5
|
import { FitAddon } from "@xterm/addon-fit";
|
|
6
6
|
import { WebglAddon } from "@xterm/addon-webgl";
|
|
7
|
+
import { WebLinksAddon } from "@xterm/addon-web-links";
|
|
8
|
+
import { SearchAddon } from "@xterm/addon-search";
|
|
7
9
|
|
|
8
10
|
function mountTerm(el: HTMLElement, key: string, onEnd?: () => void): () => void {
|
|
9
11
|
const css = getComputedStyle(el);
|
|
@@ -13,6 +15,7 @@ function mountTerm(el: HTMLElement, key: string, onEnd?: () => void): () => void
|
|
|
13
15
|
fontFamily: tok("--mono"),
|
|
14
16
|
fontSize: 12,
|
|
15
17
|
scrollback: 5000,
|
|
18
|
+
allowProposedApi: true, // search match decorations
|
|
16
19
|
theme: {
|
|
17
20
|
background: tok("--bg"),
|
|
18
21
|
foreground: tok("--ink-hi"),
|
|
@@ -22,6 +25,9 @@ function mountTerm(el: HTMLElement, key: string, onEnd?: () => void): () => void
|
|
|
22
25
|
});
|
|
23
26
|
const fit = new FitAddon();
|
|
24
27
|
term.loadAddon(fit);
|
|
28
|
+
term.loadAddon(new WebLinksAddon((_e, url) => window.open(url, "_blank", "noopener")));
|
|
29
|
+
const search = new SearchAddon();
|
|
30
|
+
term.loadAddon(search);
|
|
25
31
|
term.open(el);
|
|
26
32
|
// The DOM renderer lags on a full-screen agent's constant redraws; WebGL keeps up.
|
|
27
33
|
// No WebGL, or the context lost: xterm.js falls back to the DOM renderer by itself.
|
|
@@ -148,6 +154,58 @@ function mountTerm(el: HTMLElement, key: string, onEnd?: () => void): () => void
|
|
|
148
154
|
};
|
|
149
155
|
el.addEventListener("touchstart", touchStart, { passive: true });
|
|
150
156
|
el.addEventListener("touchmove", touchMove, { passive: false });
|
|
157
|
+
// Top-right strip: search the output (all devices; Ctrl/Cmd+Shift+F from the terminal)
|
|
158
|
+
// and, with a mouse, Paste — phones already have Paste in the key bar.
|
|
159
|
+
const tools = document.createElement("div");
|
|
160
|
+
tools.className = "termtools";
|
|
161
|
+
const tool = (label: string, title: string, fn: () => void) => {
|
|
162
|
+
const b = document.createElement("button");
|
|
163
|
+
b.type = "button";
|
|
164
|
+
b.textContent = label;
|
|
165
|
+
b.title = title;
|
|
166
|
+
b.addEventListener("mousedown", (e) => e.preventDefault());
|
|
167
|
+
b.addEventListener("click", fn);
|
|
168
|
+
return b;
|
|
169
|
+
};
|
|
170
|
+
const q = document.createElement("input");
|
|
171
|
+
q.type = "search";
|
|
172
|
+
q.placeholder = "Search";
|
|
173
|
+
const deco = { matchBackground: "#7a5c00", activeMatchBackground: "#d08000", matchOverviewRuler: "#d08000", activeMatchColorOverviewRuler: "#ff9900" };
|
|
174
|
+
const find = (back = false) => {
|
|
175
|
+
if (!q.value) return search.clearDecorations();
|
|
176
|
+
const o = { decorations: deco };
|
|
177
|
+
back ? search.findPrevious(q.value, o) : search.findNext(q.value, o);
|
|
178
|
+
};
|
|
179
|
+
const box = document.createElement("span");
|
|
180
|
+
box.className = "tsearch";
|
|
181
|
+
box.hidden = true;
|
|
182
|
+
const closeSearch = () => { box.hidden = true; search.clearDecorations(); term.focus(); };
|
|
183
|
+
const openSearch = () => { box.hidden = false; q.select(); q.focus(); };
|
|
184
|
+
q.addEventListener("input", () => find());
|
|
185
|
+
q.addEventListener("keydown", (e) => {
|
|
186
|
+
if (e.key === "Enter") { e.preventDefault(); find(e.shiftKey); }
|
|
187
|
+
else if (e.key === "Escape") { e.preventDefault(); closeSearch(); }
|
|
188
|
+
});
|
|
189
|
+
box.append(q, tool("↑", "Previous (Shift+Enter)", () => find(true)), tool("↓", "Next (Enter)", () => find()), tool("✕", "Close (Esc)", closeSearch));
|
|
190
|
+
tools.append(box, tool("⌕", "Search (Ctrl+Shift+F)", () => (box.hidden ? openSearch() : closeSearch())));
|
|
191
|
+
// A refused read (permission, or a plain-http origin) says so on the button for a moment.
|
|
192
|
+
const pasteBtn = tool("Paste", "Paste from clipboard", () => {
|
|
193
|
+
const no = () => { pasteBtn.textContent = "Blocked"; setTimeout(() => (pasteBtn.textContent = "Paste"), 1500); };
|
|
194
|
+
if (!navigator.clipboard?.readText) no();
|
|
195
|
+
else navigator.clipboard.readText().then((t) => t && term.paste(t), no);
|
|
196
|
+
term.focus();
|
|
197
|
+
});
|
|
198
|
+
if (!bar) tools.append(pasteBtn);
|
|
199
|
+
el.append(tools);
|
|
200
|
+
// xterm keeps one custom key handler: add further shortcuts here, not in a second call.
|
|
201
|
+
term.attachCustomKeyEventHandler((e) => {
|
|
202
|
+
if (e.type === "keydown" && (e.ctrlKey || e.metaKey) && e.shiftKey && e.code === "KeyF") {
|
|
203
|
+
e.preventDefault();
|
|
204
|
+
openSearch();
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
return true;
|
|
208
|
+
});
|
|
151
209
|
// Each resize makes the agent redraw its whole screen, so a panel animating or a
|
|
152
210
|
// soft keyboard opening sends one, not dozens.
|
|
153
211
|
let resizing: Timer | undefined;
|
|
@@ -162,6 +220,7 @@ function mountTerm(el: HTMLElement, key: string, onEnd?: () => void): () => void
|
|
|
162
220
|
el.removeEventListener("touchmove", touchMove);
|
|
163
221
|
typed.dispose();
|
|
164
222
|
bar?.remove();
|
|
223
|
+
tools.remove();
|
|
165
224
|
ws.onclose = null;
|
|
166
225
|
ws.close();
|
|
167
226
|
term.dispose();
|