@aayambansal/squint 0.2.5 → 0.2.6

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.
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  findChrome,
4
4
  screenshot
5
- } from "./chunk-CJXYSQNB.js";
6
- import "./chunk-CH4GNJCZ.js";
5
+ } from "./chunk-B7LOERSP.js";
6
+ import "./chunk-BWZFACBT.js";
7
7
  export {
8
8
  findChrome,
9
9
  screenshot
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  variantsRoot
4
- } from "./chunk-XLNTTZX4.js";
4
+ } from "./chunk-LVA2OQSR.js";
5
5
  import {
6
6
  findChrome,
7
7
  screenshot
8
- } from "./chunk-CJXYSQNB.js";
8
+ } from "./chunk-B7LOERSP.js";
9
9
  import {
10
10
  lineSplitter
11
- } from "./chunk-CH4GNJCZ.js";
11
+ } from "./chunk-BWZFACBT.js";
12
12
 
13
13
  // src/variants/shots.ts
14
14
  import path2 from "path";
@@ -79,12 +79,19 @@ var DevServer = class {
79
79
  callbacks;
80
80
  child = null;
81
81
  lines = [];
82
+ lastCommand = null;
83
+ restarts = 0;
82
84
  state = "stopped";
83
85
  url = null;
84
86
  start(command) {
87
+ this.restarts = 0;
88
+ return this.launch(command);
89
+ }
90
+ launch(command) {
85
91
  if (this.child) return true;
86
92
  const cmd = command ?? detectDevCommand(this.cwd);
87
93
  if (!cmd) return false;
94
+ this.lastCommand = cmd;
88
95
  this.setState("starting");
89
96
  this.lines = [];
90
97
  this.url = null;
@@ -118,7 +125,14 @@ var DevServer = class {
118
125
  });
119
126
  child.on("close", () => {
120
127
  this.child = null;
121
- if (this.state !== "stopped") this.setState("crashed");
128
+ if (this.state === "stopped") return;
129
+ this.setState("crashed");
130
+ if (this.restarts < 1 && this.lastCommand) {
131
+ this.restarts += 1;
132
+ setTimeout(() => {
133
+ if (this.state === "crashed") this.launch(this.lastCommand);
134
+ }, 1e3);
135
+ }
122
136
  });
123
137
  return true;
124
138
  }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  findBinary
4
- } from "./chunk-CH4GNJCZ.js";
4
+ } from "./chunk-BWZFACBT.js";
5
5
 
6
6
  // src/preview/chrome.ts
7
7
  import { spawn } from "child_process";
@@ -1,5 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/engines/registry.ts
4
+ import fs from "fs";
5
+ import path from "path";
6
+
7
+ // src/engines/aider.ts
8
+ var aider = {
9
+ id: "aider",
10
+ name: "Aider",
11
+ binary: "aider",
12
+ install: "python -m pip install aider-install && aider-install",
13
+ supportsResume: false,
14
+ buildArgs(opts) {
15
+ const args = ["--message", opts.prompt, "--yes-always", "--no-auto-commits"];
16
+ if (opts.mode === "plan") args.push("--dry-run");
17
+ if (opts.model) args.push("--model", opts.model);
18
+ return args;
19
+ }
20
+ };
21
+
3
22
  // src/util/stream.ts
4
23
  function lineSplitter(onLine) {
5
24
  let buffer = "";
@@ -24,25 +43,6 @@ function truncate(text, max) {
24
43
  return text.slice(0, max - 1) + "\u2026";
25
44
  }
26
45
 
27
- // src/engines/registry.ts
28
- import fs from "fs";
29
- import path from "path";
30
-
31
- // src/engines/aider.ts
32
- var aider = {
33
- id: "aider",
34
- name: "Aider",
35
- binary: "aider",
36
- install: "python -m pip install aider-install && aider-install",
37
- supportsResume: false,
38
- buildArgs(opts) {
39
- const args = ["--message", opts.prompt, "--yes-always", "--no-auto-commits"];
40
- if (opts.mode === "plan") args.push("--dry-run");
41
- if (opts.model) args.push("--model", opts.model);
42
- return args;
43
- }
44
- };
45
-
46
46
  // src/engines/claudeProtocol.ts
47
47
  function createClaudeStreamParser(readyLabel) {
48
48
  let sawTextDelta = false;
@@ -300,9 +300,48 @@ var gemini = {
300
300
  supportsResume: false,
301
301
  buildArgs(opts) {
302
302
  const approval = opts.mode === "plan" ? "plan" : opts.mode === "yolo" ? "yolo" : "auto_edit";
303
- const args = ["-p", opts.prompt, "--approval-mode", approval];
303
+ const args = ["-p", opts.prompt, "--output-format", "stream-json", "--approval-mode", approval];
304
304
  if (opts.model) args.push("-m", opts.model);
305
305
  return args;
306
+ },
307
+ createParser() {
308
+ return (line) => {
309
+ let data;
310
+ try {
311
+ data = JSON.parse(line);
312
+ } catch {
313
+ return [{ type: "text", text: line }];
314
+ }
315
+ switch (data?.type) {
316
+ case "init":
317
+ return [{ type: "status", text: `gemini ready${data.model ? ` \xB7 ${data.model}` : ""}` }];
318
+ case "message": {
319
+ if (data.role && data.role !== "assistant" && data.role !== "model") return [];
320
+ const text = data.content ?? data.text ?? data.delta;
321
+ return typeof text === "string" && text.length > 0 ? [{ type: "text", text }] : [];
322
+ }
323
+ case "tool_use": {
324
+ const name = data.name ?? data.tool_name ?? "tool";
325
+ const input = data.args ?? data.input;
326
+ const detail = input && typeof input === "object" ? truncate(JSON.stringify(input), 80) : void 0;
327
+ return [{ type: "tool", name, detail }];
328
+ }
329
+ case "tool_result":
330
+ return [];
331
+ case "error":
332
+ return data.fatal === false ? [] : [{ type: "error", text: data.message ?? "gemini error" }];
333
+ case "result":
334
+ return [
335
+ {
336
+ type: "result",
337
+ ok: !data.error,
338
+ summary: typeof data.response === "string" ? data.response : void 0
339
+ }
340
+ ];
341
+ default:
342
+ return [{ type: "raw", data }];
343
+ }
344
+ };
306
345
  }
307
346
  };
308
347
 
@@ -402,6 +441,7 @@ function detectEngines() {
402
441
  export {
403
442
  lineSplitter,
404
443
  truncate,
444
+ engines,
405
445
  getEngine,
406
446
  findBinary,
407
447
  findEngineBinary,
@@ -3,7 +3,7 @@ import {
3
3
  findEngineBinary,
4
4
  lineSplitter,
5
5
  truncate
6
- } from "./chunk-CH4GNJCZ.js";
6
+ } from "./chunk-BWZFACBT.js";
7
7
 
8
8
  // src/runner/run.ts
9
9
  import { spawn } from "child_process";
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-P3H4N2EN.js";
7
7
  import {
8
8
  runAgent
9
- } from "./chunk-TI2R7QRL.js";
9
+ } from "./chunk-C7WKNJG6.js";
10
10
 
11
11
  // src/variants/variants.ts
12
12
  import { execFileSync } from "child_process";
@@ -14,6 +14,7 @@ var COMMANDS = [
14
14
  { name: "restore", args: "<n>", description: "rewind files to before ask n" },
15
15
  { name: "mode", args: "plan|safe|yolo", description: "how much the engine may do (shift+tab cycles)" },
16
16
  { name: "engine", args: "<id>", description: "switch backend (new session)" },
17
+ { name: "engines", description: "list installed engines with streaming/resume support" },
17
18
  { name: "model", args: "[name]", description: "model override for the engine" },
18
19
  { name: "theme", args: "[name]", description: "switch the TUI theme", viewLevel: true },
19
20
  { name: "copy", description: "copy the last reply to the clipboard" },
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  findChrome,
8
8
  screenshot
9
- } from "./chunk-CJXYSQNB.js";
9
+ } from "./chunk-B7LOERSP.js";
10
10
 
11
11
  // src/preview/preview.ts
12
12
  import fs2 from "fs";
package/dist/cli.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ enrich
4
+ } from "./chunk-4LAU5TGK.js";
2
5
  import {
3
6
  diffStatSince,
4
7
  isGitRepo,
@@ -10,22 +13,22 @@ import {
10
13
  buildFixPrompt,
11
14
  detectDevCommand,
12
15
  screenshotVariants
13
- } from "./chunk-QNNT6FP4.js";
16
+ } from "./chunk-43L4QXCM.js";
14
17
  import {
15
18
  applyVariant,
16
19
  cleanVariants,
17
20
  listVariants,
18
21
  runVariants
19
- } from "./chunk-XLNTTZX4.js";
22
+ } from "./chunk-LVA2OQSR.js";
20
23
  import {
21
24
  composePrompt
22
25
  } from "./chunk-P3H4N2EN.js";
23
26
  import {
24
27
  runAgent
25
- } from "./chunk-TI2R7QRL.js";
28
+ } from "./chunk-C7WKNJG6.js";
26
29
  import {
27
30
  completeCommand
28
- } from "./chunk-EECGXFRX.js";
31
+ } from "./chunk-V3M4WQLH.js";
29
32
  import {
30
33
  buildGatePrompt,
31
34
  detectFastGates,
@@ -42,18 +45,15 @@ import {
42
45
  probeRuntime,
43
46
  runtimeSummary,
44
47
  saveState
45
- } from "./chunk-DKQ5KJD7.js";
48
+ } from "./chunk-YZEFBPBJ.js";
46
49
  import "./chunk-OC6RU6XH.js";
47
50
  import {
48
51
  findChrome
49
- } from "./chunk-CJXYSQNB.js";
52
+ } from "./chunk-B7LOERSP.js";
50
53
  import {
51
54
  detectEngines,
52
55
  getEngine
53
- } from "./chunk-CH4GNJCZ.js";
54
- import {
55
- enrich
56
- } from "./chunk-4LAU5TGK.js";
56
+ } from "./chunk-BWZFACBT.js";
57
57
 
58
58
  // src/cli.tsx
59
59
  import { Command } from "commander";
@@ -652,9 +652,21 @@ They are objective defects, not style preferences.`
652
652
  const [name, ...rest] = commandLine.slice(1).split(/\s+/);
653
653
  const arg = rest.join(" ").trim();
654
654
  switch (name) {
655
+ case "engines": {
656
+ void import("./registry-S3PCXJVF.js").then(({ detectEngines: detectEngines2 }) => {
657
+ const lines = detectEngines2().map(({ engine, path: binaryPath }) => {
658
+ const mark = binaryPath ? "\u2713" : "\u2717";
659
+ const traits = [engine.createParser ? "stream" : "text", engine.supportsResume ? "resume" : null].filter(Boolean).join(" \xB7 ");
660
+ return `${mark} ${engine.id} \u2014 ${traits}${binaryPath ? "" : ` \xB7 install: ${engine.install}`}`;
661
+ });
662
+ this.push("status", `${lines.join("\n")}
663
+ /engine <id> switches (new session)`);
664
+ });
665
+ break;
666
+ }
655
667
  case "engine":
656
668
  if (!arg) {
657
- this.push("status", "usage: /engine <id> \u2014 see squint engines");
669
+ this.command("/engines");
658
670
  } else {
659
671
  try {
660
672
  getEngine(arg);
@@ -933,7 +945,7 @@ They are objective defects, not style preferences.`
933
945
  this.notify({ items: [], totals: { costUsd: 0, turns: 0 } });
934
946
  break;
935
947
  case "help": {
936
- void import("./commands-6XDXUVO6.js").then(({ commandHelp }) => this.push("status", commandHelp()));
948
+ void import("./commands-7DTZB4JE.js").then(({ commandHelp }) => this.push("status", commandHelp()));
937
949
  break;
938
950
  }
939
951
  case "quit":
@@ -1482,7 +1494,7 @@ function App({
1482
1494
 
1483
1495
  // src/cli.tsx
1484
1496
  import { jsx as jsx4 } from "react/jsx-runtime";
1485
- var VERSION = "0.2.5";
1497
+ var VERSION = "0.2.6";
1486
1498
  var program = new Command();
1487
1499
  program.name("squint").description("Lovable for your terminal \u2014 a frontend harness on top of Claude Code, Codex, and friends.").version(VERSION);
1488
1500
  program.command("run").description("Run one prompt headlessly and stream the result").argument("<prompt...>", "what to build or change").option("-e, --engine <id>", "engine to use (see squint engines)").option("-m, --model <name>", "model override for the engine").option("--mode <mode>", "plan (read-only) \xB7 safe (default) \xB7 yolo (no friction)").option("--no-brief", "send the prompt without the squint design brief").option("--json", "emit normalized agent events as ndjson").action(
@@ -1516,12 +1528,18 @@ program.command("run").description("Run one prompt headlessly and stream the res
1516
1528
  if (!result.ok) process.exitCode = 1;
1517
1529
  }
1518
1530
  );
1519
- program.command("engines").description("List engines and whether they are installed").action(() => {
1531
+ program.command("engines").description("List engines: installed, streaming, session resume").action(() => {
1532
+ console.log(pc.dim(" id name stream resume where"));
1520
1533
  for (const { engine, path: binaryPath } of detectEngines()) {
1521
1534
  const status = binaryPath ? pc.green("\u2713") : pc.red("\u2717");
1535
+ const stream = engine.createParser ? pc.green("yes") : pc.dim("text");
1536
+ const resume = engine.supportsResume ? pc.green("yes") : pc.dim("no");
1522
1537
  const location = binaryPath ?? pc.dim(`not found \u2014 ${engine.install}`);
1523
- console.log(`${status} ${engine.id.padEnd(10)} ${engine.name.padEnd(14)} ${location}`);
1538
+ console.log(
1539
+ `${status} ${engine.id.padEnd(10)} ${engine.name.padEnd(14)} ${stream.padEnd(15)} ${resume.padEnd(14)} ${location}`
1540
+ );
1524
1541
  }
1542
+ console.log(pc.dim("\nplan/safe/yolo modes map onto every engine \xB7 squint doctor --probe verifies auth"));
1525
1543
  });
1526
1544
  program.command("doctor").description("Check squint prerequisites and engine availability").option("--probe", "run each detected engine with a one-word prompt to verify auth works").action(async (options) => {
1527
1545
  const [major] = process.versions.node.split(".");
@@ -1533,7 +1551,7 @@ program.command("doctor").description("Check squint prerequisites and engine ava
1533
1551
  console.log(`${status} ${engine.name}${binaryPath ? "" : pc.dim(` \u2014 install: ${engine.install}`)}`);
1534
1552
  }
1535
1553
  if (options.probe) {
1536
- const { runAgent: runAgent2 } = await import("./run-TIGEZHMQ.js");
1554
+ const { runAgent: runAgent2 } = await import("./run-S772BPMZ.js");
1537
1555
  console.log(pc.dim("\nprobing engines with a one-word prompt (verifies auth end to end)\u2026"));
1538
1556
  for (const { engine, path: binaryPath } of detected) {
1539
1557
  if (!binaryPath) continue;
@@ -1555,7 +1573,7 @@ program.command("doctor").description("Check squint prerequisites and engine ava
1555
1573
  );
1556
1574
  }
1557
1575
  }
1558
- const { findChrome: findChrome2 } = await import("./chrome-RV25VKUA.js");
1576
+ const { findChrome: findChrome2 } = await import("./chrome-NVU47PLK.js");
1559
1577
  const { hasWebSocket } = await import("./cdp-SFWNP7OA.js");
1560
1578
  const chrome = findChrome2();
1561
1579
  console.log(
@@ -1682,7 +1700,7 @@ variantsCommand.command("gen").description("Generate n variants of one ask in pa
1682
1700
  process.exitCode = 1;
1683
1701
  return;
1684
1702
  }
1685
- const { runVariants: runVariants2, cleanVariants: cleanVariants2 } = await import("./variants-SM6NRX4U.js");
1703
+ const { runVariants: runVariants2, cleanVariants: cleanVariants2 } = await import("./variants-2IM274AL.js");
1686
1704
  const config = loadConfig(defaultPaths(cwd));
1687
1705
  const engineId = resolveEngineId(config, options.engine);
1688
1706
  const engine = getEngine(engineId);
@@ -1700,7 +1718,7 @@ variantsCommand.command("gen").description("Generate n variants of one ask in pa
1700
1718
  );
1701
1719
  const succeeded = runs.filter((r) => r.result.ok);
1702
1720
  if (options.shots && succeeded.length > 0) {
1703
- const { screenshotVariants: screenshotVariants2 } = await import("./shots-X3I6MRLX.js");
1721
+ const { screenshotVariants: screenshotVariants2 } = await import("./shots-J7JG2FC4.js");
1704
1722
  console.log(pc.dim("capturing screenshots\u2026"));
1705
1723
  const shots = await screenshotVariants2(cwd, succeeded.map((r) => r.variant));
1706
1724
  for (const shot of shots) {
@@ -1715,7 +1733,7 @@ ${succeeded.length}/${runs.length} variants ready in .squint/variants/ \u2014 `
1715
1733
  }
1716
1734
  );
1717
1735
  variantsCommand.command("list").description("List generated variants").action(async () => {
1718
- const { listVariants: listVariants2 } = await import("./variants-SM6NRX4U.js");
1736
+ const { listVariants: listVariants2 } = await import("./variants-2IM274AL.js");
1719
1737
  const ids = listVariants2(process.cwd());
1720
1738
  if (ids.length === 0) {
1721
1739
  console.log(pc.dim('no variants \u2014 squint variants gen <n> "<ask>"'));
@@ -1724,7 +1742,7 @@ variantsCommand.command("list").description("List generated variants").action(as
1724
1742
  for (const id of ids) console.log(id);
1725
1743
  });
1726
1744
  variantsCommand.command("apply").description("Apply one variant\u2019s changes to the main tree and discard the rest").argument("<id>", "family id of the winning variant").action(async (id) => {
1727
- const { applyVariant: applyVariant2, cleanVariants: cleanVariants2 } = await import("./variants-SM6NRX4U.js");
1745
+ const { applyVariant: applyVariant2, cleanVariants: cleanVariants2 } = await import("./variants-2IM274AL.js");
1728
1746
  const cwd = process.cwd();
1729
1747
  const result = applyVariant2(cwd, id);
1730
1748
  if (!result.ok) {
@@ -1736,7 +1754,7 @@ variantsCommand.command("apply").description("Apply one variant\u2019s changes t
1736
1754
  console.log(pc.green(`\u2713 applied ${id} to the working tree`) + pc.dim(" \u2014 review with git diff"));
1737
1755
  });
1738
1756
  variantsCommand.command("clean").description("Discard all variants").action(async () => {
1739
- const { cleanVariants: cleanVariants2 } = await import("./variants-SM6NRX4U.js");
1757
+ const { cleanVariants: cleanVariants2 } = await import("./variants-2IM274AL.js");
1740
1758
  const count = cleanVariants2(process.cwd());
1741
1759
  console.log(pc.dim(`removed ${count} variant(s)`));
1742
1760
  });
@@ -1786,7 +1804,7 @@ program.command("check").description("Run this project\u2019s quality gates (typ
1786
1804
  if (results.some((r) => !r.ok)) process.exitCode = 1;
1787
1805
  });
1788
1806
  program.command("shot").description("Screenshot a running app at mobile/tablet/desktop viewports").argument("<url>", "URL of the running app (e.g. http://localhost:5173)").action(async (url) => {
1789
- const { captureViewports: captureViewports2 } = await import("./preview-ZHUQT7TJ.js");
1807
+ const { captureViewports: captureViewports2 } = await import("./preview-UCH7H5R5.js");
1790
1808
  const result = await captureViewports2(process.cwd(), url);
1791
1809
  if (!result) {
1792
1810
  console.error(pc.red("\u2717 no Chrome/Chromium found"));
@@ -3,7 +3,7 @@ import {
3
3
  COMMANDS,
4
4
  commandHelp,
5
5
  completeCommand
6
- } from "./chunk-EECGXFRX.js";
6
+ } from "./chunk-V3M4WQLH.js";
7
7
  export {
8
8
  COMMANDS,
9
9
  commandHelp,
@@ -10,10 +10,10 @@ import {
10
10
  probeRuntime,
11
11
  routeShotName,
12
12
  runtimeSummary
13
- } from "./chunk-DKQ5KJD7.js";
13
+ } from "./chunk-YZEFBPBJ.js";
14
14
  import "./chunk-OC6RU6XH.js";
15
- import "./chunk-CJXYSQNB.js";
16
- import "./chunk-CH4GNJCZ.js";
15
+ import "./chunk-B7LOERSP.js";
16
+ import "./chunk-BWZFACBT.js";
17
17
  export {
18
18
  VIEWPORTS,
19
19
  buildReviewPrompt,
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ detectEngines,
4
+ engines,
5
+ findBinary,
6
+ findEngineBinary,
7
+ getEngine
8
+ } from "./chunk-BWZFACBT.js";
9
+ export {
10
+ detectEngines,
11
+ engines,
12
+ findBinary,
13
+ findEngineBinary,
14
+ getEngine
15
+ };
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runAgent
4
- } from "./chunk-TI2R7QRL.js";
5
- import "./chunk-CH4GNJCZ.js";
4
+ } from "./chunk-C7WKNJG6.js";
5
+ import "./chunk-BWZFACBT.js";
6
6
  export {
7
7
  runAgent
8
8
  };
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ screenshotVariants
4
+ } from "./chunk-43L4QXCM.js";
5
+ import "./chunk-LVA2OQSR.js";
6
+ import "./chunk-P3H4N2EN.js";
7
+ import "./chunk-C7WKNJG6.js";
8
+ import "./chunk-B7LOERSP.js";
9
+ import "./chunk-BWZFACBT.js";
10
+ export {
11
+ screenshotVariants
12
+ };
@@ -9,10 +9,10 @@ import {
9
9
  runVariants,
10
10
  variantPrompt,
11
11
  variantsRoot
12
- } from "./chunk-XLNTTZX4.js";
12
+ } from "./chunk-LVA2OQSR.js";
13
13
  import "./chunk-P3H4N2EN.js";
14
- import "./chunk-TI2R7QRL.js";
15
- import "./chunk-CH4GNJCZ.js";
14
+ import "./chunk-C7WKNJG6.js";
15
+ import "./chunk-BWZFACBT.js";
16
16
  export {
17
17
  MAX_VARIANTS,
18
18
  applyVariant,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aayambansal/squint",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Lovable for your terminal — a frontend harness on top of Claude Code, Codex, and other coding agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- screenshotVariants
4
- } from "./chunk-QNNT6FP4.js";
5
- import "./chunk-XLNTTZX4.js";
6
- import "./chunk-P3H4N2EN.js";
7
- import "./chunk-TI2R7QRL.js";
8
- import "./chunk-CJXYSQNB.js";
9
- import "./chunk-CH4GNJCZ.js";
10
- export {
11
- screenshotVariants
12
- };