Skip to content

Instantly share code, notes, and snippets.

@JosXa
Created February 23, 2026 21:34
Show Gist options
  • Select an option

  • Save JosXa/7d94f32e80e2b67503f0756b2672599d to your computer and use it in GitHub Desktop.

Select an option

Save JosXa/7d94f32e80e2b67503f0756b2672599d to your computer and use it in GitHub Desktop.
// import type { Plugin } from "@opencode-ai/plugin"
// // AI writing patterns detection and humanization
// const AI_PATTERNS = {
// content: {
// significance: /\b(stands|serves) as\b|\btestament\b|\bpivotal (moment|role)\b|\bevolving landscape\b|\bindelible mark\b/gi,
// notability: /\bcited in\b.*\b(NYT|BBC|Times|Post)\b|\bactive social media presence\b/gi,
// superficial: /\b(highlighting|underscoring|emphasizing|ensuring|reflecting|symbolizing|showcasing)\b[^.]{0,50}\.\s*$/gim,
// promotional: /\b(nestled|breathtaking|vibrant|stunning|must-visit|renowned|boasts)\b/gi,
// vague: /\b(Experts|Industry reports|Observers|Some critics)\s+(believe|argue|suggest)\b/gi,
// challenges: /Despite (its|these) (challenges|obstacles).*continues to (thrive|grow|excel)/gi,
// },
// language: {
// aiVocab: /\b(Additionally|crucial|delve|enhance|fostering|garner|landscape|pivotal|showcase|tapestry|testament|underscore|vibrant)\b/gi,
// copulaAvoid: /\b(serves as|stands as|boasts|features)\s+[a-z]/gi,
// negativeParallel: /(It's|This is) not (just|only|merely)\s+\w+,\s+(it's|they're)/gi,
// ruleOfThree: /\b(\w+),\s+(\w+),\s+and\s+(\w+)\b/g,
// },
// style: {
// emDash: /—/g,
// boldface: /\*\*(\w+)\*\*/g,
// inlineHeader: /^\s*[-*]\s+\*\*([^*]+):\*\*\s+/gm,
// titleCase: /^#+\s+([A-Z][a-z]+\s+){2,}[A-Z][a-z]+$/gm,
// emoji: /[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]/gu,
// curlyQuotes: /[""'']/g,
// },
// communication: {
// chatbot: /\b(I hope this helps|Let me know|Would you like|Of course!|Certainly!)\b/gi,
// cutoff: /\b(as of|up to my last|while (specific )?details are (limited|scarce)|based on available)\b/gi,
// sycophantic: /\b(Great question|You're absolutely right|Excellent point)\b/gi,
// },
// filler: {
// phrases: /\b(in order to|due to the fact that|at this point in time|in the event that|has the ability to)\b/gi,
// hedging: /\b(could potentially possibly|might possibly|may potentially)\b/gi,
// generic: /\b(The future looks bright|exciting times (lie )?ahead|major step in the right direction)\b/gi,
// },
// }
// interface PatternMatch {
// category: string
// pattern: string
// matches: string[]
// count: number
// }
// function analyzeText(text: string): PatternMatch[] {
// const results: PatternMatch[] = []
// for (const [category, patterns] of Object.entries(AI_PATTERNS)) {
// for (const [patternName, regex] of Object.entries(patterns)) {
// const matches = text.match(regex)
// if (matches && matches.length > 0) {
// results.push({
// category,
// pattern: patternName,
// matches: [...new Set(matches)],
// count: matches.length,
// })
// }
// }
// }
// return results.sort((a, b) => b.count - a.count)
// }
// function generateReport(analysis: PatternMatch[]): string {
// if (analysis.length === 0) {
// return "✅ No obvious AI patterns detected"
// }
// let report = `🤖 AI Writing Patterns Detected (${analysis.length} types):\n\n`
// for (const match of analysis) {
// report += `• ${match.category}/${match.pattern} (${match.count}x)\n`
// const preview = match.matches.slice(0, 3).join(", ")
// report += ` Examples: ${preview}${match.matches.length > 3 ? "..." : ""}\n`
// }
// report += `\nRun \`opencode run --command "humanize" "<your-text>"\` to get humanized version.`
// return report
// }
// export const HumanizerPlugin: Plugin = async (ctx) => {
// const toolExecuteBefore = async (input: any) => {
// // Only analyze text from read/write/edit operations
// const textTools = ["read", "write", "edit"]
// if (!textTools.includes(input.tool?.toLowerCase())) return
// const content = input?.args?.content ?? input?.args?.newString
// if (!content || typeof content !== "string") return
// // Only analyze substantial text (>200 chars)
// if (content.length < 200) return
// const analysis = analyzeText(content)
// // Only report if significant patterns found (3+ types or 5+ total matches)
// const totalMatches = analysis.reduce((sum, a) => sum + a.count, 0)
// if (analysis.length < 3 && totalMatches < 5) return
// const report = generateReport(analysis)
// // Log to console for visibility
// console.log("\n" + report + "\n")
// }
// const eventHandler = async (input: any) => {
// // Could hook into session events if needed
// if (input.event?.type === "message.created") {
// const content = input.event?.properties?.message?.content?.[0]?.text
// if (!content || content.length < 200) return
// const analysis = analyzeText(content)
// const totalMatches = analysis.reduce((sum, a) => sum + a.count, 0)
// if (analysis.length >= 3 || totalMatches >= 5) {
// // Could inject a warning into the conversation here
// // For now, just console log
// console.log("\n⚠️ AI patterns detected in message\n")
// }
// }
// }
// return {
// "tool.execute.before": toolExecuteBefore,
// event: eventHandler,
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment