@@ -165,53 +165,63 @@ function httpPost(url: string, data: any, headers: Record<string, string>): Prom
165165 * Create tracer with automatic tier detection
166166 *
167167 * Tier Detection:
168- * - If apiKey is provided: Try to initialize CloudTraceSink (Pro/Enterprise)
169- * - If cloud init fails or no apiKey: Fall back to JsonlTraceSink (Free tier)
168+ * - If apiKey is provided AND uploadTrace is true : Try to initialize CloudTraceSink (Pro/Enterprise)
169+ * - If cloud init fails, no apiKey, or uploadTrace is false : Fall back to JsonlTraceSink (Free tier)
170170 *
171171 * @param options - Configuration options
172172 * @param options.apiKey - Sentience API key (e.g., "sk_pro_xxxxx")
173173 * @param options.runId - Unique identifier for this agent run (generates UUID if not provided)
174174 * @param options.apiUrl - Sentience API base URL (default: https://api.sentienceapi.com)
175175 * @param options.logger - Optional logger instance for logging file sizes and errors
176+ * @param options.uploadTrace - Enable cloud trace upload (default: true for backward compatibility)
176177 * @returns Tracer configured with appropriate sink
177178 *
178179 * @example
179180 * ```typescript
180- * // Pro tier user
181- * const tracer = await createTracer({ apiKey: "sk_pro_xyz", runId: "demo" });
181+ * // Pro tier user with cloud upload
182+ * const tracer = await createTracer({ apiKey: "sk_pro_xyz", runId: "demo", uploadTrace: true });
182183 * // Returns: Tracer with CloudTraceSink
183184 *
185+ * // Pro tier user with local-only tracing
186+ * const tracer = await createTracer({ apiKey: "sk_pro_xyz", runId: "demo", uploadTrace: false });
187+ * // Returns: Tracer with JsonlTraceSink (local-only)
188+ *
184189 * // Free tier user
185190 * const tracer = await createTracer({ runId: "demo" });
186191 * // Returns: Tracer with JsonlTraceSink (local-only)
187192 *
188193 * // Use with agent
189194 * const agent = new SentienceAgent(browser, llm, 50, true, tracer);
190195 * await agent.act("Click search");
191- * await tracer.close(); // Uploads to cloud if Pro tier
196+ * await tracer.close(); // Uploads to cloud if uploadTrace: true and Pro tier
192197 * ```
193198 */
194199export async function createTracer ( options : {
195200 apiKey ?: string ;
196201 runId ?: string ;
197202 apiUrl ?: string ;
198203 logger ?: SentienceLogger ;
204+ uploadTrace ?: boolean ;
199205} ) : Promise < Tracer > {
200206 const runId = options . runId || randomUUID ( ) ;
201207 const apiUrl = options . apiUrl || SENTIENCE_API_URL ;
208+ // Default uploadTrace to true for backward compatibility
209+ const uploadTrace = options . uploadTrace !== false ;
202210
203211 // PRODUCTION FIX: Recover orphaned traces from previous crashes
204212 // Note: This is skipped in test environments (see recoverOrphanedTraces function)
205213 // Run in background to avoid blocking tracer creation
206- if ( options . apiKey ) {
214+ // Only recover if uploadTrace is enabled
215+ if ( options . apiKey && uploadTrace ) {
207216 // Don't await - run in background to avoid blocking
208217 recoverOrphanedTraces ( options . apiKey , apiUrl ) . catch ( ( ) => {
209218 // Silently fail - orphan recovery should not block tracer creation
210219 } ) ;
211220 }
212221
213222 // 1. Try to initialize Cloud Sink (Pro/Enterprise tier)
214- if ( options . apiKey ) {
223+ // Only attempt cloud init if uploadTrace is enabled
224+ if ( options . apiKey && uploadTrace ) {
215225 try {
216226 // Request pre-signed upload URL from backend
217227 const response = await httpPost (
0 commit comments