gaslighting-engine 0.4.3 → 0.4.5

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.
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Gaslighting Mission Control</title>
7
- <script type="module" crossorigin src="./assets/index-BoI6eWtN.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/index-oFTvTTu8.css">
7
+ <script type="module" crossorigin src="./assets/index-LQV-cNK0.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-B3MqBLej.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -1,6 +1,6 @@
1
1
  import { app, BrowserWindow, dialog, ipcMain } from "electron";
2
2
  import { spawn } from "node:child_process";
3
- import { existsSync } from "node:fs";
3
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
4
4
  import { dirname, join, resolve } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { platform } from "node:os";
@@ -21,12 +21,22 @@ const packageRoot = resolve(desktopMainDir, "..", "..");
21
21
  let currentRoot = initialRoot;
22
22
  let currentRequest = initialRequest || "Build a practical MVP without shrinking scope.";
23
23
  let mainWindow;
24
+ const desktopUserDataKey = Buffer.from(initialRoot).toString("hex").slice(0, 24);
25
+ const desktopUserDataDir = join(app.getPath("appData"), "Gaslighting Mission Control", desktopUserDataKey);
26
+ app.setName("Gaslighting Mission Control");
27
+ mkdirSync(desktopUserDataDir, { recursive: true });
28
+ app.setPath("userData", desktopUserDataDir);
29
+ app.commandLine.appendSwitch("disable-gpu-shader-disk-cache");
30
+ if (process.env.GASLIGHTING_DESKTOP_DISABLE_GPU !== "0") {
31
+ app.disableHardwareAcceleration();
32
+ }
24
33
  async function createWindow() {
25
34
  mainWindow = new BrowserWindow({
26
35
  width: 1440,
27
36
  height: 940,
28
37
  minWidth: 1120,
29
38
  minHeight: 760,
39
+ show: false,
30
40
  title: "Gaslighting Mission Control",
31
41
  backgroundColor: "#f5f5f3",
32
42
  webPreferences: {
@@ -35,12 +45,56 @@ async function createWindow() {
35
45
  nodeIntegration: false,
36
46
  },
37
47
  });
48
+ let hasShown = false;
49
+ const showWindow = () => {
50
+ if (!hasShown && mainWindow && !mainWindow.isDestroyed()) {
51
+ hasShown = true;
52
+ mainWindow.show();
53
+ mainWindow.focus();
54
+ }
55
+ };
56
+ mainWindow.once("ready-to-show", showWindow);
57
+ if (process.env.GASLIGHTING_DESKTOP_DEBUG) {
58
+ mainWindow.webContents.on("console-message", (_event, level, message, line, sourceId) => {
59
+ console.log(`[renderer:${level}] ${message} (${sourceId}:${line})`);
60
+ });
61
+ mainWindow.webContents.on("did-fail-load", (_event, errorCode, errorDescription, validatedUrl) => {
62
+ console.error(`[renderer:load-failed] ${errorCode} ${errorDescription} ${validatedUrl}`);
63
+ });
64
+ mainWindow.webContents.on("render-process-gone", (_event, details) => {
65
+ console.error(`[renderer:gone] ${details.reason}`);
66
+ });
67
+ }
38
68
  if (process.env.GASLIGHTING_DESKTOP_DEV) {
39
69
  await mainWindow.loadURL("http://127.0.0.1:5173");
40
70
  }
41
71
  else {
42
72
  await mainWindow.loadFile(join(packageRoot, "desktop-dist", "index.html"));
43
73
  }
74
+ showWindow();
75
+ if (process.env.GASLIGHTING_DESKTOP_DEBUG) {
76
+ const snapshot = await mainWindow.webContents.executeJavaScript(`
77
+ ({
78
+ href: location.href,
79
+ title: document.title,
80
+ rootExists: Boolean(document.getElementById("root")),
81
+ rootHtml: document.getElementById("root")?.innerHTML.slice(0, 300) ?? null,
82
+ scriptSrc: Array.from(document.scripts).map((script) => script.src),
83
+ gaslightingType: typeof window.gaslighting
84
+ })
85
+ `);
86
+ console.log(`[renderer:snapshot] ${JSON.stringify(snapshot)}`);
87
+ if (process.env.GASLIGHTING_DESKTOP_DEBUG_CAPTURE) {
88
+ try {
89
+ const image = await mainWindow.webContents.capturePage();
90
+ writeFileSync(process.env.GASLIGHTING_DESKTOP_DEBUG_CAPTURE, image.toPNG());
91
+ console.log(`[renderer:capture] ${process.env.GASLIGHTING_DESKTOP_DEBUG_CAPTURE}`);
92
+ }
93
+ catch (error) {
94
+ console.error(`[renderer:capture-failed] ${String(error)}`);
95
+ }
96
+ }
97
+ }
44
98
  }
45
99
  app.whenReady().then(createWindow);
46
100
  app.on("window-all-closed", () => {
@@ -59,32 +113,34 @@ ipcMain.handle("project:select", async () => {
59
113
  });
60
114
  ipcMain.handle("mission:state", () => buildDesktopState());
61
115
  ipcMain.handle("mission:generate", (_event, input) => {
62
- updateCurrent(input);
63
116
  const generateInput = toGenerateInput(input);
117
+ updateCurrent(input);
64
118
  writeDocs(currentRoot, generateDocs(generateInput, currentRoot).docs, true, false);
65
119
  writeDocs(currentRoot, generateCodexInstallDocs(), true, false);
66
120
  return buildDesktopState(input);
67
121
  });
68
122
  ipcMain.handle("agent:start", async (event, input) => {
123
+ const runRequest = input.request || currentRequest;
69
124
  updateCurrent(input);
70
125
  const runtime = input.runtime ?? "codex";
71
126
  const adapter = getAgentRuntimeAdapter(runtime);
72
127
  const spawnInput = adapter.buildSpawn({
73
128
  root: currentRoot,
74
- request: currentRequest,
129
+ request: runRequest,
75
130
  runtime,
76
131
  model: input.model,
77
132
  permissionMode: input.permissionMode ?? "auto_review",
78
133
  loopMode: input.loopMode ?? "off",
79
134
  extraArgs: input.extraArgs,
80
135
  });
81
- event.sender.send("terminal:data", `\r\n$ ${adapter.buildCommand({ root: currentRoot, request: currentRequest, runtime, model: input.model, permissionMode: input.permissionMode ?? "auto_review", loopMode: input.loopMode ?? "off", extraArgs: input.extraArgs })}\r\n`);
136
+ event.sender.send("terminal:data", `\r\n$ ${adapter.buildCommand({ root: currentRoot, request: runRequest, runtime, model: input.model, permissionMode: input.permissionMode ?? "auto_review", loopMode: input.loopMode ?? "off", extraArgs: input.extraArgs })}\r\n`);
82
137
  await startTerminalProcess(event.sender, spawnInput.file, spawnInput.args, currentRoot);
83
138
  return { ok: true, message: `${adapter.label} started.` };
84
139
  });
85
140
  ipcMain.handle("loop:start", (_event, input) => {
141
+ const runRequest = input.request || currentRequest;
86
142
  updateCurrent(input);
87
- startMissionLoop({ root: currentRoot, request: currentRequest, runtime: input.runtime, permissionMode: input.permissionMode });
143
+ startMissionLoop({ root: currentRoot, request: runRequest, runtime: input.runtime, permissionMode: input.permissionMode });
88
144
  return buildDesktopState(input);
89
145
  });
90
146
  ipcMain.handle("loop:resume", (_event, input) => {
@@ -150,7 +206,9 @@ function buildDesktopState(input = {}) {
150
206
  function updateCurrent(input) {
151
207
  if (input.root)
152
208
  currentRoot = resolve(input.root);
153
- if (input.request)
209
+ if (input.displayRequest)
210
+ currentRequest = input.displayRequest;
211
+ else if (input.request)
154
212
  currentRequest = input.request;
155
213
  }
156
214
  function toGenerateInput(input) {
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const packageName = "gaslighting-engine";
2
- export const packageVersion = "0.4.3";
2
+ export const packageVersion = "0.4.5";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaslighting-engine",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "LUDGI Gaslighting-engine: a hardcore project-discipline generator for AI coding agents.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- .xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}:root{color:#191919;background:#f5f5f3;font-family:Inter,Segoe UI,Arial,sans-serif}*{box-sizing:border-box}body{min-width:1000px;min-height:720px;margin:0}button,input,select,textarea{font:inherit}button{color:#191919;cursor:pointer;background:#fff;border:1px solid #d7d7d2;border-radius:6px;justify-content:center;align-items:center;gap:7px;height:36px;padding:0 12px;display:inline-flex}button:hover{border-color:#a7a7a0}.primary{color:#fff;background:#111;border-color:#111}.app-shell{grid-template-columns:248px 1fr;height:100vh;display:grid}.sidebar{background:#eceff1;border-right:1px solid #d8dddf;padding:22px 16px}.brand{align-items:center;gap:12px;margin-bottom:28px;display:flex}.brand-mark{color:#fff;background:#111;border-radius:8px;place-items:center;width:38px;height:38px;font-weight:800;display:grid}.brand strong,.brand span{display:block}.brand span{color:#667078;font-size:13px}.nav-button{background:0 0;border-color:#0000;justify-content:flex-start;width:100%;margin-bottom:8px}.nav-button.active,.nav-button:hover{background:#fff;border-color:#d7d7d2}.workspace{min-width:0;padding:26px;overflow:auto}.topbar{justify-content:space-between;align-items:flex-start;margin-bottom:22px;display:flex}.topbar h1{margin:0 0 6px;font-size:24px}.topbar p{color:#667078;margin:0;font-size:13px}.top-actions,.button-row,.control-row,.inline-form{flex-wrap:wrap;align-items:center;gap:10px;display:flex}.mission-grid{grid-template-columns:minmax(520px,1fr) 330px;align-items:stretch;gap:18px;display:grid}.mission-panel,.status-panel,.domain-panel,.terminal-panel{background:#fff;border:1px solid #deded8;border-radius:8px;padding:16px}.mission-panel label{color:#555d63;margin:0 0 7px;font-size:13px;display:block}textarea{resize:vertical;border:1px solid #d7d7d2;border-radius:6px;width:100%;min-height:132px;margin-bottom:12px;padding:12px}input,select{background:#fff;border:1px solid #d7d7d2;border-radius:6px;min-width:170px;height:36px;padding:0 10px}.mission-panel input{width:100%;margin-bottom:12px}.status-panel h2,.domain-panel h2,.terminal-panel h2{align-items:center;gap:8px;margin:0 0 14px;font-size:16px;display:flex}.status-line,.care-line{border-top:1px solid #f0f0ec;grid-template-columns:12px minmax(110px,1fr) auto;align-items:center;gap:10px;min-height:34px;display:grid}.care-line{grid-template-columns:12px 1fr;align-items:start;padding:9px 0}.care-line strong{font-size:13px;display:block}.care-line p{color:#667078;margin:3px 0 0;font-size:12px}.dot{border-radius:999px;width:9px;height:9px;margin-top:5px}.dot.ok{background:#138a48}.dot.warn{background:#d88700}.lower-grid{grid-template-columns:1fr 1fr;gap:18px;margin-top:18px;display:grid}.terminal-panel{grid-column:1/-1}.terminal-host{background:#111;border-radius:6px;height:300px;padding:8px;overflow:hidden}.list-box{flex-wrap:wrap;gap:8px;min-height:42px;margin:12px 0;display:flex}.list-box button{height:32px}@media (width<=1100px){.app-shell{grid-template-columns:200px 1fr}.mission-grid,.lower-grid{grid-template-columns:1fr}}