storyforge 0.4.10 → 0.4.12
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.
|
@@ -134,7 +134,14 @@ var BridgePoller = class {
|
|
|
134
134
|
let lastErr = "";
|
|
135
135
|
for (const m of candidates) {
|
|
136
136
|
try {
|
|
137
|
-
const args = cli === "codex" ? ["exec", "-", "--model", m
|
|
137
|
+
const args = cli === "codex" ? ["exec", "-", "--model", m, "--search"] : [
|
|
138
|
+
"-p",
|
|
139
|
+
"--model",
|
|
140
|
+
m,
|
|
141
|
+
"--no-session-persistence",
|
|
142
|
+
"--allowedTools",
|
|
143
|
+
"WebSearch,WebFetch"
|
|
144
|
+
];
|
|
138
145
|
const text = await runSpawn(cli, args, prompt, CLI_TIMEOUT_MS);
|
|
139
146
|
if (text.trim()) return { text, modelUsed: `${cli}:${m}` };
|
|
140
147
|
lastErr = `${cli}/${m} returned empty stdout`;
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,12 @@ import * as path from "path";
|
|
|
17
17
|
import * as os from "os";
|
|
18
18
|
var FORGE_DIR = path.join(os.homedir(), ".forge");
|
|
19
19
|
var CREDS_PATH = path.join(FORGE_DIR, "credentials.json");
|
|
20
|
+
var FORGE_ENV_PATHS = [
|
|
21
|
+
path.join(FORGE_DIR, ".env"),
|
|
22
|
+
// ~/.forge/.env
|
|
23
|
+
path.join(os.homedir(), ".forge.env")
|
|
24
|
+
// ~/.forge.env (legacy short form)
|
|
25
|
+
];
|
|
20
26
|
function getForgeDir() {
|
|
21
27
|
fs.mkdirSync(FORGE_DIR, { recursive: true });
|
|
22
28
|
return FORGE_DIR;
|
|
@@ -32,6 +38,35 @@ function loadCredentials() {
|
|
|
32
38
|
return null;
|
|
33
39
|
}
|
|
34
40
|
}
|
|
41
|
+
function loadDotEnv() {
|
|
42
|
+
const loaded = [];
|
|
43
|
+
const sources = [];
|
|
44
|
+
const candidates = [path.resolve(process.cwd(), ".env"), ...FORGE_ENV_PATHS];
|
|
45
|
+
for (const file of candidates) {
|
|
46
|
+
let content;
|
|
47
|
+
try {
|
|
48
|
+
content = fs.readFileSync(file, "utf-8");
|
|
49
|
+
} catch {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
sources.push(file);
|
|
53
|
+
for (const rawLine of content.split(/\r?\n/)) {
|
|
54
|
+
const line = rawLine.trim();
|
|
55
|
+
if (!line || line.startsWith("#")) continue;
|
|
56
|
+
const eq = line.indexOf("=");
|
|
57
|
+
if (eq < 0) continue;
|
|
58
|
+
const key = line.slice(0, eq).trim();
|
|
59
|
+
let val = line.slice(eq + 1).trim();
|
|
60
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
61
|
+
val = val.slice(1, -1);
|
|
62
|
+
}
|
|
63
|
+
if (!key || process.env[key] != null) continue;
|
|
64
|
+
process.env[key] = val;
|
|
65
|
+
loaded.push(key);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { loaded, sources };
|
|
69
|
+
}
|
|
35
70
|
|
|
36
71
|
// src/utils/script-prompt.ts
|
|
37
72
|
var STYLE_GUIDES = {
|
|
@@ -512,7 +547,7 @@ var exec = promisify(execCb);
|
|
|
512
547
|
var PORT = 4444;
|
|
513
548
|
function runCliPipingStdin(cmd, args, stdinData, opts = {}) {
|
|
514
549
|
const maxBytes = (opts.maxBufferMB ?? 16) * 1024 * 1024;
|
|
515
|
-
return new Promise((
|
|
550
|
+
return new Promise((resolve3, reject) => {
|
|
516
551
|
const proc = spawn(cmd, args, { stdio: ["pipe", "pipe", "pipe"] });
|
|
517
552
|
let stdout = "";
|
|
518
553
|
let stderr = "";
|
|
@@ -545,7 +580,7 @@ function runCliPipingStdin(cmd, args, stdinData, opts = {}) {
|
|
|
545
580
|
});
|
|
546
581
|
proc.on("close", (code) => {
|
|
547
582
|
if (timer) clearTimeout(timer);
|
|
548
|
-
|
|
583
|
+
resolve3({ stdout, stderr, code });
|
|
549
584
|
});
|
|
550
585
|
proc.stdin.end(stdinData);
|
|
551
586
|
});
|
|
@@ -796,10 +831,14 @@ function openBrowser(url) {
|
|
|
796
831
|
});
|
|
797
832
|
}
|
|
798
833
|
async function devCommand(options) {
|
|
834
|
+
const env = loadDotEnv();
|
|
799
835
|
const port = parseInt(options.port || String(PORT), 10);
|
|
800
836
|
const dir = path2.resolve(options.dir || process.cwd());
|
|
801
837
|
console.log("");
|
|
802
838
|
log.info(`Forge \u2014 ${dir}`);
|
|
839
|
+
if (env.loaded.length > 0) {
|
|
840
|
+
log.info(`Loaded env: ${env.loaded.join(", ")} from ${env.sources.join(", ")}`);
|
|
841
|
+
}
|
|
803
842
|
const counts = scanAssets(dir);
|
|
804
843
|
const total = Object.values(counts).reduce((a, b) => a + b, 0);
|
|
805
844
|
if (total > 0) {
|
|
@@ -1026,7 +1065,14 @@ async function devCommand(options) {
|
|
|
1026
1065
|
}
|
|
1027
1066
|
try {
|
|
1028
1067
|
log.info(`[script-gen] Generating via ${cli} CLI \xB7 model=${model}`);
|
|
1029
|
-
const args = cli === "codex" ? ["exec", "-", "--model", model
|
|
1068
|
+
const args = cli === "codex" ? ["exec", "-", "--model", model, "--search"] : [
|
|
1069
|
+
"-p",
|
|
1070
|
+
"--model",
|
|
1071
|
+
model,
|
|
1072
|
+
"--no-session-persistence",
|
|
1073
|
+
"--allowedTools",
|
|
1074
|
+
"WebSearch,WebFetch"
|
|
1075
|
+
];
|
|
1030
1076
|
const timeoutMs = Number(process.env.SCRIPT_GEN_TIMEOUT_MS) || 12e5;
|
|
1031
1077
|
const { stdout, code, stderr } = await runCliPipingStdin(cli, args, prompt2, {
|
|
1032
1078
|
timeoutMs,
|
|
@@ -1424,9 +1470,9 @@ Return ONLY the complete updated TSX. No markdown fences, no explanation.`;
|
|
|
1424
1470
|
}
|
|
1425
1471
|
const boundary = boundaryM[1];
|
|
1426
1472
|
const chunks = [];
|
|
1427
|
-
await new Promise((
|
|
1473
|
+
await new Promise((resolve3, reject) => {
|
|
1428
1474
|
req.on("data", (c) => chunks.push(Buffer.from(c)));
|
|
1429
|
-
req.on("end",
|
|
1475
|
+
req.on("end", resolve3);
|
|
1430
1476
|
req.on("error", reject);
|
|
1431
1477
|
});
|
|
1432
1478
|
const body = Buffer.concat(chunks);
|
|
@@ -1538,7 +1584,7 @@ Return ONLY the complete updated TSX. No markdown fences, no explanation.`;
|
|
|
1538
1584
|
return "0.0.0";
|
|
1539
1585
|
})();
|
|
1540
1586
|
void (async () => {
|
|
1541
|
-
const { BridgePoller } = await import("./bridge-poller-
|
|
1587
|
+
const { BridgePoller } = await import("./bridge-poller-YWYLEYOD.js");
|
|
1542
1588
|
const poller = new BridgePoller({ baseUrl: bridgeUrl, token: bridgeToken, clientVersion: `storyforge ${pkgVersion}` });
|
|
1543
1589
|
poller.start();
|
|
1544
1590
|
})();
|
|
@@ -1546,7 +1592,12 @@ Return ONLY the complete updated TSX. No markdown fences, no explanation.`;
|
|
|
1546
1592
|
console.log(` Bridge tunnel \u2192 ${bridgeUrl}/api/cli-bridge/* (outbound polling)`);
|
|
1547
1593
|
} else {
|
|
1548
1594
|
console.log("");
|
|
1549
|
-
console.log(" Bridge tunnel disabled \u2014 set FORGE_BRIDGE_TOKEN to expose your CLI seats
|
|
1595
|
+
console.log(" Bridge tunnel disabled \u2014 set FORGE_BRIDGE_TOKEN to expose your CLI seats.");
|
|
1596
|
+
console.log(" Vercel env vars do NOT reach this laptop. Pick ONE of these:");
|
|
1597
|
+
console.log(" a) export FORGE_BRIDGE_TOKEN=xxx in your shell, then re-run storyforge");
|
|
1598
|
+
console.log(" b) drop FORGE_BRIDGE_TOKEN=xxx into ./.env (cwd) or ~/.forge/.env");
|
|
1599
|
+
console.log(" c) one-shot: FORGE_BRIDGE_TOKEN=xxx npx storyforge");
|
|
1600
|
+
console.log(` Use the SAME token value you set on Vercel as FORGE_BRIDGE_TOKEN.`);
|
|
1550
1601
|
}
|
|
1551
1602
|
console.log("");
|
|
1552
1603
|
console.log(" Ctrl+C to stop");
|
|
@@ -1558,10 +1609,10 @@ Return ONLY the complete updated TSX. No markdown fences, no explanation.`;
|
|
|
1558
1609
|
import * as readline from "readline";
|
|
1559
1610
|
function prompt(question) {
|
|
1560
1611
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
1561
|
-
return new Promise((
|
|
1612
|
+
return new Promise((resolve3) => {
|
|
1562
1613
|
rl.question(question, (answer) => {
|
|
1563
1614
|
rl.close();
|
|
1564
|
-
|
|
1615
|
+
resolve3(answer.trim());
|
|
1565
1616
|
});
|
|
1566
1617
|
});
|
|
1567
1618
|
}
|