Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions agents/base2/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ import {
type SecretAgentDefinition,
} from '../types/secret-agent-definition'

function formatCurrentDate(date: Date): string {
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
}).format(date)
}

export function createBase2(
mode: 'default' | 'free' | 'lite' | 'max' | 'fast',
options?: {
Expand Down Expand Up @@ -129,6 +137,8 @@ export function createBase2(

systemPrompt: `You are Buffy, a strategic assistant that orchestrates complex coding tasks through specialized sub-agents. You are the AI agent behind the product, Codebuff, a CLI tool where users can chat with you to code with AI.

Current date: ${formatCurrentDate(new Date())}.

# Core Mandates

- **Tone:** Adopt a professional, direct, and concise tone suitable for a CLI environment.
Expand Down
25 changes: 25 additions & 0 deletions common/src/types/freebuff-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,31 @@ export type FreebuffIpPrivacySignal =
| 'hosting'
| 'service'

export type FreebuffSpurStatus =
| 'not_checked'
| 'clean'
| 'suspicious'
| 'failed'

export type FreebuffPrivacyDecision =
| 'allowed_clean'
| 'ipinfo_suspicious_spur_clean'
| 'corroborated_block'
| 'cloudflare_tor_block'
| 'spur_failed_limited'
| 'ipinfo_failed_limited'
| 'limited_other'

export type FreebuffPrivacyProviderDecision =
| 'not_checked'
| 'cloudflare_tor'
| 'ipinfo_clean'
| 'ipinfo_failed'
| 'ipinfo_only'
| 'spur_failed'
| 'corroborated_soft'
| 'corroborated_hard'

export interface FreebuffLimitedModeReason {
/** Present for limited access so the model picker can explain why the
* reduced model set is shown without re-running geo/IP logic locally. */
Expand Down
1 change: 1 addition & 0 deletions docs/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Server secrets: validated in `packages/internal/src/env-schema.ts` (used via `@codebuff/internal/env`).
- Runtime/OS env: pass typed snapshots instead of reading `process.env` throughout the codebase.
- `IPINFO_TOKEN` is required; free-mode country gating uses it to check IPinfo privacy signals for VPN/proxy/Tor/relay/hosting traffic.
- `SPUR_TOKEN` is required; hard VPN/proxy/Tor/residential-proxy free-mode blocks require Spur Context API corroboration. In allowlisted countries, a successful clean Spur result overrides IPinfo privacy signals back to full access, while a Spur lookup failure falls back to limited access.
- `CODEBUFF_FULL_TELEMETRY=true` or `CODEBUFF_FULL_TELEMETRY_IDS=user-id,email@example.com`
disables client analytics sampling for targeted debugging. Use sparingly because it can send full CLI log payloads.

Expand Down
2 changes: 1 addition & 1 deletion docs/freebuff-waiting-room.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ All endpoints authenticate via the standard `Authorization: Bearer <api-key>` or
- Existing active+unexpired row, **different model** → reject with `model_locked` (HTTP 409); `active_instance_id` is **not** rotated so the other CLI stays valid. Client must DELETE the session before switching.
- Existing active+expired row → reset to queued with fresh `queued_at` and the requested `model` (re-queue at back).

Before any of those state transitions, the handler requires a resolved allowlisted country and a successful IPinfo privacy check. IPinfo `anonymous`, `vpn`, `proxy`, `tor`, `relay`, `res_proxy`, `hosting`, and `service` signals are blocked; privacy lookup failures fail closed.
Before any of those state transitions, the handler requires a resolved country and successful IPinfo/Spur privacy checks. Unsupported countries enter limited Freebuff access. In allowlisted countries, IPinfo privacy signals still receive full access when Spur returns clean context, fall back to limited access when Spur lookup fails, and hard-block only when Spur corroborates VPN/proxy/Tor/residential-proxy traffic. IPinfo lookup failures fail closed into limited access.

Response shapes:

Expand Down
2 changes: 2 additions & 0 deletions packages/internal/src/db/migrations/0053_solid_karnak.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE "free_mode_country_access_cache" ADD COLUMN "spur_ip_privacy_signals" text[];--> statement-breakpoint
ALTER TABLE "free_mode_country_access_cache" ADD COLUMN "spur_status" text;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE "free_mode_country_access_cache" ADD COLUMN "privacy_decision" text;--> statement-breakpoint
ALTER TABLE "free_mode_country_access_cache" ADD COLUMN "privacy_provider_decision" text;
Loading
Loading