loom-agent 1.2.8 → 1.2.9

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/bin/loom-tui.js CHANGED
@@ -26,7 +26,7 @@ function findBun() {
26
26
  return null;
27
27
  }
28
28
 
29
- const entry = path.join(__dirname, '..', 'src', 'tui-bootstrap.js');
29
+ const entry = path.join(__dirname, '..', 'src', 'tui-open.tsx');
30
30
  // Start bun from the package root so it discovers our bunfig.toml/tsconfig.json
31
31
  // (Solid JSX preloader); the user's real cwd rides along in LOOM_START_CWD and
32
32
  // is restored by the bootstrap shim before app code runs.
@@ -39,7 +39,7 @@ if (bun) {
39
39
  // Pin Solid to its CLIENT build: from this spawn context bun can resolve
40
40
  // solid-js under the "node" export condition (= SSR build, renders one
41
41
  // static frame then ignores all signal updates -> frozen splash).
42
- const result = spawnSync(bun, ['--conditions=browser', 'run', entry, ...process.argv.slice(2)], {
42
+ const result = spawnSync(bun, ['run', entry, ...process.argv.slice(2)], {
43
43
  stdio: 'inherit',
44
44
  cwd: pkgRoot,
45
45
  env: process.env,
package/bunfig.toml CHANGED
@@ -1 +1 @@
1
- preload = ["@opentui/solid/preload"]
1
+ preload = ["@opentui/solid/preload", "./src/tui-preload.js"]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loom-agent",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/toshalkumbhar8979-design/loomcode.git"
package/src/core/cli.js CHANGED
@@ -557,7 +557,7 @@ if (args.includes('--help') || args.includes('-h')) {
557
557
  if (canRaw) {
558
558
  // Launch new OpenTUI TUI via bun
559
559
  const bunPath = findBun();
560
- const tuiEntry = path.join(__dirname, '..', 'tui-bootstrap.js');
560
+ const tuiEntry = path.join(__dirname, '..', 'tui-open.tsx');
561
561
  if (bunPath && fs.existsSync(tuiEntry)) {
562
562
  const { spawnSync } = require('child_process');
563
563
  // Start bun from the package root so it discovers bunfig.toml /
@@ -569,7 +569,7 @@ if (args.includes('--help') || args.includes('-h')) {
569
569
  // --conditions=browser pins Solid to its client build (see
570
570
  // bin/loom-tui.js) — without it the SSR build loads and the TUI
571
571
  // renders one static frame then never updates.
572
- const tuiArgs = ['--conditions=browser', tuiEntry];
572
+ const tuiArgs = [tuiEntry];
573
573
  if (sessionId) tuiArgs.push('-s', sessionId);
574
574
  if (autoMode) tuiArgs.push('--auto');
575
575
  const prompt = promptArgs.join(' ');
package/src/tui/App.tsx CHANGED
@@ -1506,7 +1506,7 @@ export function App(props: { initialPrompt?: string; resumeSession?: string; aut
1506
1506
  _skillDoneOff = on("turn:end", function(d: any) {
1507
1507
  if (d?.skills?.length) showToast("skill handled: " + d.skills.join(", "), "ok");
1508
1508
  });
1509
- (globalThis as any).__loomTrace("onMount-done", new Error("mount complete"));
1509
+ (globalThis as any).__loomTrace?.("onMount-done", new Error("mount complete"));
1510
1510
  });
1511
1511
  onCleanup(function() { persistUi(); if (_skillToastOff) _skillToastOff(); if (_skillDoneOff) _skillDoneOff(); });
1512
1512
 
package/src/tui-open.tsx CHANGED
@@ -46,11 +46,11 @@ const sessionId = sIdx !== -1 ? args[sIdx + 1] : null;
46
46
  const autoMode = args.includes("--auto") || args.includes("-a");
47
47
  const initialPrompt = args.filter((a, i) => !a.startsWith("-") && (sIdx === -1 || i !== sIdx + 1)).join(" ");
48
48
 
49
- globalThis.__loomTrace("mcp-start", new Error("defaultMcpInstall beginning"));
49
+ globalThis.__loomTrace?.("mcp-start", new Error("defaultMcpInstall beginning"));
50
50
  try {
51
51
  defaultMcpInstall();
52
52
  } catch (e) {
53
- globalThis.__loomTrace("mcp-install-failed", e);
53
+ globalThis.__loomTrace?.("mcp-install-failed", e);
54
54
  }
55
55
 
56
56
  if (printMode) {
@@ -64,11 +64,11 @@ if (printMode) {
64
64
  process.exit(resp.type === "error" ? 1 : 0);
65
65
  }
66
66
 
67
- globalThis.__loomTrace("render-start", new Error("pre-render"));
67
+ globalThis.__loomTrace?.("render-start", new Error("pre-render"));
68
68
  render(() => <App initialPrompt={initialPrompt} resumeSession={sessionId} autoMode={autoMode} />, {
69
69
  targetFps: 60,
70
70
  useMouse: true,
71
71
  autoFocus: true,
72
72
  exitOnCtrlC: false,
73
73
  });
74
- globalThis.__loomTrace("render-returned", new Error("post-render"));
74
+ globalThis.__loomTrace?.("render-returned", new Error("post-render"));
@@ -0,0 +1,51 @@
1
+ // Loaded via bunfig.toml preload BEFORE any app code, so this replaces the
2
+ // old CJS bootstrap hop entirely: the launch chain stays a plain direct
3
+ // "bun src/tui-open.tsx" (identical shape to repo runs) while we still get
4
+ // to restore the user's project directory early and keep the crash
5
+ // black-box watching.
6
+ const fs = require("fs");
7
+ const os = require("os");
8
+ const path = require("path");
9
+
10
+ if (process.platform === "win32") {
11
+ // UTF-8 console codepage: legacy CPs render the box-drawing logo as "?"
12
+ // garbage and can mangle VT input sequences.
13
+ try {
14
+ const { dlopen } = require("bun:ffi");
15
+ const k32 = dlopen("kernel32.dll", {
16
+ SetConsoleOutputCP: { args: ["uint"], returns: "int" },
17
+ SetConsoleCP: { args: ["uint"], returns: "int" },
18
+ });
19
+ k32.symbols.SetConsoleOutputCP(65001);
20
+ k32.symbols.SetConsoleCP(65001);
21
+ } catch {}
22
+ }
23
+
24
+ if (process.env.LOOM_START_CWD) {
25
+ try { process.chdir(process.env.LOOM_START_CWD); } catch {}
26
+ }
27
+
28
+ const crashPath = () => path.join(os.homedir(), ".loom", "tui-crash.log");
29
+ function record(kind, err) {
30
+ try {
31
+ fs.mkdirSync(path.dirname(crashPath()), { recursive: true });
32
+ fs.appendFileSync(
33
+ crashPath(),
34
+ `[${new Date().toISOString()}] ${kind}: ${(err && (err.stack || err.message)) || String(err)}\n`
35
+ );
36
+ } catch {}
37
+ }
38
+ globalThis.__loomTrace = record;
39
+ process.on("uncaughtException", (e) => record("uncaughtException", e));
40
+ process.on("unhandledRejection", (r) => record("unhandledRejection", r));
41
+
42
+ const __hbStart = Date.now();
43
+ let __hbTick = 0;
44
+ let __hbScheduled = __hbStart;
45
+ const __hbTimer = setInterval(() => {
46
+ const now = Date.now();
47
+ record("heartbeat", new Error(`tick=${++__hbTick} lag=${now - __hbScheduled}ms uptime=${now - __hbStart}ms`));
48
+ __hbScheduled = now + 3000;
49
+ }, 3000);
50
+ try { __hbTimer.unref?.(); } catch {}
51
+ process.on("exit", () => { try { record("exit", new Error(`uptime=${Date.now() - __hbStart}ms ticks=${__hbTick}`)); } catch {} });
@@ -1,72 +0,0 @@
1
- // Bootstrap shim for globally-installed launches.
2
- //
3
- // Bun only discovers bunfig.toml / tsconfig.json by walking UP from its
4
- // working directory. When installed via npm the package lives outside the
5
- // user's project tree, so launchers start bun from the PACKAGE root (where
6
- // those files ship) and hand the real project directory through
7
- // LOOM_START_CWD. This file must stay import-free so the chdir happens
8
- // before any Loom module (which may read cwd at import time) executes.
9
- const fs = require("fs");
10
- const os = require("os");
11
- const path = require("path");
12
-
13
- if (process.env.LOOM_START_CWD) {
14
- try { process.chdir(process.env.LOOM_START_CWD); } catch {}
15
- }
16
-
17
- // Windows consoles default to a legacy codepage where the box-drawing /
18
- // block glyphs used across the TUI render as "?" garbage, and VT input
19
- // sequences (arrows, ctrl combos, bracketed paste) may never arrive. Switch
20
- // both console CPs to UTF-8 before anything renders or reads stdin.
21
- if (process.platform === "win32") {
22
- try {
23
- const { dlopen } = require("bun:ffi");
24
- const k32 = dlopen("kernel32.dll", {
25
- SetConsoleOutputCP: { args: ["uint"], returns: "int" },
26
- SetConsoleCP: { args: ["uint"], returns: "int" },
27
- });
28
- k32.symbols.SetConsoleOutputCP(65001);
29
- k32.symbols.SetConsoleCP(65001);
30
- } catch {}
31
- }
32
-
33
- // Crash black-box: OpenTUI swallows post-render errors, leaving users stuck
34
- // on the splash with no clue why. Persist every uncaught failure to disk so
35
- // a frozen TUI can be diagnosed after the fact.
36
- const crashPath = () => path.join(os.homedir(), ".loom", "tui-crash.log");
37
- function record(kind, err) {
38
- try {
39
- fs.mkdirSync(path.dirname(crashPath()), { recursive: true });
40
- fs.appendFileSync(
41
- crashPath(),
42
- `[${new Date().toISOString()}] ${kind}: ${(err && (err.stack || err.message)) || String(err)}\n`
43
- );
44
- } catch {}
45
- }
46
- process.on("uncaughtException", (e) => { record("uncaughtException", e); });
47
- process.on("unhandledRejection", (r) => { record("unhandledRejection", r); });
48
- globalThis.__loomTrace = record;
49
-
50
- // Watchdog: append a heartbeat every 3s carrying measured event-loop lag.
51
- // A synchronous hang shows up as a timestamp gap exactly covering the
52
- // blocking phase; markers around it name the guilty step.
53
- const __hbStart = Date.now();
54
- let __hbTick = 0;
55
- let __hbScheduled = __hbStart;
56
- const __hbTimer = setInterval(() => {
57
- const now = Date.now();
58
- const lag = now - __hbScheduled;
59
- record("heartbeat", new Error(`tick=${++__hbTick} lag=${lag}ms uptime=${now - __hbStart}ms`));
60
- __hbScheduled = now + 3000;
61
- }, 3000);
62
- try { __hbTimer.unref?.(); } catch {}
63
- process.on("exit", () => { try { record("exit", new Error(`uptime=${Date.now() - __hbStart}ms ticks=${__hbTick}`)); } catch {} });
64
-
65
- record("boot", new Error(
66
- `argv=${JSON.stringify(process.argv.slice(1))} cwd=${process.cwd()} ` +
67
- `startCwd=${process.env.LOOM_START_CWD || "-"} bun=${process.version} ` +
68
- `node=${process.versions.node || "-"} platform=${process.platform}`
69
- ));
70
- if (process.env.LOOM_TUI_TRACE) globalThis.__loomTrace = record;
71
-
72
- await import("./tui-open.tsx");