driverge-mcp 0.0.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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +179 -0
  3. package/dist/codegen/esp32.d.ts +4 -0
  4. package/dist/codegen/esp32.js +78 -0
  5. package/dist/codegen/esp32.js.map +1 -0
  6. package/dist/codegen/ident.d.ts +10 -0
  7. package/dist/codegen/ident.js +31 -0
  8. package/dist/codegen/ident.js.map +1 -0
  9. package/dist/codegen/index.d.ts +15 -0
  10. package/dist/codegen/index.js +30 -0
  11. package/dist/codegen/index.js.map +1 -0
  12. package/dist/codegen/lint.d.ts +4 -0
  13. package/dist/codegen/lint.js +112 -0
  14. package/dist/codegen/lint.js.map +1 -0
  15. package/dist/codegen/portable.d.ts +4 -0
  16. package/dist/codegen/portable.js +258 -0
  17. package/dist/codegen/portable.js.map +1 -0
  18. package/dist/codegen/stm32.d.ts +4 -0
  19. package/dist/codegen/stm32.js +64 -0
  20. package/dist/codegen/stm32.js.map +1 -0
  21. package/dist/codegen/types.d.ts +20 -0
  22. package/dist/codegen/types.js +11 -0
  23. package/dist/codegen/types.js.map +1 -0
  24. package/dist/mcp/cache.d.ts +12 -0
  25. package/dist/mcp/cache.js +24 -0
  26. package/dist/mcp/cache.js.map +1 -0
  27. package/dist/mcp/register.d.ts +6 -0
  28. package/dist/mcp/register.js +195 -0
  29. package/dist/mcp/register.js.map +1 -0
  30. package/dist/mcp/summary.d.ts +2 -0
  31. package/dist/mcp/summary.js +36 -0
  32. package/dist/mcp/summary.js.map +1 -0
  33. package/dist/pdf/analyze.d.ts +4 -0
  34. package/dist/pdf/analyze.js +29 -0
  35. package/dist/pdf/analyze.js.map +1 -0
  36. package/dist/pdf/classify.d.ts +8 -0
  37. package/dist/pdf/classify.js +35 -0
  38. package/dist/pdf/classify.js.map +1 -0
  39. package/dist/pdf/command.d.ts +12 -0
  40. package/dist/pdf/command.js +96 -0
  41. package/dist/pdf/command.js.map +1 -0
  42. package/dist/pdf/extract.d.ts +2 -0
  43. package/dist/pdf/extract.js +47 -0
  44. package/dist/pdf/extract.js.map +1 -0
  45. package/dist/pdf/index.d.ts +11 -0
  46. package/dist/pdf/index.js +13 -0
  47. package/dist/pdf/index.js.map +1 -0
  48. package/dist/pdf/interface-kind.d.ts +2 -0
  49. package/dist/pdf/interface-kind.js +46 -0
  50. package/dist/pdf/interface-kind.js.map +1 -0
  51. package/dist/pdf/manufacturer.d.ts +2 -0
  52. package/dist/pdf/manufacturer.js +86 -0
  53. package/dist/pdf/manufacturer.js.map +1 -0
  54. package/dist/pdf/page-map.d.ts +5 -0
  55. package/dist/pdf/page-map.js +52 -0
  56. package/dist/pdf/page-map.js.map +1 -0
  57. package/dist/pdf/part.d.ts +3 -0
  58. package/dist/pdf/part.js +41 -0
  59. package/dist/pdf/part.js.map +1 -0
  60. package/dist/pdf/register-table.d.ts +5 -0
  61. package/dist/pdf/register-table.js +234 -0
  62. package/dist/pdf/register-table.js.map +1 -0
  63. package/dist/pdf/table.d.ts +18 -0
  64. package/dist/pdf/table.js +33 -0
  65. package/dist/pdf/table.js.map +1 -0
  66. package/dist/pdf/types.d.ts +82 -0
  67. package/dist/pdf/types.js +3 -0
  68. package/dist/pdf/types.js.map +1 -0
  69. package/dist/schema/assemble.d.ts +4 -0
  70. package/dist/schema/assemble.js +48 -0
  71. package/dist/schema/assemble.js.map +1 -0
  72. package/dist/schema/index.d.ts +2 -0
  73. package/dist/schema/index.js +4 -0
  74. package/dist/schema/index.js.map +1 -0
  75. package/dist/schema/types.d.ts +51 -0
  76. package/dist/schema/types.js +7 -0
  77. package/dist/schema/types.js.map +1 -0
  78. package/dist/schema/validate.d.ts +2 -0
  79. package/dist/schema/validate.js +84 -0
  80. package/dist/schema/validate.js.map +1 -0
  81. package/dist/server.d.ts +7 -0
  82. package/dist/server.js +49 -0
  83. package/dist/server.js.map +1 -0
  84. package/package.json +59 -0
  85. package/schemas/.gitkeep +0 -0
  86. package/schemas/datasheet.schema.json +109 -0
@@ -0,0 +1,258 @@
1
+ // Portable thin-HAL codegen. Renders a deterministic C driver skeleton from the
2
+ // frozen DatasheetJson: register/command constants, bit-field mask+shift macros,
3
+ // the 5-function thin-HAL seam (and NOTHING platform-specific — see
4
+ // thin-hal-non-negotiable), function stubs, and TODO(driverge) markers at every
5
+ // spot needing host-AI reasoning. Output is reproducible: no timestamps, stable
6
+ // ordering. The host AI fills the brief and re-validates via validate_driver.
7
+ import { HEX_ONLY, fieldMask, hex2, macro, slug } from "./ident.js";
8
+ const AUTOGEN = (part, mfr, busLine) => [
9
+ "/*",
10
+ ` * ${part} driver — portable thin-HAL skeleton (generated by Driverge).`,
11
+ ` * Manufacturer: ${mfr}`,
12
+ ` * ${busLine}`,
13
+ " *",
14
+ " * This is a deterministic skeleton. Every TODO(driverge) marks a spot the",
15
+ " * host AI must complete (init sequence, vendor quirks, docs) using the",
16
+ " * datasheet JSON, then confirm with the validate_driver tool.",
17
+ " *",
18
+ " * Portability rule: this driver calls ONLY the hal_* seam below — never a",
19
+ " * vendor peripheral API. Implement the seam once per platform.",
20
+ " */",
21
+ ].join("\n");
22
+ // ---------------------------------------------------------------------------
23
+ // register_map
24
+ // ---------------------------------------------------------------------------
25
+ function registerConstants(prefix, registers) {
26
+ const lines = ["/* Register addresses. */"];
27
+ const seen = new Set();
28
+ for (const r of registers) {
29
+ if (!HEX_ONLY.test(r.address))
30
+ continue; // skip ranges like "0xE1…0xF0"
31
+ const macroName = `${prefix}_REG_${macro(r.name)}`;
32
+ if (seen.has(macroName))
33
+ continue;
34
+ seen.add(macroName);
35
+ lines.push(`#define ${macroName} ${r.address.toUpperCase().replace("0X", "0x")}`);
36
+ }
37
+ return lines;
38
+ }
39
+ function bitFieldMacros(prefix, registers) {
40
+ const lines = [];
41
+ for (const r of registers) {
42
+ if (r.bitFields.length === 0)
43
+ continue;
44
+ lines.push("", `/* ${r.name} bit fields. */`);
45
+ for (const f of r.bitFields) {
46
+ const base = `${prefix}_${macro(r.name)}_${macro(f.name)}`;
47
+ lines.push(`#define ${base}_MASK ${hex2(fieldMask(f.msb, f.lsb))}`);
48
+ lines.push(`#define ${base}_SHIFT ${f.lsb}`);
49
+ }
50
+ }
51
+ return lines;
52
+ }
53
+ function registerDriver(json, name, prefix) {
54
+ const registers = json.interface.registers;
55
+ const spi = json.protocol.bus === "SPI";
56
+ const addr = json.protocol.addresses?.[0];
57
+ const guard = `${prefix}_H`;
58
+ const type = `${name}_t`;
59
+ const header = [
60
+ AUTOGEN(json.metadata.part || name, json.metadata.manufacturer, spi ? "Bus: SPI" : `Bus: I2C, address ${addr ?? "(unknown — see TODO)"}`),
61
+ "",
62
+ `#ifndef ${guard}`,
63
+ `#define ${guard}`,
64
+ "",
65
+ "#include <stddef.h>",
66
+ "#include <stdint.h>",
67
+ "",
68
+ '#ifdef __cplusplus',
69
+ 'extern "C" {',
70
+ "#endif",
71
+ "",
72
+ ];
73
+ if (!spi) {
74
+ if (addr) {
75
+ header.push("/* I2C device address. */", `#define ${prefix}_I2C_ADDR ${addr}`, "");
76
+ }
77
+ else {
78
+ header.push("/* TODO(driverge): set the I2C device address (not found in the datasheet parse). */", `#define ${prefix}_I2C_ADDR 0x00`, "");
79
+ }
80
+ }
81
+ header.push(...registerConstants(prefix, registers));
82
+ const bits = bitFieldMacros(prefix, registers);
83
+ if (bits.length > 0)
84
+ header.push("", "/* Bit-field mask/shift accessors. */", ...bits);
85
+ header.push("", "/* Thin-HAL seam — implement these for your platform (see thin-hal). */", ...(spi
86
+ ? [
87
+ "void hal_spi_write(uint8_t *data, uint16_t len);",
88
+ "void hal_spi_read (uint8_t *data, uint16_t len);",
89
+ ]
90
+ : [
91
+ "void hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);",
92
+ "void hal_i2c_read (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);",
93
+ ]), "void hal_delay_ms (uint32_t ms);", "", "/* Driver handle. */", `typedef struct {`, spi ? " uint8_t _reserved; /* platform CS handled in hal_spi_* */" : " uint8_t i2c_addr;", `} ${type};`, "", "/* Public API. */", `int ${name}_init(${type} *dev);`, `int ${name}_read_register(${type} *dev, uint8_t reg, uint8_t *value);`, `int ${name}_write_register(${type} *dev, uint8_t reg, uint8_t value);`, "", '#ifdef __cplusplus', "}", "#endif", `#endif /* ${guard} */`, "");
94
+ const readBody = spi
95
+ ? [" hal_spi_write(&reg, 1);", " hal_spi_read(value, 1);"]
96
+ : [" hal_i2c_read(dev->i2c_addr, reg, value, 1);"];
97
+ const writeBody = spi
98
+ ? [" uint8_t frame[2];", " frame[0] = reg;", " frame[1] = value;", " hal_spi_write(frame, 2);"]
99
+ : [" hal_i2c_write(dev->i2c_addr, reg, &value, 1);"];
100
+ const source = [
101
+ `#include "${name}.h"`,
102
+ "",
103
+ `int ${name}_init(${type} *dev) {`,
104
+ " if (dev == NULL) {",
105
+ " return -1;",
106
+ " }",
107
+ ...(spi ? [] : [` dev->i2c_addr = ${prefix}_I2C_ADDR;`]),
108
+ " /* TODO(driverge): implement the power-on / reset init sequence — the",
109
+ " * correct register write order and values, plus any required startup",
110
+ ` * delay. See fill_in_brief.init_sequence_todo. Use ${name}_write_register()`,
111
+ " * and hal_delay_ms(). */",
112
+ " return 0;",
113
+ "}",
114
+ "",
115
+ `int ${name}_read_register(${type} *dev, uint8_t reg, uint8_t *value) {`,
116
+ " if (dev == NULL || value == NULL) {",
117
+ " return -1;",
118
+ " }",
119
+ ...readBody,
120
+ " return 0;",
121
+ "}",
122
+ "",
123
+ `int ${name}_write_register(${type} *dev, uint8_t reg, uint8_t value) {`,
124
+ " if (dev == NULL) {",
125
+ " return -1;",
126
+ " }",
127
+ ...writeBody,
128
+ " return 0;",
129
+ "}",
130
+ "",
131
+ ];
132
+ return {
133
+ files: makeFiles(name, header, source),
134
+ fill_in_brief: registerBrief(json),
135
+ };
136
+ }
137
+ function registerBrief(json) {
138
+ const part = json.metadata.part || "the device";
139
+ return {
140
+ init_sequence_todo: `Determine the correct power-on/reset init sequence for ${part}: which registers to write, in what order, with what values (mode/config), and any required startup delay. Read the datasheet init/operation section via the driverge://datasheet resource.`,
141
+ quirks_todo: `Capture vendor timing/behavior quirks for ${part} (e.g. mandatory power-on delay, soft-reset requirement, read-back constraints) and enforce them in ${slug(part)}_init using hal_delay_ms.`,
142
+ doc_todo: "Add Doxygen comments for all public functions and any device-specific compensation/conversion formulas.",
143
+ };
144
+ }
145
+ // ---------------------------------------------------------------------------
146
+ // command_set
147
+ // ---------------------------------------------------------------------------
148
+ function commandDriver(json, name, prefix) {
149
+ const commands = json.interface.commands;
150
+ const addr = json.protocol.addresses?.[0];
151
+ const crc = commands.find((c) => c.crc)?.crc;
152
+ const guard = `${prefix}_H`;
153
+ const type = `${name}_t`;
154
+ const header = [
155
+ AUTOGEN(json.metadata.part || name, json.metadata.manufacturer, `Bus: I2C, address ${addr ?? "(unknown — see TODO)"} · command-set device`),
156
+ "",
157
+ `#ifndef ${guard}`,
158
+ `#define ${guard}`,
159
+ "",
160
+ "#include <stddef.h>",
161
+ "#include <stdint.h>",
162
+ "",
163
+ '#ifdef __cplusplus',
164
+ 'extern "C" {',
165
+ "#endif",
166
+ "",
167
+ ];
168
+ if (addr) {
169
+ header.push("/* I2C device address. */", `#define ${prefix}_I2C_ADDR ${addr}`, "");
170
+ }
171
+ else {
172
+ header.push("/* TODO(driverge): set the I2C device address. */", `#define ${prefix}_I2C_ADDR 0x00`, "");
173
+ }
174
+ header.push("/* Command codes. */");
175
+ const seen = new Set();
176
+ for (const c of commands) {
177
+ const macroName = `${prefix}_CMD_${macro(c.name)}`;
178
+ if (seen.has(macroName))
179
+ continue;
180
+ seen.add(macroName);
181
+ header.push(`#define ${macroName} ${c.code.toUpperCase().replace("0X", "0x")}`);
182
+ }
183
+ if (crc) {
184
+ header.push("", `/* CRC-${crc.width} checksum parameters. */`, `#define ${prefix}_CRC_POLY ${crc.poly}`, `#define ${prefix}_CRC_INIT ${crc.init}`);
185
+ }
186
+ header.push("", "/* Thin-HAL seam — implement these for your platform (see thin-hal). */", "void hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);", "void hal_i2c_read (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len);", "void hal_delay_ms (uint32_t ms);", "", "/* Driver handle. */", "typedef struct {", " uint8_t i2c_addr;", `} ${type};`, "", "/* Public API. */", `int ${name}_init(${type} *dev);`, `int ${name}_send_command(${type} *dev, uint16_t command);`, `int ${name}_read_data(${type} *dev, uint8_t *buffer, uint16_t len);`, ...(crc ? [`uint8_t ${name}_crc8(const uint8_t *data, uint16_t len);`] : []), "", '#ifdef __cplusplus', "}", "#endif", `#endif /* ${guard} */`, "");
187
+ const source = [
188
+ `#include "${name}.h"`,
189
+ "",
190
+ `int ${name}_init(${type} *dev) {`,
191
+ " if (dev == NULL) {",
192
+ " return -1;",
193
+ " }",
194
+ ` dev->i2c_addr = ${prefix}_I2C_ADDR;`,
195
+ " /* TODO(driverge): power-up / soft-reset sequence and startup delay. See",
196
+ " * fill_in_brief.init_sequence_todo. */",
197
+ " return 0;",
198
+ "}",
199
+ "",
200
+ `int ${name}_send_command(${type} *dev, uint16_t command) {`,
201
+ " uint8_t msb;",
202
+ " uint8_t lsb;",
203
+ " if (dev == NULL) {",
204
+ " return -1;",
205
+ " }",
206
+ " msb = (uint8_t)(command >> 8);",
207
+ " lsb = (uint8_t)(command & 0xFF);",
208
+ " /* Command frame = [MSB][LSB]. hal_i2c_write emits the reg byte then the",
209
+ " * data bytes, so MSB-as-reg + LSB-as-data yields the correct 2-byte frame. */",
210
+ " hal_i2c_write(dev->i2c_addr, msb, &lsb, 1);",
211
+ " return 0;",
212
+ "}",
213
+ "",
214
+ `int ${name}_read_data(${type} *dev, uint8_t *buffer, uint16_t len) {`,
215
+ " if (dev == NULL || buffer == NULL) {",
216
+ " return -1;",
217
+ " }",
218
+ " /* TODO(driverge): read `len` response bytes (data words each followed by a",
219
+ " * CRC byte). Most command-set parts use a plain I2C read with no pointer",
220
+ " * byte — adapt the HAL call to your platform, then check each word with",
221
+ ` * ${name}_crc8(). See fill_in_brief.quirks_todo. */`,
222
+ " (void)dev;",
223
+ " (void)buffer;",
224
+ " (void)len;",
225
+ " return 0;",
226
+ "}",
227
+ "",
228
+ ];
229
+ if (crc) {
230
+ source.push(`uint8_t ${name}_crc8(const uint8_t *data, uint16_t len) {`, " (void)data;", " (void)len;", ` /* TODO(driverge): implement CRC-${crc.width} (poly ${prefix}_CRC_POLY, init`, ` * ${prefix}_CRC_INIT) per the datasheet checksum section. See`, " * fill_in_brief.crc_todo. */", " return 0;", "}", "");
231
+ }
232
+ const brief = {
233
+ init_sequence_todo: `Determine the power-up / soft-reset sequence and any startup delay for ${json.metadata.part || "the device"}.`,
234
+ quirks_todo: `Implement ${name}_read_data for this part's actual read framing (clock stretching vs. fixed delay, number of data+CRC words per command) using the driverge://datasheet resource.`,
235
+ doc_todo: "Add Doxygen comments for all public functions and document each command's response layout.",
236
+ };
237
+ if (crc) {
238
+ brief.crc_todo = `Implement ${name}_crc8: CRC-${crc.width}, polynomial ${crc.poly}, init ${crc.init}, per the datasheet checksum section.`;
239
+ }
240
+ return { files: makeFiles(name, header, source), fill_in_brief: brief };
241
+ }
242
+ // ---------------------------------------------------------------------------
243
+ function makeFiles(name, header, source) {
244
+ return [
245
+ { path: `${name}.h`, content: `${header.join("\n").replace(/\n{3,}/g, "\n\n")}` },
246
+ { path: `${name}.c`, content: `${source.join("\n").replace(/\n{3,}/g, "\n\n")}` },
247
+ ];
248
+ }
249
+ /** Render the portable thin-HAL driver skeleton for a validated datasheet. */
250
+ export function generatePortableDriver(json) {
251
+ const part = json.metadata.part;
252
+ const name = slug(part);
253
+ const prefix = macro(name);
254
+ return json.interface.kind === "command_set"
255
+ ? commandDriver(json, name, prefix)
256
+ : registerDriver(json, name, prefix);
257
+ }
258
+ //# sourceMappingURL=portable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portable.js","sourceRoot":"","sources":["../../src/codegen/portable.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { DatasheetJson } from "../schema/types.js";
2
+ import type { DriverArtifact } from "./types.js";
3
+ /** Portable core + a CubeHAL seam implementation for the same part. */
4
+ export declare function generateStm32Driver(json: DatasheetJson): DriverArtifact;
@@ -0,0 +1,64 @@
1
+ // STM32 (CubeHAL) target. Like ESP32, a native target pre-fills the thin-HAL
2
+ // seam rather than replacing it: the driver is the unchanged portable core plus a
3
+ // <part>_hal_stm32.c that implements hal_i2c_*/hal_delay_ms with STM32 CubeHAL
4
+ // (HAL_I2C_Mem_Read/Write, HAL_Delay). The user binds their I2C handle once via
5
+ // <part>_stm32_bind(); the board/clock bring-up stays in their CubeMX project.
6
+ import { prefixOf, slug } from "./ident.js";
7
+ import { generatePortableDriver } from "./portable.js";
8
+ function halImpl(name, prefix) {
9
+ const content = [
10
+ "/*",
11
+ ` * ${prefix} — STM32 CubeHAL seam implementation (generated by Driverge).`,
12
+ " *",
13
+ " * Drop this beside the portable core; it fills the thin-HAL seam with STM32",
14
+ " * CubeHAL. \"main.h\" is the CubeMX convention that pulls in your family's HAL",
15
+ " * and I2C_HandleTypeDef — if you don't use CubeMX, include your family header",
16
+ ` * (e.g. stm32f4xx_hal.h) instead. Call ${name}_stm32_bind(&hi2cX) once at`,
17
+ " * startup so the seam knows which I2C peripheral to use.",
18
+ " */",
19
+ `#include "${name}.h"`,
20
+ '#include "main.h"',
21
+ "",
22
+ `#ifndef ${prefix}_I2C_TIMEOUT_MS`,
23
+ `#define ${prefix}_I2C_TIMEOUT_MS 1000`,
24
+ "#endif",
25
+ "",
26
+ `static I2C_HandleTypeDef *s_${name}_hi2c;`,
27
+ "",
28
+ "/* Point the seam at the CubeMX-generated I2C handle (e.g. &hi2c1). */",
29
+ `void ${name}_stm32_bind(I2C_HandleTypeDef *hi2c) {`,
30
+ ` s_${name}_hi2c = hi2c;`,
31
+ "}",
32
+ "",
33
+ "void hal_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
34
+ " /* CubeHAL takes the 8-bit (left-shifted) device address. */",
35
+ ` HAL_I2C_Mem_Write(s_${name}_hi2c, (uint16_t)(addr << 1), reg,`,
36
+ ` I2C_MEMADD_SIZE_8BIT, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
37
+ "}",
38
+ "",
39
+ "void hal_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, uint16_t len) {",
40
+ ` HAL_I2C_Mem_Read(s_${name}_hi2c, (uint16_t)(addr << 1), reg,`,
41
+ ` I2C_MEMADD_SIZE_8BIT, data, len, ${prefix}_I2C_TIMEOUT_MS);`,
42
+ "}",
43
+ "",
44
+ "void hal_delay_ms(uint32_t ms) {",
45
+ " HAL_Delay(ms);",
46
+ "}",
47
+ "",
48
+ ].join("\n");
49
+ return { path: `${name}_hal_stm32.c`, content };
50
+ }
51
+ /** Portable core + a CubeHAL seam implementation for the same part. */
52
+ export function generateStm32Driver(json) {
53
+ const name = slug(json.metadata.part);
54
+ const prefix = prefixOf(json.metadata.part);
55
+ const base = generatePortableDriver(json);
56
+ return {
57
+ files: [...base.files, halImpl(name, prefix)],
58
+ fill_in_brief: {
59
+ ...base.fill_in_brief,
60
+ hal_setup_todo: `Configure the I2C peripheral in CubeMX (pins, clock, 7-bit addressing), then call ${name}_stm32_bind(&hi2cX) once at startup. Adjust ${prefix}_I2C_TIMEOUT_MS if needed.`,
61
+ },
62
+ };
63
+ }
64
+ //# sourceMappingURL=stm32.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stm32.js","sourceRoot":"","sources":["../../src/codegen/stm32.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,kFAAkF;AAClF,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAG/E,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAGvD,SAAS,OAAO,CAAC,IAAY,EAAE,MAAc;IAC3C,MAAM,OAAO,GAAG;QACd,IAAI;QACJ,MAAM,MAAM,+DAA+D;QAC3E,IAAI;QACJ,8EAA8E;QAC9E,iFAAiF;QACjF,gFAAgF;QAChF,2CAA2C,IAAI,6BAA6B;QAC5E,2DAA2D;QAC3D,KAAK;QACL,aAAa,IAAI,KAAK;QACtB,mBAAmB;QACnB,EAAE;QACF,WAAW,MAAM,iBAAiB;QAClC,WAAW,MAAM,sBAAsB;QACvC,QAAQ;QACR,EAAE;QACF,+BAA+B,IAAI,QAAQ;QAC3C,EAAE;QACF,wEAAwE;QACxE,QAAQ,IAAI,wCAAwC;QACpD,SAAS,IAAI,eAAe;QAC5B,GAAG;QACH,EAAE;QACF,8EAA8E;QAC9E,kEAAkE;QAClE,2BAA2B,IAAI,oCAAoC;QACnE,0DAA0D,MAAM,mBAAmB;QACnF,GAAG;QACH,EAAE;QACF,6EAA6E;QAC7E,0BAA0B,IAAI,oCAAoC;QAClE,yDAAyD,MAAM,mBAAmB;QAClF,GAAG;QACH,EAAE;QACF,kCAAkC;QAClC,oBAAoB;QACpB,GAAG;QACH,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,cAAc,EAAE,OAAO,EAAE,CAAC;AAClD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,mBAAmB,CAAC,IAAmB;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC;IAE1C,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7C,aAAa,EAAE;YACb,GAAG,IAAI,CAAC,aAAa;YACrB,cAAc,EAAE,qFAAqF,IAAI,+CAA+C,MAAM,4BAA4B;SAC3L;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ export type CodegenTarget = "portable" | "stm32" | "esp32" | "arduino";
2
+ export declare const CODEGEN_TARGETS: readonly CodegenTarget[];
3
+ export interface GeneratedFile {
4
+ path: string;
5
+ content: string;
6
+ }
7
+ /** Reasoning gaps the host AI must fill; keys mirror the wiki tool contract. */
8
+ export interface FillInBrief {
9
+ init_sequence_todo: string;
10
+ quirks_todo: string;
11
+ doc_todo: string;
12
+ /** Present only for command-set devices with a CRC. */
13
+ crc_todo?: string;
14
+ /** Present for native targets whose HAL seam needs board bring-up. */
15
+ hal_setup_todo?: string;
16
+ }
17
+ export interface DriverArtifact {
18
+ files: GeneratedFile[];
19
+ fill_in_brief: FillInBrief;
20
+ }
@@ -0,0 +1,11 @@
1
+ // Codegen contract types. A driver artifact is the deterministic skeleton the
2
+ // server renders (see wiki: hybrid-codegen-skeleton-plus-host-reasoning): concrete
3
+ // files plus a fill_in_brief telling the host AI which TODO(driverge) markers to
4
+ // complete. Targets beyond "portable" arrive in Sessions 7-8.
5
+ export const CODEGEN_TARGETS = [
6
+ "portable",
7
+ "stm32",
8
+ "esp32",
9
+ "arduino",
10
+ ];
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/codegen/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mFAAmF;AACnF,iFAAiF;AACjF,8DAA8D;AAI9D,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,UAAU;IACV,OAAO;IACP,OAAO;IACP,SAAS;CACV,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { DatasheetJson } from "../schema/types.js";
2
+ export interface CacheEntry {
3
+ ref: string;
4
+ pdfPath: string;
5
+ json: DatasheetJson;
6
+ }
7
+ /** Idempotent ref for a file: same path + mtime → same ref → cache hit. */
8
+ export declare function computeRef(pdfPath: string, mtimeMs: number): string;
9
+ export declare function putDatasheet(entry: CacheEntry): void;
10
+ export declare function getDatasheet(ref: string): CacheEntry | undefined;
11
+ /** Test seam — reset cache between cases. */
12
+ export declare function clearDatasheetCache(): void;
@@ -0,0 +1,24 @@
1
+ // Server-side datasheet cache. analyze_datasheet parses once and stores the full
2
+ // DatasheetJson under a content-stable `ref` (hash of pdf_path + mtime); later
3
+ // tools hydrate by ref so the large JSON never round-trips through the model.
4
+ // See wiki: parsed-json-handoff-via-handle.
5
+ import { createHash } from "node:crypto";
6
+ const store = new Map();
7
+ /** Idempotent ref for a file: same path + mtime → same ref → cache hit. */
8
+ export function computeRef(pdfPath, mtimeMs) {
9
+ const hash = createHash("sha1")
10
+ .update(`${pdfPath}:${Math.round(mtimeMs)}`)
11
+ .digest("hex");
12
+ return `ds_${hash.slice(0, 12)}`;
13
+ }
14
+ export function putDatasheet(entry) {
15
+ store.set(entry.ref, entry);
16
+ }
17
+ export function getDatasheet(ref) {
18
+ return store.get(ref);
19
+ }
20
+ /** Test seam — reset cache between cases. */
21
+ export function clearDatasheetCache() {
22
+ store.clear();
23
+ }
24
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/mcp/cache.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,+EAA+E;AAC/E,8EAA8E;AAC9E,4CAA4C;AAE5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AASzC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE5C,2EAA2E;AAC3E,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,OAAe;IACzD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC;SAC5B,MAAM,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;SAC3C,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAiB;IAC5C,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,6CAA6C;AAC7C,MAAM,UAAU,mBAAmB;IACjC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerDrivergeTools(server: McpServer): void;
3
+ export declare function registerDrivergeResources(server: McpServer): void;
4
+ export declare function registerDrivergePrompts(server: McpServer): void;
5
+ /** Register the entire Driverge surface on a server. */
6
+ export declare function registerDriverge(server: McpServer): void;
@@ -0,0 +1,195 @@
1
+ // Registers the full Driverge MCP surface — tools, resources, prompts — on a
2
+ // server instance. Kept out of server.ts so the wiring is unit-testable over an
3
+ // in-memory transport. Contract: wiki mcp-tool-usage-flow.
4
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { z } from "zod";
9
+ import { UnsupportedTargetError, generateDriver, lintDriver, } from "../codegen/index.js";
10
+ import { analyzePdfFile } from "../pdf/analyze.js";
11
+ import { assembleDatasheet } from "../schema/assemble.js";
12
+ import { validateDatasheet } from "../schema/validate.js";
13
+ import { computeRef, getDatasheet, putDatasheet } from "./cache.js";
14
+ import { buildSummary } from "./summary.js";
15
+ const TARGET = z.enum(["portable", "stm32", "esp32", "arduino"]);
16
+ const FILES = z.array(z.object({ path: z.string(), content: z.string() }));
17
+ const text = (value, isError = false) => ({
18
+ content: [
19
+ {
20
+ type: "text",
21
+ text: typeof value === "string" ? value : JSON.stringify(value, null, 2),
22
+ },
23
+ ],
24
+ ...(isError ? { isError: true } : {}),
25
+ });
26
+ // The frozen JSON-Schema, shipped alongside dist/ (see package.json "files").
27
+ function loadSchemaText() {
28
+ try {
29
+ const url = new URL("../../schemas/datasheet.schema.json", import.meta.url);
30
+ return readFileSync(fileURLToPath(url), "utf8");
31
+ }
32
+ catch {
33
+ return "{}";
34
+ }
35
+ }
36
+ export function registerDrivergeTools(server) {
37
+ server.registerTool("analyze_datasheet", {
38
+ title: "Analyze datasheet",
39
+ description: "Parse an IC datasheet PDF (L1–L5), validate it, and cache the structured JSON under a stable `ref`. Returns a compact summary; read the full JSON via the driverge://datasheet/<ref> resource.",
40
+ inputSchema: {
41
+ pdf_path: z.string().describe("absolute path to the datasheet PDF"),
42
+ manufacturer_hint: z.string().optional(),
43
+ interface_kind_hint: z.enum(["register_map", "command_set"]).optional(),
44
+ },
45
+ }, async ({ pdf_path }) => {
46
+ if (!existsSync(pdf_path)) {
47
+ return text(`file not found: ${pdf_path}`, true);
48
+ }
49
+ const ref = computeRef(pdf_path, statSync(pdf_path).mtimeMs);
50
+ const cached = getDatasheet(ref);
51
+ if (cached)
52
+ return text(buildSummary(cached));
53
+ let analysis;
54
+ try {
55
+ analysis = await analyzePdfFile(pdf_path);
56
+ }
57
+ catch (err) {
58
+ return text(`failed to parse PDF: ${err.message}`, true);
59
+ }
60
+ if (analysis.type === "scanned") {
61
+ return text("PDF appears to be scanned (no extractable text). OCR is not supported in v0.1.0.", true);
62
+ }
63
+ const json = assembleDatasheet(analysis);
64
+ putDatasheet({ ref, pdfPath: pdf_path, json });
65
+ return text(buildSummary({ ref, pdfPath: pdf_path, json }));
66
+ });
67
+ server.registerTool("generate_driver", {
68
+ title: "Generate driver",
69
+ description: "Render a deterministic thin-HAL driver skeleton (with TODO(driverge) markers + a fill_in_brief) from a previously analyzed datasheet `ref`. Rejects refs that failed validation.",
70
+ inputSchema: {
71
+ ref: z.string(),
72
+ target: TARGET.default("portable"),
73
+ out_dir: z.string().optional(),
74
+ },
75
+ }, async ({ ref, target, out_dir }) => {
76
+ const entry = getDatasheet(ref);
77
+ if (!entry)
78
+ return text(`unknown ref "${ref}" — run analyze_datasheet first`, true);
79
+ if (!entry.json.validation.valid) {
80
+ return text({
81
+ error: "datasheet validation failed — codegen refused",
82
+ errors: entry.json.validation.errors,
83
+ }, true);
84
+ }
85
+ let artifact;
86
+ try {
87
+ artifact = generateDriver(entry.json, target);
88
+ }
89
+ catch (err) {
90
+ if (err instanceof UnsupportedTargetError)
91
+ return text(err.message, true);
92
+ throw err;
93
+ }
94
+ if (out_dir) {
95
+ mkdirSync(out_dir, { recursive: true });
96
+ for (const f of artifact.files)
97
+ writeFileSync(join(out_dir, f.path), f.content);
98
+ }
99
+ return text(artifact);
100
+ });
101
+ server.registerTool("validate_driver", {
102
+ title: "Validate driver",
103
+ description: "Static-lint a completed driver against its source datasheet `ref`: thin-HAL purity, no leftover TODO(driverge), register/command references exist, bit-field masks match the JSON.",
104
+ inputSchema: { ref: z.string(), target: TARGET.optional(), files: FILES },
105
+ }, async ({ ref, files }) => {
106
+ const entry = getDatasheet(ref);
107
+ if (!entry)
108
+ return text(`unknown ref "${ref}" — run analyze_datasheet first`, true);
109
+ const result = lintDriver(files, entry.json);
110
+ return text({
111
+ passed: result.valid,
112
+ warnings: result.warnings,
113
+ errors: result.errors,
114
+ });
115
+ });
116
+ server.registerTool("validate_datasheet", {
117
+ title: "Validate datasheet JSON",
118
+ description: "Re-run the L5 validator over a cached `ref` or a supplied datasheet JSON. Thin wrapper over the same rules analyze_datasheet applies internally.",
119
+ inputSchema: {
120
+ ref: z.string().optional(),
121
+ json: z.record(z.string(), z.unknown()).optional(),
122
+ },
123
+ }, async ({ ref, json }) => {
124
+ if (ref) {
125
+ const entry = getDatasheet(ref);
126
+ if (!entry)
127
+ return text(`unknown ref "${ref}"`, true);
128
+ return text(validateDatasheet(entry.json));
129
+ }
130
+ if (json)
131
+ return text(validateDatasheet(json));
132
+ return text("provide either `ref` or `json`", true);
133
+ });
134
+ }
135
+ export function registerDrivergeResources(server) {
136
+ const schemaText = loadSchemaText();
137
+ server.registerResource("datasheet-schema", "driverge://schema", {
138
+ title: "Datasheet JSON schema",
139
+ description: "The frozen draft-07 JSON-Schema contract for parsed datasheets.",
140
+ mimeType: "application/json",
141
+ }, async (uri) => ({
142
+ contents: [{ uri: uri.href, mimeType: "application/json", text: schemaText }],
143
+ }));
144
+ server.registerResource("datasheet-json", new ResourceTemplate("driverge://datasheet/{ref}", { list: undefined }), {
145
+ title: "Parsed datasheet JSON",
146
+ description: "Full structured JSON for an analyzed datasheet, by ref.",
147
+ mimeType: "application/json",
148
+ }, async (uri, variables) => {
149
+ const ref = String(variables.ref);
150
+ const entry = getDatasheet(ref);
151
+ if (!entry)
152
+ throw new Error(`unknown datasheet ref "${ref}"`);
153
+ return {
154
+ contents: [
155
+ {
156
+ uri: uri.href,
157
+ mimeType: "application/json",
158
+ text: JSON.stringify(entry.json, null, 2),
159
+ },
160
+ ],
161
+ };
162
+ });
163
+ }
164
+ export function registerDrivergePrompts(server) {
165
+ server.registerPrompt("generate-driver", {
166
+ title: "Generate a driver",
167
+ description: "Guided flow: render the skeleton for a ref/target, complete the TODO(driverge) markers using the datasheet resource, then validate.",
168
+ argsSchema: { ref: z.string(), target: z.string().optional() },
169
+ }, ({ ref, target }) => ({
170
+ messages: [
171
+ {
172
+ role: "user",
173
+ content: {
174
+ type: "text",
175
+ text: [
176
+ `Generate an embedded driver for datasheet ref "${ref}" (target: ${target ?? "portable"}).`,
177
+ "",
178
+ `1. Call generate_driver({ ref: "${ref}", target: "${target ?? "portable"}" }).`,
179
+ `2. Read driverge://datasheet/${ref} for full register/command detail.`,
180
+ "3. Complete every TODO(driverge) marker using the fill_in_brief and the datasheet JSON — init sequence, vendor quirks, docs (and CRC for command-set parts).",
181
+ "4. Keep all bus access on the hal_* seam; never call a vendor peripheral API directly.",
182
+ `5. Call validate_driver({ ref: "${ref}", files: [...] }) and fix any reported errors, then return the final files.`,
183
+ ].join("\n"),
184
+ },
185
+ },
186
+ ],
187
+ }));
188
+ }
189
+ /** Register the entire Driverge surface on a server. */
190
+ export function registerDriverge(server) {
191
+ registerDrivergeTools(server);
192
+ registerDrivergeResources(server);
193
+ registerDrivergePrompts(server);
194
+ }
195
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/mcp/register.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,gFAAgF;AAChF,2DAA2D;AAE3D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAEL,gBAAgB,GACjB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,UAAU,GACX,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE1D,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;AACjE,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;AAM3E,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,OAAO,GAAG,KAAK,EAAc,EAAE,CAAC,CAAC;IAC7D,OAAO,EAAE;QACP;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;SACzE;KACF;IACD,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CACtC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,qCAAqC,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,OAAO,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,YAAY,CACjB,mBAAmB,EACnB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,gMAAgM;QAClM,WAAW,EAAE;YACX,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oCAAoC,CAAC;YACnE,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACxC,mBAAmB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE;SACxE;KACF,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,mBAAmB,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM;YAAE,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;QAE9C,IAAI,QAAQ,CAAC;QACb,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,wBAAyB,GAAa,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC;QACtE,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,IAAI,CACT,kFAAkF,EAClF,IAAI,CACL,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACzC,YAAY,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9D,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,kLAAkL;QACpL,WAAW,EAAE;YACX,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;YACf,MAAM,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;YAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC/B;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;QACjC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,gBAAgB,GAAG,iCAAiC,EAAE,IAAI,CAAC,CAAC;QACpF,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACjC,OAAO,IAAI,CACT;gBACE,KAAK,EAAE,+CAA+C;gBACtD,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM;aACrC,EACD,IAAI,CACL,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,CAAC;QACb,IAAI,CAAC;YACH,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,MAAuB,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,sBAAsB;gBAAE,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC1E,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YACxC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK;gBAAE,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,oLAAoL;QACtL,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE;KAC1E,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE;QACvB,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC,gBAAgB,GAAG,iCAAiC,EAAE,IAAI,CAAC,CAAC;QACpF,MAAM,MAAM,GAAG,UAAU,CAAC,KAAwB,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;YACV,MAAM,EAAE,MAAM,CAAC,KAAK;YACpB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,MAAM,CAAC,MAAM;SACtB,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,kJAAkJ;QACpJ,WAAW,EAAE;YACX,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC1B,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;SACnD;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,IAAI,GAAG,EAAE,CAAC;YACR,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC,gBAAgB,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC,IAAgC,CAAC,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,MAAiB;IACzD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IAEpC,MAAM,CAAC,gBAAgB,CACrB,kBAAkB,EAClB,mBAAmB,EACnB;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,iEAAiE;QAC9E,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;KAC9E,CAAC,CACH,CAAC;IAEF,MAAM,CAAC,gBAAgB,CACrB,gBAAgB,EAChB,IAAI,gBAAgB,CAAC,4BAA4B,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EACvE;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,yDAAyD;QACtE,QAAQ,EAAE,kBAAkB;KAC7B,EACD,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE;QACvB,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,GAAG,GAAG,CAAC,CAAC;QAC9D,OAAO;YACL,QAAQ,EAAE;gBACR;oBACE,GAAG,EAAE,GAAG,CAAC,IAAI;oBACb,QAAQ,EAAE,kBAAkB;oBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC1C;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAiB;IACvD,MAAM,CAAC,cAAc,CACnB,iBAAiB,EACjB;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,qIAAqI;QACvI,UAAU,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;KAC/D,EACD,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACpB,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;wBACJ,kDAAkD,GAAG,cAAc,MAAM,IAAI,UAAU,IAAI;wBAC3F,EAAE;wBACF,mCAAmC,GAAG,eAAe,MAAM,IAAI,UAAU,OAAO;wBAChF,gCAAgC,GAAG,oCAAoC;wBACvE,8JAA8J;wBAC9J,wFAAwF;wBACxF,mCAAmC,GAAG,8EAA8E;qBACrH,CAAC,IAAI,CAAC,IAAI,CAAC;iBACb;aACF;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAClC,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC"}