mirror of
https://github.com/ONLYOFFICE/onlyoffice.github.io.git
synced 2026-02-10 18:05:06 +08:00
refactoring
This commit is contained in:
@ -38,186 +38,156 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @extends CustomAnnotator
|
* @extends CustomAnnotator
|
||||||
*/
|
*/
|
||||||
function AssistantHint(annotationPopup, assistantData)
|
function AssistantHint(annotationPopup, assistantData) {
|
||||||
{
|
CustomAnnotator.call(this, annotationPopup, assistantData);
|
||||||
CustomAnnotator.call(this, annotationPopup, assistantData);
|
|
||||||
}
|
}
|
||||||
AssistantHint.prototype = Object.create(CustomAnnotator.prototype);
|
AssistantHint.prototype = Object.create(CustomAnnotator.prototype);
|
||||||
AssistantHint.prototype.constructor = AssistantHint;
|
AssistantHint.prototype.constructor = AssistantHint;
|
||||||
|
|
||||||
/**
|
Object.assign(AssistantHint.prototype, {
|
||||||
* @param {string} paraId
|
/**
|
||||||
* @param {string} recalcId
|
* @param {string} text
|
||||||
* @param {string} text
|
* @param {Array<HintAiResponse>} matches
|
||||||
*/
|
*/
|
||||||
AssistantHint.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
_convertToRanges: function (paraId, text, matches) {
|
||||||
{
|
const _t = this;
|
||||||
this.paragraphs[paraId] = {};
|
let rangeId = 1;
|
||||||
|
const ranges = [];
|
||||||
|
for (const {
|
||||||
|
origin,
|
||||||
|
reason,
|
||||||
|
paragraph,
|
||||||
|
occurrence,
|
||||||
|
confidence,
|
||||||
|
} of matches) {
|
||||||
|
if (confidence <= 0.7) continue;
|
||||||
|
|
||||||
if (text.length === 0)
|
let count = 0;
|
||||||
return false;
|
let searchStart = 0;
|
||||||
|
|
||||||
const argPrompt = this._createPrompt(text);
|
while (searchStart < text.length) {
|
||||||
|
const index = _t.simpleGraphemeIndexOf(
|
||||||
|
text,
|
||||||
|
origin,
|
||||||
|
searchStart,
|
||||||
|
);
|
||||||
|
if (index === -1) break;
|
||||||
|
|
||||||
let response = await this.chatRequest(argPrompt);
|
count++;
|
||||||
if (!response)
|
if (count === occurrence) {
|
||||||
return false;
|
ranges.push({
|
||||||
|
start: index,
|
||||||
let rangeId = 1;
|
length: [...origin].length,
|
||||||
let ranges = [];
|
id: rangeId,
|
||||||
|
});
|
||||||
|
_t.paragraphs[paraId][rangeId] = {
|
||||||
|
original: origin,
|
||||||
|
reason: reason,
|
||||||
|
};
|
||||||
|
++rangeId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
searchStart = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
let _t = this;
|
/**
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_createPrompt: function (text) {
|
||||||
|
let prompt = `You are a multi-disciplinary text analysis assistant.
|
||||||
|
Your task is to find text fragments that match the user's criteria.
|
||||||
|
|
||||||
|
MANDATORY RULES:
|
||||||
|
1. Analyze ONLY the provided text.
|
||||||
|
2. Find words, phrases, or sentences that match the user's criteria.
|
||||||
|
3. For EACH match you find:
|
||||||
|
- Provide the exact quote.
|
||||||
|
- Explain WHY it matches the criteria.
|
||||||
|
- Provide position information (paragraph number).
|
||||||
|
4. If no matches are found, return an empty array: [].
|
||||||
|
5. Format your response STRICTLY in JSON format.
|
||||||
|
6. Support multiple languages (English, Russian, etc.)
|
||||||
|
|
||||||
/**
|
Response format - return ONLY this JSON array with no additional text:
|
||||||
* @param {string} text
|
[
|
||||||
* @param {Array<HintAiResponse>} matches
|
|
||||||
*/
|
|
||||||
function convertToRanges(text, matches)
|
|
||||||
{
|
|
||||||
for (const { origin, reason, paragraph, occurrence, confidence } of matches)
|
|
||||||
{
|
|
||||||
if (confidence <= 0.7)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
let searchStart = 0;
|
|
||||||
|
|
||||||
while (searchStart < text.length)
|
|
||||||
{
|
{
|
||||||
const index = _t.simpleGraphemeIndexOf(text, origin, searchStart);
|
"origin": "exact text fragment that matches the query",
|
||||||
if (index === -1) break;
|
"reason": "detailed explanation why it matches the criteria",
|
||||||
|
"paragraph": paragraph_number,
|
||||||
count++;
|
"occurrence": 1,
|
||||||
if (count === occurrence)
|
"confidence": 0.95
|
||||||
{
|
|
||||||
ranges.push({
|
|
||||||
"start": index,
|
|
||||||
"length": [...origin].length,
|
|
||||||
"id": rangeId
|
|
||||||
});
|
|
||||||
_t.paragraphs[paraId][rangeId] = {
|
|
||||||
"original" : origin,
|
|
||||||
"reason" : reason
|
|
||||||
};
|
|
||||||
++rangeId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
searchStart = index + 1;
|
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
}
|
|
||||||
|
|
||||||
try
|
Guidelines for each field:
|
||||||
{
|
- "origin": EXACT UNCHANGED original text fragment. Do not fix anything in this field.
|
||||||
convertToRanges(text, JSON.parse(response));
|
- "reason": Clear explanation of why this fragment matches the criteria; IF the user's request contains words like "source", "reference", "link", "cite", "website", "URL", "Wikipedia", "proof", "evidence", "verify" - then you MUST include actual working links in your explanations in html format.
|
||||||
let obj = {
|
- "paragraph": Paragraph number where the fragment is found (0-based index)
|
||||||
"type": "highlightText",
|
- "occurrence": Which occurrence of this sentence if it appears multiple times (1 for first, 2 for second, etc.)
|
||||||
"paragraphId": paraId,
|
- "confidence": Value between 0 and 1 indicating certainty (1.0 = completely certain, 0.5 = uncertain)
|
||||||
"name" : "customAssistant_" + this.assistantData.id,
|
|
||||||
"recalcId": recalcId,
|
CRITICAL
|
||||||
"ranges": ranges
|
- Output should be in the exact this format
|
||||||
};
|
- No any comments are allowed
|
||||||
await Asc.Editor.callMethod("AnnotateParagraph", [obj]);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
CRITICAL - Output Format:
|
||||||
* @param {string} text
|
- Return ONLY the raw JSON array, nothing else
|
||||||
* @returns {string}
|
- DO NOT wrap the response in markdown code blocks (no \`\`\`json or \`\`\`)
|
||||||
*/
|
- DO NOT include any explanatory text before or after the JSON
|
||||||
AssistantHint.prototype._createPrompt = function(text) {
|
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
||||||
let prompt = `You are a multi-disciplinary text analysis assistant.
|
- The response should start with [ and end with ]
|
||||||
Your task is to find text fragments that match the user's criteria.
|
`;
|
||||||
|
prompt +=
|
||||||
MANDATORY RULES:
|
"\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
||||||
1. Analyze ONLY the provided text.
|
|
||||||
2. Find words, phrases, or sentences that match the user's criteria.
|
|
||||||
3. For EACH match you find:
|
|
||||||
- Provide the exact quote.
|
|
||||||
- Explain WHY it matches the criteria.
|
|
||||||
- Provide position information (paragraph number).
|
|
||||||
4. If no matches are found, return an empty array: [].
|
|
||||||
5. Format your response STRICTLY in JSON format.
|
|
||||||
6. Support multiple languages (English, Russian, etc.)
|
|
||||||
|
|
||||||
Response format - return ONLY this JSON array with no additional text:
|
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
||||||
[
|
|
||||||
{
|
|
||||||
"origin": "exact text fragment that matches the query",
|
|
||||||
"reason": "detailed explanation why it matches the criteria",
|
|
||||||
"paragraph": paragraph_number,
|
|
||||||
"occurrence": 1,
|
|
||||||
"confidence": 0.95
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
Guidelines for each field:
|
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
||||||
- "origin": EXACT UNCHANGED original text fragment. Do not fix anything in this field.
|
|
||||||
- "reason": Clear explanation of why this fragment matches the criteria; IF the user's request contains words like "source", "reference", "link", "cite", "website", "URL", "Wikipedia", "proof", "evidence", "verify" - then you MUST include actual working links in your explanations in html format.
|
|
||||||
- "paragraph": Paragraph number where the fragment is found (0-based index)
|
|
||||||
- "occurrence": Which occurrence of this sentence if it appears multiple times (1 for first, 2 for second, etc.)
|
|
||||||
- "confidence": Value between 0 and 1 indicating certainty (1.0 = completely certain, 0.5 = uncertain)
|
|
||||||
|
|
||||||
CRITICAL
|
|
||||||
- Output should be in the exact this format
|
|
||||||
- No any comments are allowed
|
|
||||||
|
|
||||||
CRITICAL - Output Format:
|
return prompt;
|
||||||
- Return ONLY the raw JSON array, nothing else
|
},
|
||||||
- DO NOT wrap the response in markdown code blocks (no \`\`\`json or \`\`\`)
|
|
||||||
- DO NOT include any explanatory text before or after the JSON
|
|
||||||
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
|
||||||
- The response should start with [ and end with ]
|
|
||||||
`;
|
|
||||||
prompt += "\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
|
||||||
|
|
||||||
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
|
||||||
|
|
||||||
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
/**
|
||||||
|
* @param {string} paraId
|
||||||
|
* @param {string} rangeId
|
||||||
|
* @return {HintInfoForPopup}
|
||||||
|
*/
|
||||||
|
getInfoForPopup: function (paraId, rangeId) {
|
||||||
|
let _s = this.getAnnotation(paraId, rangeId);
|
||||||
|
let reason = _s["reason"];
|
||||||
|
try {
|
||||||
|
reason = reason.replace(/<a\s+(.*?)>/gi, '<a $1 target="_blank">');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
original: _s["original"],
|
||||||
|
explanation: reason,
|
||||||
|
type: this.type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
return prompt;
|
/**
|
||||||
}
|
* @param {string} paraId
|
||||||
|
* @param {string} rangeId
|
||||||
|
*/
|
||||||
|
onAccept: async function (paraId, rangeId) {
|
||||||
|
await CustomAnnotator.prototype.onAccept.call(this);
|
||||||
|
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
||||||
|
|
||||||
/**
|
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
||||||
* @param {string} paraId
|
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
||||||
* @param {string} rangeId
|
|
||||||
* @return {HintInfoForPopup}
|
|
||||||
*/
|
|
||||||
AssistantHint.prototype.getInfoForPopup = function(paraId, rangeId)
|
|
||||||
{
|
|
||||||
let _s = this.getAnnotation(paraId, rangeId);
|
|
||||||
let reason = _s["reason"];
|
|
||||||
try {
|
|
||||||
reason = reason.replace(/<a\s+(.*?)>/gi, '<a $1 target="_blank">');
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
original : _s["original"],
|
|
||||||
explanation : reason,
|
|
||||||
type : this.type
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
await Asc.Editor.callCommand(function () {
|
||||||
* @param {string} paraId
|
Api.GetDocument().RemoveSelection();
|
||||||
* @param {string} rangeId
|
});
|
||||||
*/
|
|
||||||
AssistantHint.prototype.onAccept = async function(paraId, rangeId)
|
|
||||||
{
|
|
||||||
await CustomAnnotator.prototype.onAccept.call(this);
|
|
||||||
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
|
||||||
|
|
||||||
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
||||||
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
||||||
|
await Asc.Editor.callMethod("FocusEditor");
|
||||||
await Asc.Editor.callCommand(function(){
|
},
|
||||||
Api.GetDocument().RemoveSelection();
|
});
|
||||||
});
|
|
||||||
|
|
||||||
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
|
||||||
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
|
||||||
await Asc.Editor.callMethod("FocusEditor");
|
|
||||||
};
|
|
||||||
|
|||||||
@ -38,99 +38,71 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @extends CustomAnnotator
|
* @extends CustomAnnotator
|
||||||
*/
|
*/
|
||||||
function AssistantReplaceHint(annotationPopup, assistantData)
|
function AssistantReplaceHint(annotationPopup, assistantData) {
|
||||||
{
|
CustomAnnotator.call(this, annotationPopup, assistantData);
|
||||||
CustomAnnotator.call(this, annotationPopup, assistantData);
|
|
||||||
}
|
}
|
||||||
AssistantReplaceHint.prototype = Object.create(CustomAnnotator.prototype);
|
AssistantReplaceHint.prototype = Object.create(CustomAnnotator.prototype);
|
||||||
AssistantReplaceHint.prototype.constructor = AssistantReplaceHint;
|
AssistantReplaceHint.prototype.constructor = AssistantReplaceHint;
|
||||||
|
|
||||||
/**
|
Object.assign(AssistantReplaceHint.prototype, {
|
||||||
* @param {string} paraId
|
/**
|
||||||
* @param {string} recalcId
|
* @param {string} text
|
||||||
* @param {string} text
|
* @param {ReplaceHintAiResponse[]} matches
|
||||||
*/
|
*/
|
||||||
AssistantReplaceHint.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
_convertToRanges: function (paraId, text, matches) {
|
||||||
{
|
const _t = this;
|
||||||
this.paragraphs[paraId] = {};
|
let rangeId = 1;
|
||||||
|
const ranges = [];
|
||||||
|
for (const {
|
||||||
|
origin,
|
||||||
|
suggestion,
|
||||||
|
difference,
|
||||||
|
reason,
|
||||||
|
paragraph,
|
||||||
|
occurrence,
|
||||||
|
confidence,
|
||||||
|
} of matches) {
|
||||||
|
if (origin === suggestion || confidence <= 0.7) continue;
|
||||||
|
|
||||||
if (text.length === 0)
|
let count = 0;
|
||||||
return false;
|
let searchStart = 0;
|
||||||
|
|
||||||
const argPrompt = this._createPrompt(text);
|
while (searchStart < text.length) {
|
||||||
|
const index = _t.simpleGraphemeIndexOf(
|
||||||
|
text,
|
||||||
|
origin,
|
||||||
|
searchStart,
|
||||||
|
);
|
||||||
|
if (index === -1) break;
|
||||||
|
|
||||||
let response = await this.chatRequest(argPrompt);
|
count++;
|
||||||
if (!response)
|
if (count === occurrence) {
|
||||||
return false;
|
ranges.push({
|
||||||
|
start: index,
|
||||||
let rangeId = 1;
|
length: [...origin].length,
|
||||||
let ranges = [];
|
id: rangeId,
|
||||||
|
});
|
||||||
|
_t.paragraphs[paraId][rangeId] = {
|
||||||
|
original: origin,
|
||||||
|
suggestion: suggestion,
|
||||||
|
difference: difference,
|
||||||
|
reason: reason,
|
||||||
|
};
|
||||||
|
++rangeId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
searchStart = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
let _t = this;
|
/**
|
||||||
|
* @param {string} text
|
||||||
/**
|
* @returns {string}
|
||||||
* @param {string} text
|
*/
|
||||||
* @param {ReplaceHintAiResponse[]} matches
|
_createPrompt: function (text) {
|
||||||
*/
|
let prompt = `You are a multi-disciplinary text analysis and transformation assistant.
|
||||||
function convertToRanges(text, matches)
|
|
||||||
{
|
|
||||||
for (const { origin, suggestion, difference, reason, paragraph, occurrence, confidence } of matches)
|
|
||||||
{
|
|
||||||
if (origin === suggestion || confidence <= 0.7)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
let searchStart = 0;
|
|
||||||
|
|
||||||
while (searchStart < text.length)
|
|
||||||
{
|
|
||||||
const index = _t.simpleGraphemeIndexOf(text, origin, searchStart);
|
|
||||||
if (index === -1) break;
|
|
||||||
|
|
||||||
count++;
|
|
||||||
if (count === occurrence)
|
|
||||||
{
|
|
||||||
ranges.push({
|
|
||||||
"start": index,
|
|
||||||
"length": [...origin].length,
|
|
||||||
"id": rangeId
|
|
||||||
});
|
|
||||||
_t.paragraphs[paraId][rangeId] = {
|
|
||||||
"original" : origin,
|
|
||||||
"suggestion" : suggestion,
|
|
||||||
"difference" : difference,
|
|
||||||
"reason" : reason
|
|
||||||
};
|
|
||||||
++rangeId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
searchStart = index + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
convertToRanges(text, JSON.parse(response));
|
|
||||||
let obj = {
|
|
||||||
"type": "highlightText",
|
|
||||||
"paragraphId": paraId,
|
|
||||||
"name" : "customAssistant_" + this.assistantData.id,
|
|
||||||
"recalcId": recalcId,
|
|
||||||
"ranges": ranges
|
|
||||||
};
|
|
||||||
await Asc.Editor.callMethod("AnnotateParagraph", [obj]);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
AssistantReplaceHint.prototype._createPrompt = function(text) {
|
|
||||||
let prompt = `You are a multi-disciplinary text analysis and transformation assistant.
|
|
||||||
Your task is to analyze text based on user's specific criteria and provide intelligent corrections.
|
Your task is to analyze text based on user's specific criteria and provide intelligent corrections.
|
||||||
|
|
||||||
MANDATORY RULES:
|
MANDATORY RULES:
|
||||||
@ -180,58 +152,58 @@ AssistantReplaceHint.prototype._createPrompt = function(text) {
|
|||||||
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
||||||
- The response should start with [ and end with ]
|
- The response should start with [ and end with ]
|
||||||
`;
|
`;
|
||||||
prompt += "\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
prompt +=
|
||||||
|
"\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
||||||
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
|
||||||
|
|
||||||
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
||||||
|
|
||||||
return prompt;
|
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return prompt;
|
||||||
* @param {string} paraId
|
},
|
||||||
* @param {string} rangeId
|
|
||||||
* @returns {ReplaceHintInfoForPopup}
|
|
||||||
*/
|
|
||||||
AssistantReplaceHint.prototype.getInfoForPopup = function(paraId, rangeId)
|
|
||||||
{
|
|
||||||
let _s = this.getAnnotation(paraId, rangeId);
|
|
||||||
let reason = _s["reason"];
|
|
||||||
try {
|
|
||||||
reason = reason.replace(/<a\s+(.*?)>/gi, '<a $1 target="_blank">');
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
original : _s["original"],
|
|
||||||
suggested : _s["difference"],
|
|
||||||
explanation : reason,
|
|
||||||
type : this.type
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} paraId
|
* @param {string} paraId
|
||||||
* @param {string} rangeId
|
* @param {string} rangeId
|
||||||
*/
|
* @returns {ReplaceHintInfoForPopup}
|
||||||
AssistantReplaceHint.prototype.onAccept = async function(paraId, rangeId)
|
*/
|
||||||
{
|
getInfoForPopup: function (paraId, rangeId) {
|
||||||
await CustomAnnotator.prototype.onAccept.call(this, paraId, rangeId);
|
let _s = this.getAnnotation(paraId, rangeId);
|
||||||
let text = this.getAnnotation(paraId, rangeId)["suggestion"];
|
let reason = _s["reason"];
|
||||||
|
try {
|
||||||
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
reason = reason.replace(/<a\s+(.*?)>/gi, '<a $1 target="_blank">');
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
original: _s["original"],
|
||||||
|
suggested: _s["difference"],
|
||||||
|
explanation: reason,
|
||||||
|
type: this.type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
/**
|
||||||
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
* @param {string} paraId
|
||||||
|
* @param {string} rangeId
|
||||||
Asc.scope.text = text;
|
*/
|
||||||
await Asc.Editor.callCommand(function(){
|
onAccept: async function (paraId, rangeId) {
|
||||||
Api.ReplaceTextSmart([Asc.scope.text]);
|
await CustomAnnotator.prototype.onAccept.call(this, paraId, rangeId);
|
||||||
Api.GetDocument().RemoveSelection();
|
let text = this.getAnnotation(paraId, rangeId)["suggestion"];
|
||||||
});
|
|
||||||
|
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
||||||
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
|
||||||
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
||||||
await Asc.Editor.callMethod("FocusEditor");
|
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
||||||
};
|
|
||||||
|
Asc.scope.text = text;
|
||||||
|
await Asc.Editor.callCommand(function () {
|
||||||
|
Api.ReplaceTextSmart([Asc.scope.text]);
|
||||||
|
Api.GetDocument().RemoveSelection();
|
||||||
|
});
|
||||||
|
|
||||||
|
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
||||||
|
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
||||||
|
await Asc.Editor.callMethod("FocusEditor");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -38,97 +38,67 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @extends CustomAnnotator
|
* @extends CustomAnnotator
|
||||||
*/
|
*/
|
||||||
function AssistantReplace(annotationPopup, assistantData)
|
function AssistantReplace(annotationPopup, assistantData) {
|
||||||
{
|
CustomAnnotator.call(this, annotationPopup, assistantData);
|
||||||
CustomAnnotator.call(this, annotationPopup, assistantData);
|
|
||||||
}
|
}
|
||||||
AssistantReplace.prototype = Object.create(CustomAnnotator.prototype);
|
AssistantReplace.prototype = Object.create(CustomAnnotator.prototype);
|
||||||
AssistantReplace.prototype.constructor = AssistantReplace;
|
AssistantReplace.prototype.constructor = AssistantReplace;
|
||||||
|
|
||||||
/**
|
Object.assign(AssistantReplace.prototype, {
|
||||||
* @param {string} paraId
|
/**
|
||||||
* @param {string} recalcId
|
* @param {string} text
|
||||||
* @param {string} text
|
* @param {ReplaceAiResponse[]} matches
|
||||||
*/
|
*/
|
||||||
AssistantReplace.prototype.annotateParagraph = async function(paraId, recalcId, text)
|
_convertToRanges: function (paraId, text, matches) {
|
||||||
{
|
const _t = this;
|
||||||
this.paragraphs[paraId] = {};
|
let rangeId = 1;
|
||||||
|
const ranges = [];
|
||||||
|
for (const {
|
||||||
|
origin,
|
||||||
|
suggestion,
|
||||||
|
paragraph,
|
||||||
|
occurrence,
|
||||||
|
confidence,
|
||||||
|
} of matches) {
|
||||||
|
if (origin === suggestion || confidence <= 0.7) continue;
|
||||||
|
|
||||||
if (text.length === 0)
|
let count = 0;
|
||||||
return false;
|
let searchStart = 0;
|
||||||
|
|
||||||
const argPrompt = this._createPrompt(text);
|
while (searchStart < text.length) {
|
||||||
|
const index = _t.simpleGraphemeIndexOf(
|
||||||
|
text,
|
||||||
|
origin,
|
||||||
|
searchStart,
|
||||||
|
);
|
||||||
|
if (index === -1) break;
|
||||||
|
|
||||||
let response = await this.chatRequest(argPrompt);
|
count++;
|
||||||
if (!response)
|
if (count === occurrence) {
|
||||||
return false;
|
ranges.push({
|
||||||
|
start: index,
|
||||||
|
length: [...origin].length,
|
||||||
|
id: rangeId,
|
||||||
|
});
|
||||||
|
_t.paragraphs[paraId][rangeId] = {
|
||||||
|
original: origin,
|
||||||
|
suggestion: suggestion,
|
||||||
|
};
|
||||||
|
++rangeId;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
searchStart = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
},
|
||||||
|
|
||||||
let rangeId = 1;
|
/**
|
||||||
let ranges = [];
|
* @param {string} text
|
||||||
|
* @returns {string}
|
||||||
let _t = this;
|
*/
|
||||||
|
_createPrompt: function (text) {
|
||||||
/**
|
let prompt = `You are a multi-disciplinary text analysis and transformation assistant.
|
||||||
* @param {string} text
|
|
||||||
* @param {ReplaceAiResponse[]} matches
|
|
||||||
*/
|
|
||||||
function convertToRanges(text, matches)
|
|
||||||
{
|
|
||||||
for (const { origin, suggestion, paragraph, occurrence, confidence } of matches)
|
|
||||||
{
|
|
||||||
if (origin === suggestion || confidence <= 0.7)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
let searchStart = 0;
|
|
||||||
|
|
||||||
while (searchStart < text.length)
|
|
||||||
{
|
|
||||||
const index = _t.simpleGraphemeIndexOf(text, origin, searchStart);
|
|
||||||
if (index === -1) break;
|
|
||||||
|
|
||||||
count++;
|
|
||||||
if (count === occurrence)
|
|
||||||
{
|
|
||||||
ranges.push({
|
|
||||||
"start": index,
|
|
||||||
"length": [...origin].length,
|
|
||||||
"id": rangeId
|
|
||||||
});
|
|
||||||
_t.paragraphs[paraId][rangeId] = {
|
|
||||||
"original" : origin,
|
|
||||||
"suggestion" : suggestion,
|
|
||||||
};
|
|
||||||
++rangeId;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
searchStart = index + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
convertToRanges(text, JSON.parse(response));
|
|
||||||
let obj = {
|
|
||||||
"type": "highlightText",
|
|
||||||
"paragraphId": paraId,
|
|
||||||
"name" : "customAssistant_" + this.assistantData.id,
|
|
||||||
"recalcId": recalcId,
|
|
||||||
"ranges": ranges
|
|
||||||
};
|
|
||||||
await Asc.Editor.callMethod("AnnotateParagraph", [obj]);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} text
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
AssistantReplace.prototype._createPrompt = function(text) {
|
|
||||||
let prompt = `You are a multi-disciplinary text analysis and transformation assistant.
|
|
||||||
Your task is to analyze text based on user's specific criteria and provide intelligent corrections.
|
Your task is to analyze text based on user's specific criteria and provide intelligent corrections.
|
||||||
|
|
||||||
MANDATORY RULES:
|
MANDATORY RULES:
|
||||||
@ -174,51 +144,51 @@ AssistantReplace.prototype._createPrompt = function(text) {
|
|||||||
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
- DO NOT use escaped newlines (\\n) - return the JSON on a single line if possible
|
||||||
- The response should start with [ and end with ]
|
- The response should start with [ and end with ]
|
||||||
`;
|
`;
|
||||||
prompt += "\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
prompt +=
|
||||||
|
"\n\nUSER REQUEST:\n```" + this.assistantData.query + "\n```\n\n";
|
||||||
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
|
||||||
|
|
||||||
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
prompt += "TEXT TO ANALYZE:\n```\n" + text + "\n```\n\n";
|
||||||
|
|
||||||
return prompt;
|
prompt += `Please analyze this text and find all fragments that match the user's request. Be thorough but precise.`;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
return prompt;
|
||||||
* @param {string} paraId
|
},
|
||||||
* @param {string} rangeId
|
|
||||||
* @returns {ReplaceInfoForPopup}
|
|
||||||
*/
|
|
||||||
AssistantReplace.prototype.getInfoForPopup = function(paraId, rangeId)
|
|
||||||
{
|
|
||||||
let _s = this.getAnnotation(paraId, rangeId);
|
|
||||||
return {
|
|
||||||
original : _s["original"],
|
|
||||||
suggested : _s["suggestion"],
|
|
||||||
type : this.type
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} paraId
|
* @param {string} paraId
|
||||||
* @param {string} rangeId
|
* @param {string} rangeId
|
||||||
*/
|
* @returns {ReplaceInfoForPopup}
|
||||||
AssistantReplace.prototype.onAccept = async function(paraId, rangeId)
|
*/
|
||||||
{
|
getInfoForPopup: function (paraId, rangeId) {
|
||||||
await CustomAnnotator.prototype.onAccept.call(this);
|
let _s = this.getAnnotation(paraId, rangeId);
|
||||||
let text = this.getAnnotation(paraId, rangeId)["suggestion"];
|
return {
|
||||||
|
original: _s["original"],
|
||||||
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
suggested: _s["suggestion"],
|
||||||
|
type: this.type,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
/**
|
||||||
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
* @param {string} paraId
|
||||||
|
* @param {string} rangeId
|
||||||
Asc.scope.text = text;
|
*/
|
||||||
await Asc.Editor.callCommand(function(){
|
onAccept: async function (paraId, rangeId) {
|
||||||
Api.ReplaceTextSmart([Asc.scope.text]);
|
await CustomAnnotator.prototype.onAccept.call(this);
|
||||||
Api.GetDocument().RemoveSelection();
|
let text = this.getAnnotation(paraId, rangeId)["suggestion"];
|
||||||
});
|
|
||||||
|
await Asc.Editor.callMethod("StartAction", ["GroupActions"]);
|
||||||
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
|
||||||
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
let range = this.getAnnotationRangeObj(paraId, rangeId);
|
||||||
await Asc.Editor.callMethod("FocusEditor");
|
await Asc.Editor.callMethod("SelectAnnotationRange", [range]);
|
||||||
};
|
|
||||||
|
Asc.scope.text = text;
|
||||||
|
await Asc.Editor.callCommand(function () {
|
||||||
|
Api.ReplaceTextSmart([Asc.scope.text]);
|
||||||
|
Api.GetDocument().RemoveSelection();
|
||||||
|
});
|
||||||
|
|
||||||
|
await Asc.Editor.callMethod("RemoveAnnotationRange", [range]);
|
||||||
|
await Asc.Editor.callMethod("EndAction", ["GroupActions"]);
|
||||||
|
await Asc.Editor.callMethod("FocusEditor");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -37,61 +37,86 @@
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @extends TextAnnotator
|
* @extends TextAnnotator
|
||||||
*/
|
*/
|
||||||
function CustomAnnotator(annotationPopup, assistantData)
|
function CustomAnnotator(annotationPopup, assistantData) {
|
||||||
{
|
TextAnnotator.call(this, annotationPopup);
|
||||||
TextAnnotator.call(this, annotationPopup);
|
this.assistantData = assistantData;
|
||||||
this.assistantData = assistantData;
|
this.type = assistantData.type;
|
||||||
this.type = assistantData.type;
|
this._skipNextChangeParagraph = false;
|
||||||
this._skipNextChangeParagraph = false;
|
|
||||||
}
|
}
|
||||||
CustomAnnotator.prototype = Object.create(TextAnnotator.prototype);
|
CustomAnnotator.prototype = Object.create(TextAnnotator.prototype);
|
||||||
CustomAnnotator.prototype.constructor = CustomAnnotator;
|
CustomAnnotator.prototype.constructor = CustomAnnotator;
|
||||||
|
|
||||||
/**
|
Object.assign(CustomAnnotator.prototype, {
|
||||||
* @param {string} paraId
|
/**
|
||||||
* @param {string} rangeId
|
* @param {string} paraId
|
||||||
*/
|
* @param {string} recalcId
|
||||||
CustomAnnotator.prototype.getAnnotationRangeObj = function(paraId, rangeId)
|
* @param {string} text
|
||||||
{
|
*/
|
||||||
return {
|
annotateParagraph: async function (paraId, recalcId, text) {
|
||||||
"paragraphId" : paraId,
|
this.paragraphs[paraId] = {};
|
||||||
"rangeId" : rangeId,
|
|
||||||
"name" : "customAssistant_" + this.assistantData.id
|
|
||||||
};
|
|
||||||
};
|
|
||||||
CustomAnnotator.prototype._handleNewRangePositions = async function(range, paraId, text)
|
|
||||||
{
|
|
||||||
if (!range || range["name"] !== "customAssistant_" + this.assistantData.id || !this.paragraphs[paraId])
|
|
||||||
return;
|
|
||||||
|
|
||||||
let rangeId = range["id"];
|
if (text.length === 0) return false;
|
||||||
let annot = this.getAnnotation(paraId, rangeId);
|
|
||||||
|
|
||||||
if (!annot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let start = range["start"];
|
|
||||||
let len = range["length"];
|
|
||||||
|
|
||||||
if (annot["original"] !== text.substring(start, start + len))
|
const argPrompt = this._createPrompt(text);
|
||||||
{
|
|
||||||
let annotRange = this.getAnnotationRangeObj(paraId, rangeId);
|
let response = await this.chatRequest(argPrompt);
|
||||||
Asc.Editor.callMethod("RemoveAnnotationRange", [annotRange]);
|
if (!response) return false;
|
||||||
}
|
|
||||||
};
|
try {
|
||||||
/**
|
const ranges = this._convertToRanges(paraId, text, JSON.parse(response));
|
||||||
* @param {string[]} paraIds
|
let obj = {
|
||||||
*/
|
type: "highlightText",
|
||||||
CustomAnnotator.prototype.checkParagraphs = async function(paraIds)
|
paragraphId: paraId,
|
||||||
{
|
name: "customAssistant_" + this.assistantData.id,
|
||||||
if (this._skipNextChangeParagraph)
|
recalcId: recalcId,
|
||||||
{
|
ranges: ranges,
|
||||||
this._skipNextChangeParagraph = false;
|
};
|
||||||
return;
|
await Asc.Editor.callMethod("AnnotateParagraph", [obj]);
|
||||||
}
|
} catch (e) {}
|
||||||
TextAnnotator.prototype.checkParagraphs.call(this, paraIds);
|
},
|
||||||
};
|
/**
|
||||||
CustomAnnotator.prototype.onAccept = async function(paraId, rangeId)
|
* @param {string} paraId
|
||||||
{
|
* @param {string} rangeId
|
||||||
this._skipNextChangeParagraph = true;
|
*/
|
||||||
};
|
getAnnotationRangeObj: function (paraId, rangeId) {
|
||||||
|
return {
|
||||||
|
paragraphId: paraId,
|
||||||
|
rangeId: rangeId,
|
||||||
|
name: "customAssistant_" + this.assistantData.id,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_handleNewRangePositions: async function (range, paraId, text) {
|
||||||
|
if (
|
||||||
|
!range ||
|
||||||
|
range["name"] !== "customAssistant_" + this.assistantData.id ||
|
||||||
|
!this.paragraphs[paraId]
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
let rangeId = range["id"];
|
||||||
|
let annot = this.getAnnotation(paraId, rangeId);
|
||||||
|
|
||||||
|
if (!annot) return;
|
||||||
|
|
||||||
|
let start = range["start"];
|
||||||
|
let len = range["length"];
|
||||||
|
|
||||||
|
if (annot["original"] !== text.substring(start, start + len)) {
|
||||||
|
let annotRange = this.getAnnotationRangeObj(paraId, rangeId);
|
||||||
|
Asc.Editor.callMethod("RemoveAnnotationRange", [annotRange]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {string[]} paraIds
|
||||||
|
*/
|
||||||
|
checkParagraphs: async function (paraIds) {
|
||||||
|
if (this._skipNextChangeParagraph) {
|
||||||
|
this._skipNextChangeParagraph = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TextAnnotator.prototype.checkParagraphs.call(this, paraIds);
|
||||||
|
},
|
||||||
|
onAccept: async function (paraId, rangeId) {
|
||||||
|
this._skipNextChangeParagraph = true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|||||||
@ -41,14 +41,14 @@
|
|||||||
|
|
||||||
class CustomAssistantManager {
|
class CustomAssistantManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
/**
|
/**
|
||||||
* @type {Map<string, Assistant>}
|
* @type {Map<string, Assistant>}
|
||||||
*/
|
*/
|
||||||
this._customAssistants = new Map();
|
this._customAssistants = new Map();
|
||||||
this._isCustomAssistantInit = new Map();
|
this._isCustomAssistantInit = new Map();
|
||||||
this._isCustomAssistantRunning = new Map();
|
this._isCustomAssistantRunning = new Map();
|
||||||
/** @type {Map<string, {recalcId: number, text: string, annotations: any}>} */
|
/** @type {Map<string, {recalcId: string, text: string, annotations: any}>} */
|
||||||
this._paragraphsStack = new Map();
|
this._paragraphsStack = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,19 +62,30 @@ class CustomAssistantManager {
|
|||||||
let assistant = null;
|
let assistant = null;
|
||||||
switch (assistantData.type) {
|
switch (assistantData.type) {
|
||||||
case 0:
|
case 0:
|
||||||
assistant = new AssistantHint(customAnnotationPopup, assistantData);
|
assistant = new AssistantHint(
|
||||||
|
customAnnotationPopup,
|
||||||
|
assistantData,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
assistant = new AssistantReplaceHint(customAnnotationPopup, assistantData);
|
assistant = new AssistantReplaceHint(
|
||||||
|
customAnnotationPopup,
|
||||||
|
assistantData,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
assistant = new AssistantReplace(customAnnotationPopup, assistantData);
|
assistant = new AssistantReplace(
|
||||||
|
customAnnotationPopup,
|
||||||
|
assistantData,
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!assistant) {
|
if (!assistant) {
|
||||||
throw new Error("Unknown custom assistant type: " + assistantData.type);
|
throw new Error(
|
||||||
|
"Unknown custom assistant type: " + assistantData.type,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._isCustomAssistantInit.set(assistantData.id, false);
|
this._isCustomAssistantInit.set(assistantData.id, false);
|
||||||
this._isCustomAssistantRunning.set(assistantData.id, false);
|
this._isCustomAssistantRunning.set(assistantData.id, false);
|
||||||
this._customAssistants.set(assistantData.id, assistant);
|
this._customAssistants.set(assistantData.id, assistant);
|
||||||
@ -96,13 +107,13 @@ class CustomAssistantManager {
|
|||||||
if (!isRunning) {
|
if (!isRunning) {
|
||||||
return assistant;
|
return assistant;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._paragraphsStack.forEach((value, paraId) => {
|
this._paragraphsStack.forEach((value, paraId) => {
|
||||||
assistant.onChangeParagraph(
|
assistant.onChangeParagraph(
|
||||||
paraId,
|
paraId,
|
||||||
value.recalcId,
|
value.recalcId,
|
||||||
value.text,
|
value.text,
|
||||||
value.annotations
|
value.annotations,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const paragraphIdsToUpdate = [...assistant.checked];
|
const paragraphIdsToUpdate = [...assistant.checked];
|
||||||
@ -118,14 +129,11 @@ class CustomAssistantManager {
|
|||||||
this._isCustomAssistantRunning.delete(assistantId);
|
this._isCustomAssistantRunning.delete(assistantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {string} assistantId */
|
/** @param {string} assistantId */
|
||||||
checkNeedToRunAssistant(assistantId) {
|
checkNeedToRunAssistant(assistantId) {
|
||||||
const isRunning = this._isCustomAssistantRunning.get(assistantId);
|
const isRunning = this._isCustomAssistantRunning.get(assistantId);
|
||||||
this._isCustomAssistantRunning.set(
|
this._isCustomAssistantRunning.set(assistantId, !isRunning);
|
||||||
assistantId,
|
return isRunning;
|
||||||
!isRunning
|
|
||||||
);
|
|
||||||
return isRunning;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -134,53 +142,53 @@ class CustomAssistantManager {
|
|||||||
*/
|
*/
|
||||||
run(assistantId, paraIds) {
|
run(assistantId, paraIds) {
|
||||||
const assistant = this._customAssistants.get(assistantId);
|
const assistant = this._customAssistants.get(assistantId);
|
||||||
if (!assistant) {
|
if (!assistant) {
|
||||||
console.error("Custom assistant not found: " + assistantId);
|
console.error("Custom assistant not found: " + assistantId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._isCustomAssistantInit.get(assistantId)) {
|
if (!this._isCustomAssistantInit.get(assistantId)) {
|
||||||
this._paragraphsStack.forEach((value, paraId) => {
|
this._paragraphsStack.forEach((value, paraId) => {
|
||||||
assistant.onChangeParagraph(
|
assistant.onChangeParagraph(
|
||||||
paraId,
|
paraId,
|
||||||
value.recalcId,
|
value.recalcId,
|
||||||
value.text,
|
value.text,
|
||||||
value.annotations
|
value.annotations,
|
||||||
)
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
assistant.checkParagraphs(paraIds);
|
assistant.checkParagraphs(paraIds);
|
||||||
this._isCustomAssistantInit.set(assistantId, true);
|
this._isCustomAssistantInit.set(assistantId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} paragraphId
|
* @param {string} paragraphId
|
||||||
* @param {number} recalcId
|
* @param {string} recalcId
|
||||||
* @param {string} text
|
* @param {string} text
|
||||||
* @param {*} annotations
|
* @param {*} annotations
|
||||||
*/
|
*/
|
||||||
onChangeParagraph(paragraphId, recalcId, text, annotations) {
|
onChangeParagraph(paragraphId, recalcId, text, annotations) {
|
||||||
this._paragraphsStack.set(paragraphId, {
|
this._paragraphsStack.set(paragraphId, {
|
||||||
recalcId,
|
recalcId,
|
||||||
text,
|
text,
|
||||||
annotations
|
annotations,
|
||||||
});
|
});
|
||||||
this._customAssistants.forEach((assistant, assistantId) => {
|
this._customAssistants.forEach((assistant, assistantId) => {
|
||||||
const isInit = this._isCustomAssistantInit.get(assistantId);
|
const isInit = this._isCustomAssistantInit.get(assistantId);
|
||||||
if (!isInit) {
|
if (!isInit) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assistant.onChangeParagraph(
|
assistant.onChangeParagraph(
|
||||||
paragraphId,
|
paragraphId,
|
||||||
recalcId,
|
recalcId,
|
||||||
text,
|
text,
|
||||||
annotations
|
annotations,
|
||||||
);
|
);
|
||||||
const isRunning = this._isCustomAssistantRunning.get(assistantId);
|
const isRunning = this._isCustomAssistantRunning.get(assistantId);
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
assistant.checkParagraphs([paragraphId]);
|
assistant.checkParagraphs([paragraphId]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,7 +37,7 @@ function TextAnnotator(annotatorPopup)
|
|||||||
this.rangeId = null;
|
this.rangeId = null;
|
||||||
|
|
||||||
this.paragraphs = {};
|
this.paragraphs = {};
|
||||||
/** @type {Object.<string, {recalcId: number, text: string}>} */
|
/** @type {Object.<string, {recalcId: string, text: string}>} */
|
||||||
this.waitParagraphs = {};
|
this.waitParagraphs = {};
|
||||||
this.paraToCheck = new Set();
|
this.paraToCheck = new Set();
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
@ -47,7 +47,7 @@ function TextAnnotator(annotatorPopup)
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @param {string} paraId
|
* @param {string} paraId
|
||||||
* @param {number} recalcId
|
* @param {string} recalcId
|
||||||
* @param {string} text
|
* @param {string} text
|
||||||
* @param {string[]} ranges
|
* @param {string[]} ranges
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user