@cogenta/agents-builtin 0.3.2 → 0.5.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.
Files changed (37) hide show
  1. package/dist/image-creator/agent.d.ts +40 -0
  2. package/dist/image-creator/agent.d.ts.map +1 -0
  3. package/dist/image-creator/agent.js +48 -0
  4. package/dist/image-creator/agent.js.map +1 -0
  5. package/dist/index.d.ts +12 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +7 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/theme-creator/agent.d.ts +13 -9
  10. package/dist/theme-creator/agent.d.ts.map +1 -1
  11. package/dist/theme-creator/agent.js +14 -10
  12. package/dist/theme-creator/agent.js.map +1 -1
  13. package/dist/theme-creator/generate-sandbox-theme.d.ts +148 -0
  14. package/dist/theme-creator/generate-sandbox-theme.d.ts.map +1 -0
  15. package/dist/theme-creator/generate-sandbox-theme.js +253 -0
  16. package/dist/theme-creator/generate-sandbox-theme.js.map +1 -0
  17. package/dist/theme-creator/generate-theme-candidates.d.ts +101 -0
  18. package/dist/theme-creator/generate-theme-candidates.d.ts.map +1 -0
  19. package/dist/theme-creator/generate-theme-candidates.js +133 -0
  20. package/dist/theme-creator/generate-theme-candidates.js.map +1 -0
  21. package/dist/theme-creator/preview-sandbox-tool.d.ts +57 -0
  22. package/dist/theme-creator/preview-sandbox-tool.d.ts.map +1 -0
  23. package/dist/theme-creator/preview-sandbox-tool.js +48 -0
  24. package/dist/theme-creator/preview-sandbox-tool.js.map +1 -0
  25. package/dist/theme-creator/read-sandbox-tool.d.ts +57 -0
  26. package/dist/theme-creator/read-sandbox-tool.d.ts.map +1 -0
  27. package/dist/theme-creator/read-sandbox-tool.js +55 -0
  28. package/dist/theme-creator/read-sandbox-tool.js.map +1 -0
  29. package/dist/theme-creator/theme-spec.d.ts +31 -0
  30. package/dist/theme-creator/theme-spec.d.ts.map +1 -0
  31. package/dist/theme-creator/theme-spec.js +254 -0
  32. package/dist/theme-creator/theme-spec.js.map +1 -0
  33. package/dist/theme-creator/write-sandbox-file-tool.d.ts +54 -0
  34. package/dist/theme-creator/write-sandbox-file-tool.d.ts.map +1 -0
  35. package/dist/theme-creator/write-sandbox-file-tool.js +109 -0
  36. package/dist/theme-creator/write-sandbox-file-tool.js.map +1 -0
  37. package/package.json +3 -3
@@ -0,0 +1,57 @@
1
+ import { type ToolDefinition } from '@cogenta/agents';
2
+ import { z } from 'zod';
3
+ /**
4
+ * What was missing for a theme to be *adjusted* rather than only created.
5
+ *
6
+ * The sandbox tools could write a file and render the result, but never read
7
+ * one back. Inside a single generation run that is survivable — the agent
8
+ * still has its own transcript, so it knows what it wrote. Across a second
9
+ * conversation turn ("make it darker", "put the grid on two columns") it is
10
+ * fatal: the agent is handed a theme it has never seen, and its only options
11
+ * are to guess or to rewrite the whole thing from scratch, throwing away
12
+ * every decision the operator just approved.
13
+ *
14
+ * Two tools, because listing and reading are genuinely different questions
15
+ * and a model asked to "read the theme" should not have to guess filenames:
16
+ * `theme.list_sandbox_files` answers "what is in here", and
17
+ * `theme.read_sandbox_file` answers "what does this one say".
18
+ *
19
+ * Both are read-only (`sideEffects: false`) and confined to one sandbox
20
+ * directory — the same directory `theme.write_sandbox_file` already writes
21
+ * to, with the same host-side path-escape guard in `@cogenta/cli`, which is
22
+ * where the real filesystem lives.
23
+ */
24
+ export interface ReadSandboxToolsOptions {
25
+ readonly listFiles: (input: {
26
+ readonly sandboxId: string;
27
+ }) => Promise<readonly string[]>;
28
+ readonly readFile: (input: {
29
+ readonly sandboxId: string;
30
+ readonly path: string;
31
+ }) => Promise<string>;
32
+ /** A theme file that is genuinely enormous is truncated rather than allowed to crowd out the rest of the conversation. */
33
+ readonly maxFileChars?: number;
34
+ }
35
+ declare const ListInputSchema: z.ZodObject<{
36
+ sandboxId: z.ZodString;
37
+ }, z.core.$strip>;
38
+ export type ListSandboxFilesInput = z.infer<typeof ListInputSchema>;
39
+ declare const ListOutputSchema: z.ZodObject<{
40
+ files: z.ZodArray<z.ZodString>;
41
+ }, z.core.$strip>;
42
+ export type ListSandboxFilesOutput = z.infer<typeof ListOutputSchema>;
43
+ declare const ReadInputSchema: z.ZodObject<{
44
+ sandboxId: z.ZodString;
45
+ path: z.ZodString;
46
+ }, z.core.$strip>;
47
+ export type ReadSandboxFileInput = z.infer<typeof ReadInputSchema>;
48
+ declare const ReadOutputSchema: z.ZodObject<{
49
+ path: z.ZodString;
50
+ content: z.ZodString;
51
+ truncated: z.ZodOptional<z.ZodBoolean>;
52
+ }, z.core.$strip>;
53
+ export type ReadSandboxFileOutput = z.infer<typeof ReadOutputSchema>;
54
+ export declare function createListSandboxFilesTool(options: Pick<ReadSandboxToolsOptions, 'listFiles'>): ToolDefinition<ListSandboxFilesInput, ListSandboxFilesOutput>;
55
+ export declare function createReadSandboxFileTool(options: Pick<ReadSandboxToolsOptions, 'readFile' | 'maxFileChars'>): ToolDefinition<ReadSandboxFileInput, ReadSandboxFileOutput>;
56
+ export {};
57
+ //# sourceMappingURL=read-sandbox-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-sandbox-tool.d.ts","sourceRoot":"","sources":["../../src/theme-creator/read-sandbox-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;IACzF,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE;QACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KACtB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACrB,0HAA0H;IAC1H,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAID,QAAA,MAAM,eAAe;;iBAA6C,CAAA;AAClE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAEnE,QAAA,MAAM,gBAAgB;;iBAA2C,CAAA;AACjE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAErE,QAAA,MAAM,eAAe;;;iBAInB,CAAA;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAElE,QAAA,MAAM,gBAAgB;;;;iBAIpB,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AAEpE,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,WAAW,CAAC,GAClD,cAAc,CAAC,qBAAqB,EAAE,sBAAsB,CAAC,CAe/D;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,GAAG,cAAc,CAAC,GAClE,cAAc,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAsB7D"}
@@ -0,0 +1,55 @@
1
+ import { defineTool } from '@cogenta/agents';
2
+ import { z } from 'zod';
3
+ const DEFAULT_MAX_FILE_CHARS = 24_000;
4
+ const ListInputSchema = z.object({ sandboxId: z.string().min(1) });
5
+ const ListOutputSchema = z.object({ files: z.array(z.string()) });
6
+ const ReadInputSchema = z.object({
7
+ sandboxId: z.string().min(1),
8
+ /** Sandbox-relative, exactly as `theme.list_sandbox_files` returned it. */
9
+ path: z.string().min(1),
10
+ });
11
+ const ReadOutputSchema = z.object({
12
+ path: z.string(),
13
+ content: z.string(),
14
+ truncated: z.boolean().optional(),
15
+ });
16
+ export function createListSandboxFilesTool(options) {
17
+ return defineTool({
18
+ name: 'theme.list_sandbox_files',
19
+ version: '1.0.0',
20
+ description: `Lists every file currently in a theme sandbox, as sandbox-relative paths. Call it first when you are changing a theme you did not write in this conversation — you cannot correct a file whose name you had to guess, and a theme's stylesheet can be called anything.`,
21
+ input: ListInputSchema,
22
+ output: ListOutputSchema,
23
+ permissions: ['theme.write_sandbox'],
24
+ sideEffects: false,
25
+ reversible: false,
26
+ cost: 'low',
27
+ async execute(input) {
28
+ return { files: [...(await options.listFiles({ sandboxId: input.sandboxId }))] };
29
+ },
30
+ });
31
+ }
32
+ export function createReadSandboxFileTool(options) {
33
+ const limit = options.maxFileChars ?? DEFAULT_MAX_FILE_CHARS;
34
+ return defineTool({
35
+ name: 'theme.read_sandbox_file',
36
+ version: '1.0.0',
37
+ description: `Returns the current contents of one file in a theme sandbox. Read a file before changing it: a write replaces the whole file, so editing from memory — or from what you assume a previous run wrote — silently drops everything you did not happen to reproduce. When a request asks to adjust part of a theme, read the file, change that part, and write the whole corrected file back.`,
38
+ input: ReadInputSchema,
39
+ output: ReadOutputSchema,
40
+ permissions: ['theme.write_sandbox'],
41
+ sideEffects: false,
42
+ reversible: false,
43
+ cost: 'low',
44
+ async execute(input) {
45
+ const content = await options.readFile({ sandboxId: input.sandboxId, path: input.path });
46
+ const truncated = content.length > limit;
47
+ return {
48
+ path: input.path,
49
+ content: truncated ? `${content.slice(0, limit)}\n/* …truncated */` : content,
50
+ truncated,
51
+ };
52
+ },
53
+ });
54
+ }
55
+ //# sourceMappingURL=read-sandbox-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read-sandbox-tool.js","sourceRoot":"","sources":["../../src/theme-creator/read-sandbox-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAuB,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAkCvB,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAErC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;AAGlE,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;AAGjE,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,2EAA2E;IAC3E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAA;AAGF,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC,CAAA;AAGF,MAAM,UAAU,0BAA0B,CACxC,OAAmD;IAEnD,OAAO,UAAU,CAAC;QAChB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,wQAAwQ;QACrR,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,CAAC,qBAAqB,CAAC;QACpC,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,KAAK;QACX,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAClF,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,OAAmE;IAEnE,MAAM,KAAK,GAAG,OAAO,CAAC,YAAY,IAAI,sBAAsB,CAAA;IAC5D,OAAO,UAAU,CAAC;QAChB,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,2XAA2X;QACxY,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,CAAC,qBAAqB,CAAC;QACpC,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,KAAK;QACjB,IAAI,EAAE,KAAK;QACX,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;YACxF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAA;YACxC,OAAO;gBACL,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,OAAO;gBAC7E,SAAS;aACV,CAAA;QACH,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The structure and composition of a Cogenta theme, as one standing
3
+ * specification handed to the model in the system prompt's own
4
+ * `<specification>` section (`assembleContext`, `@cogenta/agents`).
5
+ *
6
+ * **Why this file exists.** Every fact below already existed — scattered
7
+ * across `theme.write_sandbox_file`'s tool `description`, a 311-line
8
+ * `identity.md` no admin flow ever loads, and the contract D docs. A live
9
+ * report ("I attach a screenshot and what comes back is nowhere near it")
10
+ * traced back to that scattering: a tool description is read as API
11
+ * reference for one call, not as standing knowledge about what is being
12
+ * built, and the writer agent's actual system prompt was a one-sentence role
13
+ * plus ten bullets. The tool description keeps only what belongs to the
14
+ * tool (its arguments and what it rejects); everything about what a theme
15
+ * *is* lives here.
16
+ *
17
+ * **The palette rule reversed, deliberately.** The previous brief told the
18
+ * model "colour/font/spacing VALUES are not invented here — reference
19
+ * --cogenta-*". Those custom properties are generated exclusively from the
20
+ * *site's* skin (`theme-wiring.ts`'s `computeEffectiveStyles`), so a theme
21
+ * asked to reproduce a specific design was structurally repainted in
22
+ * whatever palette the site already had — the single largest cause of "far
23
+ * from the screenshot", and no amount of layout accuracy could compensate.
24
+ * A theme's own stylesheet is emitted *after* the skin stylesheet
25
+ * (`joinStyles`, `theme-render.ts`), so a theme can and should carry its own
26
+ * design palette. The namespaced pattern below keeps the site's brand colours
27
+ * reachable rather than simply overwriting `--cogenta-*` at `:root`, which
28
+ * would silently disable the operator's own colour controls.
29
+ */
30
+ export declare const COGENTA_THEME_SPECIFICATION: string;
31
+ //# sourceMappingURL=theme-spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-spec.d.ts","sourceRoot":"","sources":["../../src/theme-creator/theme-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,2BAA2B,QA+NhC,CAAA"}
@@ -0,0 +1,254 @@
1
+ /**
2
+ * The structure and composition of a Cogenta theme, as one standing
3
+ * specification handed to the model in the system prompt's own
4
+ * `<specification>` section (`assembleContext`, `@cogenta/agents`).
5
+ *
6
+ * **Why this file exists.** Every fact below already existed — scattered
7
+ * across `theme.write_sandbox_file`'s tool `description`, a 311-line
8
+ * `identity.md` no admin flow ever loads, and the contract D docs. A live
9
+ * report ("I attach a screenshot and what comes back is nowhere near it")
10
+ * traced back to that scattering: a tool description is read as API
11
+ * reference for one call, not as standing knowledge about what is being
12
+ * built, and the writer agent's actual system prompt was a one-sentence role
13
+ * plus ten bullets. The tool description keeps only what belongs to the
14
+ * tool (its arguments and what it rejects); everything about what a theme
15
+ * *is* lives here.
16
+ *
17
+ * **The palette rule reversed, deliberately.** The previous brief told the
18
+ * model "colour/font/spacing VALUES are not invented here — reference
19
+ * --cogenta-*". Those custom properties are generated exclusively from the
20
+ * *site's* skin (`theme-wiring.ts`'s `computeEffectiveStyles`), so a theme
21
+ * asked to reproduce a specific design was structurally repainted in
22
+ * whatever palette the site already had — the single largest cause of "far
23
+ * from the screenshot", and no amount of layout accuracy could compensate.
24
+ * A theme's own stylesheet is emitted *after* the skin stylesheet
25
+ * (`joinStyles`, `theme-render.ts`), so a theme can and should carry its own
26
+ * design palette. The namespaced pattern below keeps the site's brand colours
27
+ * reachable rather than simply overwriting `--cogenta-*` at `:root`, which
28
+ * would silently disable the operator's own colour controls.
29
+ */
30
+ export const COGENTA_THEME_SPECIFICATION = `
31
+ A Cogenta theme is a small ES module package that turns a page's stored
32
+ content into HTML, plus the CSS that makes that HTML look like a design. It
33
+ runs server-side, per request. It has no build step: files are loaded with a
34
+ plain \`import()\`, so there is no JSX, no TypeScript compilation, no bundler.
35
+
36
+ ## The files
37
+
38
+ A complete theme is three things. None is optional if the theme is meant to
39
+ look like anything.
40
+
41
+ 1. \`theme.config.{js,mjs,ts}\` — the contract D manifest.
42
+ 2. \`theme.render.{js,mjs,ts}\` — \`renderPage\` and \`renderChrome\`.
43
+ 3. At least one \`.css\` file — any name, any number. Every \`.css\` at the
44
+ theme root is picked up automatically and concatenated in filename order.
45
+
46
+ \`.tsx\` and \`.jsx\` are refused: nothing transforms JSX here. Write
47
+ \`h(tag, attrs, ...children)\` calls instead, whichever extension you choose.
48
+
49
+ ## theme.config.*
50
+
51
+ \`export default defineTheme({...})\` from '@cogenta/theme-kit', with exactly
52
+ these fields:
53
+
54
+ - \`name\`: string
55
+ - \`version\`: exact semver, e.g. '1.0.0'
56
+ - \`engine\`: a semver RANGE, e.g. '^1.0.0' — never prose
57
+ - \`blocks\`: a semver RANGE too, e.g. '^1.0.0' — the block-vocabulary
58
+ version, NEVER a list of block names
59
+ - \`implements\`: string[] — the block \`_type\` names \`renderPage\` really
60
+ handles, e.g. ['hero','collectionList','prose']
61
+ - \`collections\`: string[] or '*'
62
+ - \`runtime\`: exactly one of 'static' | 'server' | 'edge'
63
+ - \`tokens\`: a STRING path, e.g. './theme.tokens.json' — never inline data
64
+
65
+ ## theme.render.*
66
+
67
+ A real ES module exporting two functions, both building markup with \`h()\`
68
+ from '@cogenta/theme-kit'. \`h(tag, attrs, ...children)\` returns an
69
+ HtmlElement tree; the pipeline calls \`serialize()\` on what you return, and
70
+ it understands only that tree or a plain string.
71
+
72
+ \`renderChrome(input)\` returns \`{ header, footer }\` as HTML **strings**.
73
+ \`input\` is \`{ site: {name,url,locales,defaultLocale}, locale, homeHref,
74
+ headerNav: [{label,href}], footerNav, brandingHtml, tagline?, social?,
75
+ footerNote?, headerAction? }\`.
76
+
77
+ \`renderPage(page, ctx, entries)\`:
78
+ - \`page\`: \`{ title, blocks: Array<{_key, _type, ...fields}> }\` — the real
79
+ saved contract B blocks.
80
+ - \`ctx\`: \`{ site, locale, url, t(key,vals), image(mediaId,opts),
81
+ link(target), content: {entry,byPath,list} }\`.
82
+ - \`entries\`: fetched \`collectionList\` results, keyed by \`block._key\`.
83
+
84
+ Design freedom is total, like a WordPress theme: fetch whatever you need
85
+ through \`ctx.content\`, place it anywhere, invent your own block types. A
86
+ page's \`blocks\` list is one available data source, never a required
87
+ structure. The shared vocabulary (hero, prose, mediaFigure, featureGrid, cta,
88
+ gallery, quote, faq, stats, logos, collectionList, embed, testimonial,
89
+ pricingTable, accordion, statCounter, logoStrip) exists so content already
90
+ composed with those still shows something — implementing all of them is never
91
+ required. But a block type you do not specifically style must still render
92
+ plainly rather than vanish: never drop content a page actually has.
93
+
94
+ There is no access to token VALUES from render code. \`ctx.theme.tokens\` does
95
+ not exist. Render code emits semantic HTML with class names; CSS does the
96
+ rest.
97
+
98
+ ## The CSS, and where colour actually comes from
99
+
100
+ This is where a design succeeds or fails. Markup structure alone renders as
101
+ unstyled text, every time.
102
+
103
+ Two stylesheets reach the page, in this order: the **site skin** first, then
104
+ **this theme's CSS**. Later wins at equal specificity, so a theme can define
105
+ its own design language and does not merely decorate the site's.
106
+
107
+ The site skin publishes these custom properties on \`:root\`:
108
+ \`--cogenta-color-bg/fg/accent/accent-fg/muted/muted-fg/border\`,
109
+ \`--cogenta-font-sans/serif/mono\`,
110
+ \`--cogenta-font-size-xs/sm/md/lg/xl/2xl/3xl\`, \`--cogenta-space-unit\`,
111
+ \`--cogenta-radius-sm/md/lg\`, \`--cogenta-shadow-sm/md\`.
112
+
113
+ **Own your palette.** When the request describes or shows a specific design,
114
+ that design's colours, type and spacing are the point — reproducing them is
115
+ the job. Define them as your own namespaced custom properties, derived from
116
+ what the request actually shows, and build every rule on those:
117
+
118
+ \`\`\`css
119
+ :root {
120
+ --t-bg: #0e1013;
121
+ --t-surface: #171a1f;
122
+ --t-fg: #f2f4f7;
123
+ --t-muted-fg: #98a1ad;
124
+ --t-accent: #3ddc84;
125
+ --t-accent-fg: #06210f;
126
+ --t-border: #262b33;
127
+ --t-radius: 14px;
128
+ --t-display: "Fraunces", Georgia, serif;
129
+ --t-body: "Inter", system-ui, sans-serif;
130
+ --t-step: 8px;
131
+ }
132
+ \`\`\`
133
+
134
+ Prefix them with something short and specific to the theme. Do **not**
135
+ redefine \`--cogenta-*\` at \`:root\`: those are the operator's own colour
136
+ controls in the Appearance screen, and overwriting them silently disables
137
+ that feature. When a value should follow the site's brand instead of the
138
+ design, read the site variable directly, or use it as the fallback:
139
+ \`color: var(--cogenta-color-accent, var(--t-accent));\`.
140
+
141
+ Literal colours are allowed and expected in a theme's own stylesheet.
142
+ **Gradients are not** — flat, structured surfaces only, no
143
+ \`linear-gradient\`/\`radial-gradient\` anywhere. Use flat fills, borders and
144
+ spacing to build hierarchy.
145
+
146
+ Google Fonts may be pulled with an \`@import\` at the very top of a CSS file;
147
+ always give a real fallback stack.
148
+
149
+ ## Light and dark
150
+
151
+ Themes are expected to work in both. The site stamps \`data-theme="dark"\` or
152
+ \`data-theme="light"\` on the root element when a visitor chooses explicitly,
153
+ and stamps nothing on the default "system" setting — where only
154
+ \`prefers-color-scheme\` separates them. Define the complete palette on bare
155
+ \`:root\`, then redefine only the tokens in two more blocks:
156
+
157
+ \`\`\`css
158
+ @media (prefers-color-scheme: dark) {
159
+ :root:not([data-theme="light"]) { --t-bg: #0e1013; --t-fg: #f2f4f7; }
160
+ }
161
+ :root[data-theme="dark"] { --t-bg: #0e1013; --t-fg: #f2f4f7; }
162
+ :root[data-theme="light"] { --t-bg: #ffffff; --t-fg: #14171c; }
163
+ \`\`\`
164
+
165
+ Never give a colour its only definition inside a media or \`[data-theme]\`
166
+ block — it then never applies in the unstamped state, and the page renders
167
+ one theme's text on the other theme's background.
168
+
169
+ A theme that deliberately commits to a single look may skip those blocks, but
170
+ must still paint background and text colours explicitly.
171
+
172
+ ## Two things the page always has
173
+
174
+ The host page template injects both on every page, whatever the theme, so
175
+ every theme must account for them:
176
+
177
+ 1. **A "Skip to content" link**, \`.cg-skip-link\`, placed before your header
178
+ markup (WCAG 2.4.1). Style it off-screen until focus — never
179
+ \`display: none\`, which removes it from the tab order and defeats its
180
+ purpose. Without a rule for it, it renders as a plain visible link at the
181
+ very top of every page:
182
+
183
+ \`\`\`css
184
+ .cg-skip-link { position: absolute; left: 1rem; top: -4rem; z-index: 50;
185
+ padding: .6em 1.1em; background: var(--t-accent); color: var(--t-accent-fg);
186
+ border-radius: 999px; text-decoration: none; transition: top 160ms ease; }
187
+ .cg-skip-link:focus-visible { top: 1rem; }
188
+ \`\`\`
189
+
190
+ 2. **The light/dark toggle script.** The host injects the script; a theme only
191
+ ever places the button, via \`renderThemeToggle()\` from
192
+ '@cogenta/theme-kit', inside its own \`renderChrome\` markup. Never inject
193
+ the script yourself, and never write client JavaScript of your own —
194
+ themes are zero-JS apart from that one host-provided toggle.
195
+
196
+ ## A theme displays the site's content. It never contains content.
197
+
198
+ This is the rule that separates a theme from a mockup, and breaking it
199
+ produces something that looks finished and is unusable.
200
+
201
+ Everything a visitor reads — article titles, excerpts, dates, menu labels,
202
+ page copy — comes from the site's database at render time, through the page
203
+ you were handed and through \`ctx.content\`. A theme that hardcodes three
204
+ article cards in \`renderPage\` produces a site whose owner cannot edit those
205
+ articles from the admin, cannot translate them, cannot add a fourth, and
206
+ cannot delete the one that is wrong. It is not a shortcut; it is a site that
207
+ does not work.
208
+
209
+ Concretely, and without exception:
210
+
211
+ - **Never invent posts, titles, excerpts, author names, dates or prices.** If
212
+ a list should show articles, fetch them:
213
+ \`const posts = await ctx.content.list({ collection: 'article', limit: 6 })\`
214
+ and render what comes back — however many that is, including none.
215
+ - **Never write \`href="#"\`.** A link goes where the content says it goes:
216
+ \`ctx.link({ collection: entry.collection, id: entry.id })\` for an entry,
217
+ \`input.headerNav\`/\`input.footerNav\` in \`renderChrome\` for navigation.
218
+ A \`#\` is a dead link shipped to a real visitor.
219
+ - **Never hardcode display text.** Labels a theme itself owns ("Read more",
220
+ "Next") go through \`ctx.t('readMore', { default: 'Read more' })\`, so a
221
+ site in another language is not stuck with English baked into its layout.
222
+ - **An empty list renders as an empty state**, not as invented filler. A site
223
+ with no articles yet must show that honestly.
224
+
225
+ A design shows three cards; the theme's job is a card *component* and a grid
226
+ that renders however many entries exist. Design the container, never the
227
+ contents.
228
+
229
+ **The preview you get back is sample data.** \`theme.preview_sandbox\` renders
230
+ your theme against a fixed demo page so you can see structure and styling —
231
+ those titles and excerpts are scaffolding for the preview, not content to
232
+ copy into your code. If you find yourself typing a title you saw in a
233
+ preview, that is the mistake this section exists to prevent.
234
+
235
+ ## Images
236
+
237
+ A photograph the request calls for is a real \`url()\` or \`<img>\`, resolved
238
+ through \`ctx.image(mediaId)\` for uploaded media or pointing at a real asset
239
+ path. A flat colour block standing in for a photo the brief asked for is a
240
+ failure to deliver the design, not a simplification.
241
+
242
+ ## What "matching a design" means here
243
+
244
+ Colour is the easiest half and the least of it. When a reference is given,
245
+ reproduce, in this order of importance: the **layout skeleton** (how the page
246
+ divides into regions, what is full-bleed vs contained, the grid and column
247
+ counts), the **spacing rhythm and density**, the **typographic scale and
248
+ pairing** (display vs body face, weights, letter-spacing, how large the
249
+ biggest thing actually is relative to body text), the **shape language**
250
+ (corner radius, borders, elevation, how flat or how carved), and only then
251
+ the palette. A theme with the right palette and the wrong skeleton does not
252
+ resemble the reference; the reverse mostly does.
253
+ `.trim();
254
+ //# sourceMappingURL=theme-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-spec.js","sourceRoot":"","sources":["../../src/theme-creator/theme-spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+N1C,CAAC,IAAI,EAAE,CAAA"}
@@ -0,0 +1,54 @@
1
+ import { type ToolDefinition } from '@cogenta/agents';
2
+ import { z } from 'zod';
3
+ /**
4
+ * `theme.write_sandbox_file` (`tools@1.6`, `docs/04-contrats.md`) — fiche 73
5
+ * task 7. Same shape as `code.propose_patch` (`code.patch`,
6
+ * `../developer/patch-tool.ts`), on purpose: a real, effectful write with a
7
+ * real `revert`, `sideEffects: true` + `reversible: true` keeping it inside
8
+ * `withAutonomy`'s ordinary gate rather than always forcing approval. What
9
+ * differs is the destination and the meaning of "revert": `code.patch`
10
+ * opens a pull request nothing merges automatically, this writes straight
11
+ * into one file of one theme *sandbox* (`<projectRoot>/.cogenta/theme-sandbox
12
+ * /<id>/`, fiche 73 task 4) — never `themes/`, and so never anything a live
13
+ * request could resolve. `revert` deletes the file it wrote, the same
14
+ * "undo the one write this tool made" meaning `deps.patch`'s `revert`
15
+ * already has, just without a forge in between.
16
+ *
17
+ * `writeFile`/`deleteFile` are factory options, not part of the Zod input
18
+ * schema — the same shape `theme.propose_theme`'s `resolveProvider` and
19
+ * `code.propose_patch`'s `prClient` already use: this package cannot import
20
+ * `@cogenta/cli`'s `theme-sandbox.ts` (the dependency arrow runs the other
21
+ * way — `@cogenta/cli` depends on `@cogenta/agents-builtin`, never the
22
+ * reverse), so the real filesystem write — and the path-escape guard that
23
+ * makes it safe to hand a model — lives in `@cogenta/cli` and is threaded in
24
+ * here as a plain function.
25
+ */
26
+ export interface WriteSandboxFileToolOptions {
27
+ readonly writeFile: (input: {
28
+ readonly sandboxId: string;
29
+ readonly path: string;
30
+ readonly content: string;
31
+ }) => Promise<{
32
+ readonly path: string;
33
+ readonly warnings?: readonly string[];
34
+ }>;
35
+ readonly deleteFile: (input: {
36
+ readonly sandboxId: string;
37
+ readonly path: string;
38
+ }) => Promise<void>;
39
+ }
40
+ declare const WriteSandboxFileInputSchema: z.ZodObject<{
41
+ sandboxId: z.ZodString;
42
+ path: z.ZodString;
43
+ content: z.ZodString;
44
+ }, z.core.$strip>;
45
+ export type WriteSandboxFileInput = z.infer<typeof WriteSandboxFileInputSchema>;
46
+ declare const WriteSandboxFileOutputSchema: z.ZodObject<{
47
+ sandboxId: z.ZodString;
48
+ path: z.ZodString;
49
+ warnings: z.ZodOptional<z.ZodArray<z.ZodString>>;
50
+ }, z.core.$strip>;
51
+ export type WriteSandboxFileOutput = z.infer<typeof WriteSandboxFileOutputSchema>;
52
+ export declare function createWriteSandboxFileTool(options: WriteSandboxFileToolOptions): ToolDefinition<WriteSandboxFileInput, WriteSandboxFileOutput>;
53
+ export {};
54
+ //# sourceMappingURL=write-sandbox-file-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-sandbox-file-tool.d.ts","sourceRoot":"","sources":["../../src/theme-creator/write-sandbox-file-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE;QAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KACzB,KAAK,OAAO,CAAC;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;IAC/E,QAAQ,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE;QAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;QAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KACtB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpB;AAED,QAAA,MAAM,2BAA2B;;;;iBAM/B,CAAA;AACF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAA;AAE/E,QAAA,MAAM,4BAA4B;;;;iBAKhC,CAAA;AACF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAA;AAEjF,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,2BAA2B,GACnC,cAAc,CAAC,qBAAqB,EAAE,sBAAsB,CAAC,CA4F/D"}
@@ -0,0 +1,109 @@
1
+ import { defineTool } from '@cogenta/agents';
2
+ import { z } from 'zod';
3
+ const WriteSandboxFileInputSchema = z.object({
4
+ /** An id `theme.propose_theme`-adjacent tooling (or a human) already created — this tool never creates a sandbox itself. */
5
+ sandboxId: z.string().min(1),
6
+ /** Sandbox-relative, e.g. `"theme.render.mjs"` — never absolute, never `../`-prefixed. The real escape guard is enforced host-side, in `@cogenta/cli`; this tool has no filesystem of its own to guard. */
7
+ path: z.string().min(1),
8
+ content: z.string(),
9
+ });
10
+ const WriteSandboxFileOutputSchema = z.object({
11
+ sandboxId: z.string(),
12
+ path: z.string(),
13
+ /** Present when the file was accepted but contains something worth fixing — a dead `href="#"`, say. Read them: a warning here is a real defect that simply was not worth refusing the write over. */
14
+ warnings: z.array(z.string()).optional(),
15
+ });
16
+ export function createWriteSandboxFileTool(options) {
17
+ return defineTool({
18
+ name: 'theme.write_sandbox_file',
19
+ version: '1.0.0',
20
+ description: `Writes one real source file (theme.config.*, theme.render.*, or any other file the theme needs) into a theme sandbox — actual TypeScript/JavaScript code, not tokens. Use this, never theme.propose_theme, whenever the request needs custom layout, custom markup structure, or anything no installed theme package already renders — a fully custom design, not a recolour of an existing one. theme.propose_theme only ever picks an existing installed theme and fills its colour/font/spacing tokens; it cannot change layout or markup. Never writes into themes/ directly, and never touches anything a live request could resolve — deploying the sandbox stays a separate, human-confirmed action.
21
+
22
+ Full design freedom, like a WordPress theme or a Strapi frontend: renderPage/renderChrome are plain code, not a fixed template — fetch whatever data you want via ctx.content.entry()/list()/byPath() (any collection, not just what a page's own blocks list) and place it anywhere, in any layout, any markup, any CSS. page.blocks is one available data source, never a required structure — a page's blocks can be ignored entirely for a fully bespoke design that queries content directly. There is no closed list of block types either: a custom block type — any name, including one nobody else uses — is fine to invent and handle in renderPage; the shared vocabulary (hero, prose, mediaFigure, featureGrid, cta, gallery, quote, faq, stats, logos, collectionList, embed, testimonial, pricingTable, accordion, statCounter, logoStrip) is only there so existing content composed with those still shows something if this theme chooses to render them — implementing all of them is never required to deploy.
23
+
24
+ Every write of theme.config.* or theme.render.* is validated for real before it lands — an invalid manifest field, a missing export, or a render function that does not actually produce a real page is rejected with a specific error naming what is wrong; read it and call this tool again with a corrected file. It is normal to need a few tries.
25
+
26
+ theme.config.* — export default defineTheme({...}) from '@cogenta/theme-kit', EXACTLY these fields:
27
+ name: string, version: 'X.Y.Z' (exact semver), engine: '^1.0.0' (a semver RANGE, not a description), blocks: '^1.0.0' (also a semver range — the block-vocabulary version this theme supports, NEVER a list of block names), implements: string[] (which block _type names this theme's renderPage actually handles, e.g. ['hero','collectionList','prose']), collections: string[] | '*', runtime: 'static' | 'server' | 'edge' (one of these three literal strings, never an object), tokens: a STRING path to the tokens file, e.g. './theme.tokens.json' (never inline token data — the token VALUES belong in that separate JSON file, shaped like SkinTokens: {color:{bg,fg,accent,accentFg,muted,mutedFg,border}, font:{sans,serif,mono,scale,baseSize}, space:{unit,density}, radius:{sm,md,lg}, motion:{duration,easing,reduced}, shadow:{sm,md}} — nothing more, nothing less).
28
+
29
+ A real .css file — any file name, any number of files (theme.css, style.css, base.css + blocks.css, whatever fits) — is REQUIRED for any design that is supposed to look like anything: real CSS, plain text, no <style> tags. Every *.css file written into this sandbox is picked up automatically, no naming convention to follow. Without at least one, the page is 100% unstyled HTML — every visual detail (colours, layout, spacing, grid, cards, hero image, typography) comes ONLY from selectors written here targeting the class names theme.render.* emits; nothing renders a design on its own. Read the request's visual reference (screenshot/description) closely and write real, specific CSS for it — layout (flexbox/grid), colours, spacing, typography, imagery — not a token dump. Colour/font/spacing VALUES are not invented here: reference the site's actual skin tokens through the CSS custom properties the site already generates on :root — --cogenta-color-bg/fg/accent/accent-fg/muted/muted-fg/border, --cogenta-font-sans/serif/mono, --cogenta-font-size-xs/sm/md/lg/xl/2xl/3xl, --cogenta-space-unit, --cogenta-radius-sm/md/lg, --cogenta-shadow-sm/md — e.g. "background: var(--cogenta-color-bg); font-family: var(--cogenta-font-serif); padding: calc(var(--cogenta-space-unit) * 2);". A background photo or other imagery is a real url() the theme's own markup or CSS points at (e.g. an uploaded media file resolved through ctx.image() and passed into the render module's markup as a style/background, or a static asset path) — never a placeholder colour standing in for a photo the brief actually asked for.
30
+
31
+ theme.render.* — a real ES module. renderPage and renderChrome build markup with h() from '@cogenta/theme-kit' (h(tag, attrs, ...children) => HtmlElement, NOT a plain data object — the render pipeline calls serialize() on what these return, which only understands an HtmlElement tree or a plain string). There is no ctx.theme.tokens or any per-request access to skin token VALUES from render code — tokens reach the page only through the CSS custom properties the .css file(s) above read, never as JS values; a render module only ever emits semantic HTML with class names for that CSS to target. Minimal, real, working example:
32
+
33
+ import { h } from '@cogenta/theme-kit'
34
+
35
+ export function renderChrome(input) {
36
+ // input: { site: {name,url,locales,defaultLocale}, locale, homeHref, headerNav: [{label,href}], footerNav, brandingHtml }
37
+ const nav = (input.headerNav || []).map((l) => \`<a href="\${l.href}">\${l.label}</a>\`).join('')
38
+ return {
39
+ header: \`<header class="cg-header"><a href="\${input.homeHref}">\${input.site.name}</a><nav>\${nav}</nav></header>\`,
40
+ footer: \`<footer class="cg-footer">\${input.site.name}</footer>\`,
41
+ }
42
+ }
43
+
44
+ export function renderPage(page, ctx, entries = {}) {
45
+ // page: { title: string, blocks: Array<{_key, _type, ...fields}> } — the entry's real, saved contract-B blocks.
46
+ // ctx: { site, locale, url, t(key,vals), image(mediaId,opts), link(target), content: {entry,byPath,list} }
47
+ // entries: fetched collectionList results, keyed by block._key.
48
+ const renderedBlocks = page.blocks.map((block) => {
49
+ if (block._type === 'hero') {
50
+ return h('section', { class: 'cg-hero' }, [
51
+ h('h1', { class: 'cg-hero__title' }, block.title || page.title),
52
+ block.subtitle ? h('p', { class: 'cg-hero__subtitle' }, block.subtitle) : null,
53
+ ])
54
+ }
55
+ if (block._type === 'collectionList') {
56
+ const items = entries[block._key] || []
57
+ return h(
58
+ 'section',
59
+ { class: 'cg-grid' },
60
+ items.map((entry) =>
61
+ h('article', { class: 'cg-card' }, [
62
+ h('h3', {}, String(entry.title ?? '')),
63
+ h('a', { href: ctx.link({ collection: entry.collection, id: entry.id }) }, ctx.t('readMore', { default: 'Read more' })),
64
+ ]),
65
+ ),
66
+ )
67
+ }
68
+ // Any block type not specifically styled still renders, plainly — never drop content the page actually has.
69
+ return h('section', { class: 'cg-block', 'data-type': block._type }, block.title ? h('h2', {}, String(block.title)) : null)
70
+ })
71
+ return h('main', { class: 'cg-main' }, [h('h1', { class: 'cg-page-title' }, page.title), ...renderedBlocks])
72
+ }
73
+
74
+ Matching .css for the example above (real selectors for the real classes theme.render.* just emitted — this is the part that actually makes it look like anything; call the file whatever you want):
75
+
76
+ .cg-main { background: var(--cogenta-color-bg); color: var(--cogenta-color-fg); font-family: var(--cogenta-font-sans); }
77
+ .cg-hero { padding: calc(var(--cogenta-space-unit) * 4) calc(var(--cogenta-space-unit) * 2); text-align: center; }
78
+ .cg-hero__title { font-family: var(--cogenta-font-serif); font-size: var(--cogenta-font-size-3xl); }
79
+ .cg-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--cogenta-space-unit); padding: var(--cogenta-space-unit); }
80
+ .cg-card { background: var(--cogenta-color-muted); color: var(--cogenta-color-muted-fg); border-radius: var(--cogenta-radius-md); padding: var(--cogenta-space-unit); box-shadow: var(--cogenta-shadow-sm); }
81
+ @media (max-width: 640px) { .cg-grid { grid-template-columns: 1fr; } }
82
+
83
+ This example is deliberately generic (it renders whatever block types a real page actually has, defaulting unknown ones to a plain but real block rather than silently dropping them) — adapt the class names, nesting and per-block-type markup freely to match the requested design, but keep using h() to build the tree, keep renderChrome returning { header, footer } as HTML strings, and always write real .css (any file name) that actually styles whatever class names this file ends up using — a theme.render.* with no matching CSS renders as unstyled text, every time, regardless of how good the markup structure is.`,
84
+ input: WriteSandboxFileInputSchema,
85
+ output: WriteSandboxFileOutputSchema,
86
+ permissions: ['theme.write_sandbox'],
87
+ sideEffects: true,
88
+ reversible: true,
89
+ cost: 'low',
90
+ async execute(input) {
91
+ const result = await options.writeFile({
92
+ sandboxId: input.sandboxId,
93
+ path: input.path,
94
+ content: input.content,
95
+ });
96
+ return {
97
+ sandboxId: input.sandboxId,
98
+ path: result.path,
99
+ ...(result.warnings === undefined || result.warnings.length === 0
100
+ ? {}
101
+ : { warnings: [...result.warnings] }),
102
+ };
103
+ },
104
+ async revert(receipt) {
105
+ await options.deleteFile({ sandboxId: receipt.sandboxId, path: receipt.path });
106
+ },
107
+ });
108
+ }
109
+ //# sourceMappingURL=write-sandbox-file-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-sandbox-file-tool.js","sourceRoot":"","sources":["../../src/theme-creator/write-sandbox-file-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAuB,MAAM,iBAAiB,CAAA;AACjE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAsCvB,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,4HAA4H;IAC5H,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,2MAA2M;IAC3M,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;CACpB,CAAC,CAAA;AAGF,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;IAChB,qMAAqM;IACrM,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC,CAAA;AAGF,MAAM,UAAU,0BAA0B,CACxC,OAAoC;IAEpC,OAAO,UAAU,CAAC;QAChB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wmBA+DulB;QACpmB,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,4BAA4B;QACpC,WAAW,EAAE,CAAC,qBAAqB,CAAC;QACpC,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,IAAI;QAChB,IAAI,EAAE,KAAK;QACX,KAAK,CAAC,OAAO,CAAC,KAAK;YACjB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC;gBACrC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAA;YACF,OAAO;gBACL,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,GAAG,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;oBAC/D,CAAC,CAAC,EAAE;oBACJ,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;aACxC,CAAA;QACH,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,OAAO;YAClB,MAAM,OAAO,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;QAChF,CAAC;KACF,CAAC,CAAA;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cogenta/agents-builtin",
3
- "version": "0.3.2",
3
+ "version": "0.5.0",
4
4
  "description": "The built-in agents shipped with Cogenta — Security, SEO, Content, Performance.",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",
@@ -28,8 +28,8 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "zod": "^4.4.3",
31
- "@cogenta/agents": "0.5.1",
32
- "@cogenta/core": "0.7.0"
31
+ "@cogenta/core": "0.9.0",
32
+ "@cogenta/agents": "0.7.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "^7.0.2",