poe-code 3.0.236 → 3.0.237

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.
@@ -40385,6 +40385,7 @@ function capitalize(value) {
40385
40385
 
40386
40386
  // packages/agent-code-review/src/config-scope.ts
40387
40387
  init_src7();
40388
+ import { isAbsolute as isAbsolute3 } from "node:path";
40388
40389
  function parseHumanGate(value) {
40389
40390
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
40390
40391
  throw new Error("humanGate must be an object");
@@ -40401,13 +40402,23 @@ function parseHumanGate(value) {
40401
40402
  }
40402
40403
  return { provider: provider2 };
40403
40404
  }
40405
+ function parseCodeReviewProfileDirectories(value) {
40406
+ if (!Array.isArray(value) || value.some((directory) => typeof directory !== "string")) {
40407
+ throw new Error("codeReview.profileDirectories must be an array of strings");
40408
+ }
40409
+ const directories = value.map((directory) => directory.trim());
40410
+ if (directories.some((directory) => !directory || !isAbsolute3(directory))) {
40411
+ throw new Error("codeReview.profileDirectories entries must be absolute paths");
40412
+ }
40413
+ return [...new Set(directories)];
40414
+ }
40404
40415
  function parseCodeReviewConfigDocument(value) {
40405
40416
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
40406
40417
  throw new Error("codeReview must be an object");
40407
40418
  }
40408
40419
  const config = value;
40409
40420
  for (const key2 of Object.keys(config)) {
40410
- if (!["agent", "draftStore", "humanGate"].includes(key2)) {
40421
+ if (!["agent", "draftStore", "humanGate", "profileDirectories"].includes(key2)) {
40411
40422
  throw new Error(`codeReview.${key2} is not supported`);
40412
40423
  }
40413
40424
  }
@@ -40420,7 +40431,8 @@ function parseCodeReviewConfigDocument(value) {
40420
40431
  return {
40421
40432
  ...config.agent === void 0 ? {} : { agent: config.agent },
40422
40433
  ...config.draftStore === void 0 ? {} : { draftStore: config.draftStore },
40423
- ...config.humanGate === void 0 ? {} : { humanGate: parseHumanGate(config.humanGate) }
40434
+ ...config.humanGate === void 0 ? {} : { humanGate: parseHumanGate(config.humanGate) },
40435
+ ...config.profileDirectories === void 0 ? {} : { profileDirectories: parseCodeReviewProfileDirectories(config.profileDirectories) }
40424
40436
  };
40425
40437
  }
40426
40438
  var codeReviewConfigScope = defineScope("codeReview", {
@@ -40439,6 +40451,12 @@ var codeReviewConfigScope = defineScope("codeReview", {
40439
40451
  default: { provider: "none" },
40440
40452
  parse: parseHumanGate,
40441
40453
  doc: "External human-gate configuration for code review runs."
40454
+ },
40455
+ profileDirectories: {
40456
+ type: "json",
40457
+ default: [],
40458
+ parse: parseCodeReviewProfileDirectories,
40459
+ doc: "Absolute external reviewer profile directories, in precedence order after repo-local profiles."
40442
40460
  }
40443
40461
  });
40444
40462
 
@@ -40462,7 +40480,7 @@ import {
40462
40480
  stat as stat6,
40463
40481
  unlink as unlink4
40464
40482
  } from "node:fs/promises";
40465
- import { basename as basename2, dirname, isAbsolute as isAbsolute3, parse as parse6, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
40483
+ import { basename as basename2, dirname, isAbsolute as isAbsolute4, parse as parse6, relative as relative2, resolve as resolve2, sep as sep2 } from "node:path";
40466
40484
 
40467
40485
  // packages/github-review/src/command.ts
40468
40486
  import { spawnSync } from "node:child_process";
@@ -42144,7 +42162,7 @@ function codeReviewFileName(prUrl) {
42144
42162
  }
42145
42163
  function resolveCodeReviewStoreDirectory(cwd, directory = DEFAULT_CODE_REVIEW_REVIEWS_DIRECTORY) {
42146
42164
  const root = resolve2(cwd, CODE_REVIEW_DIRECTORY);
42147
- const target = isAbsolute3(directory) ? resolve2(directory) : resolve2(cwd, directory);
42165
+ const target = isAbsolute4(directory) ? resolve2(directory) : resolve2(cwd, directory);
42148
42166
  const fromRoot = relative2(root, target);
42149
42167
  if (fromRoot.startsWith("..") || fromRoot.startsWith(sep2)) {
42150
42168
  throw new Error(`Code review draft store must stay under ${root}: ${target}`);
@@ -42643,7 +42661,7 @@ async function assertDirectoryPath(directory) {
42643
42661
  }
42644
42662
  }
42645
42663
  function containedPath(directory, name) {
42646
- if (!name || isAbsolute3(name)) {
42664
+ if (!name || isAbsolute4(name)) {
42647
42665
  throw new Error(`Code review path name is unsafe: ${name}`);
42648
42666
  }
42649
42667
  const root = resolve2(directory);
@@ -42742,7 +42760,8 @@ async function loadCodeReviewConfig(options) {
42742
42760
  return {
42743
42761
  ...agent2 ? { agent: agent2 } : {},
42744
42762
  draftStore,
42745
- humanGate: config.humanGate
42763
+ humanGate: config.humanGate,
42764
+ profileDirectories: config.profileDirectories
42746
42765
  };
42747
42766
  }
42748
42767
  async function validatePersistedCodeReviewConfig(options) {
@@ -42787,6 +42806,9 @@ async function resolveCodeReviewRunOptions(input, configOptions) {
42787
42806
  ...agent2 ? { agent: agent2 } : {},
42788
42807
  draftStore,
42789
42808
  humanGate: input.humanGate ?? config.humanGate,
42809
+ profileDirectories: parseCodeReviewProfileDirectories(
42810
+ input.profileDirectories ?? config.profileDirectories
42811
+ ),
42790
42812
  ...input.profilePath === void 0 ? {} : { profilePath: input.profilePath },
42791
42813
  ...input.promptPath === void 0 ? {} : { promptPath: input.promptPath },
42792
42814
  ...input.profiles === void 0 ? {} : { profiles: input.profiles },
@@ -42794,12 +42816,18 @@ async function resolveCodeReviewRunOptions(input, configOptions) {
42794
42816
  };
42795
42817
  }
42796
42818
  async function resolveCodeReviewRuntimeOptions(input) {
42797
- return resolveCodeReviewRunOptions(input, {
42819
+ return resolveCodeReviewRunOptions(input, runtimeConfigOptions(input.cwd));
42820
+ }
42821
+ async function loadCodeReviewRuntimeConfig(cwd) {
42822
+ return loadCodeReviewConfig(runtimeConfigOptions(cwd));
42823
+ }
42824
+ function runtimeConfigOptions(cwd) {
42825
+ return {
42798
42826
  fs: nativeConfigFs,
42799
42827
  filePath: resolveConfigPath(homedir4()),
42800
- projectFilePath: resolveProjectConfigPath(input.cwd),
42828
+ projectFilePath: resolveProjectConfigPath(cwd),
42801
42829
  env: process.env
42802
- });
42830
+ };
42803
42831
  }
42804
42832
  async function loadDefaultPoeCodeAgent(input) {
42805
42833
  const agent2 = await createConfigStore({
@@ -42896,8 +42924,40 @@ async function loadCodeReviewPrompt(filePath, reader) {
42896
42924
  return requireMarkdownBody(parsed.content, filePath);
42897
42925
  }
42898
42926
  async function discoverCodeReviewProfiles(input) {
42899
- const profilesDirectory = join2(codeReviewAssetsDirectory(input.cwd), "profiles");
42900
- await assertContainedAssetDirectoryOrMissing(resolve3(input.cwd), profilesDirectory);
42927
+ const cwd = resolve3(input.cwd);
42928
+ const directories = [
42929
+ { path: join2(codeReviewAssetsDirectory(cwd), "profiles"), source: "repo", root: cwd },
42930
+ ...parseCodeReviewProfileDirectories(input.profileDirectories ?? []).map((directory) => ({
42931
+ path: resolve3(directory),
42932
+ source: "external",
42933
+ root: resolve3(directory)
42934
+ }))
42935
+ ];
42936
+ const profiles = /* @__PURE__ */ new Map();
42937
+ const normalizedNames = /* @__PURE__ */ new Map();
42938
+ for (const directory of directories) {
42939
+ for (const profile of await discoverProfilesInDirectory(directory)) {
42940
+ const normalized = profile.name.normalize("NFKC").toLowerCase();
42941
+ const existingName = normalizedNames.get(normalized);
42942
+ if (existingName && existingName !== profile.name) {
42943
+ throw new Error(`Code review profile filenames normalize to the same name: ${profile.name}`);
42944
+ }
42945
+ normalizedNames.set(normalized, profile.name);
42946
+ if (!profiles.has(profile.name)) profiles.set(profile.name, profile);
42947
+ }
42948
+ }
42949
+ const availableNames = [...profiles.keys()];
42950
+ if (availableNames.length === 0) {
42951
+ validateProfileFilters(input.filters, ["generic"]);
42952
+ return [{ name: "generic", content: BUILT_IN_GENERIC_PROFILE, source: "built-in" }];
42953
+ }
42954
+ validateProfileFilters(input.filters, availableNames);
42955
+ const filterSet = input.filters?.length ? new Set(input.filters) : void 0;
42956
+ return [...profiles.values()].filter((profile) => !filterSet || filterSet.has(profile.name));
42957
+ }
42958
+ async function discoverProfilesInDirectory(input) {
42959
+ const profilesDirectory = input.path;
42960
+ await assertContainedAssetDirectoryOrMissing(input.root, profilesDirectory);
42901
42961
  let profileFileNames;
42902
42962
  try {
42903
42963
  const profileEntries = await readdir10(profilesDirectory, {
@@ -42915,40 +42975,18 @@ async function discoverCodeReviewProfiles(input) {
42915
42975
  }
42916
42976
  profileFileNames = [];
42917
42977
  }
42918
- const availableNames = profileFileNames.map(
42919
- (fileName) => requireSafeDocumentSegment(
42920
- profileNameFromFile(fileName),
42921
- `${join2(profilesDirectory, fileName)}: filename`
42922
- )
42923
- );
42924
- const normalizedNames = /* @__PURE__ */ new Set();
42925
- for (const name of availableNames) {
42926
- const normalized = name.normalize("NFKC").toLowerCase();
42927
- if (normalizedNames.has(normalized)) {
42928
- throw new Error(`Code review profile filenames normalize to the same name: ${name}`);
42929
- }
42930
- normalizedNames.add(normalized);
42931
- }
42932
- if (availableNames.length === 0) {
42933
- validateProfileFilters(input.filters, ["generic"]);
42934
- return [
42935
- {
42936
- name: "generic",
42937
- content: BUILT_IN_GENERIC_PROFILE,
42938
- source: "built-in"
42939
- }
42940
- ];
42941
- }
42942
- validateProfileFilters(input.filters, availableNames);
42943
- const filterSet = input.filters?.length ? new Set(input.filters) : void 0;
42944
42978
  return Promise.all(
42945
- profileFileNames.filter((fileName) => !filterSet || filterSet.has(profileNameFromFile(fileName))).map(async (fileName) => {
42979
+ profileFileNames.map(async (fileName) => {
42980
+ const name = requireSafeDocumentSegment(
42981
+ profileNameFromFile(fileName),
42982
+ `${join2(profilesDirectory, fileName)}: filename`
42983
+ );
42946
42984
  const filePath = join2(profilesDirectory, fileName);
42947
42985
  return {
42948
- name: profileNameFromFile(fileName),
42986
+ name,
42949
42987
  content: await loadCodeReviewProfile(filePath),
42950
42988
  filePath,
42951
- source: "repo"
42989
+ source: input.source
42952
42990
  };
42953
42991
  })
42954
42992
  );
@@ -43023,6 +43061,16 @@ async function ensureContainedDirectory(cwd, targetDirectory) {
43023
43061
  }
43024
43062
  }
43025
43063
  async function assertContainedAssetDirectoryOrMissing(cwd, targetDirectory) {
43064
+ let rootStatus;
43065
+ try {
43066
+ rootStatus = await lstat8(cwd);
43067
+ } catch (error2) {
43068
+ if (isMissingFileError4(error2)) return;
43069
+ throw error2;
43070
+ }
43071
+ if (!rootStatus.isDirectory()) {
43072
+ throw new Error(`Code review asset directory is not a regular directory: ${cwd}`);
43073
+ }
43026
43074
  const pathFromCwd = relative3(cwd, targetDirectory);
43027
43075
  if (pathFromCwd.startsWith("..") || pathFromCwd.startsWith(sep3)) {
43028
43076
  throw new Error(`Code review asset directory escapes repository: ${targetDirectory}`);
@@ -47608,7 +47656,8 @@ function parseCodeReviewAgentMcpArgs(argv) {
47608
47656
  "--cwd",
47609
47657
  "--draft-store",
47610
47658
  "--agent",
47611
- "--profiles"
47659
+ "--profiles",
47660
+ "--profile-directories"
47612
47661
  ]);
47613
47662
  for (let index = 0; index < argv.length; index += 2) {
47614
47663
  const flag = argv[index];
@@ -47629,6 +47678,7 @@ function parseCodeReviewAgentMcpArgs(argv) {
47629
47678
  throw new Error(`Invalid code-review MCP role: ${role}`);
47630
47679
  }
47631
47680
  const profiles = values.get("--profiles")?.split(",");
47681
+ const profileDirectories = values.has("--profile-directories") ? parseCodeReviewProfileDirectories(JSON.parse(requiredValue(values, "--profile-directories"))) : void 0;
47632
47682
  if (values.has("--profiles") && profiles?.length === 0) {
47633
47683
  throw new Error("--profiles requires at least one profile");
47634
47684
  }
@@ -47639,6 +47689,7 @@ function parseCodeReviewAgentMcpArgs(argv) {
47639
47689
  cwd: requiredValue(values, "--cwd"),
47640
47690
  ...values.has("--draft-store") ? { draftStore: requiredValue(values, "--draft-store") } : {},
47641
47691
  agent: requiredValue(values, "--agent"),
47692
+ ...profileDirectories ? { profileDirectories } : {},
47642
47693
  ...profiles && profiles.length > 0 ? {
47643
47694
  profiles: [
47644
47695
  ...new Set(profiles.map((profile) => requireSafeDocumentSegment(profile, "--profiles")))
@@ -47664,6 +47715,9 @@ function createCodeReviewAgentMcpConfig(context) {
47664
47715
  if (context.profiles?.length) {
47665
47716
  args.push("--profiles", context.profiles.join(","));
47666
47717
  }
47718
+ if (context.profileDirectories?.length) {
47719
+ args.push("--profile-directories", JSON.stringify(context.profileDirectories));
47720
+ }
47667
47721
  return { transport: "stdio", command: "poe-code", args: ["code-review", ...args] };
47668
47722
  }
47669
47723
  function createCodeReviewAgentMcpGroup(context, dependencies = {}) {
@@ -47756,7 +47810,8 @@ function createCodeReviewAgentMcpGroup(context, dependencies = {}) {
47756
47810
  params: S.Object({}),
47757
47811
  handler: async () => discoverCodeReviewProfiles({
47758
47812
  cwd: context.cwd,
47759
- filters: context.profiles
47813
+ filters: context.profiles,
47814
+ profileDirectories: context.profileDirectories
47760
47815
  })
47761
47816
  });
47762
47817
  const agentSpawnCommand = defineCommand({
@@ -47772,7 +47827,8 @@ function createCodeReviewAgentMcpGroup(context, dependencies = {}) {
47772
47827
  const pr = canonicalPullRequestUrl(params.pr);
47773
47828
  const profiles = await discoverCodeReviewProfiles({
47774
47829
  cwd: context.cwd,
47775
- filters: context.profiles
47830
+ filters: context.profiles,
47831
+ profileDirectories: context.profileDirectories
47776
47832
  });
47777
47833
  const profile = profiles.find((candidate) => candidate.name === params.profile);
47778
47834
  if (!profile) {
@@ -48093,7 +48149,8 @@ async function runCodeReview(input, dependencies = {}) {
48093
48149
  }
48094
48150
  const profiles = await discoverCodeReviewProfiles({
48095
48151
  cwd: options.cwd,
48096
- filters: options.profiles
48152
+ filters: options.profiles,
48153
+ profileDirectories: options.profileDirectories
48097
48154
  });
48098
48155
  const [profile, promptTemplate, prDetails, diff2, priorActivity] = await Promise.all([
48099
48156
  resolveProfile(input, options, profiles),
@@ -48132,6 +48189,7 @@ async function runCodeReview(input, dependencies = {}) {
48132
48189
  cwd: options.cwd,
48133
48190
  draftStore,
48134
48191
  agent: agent2,
48192
+ profileDirectories: options.profileDirectories,
48135
48193
  ...options.profiles ? { profiles: options.profiles } : {}
48136
48194
  });
48137
48195
  const spawnResult = await (dependencies.spawnAgent ?? spawnWithPoeCode3)(agent2, prompt, {
@@ -48249,7 +48307,8 @@ var agentMcpCommand = defineCommand({
48249
48307
  cwd: S.String({ description: "Repository working directory." }),
48250
48308
  draftStore: S.Optional(S.String({ description: "Absolute YAML review state directory." })),
48251
48309
  agent: S.String({ description: "Poe Code agent used for subagents." }),
48252
- profiles: S.Optional(S.String({ description: "Comma-separated allowed profile names." }))
48310
+ profiles: S.Optional(S.String({ description: "Comma-separated allowed profile names." })),
48311
+ profileDirectories: S.Optional(S.String({ description: "JSON array of external profile directories." }))
48253
48312
  }),
48254
48313
  scope: ["cli"],
48255
48314
  handler: async ({ params }) => runCodeReviewAgentMcp(
@@ -48265,7 +48324,8 @@ var agentMcpCommand = defineCommand({
48265
48324
  ...params.draftStore ? ["--draft-store", params.draftStore] : [],
48266
48325
  "--agent",
48267
48326
  params.agent,
48268
- ...params.profiles ? ["--profiles", params.profiles] : []
48327
+ ...params.profiles ? ["--profiles", params.profiles] : [],
48328
+ ...params.profileDirectories ? ["--profile-directories", params.profileDirectories] : []
48269
48329
  ])
48270
48330
  )
48271
48331
  });
@@ -48288,18 +48348,22 @@ var installCodeReviewAssetsCommand = defineCommand({
48288
48348
  });
48289
48349
  var listCodeReviewProfilesCommand = defineCommand({
48290
48350
  name: "profiles",
48291
- description: "List repo-local code review profiles.",
48351
+ description: "List configured code review profiles.",
48292
48352
  params: S.Object({
48293
48353
  cwd: S.Optional(S.String({ description: "Repository root directory." }))
48294
48354
  }),
48295
48355
  scope: ["cli"],
48296
- handler: async ({ params }) => (await discoverCodeReviewProfiles({ cwd: params.cwd?.trim() || process.cwd() })).map(
48297
- ({ name, source, filePath }) => ({
48298
- name,
48299
- source,
48300
- ...filePath ? { filePath } : {}
48301
- })
48302
- )
48356
+ handler: async ({ params }) => {
48357
+ const cwd = params.cwd?.trim() || process.cwd();
48358
+ const config = await loadCodeReviewRuntimeConfig(cwd);
48359
+ return (await discoverCodeReviewProfiles({ cwd, profileDirectories: config.profileDirectories })).map(
48360
+ ({ name, source, filePath }) => ({
48361
+ name,
48362
+ source,
48363
+ ...filePath ? { filePath } : {}
48364
+ })
48365
+ );
48366
+ }
48303
48367
  });
48304
48368
  var readCodeReviewDraftCommand = defineCommand({
48305
48369
  name: "drafts",