@effect-agent/pr-review 0.1.0-beta.38 → 0.1.0-beta.40

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/NOTICE CHANGED
@@ -1,5 +1,4 @@
1
- This package includes adaptations of the review instructions and numbered diff
2
- hunk presentation from PR-Agent:
1
+ This package includes adaptations of the review instructions from PR-Agent:
3
2
 
4
3
  https://github.com/The-PR-Agent/pr-agent
5
4
  Pinned source: 9e6d6a5b40f9ce90bcc085466ba7a42c0837c37a
package/README.md CHANGED
@@ -1,16 +1,33 @@
1
1
  # @effect-agent/pr-review
2
2
 
3
- A small, provider-neutral review agent. One bounded model run receives every admitted patch as
4
- numbered new and old hunks, reads immutable base or head source when needed, and returns findings
5
- through a required native completion Tool. There is no voting, candidate cache, private hypothesis
3
+ A small, provider-neutral review agent. Bounded model runs receive admitted patches as
4
+ literal unified diffs, read immutable base or head source when needed, record established
5
+ findings with `record_finding`, and return findings through a required native completion Tool.
6
+ There is no voting, candidate cache, private hypothesis
6
7
  handoff, or repository code execution.
7
8
 
8
- The reviewer traces changed entry points and boundaries through downstream consumers, guards,
9
- finite resources, transformations, effects, completion, and unchanged callees. A finding must have
10
- a supported trigger, concrete terminal failure, causative changed edge, reachable impact, and a
11
- cause-level repair checked against both a legitimate boundary input and excluded scope. Incremental
12
- findings must be introduced, exposed, or materially affected by the exact delta; unrelated old bugs
13
- and target-only changes remain out of scope, while explicit reverts remain reviewable.
9
+ The native Agent `inputPrompt` projects each complete patch once, with literal newlines. It keeps
10
+ file headers, hunk ranges, additions, deletions, context, and mode or rename metadata. It does not
11
+ duplicate context into separate old/new views or JSON-escape the source for the model. The canonical
12
+ `ReviewRequest` and finding validation retain the original patches. This reduces repeated input
13
+ overhead without excluding changes; it does not guarantee a complete review within a spending cap.
14
+
15
+ The reviewer assesses every supplied patch first. Source reads resolve concrete questions about
16
+ plausible defects, such as a missing caller, guard, contract, or limit. It reuses supplied evidence
17
+ and finishes when those questions are resolved; straightforward changes can finish without source
18
+ tools. Reads prioritize implementation and owned boundary schemas over test examples, including
19
+ the definitions needed to resolve the question rather than only a nearby call site.
20
+ Findings explain a supported trigger, concrete impact, and needed correction. Changes that
21
+ expose an unchanged downstream failure remain eligible. Incremental findings must arise from the
22
+ exact delta; unrelated old bugs and target-only changes stay out of scope, while explicit reverts
23
+ remain reviewable.
24
+ Changes to collection membership, cardinality, or representation warrant checking affected
25
+ consumer limits with a supported boundary input, including transformations and aggregation.
26
+ New or moved resource acquisition warrants checking an early-failure sequence and its cleanup.
27
+ Owned untrusted-input and model-output Schema boundaries must safely handle every admitted value,
28
+ including adversarial values at the field and collection bounds.
29
+ Novelty compares base and head with the same supported operation input, including when a
30
+ previously failing helper becomes newly reachable.
14
31
 
15
32
  The result contains model findings with host-validated paths and line anchors, exact duplicate
16
33
  removal, aggregate usage, and optional host-priced cost. Unknown changed paths fail closed and
@@ -18,12 +35,62 @@ invalid inline anchors become top-level findings. Model output, usage, context,
18
35
  bytes remain bounded. Public finding paths, titles, and bodies retain their 512, 200, and
19
36
  2,000-character limits.
20
37
 
21
- The reviewer does not resolve previous findings or declare a partial review safe
22
- to merge. GitHub history, credentials, diff collection, and publication belong to
23
- the host channel.
38
+ Hosts may supply up to eight `ReviewFollowUp` values containing complete prior feedback, each
39
+ bounded to 32,000 characters. The reviewer separately checks those blockers against current source
40
+ and may return `ReviewOutcome.resolutions` with their exact IDs and fixing evidence. Omitted or
41
+ uncertain resolutions leave prior feedback open. Unknown or duplicate resolution IDs fail
42
+ verification. Incomplete, exhausted, pending-path, or excluded-path results return no resolutions.
43
+ Follow-ups appear only in the final patch batch, sharing the existing execution and spending limits.
44
+ They do not expand new-finding scope or declare a partial review safe to merge.
45
+ GitHub history, credentials, selection, dismissal authorization, and publication belong to the host.
46
+
47
+ Without host spending admission, the engine owns a cumulative 416,000-token stop policy and
48
+ reserves 160,000 tokens for a final context and completion response. The model sees its current
49
+ turn, tool, and token usage. Token, turn, or tool exhaustion permits one constrained completion
50
+ through `submit_review`; it returns validated findings and accounted usage with
51
+ `ReviewOutcome.exhausted` naming the limit. Hosts must
52
+ treat that outcome as incomplete, even when it contains no findings. Measured usage can exceed a
53
+ policy threshold before the engine observes it; this is not a provider-side spending cap.
54
+ The usage ledger records research, compaction, and finalization without a second token limit that
55
+ could abort delivery.
56
+
57
+ An optional `costControl` reports the host's pre-request spending admission and provider usage.
58
+ Supplying it replaces the cumulative token quota and completion reserve with that admission.
59
+ Cached reads still contribute to usage diagnostics, but cannot force early token finalization.
60
+ The 8-turn, 64-tool-call, 5-minute, and 128,000-token context bounds remain in force. A cost
61
+ estimator alone does not disable the token quota. Capped hosts own model-visible spending feedback
62
+ at their provider boundary; the generic turn/tool status is disabled for these runs. The Action
63
+ counts its outgoing spending status before admission and keeps it outside the reusable cache prefix.
64
+ With `costControl`, large requests run in sequential batches of at most 256,000 patch characters,
65
+ preserving the host's file order and keeping each patch complete. Each batch has a fresh context
66
+ and the same source service. All batches share the host ledger, turn and tool allowances, deadline,
67
+ and 24-finding capacity. They stop on an incomplete result or exhaustion. `pendingPaths` identifies
68
+ admitted patches never sent to a model, including a batch refused before paid inference. Hosts
69
+ must disclose those paths as unreviewed. Without `costControl`, the reviewer retains one run and its
70
+ cumulative token policy.
71
+ When the host stops research for cost, the reviewer returns `exhausted: "cost"` and delivers
72
+ recorded findings without requiring another paid call. Hosts must reserve the full possible charge
73
+ before sending each request; the port itself does not enforce a cap. The
74
+ [GitHub Action](../../action/README.md) supplies that implementation for its supported OpenAI models.
75
+ `reservedCostMicrousd` reports the maximum additional charge for requests whose usage is still
76
+ unknown, separately from the observed usage estimate.
77
+
78
+ Recorded findings also survive a later expected execution or verification failure. Such a result
79
+ has `incomplete: true`; hosts must not treat an empty or partial result as clearing the change.
80
+ The model can also set `incomplete: true` in `submit_review` when it cannot finish assessing the
81
+ supplied patches. That declaration preserves findings and becomes `ReviewOutcome.incomplete`
82
+ even when no engine limit or provider failure occurred. Host-tracked `unreviewedPaths` remain
83
+ disclosed separately and do not by themselves mark the admitted patches unfinished. An empty
84
+ complete result is not proof that the repository is defect-free.
85
+ With `costControl`, an accounted provider attempt also returns an incomplete outcome after an
86
+ expected failure, even without findings, so hosts can publish its usage and outstanding charges.
87
+ Otherwise failures without recorded findings remain typed. Defects and interruption still
88
+ propagate, and these records belong to the current run's Scope, not persistent storage.
89
+ The report retains recorded findings before adding newly submitted findings, removes exact
90
+ duplicates, and marks coverage incomplete if the combined report exceeds 24 findings.
24
91
 
25
92
  ```ts
26
- const reviewer = makeReviewer({ model, guidance, estimateCostMicrousd });
93
+ const reviewer = makeReviewer({ model, guidance, estimateCostMicrousd, costControl });
27
94
  const program = reviewer.review(request).pipe(Effect.provideService(ReviewRepository, repository));
28
95
  ```
29
96
 
@@ -36,5 +103,5 @@ access and does not cache review answers.
36
103
  `ReviewSource.fromText(request, text)` applies the shared line and character
37
104
  bounds after the host authorizes and reads a file.
38
105
 
39
- The numbered hunk presentation and portions of the review instructions are adapted from
106
+ Portions of the review instructions are adapted from
40
107
  [PR-Agent](https://github.com/The-PR-Agent/pr-agent). See `NOTICE` for its MIT license attribution.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Context, Effect, Schema } from "effect";
2
- import { IdGenerator, RunCostEstimator } from "effect-agent";
2
+ import { IdGenerator, RunCostEstimator, ThreadHistory } from "effect-agent";
3
3
  import { LanguageModel, Model, Tool, Toolkit } from "effect/unstable/ai";
4
4
  //#region src/repository.d.ts
5
5
  declare const ReadFileInput: Schema.Struct<{
@@ -51,6 +51,18 @@ declare const ReviewChange_base: Schema.Class<ReviewChange, Schema.Struct<{
51
51
  }>, {}>;
52
52
  /** One complete textual patch supplied by the host. */
53
53
  declare class ReviewChange extends ReviewChange_base {}
54
+ declare const ReviewFollowUp_base: Schema.Class<ReviewFollowUp, Schema.Struct<{
55
+ readonly id: Schema.NonEmptyString;
56
+ readonly description: Schema.NonEmptyString;
57
+ }>, {}>;
58
+ /** Complete prior feedback selected by the host for fix verification, not new defect discovery. */
59
+ declare class ReviewFollowUp extends ReviewFollowUp_base {}
60
+ declare const ReviewResolution_base: Schema.Class<ReviewResolution, Schema.Struct<{
61
+ readonly id: Schema.NonEmptyString;
62
+ readonly evidence: Schema.NonEmptyString;
63
+ }>, {}>;
64
+ /** A positive, source-backed assessment. The host still owns authorization and publication. */
65
+ declare class ReviewResolution extends ReviewResolution_base {}
54
66
  declare const ReviewRequest_base: Schema.Class<ReviewRequest, Schema.Struct<{
55
67
  readonly title: Schema.String;
56
68
  readonly description: Schema.String;
@@ -59,6 +71,7 @@ declare const ReviewRequest_base: Schema.Class<ReviewRequest, Schema.Struct<{
59
71
  readonly scope: Schema.optionalKey<Schema.Literals<readonly ["full", "incremental"]>>;
60
72
  readonly changes: Schema.$Array<typeof ReviewChange>;
61
73
  readonly unreviewedPaths: Schema.$Array<Schema.NonEmptyString>;
74
+ readonly followUps: Schema.optionalKey<Schema.$Array<typeof ReviewFollowUp>>;
62
75
  }>, {}>;
63
76
  /** The provider-neutral input to one review pass. */
64
77
  declare class ReviewRequest extends ReviewRequest_base {}
@@ -91,38 +104,45 @@ declare const ReviewUsage_base: Schema.Class<ReviewUsage, Schema.Struct<{
91
104
  readonly cacheWriteInputTokens: Schema.Natural;
92
105
  readonly outputTokens: Schema.Natural;
93
106
  readonly estimatedCostMicrousd: Schema.optionalKey<Schema.Natural>;
107
+ /** Maximum additional charge for sent requests whose usage remains unknown. */
108
+ readonly reservedCostMicrousd: Schema.optionalKey<Schema.Natural>;
94
109
  }>, {}>;
95
110
  declare class ReviewUsage extends ReviewUsage_base {}
111
+ declare const ReviewCostSnapshot_base: Schema.Class<ReviewCostSnapshot, Schema.Struct<{
112
+ readonly stopped: Schema.Boolean;
113
+ /** Admitted provider attempts, including failed or still-unmetered requests. */
114
+ readonly modelCalls: Schema.Natural;
115
+ readonly usage: typeof ReviewUsage;
116
+ }>, {}>;
117
+ /** Host accounting covers every provider attempt, including compaction and failed requests. */
118
+ declare class ReviewCostSnapshot extends ReviewCostSnapshot_base {}
119
+ /**
120
+ * A host must reserve the full possible charge before provider I/O. If admission
121
+ * stops, the reviewer delivers recorded findings without another model request.
122
+ * This port reports that decision; it does not enforce a spending limit itself.
123
+ * Supplying it replaces the cumulative token quota with the host's admission;
124
+ * per-context, turn, tool, and duration limits still apply. Accounted attempts
125
+ * return incomplete outcomes on expected failure, even without findings.
126
+ * Capped hosts own model-visible spending feedback at their provider boundary;
127
+ * the reviewer's generic turn/tool status is disabled for these runs.
128
+ */
129
+ interface ReviewCostControl {
130
+ readonly snapshot: Effect.Effect<ReviewCostSnapshot>;
131
+ }
96
132
  declare const ReviewOutcome_base: Schema.Class<ReviewOutcome, Schema.Struct<{
97
133
  readonly report: typeof ReviewReport;
98
134
  readonly turns: Schema.Natural;
99
135
  readonly usage: typeof ReviewUsage;
136
+ /** Admitted patches in batches that never started. These are not reviewed files. */
137
+ readonly pendingPaths: Schema.optionalKey<Schema.$Array<Schema.NonEmptyString>>;
138
+ /** A constrained final answer preserves findings but cannot establish complete coverage. */
139
+ readonly exhausted: Schema.optionalKey<Schema.Literals<readonly ["tokens", "tool-calls", "turns", "cost"]>>;
140
+ /** Unfinished coverage, reported by the model or caused by failure or the report capacity bound. */
141
+ readonly incomplete: Schema.optionalKey<Schema.Literal<true>>;
142
+ /** Only returned after complete coverage, with identifiers drawn from the supplied follow-ups. */
143
+ readonly resolutions: Schema.optionalKey<Schema.$Array<typeof ReviewResolution>>;
100
144
  }>, {}>;
101
145
  declare class ReviewOutcome extends ReviewOutcome_base {}
102
- declare const ReviewSubmission_base: Schema.Class<ReviewSubmission, Schema.Struct<{
103
- readonly findings: Schema.$Array<Schema.Struct<{
104
- readonly path: Schema.NonEmptyString;
105
- readonly line: Schema.optionalKey<Schema.Int>;
106
- readonly category: Schema.Literals<readonly ["correctness", "security", "concurrency", "performance", "resources", "reliability", "error-handling", "testing", "maintainability", "docs"]>;
107
- readonly title: Schema.NonEmptyString;
108
- readonly body: Schema.NonEmptyString;
109
- readonly priority: Schema.Literals<readonly [0, 1, 2, 3]>;
110
- }>>;
111
- }>, {}>;
112
- declare class ReviewSubmission extends ReviewSubmission_base {}
113
- declare const FormattedReviewRequest_base: Schema.Class<FormattedReviewRequest, Schema.Struct<{
114
- readonly title: Schema.String;
115
- readonly description: Schema.String;
116
- readonly baseRevision: Schema.NonEmptyString;
117
- readonly headRevision: Schema.NonEmptyString;
118
- readonly scope: Schema.optionalKey<Schema.Literals<readonly ["full", "incremental"]>>;
119
- readonly unreviewedPaths: Schema.$Array<Schema.NonEmptyString>;
120
- readonly changes: Schema.$Array<Schema.Struct<{
121
- readonly path: Schema.NonEmptyString;
122
- readonly formattedDiff: Schema.NonEmptyString;
123
- }>>;
124
- }>, {}>;
125
- declare class FormattedReviewRequest extends FormattedReviewRequest_base {}
126
146
  declare const ReviewVerificationError_base: Schema.Class<ReviewVerificationError, Schema.TaggedStruct<"ReviewVerificationError", {
127
147
  readonly message: Schema.String;
128
148
  }>, import("effect/Cause").YieldableError>;
@@ -132,37 +152,11 @@ interface ReviewerOptions<Provider, ModelProvides, ModelRequires> {
132
152
  readonly model: Model.Model<Provider, LanguageModel.LanguageModel | ModelProvides, ModelRequires>;
133
153
  readonly guidance?: string | undefined;
134
154
  readonly estimateCostMicrousd?: RunCostEstimator | undefined;
155
+ readonly costControl?: ReviewCostControl | undefined;
135
156
  }
136
- /** One bounded, source-backed review of the complete admitted delta. */
157
+ /** A bounded review, with sequential patch batches when a shared spending ledger is supplied. */
137
158
  declare const makeReviewer: <Provider, ModelProvides, ModelRequires>(options: ReviewerOptions<Provider, ModelProvides, ModelRequires>) => {
138
- readonly review: (request: ReviewRequest) => Effect.Effect<ReviewOutcome, ReviewVerificationError | import("effect-agent").AgentRuntimeFailure<import("effect-agent").RuntimeBinding<typeof FormattedReviewRequest, typeof ReviewSubmission, string, {
139
- readonly find_files: Tool.Tool<"find_files", {
140
- readonly parameters: Schema.Struct<{
141
- readonly query: Schema.String;
142
- readonly revision: Schema.Literals<readonly ["base", "head"]>;
143
- }>;
144
- readonly success: typeof ReviewFileList;
145
- readonly failure: typeof ReviewContextError;
146
- readonly failureMode: "return";
147
- }, never>;
148
- readonly read_file: Tool.Tool<"read_file", {
149
- readonly parameters: Schema.Struct<{
150
- readonly path: Schema.NonEmptyString;
151
- readonly revision: Schema.Literals<readonly ["base", "head"]>;
152
- readonly startLine: Schema.Int;
153
- readonly lineCount: Schema.Int;
154
- }>;
155
- readonly success: typeof ReviewSource;
156
- readonly failure: typeof ReviewContextError;
157
- readonly failureMode: "return";
158
- }, never>;
159
- readonly submit_review: Tool.Tool<"submit_review", {
160
- readonly parameters: typeof ReviewSubmission;
161
- readonly success: Schema.Null;
162
- readonly failure: Schema.Never;
163
- readonly failureMode: "error";
164
- }, never>;
165
- }, Provider, ModelProvides, ModelRequires, never, never, undefined>, import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded, never>, ReviewRepository | Exclude<Exclude<Exclude<ModelRequires, import("effect-agent").EngineProvidedToolServices>, Tool.Handler<"submit_review"> | IdGenerator | Tool.HandlersFor<{
159
+ readonly review: (request: ReviewRequest) => Effect.Effect<ReviewOutcome, 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-agent").AgentToolAuthorizationDenied | import("effect/unstable/ai/AiError").AiError | import("effect-agent").BudgetAdapterError | import("effect-agent").BudgetExceeded | import("effect-agent").CompactionError | import("effect-agent").ContextBudgetError | import("effect-agent").ContextOverflowError | import("effect-agent").MemoryRecallError | import("effect-agent").ModelProtocolError | ReviewVerificationError | import("effect-agent").ThreadHistoryError, ReviewRepository | Exclude<Exclude<Exclude<Exclude<(import("effect-agent").ModelServices extends ModelProvides | LanguageModel.LanguageModel | Model.ModelName | Model.ProviderName ? Model.Model<Provider, ModelProvides | LanguageModel.LanguageModel, ModelRequires> : never) extends (infer T) ? T extends (import("effect-agent").ModelServices extends ModelProvides | LanguageModel.LanguageModel | Model.ModelName | Model.ProviderName ? Model.Model<Provider, ModelProvides | LanguageModel.LanguageModel, ModelRequires> : never) ? T extends import("effect/Layer").Layer<infer _Provides, infer _Error, infer Services> ? Services : never : never : never, import("effect-agent").EngineProvidedToolServices>, Tool.Handler<"record_finding">>, Tool.Handler<"submit_review"> | IdGenerator | import("effect-agent").RunContextPreparation | ThreadHistory | Tool.HandlersFor<{
166
160
  readonly find_files: Tool.Tool<"find_files", {
167
161
  readonly parameters: Schema.Struct<{
168
162
  readonly query: Schema.String;
@@ -186,5 +180,5 @@ declare const makeReviewer: <Provider, ModelProvides, ModelRequires>(options: Re
186
180
  }>>, import("effect/Scope").Scope>>;
187
181
  };
188
182
  //#endregion
189
- export { ReviewCategory, ReviewChange, ReviewContextError, ReviewFileList, ReviewFinding, ReviewOutcome, ReviewReport, ReviewRepository, ReviewRequest, ReviewSeverity, ReviewSource, ReviewUsage, ReviewVerificationError, ReviewerOptions, type RunCostEstimator, isCommentableLine, makeReviewer };
183
+ export { ReviewCategory, ReviewChange, ReviewContextError, ReviewCostControl, ReviewCostSnapshot, ReviewFileList, ReviewFinding, ReviewFollowUp, ReviewOutcome, ReviewReport, ReviewRepository, ReviewRequest, ReviewResolution, ReviewSeverity, ReviewSource, ReviewUsage, ReviewVerificationError, ReviewerOptions, type RunCostEstimator, isCommentableLine, makeReviewer };
190
184
  //# sourceMappingURL=index.d.mts.map