codehere 0.3.0-rc.2 → 0.3.0-rc.27

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.
package/dist/ui.js CHANGED
@@ -326,9 +326,6 @@ export function createSessionWelcome() {
326
326
  const padding = Math.max(0, width - contentVisual - 4);
327
327
  return borderColor('│ ') + content + ' '.repeat(padding) + borderColor(' │\n');
328
328
  };
329
- // Calculate visual lengths (without ANSI codes)
330
- const logoVisual = visualLength(logo);
331
- const versionVisual = visualLength(version);
332
329
  let welcomeBox = '';
333
330
  welcomeBox += borderColor('┌' + '─'.repeat(width - 2) + '┐\n');
334
331
  // Header line with logo and version
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Typo guard for the bare `codehere <word>` action.
3
+ *
4
+ * Why this exists: codehere's bare action treats any string as a one-shot task
5
+ * prompt for the Conductor. Without a guard, a typo like `codehere helpp`
6
+ * silently spawns a Claude task to interpret "helpp" as a question, burning
7
+ * API tokens for what was clearly meant to be `codehere help`.
8
+ *
9
+ * Earlier rc.15 attempt (greedy edit-check + prefix match) over-matched and
10
+ * blocked legitimate single-word prompts like "task-runner" or "h". Codex
11
+ * caught the regression in review. This rc.16 version uses real Levenshtein,
12
+ * a length floor, and explicit kebab-case exemption.
13
+ */
14
+ /** Standard Levenshtein distance. Bounded inputs only — no allocation guard. */
15
+ export function levenshtein(a, b) {
16
+ const m = a.length;
17
+ const n = b.length;
18
+ if (m === 0)
19
+ return n;
20
+ if (n === 0)
21
+ return m;
22
+ const dp = new Array(n + 1);
23
+ for (let j = 0; j <= n; j++)
24
+ dp[j] = j;
25
+ for (let i = 1; i <= m; i++) {
26
+ let prev = dp[0];
27
+ dp[0] = i;
28
+ for (let j = 1; j <= n; j++) {
29
+ const tmp = dp[j];
30
+ dp[j] = a[i - 1] === b[j - 1] ? prev : Math.min(prev, dp[j], dp[j - 1]) + 1;
31
+ prev = tmp;
32
+ }
33
+ }
34
+ return dp[n];
35
+ }
36
+ /**
37
+ * Decide whether a bare-action input should be treated as a typo of a known
38
+ * subcommand. Returns the suggestions if it should block; null if it should
39
+ * fall through to the task spawner.
40
+ *
41
+ * Heuristics (intentionally narrow — false positives are worse than false negatives):
42
+ * - Single token (no whitespace), 4–14 chars (excludes "h", "go", etc.)
43
+ * - Pure alphabetic, no hyphens (kebab-case is a likely real prompt)
44
+ * - True Levenshtein distance ≤ 2 to a known command
45
+ * - Distance must be < input length (avoid 2-char words matching anything)
46
+ * - Returns up to 3 closest commands ranked by ascending distance
47
+ */
48
+ export function checkTypo(input, knownCommands) {
49
+ if (/\s/.test(input))
50
+ return null;
51
+ if (input.length < 4 || input.length > 14)
52
+ return null;
53
+ if (!/^[a-z]+$/i.test(input))
54
+ return null;
55
+ const lower = input.toLowerCase();
56
+ // Defensively normalize knownCommands to lowercase too — Codex rc.16 review
57
+ // flagged this for symmetry. Currently every Commander subcommand is lower
58
+ // already, but a future addition that registers an uppercase name shouldn't
59
+ // silently slip through the equality check.
60
+ const knownLower = knownCommands.map((n) => n.toLowerCase());
61
+ if (knownLower.includes(lower))
62
+ return null;
63
+ // Length-prefilter cheap reject before computing DP — same outcome, less work.
64
+ const scored = knownLower
65
+ .filter((n) => Math.abs(n.length - lower.length) <= 2)
66
+ .map((n) => ({ n, d: levenshtein(lower, n) }))
67
+ .filter((s) => s.d > 0 && s.d <= 2 && s.d < lower.length)
68
+ // Deterministic tie-breaker (alphabetical) so ranking is stable across runs.
69
+ .sort((a, b) => (a.d - b.d) || a.n.localeCompare(b.n))
70
+ .slice(0, 3);
71
+ return scored.length > 0 ? scored.map((s) => s.n) : null;
72
+ }
73
+ //# sourceMappingURL=typo-guard.js.map
@@ -29,7 +29,7 @@ export function getVersion() {
29
29
  return version;
30
30
  }
31
31
  }
32
- catch (error) {
32
+ catch {
33
33
  // Fallback if can't read package.json
34
34
  console.warn('Warning: Could not read version from package.json, using fallback');
35
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codehere",
3
- "version": "0.3.0-rc.2",
3
+ "version": "0.3.0-rc.27",
4
4
  "description": "A PM for your AI coding agents. Delegate, orchestrate, and audit Claude Code, Codex, Aider, and OpenCode from one local web UI — every AI action traced, every file scored.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",