( args: string, context: ToolUseContext, billingNote?: string, )
| 126 | * (ultrareviewCommand.tsx handles the dialog). |
| 127 | */ |
| 128 | export async function launchRemoteReview( |
| 129 | args: string, |
| 130 | context: ToolUseContext, |
| 131 | billingNote?: string, |
| 132 | ): Promise<ContentBlockParam[] | null> { |
| 133 | const eligibility = await checkRemoteAgentEligibility() |
| 134 | // Synthetic DEFAULT_CODE_REVIEW_ENVIRONMENT_ID works without per-org CCR |
| 135 | // setup, so no_remote_environment isn't a blocker. Server-side quota |
| 136 | // consume at session creation routes billing: first N zero-rate, then |
| 137 | // anthropic:cccr org-service-key (overage-only). |
| 138 | if (!eligibility.eligible) { |
| 139 | const blockers = eligibility.errors.filter( |
| 140 | e => e.type !== 'no_remote_environment', |
| 141 | ) |
| 142 | if (blockers.length > 0) { |
| 143 | logEvent('tengu_review_remote_precondition_failed', { |
| 144 | precondition_errors: blockers |
| 145 | .map(e => e.type) |
| 146 | .join( |
| 147 | ',', |
| 148 | ) as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 149 | }) |
| 150 | const reasons = blockers.map(formatPreconditionError).join('\n') |
| 151 | return [ |
| 152 | { |
| 153 | type: 'text', |
| 154 | text: `Ultrareview cannot launch:\n${reasons}`, |
| 155 | }, |
| 156 | ] |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | const resolvedBillingNote = billingNote ?? '' |
| 161 | |
| 162 | const prNumber = args.trim() |
| 163 | const isPrNumber = /^\d+$/.test(prNumber) |
| 164 | // Synthetic code_review env. Go taggedid.FromUUID(TagEnvironment, |
| 165 | // UUID{...,0x02}) encodes with version prefix '01' — NOT Python's |
| 166 | // legacy tagged_id() format. Verified in prod. |
| 167 | const CODE_REVIEW_ENV_ID = 'env_011111111111111111111113' |
| 168 | // Lite-review bypasses bughunter.go entirely, so it doesn't see the |
| 169 | // webhook's bug_hunter_config (different GB project). These env vars are |
| 170 | // the only tuning surface — without them, run_hunt.sh's bash defaults |
| 171 | // apply (60min, 120s agent timeout), and 120s kills verifiers mid-run |
| 172 | // which causes infinite respawn. |
| 173 | // |
| 174 | // total_wallclock must stay below RemoteAgentTask's 30min poll timeout |
| 175 | // with headroom for finalization (~3min synthesis). Per-field guards |
| 176 | // match autoDream.ts — GB cache can return stale wrong-type values. |
| 177 | const raw = getFeatureValue_CACHED_MAY_BE_STALE<Record< |
| 178 | string, |
| 179 | unknown |
| 180 | > | null>('tengu_review_bughunter_config', null) |
| 181 | const posInt = (v: unknown, fallback: number, max?: number): number => { |
| 182 | if (typeof v !== 'number' || !Number.isFinite(v)) return fallback |
| 183 | const n = Math.floor(v) |
| 184 | if (n <= 0) return fallback |
| 185 | return max !== undefined && n > max ? fallback : n |
no test coverage detected