Jump to content
Wikipedia The Free Encyclopedia

User:Polygnotus/Scripts/AI Editsummary.js

From Wikipedia, the free encyclopedia
Code that you insert on this page could contain malicious content capable of compromising your account. If you import a script from another page with "importScript", "mw.loader.load", "iusc", or "lusc", take note that this causes you to dynamically load a remote script, which could be changed by others. Editors are responsible for all edits and actions they perform, including by scripts. User scripts are not centrally supported and may malfunction or become inoperable due to software changes. A guide to help you find broken scripts is available. If you are unsure whether code you are adding to this page is safe, you can ask at the appropriate village pump.
This code will be executed when previewing this page.
This user script seems to have a documentation page at User:Polygnotus/Scripts/AI Editsummary.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
 (function(){
 'use strict';

 console.log('EditSummaryGenerator: Script loaded');

 // Only run on edit pages
 if(mw.config.get('wgAction')!=='edit'){
 console.log('EditSummaryGenerator: Not on edit page, exiting');
 return;
 }

 console.log('EditSummaryGenerator: On edit page, continuing');

 classEditSummaryGenerator{
 constructor(){
 console.log('EditSummaryGenerator: Constructor called');

 // Provider configurations
 this.providers={
 claude:{
 name:'Claude',
 storageKey:'claude_api_key',
 model:'claude-sonnet-4-20250514'
 },
 gemini:{
 name:'Gemini',
 storageKey:'gemini_api_key',
 model:'gemini-2.5-flash-preview-05-20'
 },
 openai:{
 name:'ChatGPT',
 storageKey:'openai_api_key',
 model:'gpt-4o'
 }
 };

 this.currentProvider=localStorage.getItem('ai_editsummary_provider')||'claude';
 this.button=null;

 console.log('EditSummaryGenerator: Current provider:',this.currentProvider);
 console.log('EditSummaryGenerator: API key exists:',!!this.getCurrentApiKey());

 this.init();
 }

 getCurrentApiKey(){
 returnlocalStorage.getItem(this.providers[this.currentProvider].storageKey);
 }

 init(){
 console.log('EditSummaryGenerator: Init called');
 console.log('EditSummaryGenerator: jQuery available:',typeof$!=='undefined');
 console.log('EditSummaryGenerator: mw.loader available:',typeofmw!=='undefined'&&typeofmw.loader!=='undefined');

 mw.loader.using(['oojs-ui-core','mediawiki.api','mediawiki.notification'])
 .then(()=>{
 console.log('EditSummaryGenerator: Modules loaded');
 console.log('EditSummaryGenerator: OO.ui available:',typeofOO!=='undefined'&&typeofOO.ui!=='undefined');
 $(function(){
 console.log('EditSummaryGenerator: Document ready');
 this.createButton();
 }.bind(this));
 })
 .catch((error)=>{
 console.error('EditSummaryGenerator: Failed to load modules:',error);
 });
 }

 createButton(){
 console.log('EditSummaryGenerator: createButton called');

 constwpDiffWidget=$('#wpDiffWidget');
 console.log('EditSummaryGenerator: wpDiffWidget found:',wpDiffWidget.length>0);
 console.log('EditSummaryGenerator: wpDiffWidget element:',wpDiffWidget[0]);

 this.button=newOO.ui.ButtonWidget({
 label:'AI Edit Summary',
 framed:true
 });
 console.log('EditSummaryGenerator: Button created:',this.button);

 this.button.on('click',()=>this.generateEditSummary());

 $('#wpDiffWidget').after(' ',this.button.$element);
 console.log('EditSummaryGenerator: Button inserted after wpDiffWidget');
 console.log('EditSummaryGenerator: Button element:',this.button.$element[0]);
 }

 asyncgenerateEditSummary(){
 constapiKey=this.getCurrentApiKey();
 if(!apiKey){
 mw.notify('API key not found for '+this.providers[this.currentProvider].name+'. Please set it in localStorage.',{type:'error'});
 return;
 }

 // Change button state to "working"
 constoriginalLabel=this.button.getLabel();
 this.button.setLabel('Working...');
 this.button.setDisabled(true);

 try{
 // Get the current article title and revision ID
 constpageTitle=mw.config.get('wgPageName');
 constcurrentRevId=mw.config.get('wgCurRevisionId');

 // Get the edited text from the textbox
 consteditedText=$('#wpTextbox1').val();

 // Fetch the current revision from the API
 constcurrentText=awaitthis.getCurrentRevision(pageTitle,currentRevId);

 // Generate edit summary using the current provider
 leteditSummary;
 switch(this.currentProvider){
 case'claude':
 editSummary=awaitthis.callClaudeAPI(currentText,editedText);
 break;
 case'gemini':
 editSummary=awaitthis.callGeminiAPI(currentText,editedText);
 break;
 case'openai':
 editSummary=awaitthis.callOpenAIAPI(currentText,editedText);
 break;
 }

 // Put the summary in the edit summary box
 $('#wpSummary').val(editSummary).trigger('input');

 // Change button state to "done"
 this.button.setLabel('Done!');
 setTimeout(()=>{
 this.button.setLabel(originalLabel);
 this.button.setDisabled(false);
 },2000);

 }catch(error){
 console.error('Error generating edit summary:',error);
 mw.notify('Failed to generate edit summary: '+error.message,{type:'error'});
 this.button.setLabel(originalLabel);
 this.button.setDisabled(false);
 }
 }

 asyncgetCurrentRevision(pageTitle,revId){
 // If no revision exists (new page), return empty string
 if(!revId||revId===0){
 return'';
 }

 constapi=newmw.Api();
 constresponse=awaitapi.get({
 action:'query',
 prop:'revisions',
 titles:pageTitle,
 rvprop:'content',
 rvlimit:1,
 formatversion:2
 });

 if(response.query&&response.query.pages&&response.query.pages[0]){
 constpage=response.query.pages[0];
 if(page.revisions&&page.revisions[0]){
 returnpage.revisions[0].content||'';
 }
 }

 return'';
 }

 asynccallClaudeAPI(originalText,editedText){
 constrequestBody={
 model:this.providers.claude.model,
 max_tokens:200,
 system:`You are a Wikipedia edit summary generator. Generate a concise edit summary (max 100 characters) that describes the changes made to the article. Follow Wikipedia's edit summary conventions:

 - Be specific and concise
 - Use standard abbreviations (e.g., "fmt" for formatting, "typo" for typos, "ce" for copyedit)
 - Separate multiple changes with semicolons or commas
 - Don't use complete sentences or punctuation at the end
 - Examples: "Added section on early life", "Fixed typos; updated references", "Reverted vandalism"

 You will be shown two versions: the CURRENT version (already published on Wikipedia) and the NEW version (about to be saved). Describe what changes are being made FROM the current version TO the new version. Generate ONLY the edit summary text, nothing else.`,
 messages:[{
 role:"user",
 content:`CURRENT VERSION (already on Wikipedia):\n${originalText}\n\nNEW VERSION (about to be saved):\n${editedText}\n\nGenerate an edit summary describing the changes FROM current TO new version.`
 }]
 };

 constresponse=awaitfetch('https://api.anthropic.com/v1/messages',{
 method:'POST',
 headers:{
 'Content-Type':'application/json',
 'x-api-key':this.getCurrentApiKey(),
 'anthropic-version':'2023年06月01日',
 'anthropic-dangerous-direct-browser-access':'true'
 },
 body:JSON.stringify(requestBody)
 });

 if(!response.ok){
 consterrorText=awaitresponse.text();
 thrownewError(`API request failed (${response.status}): ${errorText}`);
 }

 constdata=awaitresponse.json();

 if(!data.content||!data.content[0]||!data.content[0].text){
 thrownewError('Invalid API response format');
 }

 // Trim and limit to 250 characters (Wikipedia's edit summary limit)
 letsummary=data.content[0].text.trim();
 if(summary.length>250){
 summary=summary.substring(0,247)+'...';
 }

 returnsummary;
 }

 asynccallGeminiAPI(originalText,editedText){
 constAPI_URL=`https://generativelanguage.googleapis.com/v1beta/models/${this.providers.gemini.model}:generateContent?key=${this.getCurrentApiKey()}`;

 constsystemPrompt=`You are a Wikipedia edit summary generator. Generate a concise edit summary (max 100 characters) that describes the changes made to the article. Follow Wikipedia's edit summary conventions:

 - Be specific and concise
 - Use standard abbreviations (e.g., "fmt" for formatting, "typo" for typos, "ce" for copyedit)
 - Separate multiple changes with semicolons or commas
 - Don't use complete sentences or punctuation at the end
 - Examples: "Added section on early life", "Fixed typos; updated references", "Reverted vandalism"

 You will be shown two versions: the CURRENT version (already published on Wikipedia) and the NEW version (about to be saved). Describe what changes are being made FROM the current version TO the new version. Generate ONLY the edit summary text, nothing else.`;

 constrequestBody={
 contents:[{
 parts:[{"text":`CURRENT VERSION (already on Wikipedia):\n${originalText}\n\nNEW VERSION (about to be saved):\n${editedText}\n\nGenerate an edit summary describing the changes FROM current TO new version.`}],
 }],
 systemInstruction:{
 parts:[{"text":systemPrompt}]
 },
 generationConfig:{
 maxOutputTokens:200,
 temperature:0.0,
 }
 };

 constresponse=awaitfetch(API_URL,{
 method:'POST',
 headers:{
 'Content-Type':'application/json',
 },
 body:JSON.stringify(requestBody)
 });

 constresponseData=awaitresponse.json();

 if(!response.ok){
 consterrorDetail=responseData.error?responseData.error.message:response.statusText;
 thrownewError(`API request failed (${response.status}): ${errorDetail}`);
 }

 if(!responseData.candidates||!responseData.candidates[0]||
 !responseData.candidates[0].content||!responseData.candidates[0].content.parts||
 !responseData.candidates[0].content.parts[0]||!responseData.candidates[0].content.parts[0].text){
 thrownewError('Invalid API response format or no content generated.');
 }

 // Trim and limit to 250 characters
 letsummary=responseData.candidates[0].content.parts[0].text.trim();
 if(summary.length>250){
 summary=summary.substring(0,247)+'...';
 }

 returnsummary;
 }

 asynccallOpenAIAPI(originalText,editedText){
 constrequestBody={
 model:this.providers.openai.model,
 max_tokens:200,
 messages:[
 {
 role:"system",
 content:`You are a Wikipedia edit summary generator. Generate a concise edit summary (max 100 characters) that describes the changes made to the article. Follow Wikipedia's edit summary conventions:

 - Be specific and concise
 - Use standard abbreviations (e.g., "fmt" for formatting, "typo" for typos, "ce" for copyedit)
 - Separate multiple changes with semicolons or commas
 - Don't use complete sentences or punctuation at the end
 - Examples: "Added section on early life", "Fixed typos; updated references", "Reverted vandalism"

 You will be shown two versions: the CURRENT version (already published on Wikipedia) and the NEW version (about to be saved). Describe what changes are being made FROM the current version TO the new version. Generate ONLY the edit summary text, nothing else.`
 },
 {
 role:"user",
 content:`CURRENT VERSION (already on Wikipedia):\n${originalText}\n\nNEW VERSION (about to be saved):\n${editedText}\n\nGenerate an edit summary describing the changes FROM current TO new version.`
 }
 ],
 temperature:0.3
 };

 constresponse=awaitfetch('https://api.openai.com/v1/chat/completions',{
 method:'POST',
 headers:{
 'Content-Type':'application/json',
 'Authorization':`Bearer ${this.getCurrentApiKey()}`
 },
 body:JSON.stringify(requestBody)
 });

 if(!response.ok){
 consterrorText=awaitresponse.text();
 leterrorMessage;
 try{
 consterrorData=JSON.parse(errorText);
 errorMessage=errorData.error?.message||errorText;
 }catch{
 errorMessage=errorText;
 }
 thrownewError(`API request failed (${response.status}): ${errorMessage}`);
 }

 constdata=awaitresponse.json();

 if(!data.choices||!data.choices[0]||!data.choices[0].message||!data.choices[0].message.content){
 thrownewError('Invalid API response format');
 }

 // Trim and limit to 250 characters
 letsummary=data.choices[0].message.content.trim();
 if(summary.length>250){
 summary=summary.substring(0,247)+'...';
 }

 returnsummary;
 }
 }

 console.log('EditSummaryGenerator: About to instantiate');
 newEditSummaryGenerator();
 console.log('EditSummaryGenerator: Instantiated');
 })();

AltStyle によって変換されたページ (->オリジナル) /