@fairfox/polly 0.7.2 → 0.7.4

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 (41) hide show
  1. package/dist/src/background/index.d.ts +1 -1
  2. package/dist/src/background/index.js +10 -3
  3. package/dist/src/background/index.js.map +9 -9
  4. package/dist/src/background/message-router.js +10 -3
  5. package/dist/src/background/message-router.js.map +8 -8
  6. package/dist/src/index.d.ts +9 -9
  7. package/dist/src/index.js +74 -67
  8. package/dist/src/index.js.map +12 -12
  9. package/dist/src/shared/adapters/chrome/context-menus.chrome.d.ts +1 -1
  10. package/dist/src/shared/adapters/chrome/tabs.chrome.d.ts +2 -2
  11. package/dist/src/shared/adapters/context-menus.adapter.d.ts +1 -1
  12. package/dist/src/shared/adapters/index.d.ts +4 -4
  13. package/dist/src/shared/adapters/index.js +9 -2
  14. package/dist/src/shared/adapters/index.js.map +6 -6
  15. package/dist/src/shared/adapters/tabs.adapter.d.ts +2 -2
  16. package/dist/src/shared/lib/context-helpers.js +10 -3
  17. package/dist/src/shared/lib/context-helpers.js.map +8 -8
  18. package/dist/src/shared/lib/message-bus.js +10 -3
  19. package/dist/src/shared/lib/message-bus.js.map +7 -7
  20. package/dist/src/shared/lib/state.js +10 -3
  21. package/dist/src/shared/lib/state.js.map +8 -8
  22. package/dist/src/shared/state/app-state.js +10 -3
  23. package/dist/src/shared/state/app-state.js.map +8 -8
  24. package/dist/tools/init/src/cli.js +17 -2
  25. package/dist/tools/init/src/cli.js.map +4 -4
  26. package/dist/tools/init/templates/pwa/package.json.template +3 -3
  27. package/dist/tools/teach/src/cli.js +2712 -2442
  28. package/dist/tools/teach/src/cli.js.map +11 -11
  29. package/dist/tools/teach/src/index.js +1379 -1379
  30. package/dist/tools/teach/src/index.js.map +10 -10
  31. package/dist/tools/test/src/adapters/index.d.ts +8 -8
  32. package/dist/tools/test/src/adapters/index.js +3 -2
  33. package/dist/tools/test/src/adapters/index.js.map +6 -6
  34. package/dist/tools/test/src/index.d.ts +3 -3
  35. package/dist/tools/test/src/index.js +3 -2
  36. package/dist/tools/test/src/index.js.map +6 -6
  37. package/dist/tools/verify/src/cli.js +142 -41
  38. package/dist/tools/verify/src/cli.js.map +8 -8
  39. package/dist/tools/visualize/src/cli.js +18 -3
  40. package/dist/tools/visualize/src/cli.js.map +4 -4
  41. package/package.json +26 -15
@@ -1,6 +1,21 @@
1
1
  #!/usr/bin/env bun
2
2
  import { createRequire } from "node:module";
3
+ var __create = Object.create;
4
+ var __getProtoOf = Object.getPrototypeOf;
3
5
  var __defProp = Object.defineProperty;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __toESM = (mod, isNodeMode, target) => {
9
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
10
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
+ for (let key of __getOwnPropNames(mod))
12
+ if (!__hasOwnProp.call(to, key))
13
+ __defProp(to, key, {
14
+ get: () => mod[key],
15
+ enumerable: true
16
+ });
17
+ return to;
18
+ };
4
19
  var __export = (target, all) => {
5
20
  for (var name in all)
6
21
  __defProp(target, name, {
@@ -1045,10 +1060,10 @@ class TLAGenerator {
1045
1060
  const _indexMap = new Map;
1046
1061
  result = result.replace(/(\w+(?:\.\w+)*)\[(\d+)\]|\]\[(\d+)\]/g, (_match, identPart, index1, index2) => {
1047
1062
  if (identPart) {
1048
- const newIndex2 = Number.parseInt(index1) + 1;
1063
+ const newIndex2 = Number.parseInt(index1, 10) + 1;
1049
1064
  return `${identPart}[${newIndex2}]`;
1050
1065
  }
1051
- const newIndex = Number.parseInt(index2) + 1;
1066
+ const newIndex = Number.parseInt(index2, 10) + 1;
1052
1067
  return `][${newIndex}]`;
1053
1068
  });
1054
1069
  result = result.replace(/(\w+(?:\.\w+)*)\.some\(\(?(\w+)\)?\s*=>\s*([^)]+)\)/g, (_match, arrayRef, param, condition) => {
@@ -1077,9 +1092,9 @@ class TLAGenerator {
1077
1092
  return `\\E i \\in 1..Len(${strRef}) : SubSeq(${strRef}, i, i+${substring.length}-1) = "${substring}"`;
1078
1093
  });
1079
1094
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+)(?:,\s*(-?\d+))?\)\.length/g, (_match, strRef, start, end) => {
1080
- const startNum = Number.parseInt(start);
1095
+ const startNum = Number.parseInt(start, 10);
1081
1096
  if (end !== undefined) {
1082
- const endNum = Number.parseInt(end);
1097
+ const endNum = Number.parseInt(end, 10);
1083
1098
  if (startNum < 0 && endNum < 0) {
1084
1099
  return `Len(SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}) - ${Math.abs(endNum)}))`;
1085
1100
  }
@@ -1097,9 +1112,9 @@ class TLAGenerator {
1097
1112
  return `Len(SubSeq(${strRef}, ${startNum + 1}, Len(${strRef})))`;
1098
1113
  });
1099
1114
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+)(?:,\s*(\d+))?\)\.length/g, (_match, strRef, start, end) => {
1100
- const startNum = Number.parseInt(start);
1115
+ const startNum = Number.parseInt(start, 10);
1101
1116
  if (end !== undefined) {
1102
- const endNum = Number.parseInt(end);
1117
+ const endNum = Number.parseInt(end, 10);
1103
1118
  if (startNum > endNum) {
1104
1119
  return `Len(SubSeq(${strRef}, ${endNum + 1}, ${startNum}))`;
1105
1120
  }
@@ -1108,15 +1123,15 @@ class TLAGenerator {
1108
1123
  return `Len(SubSeq(${strRef}, ${startNum + 1}, Len(${strRef})))`;
1109
1124
  });
1110
1125
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+)\)(?!,)/g, (_match, strRef, start) => {
1111
- const startNum = Number.parseInt(start);
1126
+ const startNum = Number.parseInt(start, 10);
1112
1127
  if (startNum < 0) {
1113
1128
  return `SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}))`;
1114
1129
  }
1115
1130
  return `SubSeq(${strRef}, ${startNum + 1}, Len(${strRef}))`;
1116
1131
  });
1117
1132
  result = result.replace(/(\w+(?:\.\w+)*)\.slice\((-?\d+),\s*(-?\d+)\)/g, (_match, strRef, start, end) => {
1118
- const startNum = Number.parseInt(start);
1119
- const endNum = Number.parseInt(end);
1133
+ const startNum = Number.parseInt(start, 10);
1134
+ const endNum = Number.parseInt(end, 10);
1120
1135
  if (startNum < 0 && endNum < 0) {
1121
1136
  return `SubSeq(${strRef}, Len(${strRef}) - ${Math.abs(startNum)} + 1, Len(${strRef}) - ${Math.abs(endNum)})`;
1122
1137
  }
@@ -1129,12 +1144,12 @@ class TLAGenerator {
1129
1144
  return `SubSeq(${strRef}, ${startNum + 1}, ${endNum})`;
1130
1145
  });
1131
1146
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+)\)(?!,)/g, (_match, strRef, start) => {
1132
- const startNum = Number.parseInt(start);
1147
+ const startNum = Number.parseInt(start, 10);
1133
1148
  return `SubSeq(${strRef}, ${startNum + 1}, Len(${strRef}))`;
1134
1149
  });
1135
1150
  result = result.replace(/(\w+(?:\.\w+)*)\.substring\((\d+),\s*(\d+)\)/g, (_match, strRef, start, end) => {
1136
- const startNum = Number.parseInt(start);
1137
- const endNum = Number.parseInt(end);
1151
+ const startNum = Number.parseInt(start, 10);
1152
+ const endNum = Number.parseInt(end, 10);
1138
1153
  if (startNum > endNum) {
1139
1154
  return `SubSeq(${strRef}, ${endNum + 1}, ${startNum})`;
1140
1155
  }
@@ -1210,7 +1225,7 @@ class TLAGenerator {
1210
1225
  result = result.replace(/(\w+(?:\.\w+)*)\?\.(\w+)(?!\?\.)/g, (_match, obj, prop) => `IF ${obj} # NULL THEN ${obj}.${prop} ELSE NULL`);
1211
1226
  result = result.replace(/\(([^)]+)\)\?\.(\w+)/g, (_match, expr2, prop) => `IF (${expr2}) # NULL THEN (${expr2}).${prop} ELSE NULL`);
1212
1227
  result = result.replace(/(\w+(?:\.\w+)*)\?\.\[(\d+)\]/g, (_match, obj, index) => {
1213
- const tlaIndex = Number.parseInt(index) + 1;
1228
+ const tlaIndex = Number.parseInt(index, 10) + 1;
1214
1229
  return `IF ${obj} # NULL THEN ${obj}[${tlaIndex}] ELSE NULL`;
1215
1230
  });
1216
1231
  result = result.replace(/(\w+(?:\.\w+)*)\?\.\[['"](\w+)['"]\]/g, (_match, obj, prop) => `IF ${obj} # NULL THEN ${obj}.${prop} ELSE NULL`);
@@ -1691,8 +1706,8 @@ class DockerRunner {
1691
1706
  return {
1692
1707
  success: true,
1693
1708
  stats: {
1694
- statesGenerated: statesMatch?.[1] ? Number.parseInt(statesMatch[1]) : 0,
1695
- distinctStates: distinctMatch?.[1] ? Number.parseInt(distinctMatch[1]) : 0
1709
+ statesGenerated: statesMatch?.[1] ? Number.parseInt(statesMatch[1], 10) : 0,
1710
+ distinctStates: distinctMatch?.[1] ? Number.parseInt(distinctMatch[1], 10) : 0
1696
1711
  },
1697
1712
  output
1698
1713
  };
@@ -1739,10 +1754,11 @@ class DockerRunner {
1739
1754
  proc.stderr.on("data", (data) => {
1740
1755
  stderr += data.toString();
1741
1756
  });
1742
- const timeout = options?.timeout ? setTimeout(() => {
1757
+ const timeoutValue = options?.timeout ?? 0;
1758
+ const timeout = timeoutValue > 0 ? setTimeout(() => {
1743
1759
  proc.kill();
1744
- reject(new Error(`Command timed out after ${options.timeout}ms`));
1745
- }, options.timeout) : null;
1760
+ reject(new Error(`Command timed out after ${Math.floor(timeoutValue / 1000)}s. TLC was still making progress. Consider increasing the timeout or using preset: 'thorough' for no timeout.`));
1761
+ }, timeoutValue) : null;
1746
1762
  proc.on("close", (exitCode) => {
1747
1763
  if (timeout)
1748
1764
  clearTimeout(timeout);
@@ -2135,6 +2151,22 @@ class ConfigGenerator {
2135
2151
  this.line("// • 'off' - Skip verification");
2136
2152
  this.line("//");
2137
2153
  this.line("onRelease: 'error',");
2154
+ this.line("");
2155
+ this.line("// Verification options (optional)");
2156
+ this.line("// ─────────────────────");
2157
+ this.line("//");
2158
+ this.line("// Presets provide quick configuration:");
2159
+ this.line("// • 'quick': 1 minute timeout, 1 worker");
2160
+ this.line("// • 'balanced': 5 minutes timeout, 2 workers (default)");
2161
+ this.line("// • 'thorough': No timeout, 4 workers");
2162
+ this.line("//");
2163
+ this.line("// Or customize with verification options:");
2164
+ this.line("// verification: {");
2165
+ this.line("// timeout: 300, // Timeout in seconds (0 = no timeout)");
2166
+ this.line("// workers: 2, // Number of TLC workers");
2167
+ this.line("// }");
2168
+ this.line("//");
2169
+ this.line("// preset: 'balanced',");
2138
2170
  }
2139
2171
  formatTypeName(type) {
2140
2172
  let typeName;
@@ -2247,6 +2279,9 @@ class ConfigValidator {
2247
2279
  const lineNumber = source.substring(0, position).split(`
2248
2280
  `).length;
2249
2281
  const line = lines[lineNumber - 1];
2282
+ if (line?.trim().startsWith("//")) {
2283
+ continue;
2284
+ }
2250
2285
  const fieldMatch = line?.match(/"([^"]+)":\s*{/);
2251
2286
  const fieldName = fieldMatch ? fieldMatch[1] : "unknown";
2252
2287
  locations.push({
@@ -2256,21 +2291,23 @@ class ConfigValidator {
2256
2291
  context: fieldName ?? "unknown"
2257
2292
  });
2258
2293
  }
2259
- this.issues.push({
2260
- type: "incomplete",
2261
- severity: "error",
2262
- message: `Found ${matches.length} incomplete configuration marker(s)`,
2263
- suggestion: "Replace all /* CONFIGURE */ markers with actual values"
2264
- });
2265
- for (const loc of locations) {
2294
+ if (locations.length > 0) {
2266
2295
  this.issues.push({
2267
2296
  type: "incomplete",
2268
2297
  severity: "error",
2269
- field: loc.context,
2270
- location: { line: loc.line, column: loc.column },
2271
- message: `Incomplete configuration at line ${loc.line}`,
2272
- suggestion: `Fill in value for "${loc.context}"`
2298
+ message: `Found ${locations.length} incomplete configuration marker(s)`,
2299
+ suggestion: "Replace all /* CONFIGURE */ markers with actual values"
2273
2300
  });
2301
+ for (const loc of locations) {
2302
+ this.issues.push({
2303
+ type: "incomplete",
2304
+ severity: "error",
2305
+ field: loc.context,
2306
+ location: { line: loc.line, column: loc.column },
2307
+ message: `Incomplete configuration at line ${loc.line}`,
2308
+ suggestion: `Fill in value for "${loc.context}"`
2309
+ });
2310
+ }
2274
2311
  }
2275
2312
  }
2276
2313
  }
@@ -2278,12 +2315,23 @@ class ConfigValidator {
2278
2315
  const reviewRegex = /\/\*\s*REVIEW\s*\*\//g;
2279
2316
  const matches = [...source.matchAll(reviewRegex)];
2280
2317
  if (matches.length > 0) {
2281
- this.issues.push({
2282
- type: "incomplete",
2283
- severity: "warning",
2284
- message: `Found ${matches.length} value(s) that should be reviewed`,
2285
- suggestion: "Review auto-generated values marked with /* REVIEW */"
2318
+ const lines = source.split(`
2319
+ `);
2320
+ const validMatches = [...matches].filter((match) => {
2321
+ const position = match.index ?? 0;
2322
+ const lineNumber = source.substring(0, position).split(`
2323
+ `).length;
2324
+ const line = lines[lineNumber - 1];
2325
+ return !line?.trim().startsWith("//");
2286
2326
  });
2327
+ if (validMatches.length > 0) {
2328
+ this.issues.push({
2329
+ type: "incomplete",
2330
+ severity: "warning",
2331
+ message: `Found ${validMatches.length} value(s) that should be reviewed`,
2332
+ suggestion: "Review auto-generated values marked with /* REVIEW */"
2333
+ });
2334
+ }
2287
2335
  }
2288
2336
  }
2289
2337
  loadConfig(configPath) {
@@ -3072,7 +3120,7 @@ class HandlerExtractor {
3072
3120
  const index = indexExpr ? indexExpr.getText() : "0";
3073
3121
  const value = this.extractValue(right);
3074
3122
  if (value !== undefined) {
3075
- const tlaIndex = this.isNumericLiteral(index) ? (Number.parseInt(index) + 1).toString() : `${index} + 1`;
3123
+ const tlaIndex = this.isNumericLiteral(index) ? (Number.parseInt(index, 10) + 1).toString() : `${index} + 1`;
3076
3124
  assignments.push({
3077
3125
  field: `${field}[${tlaIndex}]`,
3078
3126
  value
@@ -4348,10 +4396,55 @@ async function verifyCommand() {
4348
4396
  console.log();
4349
4397
  try {
4350
4398
  await runFullVerification(configPath);
4351
- } catch (_error) {
4399
+ } catch (error) {
4400
+ console.error(color(`
4401
+ ❌ Verification error:`, COLORS.red));
4402
+ if (error instanceof Error) {
4403
+ console.error(color(error.message, COLORS.red));
4404
+ if (process.env.POLLY_DEBUG) {
4405
+ console.error(color(`
4406
+ Stack trace:`, COLORS.gray));
4407
+ console.error(error.stack);
4408
+ }
4409
+ } else {
4410
+ console.error(String(error));
4411
+ }
4412
+ console.error();
4352
4413
  process.exit(1);
4353
4414
  }
4354
4415
  }
4416
+ function getTimeout(config) {
4417
+ if (config.verification?.timeout !== undefined) {
4418
+ return config.verification.timeout;
4419
+ }
4420
+ const preset = config.preset || "balanced";
4421
+ switch (preset) {
4422
+ case "quick":
4423
+ return 60;
4424
+ case "balanced":
4425
+ return 300;
4426
+ case "thorough":
4427
+ return 0;
4428
+ default:
4429
+ return 300;
4430
+ }
4431
+ }
4432
+ function getWorkers(config) {
4433
+ if (config.verification?.workers !== undefined) {
4434
+ return config.verification.workers;
4435
+ }
4436
+ const preset = config.preset || "balanced";
4437
+ switch (preset) {
4438
+ case "quick":
4439
+ return 1;
4440
+ case "balanced":
4441
+ return 2;
4442
+ case "thorough":
4443
+ return 4;
4444
+ default:
4445
+ return 2;
4446
+ }
4447
+ }
4355
4448
  async function runFullVerification(configPath) {
4356
4449
  const config = await loadVerificationConfig(configPath);
4357
4450
  const analysis = await runCodebaseAnalysis();
@@ -4361,19 +4454,27 @@ async function runFullVerification(configPath) {
4361
4454
  console.log(color(` ${specPath}`, COLORS.gray));
4362
4455
  console.log();
4363
4456
  const docker = await setupDocker();
4457
+ const timeoutSeconds = getTimeout(config);
4458
+ const workers = getWorkers(config);
4364
4459
  console.log(color("⚙️ Running TLC model checker...", COLORS.blue));
4365
- console.log(color(" This may take a minute...", COLORS.gray));
4460
+ if (timeoutSeconds === 0) {
4461
+ console.log(color(" No timeout set - will run until completion", COLORS.gray));
4462
+ } else {
4463
+ const timeoutMinutes = Math.floor(timeoutSeconds / 60);
4464
+ const timeoutLabel = timeoutMinutes > 0 ? `${timeoutMinutes} minute${timeoutMinutes > 1 ? "s" : ""}` : `${timeoutSeconds} seconds`;
4465
+ console.log(color(` Timeout: ${timeoutLabel}`, COLORS.gray));
4466
+ }
4366
4467
  console.log();
4367
4468
  const result = await docker.runTLC(specPath, {
4368
- workers: 2,
4369
- timeout: 120000
4469
+ workers,
4470
+ timeout: timeoutSeconds > 0 ? timeoutSeconds * 1000 : undefined
4370
4471
  });
4371
4472
  displayVerificationResults(result, specDir);
4372
4473
  }
4373
4474
  async function loadVerificationConfig(configPath) {
4374
4475
  const resolvedPath = path4.resolve(configPath);
4375
4476
  const configModule = await import(`file://${resolvedPath}?t=${Date.now()}`);
4376
- return configModule.default;
4477
+ return configModule.verificationConfig || configModule.default;
4377
4478
  }
4378
4479
  async function runCodebaseAnalysis() {
4379
4480
  console.log(color("\uD83D\uDCCA Analyzing codebase...", COLORS.blue));
@@ -4547,4 +4648,4 @@ main().catch((error) => {
4547
4648
  process.exit(1);
4548
4649
  });
4549
4650
 
4550
- //# debugId=6EFAE591D90C88BD64756E2164756E21
4651
+ //# debugId=487C3279544257BF64756E2164756E21