@gaberrb/polypus 0.4.1 → 0.4.3
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/index.js +210 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -285,7 +285,11 @@ var en = {
|
|
|
285
285
|
"welcome.firstRun": "No agents configured yet \u2014 let's set you up.",
|
|
286
286
|
// agent system prompt
|
|
287
287
|
"prompt.language": "Communicate with the user in {language}.",
|
|
288
|
-
"prompt.projectInstructions": "Project-specific operating instructions follow, loaded from `.poly/agents.md`. Treat them as authoritative for how to work in THIS repo. Paths they reference (e.g. skills/*.md, ../context.md, ../rules.md) are relative to the `.poly/` directory \u2014 read those files when relevant before acting:"
|
|
288
|
+
"prompt.projectInstructions": "Project-specific operating instructions follow, loaded from `.poly/agents.md`. Treat them as authoritative for how to work in THIS repo. Paths they reference (e.g. skills/*.md, ../context.md, ../rules.md) are relative to the `.poly/` directory \u2014 read those files when relevant before acting:",
|
|
289
|
+
// @-mentions
|
|
290
|
+
"mentions.injectedHeader": "Referenced files (@-mentions)",
|
|
291
|
+
"mentions.dirHeader": "@{path} (directory listing)",
|
|
292
|
+
"mentions.notFound": "(could not resolve @{path}: not found or outside the allow-list)"
|
|
289
293
|
};
|
|
290
294
|
var ptBR = {
|
|
291
295
|
"common.default": "padr\xE3o",
|
|
@@ -478,6 +482,10 @@ var ptBR = {
|
|
|
478
482
|
"wizard.keyPrompt": "Chave de API (armazenada em texto puro no arquivo de config)",
|
|
479
483
|
"prompt.language": "Comunique-se com o usu\xE1rio em {language}.",
|
|
480
484
|
"prompt.projectInstructions": "Seguem instru\xE7\xF5es operacionais espec\xEDficas do projeto, carregadas de `.poly/agents.md`. Trate-as como autoritativas para trabalhar NESTE reposit\xF3rio. Os caminhos que elas citam (ex.: skills/*.md, ../context.md, ../rules.md) s\xE3o relativos \xE0 pasta `.poly/` \u2014 leia esses arquivos quando relevante antes de agir:",
|
|
485
|
+
// @-mentions
|
|
486
|
+
"mentions.injectedHeader": "Arquivos referenciados (@-mentions)",
|
|
487
|
+
"mentions.dirHeader": "@{path} (conte\xFAdo do diret\xF3rio)",
|
|
488
|
+
"mentions.notFound": "(n\xE3o foi poss\xEDvel resolver @{path}: n\xE3o encontrado ou fora da allow-list)",
|
|
481
489
|
"models.fetching": "Buscando modelos do OpenRouter\u2026",
|
|
482
490
|
"models.fetchError": "N\xE3o foi poss\xEDvel buscar modelos: {msg}",
|
|
483
491
|
"models.none": "Nenhum modelo corresponde aos filtros.",
|
|
@@ -1435,6 +1443,116 @@ function clamp(s) {
|
|
|
1435
1443
|
return s.length > MAX_OUTPUT ? s.slice(0, MAX_OUTPUT) + "\n\u2026[truncated]" : s;
|
|
1436
1444
|
}
|
|
1437
1445
|
|
|
1446
|
+
// src/core/tools/search-file.ts
|
|
1447
|
+
import { readdir as readdir2, readFile as readFile4, stat } from "fs/promises";
|
|
1448
|
+
import { join as join2, resolve as resolve5 } from "path";
|
|
1449
|
+
import { z as z6 } from "zod";
|
|
1450
|
+
var Args5 = z6.object({
|
|
1451
|
+
query: z6.string().min(1),
|
|
1452
|
+
path: z6.string().optional(),
|
|
1453
|
+
glob: z6.string().optional(),
|
|
1454
|
+
max_results: z6.number().int().positive().max(1e3).optional()
|
|
1455
|
+
});
|
|
1456
|
+
var DEFAULT_MAX_RESULTS = 50;
|
|
1457
|
+
var MAX_OUTPUT2 = 2e4;
|
|
1458
|
+
var MAX_FILE_BYTES = 2e6;
|
|
1459
|
+
var SNIPPET_CHARS = 200;
|
|
1460
|
+
var NUL = String.fromCharCode(0);
|
|
1461
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".next", "coverage", ".turbo"]);
|
|
1462
|
+
var searchTool = {
|
|
1463
|
+
mutating: false,
|
|
1464
|
+
spec: {
|
|
1465
|
+
name: "search",
|
|
1466
|
+
description: "Search file contents by regular expression across the workspace (like grep/ripgrep). Returns matches as 'path:line: snippet'. Respects the allow/deny-list and skips node_modules/.git. Use this to find where a symbol is defined or used instead of reading files blindly.",
|
|
1467
|
+
parameters: {
|
|
1468
|
+
type: "object",
|
|
1469
|
+
properties: {
|
|
1470
|
+
query: { type: "string", description: "Regular expression to match against each line" },
|
|
1471
|
+
path: { type: "string", description: "Workspace-relative directory to search in (default '.')" },
|
|
1472
|
+
glob: {
|
|
1473
|
+
type: "string",
|
|
1474
|
+
description: "Optional glob to limit files, e.g. 'src/**/*.ts'"
|
|
1475
|
+
},
|
|
1476
|
+
max_results: {
|
|
1477
|
+
type: "number",
|
|
1478
|
+
description: `Maximum number of matches to return (default ${DEFAULT_MAX_RESULTS})`
|
|
1479
|
+
}
|
|
1480
|
+
},
|
|
1481
|
+
required: ["query"]
|
|
1482
|
+
}
|
|
1483
|
+
},
|
|
1484
|
+
async run(rawArgs, ctx) {
|
|
1485
|
+
const parsed = Args5.safeParse(rawArgs);
|
|
1486
|
+
if (!parsed.success) return { ok: false, output: "Invalid args: 'query' is required." };
|
|
1487
|
+
const { query, path = ".", glob, max_results } = parsed.data;
|
|
1488
|
+
let regex;
|
|
1489
|
+
try {
|
|
1490
|
+
regex = new RegExp(query);
|
|
1491
|
+
} catch (err) {
|
|
1492
|
+
return { ok: false, output: `Invalid regular expression: ${err.message}` };
|
|
1493
|
+
}
|
|
1494
|
+
if (path !== ".") {
|
|
1495
|
+
const decision = ctx.permissions.authorizeRead(path);
|
|
1496
|
+
if (!decision.allowed) return { ok: false, output: `Search denied: ${decision.reason}` };
|
|
1497
|
+
}
|
|
1498
|
+
const globRe = glob ? globToRegExp(glob) : void 0;
|
|
1499
|
+
const limit = max_results ?? DEFAULT_MAX_RESULTS;
|
|
1500
|
+
const root = resolve5(ctx.workspace, path);
|
|
1501
|
+
const matches = [];
|
|
1502
|
+
let truncated = false;
|
|
1503
|
+
const walk = async (dir) => {
|
|
1504
|
+
if (matches.length >= limit) return;
|
|
1505
|
+
let entries;
|
|
1506
|
+
try {
|
|
1507
|
+
entries = await readdir2(dir, { withFileTypes: true });
|
|
1508
|
+
} catch {
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
for (const entry of entries) {
|
|
1512
|
+
if (matches.length >= limit) return;
|
|
1513
|
+
const abs = join2(dir, entry.name);
|
|
1514
|
+
const rel = toPosix(abs.slice(ctx.workspace.length + 1));
|
|
1515
|
+
if (entry.isDirectory()) {
|
|
1516
|
+
if (SKIP_DIRS.has(entry.name)) continue;
|
|
1517
|
+
await walk(abs);
|
|
1518
|
+
continue;
|
|
1519
|
+
}
|
|
1520
|
+
if (!entry.isFile()) continue;
|
|
1521
|
+
if (globRe && !globRe.test(rel)) continue;
|
|
1522
|
+
if (!ctx.permissions.authorizeRead(rel).allowed) continue;
|
|
1523
|
+
try {
|
|
1524
|
+
const info = await stat(abs);
|
|
1525
|
+
if (info.size > MAX_FILE_BYTES) continue;
|
|
1526
|
+
const content = await readFile4(abs, "utf8");
|
|
1527
|
+
if (content.includes(NUL)) continue;
|
|
1528
|
+
const lines = content.split("\n");
|
|
1529
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1530
|
+
if (matches.length >= limit) {
|
|
1531
|
+
truncated = true;
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
if (regex.test(lines[i])) {
|
|
1535
|
+
const snippet = lines[i].trim().slice(0, SNIPPET_CHARS);
|
|
1536
|
+
matches.push(`${rel}:${i + 1}: ${snippet}`);
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
} catch {
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
await walk(root);
|
|
1544
|
+
if (matches.length === 0) {
|
|
1545
|
+
return { ok: true, output: `No matches for /${query}/${glob ? ` in ${glob}` : ""}.` };
|
|
1546
|
+
}
|
|
1547
|
+
const header = `${matches.length}${truncated ? "+" : ""} match(es) for /${query}/:`;
|
|
1548
|
+
const body = [header, ...matches].join("\n");
|
|
1549
|
+
return {
|
|
1550
|
+
ok: true,
|
|
1551
|
+
output: body.length > MAX_OUTPUT2 ? body.slice(0, MAX_OUTPUT2) + "\n\u2026[truncated]" : body
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
};
|
|
1555
|
+
|
|
1438
1556
|
// src/core/tools/types.ts
|
|
1439
1557
|
var FINISH_TOOL = {
|
|
1440
1558
|
name: "finish",
|
|
@@ -1450,9 +1568,9 @@ var FINISH_TOOL = {
|
|
|
1450
1568
|
|
|
1451
1569
|
// src/core/tools/write-file.ts
|
|
1452
1570
|
import { mkdir as mkdir2, writeFile as writeFile3 } from "fs/promises";
|
|
1453
|
-
import { dirname, resolve as
|
|
1454
|
-
import { z as
|
|
1455
|
-
var
|
|
1571
|
+
import { dirname, resolve as resolve6 } from "path";
|
|
1572
|
+
import { z as z7 } from "zod";
|
|
1573
|
+
var Args6 = z7.object({ path: z7.string().min(1), content: z7.string() });
|
|
1456
1574
|
var writeFileTool = {
|
|
1457
1575
|
mutating: true,
|
|
1458
1576
|
spec: {
|
|
@@ -1468,7 +1586,7 @@ var writeFileTool = {
|
|
|
1468
1586
|
}
|
|
1469
1587
|
},
|
|
1470
1588
|
async run(rawArgs, ctx) {
|
|
1471
|
-
const args =
|
|
1589
|
+
const args = Args6.safeParse(rawArgs);
|
|
1472
1590
|
if (!args.success) {
|
|
1473
1591
|
const got = Object.keys(rawArgs ?? {});
|
|
1474
1592
|
return {
|
|
@@ -1480,7 +1598,7 @@ var writeFileTool = {
|
|
|
1480
1598
|
const decision = await ctx.permissions.authorizeWrite(args.data.path, preview);
|
|
1481
1599
|
if (!decision.allowed) return { ok: false, output: `Write denied: ${decision.reason}` };
|
|
1482
1600
|
try {
|
|
1483
|
-
const abs =
|
|
1601
|
+
const abs = resolve6(ctx.workspace, args.data.path);
|
|
1484
1602
|
await mkdir2(dirname(abs), { recursive: true });
|
|
1485
1603
|
await writeFile3(abs, args.data.content, "utf8");
|
|
1486
1604
|
const lines = args.data.content.split("\n").length;
|
|
@@ -1499,6 +1617,7 @@ function previewContent(content) {
|
|
|
1499
1617
|
var TOOLS = {
|
|
1500
1618
|
[readFileTool.spec.name]: readFileTool,
|
|
1501
1619
|
[listDirTool.spec.name]: listDirTool,
|
|
1620
|
+
[searchTool.spec.name]: searchTool,
|
|
1502
1621
|
[writeFileTool.spec.name]: writeFileTool,
|
|
1503
1622
|
[editFileTool.spec.name]: editFileTool,
|
|
1504
1623
|
[runCommandTool.spec.name]: runCommandTool
|
|
@@ -1511,8 +1630,8 @@ function getTool(name) {
|
|
|
1511
1630
|
}
|
|
1512
1631
|
|
|
1513
1632
|
// src/core/agent/correction.ts
|
|
1514
|
-
import { readFile as
|
|
1515
|
-
import { dirname as dirname2, resolve as
|
|
1633
|
+
import { readFile as readFile5, readdir as readdir3 } from "fs/promises";
|
|
1634
|
+
import { dirname as dirname2, resolve as resolve7 } from "path";
|
|
1516
1635
|
function truncationGuidance(toolName) {
|
|
1517
1636
|
const fileHint = toolName === "write_file" || toolName === "edit_file" ? " Write large files in parts: create the file with the first chunk via write_file, then append the rest with edit_file in the next steps." : "";
|
|
1518
1637
|
return [
|
|
@@ -1612,7 +1731,7 @@ ${text2}` : null;
|
|
|
1612
1731
|
}
|
|
1613
1732
|
async function readWorkspaceFile(workspace, path) {
|
|
1614
1733
|
try {
|
|
1615
|
-
return await
|
|
1734
|
+
return await readFile5(resolve7(workspace, path), "utf8");
|
|
1616
1735
|
} catch {
|
|
1617
1736
|
return null;
|
|
1618
1737
|
}
|
|
@@ -1670,11 +1789,11 @@ async function occurrenceLines(workspace, path, search) {
|
|
|
1670
1789
|
return out;
|
|
1671
1790
|
}
|
|
1672
1791
|
async function listNearest(workspace, path) {
|
|
1673
|
-
let dir = dirname2(
|
|
1792
|
+
let dir = dirname2(resolve7(workspace, path));
|
|
1674
1793
|
for (let i = 0; i < 8; i++) {
|
|
1675
1794
|
try {
|
|
1676
|
-
const entries = await
|
|
1677
|
-
const rel = dir ===
|
|
1795
|
+
const entries = await readdir3(dir, { withFileTypes: true });
|
|
1796
|
+
const rel = dir === resolve7(workspace) ? "." : dir;
|
|
1678
1797
|
const names = entries.slice(0, 40).map((e) => e.isDirectory() ? `${e.name}/` : e.name);
|
|
1679
1798
|
return `${rel}:
|
|
1680
1799
|
${names.join(" ") || "(empty)"}`;
|
|
@@ -1696,14 +1815,14 @@ function formatSchema(spec) {
|
|
|
1696
1815
|
}
|
|
1697
1816
|
|
|
1698
1817
|
// src/core/agent/project-context.ts
|
|
1699
|
-
import { readFile as
|
|
1700
|
-
import { join as
|
|
1701
|
-
var INSTRUCTION_FILES = [
|
|
1818
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
1819
|
+
import { join as join3 } from "path";
|
|
1820
|
+
var INSTRUCTION_FILES = [join3(".poly", "agents.md"), "AGENTS.md"];
|
|
1702
1821
|
var MAX_CHARS2 = 8e3;
|
|
1703
1822
|
async function loadProjectInstructions(workspace) {
|
|
1704
1823
|
for (const rel of INSTRUCTION_FILES) {
|
|
1705
1824
|
try {
|
|
1706
|
-
const raw = (await
|
|
1825
|
+
const raw = (await readFile6(join3(workspace, rel), "utf8")).trim();
|
|
1707
1826
|
if (!raw) continue;
|
|
1708
1827
|
return raw.length > MAX_CHARS2 ? raw.slice(0, MAX_CHARS2) + "\n\u2026(truncated)" : raw;
|
|
1709
1828
|
} catch {
|
|
@@ -1863,6 +1982,56 @@ ${guidance}`;
|
|
|
1863
1982
|
return { finished: false, reason: "maxsteps", steps: maxSteps, messages, usage };
|
|
1864
1983
|
}
|
|
1865
1984
|
|
|
1985
|
+
// src/core/context/mentions.ts
|
|
1986
|
+
import { readdir as readdir4, readFile as readFile7, stat as stat2 } from "fs/promises";
|
|
1987
|
+
import { resolve as resolve8 } from "path";
|
|
1988
|
+
var MAX_FILE_CHARS = 1e4;
|
|
1989
|
+
var MENTION_RE = /(?:^|\s)@([\w./-]+)/g;
|
|
1990
|
+
async function resolveMentions(task, policy) {
|
|
1991
|
+
const tokens2 = [...task.matchAll(MENTION_RE)].map((m) => m[1]);
|
|
1992
|
+
const unique = [...new Set(tokens2)];
|
|
1993
|
+
if (unique.length === 0) return { task, injected: [] };
|
|
1994
|
+
const blocks = [];
|
|
1995
|
+
const injected = [];
|
|
1996
|
+
for (const token of unique) {
|
|
1997
|
+
const decision = checkPath(policy, token);
|
|
1998
|
+
if (!decision.allowed) {
|
|
1999
|
+
blocks.push(`## @${token}
|
|
2000
|
+
${t("mentions.notFound", { path: token })}`);
|
|
2001
|
+
continue;
|
|
2002
|
+
}
|
|
2003
|
+
const abs = resolve8(policy.workspace, token);
|
|
2004
|
+
try {
|
|
2005
|
+
const info = await stat2(abs);
|
|
2006
|
+
if (info.isDirectory()) {
|
|
2007
|
+
const entries = await readdir4(abs, { withFileTypes: true });
|
|
2008
|
+
const listing = entries.map((e) => e.isDirectory() ? `${e.name}/` : e.name).sort().join("\n");
|
|
2009
|
+
blocks.push(`## ${t("mentions.dirHeader", { path: decision.rel })}
|
|
2010
|
+
${listing || "(empty)"}`);
|
|
2011
|
+
injected.push(decision.rel);
|
|
2012
|
+
} else {
|
|
2013
|
+
const raw = await readFile7(abs, "utf8");
|
|
2014
|
+
const content = raw.length > MAX_FILE_CHARS ? raw.slice(0, MAX_FILE_CHARS) + "\n\u2026[truncated]" : raw;
|
|
2015
|
+
blocks.push(`## @${decision.rel}
|
|
2016
|
+
\`\`\`
|
|
2017
|
+
${content}
|
|
2018
|
+
\`\`\``);
|
|
2019
|
+
injected.push(decision.rel);
|
|
2020
|
+
}
|
|
2021
|
+
} catch {
|
|
2022
|
+
blocks.push(`## @${token}
|
|
2023
|
+
${t("mentions.notFound", { path: token })}`);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
if (injected.length === 0) return { task, injected: [] };
|
|
2027
|
+
const augmented = `${task}
|
|
2028
|
+
|
|
2029
|
+
--- ${t("mentions.injectedHeader")} ---
|
|
2030
|
+
|
|
2031
|
+
${blocks.join("\n\n")}`;
|
|
2032
|
+
return { task: augmented, injected };
|
|
2033
|
+
}
|
|
2034
|
+
|
|
1866
2035
|
// src/ui/repl.ts
|
|
1867
2036
|
import pc6 from "picocolors";
|
|
1868
2037
|
|
|
@@ -2501,10 +2670,10 @@ async function readLineTTY(prompt) {
|
|
|
2501
2670
|
stdin.resume();
|
|
2502
2671
|
stdin.on("data", onData);
|
|
2503
2672
|
try {
|
|
2504
|
-
const line = await new Promise((
|
|
2505
|
-
rl.question(prompt).then(
|
|
2506
|
-
rl.on("SIGINT", () =>
|
|
2507
|
-
rl.on("close", () =>
|
|
2673
|
+
const line = await new Promise((resolve10) => {
|
|
2674
|
+
rl.question(prompt).then(resolve10, () => resolve10(null));
|
|
2675
|
+
rl.on("SIGINT", () => resolve10(null));
|
|
2676
|
+
rl.on("close", () => resolve10(null));
|
|
2508
2677
|
});
|
|
2509
2678
|
return line === null ? null : store.expand(line);
|
|
2510
2679
|
} finally {
|
|
@@ -2649,7 +2818,7 @@ import pc7 from "picocolors";
|
|
|
2649
2818
|
// src/core/git/worktree.ts
|
|
2650
2819
|
import { mkdtemp } from "fs/promises";
|
|
2651
2820
|
import { tmpdir } from "os";
|
|
2652
|
-
import { join as
|
|
2821
|
+
import { join as join4 } from "path";
|
|
2653
2822
|
import { simpleGit } from "simple-git";
|
|
2654
2823
|
async function ensureRepo(workspace) {
|
|
2655
2824
|
const git = simpleGit(workspace);
|
|
@@ -2670,7 +2839,7 @@ async function identityArgs(git) {
|
|
|
2670
2839
|
}
|
|
2671
2840
|
async function createWorktree(git, label) {
|
|
2672
2841
|
const branch = `polypus/${label}-${Date.now().toString(36)}`;
|
|
2673
|
-
const path = await mkdtemp(
|
|
2842
|
+
const path = await mkdtemp(join4(tmpdir(), "polypus-wt-"));
|
|
2674
2843
|
await git.raw(["worktree", "add", "-b", branch, path, "HEAD"]);
|
|
2675
2844
|
return { path, branch };
|
|
2676
2845
|
}
|
|
@@ -3153,6 +3322,15 @@ async function run(task, opts) {
|
|
|
3153
3322
|
await startRepl(ctx);
|
|
3154
3323
|
}
|
|
3155
3324
|
async function executeTask(task, resolved, workspace, session) {
|
|
3325
|
+
const mention = await resolveMentions(task, {
|
|
3326
|
+
workspace,
|
|
3327
|
+
allow: session.allow,
|
|
3328
|
+
deny: session.deny
|
|
3329
|
+
});
|
|
3330
|
+
if (mention.injected.length > 0) {
|
|
3331
|
+
task = mention.task;
|
|
3332
|
+
console.log(pc8.dim(`\u21B3 @ ${mention.injected.join(", ")}`));
|
|
3333
|
+
}
|
|
3156
3334
|
const spinner3 = new Spinner();
|
|
3157
3335
|
const controller = new AbortController();
|
|
3158
3336
|
const cancel2 = listenForCancel(controller);
|
|
@@ -3288,7 +3466,7 @@ import pc9 from "picocolors";
|
|
|
3288
3466
|
|
|
3289
3467
|
// src/core/scaffold/init.ts
|
|
3290
3468
|
import { mkdir as mkdir3, writeFile as writeFile4, access } from "fs/promises";
|
|
3291
|
-
import { dirname as dirname3, join as
|
|
3469
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
3292
3470
|
|
|
3293
3471
|
// src/core/scaffold/templates.ts
|
|
3294
3472
|
function polyTemplates(locale) {
|
|
@@ -3531,7 +3709,7 @@ async function scaffoldPoly(workspace, opts) {
|
|
|
3531
3709
|
const skipped = [];
|
|
3532
3710
|
for (const [rel, content] of Object.entries(templates)) {
|
|
3533
3711
|
const display = `.poly/${rel}`;
|
|
3534
|
-
const abs =
|
|
3712
|
+
const abs = join5(workspace, ".poly", ...rel.split("/"));
|
|
3535
3713
|
if (!opts.force && await exists(abs)) {
|
|
3536
3714
|
skipped.push(display);
|
|
3537
3715
|
continue;
|
|
@@ -3631,7 +3809,7 @@ async function resolveOpenRouterKey() {
|
|
|
3631
3809
|
}
|
|
3632
3810
|
|
|
3633
3811
|
// src/cli/commands/prd.ts
|
|
3634
|
-
import { writeFile as writeFile5, readFile as
|
|
3812
|
+
import { writeFile as writeFile5, readFile as readFile8 } from "fs/promises";
|
|
3635
3813
|
import { execFile } from "child_process";
|
|
3636
3814
|
import { promisify as promisify2 } from "util";
|
|
3637
3815
|
import pc11 from "picocolors";
|
|
@@ -3723,13 +3901,13 @@ async function withRetry(fn, opts = {}) {
|
|
|
3723
3901
|
|
|
3724
3902
|
// src/cli/commands/cli-io.ts
|
|
3725
3903
|
import { readFileSync, existsSync as existsSync2 } from "fs";
|
|
3726
|
-
import { resolve as
|
|
3904
|
+
import { resolve as resolve9 } from "path";
|
|
3727
3905
|
var GUIDE_MAX = 12e3;
|
|
3728
3906
|
function readProjectGuide(files) {
|
|
3729
3907
|
const parts = [];
|
|
3730
3908
|
for (const file of files) {
|
|
3731
3909
|
try {
|
|
3732
|
-
const path =
|
|
3910
|
+
const path = resolve9(process.cwd(), file);
|
|
3733
3911
|
if (existsSync2(path)) parts.push(`# ${file}
|
|
3734
3912
|
${readFileSync(path, "utf8").trim()}`);
|
|
3735
3913
|
} catch {
|
|
@@ -3770,7 +3948,7 @@ async function prd(issueRef, opts) {
|
|
|
3770
3948
|
}
|
|
3771
3949
|
async function loadIssue(issueRef, input) {
|
|
3772
3950
|
if (input) {
|
|
3773
|
-
const raw = input === "-" ? await readStdin() : await
|
|
3951
|
+
const raw = input === "-" ? await readStdin() : await readFile8(input, "utf8");
|
|
3774
3952
|
return normalize2(JSON.parse(stripBom(raw)));
|
|
3775
3953
|
}
|
|
3776
3954
|
const num = numericRef(issueRef);
|
|
@@ -3789,7 +3967,7 @@ function normalize2(raw) {
|
|
|
3789
3967
|
}
|
|
3790
3968
|
|
|
3791
3969
|
// src/cli/commands/review.ts
|
|
3792
|
-
import { writeFile as writeFile6, readFile as
|
|
3970
|
+
import { writeFile as writeFile6, readFile as readFile9 } from "fs/promises";
|
|
3793
3971
|
import { execFile as execFile2 } from "child_process";
|
|
3794
3972
|
import { promisify as promisify3 } from "util";
|
|
3795
3973
|
import pc12 from "picocolors";
|
|
@@ -3865,7 +4043,7 @@ async function review(prRef, opts) {
|
|
|
3865
4043
|
}
|
|
3866
4044
|
}
|
|
3867
4045
|
async function loadDiff(num, input) {
|
|
3868
|
-
if (input) return input === "-" ? readStdin() :
|
|
4046
|
+
if (input) return input === "-" ? readStdin() : readFile9(input, "utf8");
|
|
3869
4047
|
const { stdout: stdout2 } = await exec3("gh", ["pr", "diff", num]);
|
|
3870
4048
|
return stdout2;
|
|
3871
4049
|
}
|
|
@@ -3877,7 +4055,7 @@ async function loadMeta(num, input) {
|
|
|
3877
4055
|
}
|
|
3878
4056
|
|
|
3879
4057
|
// src/cli/index.ts
|
|
3880
|
-
import { join as
|
|
4058
|
+
import { join as join6 } from "path";
|
|
3881
4059
|
|
|
3882
4060
|
// src/core/config/dotenv.ts
|
|
3883
4061
|
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
@@ -3946,7 +4124,7 @@ function buildProgram() {
|
|
|
3946
4124
|
}
|
|
3947
4125
|
async function main() {
|
|
3948
4126
|
try {
|
|
3949
|
-
loadDotenv([
|
|
4127
|
+
loadDotenv([join6(configDir(), ".env"), join6(process.cwd(), ".env")]);
|
|
3950
4128
|
await resolveLocale();
|
|
3951
4129
|
await buildProgram().parseAsync(process.argv);
|
|
3952
4130
|
} catch (err) {
|