@turri-dev/cli 0.1.4-next.4342332 → 0.1.4-next.5a8c6e5
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 +1 -1
- package/assets/jellyfish/dark-00.png +0 -0
- package/assets/jellyfish/dark-01.png +0 -0
- package/assets/jellyfish/dark-02.png +0 -0
- package/assets/jellyfish/dark-03.png +0 -0
- package/assets/jellyfish/dark-04.png +0 -0
- package/assets/jellyfish/dark-05.png +0 -0
- package/assets/jellyfish/dark-06.png +0 -0
- package/assets/jellyfish/dark-07.png +0 -0
- package/assets/jellyfish/dark-08.png +0 -0
- package/assets/jellyfish/dark-09.png +0 -0
- package/assets/jellyfish/dark-10.png +0 -0
- package/assets/jellyfish/dark-11.png +0 -0
- package/assets/jellyfish/light-00.png +0 -0
- package/assets/jellyfish/light-01.png +0 -0
- package/assets/jellyfish/light-02.png +0 -0
- package/assets/jellyfish/light-03.png +0 -0
- package/assets/jellyfish/light-04.png +0 -0
- package/assets/jellyfish/light-05.png +0 -0
- package/assets/jellyfish/light-06.png +0 -0
- package/assets/jellyfish/light-07.png +0 -0
- package/assets/jellyfish/light-08.png +0 -0
- package/assets/jellyfish/light-09.png +0 -0
- package/assets/jellyfish/light-10.png +0 -0
- package/assets/jellyfish/light-11.png +0 -0
- package/dist/extension.js +18 -38
- package/dist/jellyfish.js +130 -0
- package/dist/regenerate/plain-palette.js +1 -1
- package/docs/images/turri-banner.png +0 -0
- package/docs/theming.md +3 -3
- package/docs/using.md +1 -1
- package/package.json +1 -1
- package/assets/jellyfish/dark-12.png +0 -0
- package/assets/jellyfish/dark-13.png +0 -0
- package/assets/jellyfish/dark-14.png +0 -0
- package/assets/jellyfish/fallback.txt +0 -252
- package/assets/jellyfish/light-12.png +0 -0
- package/assets/jellyfish/light-13.png +0 -0
- package/assets/jellyfish/light-14.png +0 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<p align="center"><img src="docs/images/turri-banner.png" alt="turri - coding agent with the power of regenerative software:
|
|
1
|
+
<p align="center"><img src="docs/images/turri-banner.png" alt="turri - the first coding agent with the power of regenerative software, beside a pixel jellyfish: npm install -g @turri-dev/cli"></p>
|
|
2
2
|
|
|
3
3
|
<h1 align="center">turri<br>the first coding agent with the power of<br>regenerative software<br> </h1>
|
|
4
4
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/extension.js
CHANGED
|
@@ -5,7 +5,7 @@ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
|
5
5
|
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
6
6
|
import { conversationCommand, conversationSettled, conversationWriting } from "./regenerate/conversation-writes.js";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { allocateImageId, Box, getCapabilities, getPngDimensions, isKeyRelease, isKeyRepeat, matchesKey, renderImage, Text,
|
|
8
|
+
import { allocateImageId, Box, getCapabilities, getPngDimensions, isKeyRelease, isKeyRepeat, matchesKey, renderImage, Text, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
9
9
|
import { defineTool } from "@earendil-works/pi-coding-agent";
|
|
10
10
|
import { Type } from "typebox";
|
|
11
11
|
import { CODING_MODEL_ENV } from "./chat-models.js";
|
|
@@ -30,6 +30,7 @@ import { checkPlainFile, checkPlainTargets, formatCheckResults } from "./plain/c
|
|
|
30
30
|
import { whyFailed } from "./regenerate/diagnose-job.js";
|
|
31
31
|
import { createWorkLoop, describeModules, isUpToDate, previewJobs } from "./regenerate/loop.js";
|
|
32
32
|
import { brandNeon, brandPink, plainPaint } from "./regenerate/plain-palette.js";
|
|
33
|
+
import { halfBlocks, JELLYFISH_FRAME_MS, JELLYFISH_TEXT_FRAMES } from "./jellyfish.js";
|
|
33
34
|
import { createJobPanel, didNotPass, keyPressed, PANEL_KEY, spinner } from "./regenerate/job-panel.js";
|
|
34
35
|
import { clickToFocus, dockedWidth, narrowChat, shade, shadeChat } from "./regenerate/panel-dock.js";
|
|
35
36
|
import { overPictureRow, PICTURE_AT } from "./picture-row.js";
|
|
@@ -47,7 +48,7 @@ import { inheritProviders, inheritThinkingLevel } from "./pi.js";
|
|
|
47
48
|
import { beginCapture, captureConsole, describeCaptured, dropNoise } from "./quiet.js";
|
|
48
49
|
import { loadRules, renderRulesBlock } from "./rules.js";
|
|
49
50
|
import { registerTurriConfig } from "./config-command.js";
|
|
50
|
-
import { describeStdlib
|
|
51
|
+
import { describeStdlib } from "./stdlib.js";
|
|
51
52
|
import { peekKeyListener, runAsk } from "./ask.js";
|
|
52
53
|
import { QuestionDialog } from "./question-dialog.js";
|
|
53
54
|
import { registerStacks } from "./stacks.js";
|
|
@@ -370,7 +371,7 @@ export default function (pi) {
|
|
|
370
371
|
conversationModels = ctx.modelRegistry;
|
|
371
372
|
});
|
|
372
373
|
inheritProviders(() => conversationModels);
|
|
373
|
-
registerBranding(pi,
|
|
374
|
+
registerBranding(pi, discoveredSkills);
|
|
374
375
|
registerInterviewLog(pi);
|
|
375
376
|
registerJobTools(pi, jobs, cwd);
|
|
376
377
|
registerCheckPlain(pi, cwd);
|
|
@@ -2295,7 +2296,7 @@ const BANNER_ENTRY = "turri_banner";
|
|
|
2295
2296
|
export function chatRulesBlock(rules = loadRules(join(PACKAGE_ROOT, "genome", "rules"))) {
|
|
2296
2297
|
return renderRulesBlock(rules);
|
|
2297
2298
|
}
|
|
2298
|
-
function registerBranding(pi,
|
|
2299
|
+
function registerBranding(pi, skills) {
|
|
2299
2300
|
pi.registerCommand("stdlib", {
|
|
2300
2301
|
description: "List the ***plain standard library: the stacks a spec can import instead of writing its implementation reqs.",
|
|
2301
2302
|
handler: async (_args, ctx) => {
|
|
@@ -2310,22 +2311,16 @@ function registerBranding(pi, ruleCount, skills) {
|
|
|
2310
2311
|
const lines = [
|
|
2311
2312
|
`${brandPink(theme)("turri")} ${theme.fg("muted", `v${data.version}`)}` +
|
|
2312
2313
|
(data.commit !== undefined ? theme.fg("dim", ` from a clone, ${data.commit}${data.changed ? " with changes" : ""}`) : ""),
|
|
2313
|
-
theme.fg("text", "
|
|
2314
|
-
theme.fg("muted", `${data.rules} rules · ${data.skills} skill${data.skills === 1 ? "" : "s"}` +
|
|
2315
|
-
(data.projectSkills !== undefined && data.projectSkills > 0 ? ` (${data.projectSkills} the project's)` : "") +
|
|
2316
|
-
(data.stdlib !== undefined && data.stdlib > 0 ? ` · ${data.stdlib} stdlib stacks (/stdlib)` : "") +
|
|
2317
|
-
(data.pending > 0 ? theme.fg("warning", ` (${data.pending} failed to load)`) : "")),
|
|
2314
|
+
theme.fg("text", "the first coding agent with the power of regenerative software"),
|
|
2318
2315
|
// Where the settings are changed, without leaving the chat.
|
|
2319
2316
|
theme.fg("muted", "configure with /turri-config"),
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
...(data.sandbox
|
|
2323
|
-
? [theme.fg(data.sandbox.level === "ok" ? "dim" : data.sandbox.level === "limited" ? "warning" : "error", data.sandbox.text)]
|
|
2324
|
-
: []),
|
|
2317
|
+
// Only what is wrong: skills that did not load, and agents' commands less fenced than they should be.
|
|
2318
|
+
...(data.pending > 0 ? [theme.fg("warning", `${data.pending} skill${data.pending === 1 ? "" : "s"} failed to load`)] : []),
|
|
2319
|
+
...(data.sandbox !== undefined && data.sandbox.level !== "ok" ? [theme.fg(data.sandbox.level === "limited" ? "warning" : "error", data.sandbox.text)] : []),
|
|
2325
2320
|
];
|
|
2326
2321
|
// The jellyfish turri is named after, in ink for the theme's background: a picture where the
|
|
2327
2322
|
// terminal shows images, drawn in text where it does not.
|
|
2328
|
-
return new Banner(lines, (rule) => theme.fg("borderMuted", rule), jellyfishArt(theme.appearance, (
|
|
2323
|
+
return new Banner(lines, (rule) => theme.fg("borderMuted", rule), jellyfishArt(theme.appearance, (theme.getColorMode?.() ?? "truecolor") === "truecolor"));
|
|
2329
2324
|
});
|
|
2330
2325
|
pi.on("session_start", (_event, ctx) => {
|
|
2331
2326
|
if (ctx.hasUI)
|
|
@@ -2336,12 +2331,7 @@ function registerBranding(pi, ruleCount, skills) {
|
|
|
2336
2331
|
version: identity.version ?? "0.0.0",
|
|
2337
2332
|
commit: identity.git_commit?.slice(0, 7),
|
|
2338
2333
|
changed: identity.git_dirty === true,
|
|
2339
|
-
rules: ruleCount,
|
|
2340
|
-
skills: skills.skills.length,
|
|
2341
|
-
projectSkills: skills.skills.filter((skill) => skill.origin !== "turri").length,
|
|
2342
2334
|
pending: skills.pending.length,
|
|
2343
|
-
stdlib: stdlibStackCount(),
|
|
2344
|
-
cwd: ctx.cwd,
|
|
2345
2335
|
sandbox: sandboxSummary(),
|
|
2346
2336
|
});
|
|
2347
2337
|
}
|
|
@@ -2350,10 +2340,8 @@ function registerBranding(pi, ruleCount, skills) {
|
|
|
2350
2340
|
}
|
|
2351
2341
|
});
|
|
2352
2342
|
}
|
|
2353
|
-
/** How many rows the banner's jellyfish takes:
|
|
2354
|
-
const JELLYFISH_ROWS =
|
|
2355
|
-
/** How long each frame of the jellyfish shows. */
|
|
2356
|
-
const JELLYFISH_FRAME_MS = 250;
|
|
2343
|
+
/** How many rows the banner's jellyfish takes at most: as tall as the one drawn in text. */
|
|
2344
|
+
const JELLYFISH_ROWS = 10;
|
|
2357
2345
|
/** Which frame of the jellyfish every banner shows, moved on by `animateJellyfish`. */
|
|
2358
2346
|
let jellyfishFrame = 0;
|
|
2359
2347
|
let jellyfishTimer;
|
|
@@ -2473,24 +2461,16 @@ class Banner {
|
|
|
2473
2461
|
}
|
|
2474
2462
|
const jellyfishFrameCache = new Map();
|
|
2475
2463
|
/**
|
|
2476
|
-
* The banner's jellyfish for this terminal: where it shows images, the picture's frames
|
|
2477
|
-
*
|
|
2478
|
-
*
|
|
2464
|
+
* The banner's jellyfish for this terminal: where it shows images, the picture's frames
|
|
2465
|
+
* (scripts/jellyfish-frames.mjs writes them), in the colours for the theme's background; where it does not, the
|
|
2466
|
+
* small one in half blocks. None when the pictures cannot be read.
|
|
2479
2467
|
*/
|
|
2480
|
-
function jellyfishArt(appearance,
|
|
2468
|
+
function jellyfishArt(appearance, truecolor) {
|
|
2481
2469
|
const dir = join(PACKAGE_ROOT, "assets", "jellyfish");
|
|
2482
2470
|
try {
|
|
2483
2471
|
if (getCapabilities().images === null) {
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
.split(/^---$/m)
|
|
2487
|
-
.map((frame) => frame.replace(/^\n+|\n+$/g, "").split("\n"))
|
|
2488
|
-
.filter((frame) => frame.some((line) => line.trim() !== ""));
|
|
2489
|
-
if (drawn.length === 0)
|
|
2490
|
-
return undefined;
|
|
2491
|
-
const columns = Math.max(...drawn.flat().map((line) => visibleWidth(line)));
|
|
2492
|
-
const rows = Math.max(...drawn.map((frame) => frame.length));
|
|
2493
|
-
return { kind: "text", frames: drawn.map((frame) => frame.map((line) => ink(line.padEnd(columns)))), columns, rows };
|
|
2472
|
+
const frames = JELLYFISH_TEXT_FRAMES.map((pixels) => halfBlocks(pixels, appearance, truecolor));
|
|
2473
|
+
return { kind: "text", frames, columns: JELLYFISH_TEXT_FRAMES[0][0].length, rows: frames[0].length };
|
|
2494
2474
|
}
|
|
2495
2475
|
let frames = jellyfishFrameCache.get(appearance);
|
|
2496
2476
|
if (frames === undefined) {
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { sgr } from "./regenerate/plain-palette.js";
|
|
2
|
+
/** The pixels' colours on a dark background and a light one - the tentacles darker on light, where neon does not show. */
|
|
3
|
+
export const JELLYFISH_COLOURS = {
|
|
4
|
+
dark: { p: "#ff5c8d", h: "#ff7fa6", w: "#f4f7f9", o: "#ff7a3d", e: "#732553", N: "#8eebee", n: "#5ce1e6", l: "#85a3b2", g: "#3e5a6b" },
|
|
5
|
+
light: { p: "#ff5c8d", h: "#ff7fa6", w: "#f4f7f9", o: "#ff7a3d", e: "#732553", N: "#3e5a6b", n: "#1e3442", l: "#85a3b2", g: "#85a3b2" },
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* How shut the bell is, frame by frame - a quarter second each: shut quickly, held a moment, opened slowly, at rest
|
|
9
|
+
* until the next stroke.
|
|
10
|
+
*/
|
|
11
|
+
const SHUT = [0.1, 0.55, 0.9, 1, 0.85, 0.7, 0.56, 0.44, 0.33, 0.23, 0.14, 0.06];
|
|
12
|
+
const LARGE = {
|
|
13
|
+
width: 24,
|
|
14
|
+
height: 26,
|
|
15
|
+
open: [6, 12, 16, 18, 20, 22, 22, 24, 24],
|
|
16
|
+
shut: [6, 10, 14, 16, 18, 18, 18, 20, 20],
|
|
17
|
+
glint: [[-3, 2], [-4, 2], [-5, 3], [-6, 4], [-6, 5]],
|
|
18
|
+
shine: [-2, 2],
|
|
19
|
+
gut: [".oo..oo.", "oooooooo", "oooooooo", ".oo..oo."],
|
|
20
|
+
gutRow: 4,
|
|
21
|
+
strands: [
|
|
22
|
+
{ at: -8, length: 10, sway: 1.1, ink: "N" },
|
|
23
|
+
{ at: -4.5, length: 13, sway: 1.3, ink: "N" },
|
|
24
|
+
{ at: -1, length: 14, sway: 0.8, ink: "n" },
|
|
25
|
+
{ at: 2, length: 13, sway: 0.8, ink: "n" },
|
|
26
|
+
{ at: 5.5, length: 13, sway: 1.3, ink: "N" },
|
|
27
|
+
{ at: 9, length: 10, sway: 1.1, ink: "N" },
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
const SMALL = {
|
|
31
|
+
width: 18,
|
|
32
|
+
height: 20,
|
|
33
|
+
open: [4, 10, 12, 14, 16, 18, 18],
|
|
34
|
+
shut: [4, 8, 10, 12, 14, 14, 14],
|
|
35
|
+
glint: [[-2, 1], [-3, 2], [-4, 3]],
|
|
36
|
+
shine: [-1, 1],
|
|
37
|
+
gut: ["oo..oo", "oooooo", "oo..oo"],
|
|
38
|
+
gutRow: 3,
|
|
39
|
+
strands: [
|
|
40
|
+
{ at: -6, length: 8, sway: 0.9, ink: "N" },
|
|
41
|
+
{ at: -3, length: 10, sway: 1, ink: "N" },
|
|
42
|
+
{ at: -0.5, length: 11, sway: 0.7, ink: "n" },
|
|
43
|
+
{ at: 1.5, length: 10, sway: 0.7, ink: "n" },
|
|
44
|
+
{ at: 4, length: 10, sway: 1, ink: "N" },
|
|
45
|
+
{ at: 7, length: 8, sway: 0.9, ink: "N" },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
/** One frame of a design: its height in rows of its width in pixels, "." where there is none. */
|
|
49
|
+
function frame(design, t) {
|
|
50
|
+
const grid = Array.from({ length: design.height }, () => Array(design.width).fill("."));
|
|
51
|
+
const centre = design.width / 2;
|
|
52
|
+
const set = (y, x, pixel, over = true) => {
|
|
53
|
+
if (y < 0 || y >= design.height || x < 0 || x >= design.width)
|
|
54
|
+
return;
|
|
55
|
+
if (over || grid[y][x] === ".")
|
|
56
|
+
grid[y][x] = pixel;
|
|
57
|
+
};
|
|
58
|
+
const shut = SHUT[t % SHUT.length];
|
|
59
|
+
// Shut, it has risen a pixel.
|
|
60
|
+
const top = shut > 0.6 ? 0 : 1;
|
|
61
|
+
const widths = design.open.map((open, row) => 2 * Math.round((open - (open - design.shut[row]) * shut) / 2));
|
|
62
|
+
widths.forEach((width, row) => {
|
|
63
|
+
for (let x = centre - width / 2; x < centre + width / 2; x++)
|
|
64
|
+
set(top + row, x, "p");
|
|
65
|
+
});
|
|
66
|
+
const rimWidth = widths.at(-1);
|
|
67
|
+
const rim = top + widths.length;
|
|
68
|
+
// The underside along the bottom row, the rim scalloped under it.
|
|
69
|
+
for (let x = centre - rimWidth / 2 + 2; x < centre + rimWidth / 2 - 2; x++)
|
|
70
|
+
set(rim - 1, x, "e");
|
|
71
|
+
for (let x = centre - rimWidth / 2; x < centre + rimWidth / 2; x += 2)
|
|
72
|
+
set(rim, x + 1, "p");
|
|
73
|
+
// A glint up on the left, curving with the dome, and a pixel of shine.
|
|
74
|
+
for (const [dx, dy] of design.glint)
|
|
75
|
+
set(top + dy, centre + dx, "h");
|
|
76
|
+
set(top + design.shine[1], centre + design.shine[0], "w");
|
|
77
|
+
const gutLeft = centre - Math.floor(design.gut[0].length / 2);
|
|
78
|
+
design.gut.forEach((line, dy) => [...line].forEach((pixel, dx) => pixel === "o" && set(top + design.gutRow + dy, gutLeft + dx, "o")));
|
|
79
|
+
// The tentacles: rooted under the bell, drawn in as it shuts, swaying - the further down, the later.
|
|
80
|
+
const phase = (2 * Math.PI * t) / SHUT.length;
|
|
81
|
+
design.strands.forEach((strand, i) => {
|
|
82
|
+
const root = centre - 0.5 + strand.at * (rimWidth / design.open.at(-1));
|
|
83
|
+
for (let y = 0; y < strand.length; y++) {
|
|
84
|
+
const x = Math.round(root + strand.sway * Math.sin(phase - y * 0.55 + i * 0.8) * Math.min(1, y / 3));
|
|
85
|
+
const left = strand.length - y;
|
|
86
|
+
// The tips come apart, every other pixel, fading - into code.
|
|
87
|
+
if (left <= 3 && y % 2 === 1)
|
|
88
|
+
continue;
|
|
89
|
+
set(rim + 1 + y, x, left > 5 ? strand.ink : left > 2 ? "l" : "g", false);
|
|
90
|
+
// The oral arms are frilled.
|
|
91
|
+
if (strand.ink === "n" && left > 5 && (y + t) % 3 === 0)
|
|
92
|
+
set(rim + 1 + y, x + (strand.at < 0 ? -1 : 1), "n", false);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return grid.map((row) => row.join(""));
|
|
96
|
+
}
|
|
97
|
+
export const JELLYFISH_WIDTH = LARGE.width;
|
|
98
|
+
export const JELLYFISH_HEIGHT = LARGE.height;
|
|
99
|
+
/** The large jellyfish's frames, a stroke: what the pictures are rendered from. */
|
|
100
|
+
export const JELLYFISH_FRAMES = SHUT.map((_, t) => frame(LARGE, t));
|
|
101
|
+
/** The small jellyfish's frames, a stroke: what a terminal without images draws, in half blocks. */
|
|
102
|
+
export const JELLYFISH_TEXT_FRAMES = SHUT.map((_, t) => frame(SMALL, t));
|
|
103
|
+
/** How long each frame shows. */
|
|
104
|
+
export const JELLYFISH_FRAME_MS = 250;
|
|
105
|
+
/**
|
|
106
|
+
* A frame drawn in half blocks for a terminal that shows no images: two pixels a cell, the upper one the text's colour
|
|
107
|
+
* and the lower one the background's, in as many colours as the terminal has: a column a pixel, a row every two.
|
|
108
|
+
*/
|
|
109
|
+
export function halfBlocks(pixels, appearance, truecolor) {
|
|
110
|
+
const colours = JELLYFISH_COLOURS[appearance];
|
|
111
|
+
const colour = (pixel) => (pixel === undefined || pixel === "." ? undefined : colours[pixel]);
|
|
112
|
+
const rows = [];
|
|
113
|
+
for (let y = 0; y < pixels.length; y += 2) {
|
|
114
|
+
let row = "";
|
|
115
|
+
for (let x = 0; x < (pixels[0]?.length ?? 0); x++) {
|
|
116
|
+
const upper = colour(pixels[y]?.[x]);
|
|
117
|
+
const lower = colour(pixels[y + 1]?.[x]);
|
|
118
|
+
if (upper === undefined && lower === undefined)
|
|
119
|
+
row += " ";
|
|
120
|
+
else if (upper === undefined)
|
|
121
|
+
row += `\x1b[${sgr(lower, false, truecolor)}m▄\x1b[39m`;
|
|
122
|
+
else if (lower === undefined)
|
|
123
|
+
row += `\x1b[${sgr(upper, false, truecolor)}m▀\x1b[39m`;
|
|
124
|
+
else
|
|
125
|
+
row += `\x1b[${sgr(upper, false, truecolor)};${sgr(lower, true, truecolor)}m▀\x1b[39;49m`;
|
|
126
|
+
}
|
|
127
|
+
rows.push(row);
|
|
128
|
+
}
|
|
129
|
+
return rows;
|
|
130
|
+
}
|
|
@@ -47,7 +47,7 @@ const rgb = (hex) => {
|
|
|
47
47
|
return [(value >> 16) & 255, (value >> 8) & 255, value & 255];
|
|
48
48
|
};
|
|
49
49
|
/** A colour's SGR parameters: 24-bit, or the nearest of the 256 where the terminal has no more. */
|
|
50
|
-
function sgr(hex, background, truecolor) {
|
|
50
|
+
export function sgr(hex, background, truecolor) {
|
|
51
51
|
const [r, g, b] = rgb(hex);
|
|
52
52
|
if (truecolor)
|
|
53
53
|
return `${background ? 48 : 38};2;${r};${g};${b}`;
|
|
Binary file
|
package/docs/theming.md
CHANGED
|
@@ -25,14 +25,14 @@ Both themes, the command line's colours, the spec diff's, the banner's jellyfish
|
|
|
25
25
|
| lines | `#22344a` | rules, dividers, frames: `borderMuted`, `mdHr` |
|
|
26
26
|
| path | `#3e5a6b` | the editor's border, what is dim: `dim`, line numbers |
|
|
27
27
|
| grauzone | `#85a3b2` | body text, and what can be skimmed: `text`, `muted` |
|
|
28
|
-
| white | `#f4f7f9` | headings, tool titles, what you typed, the jellyfish |
|
|
28
|
+
| white | `#f4f7f9` | headings, tool titles, what you typed, the jellyfish's shine |
|
|
29
29
|
| siesta tan | `#e9d8c8` | inline code, \*\*\*plain's text in quotes or backticks |
|
|
30
30
|
| eggplant | `#732553` | a removed line's fill in a spec diff |
|
|
31
31
|
| neon | `#5ce1e6` | links, focus, the selection, section labels, \*\*\*plain's concepts in a spec diff: `accent`, `mdLink`, regen's `◆` |
|
|
32
32
|
| neon hover | `#8eebee` | types in code, an added line's fill in a light theme's spec diff |
|
|
33
|
-
| pink | `#ff5c8d` | the wordmark, and what is done - its `✓`, the spec map's `◇` and `◆`: `success` |
|
|
33
|
+
| pink | `#ff5c8d` | the wordmark, the jellyfish's bell, and what is done - its `✓`, the spec map's `◇` and `◆`: `success` |
|
|
34
34
|
| pink hover | `#ff7fa6` | \*\*\*plain's section headers, a removed line's `-`, keywords in code |
|
|
35
|
-
| orange | `#ff7a3d` | the `$` of bash mode, and everything that asks for you - what failed (`✗`), what works with limits, what needs you (the spec map's `!`): `error`, `warning` |
|
|
35
|
+
| orange | `#ff7a3d` | the jellyfish's gut, the `$` of bash mode, and everything that asks for you - what failed (`✗`), what works with limits, what needs you (the spec map's `!`): `error`, `warning` |
|
|
36
36
|
|
|
37
37
|
The design system keeps pink for the one thing to press and orange for the `$` prompt alone. A terminal has no buttons, but it needs status colours, so pink carries what is done and orange everything that asks for you - what failed, what works with limits, what waits on you - the mark (`✗`, `!`, `■`) telling them apart. The palette has no red.
|
|
38
38
|
|
package/docs/using.md
CHANGED
|
@@ -7,7 +7,7 @@ cd ~/my-project
|
|
|
7
7
|
turri
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
That is pi, with turri's tools, skills and themes loaded - `turri` alone, or with pi's options (`turri -c`, `turri --harness-model <m>`). It opens with turri's own banner - the jellyfish it is named after, swimming until the conversation fills the screen: a picture in a terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn in
|
|
10
|
+
That is pi, with turri's tools, skills and themes loaded - `turri` alone, or with pi's options (`turri -c`, `turri --harness-model <m>`). It opens with turri's own banner - the jellyfish it is named after, swimming until the conversation fills the screen: a pixel jellyfish - a pink bell, an orange gut, neon tentacles coming apart into code at their tips - swimming a stroke a loop, its bell shutting and rising, its tentacles following: a picture in a terminal that shows images (Kitty, Ghostty, WezTerm, Warp, iTerm2), and drawn smaller in half blocks in any other, tmux included (`src/jellyfish.ts` draws it, `scripts/jellyfish-frames.mjs` writes the pictures) - turri's version (and, run from a clone, the commit it is on, and whether the clone has changes) and where its settings are changed - and only when something is wrong, skills that failed to load or agents' commands less fenced than they should be - rather than pi's startup header and resource list; `turri --verbose` shows those too. pi's "Update Available" notice is left out - turri's pi is a pinned dependency `pi update` never touches - and the terminal's tab reads `🪼 turri - <folder>`, not pi's `π`. Talk to it: ask it to start a project, add a feature, render a module, fix a spec. It decides which skill or tool applies - but not *how* a skill runs: `cultivate` hands the work to the gated runner, which owns the steps, the gates and the judges (see [skills and gates](skills-and-gates.md)).
|
|
11
11
|
|
|
12
12
|
The skills that build from scratch:
|
|
13
13
|
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
▄▄▆▆██▆▆▄▄
|
|
3
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
4
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
5
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
6
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
7
|
-
) ) ) ║║ ╱ ) )
|
|
8
|
-
( ╱ ╱ ╱╱ ( ( )
|
|
9
|
-
╱ ╱ ) )) ) ) )
|
|
10
|
-
╱ ( ( ) ⁏ ) ) (
|
|
11
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
12
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
13
|
-
# % & .
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
▄▆▆██▆▆▄
|
|
17
|
-
▄▆█▓▒░░░░▒▓█▆▄
|
|
18
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
19
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
20
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
21
|
-
) ) ) ║║ ) ) )
|
|
22
|
-
( ( ( (╱ ( ( (
|
|
23
|
-
╱ ╱ ╱ ╱ ) ) )
|
|
24
|
-
╱ ( ) ) ⁏ ) ) )
|
|
25
|
-
) ⁏ ) ⁏ @ ) ⁏ ╱
|
|
26
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
27
|
-
# % & .
|
|
28
|
-
---
|
|
29
|
-
▄▆██▆▄
|
|
30
|
-
▄▆█▓▒░░▒▓█▆▄
|
|
31
|
-
▄█▓▒░░▒▓▓▒░░▒▓█▄
|
|
32
|
-
▐█▒░░▒▓████▓▒░░▒█▌
|
|
33
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
34
|
-
) ) ) ║║ ) ) )
|
|
35
|
-
( ( ( (( ( ( )
|
|
36
|
-
) ) ) )) ) ) )
|
|
37
|
-
╱ ╱ ( (⁏ ) ) )
|
|
38
|
-
) ⁏ ) ⁏ @ ) ⁏ ╱
|
|
39
|
-
⁏ $ ⁏ ; ⁏ *⁏
|
|
40
|
-
# % & .
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
▄▆██▆▄
|
|
44
|
-
▄▆█▓▒░░▒▓█▆▄
|
|
45
|
-
▄█▓▒░░▒▓▓▒░░▒▓█▄
|
|
46
|
-
▐█▒░░▒▓████▓▒░░▒█▌
|
|
47
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
48
|
-
) ) ) ║║ ) ) )
|
|
49
|
-
( ( ) (( ( ) (
|
|
50
|
-
) ) ))) ) ) )
|
|
51
|
-
╱ ╱ ( (⁏ ( ( )
|
|
52
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
53
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
54
|
-
# % & .
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
▄▆██▆▄
|
|
58
|
-
▄▆█▓▒░░▒▓█▆▄
|
|
59
|
-
▄█▓▒░░▒▓▓▒░░▒▓█▄
|
|
60
|
-
▐█▒░░▒▓████▓▒░░▒█▌
|
|
61
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
62
|
-
) ) ) ║║ ) ) )
|
|
63
|
-
( ) ) )) ) ) (
|
|
64
|
-
) ) ) )) ) ) )
|
|
65
|
-
( ( ( (⁏ ( ( )
|
|
66
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
67
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
68
|
-
# % & .
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
▄▆██▆▄
|
|
72
|
-
▄▆█▓▒░░▒▓█▆▄
|
|
73
|
-
▄█▓▒░░▒▓▓▒░░▒▓█▄
|
|
74
|
-
▐█▒░░▒▓████▓▒░░▒█▌
|
|
75
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
76
|
-
) ) ) ║║ ) ) )
|
|
77
|
-
( ( ) )) ( ) )
|
|
78
|
-
) ) ) ))) ) )
|
|
79
|
-
( ( ( (⁏ ( ( )
|
|
80
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
81
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
82
|
-
# % & .
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
▄▆██▆▄
|
|
86
|
-
▄▆█▓▒░░▒▓█▆▄
|
|
87
|
-
▄█▓▒░░▒▓▓▒░░▒▓█▄
|
|
88
|
-
▐█▒░░▒▓████▓▒░░▒█▌
|
|
89
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
90
|
-
) ) ) ║║ ) ) )
|
|
91
|
-
( ( ((( ( ) )
|
|
92
|
-
) ) ))) ) ) )
|
|
93
|
-
) ( ( (⁏ ( ( )
|
|
94
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
95
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
96
|
-
# % & .
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
▄▆▆██▆▆▄
|
|
101
|
-
▄▆█▓▒░░░░▒▓█▆▄
|
|
102
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
103
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
104
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
105
|
-
) ) ) ║║ ) ) )
|
|
106
|
-
( ( ( (( ( ( )
|
|
107
|
-
) ) ) )) ) ) )
|
|
108
|
-
( ( ) ) ⁏ ( ( (
|
|
109
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
110
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
111
|
-
# % & .
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
▄▆▆██▆▆▄
|
|
115
|
-
▄▆█▓▒░░░░▒▓█▆▄
|
|
116
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
117
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
118
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
119
|
-
) ) ) ║║ ) ) )
|
|
120
|
-
( ( ( (( ( ) )
|
|
121
|
-
╱ ) ) )) ) ) )
|
|
122
|
-
) ( ) )⁏ ( ( )
|
|
123
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
124
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
125
|
-
# % & .
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
▄▆▆██▆▆▄
|
|
129
|
-
▄▆█▓▒░░░░▒▓█▆▄
|
|
130
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
131
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
132
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
133
|
-
) ) ) ║║ ) ) )
|
|
134
|
-
( ( ( (( ( ) (
|
|
135
|
-
╱ ) ) )) ) ) )
|
|
136
|
-
( ( ( )⁏ ( ) )
|
|
137
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
138
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
139
|
-
# % & .
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
▄▆▆██▆▆▄
|
|
143
|
-
▄▆█▓▒░░░░▒▓█▆▄
|
|
144
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
145
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
146
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
147
|
-
) ) ) ║ ) ) )
|
|
148
|
-
( ( ( (( ( ) (
|
|
149
|
-
╱ ╱ ) )) ) ) )
|
|
150
|
-
( ) ( )⁏ ( ) )
|
|
151
|
-
) ⁏ ) ⁏@ ) ⁏ )
|
|
152
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
153
|
-
# % & .
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
▄▄▆▆██▆▆▄▄
|
|
157
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
158
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
159
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
160
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
161
|
-
) ) ) ║ ╱ ) )
|
|
162
|
-
( ╱ ( (( ( ( )
|
|
163
|
-
╱ ) ╱ )) ) ) )
|
|
164
|
-
( ( ) (⁏ ) ) (
|
|
165
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
166
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
167
|
-
# % & .
|
|
168
|
-
---
|
|
169
|
-
|
|
170
|
-
▄▄▆▆██▆▆▄▄
|
|
171
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
172
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
173
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
174
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
175
|
-
) ) ) ║║ ╱ ) )
|
|
176
|
-
( ╱ ( (( ( ( )
|
|
177
|
-
╱ ) ╱ )) ) ) )
|
|
178
|
-
( ( ) (⁏ ) ) (
|
|
179
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
180
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
181
|
-
# % & .
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
▄▄▆▆██▆▆▄▄
|
|
185
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
186
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
187
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
188
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
189
|
-
) ) ) ║║ ╱ ) )
|
|
190
|
-
( ╱ ( (( ( ( )
|
|
191
|
-
╱ ) ╱ )) ) ) )
|
|
192
|
-
( ( ) (⁏ ) ) (
|
|
193
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
194
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
195
|
-
# % & .
|
|
196
|
-
---
|
|
197
|
-
|
|
198
|
-
▄▄▆▆██▆▆▄▄
|
|
199
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
200
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
201
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
202
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
203
|
-
) ) ) ║║ ╱ ╱ )
|
|
204
|
-
( ╱ ╱ ╱╱ ( ) )
|
|
205
|
-
╱ ╱ ) )) ) ) )
|
|
206
|
-
( ( ( ) ⁏ ) ) (
|
|
207
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
208
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
209
|
-
# % & .
|
|
210
|
-
---
|
|
211
|
-
|
|
212
|
-
▄▄▆▆██▆▆▄▄
|
|
213
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
214
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
215
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
216
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
217
|
-
) ) ╱ ║║ ╱ ╱ )
|
|
218
|
-
( ╱ ╱ ╱╱ ( ) )
|
|
219
|
-
╱ ╱ ) )) ) ) )
|
|
220
|
-
( ( ( ) ⁏ ) ) (
|
|
221
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
222
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
223
|
-
# % & .
|
|
224
|
-
---
|
|
225
|
-
|
|
226
|
-
▄▄▆▆██▆▆▄▄
|
|
227
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
228
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
229
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
230
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
231
|
-
) ) ╱ ║║ ╱ ╱ )
|
|
232
|
-
( ╱ ╱ ╱╱ ( ) )
|
|
233
|
-
╱ ╱ ) )) ) ) )
|
|
234
|
-
( ( ( ) ⁏ ) ) (
|
|
235
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
236
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
237
|
-
# % & .
|
|
238
|
-
---
|
|
239
|
-
|
|
240
|
-
▄▄▆▆██▆▆▄▄
|
|
241
|
-
▄▆█▓▒░░░░░░▒▓█▆▄
|
|
242
|
-
▄█▓▒░ ░▒▒▒▒░ ░▒▓█▄
|
|
243
|
-
▐█▒░ ░▒▓████▓▒░ ░▒█▌
|
|
244
|
-
▝█▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█▘
|
|
245
|
-
) ) ) ║║ ╱ ╱ )
|
|
246
|
-
( ╱ ╱ ╱╱ ( ) )
|
|
247
|
-
╱ ╱ ) )) ) ) )
|
|
248
|
-
( ( ( ) ⁏ ) ) (
|
|
249
|
-
) ⁏ ) ⁏ @ ) ⁏ )
|
|
250
|
-
⁏ $ ⁏ ; ⁏ * ⁏
|
|
251
|
-
# % & .
|
|
252
|
-
---
|
|
Binary file
|
|
Binary file
|
|
Binary file
|