@pebbly/aseprite-ai-artist 0.1.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 (103) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/LICENSE +21 -0
  3. package/README.md +169 -0
  4. package/agents/animation-director.md +65 -0
  5. package/agents/palette-smith.md +57 -0
  6. package/agents/pixel-critic.md +69 -0
  7. package/agents/rig-builder.md +46 -0
  8. package/bin/aseprite-ai-artist +6 -0
  9. package/bin/aseprite-ai-artist.mjs +44 -0
  10. package/dist/bridge/bridge.d.ts +52 -0
  11. package/dist/bridge/bridge.js +230 -0
  12. package/dist/bridge/bridge.js.map +1 -0
  13. package/dist/bridge/client.d.ts +54 -0
  14. package/dist/bridge/client.js +214 -0
  15. package/dist/bridge/client.js.map +1 -0
  16. package/dist/cli.d.ts +10 -0
  17. package/dist/cli.js +272 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/extension.d.ts +21 -0
  20. package/dist/extension.js +65 -0
  21. package/dist/extension.js.map +1 -0
  22. package/dist/install.d.ts +35 -0
  23. package/dist/install.js +185 -0
  24. package/dist/install.js.map +1 -0
  25. package/dist/lib/color.d.ts +66 -0
  26. package/dist/lib/color.js +170 -0
  27. package/dist/lib/color.js.map +1 -0
  28. package/dist/lib/protocol.d.ts +78 -0
  29. package/dist/lib/protocol.js +72 -0
  30. package/dist/lib/protocol.js.map +1 -0
  31. package/dist/lib/render.d.ts +62 -0
  32. package/dist/lib/render.js +134 -0
  33. package/dist/lib/render.js.map +1 -0
  34. package/dist/lib/skills.d.ts +43 -0
  35. package/dist/lib/skills.js +112 -0
  36. package/dist/lib/skills.js.map +1 -0
  37. package/dist/lib/version.d.ts +4 -0
  38. package/dist/lib/version.js +25 -0
  39. package/dist/lib/version.js.map +1 -0
  40. package/dist/server.d.ts +15 -0
  41. package/dist/server.js +144 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/tools/assets.d.ts +3 -0
  44. package/dist/tools/assets.js +181 -0
  45. package/dist/tools/assets.js.map +1 -0
  46. package/dist/tools/craft.d.ts +12 -0
  47. package/dist/tools/craft.js +143 -0
  48. package/dist/tools/craft.js.map +1 -0
  49. package/dist/tools/draw.d.ts +3 -0
  50. package/dist/tools/draw.js +256 -0
  51. package/dist/tools/draw.js.map +1 -0
  52. package/dist/tools/escape.d.ts +12 -0
  53. package/dist/tools/escape.js +49 -0
  54. package/dist/tools/escape.js.map +1 -0
  55. package/dist/tools/kit.d.ts +29 -0
  56. package/dist/tools/kit.js +85 -0
  57. package/dist/tools/kit.js.map +1 -0
  58. package/dist/tools/look.d.ts +7 -0
  59. package/dist/tools/look.js +215 -0
  60. package/dist/tools/look.js.map +1 -0
  61. package/dist/tools/palette.d.ts +3 -0
  62. package/dist/tools/palette.js +232 -0
  63. package/dist/tools/palette.js.map +1 -0
  64. package/dist/tools/session.d.ts +3 -0
  65. package/dist/tools/session.js +231 -0
  66. package/dist/tools/session.js.map +1 -0
  67. package/dist/tools/structure.d.ts +3 -0
  68. package/dist/tools/structure.js +218 -0
  69. package/dist/tools/structure.js.map +1 -0
  70. package/examples/mcp-configs/claude-code.json +9 -0
  71. package/examples/mcp-configs/codex.toml +13 -0
  72. package/examples/mcp-configs/cursor.json +9 -0
  73. package/examples/mcp-configs/gemini-cli.json +9 -0
  74. package/examples/mcp-configs/vscode.json +10 -0
  75. package/extension/ai-artist.lua +3291 -0
  76. package/extension/package.json +14 -0
  77. package/hooks/hooks.json +25 -0
  78. package/hooks/look-nudge.mjs +46 -0
  79. package/hooks/session-status.mjs +47 -0
  80. package/knowledge/palettes.json +60 -0
  81. package/package.json +69 -0
  82. package/rules/00-core-principles.md +57 -0
  83. package/rules/01-palette-and-color.md +51 -0
  84. package/rules/02-shading-and-light.md +56 -0
  85. package/rules/03-silhouette-and-form.md +60 -0
  86. package/rules/04-outlines-and-edges.md +46 -0
  87. package/rules/05-animation.md +62 -0
  88. package/rules/06-layers-and-rigging.md +52 -0
  89. package/rules/07-review-checklist.md +51 -0
  90. package/rules/README.md +16 -0
  91. package/skills/README.md +29 -0
  92. package/skills/pixel-animate/SKILL.md +91 -0
  93. package/skills/pixel-brief/SKILL.md +61 -0
  94. package/skills/pixel-draw/SKILL.md +93 -0
  95. package/skills/pixel-export/SKILL.md +80 -0
  96. package/skills/pixel-fix/SKILL.md +91 -0
  97. package/skills/pixel-new/SKILL.md +70 -0
  98. package/skills/pixel-palette/SKILL.md +80 -0
  99. package/skills/pixel-review/SKILL.md +81 -0
  100. package/skills/pixel-rig/SKILL.md +76 -0
  101. package/skills/pixel-shade/SKILL.md +77 -0
  102. package/skills/pixel-tileset/SKILL.md +104 -0
  103. package/templates/AGENTS.section.md +33 -0
@@ -0,0 +1,215 @@
1
+ import { readFile, unlink } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { filmstripLayout, renderAscii, renderDiff, } from "../lib/render.js";
6
+ import { fail, ok, okWithImage, targetShape } from "./kit.js";
7
+ /**
8
+ * The "see your own work" tool. Drawing without looking is how an agent ends up
9
+ * confidently reporting a finished sprite that is a smear of misplaced pixels.
10
+ */
11
+ export function registerLookTools(server, live) {
12
+ server.registerTool("look", {
13
+ title: "Look at the sprite",
14
+ description: "See what is actually on the canvas. Ops:\n" +
15
+ "• 'preview' — a nearest-neighbour upscaled PNG of the active frame (~1024px long edge). Use for overall read: silhouette, colour, whether it looks like the thing.\n" +
16
+ "• 'ascii' — an exact text grid, one glyph per pixel with a colour legend and coordinate rulers. Use to verify precise pixel positions and values, to count cells, or on any client without vision. Capped at 64×64; pass a region to crop.\n" +
17
+ "• 'filmstrip' — every frame composited into one image. The only reliable way to review an animation, since a vision model reads just the first frame of a GIF.\n" +
18
+ "• 'diff' — a pixel-level text diff between two frames: '.' unchanged, '-' erased, glyph = the new colour. Use it to confirm exactly what an edit touched.\n" +
19
+ "Draw, then look, then fix. Do not report a sprite finished without looking at it.",
20
+ inputSchema: {
21
+ op: z.enum(["preview", "ascii", "filmstrip", "diff"]).default("preview"),
22
+ sprite: targetShape.sprite,
23
+ frame: targetShape.frame,
24
+ fromFrame: z.number().int().positive().optional().describe("Diff: the earlier frame."),
25
+ toFrame: z.number().int().positive().optional().describe("Diff: the later frame."),
26
+ region: z
27
+ .object({
28
+ x: z.number().int(),
29
+ y: z.number().int(),
30
+ width: z.number().int().positive(),
31
+ height: z.number().int().positive(),
32
+ })
33
+ .optional()
34
+ .describe("Crop. Required for 'ascii' on sprites larger than 64×64."),
35
+ layer: z
36
+ .string()
37
+ .optional()
38
+ .describe("Read a single layer instead of the composited image."),
39
+ scale: z
40
+ .number()
41
+ .int()
42
+ .positive()
43
+ .max(128)
44
+ .optional()
45
+ .describe("Integer upscale for image ops, 1-128 (clamped so the output stays under ~2048px). Omit it — the automatic choice targets a ~1024px long edge, which is what a vision model can actually read."),
46
+ },
47
+ outputSchema: {
48
+ op: z.string(),
49
+ sprite: z.string(),
50
+ width: z.number().int(),
51
+ height: z.number().int(),
52
+ scale: z.number().int().optional(),
53
+ text: z.string().optional().describe("The grid, for 'ascii' and 'diff'."),
54
+ legend: z.record(z.string()).optional().describe("glyph → #rrggbb."),
55
+ changedPixels: z.number().int().optional(),
56
+ totalPixels: z.number().int().optional(),
57
+ frames: z.number().int().optional(),
58
+ columns: z.number().int().optional(),
59
+ rows: z.number().int().optional(),
60
+ },
61
+ annotations: { readOnlyHint: true, openWorldHint: false },
62
+ }, async (args) => {
63
+ try {
64
+ switch (args.op) {
65
+ case "ascii": {
66
+ const region = await readRegion(live, args);
67
+ const view = renderAscii(region);
68
+ return ok({
69
+ op: "ascii",
70
+ sprite: region.spriteName,
71
+ width: view.width,
72
+ height: view.height,
73
+ text: view.text,
74
+ legend: view.legend,
75
+ }, `${view.width}×${view.height} at (${view.originX},${view.originY})\n\n${view.text}\n\nLegend: ${formatLegend(view.legend)}\n'.' = transparent`);
76
+ }
77
+ case "diff": {
78
+ const from = args.fromFrame ?? 1;
79
+ const to = args.toFrame ?? from + 1;
80
+ const [before, after] = await Promise.all([
81
+ readRegion(live, { ...args, frame: from }),
82
+ readRegion(live, { ...args, frame: to }),
83
+ ]);
84
+ const view = renderDiff(before, after);
85
+ return ok({
86
+ op: "diff",
87
+ sprite: before.spriteName,
88
+ width: before.width,
89
+ height: before.height,
90
+ text: view.text,
91
+ legend: view.legend,
92
+ changedPixels: view.changed,
93
+ totalPixels: view.total,
94
+ }, `Frame ${from} → ${to}: ${view.changed} of ${view.total} pixels changed.\n\n${view.text}\n\nLegend: ${formatLegend(view.legend)}\n'.' unchanged '-' erased`);
95
+ }
96
+ case "filmstrip": {
97
+ const out = tempPng("filmstrip");
98
+ const meta = await live.call("look.filmstrip", {
99
+ sprite: args.sprite,
100
+ path: out,
101
+ scale: args.scale,
102
+ });
103
+ const layout = filmstripLayout(meta.frames);
104
+ const image = await readAndClean(out);
105
+ return okWithImage({
106
+ op: "filmstrip",
107
+ sprite: meta.sprite,
108
+ width: meta.width,
109
+ height: meta.height,
110
+ scale: meta.scale,
111
+ frames: meta.frames,
112
+ columns: layout.cols,
113
+ rows: layout.rows,
114
+ }, image, `Filmstrip of ${meta.frames} frame(s), ${layout.cols}×${layout.rows} grid, ${meta.scale}× upscale. Read left to right, top to bottom; check timing and cross-frame volume drift.`);
115
+ }
116
+ default: {
117
+ const out = tempPng("preview");
118
+ const meta = await live.call("look.preview", {
119
+ sprite: args.sprite,
120
+ frame: args.frame,
121
+ layer: args.layer,
122
+ region: args.region,
123
+ path: out,
124
+ // Omitted scale means the extension picks one from the sprite size.
125
+ scale: args.scale,
126
+ });
127
+ const image = await readAndClean(out);
128
+ return okWithImage({
129
+ op: "preview",
130
+ sprite: meta.sprite,
131
+ width: meta.sourceWidth,
132
+ height: meta.sourceHeight,
133
+ scale: meta.scale,
134
+ }, image, `${meta.sprite} — ${meta.sourceWidth}×${meta.sourceHeight} shown at ${meta.scale}×. For exact pixel values use op 'ascii'.`);
135
+ }
136
+ }
137
+ }
138
+ catch (err) {
139
+ return fail(err);
140
+ }
141
+ });
142
+ server.registerTool("read_pixels", {
143
+ title: "Read pixels",
144
+ description: "Read a rectangular region as structured data: a list of distinct colours plus a row-major index grid. Use this when you need to compute over pixels (sample a palette from art, find a silhouette edge, copy a region) rather than just look at them. For eyeballing, 'look' is cheaper.",
145
+ inputSchema: {
146
+ ...targetShape,
147
+ region: z
148
+ .object({
149
+ x: z.number().int(),
150
+ y: z.number().int(),
151
+ width: z.number().int().positive(),
152
+ height: z.number().int().positive(),
153
+ })
154
+ .optional()
155
+ .describe("Omit to read the whole canvas."),
156
+ composite: z
157
+ .boolean()
158
+ .default(true)
159
+ .describe("Read the flattened image. False reads only the target layer's cel."),
160
+ },
161
+ outputSchema: {
162
+ sprite: z.string(),
163
+ x: z.number().int(),
164
+ y: z.number().int(),
165
+ width: z.number().int(),
166
+ height: z.number().int(),
167
+ colors: z.array(z.string()).describe("Distinct colours; index 0 is fully transparent."),
168
+ grid: z.array(z.number().int()).describe("Row-major indices into `colors`."),
169
+ uniqueColors: z.number().int(),
170
+ },
171
+ annotations: { readOnlyHint: true, openWorldHint: false },
172
+ }, async (args) => {
173
+ try {
174
+ const region = await readRegion(live, args);
175
+ return ok({
176
+ sprite: region.spriteName,
177
+ x: region.x,
178
+ y: region.y,
179
+ width: region.width,
180
+ height: region.height,
181
+ colors: region.colors,
182
+ grid: region.grid,
183
+ uniqueColors: Math.max(0, region.colors.length - 1),
184
+ }, `${region.width}×${region.height} region, ${Math.max(0, region.colors.length - 1)} distinct colour(s).`);
185
+ }
186
+ catch (err) {
187
+ return fail(err);
188
+ }
189
+ });
190
+ }
191
+ async function readRegion(live, args) {
192
+ const data = await live.call("pixels.read", {
193
+ sprite: args.sprite,
194
+ layer: args.layer,
195
+ frame: args.frame,
196
+ region: args.region,
197
+ composite: args.composite ?? true,
198
+ });
199
+ return { ...data, spriteName: data.sprite };
200
+ }
201
+ function tempPng(prefix) {
202
+ return path.join(tmpdir(), `aseprite-ai-artist-${prefix}-${Date.now()}-${process.pid}.png`);
203
+ }
204
+ async function readAndClean(file) {
205
+ const buf = await readFile(file);
206
+ await unlink(file).catch(() => { });
207
+ return { data: buf.toString("base64"), mimeType: "image/png" };
208
+ }
209
+ function formatLegend(legend) {
210
+ const entries = Object.entries(legend);
211
+ if (entries.length === 0)
212
+ return "(empty)";
213
+ return entries.map(([g, hex]) => `${g}=${hex}`).join(" ");
214
+ }
215
+ //# sourceMappingURL=look.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"look.js","sourceRoot":"","sources":["../../src/tools/look.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { LiveClient } from "../bridge/client.js";
3
+ export declare function registerPaletteTools(server: McpServer, live: LiveClient): void;
@@ -0,0 +1,232 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { fileURLToPath } from "node:url";
3
+ import path from "node:path";
4
+ import { z } from "zod";
5
+ import { buildRamp, contrastRatio, parseHex, snapToPalette } from "../lib/color.js";
6
+ import { fail, hexColor, ok, targetShape } from "./kit.js";
7
+ let presetCache = null;
8
+ function presets() {
9
+ if (presetCache)
10
+ return presetCache;
11
+ const here = path.dirname(fileURLToPath(import.meta.url));
12
+ // dist/tools/palette.js → package root
13
+ const file = path.resolve(here, "..", "..", "knowledge", "palettes.json");
14
+ const parsed = JSON.parse(readFileSync(file, "utf8"));
15
+ presetCache = parsed.presets;
16
+ return presetCache;
17
+ }
18
+ export function registerPaletteTools(server, live) {
19
+ server.registerTool("palette", {
20
+ title: "Palette",
21
+ description: "Read and shape the sprite's palette. Ops:\n" +
22
+ "• 'get' — current palette with per-colour usage counts.\n" +
23
+ "• 'set' — write specific indices, or replace the palette wholesale.\n" +
24
+ "• 'preset' — load a bundled palette (pico8, gameboy, gameboy-pocket, cga, 1bit, grayscale-8).\n" +
25
+ "• 'load' — read a .gpl/.hex/.pal/.png palette file from disk.\n" +
26
+ "• 'ramp' — generate a hue-shifted ramp from a base colour and append it. Shadows rotate toward blue, highlights toward orange; a ramp that only changes brightness is the clearest tell of machine-made pixel art.\n" +
27
+ "• 'analyze' — report ramp structure, contrast, near-duplicate entries and colours used in the art that are not in the palette.\n" +
28
+ "Decide the palette before drawing. Retro-fitting one onto finished art means repainting.",
29
+ inputSchema: {
30
+ op: z.enum(["get", "set", "preset", "load", "ramp", "analyze"]),
31
+ sprite: targetShape.sprite,
32
+ preset: z.string().optional().describe("Preset key for op 'preset'."),
33
+ path: z.string().optional().describe("Palette file for op 'load'."),
34
+ colors: z
35
+ .array(hexColor)
36
+ .optional()
37
+ .describe("For op 'set': the colours to write."),
38
+ startIndex: z
39
+ .number()
40
+ .int()
41
+ .min(0)
42
+ .default(0)
43
+ .describe("For op 'set': where `colors` starts. Ignored when `replace` is true."),
44
+ replace: z
45
+ .boolean()
46
+ .default(false)
47
+ .describe("For op 'set'/'preset': replace the whole palette instead of merging."),
48
+ base: hexColor.optional().describe("Base colour for op 'ramp'."),
49
+ steps: z.number().int().min(2).max(16).default(5).describe("Ramp length."),
50
+ spread: z
51
+ .number()
52
+ .min(0.1)
53
+ .max(1)
54
+ .default(0.55)
55
+ .describe("How far the ramp reaches into shadow and light."),
56
+ remapArt: z
57
+ .boolean()
58
+ .default(false)
59
+ .describe("When replacing a palette, repaint existing pixels to the nearest new colour instead of leaving them off-palette."),
60
+ },
61
+ outputSchema: {
62
+ op: z.string(),
63
+ sprite: z.string().optional(),
64
+ colors: z.array(z.string()).optional(),
65
+ size: z.number().int().optional(),
66
+ path: z.string().optional().describe("Palette file read by op 'load'."),
67
+ usage: z
68
+ .array(z.object({ index: z.number().int(), hex: z.string(), pixels: z.number().int() }))
69
+ .optional(),
70
+ ramp: z.array(z.string()).optional(),
71
+ analysis: z
72
+ .object({
73
+ size: z.number().int(),
74
+ unusedIndices: z.array(z.number().int()),
75
+ nearDuplicates: z.array(z.object({ a: z.string(), b: z.string(), deltaE: z.number() })),
76
+ offPaletteColors: z.array(z.object({ hex: z.string(), pixels: z.number().int() })),
77
+ lowestContrastPair: z
78
+ .object({ a: z.string(), b: z.string(), ratio: z.number() })
79
+ .nullish(),
80
+ verdict: z.string(),
81
+ })
82
+ .optional(),
83
+ availablePresets: z
84
+ .array(z.object({ key: z.string(), name: z.string(), size: z.number().int(), notes: z.string() }))
85
+ .optional(),
86
+ },
87
+ annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },
88
+ }, async (args) => {
89
+ try {
90
+ switch (args.op) {
91
+ case "ramp": {
92
+ if (!args.base)
93
+ return fail(new Error("op 'ramp' needs a `base` colour."));
94
+ const ramp = buildRamp(parseHex(args.base), args.steps, args.spread);
95
+ const data = await live.call("palette.set", {
96
+ sprite: args.sprite,
97
+ colors: ramp,
98
+ append: true,
99
+ });
100
+ return ok({ op: "ramp", ramp, ...data }, `Appended a ${args.steps}-step hue-shifted ramp from ${args.base}: ${ramp.join(" ")}`);
101
+ }
102
+ case "preset": {
103
+ const key = (args.preset ?? "").toLowerCase();
104
+ const table = presets();
105
+ const chosen = table[key];
106
+ if (!chosen) {
107
+ return ok({
108
+ op: "preset",
109
+ availablePresets: Object.entries(table).map(([k, p]) => ({
110
+ key: k,
111
+ name: p.name,
112
+ size: p.size,
113
+ notes: p.notes,
114
+ })),
115
+ }, `Unknown preset '${args.preset ?? ""}'. Available: ${Object.keys(table).join(", ")}. Any other palette can be loaded from a file with op 'load'.`);
116
+ }
117
+ const data = await live.call("palette.set", {
118
+ sprite: args.sprite,
119
+ colors: chosen.colors,
120
+ replace: args.replace !== false,
121
+ remapArt: args.remapArt,
122
+ });
123
+ return ok({ op: "preset", colors: chosen.colors, size: chosen.colors.length, ...data }, `Loaded ${chosen.name} (${chosen.colors.length} colours). ${chosen.notes}`);
124
+ }
125
+ case "load": {
126
+ if (!args.path)
127
+ return fail(new Error("op 'load' needs a `path`."));
128
+ const data = await live.call("palette.load", {
129
+ sprite: args.sprite,
130
+ path: args.path,
131
+ replace: args.replace,
132
+ remapArt: args.remapArt,
133
+ });
134
+ return ok({ op: "load", ...data });
135
+ }
136
+ case "set": {
137
+ if (!args.colors || args.colors.length === 0) {
138
+ return fail(new Error("op 'set' needs at least one colour."));
139
+ }
140
+ const data = await live.call("palette.set", {
141
+ sprite: args.sprite,
142
+ colors: args.colors,
143
+ startIndex: args.startIndex,
144
+ replace: args.replace,
145
+ remapArt: args.remapArt,
146
+ });
147
+ return ok({ op: "set", ...data });
148
+ }
149
+ case "analyze": {
150
+ const state = await live.call("palette.stats", { sprite: args.sprite });
151
+ return ok({ op: "analyze", sprite: state.sprite, colors: state.colors, analysis: analyze(state) }, describeAnalysis(analyze(state)));
152
+ }
153
+ default: {
154
+ const data = await live.call("palette.get", {
155
+ sprite: args.sprite,
156
+ });
157
+ const colors = data.colors ?? [];
158
+ return ok({ op: "get", ...data }, `${colors.length} colours: ${colors.join(" ")}`);
159
+ }
160
+ }
161
+ }
162
+ catch (err) {
163
+ return fail(err);
164
+ }
165
+ });
166
+ }
167
+ function analyze(state) {
168
+ const unusedIndices = state.usage.filter((u) => u.pixels === 0).map((u) => u.index);
169
+ const nearDuplicates = [];
170
+ for (let i = 0; i < state.colors.length; i++) {
171
+ const a = state.colors[i];
172
+ if (!a)
173
+ continue;
174
+ // Only compare forward, and only against the rest of the palette.
175
+ const rest = state.colors.slice(i + 1);
176
+ if (rest.length === 0)
177
+ continue;
178
+ const snap = snapToPalette(parseHex(a), rest);
179
+ if (snap.distance < 3) {
180
+ nearDuplicates.push({ a, b: snap.hex, deltaE: round(snap.distance) });
181
+ }
182
+ }
183
+ let lowestContrastPair = null;
184
+ const used = state.usage.filter((u) => u.pixels > 0).slice(0, 32);
185
+ for (let i = 0; i < used.length; i++) {
186
+ for (let j = i + 1; j < used.length; j++) {
187
+ const a = used[i];
188
+ const b = used[j];
189
+ const ratio = contrastRatio(parseHex(a.hex), parseHex(b.hex));
190
+ if (!lowestContrastPair || ratio < lowestContrastPair.ratio) {
191
+ lowestContrastPair = { a: a.hex, b: b.hex, ratio: round(ratio) };
192
+ }
193
+ }
194
+ }
195
+ const problems = [];
196
+ if (state.offPalette.length > 0) {
197
+ problems.push(`${state.offPalette.length} colour(s) in the art are not in the palette`);
198
+ }
199
+ if (nearDuplicates.length > 0) {
200
+ problems.push(`${nearDuplicates.length} near-duplicate palette entr(ies) (ΔE < 3)`);
201
+ }
202
+ if (state.colors.length > 64) {
203
+ problems.push(`${state.colors.length} colours is large for pixel art; most sprites read better under 32`);
204
+ }
205
+ return {
206
+ size: state.colors.length,
207
+ unusedIndices,
208
+ nearDuplicates,
209
+ offPaletteColors: state.offPalette,
210
+ lowestContrastPair,
211
+ verdict: problems.length === 0 ? "clean" : problems.join("; "),
212
+ };
213
+ }
214
+ function describeAnalysis(a) {
215
+ const lines = [`Palette: ${a.size} colours — ${a.verdict}.`];
216
+ if (a.offPaletteColors.length > 0) {
217
+ lines.push(`Off-palette: ${a.offPaletteColors
218
+ .slice(0, 8)
219
+ .map((c) => `${c.hex} (${c.pixels}px)`)
220
+ .join(", ")}. Use recolor op 'snap' to bring them in line.`);
221
+ }
222
+ if (a.nearDuplicates.length > 0) {
223
+ lines.push(`Near-duplicates: ${a.nearDuplicates.slice(0, 5).map((d) => `${d.a}≈${d.b}`).join(", ")}. Merging them makes ramps read more clearly.`);
224
+ }
225
+ if (a.unusedIndices.length > 0)
226
+ lines.push(`${a.unusedIndices.length} palette slot(s) unused.`);
227
+ return lines.join(" ");
228
+ }
229
+ function round(n) {
230
+ return Math.round(n * 100) / 100;
231
+ }
232
+ //# sourceMappingURL=palette.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"palette.js","sourceRoot":"","sources":["../../src/tools/palette.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { LiveClient } from "../bridge/client.js";
3
+ export declare function registerSessionTools(server: McpServer, live: LiveClient): void;