@whisperr/wizard 0.1.12 → 0.1.13

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 (2) hide show
  1. package/dist/index.js +82 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -73,7 +73,7 @@ var systemPrompt = `
73
73
  This SDK is published on pub.dev. Integrate it as follows.
74
74
 
75
75
  1) Dependency. Add to pubspec.yaml under dependencies:
76
- whisperr: ^0.2.0
76
+ whisperr: ^0.2.2
77
77
  Then the SDK expects \`flutter pub get\` to be run (run it via bash).
78
78
 
79
79
  2) Initialize once, early, before runApp(), in lib/main.dart:
@@ -1539,6 +1539,51 @@ async function pollFirstEvent(config, session, opts = {}) {
1539
1539
  return { received: false };
1540
1540
  }
1541
1541
 
1542
+ // src/core/postflight.ts
1543
+ import { spawn as spawn2 } from "child_process";
1544
+ var MAX_OUTPUT = 4e3;
1545
+ var DEFAULT_TIMEOUT_MS = 18e4;
1546
+ function runVerifyCommand(repoPath, command, opts = {}) {
1547
+ if (!command || !command.trim()) {
1548
+ return Promise.resolve({ ran: false, ok: true, output: "" });
1549
+ }
1550
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1551
+ return new Promise((resolve2) => {
1552
+ const child = spawn2(command, { cwd: repoPath, shell: true, env: process.env });
1553
+ let out = "";
1554
+ const append = (d) => {
1555
+ out += d.toString();
1556
+ if (out.length > MAX_OUTPUT * 4) out = out.slice(-MAX_OUTPUT * 2);
1557
+ };
1558
+ child.stdout?.on("data", append);
1559
+ child.stderr?.on("data", append);
1560
+ const timer = setTimeout(() => {
1561
+ child.kill("SIGKILL");
1562
+ resolve2({ ran: true, ok: false, command, output: tail(out), timedOut: true });
1563
+ }, timeoutMs);
1564
+ child.on("close", (code) => {
1565
+ clearTimeout(timer);
1566
+ resolve2({
1567
+ ran: true,
1568
+ ok: code === 0,
1569
+ command,
1570
+ exitCode: code,
1571
+ output: tail(out),
1572
+ // 127 = "command not found": the verify tool isn't on PATH here.
1573
+ toolMissing: code === 127
1574
+ });
1575
+ });
1576
+ child.on("error", () => {
1577
+ clearTimeout(timer);
1578
+ resolve2({ ran: true, ok: false, command, output: tail(out), toolMissing: true });
1579
+ });
1580
+ });
1581
+ }
1582
+ function tail(s) {
1583
+ const t = s.trim();
1584
+ return t.length > MAX_OUTPUT ? `\u2026${t.slice(-MAX_OUTPUT)}` : t;
1585
+ }
1586
+
1542
1587
  // src/core/report.ts
1543
1588
  async function postRunReport(config, session, report) {
1544
1589
  if (config.offline) return;
@@ -1705,6 +1750,40 @@ Flutter is live today; ${theme.bright(
1705
1750
  return 1;
1706
1751
  }
1707
1752
  }
1753
+ let verified = null;
1754
+ if (chosen.playbook.verifyCommand && files.length) {
1755
+ const cmd = chosen.playbook.verifyCommand;
1756
+ const vspin = p.spinner();
1757
+ vspin.start(`Verifying the integration \u2014 ${theme.muted(cmd)}`);
1758
+ const verdict = await runVerifyCommand(repoPath, cmd);
1759
+ if (verdict.toolMissing) {
1760
+ vspin.stop(
1761
+ theme.warn("Couldn't verify automatically") + theme.muted(` \u2014 \`${cmd}\` isn't available here. Run it yourself before committing.`)
1762
+ );
1763
+ } else if (verdict.timedOut) {
1764
+ vspin.stop(
1765
+ theme.warn(`Verification timed out \u2014 \`${cmd}\``) + theme.muted(" \u2014 run it yourself before committing.")
1766
+ );
1767
+ } else if (verdict.ok) {
1768
+ verified = true;
1769
+ vspin.stop(theme.success("Verified \u2713") + theme.muted(` (${cmd})`));
1770
+ } else {
1771
+ verified = false;
1772
+ vspin.stop(theme.alert(`Verification failed \u2014 ${cmd}`));
1773
+ if (verdict.output) {
1774
+ p.note(verdict.output, theme.warn("Verifier output"));
1775
+ }
1776
+ const reverted = await maybeRevert(
1777
+ repoPath,
1778
+ checkpoint,
1779
+ "The integration didn't pass its build/lint check, so the edits may be broken."
1780
+ );
1781
+ if (reverted) {
1782
+ p.outro(theme.muted("Reverted \u2014 nothing was left in your working tree."));
1783
+ return 1;
1784
+ }
1785
+ }
1786
+ }
1708
1787
  const wiredMap = await scanWiredEvents(
1709
1788
  repoPath,
1710
1789
  files,
@@ -1719,6 +1798,7 @@ Flutter is live today; ${theme.bright(
1719
1798
  target: chosen.playbook.target.id,
1720
1799
  repo_fingerprint: fingerprint,
1721
1800
  identify_wired: outcome.coreOk,
1801
+ verified,
1722
1802
  cost_usd: outcome.costUsd,
1723
1803
  duration_ms: outcome.durationMs,
1724
1804
  summary: outcome.summary.slice(0, 4e3),
@@ -1726,7 +1806,7 @@ Flutter is live today; ${theme.bright(
1726
1806
  });
1727
1807
  p.log.info(
1728
1808
  theme.muted(
1729
- `${wiredMap.size}/${manifest.events.length} events wired \xB7 ${files.length} file${files.length === 1 ? "" : "s"} changed \xB7 ${Math.round(outcome.durationMs / 1e3)}s`
1809
+ `${wiredMap.size}/${manifest.events.length} events wired \xB7 ${files.length} file${files.length === 1 ? "" : "s"} changed \xB7 ` + (verified === true ? "verified \xB7 " : verified === false ? "unverified \xB7 " : "") + `${Math.round(outcome.durationMs / 1e3)}s`
1730
1810
  )
1731
1811
  );
1732
1812
  if (!config.offline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whisperr/wizard",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "Whisperr Wizard — one command to integrate the Whisperr SDK into your app. Authenticates with your onboarded account and uses an AI coding agent to wire up identify() and your business events automatically.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,