synthesisui 0.16.488 → 0.16.490
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/dist/claude-md.js +2 -1
- package/dist/commands/mcp.js +11 -3
- package/dist/doctor/transcribe.js +53 -6
- package/dist/install-marks.js +1 -1
- package/dist/preferences.js +51 -6
- package/package.json +1 -1
package/dist/claude-md.js
CHANGED
|
@@ -467,7 +467,8 @@ written now** - read the code before you edit it, never a remembered signature.`
|
|
|
467
467
|
? `
|
|
468
468
|
|
|
469
469
|
**Their page blueprints are on:** call \`preferences\` with the page's kind before building one, unless
|
|
470
|
-
they say not to (\`synthesisui preferences off\`)
|
|
470
|
+
they say not to (\`synthesisui preferences off\`), for one landing part with its \`section\`; a correction to keep
|
|
471
|
+
is \`remember_preference\`.`
|
|
471
472
|
: "";
|
|
472
473
|
/**
|
|
473
474
|
* O TEMA É DELE - bateria ampliada, item 22 (29/09). Em c01, c02, c05, c17 e c23 o agente mexeu no tema do projeto
|
package/dist/commands/mcp.js
CHANGED
|
@@ -16,7 +16,7 @@ import { ruleLine } from "../doctrine.js";
|
|
|
16
16
|
import { fromCensus } from "../memory/observation.js";
|
|
17
17
|
import { handleRecall, handleRemember, MEMORY_TOOLS } from "../memory/tools.js";
|
|
18
18
|
import { ourSpellingLines } from "../our-spelling.js";
|
|
19
|
-
import { fetchPreferences, isKind, isLayer, PREFERENCE_KINDS, PREFERENCE_LAYERS, preferencesAnswer, readOff, readSelection, sendPiece, } from "../preferences.js";
|
|
19
|
+
import { fetchPreferences, isKind, isLayer, isSection, PREFERENCE_KINDS, PREFERENCE_LAYERS, preferencesAnswer, readOff, readSelection, SECTIONS, sendPiece, } from "../preferences.js";
|
|
20
20
|
import { readInstalledConvention } from "../project-facts.js";
|
|
21
21
|
import { repoStateOf } from "../repo-state.js";
|
|
22
22
|
import { detectStack } from "../stack.js";
|
|
@@ -370,7 +370,7 @@ const TOOLS = [
|
|
|
370
370
|
*/
|
|
371
371
|
{
|
|
372
372
|
name: "preferences",
|
|
373
|
-
description: "The person's OWN preference blueprint for a kind of page - how they like a landing, a blog article or a dashboard built (structure, behavior, view), kept in their account and shared by all their projects. Call this BEFORE building or reshaping a page of one of these kinds - their blueprints are on by default, so a plain \"make me a landing page\" gets them too. Skip it only when the request says to build without them; a project that turned them off answers so itself. The rules name roles and steps; you resolve them to this project's --ds-* variables.",
|
|
373
|
+
description: "The person's OWN preference blueprint for a kind of page - how they like a landing, a blog article or a dashboard built (structure, behavior, view), kept in their account and shared by all their projects. Call this BEFORE building or reshaping a page of one of these kinds - their blueprints are on by default, so a plain \"make me a landing page\" gets them too. Skip it only when the request says to build without them; a project that turned them off answers so itself. Building ONE part of a landing (a hero, the pricing or offer cards, testimonials, the closing call, the footer) - most of all when the person adds one part per message - call it again with that `section` for each part. Too vague to tell what kind of page is being built? Ask one short question first instead of guessing. The rules name roles and steps; you resolve them to this project's --ds-* variables.",
|
|
374
374
|
inputSchema: {
|
|
375
375
|
type: "object",
|
|
376
376
|
properties: {
|
|
@@ -379,6 +379,11 @@ const TOOLS = [
|
|
|
379
379
|
enum: [...PREFERENCE_KINDS],
|
|
380
380
|
description: "Which kind of page is being built.",
|
|
381
381
|
},
|
|
382
|
+
section: {
|
|
383
|
+
type: "string",
|
|
384
|
+
enum: [...SECTIONS],
|
|
385
|
+
description: "Only with kind landing, when ONE part is being built now: hero, pricing (offer or product cards with prices), testimonials, closing (the last call to action), footer. Omit for the whole page or a part outside this list.",
|
|
386
|
+
},
|
|
382
387
|
},
|
|
383
388
|
required: ["kind"],
|
|
384
389
|
},
|
|
@@ -1939,7 +1944,10 @@ cli) {
|
|
|
1939
1944
|
const token = await readToken();
|
|
1940
1945
|
if (!token)
|
|
1941
1946
|
return fromContract("Not signed in, so the person's preferences cannot be read. They have to run `synthesisui login` once in the terminal - it opens a browser, and I cannot complete it for them.");
|
|
1942
|
-
const
|
|
1947
|
+
const section = args.section;
|
|
1948
|
+
if (section !== undefined && (kind !== "landing" || !isSection(section)))
|
|
1949
|
+
return fromContract(`section goes with kind landing and is one of ${SECTIONS.join(", ")} - for any other part, call with the kind alone.`);
|
|
1950
|
+
const prefs = await fetchPreferences({ base: resolveRegistry(), token }, kind, section, await installedSlug(root));
|
|
1943
1951
|
if ("failed" in prefs)
|
|
1944
1952
|
return fromContract(`Their preferences could not be read: ${prefs.failed}. Build with the system as usual and say so in one line.`);
|
|
1945
1953
|
return preferencesAnswer(kind, prefs, await readSelection(root), await readOff(root));
|
|
@@ -2719,12 +2719,59 @@ export function rootClasses(source, name) {
|
|
|
2719
2719
|
const own = ownClassNameExpr(tag);
|
|
2720
2720
|
if (own == null)
|
|
2721
2721
|
return [];
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2722
|
+
/**
|
|
2723
|
+
* O TEXTO FIXO DE UM TEMPLATE TAMBÉM É CLASSE ESCRITA - dono, 04/10 18:28Z, no PASS com a conta zerada: o botão do
|
|
2724
|
+
* projeto importado chegou sem centralizar e de canto reto. O `Button.tsx` dele escreve
|
|
2725
|
+
*
|
|
2726
|
+
* className={`inline-flex items-center justify-center gap-2 rounded-pill font-medium ${variants[variant]} ${sizes[size]} ${className}`}
|
|
2727
|
+
*
|
|
2728
|
+
* e esta função pulava template inteiro ("a class we cannot see in full"). Só que o texto FORA do `${}` se vê
|
|
2729
|
+
* inteiro: o que não se vê é a classe COLADA numa interpolação (`p-${n}`, `${tone}-500`). Então entram as classes
|
|
2730
|
+
* inteiras do texto fixo, e a colada continua de fora. O que vem DENTRO de `${}` é cálculo (o mapa da variante, uma
|
|
2731
|
+
* condição) e não é lido daqui - as variantes têm o leitor delas.
|
|
2732
|
+
*/
|
|
2733
|
+
const fromTemplates = [];
|
|
2734
|
+
const outside = own.replace(/`(?:\\[\s\S]|\$\{(?:[^{}]|\{[^{}]*\})*\}|[^`\\])*`/g, (lit) => {
|
|
2735
|
+
fromTemplates.push(...templateStatics(lit.slice(1, -1)));
|
|
2736
|
+
return " ";
|
|
2737
|
+
});
|
|
2738
|
+
// Every string literal inside the className expression - outside a template.
|
|
2739
|
+
return [
|
|
2740
|
+
...[...outside.matchAll(/["']([^"']+)["']/g)].flatMap((m) => m[1].split(/\s+/)),
|
|
2741
|
+
...fromTemplates,
|
|
2742
|
+
].filter((c) => c.length > 0 && !c.includes("${"));
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* As classes INTEIRAS do texto fixo de um template: cada `${...}` vira uma marca, e a classe que encosta nela (sem
|
|
2746
|
+
* espaço no meio) sai - ela só existe completa depois do cálculo.
|
|
2747
|
+
*/
|
|
2748
|
+
export function templateStatics(body) {
|
|
2749
|
+
let out = "";
|
|
2750
|
+
for (let i = 0; i < body.length; i++) {
|
|
2751
|
+
if (body[i] === "\\") {
|
|
2752
|
+
out += body[i + 1] ?? "";
|
|
2753
|
+
i++;
|
|
2754
|
+
continue;
|
|
2755
|
+
}
|
|
2756
|
+
if (body[i] === "$" && body[i + 1] === "{") {
|
|
2757
|
+
let depth = 0;
|
|
2758
|
+
let j = i + 1;
|
|
2759
|
+
for (; j < body.length; j++) {
|
|
2760
|
+
if (body[j] === "{")
|
|
2761
|
+
depth++;
|
|
2762
|
+
else if (body[j] === "}") {
|
|
2763
|
+
depth--;
|
|
2764
|
+
if (depth === 0)
|
|
2765
|
+
break;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
out += "\u0000";
|
|
2769
|
+
i = j;
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
out += body[i];
|
|
2773
|
+
}
|
|
2774
|
+
return out.split(/\s+/).filter((c) => c.length > 0 && !c.includes("\u0000"));
|
|
2728
2775
|
}
|
|
2729
2776
|
/**
|
|
2730
2777
|
* A EXPRESSÃO do `className` que é atributo DIRETO desta tag de abertura, ou `null`.
|
package/dist/install-marks.js
CHANGED
|
@@ -319,7 +319,7 @@
|
|
|
319
319
|
* linha das preferências da pessoa - `preferences` quando ela pede, `remember_preference` quando ela corrige. Uma pasta
|
|
320
320
|
* escrita antes não diz ao agente que essas portas existem.
|
|
321
321
|
*/
|
|
322
|
-
export const MATERIALISER_SINCE = "0.16.
|
|
322
|
+
export const MATERIALISER_SINCE = "0.16.489";
|
|
323
323
|
/**
|
|
324
324
|
* A ÚLTIMA VERSÃO EM QUE O QUE O HOOK RODA MUDOU.
|
|
325
325
|
*
|
package/dist/preferences.js
CHANGED
|
@@ -16,6 +16,18 @@ import { join } from "node:path";
|
|
|
16
16
|
*/
|
|
17
17
|
export const PREFERENCE_KINDS = ["landing", "blog", "dashboard"];
|
|
18
18
|
export const PREFERENCE_LAYERS = ["structure", "behavior", "view"];
|
|
19
|
+
/**
|
|
20
|
+
* AS PARTES DA LANDING - a jornada "o agente reconhece o que se constrói" (03/10). Quem pede por partes ("coloca a
|
|
21
|
+
* hero", "agora o rodapé") recebe, a cada parte, a estrutura daquela parte (apps/web lib/ds/section-structural.ts).
|
|
22
|
+
*/
|
|
23
|
+
export const SECTIONS = [
|
|
24
|
+
"hero",
|
|
25
|
+
"pricing",
|
|
26
|
+
"testimonials",
|
|
27
|
+
"closing",
|
|
28
|
+
"footer",
|
|
29
|
+
];
|
|
30
|
+
export const isSection = (s) => typeof s === "string" && SECTIONS.includes(s);
|
|
19
31
|
export const isKind = (k) => typeof k === "string" && PREFERENCE_KINDS.includes(k);
|
|
20
32
|
export const isLayer = (l) => typeof l === "string" && PREFERENCE_LAYERS.includes(l);
|
|
21
33
|
/** Onde o projeto guarda quais blueprints dela ele usa - versionado, porque é decisão do projeto. */
|
|
@@ -83,8 +95,20 @@ export function chosen(all, selection) {
|
|
|
83
95
|
const want = new Set(selection.map((s) => s.toLowerCase()));
|
|
84
96
|
return all.filter((b) => want.has(b.name.toLowerCase()) || want.has(b.id.toLowerCase()));
|
|
85
97
|
}
|
|
86
|
-
export async function fetchPreferences(reach, kind
|
|
87
|
-
|
|
98
|
+
export async function fetchPreferences(reach, kind, section,
|
|
99
|
+
/** O projeto instalado aqui - a estrutura que vale é a dele ("a alma da estrutura", 04/10). */
|
|
100
|
+
ds) {
|
|
101
|
+
const params = new URLSearchParams();
|
|
102
|
+
if (kind)
|
|
103
|
+
params.set("kind", kind);
|
|
104
|
+
if (kind && section)
|
|
105
|
+
params.set("section", section);
|
|
106
|
+
if (ds)
|
|
107
|
+
params.set("ds", ds);
|
|
108
|
+
const q = params.size ? `?${params}` : "";
|
|
109
|
+
const res = await fetch(`${reach.base}/api/preferences${q}`, {
|
|
110
|
+
headers: { Authorization: `Bearer ${reach.token}` },
|
|
111
|
+
}).catch(() => null);
|
|
88
112
|
if (!res)
|
|
89
113
|
return { failed: "the platform could not be reached" };
|
|
90
114
|
if (!res.ok)
|
|
@@ -165,13 +189,28 @@ function craftOf(kind, prefs) {
|
|
|
165
189
|
const lines = prefs.craft?.[kind] ?? [];
|
|
166
190
|
if (lines.length === 0)
|
|
167
191
|
return [];
|
|
192
|
+
// a estrutura só existe para a landing: é ela que o rhythm e o type abaixo trazem
|
|
193
|
+
const structure = kind === "landing" && prefs.structure
|
|
194
|
+
? ` with THIS project's structure, "${prefs.structure.name}"${prefs.structure.chosen ? "" : " (the default - they can pick another under Structure on the site)"}`
|
|
195
|
+
: "";
|
|
168
196
|
return [
|
|
169
197
|
"",
|
|
170
|
-
`HOW THIS PLATFORM BUILDS A ${kind.toUpperCase()} - the same rules its guide uses; their blueprint wins where the two disagree:`,
|
|
198
|
+
`HOW THIS PLATFORM BUILDS A ${kind.toUpperCase()}${structure} - the same rules its guide uses; their blueprint wins where the two disagree:`,
|
|
171
199
|
...lines.map((l) => `- ${l}`),
|
|
172
200
|
];
|
|
173
201
|
}
|
|
174
|
-
/** A
|
|
202
|
+
/** A parte que se constrói agora vem PRIMEIRO: é dela que o turno trata. */
|
|
203
|
+
function sectionOf(prefs) {
|
|
204
|
+
const s = prefs.section;
|
|
205
|
+
if (!s || s.lines.length === 0)
|
|
206
|
+
return [];
|
|
207
|
+
return [
|
|
208
|
+
`THE PART BEING BUILT NOW - the ${s.name} of this landing, as this platform builds it:`,
|
|
209
|
+
...s.lines.map((l) => `- ${l}`),
|
|
210
|
+
"",
|
|
211
|
+
];
|
|
212
|
+
}
|
|
213
|
+
/** A resposta da ferramenta `preferences` - ligada por padrão (03/10), e a cada parte da landing com a `section`. */
|
|
175
214
|
export function preferencesAnswer(kind, prefs, selection,
|
|
176
215
|
/** O projeto desligou os blueprints (`synthesisui preferences off`). */
|
|
177
216
|
off = false) {
|
|
@@ -184,9 +223,15 @@ off = false) {
|
|
|
184
223
|
? `The person has no ${kind} preference blueprint yet.`
|
|
185
224
|
: `The person has ${mine.length} ${kind} blueprint(s) (${mine.map((b) => `"${b.name}"`).join(", ")}), but this project chose others in _synthesisui/preferences.json.`;
|
|
186
225
|
// não ter preferência não é lacuna do sistema: é uma resposta verdadeira, e não entra na conta de lacunas
|
|
187
|
-
return composed(
|
|
226
|
+
return composed([
|
|
227
|
+
...sectionOf(prefs),
|
|
228
|
+
`${why} Build the ${kind} with the system as usual, and tell them in one line that they can keep their ${kind} preferences under Memory -> Preference blueprints on the site.`,
|
|
229
|
+
// a estrutura do projeto vale com ou sem blueprint: ela é do projeto, não da pessoa
|
|
230
|
+
...craftOf(kind, prefs),
|
|
231
|
+
].join("\n"), `preferences:${kind}:0${prefs.section ? `:${prefs.section.name}` : ""}`);
|
|
188
232
|
}
|
|
189
233
|
return composed([
|
|
234
|
+
...sectionOf(prefs),
|
|
190
235
|
`The person's preference blueprint${use.length > 1 ? "s" : ""} for a ${kind} - THEIR preferences, kept by them across projects:`,
|
|
191
236
|
"",
|
|
192
237
|
...use.map(describeBlueprint),
|
|
@@ -196,5 +241,5 @@ off = false) {
|
|
|
196
241
|
"- They win over generic page craft when the two disagree; this system's tokens and rules still win over them.",
|
|
197
242
|
`- When you finish, tell them in ONE line which blueprint you applied${use.length > 1 ? " (if more than one fits, use the first and name it)" : ""}, and any rule you could not follow and why.`,
|
|
198
243
|
...craftOf(kind, prefs),
|
|
199
|
-
].join("\n"), `preferences:${kind}:${use.length}`);
|
|
244
|
+
].join("\n"), `preferences:${kind}:${use.length}${prefs.section ? `:${prefs.section.name}` : ""}`);
|
|
200
245
|
}
|
package/package.json
CHANGED