Force Claude AI to always use extended thinking mode
// ==UserScript==
// @name Claude Extended Mode Enforcer v1.4
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Force Claude AI to always use extended thinking mode
// @author LituDev
// @match https://claude.ai/*
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
const originalFetch = window.fetch;
const targetPathEnd = '/chat_conversations'; // More specific target
console.log("[Claude Extended Mode Enforcer] Initializing v1.4...");
window.fetch = async function(input, init) {
let resourceUrl = '';
let requestMethod = '';
let isChatCreationPOST = false;
// --- Determine URL and Method ---
if (input instanceof Request) {
resourceUrl = input.url;
requestMethod = input.method;
} else if (typeof input === 'string' || input instanceof URL) {
resourceUrl = input.toString();
requestMethod = init?.method || 'GET'; // Use optional chaining and default
} else {
// Unknown input type, proceed with original fetch
console.warn("[Claude Extended Mode Enforcer] Unknown fetch input type:", input);
return originalFetch.apply(this, arguments);
}
// --- Check if it's the target POST request for chat creation ---
// Be specific: ends with /chat_conversations and is POST
isChatCreationPOST = resourceUrl.includes('/api/organizations/') &&
resourceUrl.endsWith(targetPathEnd) && // Use endsWith for specificity
requestMethod.toUpperCase() === 'POST';
if (!isChatCreationPOST) {
// Not the target request, proceed with original fetch
return originalFetch.apply(this, arguments);
}
console.log(`[Claude Extended Mode Enforcer] Intercepted Chat Creation POST: ${resourceUrl}`);
try {
let modifiedInput = input;
let modifiedInit = init;
if (input instanceof Request) {
// --- Handle Request Object Input ---
const clonedRequest = input.clone(); // Clone to read body
const bodyData = await clonedRequest.json(); // Read body as JSON
bodyData.paprika_mode = "extended";
console.log("[Claude Extended Mode Enforcer] Modifying Request body:", bodyData);
// Create a NEW Request object with the modified body and necessary headers
const headers = new Headers(input.headers); // Copy original headers
headers.set('Content-Type', 'application/json'); // Ensure correct Content-Type
// Create new Request based on the original one but override body/headers
modifiedInput = new Request(input, {
body: JSON.stringify(bodyData),
headers: headers
// Method, credentials, mode etc. are inherited
});
modifiedInit = undefined; // Init is not used when fetch's first arg is a Request
} else if (init?.body) {
// --- Handle URL + Init Object Input ---
const originalBody = init.body;
let bodyText = '';
// Need to handle different body types before parsing
if (typeof originalBody === 'string') {
bodyText = originalBody;
} else if (originalBody instanceof ReadableStream) {
// This is complex to handle reliably *within* the sync wrapper
console.warn("[Claude Extended Mode Enforcer] ReadableStream body detected in init - modification skipped.");
return originalFetch.apply(this, arguments); // Skip modification for streams in init
} else if (originalBody instanceof Blob) {
bodyText = await originalBody.text();
} else if (originalBody instanceof ArrayBuffer || ArrayBuffer.isView(originalBody)) {
bodyText = new TextDecoder().decode(originalBody);
} else {
console.warn("[Claude Extended Mode Enforcer] Unsupported init.body type - modification skipped:", typeof originalBody);
return originalFetch.apply(this, arguments); // Skip modification
}
if (bodyText) {
const bodyData = JSON.parse(bodyText);
bodyData.paprika_mode = "extended";
console.log("[Claude Extended Mode Enforcer] Modifying init.body:", bodyData);
// Create a *new* init object to avoid side effects, copying properties
modifiedInit = { ...init }; // Shallow copy is usually sufficient here
modifiedInit.body = JSON.stringify(bodyData);
// Ensure headers object exists if we need to modify it
if (!modifiedInit.headers) {
modifiedInit.headers = {};
} else if (modifiedInit.headers instanceof Headers) {
// Convert Headers object to plain object if needed, or work with Headers API
// For simplicity, just ensure Content-Type is set if needed
}
// Ensure Content-Type is correctly set (might be redundant, but safe)
if (typeof modifiedInit.headers === 'object' && !Array.isArray(modifiedInit.headers)) {
modifiedInit.headers['Content-Type'] = 'application/json';
// Let the browser handle Content-Length
delete modifiedInit.headers['Content-Length'];
} else if (modifiedInit.headers instanceof Headers) {
modifiedInit.headers.set('Content-Type', 'application/json');
modifiedInit.headers.delete('Content-Length');
}
} else {
console.warn("[Claude Extended Mode Enforcer] init.body present but could not be read as text.");
return originalFetch.apply(this, arguments); // Skip if body couldn't be read
}
} else {
console.warn("[Claude Extended Mode Enforcer] Chat Creation POST detected, but no body found to modify.");
// Still proceed, maybe it's a request type we don't expect?
return originalFetch.apply(this, arguments);
}
// --- Call original fetch with potentially modified arguments ---
console.log("[Claude Extended Mode Enforcer] Proceeding with fetch call.");
return originalFetch.apply(this, [modifiedInput, modifiedInit]);
} catch (error) {
console.error("[Claude Extended Mode Enforcer] Error during modification:", error);
// Fallback to original fetch if any error occurs during modification
return originalFetch.apply(this, arguments);
}
};
console.log("[Claude Extended Mode Enforcer] v1.4 Hooked into fetch.");
})();