Created
August 18, 2025 15:02
-
-
Save andrewgross/6bea4d5b071cadef939c5b63ea5b0cff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Thinking token levels | |
| const THINK_LEVEL = { | |
| HIGHEST: 31999, | |
| MIDDLE: 10000, | |
| BASIC: 4000, | |
| NONE: 0, | |
| }; | |
| // Language cues for thinking intensity | |
| const THINK_CUES = { | |
| english: { | |
| HIGHEST: [ | |
| { pattern: "think harder", needsWordBoundary: true }, | |
| { pattern: "think intensely", needsWordBoundary: true }, | |
| { pattern: "think longer", needsWordBoundary: true }, | |
| { pattern: "think really hard", needsWordBoundary: true }, | |
| { pattern: "think super hard", needsWordBoundary: true }, | |
| { pattern: "think very hard", needsWordBoundary: true }, | |
| { pattern: "ultrathink", needsWordBoundary: true }, | |
| ], | |
| MIDDLE: [ | |
| { pattern: "think about it", needsWordBoundary: true }, | |
| { pattern: "think a lot", needsWordBoundary: true }, | |
| { pattern: "think deeply", needsWordBoundary: true }, | |
| { pattern: "think hard", needsWordBoundary: true }, | |
| { pattern: "think more", needsWordBoundary: true }, | |
| { pattern: "megathink", needsWordBoundary: true }, | |
| ], | |
| BASIC: [{ pattern: "think", needsWordBoundary: true }], | |
| NONE: [], | |
| }, | |
| japanese: { | |
| HIGHEST: [{ pattern: "熟考" }, { pattern: "深く考えて" }, { pattern: "しっかり考えて" }], | |
| MIDDLE: [{ pattern: "もっと考えて" }, { pattern: "たくさん考えて" }, { pattern: "よく考えて" }, { pattern: "長考" }], | |
| BASIC: [{ pattern: "考えて" }], | |
| NONE: [], | |
| }, | |
| chinese: { | |
| HIGHEST: [{ pattern: "多想一会" }, { pattern: "深思" }, { pattern: "仔细思考" }], | |
| MIDDLE: [{ pattern: "多想想" }, { pattern: "好好想" }], | |
| BASIC: [{ pattern: "想" }, { pattern: "思考" }], | |
| NONE: [], | |
| }, | |
| spanish: { | |
| HIGHEST: [ | |
| { pattern: "piensa más", needsWordBoundary: true }, | |
| { pattern: "piensa mucho", needsWordBoundary: true }, | |
| { pattern: "piensa profundamente", needsWordBoundary: true }, | |
| ], | |
| MIDDLE: [{ pattern: "piensa", needsWordBoundary: true }], | |
| BASIC: [ | |
| { pattern: "pienso", needsWordBoundary: true }, | |
| { pattern: "pensando", needsWordBoundary: true }, | |
| ], | |
| NONE: [], | |
| }, | |
| french: { | |
| HIGHEST: [ | |
| { pattern: "réfléchis plus", needsWordBoundary: true }, | |
| { pattern: "réfléchis beaucoup", needsWordBoundary: true }, | |
| { pattern: "réfléchis profondément", needsWordBoundary: true }, | |
| ], | |
| MIDDLE: [{ pattern: "réfléchis", needsWordBoundary: true }], | |
| BASIC: [ | |
| { pattern: "pense", needsWordBoundary: true }, | |
| { pattern: "réfléchir", needsWordBoundary: true }, | |
| ], | |
| NONE: [], | |
| }, | |
| german: { | |
| HIGHEST: [ | |
| { pattern: "denk mehr", needsWordBoundary: true }, | |
| { pattern: "denk gründlich", needsWordBoundary: true }, | |
| { pattern: "denk tief", needsWordBoundary: true }, | |
| ], | |
| MIDDLE: [ | |
| { pattern: "denk nach", needsWordBoundary: true }, | |
| { pattern: "denk", needsWordBoundary: true }, | |
| ], | |
| BASIC: [ | |
| { pattern: "denke", needsWordBoundary: true }, | |
| { pattern: "nachdenken", needsWordBoundary: true }, | |
| ], | |
| NONE: [], | |
| }, | |
| korean: { | |
| HIGHEST: [{ pattern: "더 오래 생각" }, { pattern: "깊이 생각" }, { pattern: "심사숙고" }, { pattern: "곰곰이 생각" }], | |
| MIDDLE: [{ pattern: "많이 생각" }, { pattern: "더 생각" }, { pattern: "잘 생각" }], | |
| BASIC: [{ pattern: "생각" }], | |
| NONE: [], | |
| }, | |
| italian: { | |
| HIGHEST: [ | |
| { pattern: "pensa di più", needsWordBoundary: true }, | |
| { pattern: "pensa a lungo", needsWordBoundary: true }, | |
| { pattern: "pensa profondamente", needsWordBoundary: true }, | |
| { pattern: "rifletti a fondo", needsWordBoundary: true }, | |
| ], | |
| MIDDLE: [ | |
| { pattern: "pensa", needsWordBoundary: true }, | |
| { pattern: "pensa molto", needsWordBoundary: true }, | |
| { pattern: "rifletti", needsWordBoundary: true }, | |
| ], | |
| BASIC: [ | |
| { pattern: "penso", needsWordBoundary: true }, | |
| { pattern: "pensare", needsWordBoundary: true }, | |
| { pattern: "pensando", needsWordBoundary: true }, | |
| { pattern: "riflettere", needsWordBoundary: true }, | |
| ], | |
| NONE: [], | |
| }, | |
| }; | |
| // Extract plain text from a message object | |
| function getMessageText(msg) { | |
| if (typeof msg.message?.content === "string") return msg.message.content; | |
| return (msg.message?.content || []) | |
| .map((p) => (p.type === "text" ? p.text : "")) | |
| .join(""); | |
| } | |
| // Score a single message for thinking tokens | |
| function scoreMessageThinkingTokens(msg) { | |
| if (msg.isMeta) return 0; | |
| const text = getMessageText(msg) | |
| .toLowerCase() | |
| .replaceAll("i think", "") | |
| .replaceAll("we think", ""); | |
| const tokens = scoreTextThinkingTokens(text); | |
| if (tokens > 0) X1("tengu_thinking", { provider: HN(), tokenCount: tokens }); | |
| return tokens; | |
| } | |
| // Compute tokens for free text using cue tables | |
| function scoreTextThinkingTokens(text) { | |
| const levels = [ | |
| ["HIGHEST", THINK_LEVEL.HIGHEST], | |
| ["MIDDLE", THINK_LEVEL.MIDDLE], | |
| ["BASIC", THINK_LEVEL.BASIC], | |
| ]; | |
| for (const [levelKey, val] of levels) { | |
| if (matchesLevel(text, levelKey)) return val; | |
| } | |
| return THINK_LEVEL.NONE; | |
| } | |
| // Check if text matches any cue at a given level across languages | |
| function matchesLevel(text, levelKey) { | |
| for (const lang of Object.values(THINK_CUES)) { | |
| const cues = lang[levelKey] || []; | |
| for (const { pattern, needsWordBoundary } of cues) { | |
| const re = needsWordBoundary | |
| ? new RegExp(`\\b${pattern}\\b`) | |
| : new RegExp(pattern); | |
| if (re.test(text)) return true; | |
| } | |
| } | |
| return false; | |
| } | |
| // Determine max thinking tokens from env or user messages | |
| function selectMaxThinkingTokens(messages, fallbackMax) { | |
| if (process.env.MAX_THINKING_TOKENS) { | |
| const Q = parseInt(process.env.MAX_THINKING_TOKENS, 10); | |
| if (Q > 0) X1("tengu_thinking", { provider: HN(), tokenCount: Q }); | |
| return Q; | |
| } | |
| const bestFromUser = Math.max( | |
| ...messages | |
| .filter((m) => m.type === "user" && !m.isMeta) | |
| .map(scoreMessageThinkingTokens), | |
| fallbackMax ?? 0 | |
| ); | |
| return bestFromUser; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment