@tscircuit/cli 0.1.1630 → 0.1.1631

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.
@@ -11984,6 +11984,7 @@ var kleur_default = $;
11984
11984
  // lib/shared/autorouter-diagnostics.ts
11985
11985
  var DEFAULT_DEBUG_DIR = path2.join("dist", "autorouter-debug");
11986
11986
  var PROGRESS_LOG_INTERVAL_MS = 1e4;
11987
+ var CIRCUIT_JSON_ID_PATTERN = /\b(?:source|pcb|schematic|subcircuit|cad|simulation)_[a-z0-9_]*_\d+\b/gi;
11987
11988
  var parseAutorouterTimeout = (duration) => {
11988
11989
  const trimmed = duration.trim();
11989
11990
  const match = trimmed.match(/^(\d+(?:\.\d+)?)(ms|s|m)?$/);
@@ -12086,7 +12087,7 @@ class AutorouterDiagnostics {
12086
12087
  const previousTraceCount = event.previousTraceCount ?? this.traceCountBySubcircuit.get(subcircuitId) ?? 0;
12087
12088
  this.activePhase = {
12088
12089
  subcircuitId,
12089
- componentDisplayName: event.componentDisplayName ?? subcircuitId,
12090
+ componentDisplayName: event.componentDisplayName ?? "subcircuit",
12090
12091
  routingPhaseIndex,
12091
12092
  phaseOrdinal,
12092
12093
  phaseCount: event.phaseCount,
@@ -12191,7 +12192,7 @@ class AutorouterDiagnostics {
12191
12192
  if (!activePhase.hasLoggedStart) {
12192
12193
  this.logPhaseStart(activePhase, "failed");
12193
12194
  }
12194
- this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${error.message}`);
12195
+ this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${this.formatUserFacingText(error.message)}`);
12195
12196
  }
12196
12197
  if (this.shouldDumpFailedInput(activePhase.routingPhaseIndex)) {
12197
12198
  this.writeJson(this.getPhaseFileName(activePhase, "input.simple-route.json"), event.simpleRouteJson ?? activePhase.simpleRouteJson ?? {});
@@ -12267,7 +12268,7 @@ class AutorouterDiagnostics {
12267
12268
  logPhaseStart(activePhase, reason) {
12268
12269
  const reasonText = reason ? ` ${reason}` : "";
12269
12270
  this.log([
12270
- `Autorouting ${activePhase.componentDisplayName} (${activePhase.subcircuitId}) ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
12271
+ `Autorouting ${this.formatUserFacingText(activePhase.componentDisplayName)} ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
12271
12272
  `connections=${activePhase.connectionCount},`,
12272
12273
  `obstacles=${activePhase.obstacleCount},`,
12273
12274
  `previous_traces=${activePhase.previousTraceCount}`,
@@ -12348,10 +12349,61 @@ class AutorouterDiagnostics {
12348
12349
  return parts.join(", ");
12349
12350
  }
12350
12351
  getConnectionNames(simpleRouteJson) {
12351
- return (simpleRouteJson?.connections ?? []).map((connection) => {
12352
- const name = connection.name ?? connection.rootConnectionName ?? connection.source_trace_id;
12353
- return typeof name === "string" ? name : null;
12354
- }).filter((name) => Boolean(name));
12352
+ return [
12353
+ ...new Set((simpleRouteJson?.connections ?? []).map((connection) => [
12354
+ connection.rootConnectionName,
12355
+ connection.name,
12356
+ connection.source_trace_id
12357
+ ].filter((value) => typeof value === "string").map((value) => this.resolveCircuitJsonId(value)).find((value) => value !== null)).filter((name) => name !== null))
12358
+ ];
12359
+ }
12360
+ resolveCircuitJsonId(value) {
12361
+ const circuitJson = this.getCurrentCircuitJson();
12362
+ const element = circuitJson.find((candidate) => Object.entries(candidate).some(([key, candidateValue]) => key.endsWith("_id") && candidateValue === value));
12363
+ if (!element)
12364
+ return value;
12365
+ if (element.type === "source_trace") {
12366
+ if (typeof element.name === "string")
12367
+ return element.name;
12368
+ return this.getTraceSelector(element, circuitJson);
12369
+ }
12370
+ if (element.type === "source_net" && typeof element.name === "string") {
12371
+ return `net.${element.name}`;
12372
+ }
12373
+ if (element.type === "source_port") {
12374
+ return this.getPortSelector(element, circuitJson);
12375
+ }
12376
+ return null;
12377
+ }
12378
+ formatUserFacingText(value) {
12379
+ let formattedValue = value;
12380
+ for (const element of this.getCurrentCircuitJson()) {
12381
+ for (const [key, id] of Object.entries(element)) {
12382
+ if (!key.endsWith("_id") || typeof id !== "string")
12383
+ continue;
12384
+ formattedValue = formattedValue.replaceAll(id, this.resolveCircuitJsonId(id) ?? "internal element");
12385
+ }
12386
+ }
12387
+ return formattedValue.replace(CIRCUIT_JSON_ID_PATTERN, "internal element");
12388
+ }
12389
+ getTraceSelector(trace, circuitJson) {
12390
+ const portIds = trace.connected_source_port_ids;
12391
+ if (!Array.isArray(portIds))
12392
+ return null;
12393
+ const selectors = portIds.map((portId) => typeof portId === "string" ? this.getPortSelectorById(portId, circuitJson) : null).filter((selector) => selector !== null);
12394
+ return selectors.length >= 2 ? selectors.join(" to ") : null;
12395
+ }
12396
+ getPortSelectorById(sourcePortId, circuitJson) {
12397
+ const port = circuitJson.find((element) => element.type === "source_port" && element.source_port_id === sourcePortId);
12398
+ return port ? this.getPortSelector(port, circuitJson) : null;
12399
+ }
12400
+ getPortSelector(port, circuitJson) {
12401
+ const portName = typeof port.most_frequently_referenced_by_name === "string" ? port.most_frequently_referenced_by_name : typeof port.name === "string" ? port.name : null;
12402
+ if (!portName)
12403
+ return null;
12404
+ const component = circuitJson.find((element) => element.type === "source_component" && element.source_component_id === port.source_component_id);
12405
+ const componentName = component && typeof component.name === "string" ? component.name : null;
12406
+ return componentName ? `${componentName}.${portName}` : portName;
12355
12407
  }
12356
12408
  countErrors(simpleRouteJson) {
12357
12409
  const errors = simpleRouteJson?.errors;
@@ -12359,7 +12411,8 @@ class AutorouterDiagnostics {
12359
12411
  }
12360
12412
  getCurrentCircuitJson() {
12361
12413
  try {
12362
- return this.rootCircuit?.db?.toArray?.() ?? [];
12414
+ const circuitJson = this.rootCircuit?.db?.toArray?.();
12415
+ return Array.isArray(circuitJson) ? circuitJson : [];
12363
12416
  } catch {
12364
12417
  return [];
12365
12418
  }
package/dist/cli/main.js CHANGED
@@ -97764,6 +97764,7 @@ import fs16 from "node:fs";
97764
97764
  import path16 from "node:path";
97765
97765
  var DEFAULT_DEBUG_DIR = path16.join("dist", "autorouter-debug");
97766
97766
  var PROGRESS_LOG_INTERVAL_MS = 1e4;
97767
+ var CIRCUIT_JSON_ID_PATTERN = /\b(?:source|pcb|schematic|subcircuit|cad|simulation)_[a-z0-9_]*_\d+\b/gi;
97767
97768
  var parseAutorouterTimeout = (duration) => {
97768
97769
  const trimmed = duration.trim();
97769
97770
  const match = trimmed.match(/^(\d+(?:\.\d+)?)(ms|s|m)?$/);
@@ -97866,7 +97867,7 @@ class AutorouterDiagnostics {
97866
97867
  const previousTraceCount = event.previousTraceCount ?? this.traceCountBySubcircuit.get(subcircuitId) ?? 0;
97867
97868
  this.activePhase = {
97868
97869
  subcircuitId,
97869
- componentDisplayName: event.componentDisplayName ?? subcircuitId,
97870
+ componentDisplayName: event.componentDisplayName ?? "subcircuit",
97870
97871
  routingPhaseIndex,
97871
97872
  phaseOrdinal,
97872
97873
  phaseCount: event.phaseCount,
@@ -97971,7 +97972,7 @@ class AutorouterDiagnostics {
97971
97972
  if (!activePhase.hasLoggedStart) {
97972
97973
  this.logPhaseStart(activePhase, "failed");
97973
97974
  }
97974
- this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${error.message}`);
97975
+ this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${this.formatUserFacingText(error.message)}`);
97975
97976
  }
97976
97977
  if (this.shouldDumpFailedInput(activePhase.routingPhaseIndex)) {
97977
97978
  this.writeJson(this.getPhaseFileName(activePhase, "input.simple-route.json"), event.simpleRouteJson ?? activePhase.simpleRouteJson ?? {});
@@ -98047,7 +98048,7 @@ class AutorouterDiagnostics {
98047
98048
  logPhaseStart(activePhase, reason) {
98048
98049
  const reasonText = reason ? ` ${reason}` : "";
98049
98050
  this.log([
98050
- `Autorouting ${activePhase.componentDisplayName} (${activePhase.subcircuitId}) ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
98051
+ `Autorouting ${this.formatUserFacingText(activePhase.componentDisplayName)} ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
98051
98052
  `connections=${activePhase.connectionCount},`,
98052
98053
  `obstacles=${activePhase.obstacleCount},`,
98053
98054
  `previous_traces=${activePhase.previousTraceCount}`,
@@ -98128,10 +98129,61 @@ class AutorouterDiagnostics {
98128
98129
  return parts.join(", ");
98129
98130
  }
98130
98131
  getConnectionNames(simpleRouteJson) {
98131
- return (simpleRouteJson?.connections ?? []).map((connection) => {
98132
- const name = connection.name ?? connection.rootConnectionName ?? connection.source_trace_id;
98133
- return typeof name === "string" ? name : null;
98134
- }).filter((name) => Boolean(name));
98132
+ return [
98133
+ ...new Set((simpleRouteJson?.connections ?? []).map((connection) => [
98134
+ connection.rootConnectionName,
98135
+ connection.name,
98136
+ connection.source_trace_id
98137
+ ].filter((value) => typeof value === "string").map((value) => this.resolveCircuitJsonId(value)).find((value) => value !== null)).filter((name) => name !== null))
98138
+ ];
98139
+ }
98140
+ resolveCircuitJsonId(value) {
98141
+ const circuitJson = this.getCurrentCircuitJson();
98142
+ const element = circuitJson.find((candidate) => Object.entries(candidate).some(([key, candidateValue]) => key.endsWith("_id") && candidateValue === value));
98143
+ if (!element)
98144
+ return value;
98145
+ if (element.type === "source_trace") {
98146
+ if (typeof element.name === "string")
98147
+ return element.name;
98148
+ return this.getTraceSelector(element, circuitJson);
98149
+ }
98150
+ if (element.type === "source_net" && typeof element.name === "string") {
98151
+ return `net.${element.name}`;
98152
+ }
98153
+ if (element.type === "source_port") {
98154
+ return this.getPortSelector(element, circuitJson);
98155
+ }
98156
+ return null;
98157
+ }
98158
+ formatUserFacingText(value) {
98159
+ let formattedValue = value;
98160
+ for (const element of this.getCurrentCircuitJson()) {
98161
+ for (const [key, id] of Object.entries(element)) {
98162
+ if (!key.endsWith("_id") || typeof id !== "string")
98163
+ continue;
98164
+ formattedValue = formattedValue.replaceAll(id, this.resolveCircuitJsonId(id) ?? "internal element");
98165
+ }
98166
+ }
98167
+ return formattedValue.replace(CIRCUIT_JSON_ID_PATTERN, "internal element");
98168
+ }
98169
+ getTraceSelector(trace, circuitJson) {
98170
+ const portIds = trace.connected_source_port_ids;
98171
+ if (!Array.isArray(portIds))
98172
+ return null;
98173
+ const selectors = portIds.map((portId) => typeof portId === "string" ? this.getPortSelectorById(portId, circuitJson) : null).filter((selector) => selector !== null);
98174
+ return selectors.length >= 2 ? selectors.join(" to ") : null;
98175
+ }
98176
+ getPortSelectorById(sourcePortId, circuitJson) {
98177
+ const port = circuitJson.find((element) => element.type === "source_port" && element.source_port_id === sourcePortId);
98178
+ return port ? this.getPortSelector(port, circuitJson) : null;
98179
+ }
98180
+ getPortSelector(port, circuitJson) {
98181
+ const portName = typeof port.most_frequently_referenced_by_name === "string" ? port.most_frequently_referenced_by_name : typeof port.name === "string" ? port.name : null;
98182
+ if (!portName)
98183
+ return null;
98184
+ const component = circuitJson.find((element) => element.type === "source_component" && element.source_component_id === port.source_component_id);
98185
+ const componentName = component && typeof component.name === "string" ? component.name : null;
98186
+ return componentName ? `${componentName}.${portName}` : portName;
98135
98187
  }
98136
98188
  countErrors(simpleRouteJson) {
98137
98189
  const errors = simpleRouteJson?.errors;
@@ -98139,7 +98191,8 @@ class AutorouterDiagnostics {
98139
98191
  }
98140
98192
  getCurrentCircuitJson() {
98141
98193
  try {
98142
- return this.rootCircuit?.db?.toArray?.() ?? [];
98194
+ const circuitJson = this.rootCircuit?.db?.toArray?.();
98195
+ return Array.isArray(circuitJson) ? circuitJson : [];
98143
98196
  } catch {
98144
98197
  return [];
98145
98198
  }
@@ -215125,9 +215178,9 @@ var addStartAndEndPortIdsIfMissing = (soup) => {
215125
215178
  }
215126
215179
  }
215127
215180
  };
215128
- var CIRCUIT_JSON_ID_PATTERN = /\b(?:pcb|source|schematic|subcircuit)_[a-z0-9_]+\b/i;
215181
+ var CIRCUIT_JSON_ID_PATTERN2 = /\b(?:pcb|source|schematic|subcircuit)_[a-z0-9_]+\b/i;
215129
215182
  var sanitizeReadableName = (candidate, id2, fallbackLabel) => {
215130
- if (!candidate || candidate === id2 || CIRCUIT_JSON_ID_PATTERN.test(candidate)) {
215183
+ if (!candidate || candidate === id2 || CIRCUIT_JSON_ID_PATTERN2.test(candidate)) {
215131
215184
  return fallbackLabel;
215132
215185
  }
215133
215186
  return candidate;
@@ -215164,7 +215217,7 @@ var getReadableNameForPort = (circuitJson, pcbPortId) => {
215164
215217
  return sanitizeReadableName(getReadableNameForPcbPort(circuitJson, pcbPortId) ?? getReadableNameForElement(circuitJson, pcbPortId), pcbPortId, "port");
215165
215218
  };
215166
215219
  var getReadableNameForElementId = (circuitJson, elementId) => sanitizeReadableName(getReadableNameForElement(circuitJson, elementId), elementId, "element");
215167
- var containsCircuitJsonId = (message) => CIRCUIT_JSON_ID_PATTERN.test(message);
215220
+ var containsCircuitJsonId = (message) => CIRCUIT_JSON_ID_PATTERN2.test(message);
215168
215221
  function checkEachPcbPortConnectedToPcbTraces(circuitJson) {
215169
215222
  addStartAndEndPortIdsIfMissing(circuitJson);
215170
215223
  const sourceTraces = circuitJson.filter((item) => item.type === "source_trace");
@@ -264684,6 +264737,28 @@ Publish completed with ${uploadResults.succeeded.length} files uploaded and ${up
264684
264737
  var debug13 = Debug3("tscircuit:devserver");
264685
264738
  var BINARY_FILE_EXTENSIONS2 = new Set([".glb", ".png", ".jpeg", ".jpg"]);
264686
264739
  var CONFIG_MODULE_FILENAMES2 = ["tscircuit.config.ts", "tscircuit.config.js"];
264740
+ var CIRCUIT_JSON_ID_PATTERN3 = /\b(?:source|pcb|schematic|subcircuit|cad|simulation)_[a-z0-9_]*_\d+\b/gi;
264741
+ var formatAutorouterDebugEvent = (event) => {
264742
+ const parts = [
264743
+ typeof event.componentDisplayName === "string" ? `component=${event.componentDisplayName}` : null,
264744
+ typeof event.phase === "string" ? `phase=${event.phase}` : null,
264745
+ typeof event.solverName === "string" ? `solver=${event.solverName}` : null,
264746
+ typeof event.connectionCount === "number" ? `connections=${event.connectionCount}` : null,
264747
+ typeof event.obstacleCount === "number" ? `obstacles=${event.obstacleCount}` : null,
264748
+ typeof event.steps === "number" ? `steps=${event.steps}` : null,
264749
+ typeof event.iteration === "number" ? `iteration=${event.iteration}` : null,
264750
+ typeof event.progress === "number" ? `progress=${Math.round(event.progress * 100)}%` : null,
264751
+ typeof event.iterationsPerSecond === "number" ? `iterations_per_second=${Math.round(event.iterationsPerSecond)}` : null,
264752
+ typeof event.elapsedMs === "number" ? `elapsed=${Math.round(event.elapsedMs)}ms` : null
264753
+ ].filter((part) => part !== null);
264754
+ const error2 = event.error;
264755
+ const errorMessage = error2 && typeof error2 === "object" && "message" in error2 ? error2.message : typeof error2 === "string" ? error2 : null;
264756
+ if (typeof errorMessage === "string") {
264757
+ parts.push(`error=${errorMessage.replace(CIRCUIT_JSON_ID_PATTERN3, "internal element")}`);
264758
+ }
264759
+ const eventType = typeof event.event_type === "string" ? event.event_type : "autorouting";
264760
+ return `[autorouter] ${eventType}${parts.length > 0 ? ` ${parts.join(" ")}` : ""}`;
264761
+ };
264687
264762
 
264688
264763
  class DevServer {
264689
264764
  port;
@@ -264735,7 +264810,7 @@ class DevServer {
264735
264810
  this.eventsWatcher.on("*", (event) => {
264736
264811
  if (!String(event.event_type).startsWith("autorouting:"))
264737
264812
  return;
264738
- console.log(kleur_default.cyan(`[autorouter] ${event.event_type} ${JSON.stringify(event)}`));
264813
+ console.log(kleur_default.cyan(formatAutorouterDebugEvent(event)));
264739
264814
  });
264740
264815
  }
264741
264816
  this.filesystemWatcher = watch(this.projectDir, {
@@ -2803,6 +2803,7 @@ import fs from "node:fs";
2803
2803
  import path from "node:path";
2804
2804
  var DEFAULT_DEBUG_DIR = path.join("dist", "autorouter-debug");
2805
2805
  var PROGRESS_LOG_INTERVAL_MS = 1e4;
2806
+ var CIRCUIT_JSON_ID_PATTERN = /\b(?:source|pcb|schematic|subcircuit|cad|simulation)_[a-z0-9_]*_\d+\b/gi;
2806
2807
  var parseAutorouterTimeout = (duration) => {
2807
2808
  const trimmed = duration.trim();
2808
2809
  const match = trimmed.match(/^(\d+(?:\.\d+)?)(ms|s|m)?$/);
@@ -2905,7 +2906,7 @@ class AutorouterDiagnostics {
2905
2906
  const previousTraceCount = event.previousTraceCount ?? this.traceCountBySubcircuit.get(subcircuitId) ?? 0;
2906
2907
  this.activePhase = {
2907
2908
  subcircuitId,
2908
- componentDisplayName: event.componentDisplayName ?? subcircuitId,
2909
+ componentDisplayName: event.componentDisplayName ?? "subcircuit",
2909
2910
  routingPhaseIndex,
2910
2911
  phaseOrdinal,
2911
2912
  phaseCount: event.phaseCount,
@@ -3010,7 +3011,7 @@ class AutorouterDiagnostics {
3010
3011
  if (!activePhase.hasLoggedStart) {
3011
3012
  this.logPhaseStart(activePhase, "failed");
3012
3013
  }
3013
- this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${error.message}`);
3014
+ this.log(` ${this.getPhaseLabel(activePhase)} error after ${this.formatElapsed(elapsedMs)}: ${this.formatUserFacingText(error.message)}`);
3014
3015
  }
3015
3016
  if (this.shouldDumpFailedInput(activePhase.routingPhaseIndex)) {
3016
3017
  this.writeJson(this.getPhaseFileName(activePhase, "input.simple-route.json"), event.simpleRouteJson ?? activePhase.simpleRouteJson ?? {});
@@ -3086,7 +3087,7 @@ class AutorouterDiagnostics {
3086
3087
  logPhaseStart(activePhase, reason) {
3087
3088
  const reasonText = reason ? ` ${reason}` : "";
3088
3089
  this.log([
3089
- `Autorouting ${activePhase.componentDisplayName} (${activePhase.subcircuitId}) ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
3090
+ `Autorouting ${this.formatUserFacingText(activePhase.componentDisplayName)} ${this.getPhaseLabel(activePhase)}${reasonText} start:`,
3090
3091
  `connections=${activePhase.connectionCount},`,
3091
3092
  `obstacles=${activePhase.obstacleCount},`,
3092
3093
  `previous_traces=${activePhase.previousTraceCount}`,
@@ -3167,10 +3168,61 @@ class AutorouterDiagnostics {
3167
3168
  return parts.join(", ");
3168
3169
  }
3169
3170
  getConnectionNames(simpleRouteJson) {
3170
- return (simpleRouteJson?.connections ?? []).map((connection) => {
3171
- const name = connection.name ?? connection.rootConnectionName ?? connection.source_trace_id;
3172
- return typeof name === "string" ? name : null;
3173
- }).filter((name) => Boolean(name));
3171
+ return [
3172
+ ...new Set((simpleRouteJson?.connections ?? []).map((connection) => [
3173
+ connection.rootConnectionName,
3174
+ connection.name,
3175
+ connection.source_trace_id
3176
+ ].filter((value) => typeof value === "string").map((value) => this.resolveCircuitJsonId(value)).find((value) => value !== null)).filter((name) => name !== null))
3177
+ ];
3178
+ }
3179
+ resolveCircuitJsonId(value) {
3180
+ const circuitJson = this.getCurrentCircuitJson();
3181
+ const element = circuitJson.find((candidate) => Object.entries(candidate).some(([key, candidateValue]) => key.endsWith("_id") && candidateValue === value));
3182
+ if (!element)
3183
+ return value;
3184
+ if (element.type === "source_trace") {
3185
+ if (typeof element.name === "string")
3186
+ return element.name;
3187
+ return this.getTraceSelector(element, circuitJson);
3188
+ }
3189
+ if (element.type === "source_net" && typeof element.name === "string") {
3190
+ return `net.${element.name}`;
3191
+ }
3192
+ if (element.type === "source_port") {
3193
+ return this.getPortSelector(element, circuitJson);
3194
+ }
3195
+ return null;
3196
+ }
3197
+ formatUserFacingText(value) {
3198
+ let formattedValue = value;
3199
+ for (const element of this.getCurrentCircuitJson()) {
3200
+ for (const [key, id] of Object.entries(element)) {
3201
+ if (!key.endsWith("_id") || typeof id !== "string")
3202
+ continue;
3203
+ formattedValue = formattedValue.replaceAll(id, this.resolveCircuitJsonId(id) ?? "internal element");
3204
+ }
3205
+ }
3206
+ return formattedValue.replace(CIRCUIT_JSON_ID_PATTERN, "internal element");
3207
+ }
3208
+ getTraceSelector(trace, circuitJson) {
3209
+ const portIds = trace.connected_source_port_ids;
3210
+ if (!Array.isArray(portIds))
3211
+ return null;
3212
+ const selectors = portIds.map((portId) => typeof portId === "string" ? this.getPortSelectorById(portId, circuitJson) : null).filter((selector) => selector !== null);
3213
+ return selectors.length >= 2 ? selectors.join(" to ") : null;
3214
+ }
3215
+ getPortSelectorById(sourcePortId, circuitJson) {
3216
+ const port = circuitJson.find((element) => element.type === "source_port" && element.source_port_id === sourcePortId);
3217
+ return port ? this.getPortSelector(port, circuitJson) : null;
3218
+ }
3219
+ getPortSelector(port, circuitJson) {
3220
+ const portName = typeof port.most_frequently_referenced_by_name === "string" ? port.most_frequently_referenced_by_name : typeof port.name === "string" ? port.name : null;
3221
+ if (!portName)
3222
+ return null;
3223
+ const component = circuitJson.find((element) => element.type === "source_component" && element.source_component_id === port.source_component_id);
3224
+ const componentName = component && typeof component.name === "string" ? component.name : null;
3225
+ return componentName ? `${componentName}.${portName}` : portName;
3174
3226
  }
3175
3227
  countErrors(simpleRouteJson) {
3176
3228
  const errors = simpleRouteJson?.errors;
@@ -3178,7 +3230,8 @@ class AutorouterDiagnostics {
3178
3230
  }
3179
3231
  getCurrentCircuitJson() {
3180
3232
  try {
3181
- return this.rootCircuit?.db?.toArray?.() ?? [];
3233
+ const circuitJson = this.rootCircuit?.db?.toArray?.();
3234
+ return Array.isArray(circuitJson) ? circuitJson : [];
3182
3235
  } catch {
3183
3236
  return [];
3184
3237
  }
package/dist/lib/index.js CHANGED
@@ -80118,6 +80118,28 @@ Publish completed with ${uploadResults.succeeded.length} files uploaded and ${up
80118
80118
  var debug2 = Debug2("tscircuit:devserver");
80119
80119
  var BINARY_FILE_EXTENSIONS2 = new Set([".glb", ".png", ".jpeg", ".jpg"]);
80120
80120
  var CONFIG_MODULE_FILENAMES2 = ["tscircuit.config.ts", "tscircuit.config.js"];
80121
+ var CIRCUIT_JSON_ID_PATTERN = /\b(?:source|pcb|schematic|subcircuit|cad|simulation)_[a-z0-9_]*_\d+\b/gi;
80122
+ var formatAutorouterDebugEvent = (event) => {
80123
+ const parts = [
80124
+ typeof event.componentDisplayName === "string" ? `component=${event.componentDisplayName}` : null,
80125
+ typeof event.phase === "string" ? `phase=${event.phase}` : null,
80126
+ typeof event.solverName === "string" ? `solver=${event.solverName}` : null,
80127
+ typeof event.connectionCount === "number" ? `connections=${event.connectionCount}` : null,
80128
+ typeof event.obstacleCount === "number" ? `obstacles=${event.obstacleCount}` : null,
80129
+ typeof event.steps === "number" ? `steps=${event.steps}` : null,
80130
+ typeof event.iteration === "number" ? `iteration=${event.iteration}` : null,
80131
+ typeof event.progress === "number" ? `progress=${Math.round(event.progress * 100)}%` : null,
80132
+ typeof event.iterationsPerSecond === "number" ? `iterations_per_second=${Math.round(event.iterationsPerSecond)}` : null,
80133
+ typeof event.elapsedMs === "number" ? `elapsed=${Math.round(event.elapsedMs)}ms` : null
80134
+ ].filter((part) => part !== null);
80135
+ const error = event.error;
80136
+ const errorMessage = error && typeof error === "object" && "message" in error ? error.message : typeof error === "string" ? error : null;
80137
+ if (typeof errorMessage === "string") {
80138
+ parts.push(`error=${errorMessage.replace(CIRCUIT_JSON_ID_PATTERN, "internal element")}`);
80139
+ }
80140
+ const eventType = typeof event.event_type === "string" ? event.event_type : "autorouting";
80141
+ return `[autorouter] ${eventType}${parts.length > 0 ? ` ${parts.join(" ")}` : ""}`;
80142
+ };
80121
80143
 
80122
80144
  class DevServer {
80123
80145
  port;
@@ -80169,7 +80191,7 @@ class DevServer {
80169
80191
  this.eventsWatcher.on("*", (event) => {
80170
80192
  if (!String(event.event_type).startsWith("autorouting:"))
80171
80193
  return;
80172
- console.log(kleur_default.cyan(`[autorouter] ${event.event_type} ${JSON.stringify(event)}`));
80194
+ console.log(kleur_default.cyan(formatAutorouterDebugEvent(event)));
80173
80195
  });
80174
80196
  }
80175
80197
  this.filesystemWatcher = watch(this.projectDir, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/cli",
3
- "version": "0.1.1630",
3
+ "version": "0.1.1631",
4
4
  "main": "dist/cli/main.js",
5
5
  "exports": {
6
6
  ".": "./dist/cli/main.js",