@gaberrb/polypus 0.4.2 → 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 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.",
@@ -1974,6 +1982,56 @@ ${guidance}`;
1974
1982
  return { finished: false, reason: "maxsteps", steps: maxSteps, messages, usage };
1975
1983
  }
1976
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
+
1977
2035
  // src/ui/repl.ts
1978
2036
  import pc6 from "picocolors";
1979
2037
 
@@ -2612,10 +2670,10 @@ async function readLineTTY(prompt) {
2612
2670
  stdin.resume();
2613
2671
  stdin.on("data", onData);
2614
2672
  try {
2615
- const line = await new Promise((resolve9) => {
2616
- rl.question(prompt).then(resolve9, () => resolve9(null));
2617
- rl.on("SIGINT", () => resolve9(null));
2618
- rl.on("close", () => resolve9(null));
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));
2619
2677
  });
2620
2678
  return line === null ? null : store.expand(line);
2621
2679
  } finally {
@@ -3264,6 +3322,15 @@ async function run(task, opts) {
3264
3322
  await startRepl(ctx);
3265
3323
  }
3266
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
+ }
3267
3334
  const spinner3 = new Spinner();
3268
3335
  const controller = new AbortController();
3269
3336
  const cancel2 = listenForCancel(controller);
@@ -3742,7 +3809,7 @@ async function resolveOpenRouterKey() {
3742
3809
  }
3743
3810
 
3744
3811
  // src/cli/commands/prd.ts
3745
- import { writeFile as writeFile5, readFile as readFile7 } from "fs/promises";
3812
+ import { writeFile as writeFile5, readFile as readFile8 } from "fs/promises";
3746
3813
  import { execFile } from "child_process";
3747
3814
  import { promisify as promisify2 } from "util";
3748
3815
  import pc11 from "picocolors";
@@ -3834,13 +3901,13 @@ async function withRetry(fn, opts = {}) {
3834
3901
 
3835
3902
  // src/cli/commands/cli-io.ts
3836
3903
  import { readFileSync, existsSync as existsSync2 } from "fs";
3837
- import { resolve as resolve8 } from "path";
3904
+ import { resolve as resolve9 } from "path";
3838
3905
  var GUIDE_MAX = 12e3;
3839
3906
  function readProjectGuide(files) {
3840
3907
  const parts = [];
3841
3908
  for (const file of files) {
3842
3909
  try {
3843
- const path = resolve8(process.cwd(), file);
3910
+ const path = resolve9(process.cwd(), file);
3844
3911
  if (existsSync2(path)) parts.push(`# ${file}
3845
3912
  ${readFileSync(path, "utf8").trim()}`);
3846
3913
  } catch {
@@ -3881,7 +3948,7 @@ async function prd(issueRef, opts) {
3881
3948
  }
3882
3949
  async function loadIssue(issueRef, input) {
3883
3950
  if (input) {
3884
- const raw = input === "-" ? await readStdin() : await readFile7(input, "utf8");
3951
+ const raw = input === "-" ? await readStdin() : await readFile8(input, "utf8");
3885
3952
  return normalize2(JSON.parse(stripBom(raw)));
3886
3953
  }
3887
3954
  const num = numericRef(issueRef);
@@ -3900,7 +3967,7 @@ function normalize2(raw) {
3900
3967
  }
3901
3968
 
3902
3969
  // src/cli/commands/review.ts
3903
- import { writeFile as writeFile6, readFile as readFile8 } from "fs/promises";
3970
+ import { writeFile as writeFile6, readFile as readFile9 } from "fs/promises";
3904
3971
  import { execFile as execFile2 } from "child_process";
3905
3972
  import { promisify as promisify3 } from "util";
3906
3973
  import pc12 from "picocolors";
@@ -3976,7 +4043,7 @@ async function review(prRef, opts) {
3976
4043
  }
3977
4044
  }
3978
4045
  async function loadDiff(num, input) {
3979
- if (input) return input === "-" ? readStdin() : readFile8(input, "utf8");
4046
+ if (input) return input === "-" ? readStdin() : readFile9(input, "utf8");
3980
4047
  const { stdout: stdout2 } = await exec3("gh", ["pr", "diff", num]);
3981
4048
  return stdout2;
3982
4049
  }