copperhead 0.8.1 → 0.10.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 (105) hide show
  1. package/NOTICE +1 -1
  2. package/README.md +13 -5
  3. package/dist/agent/filetools.js +24 -1
  4. package/dist/agent/filetools.js.map +1 -1
  5. package/dist/agent/ledger.js +24 -0
  6. package/dist/agent/ledger.js.map +1 -1
  7. package/dist/agent/loop.js +67 -62
  8. package/dist/agent/loop.js.map +1 -1
  9. package/dist/agent/prompts.js +4 -3
  10. package/dist/agent/prompts.js.map +1 -1
  11. package/dist/agent/providers/openai.js +28 -6
  12. package/dist/agent/providers/openai.js.map +1 -1
  13. package/dist/agent/providers/tool-protocol.js +21 -0
  14. package/dist/agent/providers/tool-protocol.js.map +1 -1
  15. package/dist/agent/recovery.js +95 -1
  16. package/dist/agent/recovery.js.map +1 -1
  17. package/dist/agent/response-cache.js +18 -2
  18. package/dist/agent/response-cache.js.map +1 -1
  19. package/dist/agent/tools.js +185 -1
  20. package/dist/agent/tools.js.map +1 -1
  21. package/dist/agent/transcript.js +2 -0
  22. package/dist/agent/transcript.js.map +1 -1
  23. package/dist/cli.js +77 -2
  24. package/dist/cli.js.map +1 -1
  25. package/dist/commands/check.js +33 -1
  26. package/dist/commands/check.js.map +1 -1
  27. package/dist/commands/create.js +282 -26
  28. package/dist/commands/create.js.map +1 -1
  29. package/dist/commands/doctor.js +211 -11
  30. package/dist/commands/doctor.js.map +1 -1
  31. package/dist/config.js +61 -4
  32. package/dist/config.js.map +1 -1
  33. package/dist/kicad/bootstrap.js +24 -3
  34. package/dist/kicad/bootstrap.js.map +1 -1
  35. package/dist/kicad/cli.js +7 -26
  36. package/dist/kicad/cli.js.map +1 -1
  37. package/dist/kicad/dossier.js +207 -0
  38. package/dist/kicad/dossier.js.map +1 -0
  39. package/dist/kicad/draft/draft.js +132 -0
  40. package/dist/kicad/draft/draft.js.map +1 -0
  41. package/dist/kicad/draft/engine.js +2389 -0
  42. package/dist/kicad/draft/engine.js.map +1 -0
  43. package/dist/kicad/draft/ir.js +368 -0
  44. package/dist/kicad/draft/ir.js.map +1 -0
  45. package/dist/kicad/draft/symsource.js +490 -0
  46. package/dist/kicad/draft/symsource.js.map +1 -0
  47. package/dist/kicad/emit.js +181 -0
  48. package/dist/kicad/emit.js.map +1 -0
  49. package/dist/kicad/fab.js +13 -0
  50. package/dist/kicad/fab.js.map +1 -1
  51. package/dist/kicad/legibility.js +561 -0
  52. package/dist/kicad/legibility.js.map +1 -0
  53. package/dist/kicad/score.js +261 -0
  54. package/dist/kicad/score.js.map +1 -0
  55. package/dist/kicad/sexp.js +262 -10
  56. package/dist/kicad/sexp.js.map +1 -1
  57. package/dist/kicad/symlib.js +346 -16
  58. package/dist/kicad/symlib.js.map +1 -1
  59. package/dist/memory/bom-table.js +108 -34
  60. package/dist/memory/bom-table.js.map +1 -1
  61. package/dist/memory/scaffold.js +6 -0
  62. package/dist/memory/scaffold.js.map +1 -1
  63. package/dist/openspec/cli.js +2 -1
  64. package/dist/openspec/cli.js.map +1 -1
  65. package/dist/util/preflight.js +17 -0
  66. package/dist/util/preflight.js.map +1 -1
  67. package/dist/util/redact.js +12 -2
  68. package/dist/util/redact.js.map +1 -1
  69. package/package.json +9 -7
  70. package/src/agent/filetools.ts +26 -1
  71. package/src/agent/ledger.ts +24 -0
  72. package/src/agent/loop.ts +88 -65
  73. package/src/agent/prompts.ts +4 -3
  74. package/src/agent/providers/openai.ts +38 -4
  75. package/src/agent/providers/tool-protocol.ts +22 -0
  76. package/src/agent/recovery.ts +94 -1
  77. package/src/agent/response-cache.ts +17 -1
  78. package/src/agent/tools.ts +189 -1
  79. package/src/agent/transcript.ts +6 -0
  80. package/src/cli.ts +73 -2
  81. package/src/commands/check.ts +51 -1
  82. package/src/commands/create.ts +278 -22
  83. package/src/commands/doctor.ts +219 -12
  84. package/src/config.ts +107 -2
  85. package/src/kicad/bootstrap.ts +24 -3
  86. package/src/kicad/cli.ts +6 -19
  87. package/src/kicad/dossier.ts +217 -0
  88. package/src/kicad/draft/draft.ts +171 -0
  89. package/src/kicad/draft/engine.ts +2466 -0
  90. package/src/kicad/draft/ir.ts +416 -0
  91. package/src/kicad/draft/symsource.ts +535 -0
  92. package/src/kicad/emit.ts +236 -0
  93. package/src/kicad/fab.ts +15 -0
  94. package/src/kicad/legibility.ts +646 -0
  95. package/src/kicad/score.ts +323 -0
  96. package/src/kicad/sexp.ts +339 -10
  97. package/src/kicad/symlib.ts +364 -18
  98. package/src/memory/bom-table.ts +119 -31
  99. package/src/memory/scaffold.ts +6 -0
  100. package/src/openspec/cli.ts +3 -2
  101. package/src/util/preflight.ts +18 -0
  102. package/src/util/redact.ts +12 -2
  103. package/dist/memory/synap.js +0 -152
  104. package/dist/memory/synap.js.map +0 -1
  105. package/src/memory/synap.ts +0 -217
@@ -1,10 +1,12 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
+ import { execa } from 'execa';
3
4
  import { existsSync } from 'node:fs';
4
5
  import path from 'node:path';
5
- import { DEFAULTS, loadConfig, resolveModel } from '../config.js';
6
+ import { DEFAULTS, DEFAULT_API_KEY_ENV, isLocalEndpoint, loadConfig, resolveCompatSettings, resolveModel, } from '../config.js';
6
7
  import { kicadCliVersion } from '../kicad/cli.js';
7
8
  import { redactSecrets } from '../util/redact.js';
9
+ import { isNotFoundError } from '../util/preflight.js';
8
10
  const execFileP = promisify(execFile);
9
11
  function defaultDeps() {
10
12
  return {
@@ -13,6 +15,15 @@ function defaultDeps() {
13
15
  // `git --version` prints "git version 2.34.1"; keep only the number, the
14
16
  // report already labels the row "git".
15
17
  gitVersion: async () => (await execFileP('git', ['--version'])).stdout.trim().replace(/^git version\s+/, ''),
18
+ /**
19
+ * Probes `openspec --version` via execa, the same probe shape as the real
20
+ * call site (src/openspec/cli.ts): execa resolves Windows .cmd/.bat shims
21
+ * via cross-spawn without a shell, so a missing binary still yields ENOENT
22
+ * (what isNotFoundError expects) on every platform, instead of a
23
+ * shell-reported exit 127/"not found".
24
+ * @returns the trimmed stdout of `openspec --version` (e.g. "1.8.0").
25
+ */
26
+ openspecVersion: async () => (await execa('openspec', ['--version'])).stdout.trim(),
16
27
  env: process.env,
17
28
  };
18
29
  }
@@ -55,6 +66,41 @@ async function gitCheck(probe) {
55
66
  };
56
67
  }
57
68
  }
69
+ /**
70
+ * Report whether the `openspec` CLI is reachable, needed for `validate_change`
71
+ * and the `create` pipeline. Fails soft like `kicadCheck`/`gitCheck`: a
72
+ * missing or erroring probe is returned as a `fail` check, never thrown.
73
+ * @param probe resolves the openspec version string, or rejects if the CLI
74
+ * can't be run (e.g. not found on PATH).
75
+ * @returns an `ok` check with the version on success; a `fail` check with an
76
+ * install hint when `probe` rejects with a not-found error (per
77
+ * `isNotFoundError`), or a `fail` check with the flattened error message
78
+ * otherwise.
79
+ */
80
+ async function openspecCheck(probe) {
81
+ try {
82
+ return { name: 'openspec', status: 'ok', detail: await probe() };
83
+ }
84
+ catch (err) {
85
+ if (isNotFoundError(err)) {
86
+ return {
87
+ name: 'openspec',
88
+ status: 'fail',
89
+ detail: 'not found on PATH',
90
+ hint: 'npm i -g @fission-ai/openspec; validate_change and the create pipeline need it.',
91
+ };
92
+ }
93
+ // Collapse embedded newlines/whitespace from a raw shell/subprocess error:
94
+ // formatDoctor's column layout assumes a single-line detail, and wrapWords
95
+ // splits on plain spaces only.
96
+ const rawMessage = err.message || String(err);
97
+ return {
98
+ name: 'openspec',
99
+ status: 'fail',
100
+ detail: rawMessage.replace(/\s+/g, ' ').trim(),
101
+ };
102
+ }
103
+ }
58
104
  /**
59
105
  * Map a resolved model to the credential its provider needs, mirroring
60
106
  * makeProvider's prefix routing (agent/loop.ts). Presence-only: it checks that a
@@ -62,7 +108,140 @@ async function gitCheck(probe) {
62
108
  * Saved-login providers (codex, claude-code) need no key and can't be verified
63
109
  * offline, so they report `info` (which does not block `ok`).
64
110
  */
65
- export function checkCredential(model, env) {
111
+ export function checkCredential(model, env, compat) {
112
+ // OpenAI-compatible endpoint: the credential lives in a variable the user
113
+ // names, and the endpoint is worth showing because it is the whole point of
114
+ // the route. A loopback endpoint (Ollama) needs no key at all (design D4).
115
+ if (model === 'compat' || model.startsWith('compat:')) {
116
+ const shownModel = redactSecrets(model);
117
+ const compatModel = model.startsWith('compat:') ? model.slice('compat:'.length) : undefined;
118
+ // Mirrors makeProvider (agent/loop.ts): bare `compat` has no valid default
119
+ // model, so it must fail here too, or doctor reports "ready" for a run
120
+ // that would fail on its very first turn.
121
+ if (!compatModel) {
122
+ return {
123
+ name: 'provider',
124
+ status: 'fail',
125
+ detail: `${shownModel} -> compat: ${model === 'compat:' ? 'empty' : 'missing'} model id`,
126
+ hint: 'use "compat:<model-id>"; a compatible endpoint has no default model to assume.',
127
+ };
128
+ }
129
+ const settings = compat ?? { apiKeyEnv: DEFAULT_API_KEY_ENV };
130
+ // Display only: some endpoints embed a credential in the URL itself (a
131
+ // query param, userinfo) — Gemini's compat endpoint does this with
132
+ // ?key=.... redactSecrets covers known key shapes, but a key embedded in
133
+ // a URL query isn't reliably one of them, so drop the query and userinfo
134
+ // entirely rather than pattern-matching, regardless of shape.
135
+ // isLocalEndpoint() below still runs against the raw settings.baseURL,
136
+ // never this.
137
+ const where = (() => {
138
+ if (!settings.baseURL)
139
+ return '(no baseURL configured)';
140
+ try {
141
+ const u = new URL(settings.baseURL);
142
+ return `${u.origin}${u.pathname}`;
143
+ }
144
+ catch {
145
+ return redactSecrets(settings.baseURL);
146
+ }
147
+ })();
148
+ if (!settings.baseURL) {
149
+ return {
150
+ name: 'provider',
151
+ status: 'fail',
152
+ detail: `${shownModel} -> compat: no endpoint configured`,
153
+ hint: 'set COPPERHEAD_BASE_URL, or "baseURL" in .copperhead/config.json.',
154
+ };
155
+ }
156
+ if (isLocalEndpoint(settings.baseURL)) {
157
+ return {
158
+ name: 'provider',
159
+ status: 'ok',
160
+ detail: `${shownModel} -> compat: ${where} (local endpoint, no key required)`,
161
+ };
162
+ }
163
+ return env[settings.apiKeyEnv]
164
+ ? { name: 'provider', status: 'ok', detail: `${shownModel} -> compat: ${where} (${settings.apiKeyEnv} set)` }
165
+ : {
166
+ name: 'provider',
167
+ status: 'fail',
168
+ detail: `${shownModel} -> compat: ${where} (${settings.apiKeyEnv} not set)`,
169
+ hint: `export ${settings.apiKeyEnv}=... for that endpoint.`,
170
+ };
171
+ }
172
+ return checkKeyedCredential(model, env);
173
+ }
174
+ /**
175
+ * Hosts whose free tier may train on submitted prompts. Keyed on hostname
176
+ * rather than model name: hostnames are stable, model and tier names rot in
177
+ * months, so the tier detail belongs in docs (design D5). Never `fail` — a
178
+ * contributor deliberately using a free tier on a non-proprietary board is not
179
+ * misconfigured, so this must not make `doctor` exit non-zero.
180
+ */
181
+ const TRAINING_RISK_HOSTS = {
182
+ 'generativelanguage.googleapis.com': "Gemini's free tier may train on submitted prompts",
183
+ 'openrouter.ai': 'OpenRouter `:free` models may route to providers that train on prompts',
184
+ };
185
+ /**
186
+ * True loopback only — unlike `isLocalEndpoint` (config.ts), this excludes
187
+ * `.local`/mDNS hostnames. `isLocalEndpoint`'s broader definition is correct
188
+ * for "does this need a credential" (many LAN-hosted servers skip auth), but
189
+ * wrong for the privacy bypass below: a request to `nas.local` genuinely
190
+ * leaves the machine onto the LAN to a different physical device, so "nothing
191
+ * leaves the machine" does not hold the way it does for real loopback.
192
+ */
193
+ function isLoopbackHost(baseURL) {
194
+ try {
195
+ const h = new URL(baseURL).hostname.toLowerCase();
196
+ return h === 'localhost' || h === '127.0.0.1' || h === '::1' || h === '[::1]';
197
+ }
198
+ catch {
199
+ return false;
200
+ }
201
+ }
202
+ /** A `warn` line when the configured endpoint's host is a documented training risk. */
203
+ export function checkPromptPrivacy(model, compat) {
204
+ if (model !== 'compat' && !model.startsWith('compat:'))
205
+ return null;
206
+ if (!compat?.baseURL)
207
+ return null;
208
+ // A true loopback endpoint has no third party to have a policy about:
209
+ // nothing leaves the machine, so "check the provider's terms" would be
210
+ // nonsensical. A LAN host (including .local) does not get this bypass.
211
+ if (isLoopbackHost(compat.baseURL))
212
+ return null;
213
+ let host;
214
+ try {
215
+ host = new URL(compat.baseURL).hostname.toLowerCase();
216
+ }
217
+ catch {
218
+ return null;
219
+ }
220
+ const noPolicyOnRecord = () => ({
221
+ name: 'privacy',
222
+ status: 'info',
223
+ detail: `${host}: no known training-on-prompts policy on record (copperhead cannot verify this; check the provider's terms)`,
224
+ });
225
+ const risk = Object.entries(TRAINING_RISK_HOSTS).find(([h]) => host === h || host.endsWith(`.${h}`));
226
+ if (!risk)
227
+ return noPolicyOnRecord();
228
+ // OpenRouter's documented risk is specific to its `:free`-suffixed models
229
+ // (their own wording), not the host as a whole. Warning on a fully paid
230
+ // OpenRouter model would be a false positive that undermines trust in the
231
+ // other, host-wide warnings (Gemini's applies to its whole free tier).
232
+ if (risk[0] === 'openrouter.ai') {
233
+ const compatModel = model.startsWith('compat:') ? model.slice('compat:'.length) : '';
234
+ if (!compatModel.endsWith(':free'))
235
+ return noPolicyOnRecord();
236
+ }
237
+ return {
238
+ name: 'privacy',
239
+ status: 'warn',
240
+ detail: `${host}: ${risk[1]}`,
241
+ hint: 'PCB designs are often proprietary. Use a paid tier or a local endpoint for confidential work.',
242
+ };
243
+ }
244
+ function checkKeyedCredential(model, env) {
66
245
  // A pasted API key can end up as the model value (--model sk-..., a stray
67
246
  // COPPERHEAD_MODEL); redact it before it reaches the report, same policy as
68
247
  // transcripts (AC-4.1). Routing below still uses the raw value.
@@ -112,17 +291,21 @@ export function checkCredential(model, env) {
112
291
  function providerCheck(flag, config, env) {
113
292
  try {
114
293
  const { model } = resolveModel(flag, config, env);
115
- return checkCredential(model, env);
294
+ return checkCredential(model, env, resolveCompatSettings(config, env));
116
295
  }
117
296
  catch (err) {
118
- // resolveModel throws only when nothing selects a model at all. Its message
119
- // starts with "no model configured: " already this check's detail line —
120
- // so keep only the remedy part for the hint.
297
+ // resolveModel throws for two distinct reasons: nothing selects a model at
298
+ // all ("no model configured: ..."), or two-plus credentials are present
299
+ // with nothing to break the tie ("ambiguous: ..."). Strip whichever prefix
300
+ // matched for the hint, and reflect which case it was in the detail so an
301
+ // ambiguous setup does not misreport as "nothing configured".
302
+ const message = err.message;
303
+ const ambiguous = message.startsWith('ambiguous:');
121
304
  return {
122
305
  name: 'provider',
123
306
  status: 'fail',
124
- detail: 'no model configured',
125
- hint: err.message.replace(/^no model configured:\s*/, ''),
307
+ detail: ambiguous ? 'ambiguous: multiple credentials, no model selected' : 'no model configured',
308
+ hint: message.replace(/^(no model configured|ambiguous):\s*/, ''),
126
309
  };
127
310
  }
128
311
  }
@@ -175,16 +358,33 @@ export async function runDoctor(opts) {
175
358
  hint: 'check that it is a regular file (not a directory) and that you have permission to read it.',
176
359
  };
177
360
  }
361
+ // Resolving the model can fail (nothing configured); providerCheck reports
362
+ // that, and the compat-only checks simply do not apply in that case.
363
+ const compat = resolveCompatSettings(config, deps.env);
364
+ let resolvedModel = null;
365
+ try {
366
+ resolvedModel = resolveModel(opts.model, config, deps.env).model;
367
+ }
368
+ catch {
369
+ resolvedModel = null;
370
+ }
178
371
  const checks = [
179
372
  nodeCheck(deps.nodeVersion),
180
373
  await kicadCheck(deps.kicadVersion),
181
374
  await gitCheck(deps.gitVersion),
375
+ await openspecCheck(deps.openspecVersion),
182
376
  providerCheck(opts.model, config, deps.env),
183
- configError ?? projectCheck(config, opts.repoRoot),
184
377
  ];
378
+ if (resolvedModel) {
379
+ const privacy = checkPromptPrivacy(resolvedModel, compat);
380
+ if (privacy)
381
+ checks.push(privacy);
382
+ }
383
+ checks.push(configError ?? projectCheck(config, opts.repoRoot));
384
+ // `warn` and `info` never block: only a hard failure means "not ready".
185
385
  return { ok: checks.every((c) => c.status !== 'fail'), checks };
186
386
  }
187
- const TAG = { ok: '[ok]', fail: '[FAIL]', info: '[info]' };
387
+ const TAG = { ok: '[ok]', fail: '[FAIL]', warn: '[warn]', info: '[info]' };
188
388
  const TAG_COL = 2; // leading indent
189
389
  const NAME_COL = TAG_COL + 7; // widest tag "[FAIL]" + one space
190
390
  const DETAIL_COL = NAME_COL + 10; // widest name "kicad-cli" + one space
@@ -193,7 +393,7 @@ const DETAIL_COL = NAME_COL + 10; // widest name "kicad-cli" + one space
193
393
  // tests see plain text. Colored text is padded before painting — escape codes
194
394
  // have zero display width but nonzero string length, so painting first would
195
395
  // break the column math.
196
- const ANSI = { ok: '32', fail: '31', info: '36' };
396
+ const ANSI = { ok: '32', fail: '31', warn: '33', info: '36' };
197
397
  const DIM = '2';
198
398
  function paint(text, code, on) {
199
399
  return on ? `\u001b[${code}m${text}\u001b[0m` : text;
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,QAAQ,EACR,mBAAmB,EACnB,eAAe,EACf,UAAU,EACV,qBAAqB,EACrB,YAAY,GAGb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAiCtC,SAAS,WAAW;IAClB,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,OAAO;QAC5B,YAAY,EAAE,eAAe;QAC7B,yEAAyE;QACzE,uCAAuC;QACvC,UAAU,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC;QAC5G;;;;;;;WAOG;QACH,eAAe,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE;QACnF,GAAG,EAAE,OAAO,CAAC,GAAG;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,cAAc,GAAG,EAAE,CAAC,CAAC,+BAA+B;AAE1D,SAAS,SAAS,CAAC,OAAe;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,cAAc,EAAE,CAAC;QACtD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,QAAQ,cAAc,GAAG,EAAE,CAAC;IACrF,CAAC;IACD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,OAAO,OAAO,cAAc,GAAG;QAC1C,IAAI,EAAE,4BAA4B,cAAc,iBAAiB;KAClE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,KAA4B;IACpD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC;IACpE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,gEAAgE;SACvE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAA4B;IAClD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,mBAAmB;YAC3B,IAAI,EAAE,yDAAyD;SAChE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,aAAa,CAAC,KAA4B;IACvD,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,KAAK,EAAE,EAAE,CAAC;IACnE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,mBAAmB;gBAC3B,IAAI,EAAE,iFAAiF;aACxF,CAAC;QACJ,CAAC;QACD,2EAA2E;QAC3E,2EAA2E;QAC3E,+BAA+B;QAC/B,MAAM,UAAU,GAAI,GAAa,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QACzD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;SAC/C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,GAAsB,EACtB,MAAmC;IAEnC,0EAA0E;IAC1E,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC5F,2EAA2E;QAC3E,uEAAuE;QACvE,0CAA0C;QAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,UAAU,eAAe,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,WAAW;gBACxF,IAAI,EAAE,gFAAgF;aACvF,CAAC;QACJ,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC;QAC9D,uEAAuE;QACvE,mEAAmE;QACnE,yEAAyE;QACzE,yEAAyE;QACzE,8DAA8D;QAC9D,uEAAuE;QACvE,cAAc;QACd,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE;YAClB,IAAI,CAAC,QAAQ,CAAC,OAAO;gBAAE,OAAO,yBAAyB,CAAC;YACxD,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBACpC,OAAO,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzC,CAAC;QACH,CAAC,CAAC,EAAE,CAAC;QACL,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YACtB,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,UAAU,oCAAoC;gBACzD,IAAI,EAAE,mEAAmE;aAC1E,CAAC;QACJ,CAAC;QACD,IAAI,eAAe,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,IAAI;gBACZ,MAAM,EAAE,GAAG,UAAU,eAAe,KAAK,oCAAoC;aAC9E,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;YAC5B,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,eAAe,KAAK,KAAK,QAAQ,CAAC,SAAS,OAAO,EAAE;YAC7G,CAAC,CAAC;gBACE,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,UAAU,eAAe,KAAK,KAAK,QAAQ,CAAC,SAAS,WAAW;gBAC3E,IAAI,EAAE,UAAU,QAAQ,CAAC,SAAS,yBAAyB;aAC5D,CAAC;IACR,CAAC;IACD,OAAO,oBAAoB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,mBAAmB,GAA2B;IAClD,mCAAmC,EAAE,mDAAmD;IACxF,eAAe,EAAE,wEAAwE;CAC1F,CAAC;AAEF;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;QAClD,OAAO,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,WAAW,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,OAAO,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,kBAAkB,CAAC,KAAa,EAAE,MAAmC;IACnF,IAAI,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,OAAO;QAAE,OAAO,IAAI,CAAC;IAClC,sEAAsE;IACtE,uEAAuE;IACvE,uEAAuE;IACvE,IAAI,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,gBAAgB,GAAG,GAAgB,EAAE,CAAC,CAAC;QAC3C,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,IAAI,6GAA6G;KAC7H,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACrG,IAAI,CAAC,IAAI;QAAE,OAAO,gBAAgB,EAAE,CAAC;IACrC,0EAA0E;IAC1E,wEAAwE;IACxE,0EAA0E;IAC1E,uEAAuE;IACvE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,eAAe,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,OAAO,gBAAgB,EAAE,CAAC;IAChE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE;QAC7B,IAAI,EAAE,+FAA+F;KACtG,CAAC;AACJ,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAa,EAAE,GAAsB;IACjE,0EAA0E;IAC1E,4EAA4E;IAC5E,gEAAgE;IAChE,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,UAAU,GAA2B;QACzC,KAAK,EAAE,wBAAwB;QAC/B,aAAa,EAAE,wBAAwB;QACvC,MAAM,EAAE,6BAA6B;KACtC,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QACvD,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,sEAAsE;YACtE,IAAI,KAAK,KAAK,GAAG,MAAM,GAAG,EAAE,CAAC;gBAC3B,OAAO;oBACL,IAAI,EAAE,UAAU;oBAChB,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,GAAG,KAAK,OAAO,MAAM,wBAAwB;oBACrD,IAAI,EAAE,QAAQ,MAAM,SAAS,MAAM,eAAe;iBACnD,CAAC;YACJ,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,KAAK,OAAO,MAAM,KAAK,GAAG,yBAAyB;aAC/D,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,OAAO,GAAG,CAAC,iBAAiB;YAC1B,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,sCAAsC,EAAE;YAC5F,CAAC,CAAC;gBACE,IAAI,EAAE,UAAU;gBAChB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,GAAG,KAAK,0CAA0C;gBAC1D,IAAI,EAAE,4EAA4E;aACnF,CAAC;IACR,CAAC;IACD,OAAO,GAAG,CAAC,cAAc;QACvB,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAAK,gCAAgC,EAAE;QACtF,CAAC,CAAC;YACE,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG,KAAK,oCAAoC;YACpD,IAAI,EAAE,mEAAmE;SAC1E,CAAC;AACR,CAAC;AAED,SAAS,aAAa,CACpB,IAAwB,EACxB,MAA8C,EAC9C,GAAsB;IAEtB,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAClD,OAAO,eAAe,CAAC,KAAK,EAAE,GAAG,EAAE,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,2EAA2E;QAC3E,wEAAwE;QACxE,2EAA2E;QAC3E,0EAA0E;QAC1E,8DAA8D;QAC9D,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QACnD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,qBAAqB;YAChG,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,sCAAsC,EAAE,EAAE,CAAC;SAClE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,MAA8C,EAAE,QAAgB;IACpF,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;YACL,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,gEAAgE;SACzE,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,aAAa,MAAM,CAAC,SAAS,IAAI,WAAW,YAAY,MAAM,CAAC,KAAK,IAAI,WAAW,EAAE;KAC9F,CAAC;AACJ,CAAC;AAQD,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AACxE,yEAAyE;AACzE,MAAM,eAAe,GAAqB,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;AAExF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAsB;IACpD,MAAM,IAAI,GAAG,EAAE,GAAG,WAAW,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAChD,IAAI,MAAwB,CAAC;IAC7B,IAAI,WAAoC,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,eAAe,CAAC;QACzB,0EAA0E;QAC1E,wEAAwE;QACxE,uEAAuE;QACvE,wEAAwE;QACxE,qBAAqB;QACrB,WAAW;YACT,GAAG,YAAY,WAAW;gBACxB,CAAC,CAAC;oBACE,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,yCAAyC,GAAG,CAAC,OAAO,EAAE;oBAC9D,IAAI,EAAE,uGAAuG;iBAC9G;gBACH,CAAC,CAAC;oBACE,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,MAAM;oBACd,MAAM,EAAE,8CAA+C,GAAa,CAAC,OAAO,EAAE;oBAC9E,IAAI,EAAE,4FAA4F;iBACnG,CAAC;IACV,CAAC;IACD,2EAA2E;IAC3E,qEAAqE;IACrE,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACvD,IAAI,aAAa,GAAkB,IAAI,CAAC;IACxC,IAAI,CAAC;QACH,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IACD,MAAM,MAAM,GAAkB;QAC5B,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC;QAC3B,MAAM,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC;QACnC,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;QAC/B,MAAM,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC;QACzC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC;KAC5C,CAAC;IACF,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,kBAAkB,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAC1D,IAAI,OAAO;YAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,WAAW,IAAI,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAChE,wEAAwE;IACxE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;AAClE,CAAC;AAED,MAAM,GAAG,GAAiC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;AACzG,MAAM,OAAO,GAAG,CAAC,CAAC,CAAC,iBAAiB;AACpC,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,kCAAkC;AAChE,MAAM,UAAU,GAAG,QAAQ,GAAG,EAAE,CAAC,CAAC,sCAAsC;AAExE,4EAA4E;AAC5E,2EAA2E;AAC3E,8EAA8E;AAC9E,6EAA6E;AAC7E,yBAAyB;AACzB,MAAM,IAAI,GAAiC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC5F,MAAM,GAAG,GAAG,GAAG,CAAC;AAChB,SAAS,KAAK,CAAC,IAAY,EAAE,IAAY,EAAE,EAAW;IACpD,OAAO,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,IAAI,IAAI,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC;YAClD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,IAAI,GAAG,IAAI,CAAC;QACd,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QACzC,CAAC;IACH,CAAC;IACD,IAAI,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mGAAmG;AACnG,SAAS,WAAW,CAAC,KAAe,EAAE,KAAa,EAAE,IAAY,EAAE,GAAW,EAAE,KAAa;IAC3F,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC;IAC3D,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAoB,EAAE,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,KAAK;IAC1E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,GAAG,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,CAAC;QAC9E,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC;QACtD,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACX,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YAC3B,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;YACjF,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CACR,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,uCAAuC,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAC9G,CAAC;IACF,OAAO,KAAK,CAAC;AACf,CAAC"}
package/dist/config.js CHANGED
@@ -49,8 +49,11 @@ export async function loadConfig(repoRoot) {
49
49
  ? raw.maxStageRetries
50
50
  : DEFAULTS.maxStageRetries,
51
51
  llmCache: raw.llmCache !== false,
52
+ ...(typeof raw.baseURL === 'string' && raw.baseURL.trim() ? { baseURL: raw.baseURL.trim() } : {}),
53
+ ...(typeof raw.apiKeyEnv === 'string' && raw.apiKeyEnv.trim() ? { apiKeyEnv: raw.apiKeyEnv.trim() } : {}),
52
54
  ...(raw.generatedHashes ? { generatedHashes: raw.generatedHashes } : {}),
53
55
  ...(raw.origin === 'create' || raw.origin === 'init' ? { origin: raw.origin } : {}),
56
+ ...(raw.legibility && typeof raw.legibility === 'object' ? { legibility: raw.legibility } : {}),
54
57
  };
55
58
  }
56
59
  /**
@@ -93,10 +96,64 @@ export function resolveModel(flag, config, env = process.env) {
93
96
  return { model: env.COPPERHEAD_MODEL, source: 'env' };
94
97
  if (config.model)
95
98
  return { model: config.model, source: 'config' };
96
- if (env.OPENAI_API_KEY)
97
- return { model: 'gpt-5', source: 'openai-key' };
98
- if (env.ANTHROPIC_API_KEY)
99
- return { model: 'claude', source: 'anthropic-key' };
99
+ // Auto-fallback is only safe when exactly one credential is present: guessing
100
+ // is a convenience when there is nothing to guess wrong. With two or more
101
+ // keys set (a common dev setup once a compat endpoint's key sits alongside
102
+ // OPENAI_API_KEY/ANTHROPIC_API_KEY), silently favoring whichever is checked
103
+ // first can send a request to the wrong provider with no signal — including
104
+ // a paid one when a free key was what was actually intended. Refuse instead
105
+ // of guessing; the compat route itself is never a fallback candidate here,
106
+ // since it is opt-in only via an explicit `compat:` prefix (design D2).
107
+ const available = [
108
+ ...(env.OPENAI_API_KEY ? [{ keyVar: 'OPENAI_API_KEY', model: 'gpt-5', source: 'openai-key' }] : []),
109
+ ...(env.ANTHROPIC_API_KEY ? [{ keyVar: 'ANTHROPIC_API_KEY', model: 'claude', source: 'anthropic-key' }] : []),
110
+ ];
111
+ if (available.length === 1)
112
+ return { model: available[0].model, source: available[0].source };
113
+ if (available.length > 1) {
114
+ throw new Error(`ambiguous: ${available.length} credentials found (${available.map((a) => a.keyVar).join(', ')}) and no model was ` +
115
+ 'selected; pass --model, set COPPERHEAD_MODEL, or set "model" in .copperhead/config.json.');
116
+ }
100
117
  throw new Error('no model configured: pass --model, set COPPERHEAD_MODEL, or export an API key; see https://docs.copperhead.sh/reference/configuration/');
101
118
  }
119
+ /** The credential variable used when nothing else is configured. */
120
+ export const DEFAULT_API_KEY_ENV = 'OPENAI_API_KEY';
121
+ /**
122
+ * Resolve the compatible-endpoint settings: environment wins over config, the
123
+ * same direction as `resolveModel`'s chain. These are *settings*, not a
124
+ * provider selector — only the `compat` route reads them (design D1/D2), so an
125
+ * exported COPPERHEAD_BASE_URL never silently redirects a `gpt-5` run.
126
+ */
127
+ export function resolveCompatSettings(config, env = process.env) {
128
+ const baseURL = env.COPPERHEAD_BASE_URL?.trim() || config.baseURL?.trim();
129
+ const apiKeyEnv = env.COPPERHEAD_API_KEY_ENV?.trim() || config.apiKeyEnv?.trim() || DEFAULT_API_KEY_ENV;
130
+ return { ...(baseURL ? { baseURL } : {}), apiKeyEnv };
131
+ }
132
+ /**
133
+ * True when a resolved model id routes through the `compat` provider (D1/D2).
134
+ * The single source of truth for that gate: `makeProvider` uses it to decide
135
+ * whether to consult `CompatSettings` at all, and the response cache (loop.ts)
136
+ * uses it to decide whether a run's cache key may depend on `baseURL` — a
137
+ * non-compat run (gpt-5, claude, ...) never reads COPPERHEAD_BASE_URL, so its
138
+ * cache key must not vary with it either, or every entry gets orphaned each
139
+ * time the endpoint used for unrelated compat testing changes.
140
+ */
141
+ export function isCompatModel(model) {
142
+ return model === 'compat' || model.startsWith('compat:');
143
+ }
144
+ /**
145
+ * True when the endpoint is loopback, i.e. a local server such as Ollama.
146
+ * Those need no credential (design D4); a remote endpoint always does.
147
+ */
148
+ export function isLocalEndpoint(baseURL) {
149
+ if (!baseURL)
150
+ return false;
151
+ try {
152
+ const h = new URL(baseURL).hostname.toLowerCase();
153
+ return h === 'localhost' || h === '127.0.0.1' || h === '::1' || h === '[::1]' || h.endsWith('.local');
154
+ }
155
+ catch {
156
+ return false; // an unparseable URL is not a local endpoint; the run fails later with a clearer error
157
+ }
158
+ }
102
159
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  import { existsSync } from 'node:fs';
2
- import { writeFile } from 'node:fs/promises';
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
3
  import { createHash } from 'node:crypto';
4
4
  import path from 'node:path';
5
5
  import { configPath, loadConfig } from '../config.js';
6
+ import { CREATE_ORIGIN } from './fab.js';
6
7
  /**
7
8
  * The create pipeline starts from a brief with no KiCad files, but the agent
8
9
  * cannot create them: `write_file` refuses KiCad files and `edit_file` only
@@ -33,8 +34,8 @@ function uuidFrom(seed) {
33
34
  function emptySchematic(rootUuid) {
34
35
  return `(kicad_sch
35
36
  (version 20231120)
36
- (generator "eeschema")
37
- (generator_version "8.0")
37
+ (generator "copperhead-draft")
38
+ (generator_version "0")
38
39
  (uuid "${rootUuid}")
39
40
  (paper "A4")
40
41
  (lib_symbols)
@@ -134,8 +135,24 @@ function projectFile(slug, rootUuid) {
134
135
  }, null, 2) + '\n');
135
136
  }
136
137
  async function persist(repoRoot, config) {
138
+ await mkdir(path.dirname(configPath(repoRoot)), { recursive: true });
137
139
  await writeFile(configPath(repoRoot), JSON.stringify(config, null, 2) + '\n', 'utf8');
138
140
  }
141
+ /**
142
+ * Stamp the config as create-produced (`origin: "create"`). The marker is what
143
+ * scopes the legibility finish gate (`isCreateProducedRepo` feeds the
144
+ * obligations ledger) and the fab release gate — a gate hung on a marker
145
+ * nothing writes is silently inert, so `runCreate` stamps it up front and
146
+ * `bootstrapKicadProject` re-stamps on every (re-)scaffold, covering the
147
+ * rollback path that deletes an uncommitted config.
148
+ */
149
+ export async function markCreateOrigin(repoRoot) {
150
+ const config = await loadConfig(repoRoot);
151
+ if (config.origin === CREATE_ORIGIN)
152
+ return;
153
+ config.origin = CREATE_ORIGIN;
154
+ await persist(repoRoot, config);
155
+ }
139
156
  /**
140
157
  * Ensure a KiCad project exists and is wired into config. No-op (returns null)
141
158
  * when config already points at a schematic on disk. If project files exist but
@@ -147,6 +164,10 @@ export async function bootstrapKicadProject(repoRoot, brief) {
147
164
  const config = await loadConfig(repoRoot);
148
165
  if (config.schematic && existsSync(path.join(repoRoot, config.schematic)))
149
166
  return null;
167
+ // Only `create` scaffolds through here, so the repo is create-produced by
168
+ // definition; stamping on every scaffold keeps the marker alive across the
169
+ // rollback-then-rescaffold path (git clean deletes an uncommitted config).
170
+ config.origin = CREATE_ORIGIN;
150
171
  const slug = projectSlug(brief);
151
172
  const schRel = `${slug}.kicad_sch`;
152
173
  const pcbRel = `${slug}.kicad_pcb`;
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/kicad/bootstrap.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/kicad/bootstrap.ts"],"names":[],"mappings":"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"}
package/dist/kicad/cli.js CHANGED
@@ -4,7 +4,7 @@ import { mkdtemp, readFile, rm } from 'node:fs/promises';
4
4
  import { tmpdir } from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { normalizeReport } from './report.js';
7
- import { PreflightError } from '../util/preflight.js';
7
+ import { PreflightError, isNotFoundError } from '../util/preflight.js';
8
8
  export class KicadCliMissingError extends PreflightError {
9
9
  constructor() {
10
10
  super('kicad-cli not found on PATH', 'copperhead verifies every mutation with kicad-cli ERC/DRC; without it no edit can be checked, so no run can start', [
@@ -95,7 +95,7 @@ function fallbackAfterMissing() {
95
95
  async function runKicad(args, opts) {
96
96
  let bin = resolveKicadCli();
97
97
  let res = await execa(bin, args, { reject: false });
98
- if (res.failed && res.code === 'ENOENT') {
98
+ if (res.failed && isNotFoundError(res)) {
99
99
  if (bin === 'kicad-cli') {
100
100
  bin = fallbackAfterMissing();
101
101
  res = await execa(bin, args, { reject: false });
@@ -104,11 +104,11 @@ async function runKicad(args, opts) {
104
104
  throw new KicadCliMissingError();
105
105
  }
106
106
  }
107
- if (opts?.reject === false)
108
- return res;
109
- if (res.failed && res.code === 'ENOENT') {
107
+ if (res.failed && isNotFoundError(res)) {
110
108
  throw new KicadCliMissingError();
111
109
  }
110
+ if (opts?.reject === false)
111
+ return res;
112
112
  if (res.failed) {
113
113
  throw Object.assign(new Error(res.stderr || res.stdout || `kicad-cli exited ${res.exitCode}`), res);
114
114
  }
@@ -128,18 +128,8 @@ export function setKicadFallbackBinaries(paths) {
128
128
  fallbackBinaries = paths ?? FALLBACK_BINARIES;
129
129
  }
130
130
  export async function kicadCliVersion() {
131
- try {
132
- const res = await runKicad(['version']);
133
- return String(res.stdout ?? '').trim();
134
- }
135
- catch (err) {
136
- if (err.code === 'ENOENT')
137
- throw new KicadCliMissingError();
138
- // runKicad already maps PATH ENOENT → fallback → KicadCliMissingError
139
- if (err instanceof KicadCliMissingError)
140
- throw err;
141
- throw err;
142
- }
131
+ const res = await runKicad(['version']);
132
+ return String(res.stdout ?? '').trim();
143
133
  }
144
134
  async function runCheck(kind, filePath, extraArgs = []) {
145
135
  const dir = await mkdtemp(path.join(tmpdir(), 'copperhead-'));
@@ -147,9 +137,6 @@ async function runCheck(kind, filePath, extraArgs = []) {
147
137
  const sub = kind === 'erc' ? ['sch', 'erc'] : ['pcb', 'drc'];
148
138
  try {
149
139
  const res = await runKicad([...sub, '--format', 'json', '--exit-code-violations', '--output', out, ...extraArgs, filePath], { reject: false });
150
- if (res.failed && res.code === 'ENOENT') {
151
- throw new KicadCliMissingError();
152
- }
153
140
  let raw;
154
141
  try {
155
142
  raw = JSON.parse(await readFile(out, 'utf8'));
@@ -196,8 +183,6 @@ export async function kicadLoadError(filePath) {
196
183
  : ['pcb', 'export', 'pos', '--output', path.join(dir, 'probe.pos'), filePath];
197
184
  try {
198
185
  const res = await runKicad(args, { reject: false });
199
- if (res.failed && res.code === 'ENOENT')
200
- throw new KicadCliMissingError();
201
186
  if (res.exitCode === 0)
202
187
  return null;
203
188
  return [res.stderr, res.stdout].filter(Boolean).join('\n').trim() || `kicad-cli exited ${res.exitCode}`;
@@ -234,8 +219,6 @@ export async function exportFab(pcbPath, schPath, outDir) {
234
219
  catch (err) {
235
220
  if (err instanceof KicadCliMissingError)
236
221
  throw err;
237
- if (err.code === 'ENOENT')
238
- throw new KicadCliMissingError();
239
222
  result.failed.push({ artifact: job.artifact, reason: String(err.stderr ?? err.message).slice(0, 200) });
240
223
  }
241
224
  }
@@ -252,8 +235,6 @@ export async function exportSvg(kind, filePath, outDir) {
252
235
  catch (err) {
253
236
  if (err instanceof KicadCliMissingError)
254
237
  throw err;
255
- if (err.code === 'ENOENT')
256
- throw new KicadCliMissingError();
257
238
  throw err;
258
239
  }
259
240
  return outDir;