gaslighting-engine 0.3.0 → 0.3.1
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/README.md +14 -0
- package/dist/cli.js +3 -0
- package/dist/commands/cockpit.js +29 -6
- package/dist/core/cockpitHtml.js +4 -2
- package/dist/core/codexRuntime.js +42 -13
- package/dist/version.js +1 -1
- package/docs/codex-usage.md +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -122,6 +122,20 @@ It shows:
|
|
|
122
122
|
- Codex runtime args
|
|
123
123
|
- Start Codex action
|
|
124
124
|
|
|
125
|
+
By default, `Start Codex` closes the local cockpit server and continues Codex in the same terminal that launched Mission Control. This keeps Cursor, Warp, Windows Terminal, or any other terminal flow intact.
|
|
126
|
+
|
|
127
|
+
If you explicitly want a separate terminal, add:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx gaslighting-engine@latest start "I want to build a hospital website." --new-terminal
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
To customize Codex flags, use:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npx gaslighting-engine@latest start "I want to build a hospital website." --codex-args="--search --dangerously-bypass-approvals-and-sandbox"
|
|
137
|
+
```
|
|
138
|
+
|
|
125
139
|
Open it for an existing project:
|
|
126
140
|
|
|
127
141
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -117,6 +117,7 @@ Defaults:
|
|
|
117
117
|
.option("--lang <lang>", "language: en or ko", "en")
|
|
118
118
|
.option("--type <type>", "project type override", parseProjectType)
|
|
119
119
|
.option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
|
|
120
|
+
.option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
|
|
120
121
|
.action(runStart);
|
|
121
122
|
program
|
|
122
123
|
.command("cockpit [request]")
|
|
@@ -130,6 +131,7 @@ Defaults:
|
|
|
130
131
|
.option("--lang <lang>", "language: en or ko", "en")
|
|
131
132
|
.option("--type <type>", "project type override", parseProjectType)
|
|
132
133
|
.option("--codex-args <args>", "Codex CLI args used by the Start Codex button")
|
|
134
|
+
.option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
|
|
133
135
|
.action(runCockpit);
|
|
134
136
|
program
|
|
135
137
|
.command("run <request>")
|
|
@@ -140,6 +142,7 @@ Defaults:
|
|
|
140
142
|
.option("--lang <lang>", "language: en or ko", "en")
|
|
141
143
|
.option("--type <type>", "project type override", parseProjectType)
|
|
142
144
|
.option("--codex-args <args>", "Codex CLI args")
|
|
145
|
+
.option("--new-terminal", "launch Codex in a separate terminal instead of handing off the current terminal")
|
|
143
146
|
.action(runCodexRun);
|
|
144
147
|
program
|
|
145
148
|
.command("upgrade")
|
package/dist/commands/cockpit.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createServer } from "node:http";
|
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { platform } from "node:os";
|
|
6
6
|
import { analyze } from "../core/analyze.js";
|
|
7
|
-
import { getDefaultCodexArgs,
|
|
7
|
+
import { buildCodexCommand, getDefaultCodexArgs, launchCodexInCurrentTerminal, launchCodexInNewTerminal } from "../core/codexRuntime.js";
|
|
8
8
|
import { pageList, projectPurpose } from "../core/content.js";
|
|
9
9
|
import { generateCodexInstallDocs, generateDocs, generateProjectCareDoc } from "../core/generateDocs.js";
|
|
10
10
|
import { renderCockpitHtml } from "../core/cockpitHtml.js";
|
|
@@ -34,10 +34,14 @@ export function runCodexRun(rawUserRequest, options) {
|
|
|
34
34
|
const input = makeInput(rawUserRequest, options);
|
|
35
35
|
writeDocs(root, generateDocs(input, root).docs, options.force ?? true, false);
|
|
36
36
|
writeDocs(root, generateCodexInstallDocs(), true, false);
|
|
37
|
-
const result = launchCodex({ root, request: rawUserRequest, codexArgs: options.codexArgs });
|
|
38
37
|
printBanner("CODEX RUN");
|
|
39
|
-
console.log(
|
|
40
|
-
console.log(
|
|
38
|
+
console.log(options.newTerminal ? "Starting Codex in a new terminal." : "Handing this terminal over to Codex.");
|
|
39
|
+
console.log(buildCodexCommand({ root, request: rawUserRequest, codexArgs: options.codexArgs }));
|
|
40
|
+
const result = options.newTerminal
|
|
41
|
+
? launchCodexInNewTerminal({ root, request: rawUserRequest, codexArgs: options.codexArgs })
|
|
42
|
+
: launchCodexInCurrentTerminal({ root, request: rawUserRequest, codexArgs: options.codexArgs });
|
|
43
|
+
if (!result.ok)
|
|
44
|
+
console.log(result.message);
|
|
41
45
|
}
|
|
42
46
|
async function openCockpit(rawUserRequest, options) {
|
|
43
47
|
const root = resolve(options.path ?? process.cwd());
|
|
@@ -66,8 +70,19 @@ async function openCockpit(rawUserRequest, options) {
|
|
|
66
70
|
currentRequest = String(body.request || currentRequest);
|
|
67
71
|
currentInput = makeInput(currentRequest, options);
|
|
68
72
|
writeDocs(root, generateDocs(currentInput, root).docs, true, false);
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
if (options.newTerminal) {
|
|
74
|
+
const result = launchCodexInNewTerminal({ root, request: currentRequest, codexArgs: options.codexArgs });
|
|
75
|
+
return sendJson(response, { ...result });
|
|
76
|
+
}
|
|
77
|
+
const commandPreview = launchMessageForCurrentTerminal(root, currentRequest, options);
|
|
78
|
+
sendJson(response, commandPreview);
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
server.close(() => {
|
|
81
|
+
console.log("\nMission Control is handing off to Codex in this terminal.\n");
|
|
82
|
+
launchCodexInCurrentTerminal({ root, request: currentRequest, codexArgs: options.codexArgs });
|
|
83
|
+
});
|
|
84
|
+
}, 250);
|
|
85
|
+
return;
|
|
71
86
|
}
|
|
72
87
|
if (request.method === "POST" && request.url === "/api/connect-github") {
|
|
73
88
|
const body = await readJson(request);
|
|
@@ -108,9 +123,17 @@ function buildState(root, request, input, options) {
|
|
|
108
123
|
care: inspectProjectCare(root),
|
|
109
124
|
docsPresent,
|
|
110
125
|
codexArgs: options.codexArgs || getDefaultCodexArgs(),
|
|
126
|
+
launchMode: options.newTerminal ? "new_terminal" : "current_terminal",
|
|
111
127
|
codexAvailable: isCommandAvailable("codex"),
|
|
112
128
|
};
|
|
113
129
|
}
|
|
130
|
+
function launchMessageForCurrentTerminal(root, request, options) {
|
|
131
|
+
return {
|
|
132
|
+
ok: true,
|
|
133
|
+
command: buildCodexCommand({ root, request, codexArgs: options.codexArgs }),
|
|
134
|
+
message: "Mission Control will close and Codex will continue in the same terminal that launched it.",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
114
137
|
function makeInput(rawUserRequest, options) {
|
|
115
138
|
return {
|
|
116
139
|
rawUserRequest,
|
package/dist/core/cockpitHtml.js
CHANGED
|
@@ -424,7 +424,7 @@ export function renderCockpitHtml() {
|
|
|
424
424
|
<div class="action-card"><div><strong>Refresh Docs</strong><br /><span>Regenerate .gaslighting and root AGENTS.md from the current request.</span></div><button id="generateBtn">Generate</button></div>
|
|
425
425
|
<div class="action-card"><div><strong>Connect GitHub</strong><br /><span>Initialize Git if needed and connect origin without blocking implementation.</span></div><button id="githubBtn">Connect</button></div>
|
|
426
426
|
<div class="action-card"><div><strong>Doctor</strong><br /><span>Check discipline documents and operational care state.</span></div><button id="doctorBtn">Check</button></div>
|
|
427
|
-
<div class="action-card"><div><strong>Start Codex</strong><br /><span>
|
|
427
|
+
<div class="action-card"><div><strong>Start Codex</strong><br /><span>Close the cockpit server and continue Codex in this same terminal.</span></div><button class="primary" id="startCardBtn">Start</button></div>
|
|
428
428
|
</div>
|
|
429
429
|
</footer>
|
|
430
430
|
</main>
|
|
@@ -436,6 +436,7 @@ export function renderCockpitHtml() {
|
|
|
436
436
|
</div>
|
|
437
437
|
<div class="side-panel">
|
|
438
438
|
<h3>Runtime</h3>
|
|
439
|
+
<div class="status-row"><span class="badge">T</span><div><strong>Launch mode</strong><small id="launchMode">-</small></div></div>
|
|
439
440
|
<div class="status-row"><span class="badge">C</span><div><strong>Codex args</strong><small id="codexArgs">-</small></div></div>
|
|
440
441
|
<div class="status-row"><span class="badge warn">M</span><div><strong>Model strategy</strong><small>Codex-first now. Multi-model slots can be added later.</small></div></div>
|
|
441
442
|
</div>
|
|
@@ -507,6 +508,7 @@ export function renderCockpitHtml() {
|
|
|
507
508
|
el('confidence').textContent = state.analysis.confidence;
|
|
508
509
|
el('stackHints').textContent = state.analysis.detectedStackHints.length ? state.analysis.detectedStackHints.join(', ') : 'default web stack';
|
|
509
510
|
el('codexArgs').textContent = state.codexArgs;
|
|
511
|
+
el('launchMode').textContent = state.launchMode === 'new_terminal' ? 'New terminal window' : 'Same terminal handoff';
|
|
510
512
|
|
|
511
513
|
var warningCount = state.care.checks.filter(function (check) { return !check.ok; }).length;
|
|
512
514
|
var score = Math.max(0, Math.round(((state.care.checks.length - warningCount) / Math.max(1, state.care.checks.length)) * 100));
|
|
@@ -563,7 +565,7 @@ export function renderCockpitHtml() {
|
|
|
563
565
|
headers: { 'content-type': 'application/json' },
|
|
564
566
|
body: JSON.stringify({ request: el('requestInput').value })
|
|
565
567
|
});
|
|
566
|
-
log(data.message + '\\n\\n' + data.command);
|
|
568
|
+
log(data.message + '\\n\\n' + data.command + '\\n\\nThe original terminal will continue as Codex.');
|
|
567
569
|
}
|
|
568
570
|
async function connectGithub() {
|
|
569
571
|
var githubUrl = el('githubInput').value.trim();
|
|
@@ -26,38 +26,67 @@ export function buildCodexPrompt(request) {
|
|
|
26
26
|
].join("\n");
|
|
27
27
|
}
|
|
28
28
|
export function buildCodexCommand(input) {
|
|
29
|
-
|
|
30
|
-
return ["codex", ...args, "-C", quoteArg(input.root), quoteArg(buildCodexPrompt(input.request))].join(" ");
|
|
29
|
+
return buildCodexCommandParts(input).command;
|
|
31
30
|
}
|
|
32
|
-
export function
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
export function launchCodexInCurrentTerminal(input) {
|
|
32
|
+
const parts = buildCodexCommandParts(input);
|
|
33
|
+
try {
|
|
34
|
+
const child = platform() === "win32"
|
|
35
|
+
? spawn("cmd.exe", ["/d", "/s", "/c", "codex", ...parts.args, "-C", input.root, parts.prompt], {
|
|
36
|
+
cwd: input.root,
|
|
37
|
+
stdio: "inherit",
|
|
38
|
+
})
|
|
39
|
+
: spawn("codex", [...parts.args, "-C", input.root, parts.prompt], {
|
|
40
|
+
cwd: input.root,
|
|
41
|
+
stdio: "inherit",
|
|
42
|
+
});
|
|
43
|
+
child.on("exit", (code) => {
|
|
44
|
+
process.exit(code ?? 0);
|
|
45
|
+
});
|
|
46
|
+
child.on("error", (error) => {
|
|
47
|
+
console.error(`Could not start Codex: ${error.message}`);
|
|
48
|
+
console.error(parts.command);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
});
|
|
51
|
+
return { ok: true, command: parts.command, message: "Mission Control handed off to Codex in this terminal." };
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const message = error instanceof Error ? error.message : "Unknown Codex launch failure.";
|
|
55
|
+
return { ok: false, command: parts.command, message };
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export function launchCodexInNewTerminal(input) {
|
|
59
|
+
const parts = buildCodexCommandParts(input);
|
|
36
60
|
try {
|
|
37
61
|
if (platform() === "win32") {
|
|
38
|
-
const child = spawn("cmd.exe", ["/c", "start", "Gaslighting Codex", "/D", input.root, "codex", ...args, "-C", input.root, prompt], {
|
|
62
|
+
const child = spawn("cmd.exe", ["/c", "start", "Gaslighting Codex", "/D", input.root, "codex", ...parts.args, "-C", input.root, parts.prompt], {
|
|
39
63
|
cwd: input.root,
|
|
40
64
|
detached: true,
|
|
41
65
|
stdio: "ignore",
|
|
42
66
|
});
|
|
43
67
|
child.unref();
|
|
44
|
-
return { ok: true, command, message: "Started Codex in a new terminal window." };
|
|
68
|
+
return { ok: true, command: parts.command, message: "Started Codex in a new terminal window." };
|
|
45
69
|
}
|
|
46
70
|
if (platform() === "darwin") {
|
|
47
|
-
const script = `tell application "Terminal" to do script ${JSON.stringify(`cd ${quoteShell(input.root)} && ${command}`)}`;
|
|
71
|
+
const script = `tell application "Terminal" to do script ${JSON.stringify(`cd ${quoteShell(input.root)} && ${parts.command}`)}`;
|
|
48
72
|
const child = spawn("osascript", ["-e", script], { detached: true, stdio: "ignore" });
|
|
49
73
|
child.unref();
|
|
50
|
-
return { ok: true, command, message: "Started Codex in Terminal." };
|
|
74
|
+
return { ok: true, command: parts.command, message: "Started Codex in Terminal." };
|
|
51
75
|
}
|
|
52
|
-
const child = spawn("sh", ["-lc", `cd ${quoteShell(input.root)} && ${command}`], { detached: true, stdio: "ignore" });
|
|
76
|
+
const child = spawn("sh", ["-lc", `cd ${quoteShell(input.root)} && ${parts.command}`], { detached: true, stdio: "ignore" });
|
|
53
77
|
child.unref();
|
|
54
|
-
return { ok: true, command, message: "Started Codex in the background. If no terminal appears, copy the command and run it manually." };
|
|
78
|
+
return { ok: true, command: parts.command, message: "Started Codex in the background. If no terminal appears, copy the command and run it manually." };
|
|
55
79
|
}
|
|
56
80
|
catch (error) {
|
|
57
81
|
const message = error instanceof Error ? error.message : "Unknown Codex launch failure.";
|
|
58
|
-
return { ok: false, command, message };
|
|
82
|
+
return { ok: false, command: parts.command, message };
|
|
59
83
|
}
|
|
60
84
|
}
|
|
85
|
+
function buildCodexCommandParts(input) {
|
|
86
|
+
const args = splitCommandArgs(input.codexArgs || getDefaultCodexArgs());
|
|
87
|
+
const prompt = buildCodexPrompt(input.request);
|
|
88
|
+
return { args, prompt, command: ["codex", ...args, "-C", quoteArg(input.root), quoteArg(prompt)].join(" ") };
|
|
89
|
+
}
|
|
61
90
|
export function splitCommandArgs(input) {
|
|
62
91
|
const args = [];
|
|
63
92
|
const pattern = /"([^"]*)"|'([^']*)'|(\S+)/g;
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const packageName = "gaslighting-engine";
|
|
2
|
-
export const packageVersion = "0.3.
|
|
2
|
+
export const packageVersion = "0.3.1";
|
package/docs/codex-usage.md
CHANGED
|
@@ -54,6 +54,14 @@ Generate documents and open Mission Control:
|
|
|
54
54
|
npx gaslighting-engine@latest start "I want to build a hospital website."
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
`Start Codex` continues in the same terminal by default. Use `--new-terminal` only when you intentionally want a separate terminal window.
|
|
58
|
+
|
|
59
|
+
Custom Codex flags:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx gaslighting-engine@latest start "I want to build a hospital website." --codex-args="--search --dangerously-bypass-approvals-and-sandbox"
|
|
63
|
+
```
|
|
64
|
+
|
|
57
65
|
Open the GUI for an existing Gaslighting project:
|
|
58
66
|
|
|
59
67
|
```bash
|