@effect-agent/pr-review 0.1.0-beta.19 → 0.1.0-beta.20
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/cli.mjs +4 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +4 -4
- package/package.json +7 -7
- package/src/cli.ts +4 -0
package/dist/cli.mjs
CHANGED
|
@@ -11,12 +11,12 @@ const prFlag = Flag.integer("pr").pipe(Flag.optional, Flag.withDescription("Pull
|
|
|
11
11
|
const providerFlag = Flag.string("provider").pipe(Flag.withDefault(DEFAULT_PROVIDER), Flag.withDescription("Model provider: \"openai\" (default) or \"anthropic\"."));
|
|
12
12
|
const modelFlag = Flag.string("model").pipe(Flag.optional, Flag.withDescription(`Model id (defaults: openai ${DEFAULT_MODEL.openai}, anthropic ${DEFAULT_MODEL.anthropic}).`));
|
|
13
13
|
const effortFlag = Flag.string("effort").pipe(Flag.optional, Flag.withDescription("Reasoning effort: \"low\", \"medium\", \"high\", \"xhigh\", \"max\", or a number in [0, 1] resolved onto the provider's own ladder."));
|
|
14
|
-
const postFlag = Flag.boolean("post").pipe(Flag.withDescription("Post the review to GitHub; without it the plan prints to stdout."));
|
|
15
|
-
const applyVerdictFlag = Flag.boolean("apply-verdict").pipe(Flag.withDescription("Map the model verdict onto APPROVE/REQUEST_CHANGES instead of always COMMENT."));
|
|
16
|
-
const fanOutFlag = Flag.boolean("fan-out").pipe(Flag.withDescription("Fan the review out to bounded per-unit subagent reviewers (S1 attached delegation) instead of one flat reviewer."));
|
|
14
|
+
const postFlag = Flag.boolean("post").pipe(Flag.withDefault(false), Flag.withDescription("Post the review to GitHub; without it the plan prints to stdout."));
|
|
15
|
+
const applyVerdictFlag = Flag.boolean("apply-verdict").pipe(Flag.withDefault(false), Flag.withDescription("Map the model verdict onto APPROVE/REQUEST_CHANGES instead of always COMMENT."));
|
|
16
|
+
const fanOutFlag = Flag.boolean("fan-out").pipe(Flag.withDefault(false), Flag.withDescription("Fan the review out to bounded per-unit subagent reviewers (S1 attached delegation) instead of one flat reviewer."));
|
|
17
17
|
const ignoreFlag = Flag.string("ignore").pipe(Flag.withDefault(""), Flag.withDescription("Comma-separated glob patterns removed from the review surface, e.g. \"**/*.lock,dist/**\"."));
|
|
18
18
|
const maxFindingsFlag = Flag.integer("max-findings").pipe(Flag.optional, Flag.withDescription("Findings bound (1-20); the schema cap of 20 applies regardless."));
|
|
19
|
-
const skipUnchangedFlag = Flag.boolean("skip-unchanged").pipe(Flag.withDescription("Skip when the changeset fingerprint matches the last posted review (explicit runs review unconditionally by default)."));
|
|
19
|
+
const skipUnchangedFlag = Flag.boolean("skip-unchanged").pipe(Flag.withDefault(false), Flag.withDescription("Skip when the changeset fingerprint matches the last posted review (explicit runs review unconditionally by default)."));
|
|
20
20
|
/** An unknown --provider value; the two supported providers are spelled out. */
|
|
21
21
|
var UnknownProvider = class extends Schema.TaggedError()("UnknownProvider", { provider: Schema.String }) {
|
|
22
22
|
get message() {
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["CliCommand"],"sources":["../src/cli.ts"],"sourcesContent":["import { NodeRuntime, NodeServices } from \"@effect/platform-node\";\nimport { Console, Effect, Layer, Option, Schema } from \"effect\";\nimport { BudgetExceeded } from \"effect-agent\";\nimport { Command as CliCommand, Flag } from \"effect/unstable/cli\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport { InvalidEffortInput, parseEffortPosition, type EffortPosition } from \"./internal/effort.ts\";\nimport { PrReview, type RunReviewOptions } from \"./internal/factory.ts\";\nimport { gitHubReviewLayers, resolveReviewTarget } from \"./internal/github-env.ts\";\nimport { fingerprintUnchanged } from \"./internal/github.ts\";\nimport {\n anthropicClientLayer,\n DEFAULT_MODEL,\n DEFAULT_PROVIDER,\n describeReviewModel,\n makeAnthropicReviewModel,\n makeOpenAiReviewModel,\n openAiClientLayer,\n type ReviewProvider,\n} from \"./internal/providers.ts\";\nimport { ReviewPublicationPlan } from \"./internal/render.ts\";\nimport type { ReviewRunOutcome } from \"./internal/run.ts\";\n\n// ---------------------------------------------------------------------------\n// The CLI entrypoint: resolve which pull request to review (flags first, then\n// the GitHub Actions event environment), run one bounded ephemeral review,\n// and either print the validated publication plan (default: dry run) or post\n// it as a pull-request review (--post).\n// ---------------------------------------------------------------------------\n\nconst repoFlag = Flag.string(\"repo\").pipe(\n Flag.optional,\n Flag.withDescription(\"Repository as owner/name; defaults to GITHUB_REPOSITORY.\"),\n);\nconst prFlag = Flag.integer(\"pr\").pipe(\n Flag.optional,\n Flag.withDescription(\"Pull request number; defaults to the GITHUB_EVENT_PATH payload.\"),\n);\nconst providerFlag = Flag.string(\"provider\").pipe(\n Flag.withDefault<string>(DEFAULT_PROVIDER),\n Flag.withDescription('Model provider: \"openai\" (default) or \"anthropic\".'),\n);\nconst modelFlag = Flag.string(\"model\").pipe(\n Flag.optional,\n Flag.withDescription(\n `Model id (defaults: openai ${DEFAULT_MODEL.openai}, anthropic ${DEFAULT_MODEL.anthropic}).`,\n ),\n);\nconst effortFlag = Flag.string(\"effort\").pipe(\n Flag.optional,\n Flag.withDescription(\n 'Reasoning effort: \"low\", \"medium\", \"high\", \"xhigh\", \"max\", or a number in [0, 1] resolved onto the provider\\'s own ladder.',\n ),\n);\nconst postFlag = Flag.boolean(\"post\").pipe(\n Flag.withDescription(\"Post the review to GitHub; without it the plan prints to stdout.\"),\n);\nconst applyVerdictFlag = Flag.boolean(\"apply-verdict\").pipe(\n Flag.withDescription(\n \"Map the model verdict onto APPROVE/REQUEST_CHANGES instead of always COMMENT.\",\n ),\n);\nconst fanOutFlag = Flag.boolean(\"fan-out\").pipe(\n Flag.withDescription(\n \"Fan the review out to bounded per-unit subagent reviewers (S1 attached delegation) instead of one flat reviewer.\",\n ),\n);\nconst ignoreFlag = Flag.string(\"ignore\").pipe(\n Flag.withDefault(\"\"),\n Flag.withDescription(\n 'Comma-separated glob patterns removed from the review surface, e.g. \"**/*.lock,dist/**\".',\n ),\n);\nconst maxFindingsFlag = Flag.integer(\"max-findings\").pipe(\n Flag.optional,\n Flag.withDescription(\"Findings bound (1-20); the schema cap of 20 applies regardless.\"),\n);\nconst skipUnchangedFlag = Flag.boolean(\"skip-unchanged\").pipe(\n Flag.withDescription(\n \"Skip when the changeset fingerprint matches the last posted review (explicit runs review unconditionally by default).\",\n ),\n);\n\n/** An unknown --provider value; the two supported providers are spelled out. */\nclass UnknownProvider extends Schema.TaggedError<UnknownProvider>()(\"UnknownProvider\", {\n provider: Schema.String,\n}) {\n override get message() {\n return `Unknown provider '${this.provider}': expected \"openai\" or \"anthropic\".`;\n }\n}\n\nconst decodeProvider = (raw: string): Effect.Effect<ReviewProvider, UnknownProvider> =>\n raw === \"openai\" || raw === \"anthropic\"\n ? Effect.succeed(raw)\n : Effect.fail(UnknownProvider.make({ provider: raw }));\n\nconst command = CliCommand.make(\n \"pr-review\",\n {\n repo: repoFlag,\n pr: prFlag,\n provider: providerFlag,\n model: modelFlag,\n effort: effortFlag,\n post: postFlag,\n applyVerdict: applyVerdictFlag,\n fanOut: fanOutFlag,\n ignore: ignoreFlag,\n maxFindings: maxFindingsFlag,\n skipUnchanged: skipUnchangedFlag,\n },\n (flags) =>\n Effect.gen(function* () {\n const provider = yield* decodeProvider(flags.provider);\n const target = yield* resolveReviewTarget({\n repository: Option.getOrUndefined(flags.repo),\n number: Option.getOrUndefined(flags.pr),\n });\n const model = Option.getOrUndefined(flags.model);\n const effortRaw = Option.getOrUndefined(flags.effort);\n let effort: EffortPosition | undefined;\n if (effortRaw !== undefined) {\n effort = parseEffortPosition(effortRaw);\n if (effort === undefined) {\n return yield* InvalidEffortInput.make({ input: effortRaw });\n }\n }\n const shared = {\n applyVerdict: flags.applyVerdict,\n ignore: flags.ignore\n .split(\",\")\n .map((pattern) => pattern.trim())\n .filter((pattern) => pattern.length > 0),\n maxFindings: Option.getOrUndefined(flags.maxFindings),\n modelLabel: describeReviewModel(provider, model, effort),\n };\n\n yield* Console.log(\n `Reviewing ${target.repository}#${target.number} with ${provider}:${model ?? DEFAULT_MODEL[provider]} (${flags.post ? \"posting\" : \"dry run\"}${flags.fanOut ? \", fan-out\" : \"\"})...`,\n );\n\n const githubLayers = gitHubReviewLayers(target);\n // Fingerprint check and run under ONE provide, sharing the cached\n // pull-request snapshot; None means \"unchanged, skipped\".\n const runOrSkip = <E, R, FingerprintE, FingerprintR>(reviewer: {\n readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, E, R>;\n readonly fingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;\n }) =>\n Effect.gen(function* () {\n if (flags.skipUnchanged) {\n const current = yield* reviewer.fingerprint;\n if (yield* fingerprintUnchanged(current)) {\n return Option.none<ReviewRunOutcome>();\n }\n }\n return Option.some(yield* reviewer.run({ post: flags.post }));\n });\n\n let result: Option.Option<ReviewRunOutcome>;\n if (provider === \"anthropic\") {\n const boundModel = makeAnthropicReviewModel(model, effort);\n const reviewer = flags.fanOut\n ? PrReview.makeFanOut({ ...shared, model: boundModel })\n : PrReview.make({ ...shared, model: boundModel });\n result = yield* runOrSkip(reviewer).pipe(\n Effect.provide(Layer.merge(githubLayers, anthropicClientLayer)),\n );\n } else {\n const boundModel = makeOpenAiReviewModel(model, effort);\n const reviewer = flags.fanOut\n ? PrReview.makeFanOut({ ...shared, model: boundModel })\n : PrReview.make({ ...shared, model: boundModel });\n result = yield* runOrSkip(reviewer).pipe(\n Effect.provide(Layer.merge(githubLayers, openAiClientLayer)),\n );\n }\n\n if (Option.isNone(result)) {\n yield* Console.log(\"Skipped: changeset unchanged since the last posted review.\");\n return;\n }\n const outcome = result.value;\n\n yield* Console.log(\n `Review finished in ${outcome.turns} turn(s): verdict ${outcome.review.verdict}, ` +\n `${outcome.plan.comments.length} inline comment(s), ${outcome.plan.demoted.length} demoted finding(s).`,\n );\n if (outcome.published !== undefined) {\n yield* Console.log(`Posted ${outcome.published.event} review: ${outcome.published.url}`);\n } else {\n const encodedPlan = yield* Schema.encodeEffect(ReviewPublicationPlan)(outcome.plan);\n yield* Console.log(JSON.stringify(encodedPlan, null, 2));\n }\n }),\n).pipe(\n CliCommand.withDescription(\n \"Review one GitHub pull request with an @effect-agent/pr-review reviewer and post the validated result as a pull-request review.\",\n ),\n);\n\nconst program = CliCommand.run(command, { version: \"0.0.0\" }).pipe(\n Effect.tapError((error) =>\n Console.error(\n Schema.is(BudgetExceeded)(error)\n ? `Budget exceeded: ${error.limit} observed ${error.observedValue}, limit ${error.limitValue}.`\n : String(error),\n ),\n ),\n Effect.scoped,\n Effect.provide(Layer.merge(NodeServices.layer, FetchHttpClient.layer)),\n);\n\nNodeRuntime.runMain(program, { disableErrorReporting: true });\n"],"mappings":";;;;;;;;AA8BA,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,CAAC,KACnC,KAAK,UACL,KAAK,gBAAgB,0DAA0D,CACjF;AACA,MAAM,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,KAChC,KAAK,UACL,KAAK,gBAAgB,iEAAiE,CACxF;AACA,MAAM,eAAe,KAAK,OAAO,UAAU,CAAC,CAAC,KAC3C,KAAK,YAAoB,gBAAgB,GACzC,KAAK,gBAAgB,wDAAoD,CAC3E;AACA,MAAM,YAAY,KAAK,OAAO,OAAO,CAAC,CAAC,KACrC,KAAK,UACL,KAAK,gBACH,8BAA8B,cAAc,OAAO,cAAc,cAAc,UAAU,GAC3F,CACF;AACA,MAAM,aAAa,KAAK,OAAO,QAAQ,CAAC,CAAC,KACvC,KAAK,UACL,KAAK,gBACH,qIACF,CACF;AACA,MAAM,WAAW,KAAK,QAAQ,MAAM,CAAC,CAAC,KACpC,KAAK,gBAAgB,kEAAkE,CACzF;AACA,MAAM,mBAAmB,KAAK,QAAQ,eAAe,CAAC,CAAC,KACrD,KAAK,gBACH,+EACF,CACF;AACA,MAAM,aAAa,KAAK,QAAQ,SAAS,CAAC,CAAC,KACzC,KAAK,gBACH,kHACF,CACF;AACA,MAAM,aAAa,KAAK,OAAO,QAAQ,CAAC,CAAC,KACvC,KAAK,YAAY,EAAE,GACnB,KAAK,gBACH,4FACF,CACF;AACA,MAAM,kBAAkB,KAAK,QAAQ,cAAc,CAAC,CAAC,KACnD,KAAK,UACL,KAAK,gBAAgB,iEAAiE,CACxF;AACA,MAAM,oBAAoB,KAAK,QAAQ,gBAAgB,CAAC,CAAC,KACvD,KAAK,gBACH,uHACF,CACF;;AAGA,IAAM,kBAAN,cAA8B,OAAO,YAA6B,CAAC,CAAC,mBAAmB,EACrF,UAAU,OAAO,OACnB,CAAC,CAAC,CAAC;CACD,IAAa,UAAU;EACrB,OAAO,qBAAqB,KAAK,SAAS;CAC5C;AACF;AAEA,MAAM,kBAAkB,QACtB,QAAQ,YAAY,QAAQ,cACxB,OAAO,QAAQ,GAAG,IAClB,OAAO,KAAK,gBAAgB,KAAK,EAAE,UAAU,IAAI,CAAC,CAAC;AAEzD,MAAM,UAAUA,QAAW,KACzB,aACA;CACE,MAAM;CACN,IAAI;CACJ,UAAU;CACV,OAAO;CACP,QAAQ;CACR,MAAM;CACN,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,eAAe;AACjB,IACC,UACC,OAAO,IAAI,aAAa;CACtB,MAAM,WAAW,OAAO,eAAe,MAAM,QAAQ;CACrD,MAAM,SAAS,OAAO,oBAAoB;EACxC,YAAY,OAAO,eAAe,MAAM,IAAI;EAC5C,QAAQ,OAAO,eAAe,MAAM,EAAE;CACxC,CAAC;CACD,MAAM,QAAQ,OAAO,eAAe,MAAM,KAAK;CAC/C,MAAM,YAAY,OAAO,eAAe,MAAM,MAAM;CACpD,IAAI;CACJ,IAAI,cAAc,KAAA,GAAW;EAC3B,SAAS,oBAAoB,SAAS;EACtC,IAAI,WAAW,KAAA,GACb,OAAO,OAAO,mBAAmB,KAAK,EAAE,OAAO,UAAU,CAAC;CAE9D;CACA,MAAM,SAAS;EACb,cAAc,MAAM;EACpB,QAAQ,MAAM,OACX,MAAM,GAAG,CAAC,CACV,KAAK,YAAY,QAAQ,KAAK,CAAC,CAAC,CAChC,QAAQ,YAAY,QAAQ,SAAS,CAAC;EACzC,aAAa,OAAO,eAAe,MAAM,WAAW;EACpD,YAAY,oBAAoB,UAAU,OAAO,MAAM;CACzD;CAEA,OAAO,QAAQ,IACb,aAAa,OAAO,WAAW,GAAG,OAAO,OAAO,QAAQ,SAAS,GAAG,SAAS,cAAc,UAAU,IAAI,MAAM,OAAO,YAAY,YAAY,MAAM,SAAS,cAAc,GAAG,KAChL;CAEA,MAAM,eAAe,mBAAmB,MAAM;CAG9C,MAAM,aAA+C,aAInD,OAAO,IAAI,aAAa;EACtB,IAAI,MAAM,eAEJ;OAAA,OAAO,qBAAqB,OADT,SAAS,WACO,GACrC,OAAO,OAAO,KAAuB;EAAA;EAGzC,OAAO,OAAO,KAAK,OAAO,SAAS,IAAI,EAAE,MAAM,MAAM,KAAK,CAAC,CAAC;CAC9D,CAAC;CAEH,IAAI;CACJ,IAAI,aAAa,aAAa;EAC5B,MAAM,aAAa,yBAAyB,OAAO,MAAM;EAIzD,SAAS,OAAO,UAHC,MAAM,SACnB,SAAS,WAAW;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,IACpD,SAAS,KAAK;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,CAChB,CAAC,CAAC,KAClC,OAAO,QAAQ,MAAM,MAAM,cAAc,oBAAoB,CAAC,CAChE;CACF,OAAO;EACL,MAAM,aAAa,sBAAsB,OAAO,MAAM;EAItD,SAAS,OAAO,UAHC,MAAM,SACnB,SAAS,WAAW;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,IACpD,SAAS,KAAK;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,CAChB,CAAC,CAAC,KAClC,OAAO,QAAQ,MAAM,MAAM,cAAc,iBAAiB,CAAC,CAC7D;CACF;CAEA,IAAI,OAAO,OAAO,MAAM,GAAG;EACzB,OAAO,QAAQ,IAAI,4DAA4D;EAC/E;CACF;CACA,MAAM,UAAU,OAAO;CAEvB,OAAO,QAAQ,IACb,sBAAsB,QAAQ,MAAM,oBAAoB,QAAQ,OAAO,QAAQ,IAC1E,QAAQ,KAAK,SAAS,OAAO,sBAAsB,QAAQ,KAAK,QAAQ,OAAO,qBACtF;CACA,IAAI,QAAQ,cAAc,KAAA,GACxB,OAAO,QAAQ,IAAI,UAAU,QAAQ,UAAU,MAAM,WAAW,QAAQ,UAAU,KAAK;MAClF;EACL,MAAM,cAAc,OAAO,OAAO,aAAa,qBAAqB,CAAC,CAAC,QAAQ,IAAI;EAClF,OAAO,QAAQ,IAAI,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;CACzD;AACF,CAAC,CACL,CAAC,CAAC,KACAA,QAAW,gBACT,iIACF,CACF;AAEA,MAAM,UAAUA,QAAW,IAAI,SAAS,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,KAC5D,OAAO,UAAU,UACf,QAAQ,MACN,OAAO,GAAG,cAAc,CAAC,CAAC,KAAK,IAC3B,oBAAoB,MAAM,MAAM,YAAY,MAAM,cAAc,UAAU,MAAM,WAAW,KAC3F,OAAO,KAAK,CAClB,CACF,GACA,OAAO,QACP,OAAO,QAAQ,MAAM,MAAM,aAAa,OAAO,gBAAgB,KAAK,CAAC,CACvE;AAEA,YAAY,QAAQ,SAAS,EAAE,uBAAuB,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":["CliCommand"],"sources":["../src/cli.ts"],"sourcesContent":["import { NodeRuntime, NodeServices } from \"@effect/platform-node\";\nimport { Console, Effect, Layer, Option, Schema } from \"effect\";\nimport { BudgetExceeded } from \"effect-agent\";\nimport { Command as CliCommand, Flag } from \"effect/unstable/cli\";\nimport { FetchHttpClient } from \"effect/unstable/http\";\n\nimport { InvalidEffortInput, parseEffortPosition, type EffortPosition } from \"./internal/effort.ts\";\nimport { PrReview, type RunReviewOptions } from \"./internal/factory.ts\";\nimport { gitHubReviewLayers, resolveReviewTarget } from \"./internal/github-env.ts\";\nimport { fingerprintUnchanged } from \"./internal/github.ts\";\nimport {\n anthropicClientLayer,\n DEFAULT_MODEL,\n DEFAULT_PROVIDER,\n describeReviewModel,\n makeAnthropicReviewModel,\n makeOpenAiReviewModel,\n openAiClientLayer,\n type ReviewProvider,\n} from \"./internal/providers.ts\";\nimport { ReviewPublicationPlan } from \"./internal/render.ts\";\nimport type { ReviewRunOutcome } from \"./internal/run.ts\";\n\n// ---------------------------------------------------------------------------\n// The CLI entrypoint: resolve which pull request to review (flags first, then\n// the GitHub Actions event environment), run one bounded ephemeral review,\n// and either print the validated publication plan (default: dry run) or post\n// it as a pull-request review (--post).\n// ---------------------------------------------------------------------------\n\nconst repoFlag = Flag.string(\"repo\").pipe(\n Flag.optional,\n Flag.withDescription(\"Repository as owner/name; defaults to GITHUB_REPOSITORY.\"),\n);\nconst prFlag = Flag.integer(\"pr\").pipe(\n Flag.optional,\n Flag.withDescription(\"Pull request number; defaults to the GITHUB_EVENT_PATH payload.\"),\n);\nconst providerFlag = Flag.string(\"provider\").pipe(\n Flag.withDefault<string>(DEFAULT_PROVIDER),\n Flag.withDescription('Model provider: \"openai\" (default) or \"anthropic\".'),\n);\nconst modelFlag = Flag.string(\"model\").pipe(\n Flag.optional,\n Flag.withDescription(\n `Model id (defaults: openai ${DEFAULT_MODEL.openai}, anthropic ${DEFAULT_MODEL.anthropic}).`,\n ),\n);\nconst effortFlag = Flag.string(\"effort\").pipe(\n Flag.optional,\n Flag.withDescription(\n 'Reasoning effort: \"low\", \"medium\", \"high\", \"xhigh\", \"max\", or a number in [0, 1] resolved onto the provider\\'s own ladder.',\n ),\n);\nconst postFlag = Flag.boolean(\"post\").pipe(\n Flag.withDefault(false),\n Flag.withDescription(\"Post the review to GitHub; without it the plan prints to stdout.\"),\n);\nconst applyVerdictFlag = Flag.boolean(\"apply-verdict\").pipe(\n Flag.withDefault(false),\n Flag.withDescription(\n \"Map the model verdict onto APPROVE/REQUEST_CHANGES instead of always COMMENT.\",\n ),\n);\nconst fanOutFlag = Flag.boolean(\"fan-out\").pipe(\n Flag.withDefault(false),\n Flag.withDescription(\n \"Fan the review out to bounded per-unit subagent reviewers (S1 attached delegation) instead of one flat reviewer.\",\n ),\n);\nconst ignoreFlag = Flag.string(\"ignore\").pipe(\n Flag.withDefault(\"\"),\n Flag.withDescription(\n 'Comma-separated glob patterns removed from the review surface, e.g. \"**/*.lock,dist/**\".',\n ),\n);\nconst maxFindingsFlag = Flag.integer(\"max-findings\").pipe(\n Flag.optional,\n Flag.withDescription(\"Findings bound (1-20); the schema cap of 20 applies regardless.\"),\n);\nconst skipUnchangedFlag = Flag.boolean(\"skip-unchanged\").pipe(\n Flag.withDefault(false),\n Flag.withDescription(\n \"Skip when the changeset fingerprint matches the last posted review (explicit runs review unconditionally by default).\",\n ),\n);\n\n/** An unknown --provider value; the two supported providers are spelled out. */\nclass UnknownProvider extends Schema.TaggedError<UnknownProvider>()(\"UnknownProvider\", {\n provider: Schema.String,\n}) {\n override get message() {\n return `Unknown provider '${this.provider}': expected \"openai\" or \"anthropic\".`;\n }\n}\n\nconst decodeProvider = (raw: string): Effect.Effect<ReviewProvider, UnknownProvider> =>\n raw === \"openai\" || raw === \"anthropic\"\n ? Effect.succeed(raw)\n : Effect.fail(UnknownProvider.make({ provider: raw }));\n\nconst command = CliCommand.make(\n \"pr-review\",\n {\n repo: repoFlag,\n pr: prFlag,\n provider: providerFlag,\n model: modelFlag,\n effort: effortFlag,\n post: postFlag,\n applyVerdict: applyVerdictFlag,\n fanOut: fanOutFlag,\n ignore: ignoreFlag,\n maxFindings: maxFindingsFlag,\n skipUnchanged: skipUnchangedFlag,\n },\n (flags) =>\n Effect.gen(function* () {\n const provider = yield* decodeProvider(flags.provider);\n const target = yield* resolveReviewTarget({\n repository: Option.getOrUndefined(flags.repo),\n number: Option.getOrUndefined(flags.pr),\n });\n const model = Option.getOrUndefined(flags.model);\n const effortRaw = Option.getOrUndefined(flags.effort);\n let effort: EffortPosition | undefined;\n if (effortRaw !== undefined) {\n effort = parseEffortPosition(effortRaw);\n if (effort === undefined) {\n return yield* InvalidEffortInput.make({ input: effortRaw });\n }\n }\n const shared = {\n applyVerdict: flags.applyVerdict,\n ignore: flags.ignore\n .split(\",\")\n .map((pattern) => pattern.trim())\n .filter((pattern) => pattern.length > 0),\n maxFindings: Option.getOrUndefined(flags.maxFindings),\n modelLabel: describeReviewModel(provider, model, effort),\n };\n\n yield* Console.log(\n `Reviewing ${target.repository}#${target.number} with ${provider}:${model ?? DEFAULT_MODEL[provider]} (${flags.post ? \"posting\" : \"dry run\"}${flags.fanOut ? \", fan-out\" : \"\"})...`,\n );\n\n const githubLayers = gitHubReviewLayers(target);\n // Fingerprint check and run under ONE provide, sharing the cached\n // pull-request snapshot; None means \"unchanged, skipped\".\n const runOrSkip = <E, R, FingerprintE, FingerprintR>(reviewer: {\n readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, E, R>;\n readonly fingerprint: Effect.Effect<string, FingerprintE, FingerprintR>;\n }) =>\n Effect.gen(function* () {\n if (flags.skipUnchanged) {\n const current = yield* reviewer.fingerprint;\n if (yield* fingerprintUnchanged(current)) {\n return Option.none<ReviewRunOutcome>();\n }\n }\n return Option.some(yield* reviewer.run({ post: flags.post }));\n });\n\n let result: Option.Option<ReviewRunOutcome>;\n if (provider === \"anthropic\") {\n const boundModel = makeAnthropicReviewModel(model, effort);\n const reviewer = flags.fanOut\n ? PrReview.makeFanOut({ ...shared, model: boundModel })\n : PrReview.make({ ...shared, model: boundModel });\n result = yield* runOrSkip(reviewer).pipe(\n Effect.provide(Layer.merge(githubLayers, anthropicClientLayer)),\n );\n } else {\n const boundModel = makeOpenAiReviewModel(model, effort);\n const reviewer = flags.fanOut\n ? PrReview.makeFanOut({ ...shared, model: boundModel })\n : PrReview.make({ ...shared, model: boundModel });\n result = yield* runOrSkip(reviewer).pipe(\n Effect.provide(Layer.merge(githubLayers, openAiClientLayer)),\n );\n }\n\n if (Option.isNone(result)) {\n yield* Console.log(\"Skipped: changeset unchanged since the last posted review.\");\n return;\n }\n const outcome = result.value;\n\n yield* Console.log(\n `Review finished in ${outcome.turns} turn(s): verdict ${outcome.review.verdict}, ` +\n `${outcome.plan.comments.length} inline comment(s), ${outcome.plan.demoted.length} demoted finding(s).`,\n );\n if (outcome.published !== undefined) {\n yield* Console.log(`Posted ${outcome.published.event} review: ${outcome.published.url}`);\n } else {\n const encodedPlan = yield* Schema.encodeEffect(ReviewPublicationPlan)(outcome.plan);\n yield* Console.log(JSON.stringify(encodedPlan, null, 2));\n }\n }),\n).pipe(\n CliCommand.withDescription(\n \"Review one GitHub pull request with an @effect-agent/pr-review reviewer and post the validated result as a pull-request review.\",\n ),\n);\n\nconst program = CliCommand.run(command, { version: \"0.0.0\" }).pipe(\n Effect.tapError((error) =>\n Console.error(\n Schema.is(BudgetExceeded)(error)\n ? `Budget exceeded: ${error.limit} observed ${error.observedValue}, limit ${error.limitValue}.`\n : String(error),\n ),\n ),\n Effect.scoped,\n Effect.provide(Layer.merge(NodeServices.layer, FetchHttpClient.layer)),\n);\n\nNodeRuntime.runMain(program, { disableErrorReporting: true });\n"],"mappings":";;;;;;;;AA8BA,MAAM,WAAW,KAAK,OAAO,MAAM,CAAC,CAAC,KACnC,KAAK,UACL,KAAK,gBAAgB,0DAA0D,CACjF;AACA,MAAM,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,KAChC,KAAK,UACL,KAAK,gBAAgB,iEAAiE,CACxF;AACA,MAAM,eAAe,KAAK,OAAO,UAAU,CAAC,CAAC,KAC3C,KAAK,YAAoB,gBAAgB,GACzC,KAAK,gBAAgB,wDAAoD,CAC3E;AACA,MAAM,YAAY,KAAK,OAAO,OAAO,CAAC,CAAC,KACrC,KAAK,UACL,KAAK,gBACH,8BAA8B,cAAc,OAAO,cAAc,cAAc,UAAU,GAC3F,CACF;AACA,MAAM,aAAa,KAAK,OAAO,QAAQ,CAAC,CAAC,KACvC,KAAK,UACL,KAAK,gBACH,qIACF,CACF;AACA,MAAM,WAAW,KAAK,QAAQ,MAAM,CAAC,CAAC,KACpC,KAAK,YAAY,KAAK,GACtB,KAAK,gBAAgB,kEAAkE,CACzF;AACA,MAAM,mBAAmB,KAAK,QAAQ,eAAe,CAAC,CAAC,KACrD,KAAK,YAAY,KAAK,GACtB,KAAK,gBACH,+EACF,CACF;AACA,MAAM,aAAa,KAAK,QAAQ,SAAS,CAAC,CAAC,KACzC,KAAK,YAAY,KAAK,GACtB,KAAK,gBACH,kHACF,CACF;AACA,MAAM,aAAa,KAAK,OAAO,QAAQ,CAAC,CAAC,KACvC,KAAK,YAAY,EAAE,GACnB,KAAK,gBACH,4FACF,CACF;AACA,MAAM,kBAAkB,KAAK,QAAQ,cAAc,CAAC,CAAC,KACnD,KAAK,UACL,KAAK,gBAAgB,iEAAiE,CACxF;AACA,MAAM,oBAAoB,KAAK,QAAQ,gBAAgB,CAAC,CAAC,KACvD,KAAK,YAAY,KAAK,GACtB,KAAK,gBACH,uHACF,CACF;;AAGA,IAAM,kBAAN,cAA8B,OAAO,YAA6B,CAAC,CAAC,mBAAmB,EACrF,UAAU,OAAO,OACnB,CAAC,CAAC,CAAC;CACD,IAAa,UAAU;EACrB,OAAO,qBAAqB,KAAK,SAAS;CAC5C;AACF;AAEA,MAAM,kBAAkB,QACtB,QAAQ,YAAY,QAAQ,cACxB,OAAO,QAAQ,GAAG,IAClB,OAAO,KAAK,gBAAgB,KAAK,EAAE,UAAU,IAAI,CAAC,CAAC;AAEzD,MAAM,UAAUA,QAAW,KACzB,aACA;CACE,MAAM;CACN,IAAI;CACJ,UAAU;CACV,OAAO;CACP,QAAQ;CACR,MAAM;CACN,cAAc;CACd,QAAQ;CACR,QAAQ;CACR,aAAa;CACb,eAAe;AACjB,IACC,UACC,OAAO,IAAI,aAAa;CACtB,MAAM,WAAW,OAAO,eAAe,MAAM,QAAQ;CACrD,MAAM,SAAS,OAAO,oBAAoB;EACxC,YAAY,OAAO,eAAe,MAAM,IAAI;EAC5C,QAAQ,OAAO,eAAe,MAAM,EAAE;CACxC,CAAC;CACD,MAAM,QAAQ,OAAO,eAAe,MAAM,KAAK;CAC/C,MAAM,YAAY,OAAO,eAAe,MAAM,MAAM;CACpD,IAAI;CACJ,IAAI,cAAc,KAAA,GAAW;EAC3B,SAAS,oBAAoB,SAAS;EACtC,IAAI,WAAW,KAAA,GACb,OAAO,OAAO,mBAAmB,KAAK,EAAE,OAAO,UAAU,CAAC;CAE9D;CACA,MAAM,SAAS;EACb,cAAc,MAAM;EACpB,QAAQ,MAAM,OACX,MAAM,GAAG,CAAC,CACV,KAAK,YAAY,QAAQ,KAAK,CAAC,CAAC,CAChC,QAAQ,YAAY,QAAQ,SAAS,CAAC;EACzC,aAAa,OAAO,eAAe,MAAM,WAAW;EACpD,YAAY,oBAAoB,UAAU,OAAO,MAAM;CACzD;CAEA,OAAO,QAAQ,IACb,aAAa,OAAO,WAAW,GAAG,OAAO,OAAO,QAAQ,SAAS,GAAG,SAAS,cAAc,UAAU,IAAI,MAAM,OAAO,YAAY,YAAY,MAAM,SAAS,cAAc,GAAG,KAChL;CAEA,MAAM,eAAe,mBAAmB,MAAM;CAG9C,MAAM,aAA+C,aAInD,OAAO,IAAI,aAAa;EACtB,IAAI,MAAM,eAEJ;OAAA,OAAO,qBAAqB,OADT,SAAS,WACO,GACrC,OAAO,OAAO,KAAuB;EAAA;EAGzC,OAAO,OAAO,KAAK,OAAO,SAAS,IAAI,EAAE,MAAM,MAAM,KAAK,CAAC,CAAC;CAC9D,CAAC;CAEH,IAAI;CACJ,IAAI,aAAa,aAAa;EAC5B,MAAM,aAAa,yBAAyB,OAAO,MAAM;EAIzD,SAAS,OAAO,UAHC,MAAM,SACnB,SAAS,WAAW;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,IACpD,SAAS,KAAK;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,CAChB,CAAC,CAAC,KAClC,OAAO,QAAQ,MAAM,MAAM,cAAc,oBAAoB,CAAC,CAChE;CACF,OAAO;EACL,MAAM,aAAa,sBAAsB,OAAO,MAAM;EAItD,SAAS,OAAO,UAHC,MAAM,SACnB,SAAS,WAAW;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,IACpD,SAAS,KAAK;GAAE,GAAG;GAAQ,OAAO;EAAW,CAAC,CAChB,CAAC,CAAC,KAClC,OAAO,QAAQ,MAAM,MAAM,cAAc,iBAAiB,CAAC,CAC7D;CACF;CAEA,IAAI,OAAO,OAAO,MAAM,GAAG;EACzB,OAAO,QAAQ,IAAI,4DAA4D;EAC/E;CACF;CACA,MAAM,UAAU,OAAO;CAEvB,OAAO,QAAQ,IACb,sBAAsB,QAAQ,MAAM,oBAAoB,QAAQ,OAAO,QAAQ,IAC1E,QAAQ,KAAK,SAAS,OAAO,sBAAsB,QAAQ,KAAK,QAAQ,OAAO,qBACtF;CACA,IAAI,QAAQ,cAAc,KAAA,GACxB,OAAO,QAAQ,IAAI,UAAU,QAAQ,UAAU,MAAM,WAAW,QAAQ,UAAU,KAAK;MAClF;EACL,MAAM,cAAc,OAAO,OAAO,aAAa,qBAAqB,CAAC,CAAC,QAAQ,IAAI;EAClF,OAAO,QAAQ,IAAI,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;CACzD;AACF,CAAC,CACL,CAAC,CAAC,KACAA,QAAW,gBACT,iIACF,CACF;AAEA,MAAM,UAAUA,QAAW,IAAI,SAAS,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,KAC5D,OAAO,UAAU,UACf,QAAQ,MACN,OAAO,GAAG,cAAc,CAAC,CAAC,KAAK,IAC3B,oBAAoB,MAAM,MAAM,YAAY,MAAM,cAAc,UAAU,MAAM,WAAW,KAC3F,OAAO,KAAK,CAClB,CACF,GACA,OAAO,QACP,OAAO,QAAQ,MAAM,MAAM,aAAa,OAAO,gBAAgB,KAAK,CAAC,CACvE;AAEA,YAAY,QAAQ,SAAS,EAAE,uBAAuB,KAAK,CAAC"}
|
package/dist/index.d.mts
CHANGED
|
@@ -230,7 +230,7 @@ declare const make: <Provider, ModelProvides, ModelRequires, const Extra extends
|
|
|
230
230
|
}, PullRequestSource>, ...Extra]>>, undefined>;
|
|
231
231
|
model: Model.Model<Provider, ModelProvides | LanguageModel.LanguageModel, ModelRequires>;
|
|
232
232
|
}>;
|
|
233
|
-
readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/
|
|
233
|
+
readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/Schema").SchemaError | Agent.RunDispositionFailure<import("effect-agent").RuntimeBinding<typeof ReviewMission, typeof CodeReview, (mission: ReviewMission) => string, Toolkit.ToolsByName<[Tool.Tool<"list_changed_files", {
|
|
234
234
|
readonly parameters: typeof ListChangedFilesQuery;
|
|
235
235
|
readonly success: typeof ChangedFilesView;
|
|
236
236
|
readonly failure: typeof PullRequestSourceFailure;
|
|
@@ -347,7 +347,7 @@ declare const make: <Provider, ModelProvides, ModelRequires, const Extra extends
|
|
|
347
347
|
readonly failure: import("effect/Schema").Union<readonly [typeof PullRequestSourceFailure, typeof ReviewInputViolation]>;
|
|
348
348
|
readonly failureMode: "return";
|
|
349
349
|
}, PullRequestSource>;
|
|
350
|
-
}>>, import("effect/Scope").Scope>> | Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/
|
|
350
|
+
}>>, import("effect/Scope").Scope>> | Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/Schema").SchemaError | Agent.RunDispositionFailure<import("effect-agent").RuntimeBinding<typeof ReviewMission, typeof CodeReview, (mission: ReviewMission) => string, Toolkit.ToolsByName<[Tool.Tool<"list_changed_files", {
|
|
351
351
|
readonly parameters: typeof ListChangedFilesQuery;
|
|
352
352
|
readonly success: typeof ChangedFilesView;
|
|
353
353
|
readonly failure: typeof PullRequestSourceFailure;
|
|
@@ -541,7 +541,7 @@ declare const makeFanOut: <Provider, ModelProvides, ModelRequires>(options: PrRe
|
|
|
541
541
|
}>, undefined>;
|
|
542
542
|
model: Model.Model<Provider, ModelProvides | LanguageModel.LanguageModel, ModelRequires>;
|
|
543
543
|
}>;
|
|
544
|
-
readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/
|
|
544
|
+
readonly run: (runOptions?: RunReviewOptions) => Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/Schema").SchemaError, PullRequestSource | ReviewPublisher | Exclude<Exclude<Exclude<ModelRequires, import("effect-agent").EngineProvidedToolServices>, IdGenerator | import("effect-agent").SubagentReservations | Tool.HandlersFor<{
|
|
545
545
|
readonly read_file: Tool.Tool<"read_file", {
|
|
546
546
|
readonly parameters: typeof FileSliceQuery;
|
|
547
547
|
readonly success: typeof FileSlice;
|
|
@@ -554,7 +554,7 @@ declare const makeFanOut: <Provider, ModelProvides, ModelRequires>(options: PrRe
|
|
|
554
554
|
readonly failure: import("effect/Schema").Union<readonly [typeof PullRequestSourceFailure, typeof ReviewInputViolation]>;
|
|
555
555
|
readonly failureMode: "return";
|
|
556
556
|
}, PullRequestSource>;
|
|
557
|
-
}>>, import("effect/Scope").Scope> | Exclude<Exclude<Exclude<ModelRequires, import("effect-agent").EngineProvidedToolServices>, Tool.Handler<"delegate_file_review"> | Tool.Handler<"list_review_units"> | IdGenerator>, import("effect/Scope").Scope>> | Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/
|
|
557
|
+
}>>, import("effect/Scope").Scope> | Exclude<Exclude<Exclude<ModelRequires, import("effect-agent").EngineProvidedToolServices>, Tool.Handler<"delegate_file_review"> | Tool.Handler<"list_review_units"> | IdGenerator>, import("effect/Scope").Scope>> | Effect.Effect<ReviewRunOutcome, import("effect-agent").AgentApprovalDenied | import("effect-agent").AgentApprovalPending | import("effect-agent").AgentChildPending | import("effect-agent").AgentInputError | import("effect-agent").AgentOutputError | import("effect-agent").AgentPolicyError | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").ContextOverflowError | GitHubApiFailure | import("effect-agent").ModelProtocolError | PullRequestSourceFailure | import("effect/Schema").SchemaError, PullRequestSource | ReviewPublisher | Exclude<Exclude<Exclude<Exclude<ModelRequires, import("effect-agent").EngineProvidedToolServices>, IdGenerator | import("effect-agent").SubagentReservations | Tool.HandlersFor<{
|
|
558
558
|
readonly read_file: Tool.Tool<"read_file", {
|
|
559
559
|
readonly parameters: typeof FileSliceQuery;
|
|
560
560
|
readonly success: typeof FileSlice;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-agent/pr-review",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.20",
|
|
4
4
|
"exports": {
|
|
5
5
|
".": {
|
|
6
6
|
"types": "./dist/index.d.mts",
|
|
@@ -20,11 +20,11 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@effect/ai-anthropic": "4.0.0-
|
|
24
|
-
"@effect/ai-openai": "4.0.0-
|
|
25
|
-
"@effect/platform-node": "4.0.0-
|
|
26
|
-
"effect": "4.0.0-
|
|
27
|
-
"effect-agent": "0.1.0-beta.
|
|
23
|
+
"@effect/ai-anthropic": "4.0.0-rc.110",
|
|
24
|
+
"@effect/ai-openai": "4.0.0-rc.110",
|
|
25
|
+
"@effect/platform-node": "4.0.0-rc.110",
|
|
26
|
+
"effect": "4.0.0-rc.110",
|
|
27
|
+
"effect-agent": "0.1.0-beta.20"
|
|
28
28
|
},
|
|
29
29
|
"description": "Bounded, fail-closed GitHub pull-request reviewer built on the effect-agent public surface: schema-first review contracts, read-only tools, GitHub adapters, a configuration factory, and CLI + GitHub Actions entrypoints.",
|
|
30
30
|
"license": "MIT",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"test": "vp test --passWithNoTests"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@effect/vitest": "4.0.0-
|
|
50
|
+
"@effect/vitest": "4.0.0-rc.110",
|
|
51
51
|
"typescript": "7.0.2",
|
|
52
52
|
"vite-plus": "0.2.6"
|
|
53
53
|
}
|
package/src/cli.ts
CHANGED
|
@@ -53,14 +53,17 @@ const effortFlag = Flag.string("effort").pipe(
|
|
|
53
53
|
),
|
|
54
54
|
);
|
|
55
55
|
const postFlag = Flag.boolean("post").pipe(
|
|
56
|
+
Flag.withDefault(false),
|
|
56
57
|
Flag.withDescription("Post the review to GitHub; without it the plan prints to stdout."),
|
|
57
58
|
);
|
|
58
59
|
const applyVerdictFlag = Flag.boolean("apply-verdict").pipe(
|
|
60
|
+
Flag.withDefault(false),
|
|
59
61
|
Flag.withDescription(
|
|
60
62
|
"Map the model verdict onto APPROVE/REQUEST_CHANGES instead of always COMMENT.",
|
|
61
63
|
),
|
|
62
64
|
);
|
|
63
65
|
const fanOutFlag = Flag.boolean("fan-out").pipe(
|
|
66
|
+
Flag.withDefault(false),
|
|
64
67
|
Flag.withDescription(
|
|
65
68
|
"Fan the review out to bounded per-unit subagent reviewers (S1 attached delegation) instead of one flat reviewer.",
|
|
66
69
|
),
|
|
@@ -76,6 +79,7 @@ const maxFindingsFlag = Flag.integer("max-findings").pipe(
|
|
|
76
79
|
Flag.withDescription("Findings bound (1-20); the schema cap of 20 applies regardless."),
|
|
77
80
|
);
|
|
78
81
|
const skipUnchangedFlag = Flag.boolean("skip-unchanged").pipe(
|
|
82
|
+
Flag.withDefault(false),
|
|
79
83
|
Flag.withDescription(
|
|
80
84
|
"Skip when the changeset fingerprint matches the last posted review (explicit runs review unconditionally by default).",
|
|
81
85
|
),
|