diff options
| -rw-r--r-- | src/ollama.tsx | 113 |
1 files changed, 96 insertions, 17 deletions
diff --git a/src/ollama.tsx b/src/ollama.tsx index 7da5f8f..4451beb 100644 --- a/src/ollama.tsx +++ b/src/ollama.tsx @@ -119,17 +119,21 @@ async function promptLLM(prompt: string) { prompt: prompt, stream: false, }), - }) + }); if (!response.ok) { - logseq.App.showMsg("Coudln't fulfill request make sure that ollama service is running and make sure there is no typo in host or model name") - throw new Error("Error in Ollama request: " + response.statusText) + logseq.App.showMsg("Couldn't fulfill request. Make sure Ollama service is running and there are no typos in host or model name."); + throw new Error("Error in Ollama request: " + response.statusText); } + const data = await response.json(); - return data.response; + // Remove any <think>…</think> blocks in the response + const filteredResponse = data.response.replace(/<think>[\s\S]*?<\/think>/g, ''); + + return filteredResponse; } catch (e: any) { - console.error("ERROR: ", e) - logseq.App.showMsg("Coudln't fulfill request make sure that ollama service is running and make sure there is no typo in host or model name") + console.error("ERROR: ", e); + logseq.App.showMsg("Couldn't fulfill request. Make sure Ollama service is running and there are no typos in host or model name."); } } @@ -302,20 +306,95 @@ export async function convertToFlashCardCurrentBlock() { export async function DivideTaskIntoSubTasks(uuid: string, content: string) { try { - const block = await logseq.Editor.insertBlock(uuid, "✅ Genearting todos ...", { before: false }) - let i = 0; - const response = await promptLLM(`Divide this task into subtasks with numbers: ${content} `) - for (const todo of response.split("\n")) { - if (i == 0) { - await logseq.Editor.updateBlock(block!.uuid, `TODO ${todo.slice(3)} `) - } else { - await logseq.Editor.insertBlock(uuid, `TODO ${todo.slice(3)} `, { before: false }) + // 1) Insert initial placeholder block. + const placeholderBlock = await logseq.Editor.insertBlock( + uuid, + "✅ Generating todos ...", + { before: false } + ); + if (!placeholderBlock) { + throw new Error("Could not insert the placeholder block."); + } + + // 2) Fetch LLM response + const response = await promptLLM( + `Divide this task into subtasks with numbers respond with multilevel nested markdown format, no dot notation, one subtask per line, plain text only.: ${content}` + ); + + // 3) Split on newlines, ignoring empty lines + const lines = response + .split("\n") + .map((line: string) => line.replace(/\r$/, "")) // remove trailing \r if present + .filter((line: string) => line.trim().length > 0); + + // If there's nothing, do nothing + if (!lines.length) return; + + // 4) Update the placeholder block with the very first line + // preserving its entire text (no slicing or removal). + // Prepend “TODO ” as in your original code structure. + await logseq.Editor.updateBlock( + placeholderBlock.uuid, + `TODO ${lines[0]}` + ); + + // If there was only one line, we’re done + if (lines.length === 1) return; + + // 5) Now set up stack-based nesting for the rest: + // stack top is always the most recent block at a particular level. + // We'll treat the placeholder block as level=0 + const stack = [{ uuid: placeholderBlock.uuid, level: 0 }]; + + // Helper: Determine indent-based nesting level. + // Adjust baseIndent if your model uses different spacing for sub-levels. + function getIndentLevel(line: string): number { + const firstCharIndex = line.search(/\S/); + // no non-whitespace => treat as top-level + if (firstCharIndex < 0) { + return 0; + } + // e.g. baseIndent=2 → each 2 leading spaces => +1 nesting level + const baseIndent = 3; + return Math.floor(firstCharIndex / baseIndent); + } + + // 6) Process remaining lines to handle nesting + for (let i = 1; i < lines.length; i++) { + const rawLine = lines[i]; + + // figure out “level” from indentation + const level = getIndentLevel(rawLine); + + // pop the stack until we find a block whose level is < current level + while (stack.length > 0 && stack[stack.length - 1].level >= level) { + stack.pop(); + } + + // if the stack is empty (all popped), fallback to the placeholder: + if (stack.length === 0) { + stack.push({ uuid: placeholderBlock.uuid, level: 0 }); + } + + // top of stack is the parent block where we create a child + const parent = stack[stack.length - 1]; + + // Insert a child block. Trim only leading spaces from the line’s text so we keep the numbering/content + const trimmedText = rawLine.replace(/^\s+/, ""); + const newBlock = await logseq.Editor.insertBlock( + parent.uuid, + `TODO ${trimmedText}`, + { sibling: false } + ); + + if (newBlock) { + // push newly inserted block at the correct level + stack.push({ uuid: newBlock.uuid, level }); } - i++; } } catch (e: any) { - logseq.App.showMsg(e.toString(), 'warning') - console.error(e) + logseq.App.showMsg(e.toString(), "warning"); + console.error(e); } } |
