Strengthen tool-calling discipline and add auto-nudge fallback
Tighten system prompts across edit, organize, and research modes to prohibit "Let me..." / "I will..." prefatory text and require immediate tool_call emission. Remove stale instructions referencing deleted tools. Improve search_vault_files description for LLM clarity. Add runtime auto-nudge: if a tool-capable mode emits no tool_calls but language suggests intent to act, re-prompt the model to emit the required calls.
This commit is contained in:
@@ -3180,7 +3180,7 @@ Do not make up facts.`,
|
||||
description: "Create, modify, and organize notes with full editing tools.",
|
||||
systemPrompt: `You are an assistant that helps edit and manage notes in the user's Obsidian vault.
|
||||
You have full access to reading, searching, creating, appending, renaming, moving, and deleting notes.
|
||||
IMPORTANT: When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to the appropriate tool.
|
||||
CRITICAL RULE: When you need to take action, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
When editing notes:
|
||||
- Prefer modifying existing content over creating duplicates.
|
||||
@@ -3196,9 +3196,8 @@ When editing notes:
|
||||
label: "Organize",
|
||||
description: "Tag, rename, move, and link notes to keep the vault tidy.",
|
||||
systemPrompt: `You are an assistant that helps organize the user's Obsidian vault.
|
||||
You can search notes, read them, list all vault tags, get vault structure stats, update frontmatter tags, rename files, move files to folders, and insert wiki-links.
|
||||
IMPORTANT: When the user asks about tags or folder structure, use list_vault_tags or get_vault_stats FIRST instead of searching blindly.
|
||||
When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to the appropriate tool.
|
||||
You can search notes, read them, update frontmatter tags, rename files, move files to folders, and insert wiki-links.
|
||||
CRITICAL RULE: When you need to take action, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
When organizing:
|
||||
- Suggest consistent tag vocabularies.
|
||||
@@ -3214,8 +3213,7 @@ When organizing:
|
||||
description: "Deep vault search and synthesis across multiple notes.",
|
||||
systemPrompt: `You are a research assistant that dives deep into the user's Obsidian vault.
|
||||
Your job is to synthesize information across multiple notes, find connections, and produce comprehensive summaries.
|
||||
IMPORTANT: When the user asks about tags or vault structure, use list_vault_tags or get_vault_stats FIRST before searching.
|
||||
When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to search_vault_files or read_vault_file.
|
||||
CRITICAL RULE: When you need vault information, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
Search broadly, read key sources, and cross-reference information.
|
||||
Cite specific notes and quotes where possible.
|
||||
@@ -11285,13 +11283,13 @@ var ChatView = class extends import_obsidian5.ItemView {
|
||||
type: "function",
|
||||
function: {
|
||||
name: "search_vault_files",
|
||||
description: "Searches for files in the vault that match a given query",
|
||||
description: "Searches for files in the vault by content, tags, titles, and headings using a given query. Returns matching file metadata including paths, titles, and tags.",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
query: {
|
||||
type: "string",
|
||||
description: "The search query to use"
|
||||
description: "The search query to use (can be a keyword, tag, or phrase)"
|
||||
},
|
||||
limit: {
|
||||
type: "number",
|
||||
@@ -11893,6 +11891,60 @@ ${actualMessage}` : actualMessage;
|
||||
assistantMessageId
|
||||
);
|
||||
}
|
||||
const toolCapableModes = ["edit", "organize", "research"];
|
||||
if (toolCalls.length === 0 && toolCapableModes.includes(this.currentAgentMode) && fullResponse.trim().length > 0) {
|
||||
const intentPhrases = [
|
||||
"let me",
|
||||
"i will",
|
||||
"i need to",
|
||||
"search for",
|
||||
"find",
|
||||
"read",
|
||||
"explore",
|
||||
"look for",
|
||||
"check",
|
||||
"move",
|
||||
"rename",
|
||||
"create"
|
||||
];
|
||||
const lowerResponse = fullResponse.toLowerCase();
|
||||
const seemsToWantTools = intentPhrases.some((p) => lowerResponse.includes(p));
|
||||
if (seemsToWantTools) {
|
||||
const nudgeMessages = [
|
||||
...messagesWithMemory,
|
||||
{ role: "assistant", content: fullResponse },
|
||||
{
|
||||
role: "user",
|
||||
content: "You indicated you would take action but did not emit any tool_calls. Please emit the required tool_calls now. Do not output explanatory text."
|
||||
}
|
||||
];
|
||||
const nudgeStream = activeClient.streamChat(nudgeMessages, tools);
|
||||
fullResponse = "";
|
||||
toolCalls = [];
|
||||
for await (const chunk of nudgeStream) {
|
||||
if (chunk.content) {
|
||||
fullResponse += chunk.content;
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: fullResponse,
|
||||
isStreaming: true,
|
||||
isThinking: false
|
||||
});
|
||||
}
|
||||
if (chunk.tool_calls) {
|
||||
toolCalls = [...toolCalls, ...chunk.tool_calls];
|
||||
}
|
||||
}
|
||||
if (toolCalls.length > 0) {
|
||||
await this.processToolCalls(
|
||||
toolCalls,
|
||||
nudgeMessages,
|
||||
tools,
|
||||
fullResponse,
|
||||
assistantMessageId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (toolCalls.length === 0) {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: fullResponse,
|
||||
|
||||
+4
-6
@@ -86,7 +86,7 @@ Do not make up facts.`,
|
||||
description: 'Create, modify, and organize notes with full editing tools.',
|
||||
systemPrompt: `You are an assistant that helps edit and manage notes in the user's Obsidian vault.
|
||||
You have full access to reading, searching, creating, appending, renaming, moving, and deleting notes.
|
||||
IMPORTANT: When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to the appropriate tool.
|
||||
CRITICAL RULE: When you need to take action, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
When editing notes:
|
||||
- Prefer modifying existing content over creating duplicates.
|
||||
@@ -103,9 +103,8 @@ When editing notes:
|
||||
label: 'Organize',
|
||||
description: 'Tag, rename, move, and link notes to keep the vault tidy.',
|
||||
systemPrompt: `You are an assistant that helps organize the user's Obsidian vault.
|
||||
You can search notes, read them, list all vault tags, get vault structure stats, update frontmatter tags, rename files, move files to folders, and insert wiki-links.
|
||||
IMPORTANT: When the user asks about tags or folder structure, use list_vault_tags or get_vault_stats FIRST instead of searching blindly.
|
||||
When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to the appropriate tool.
|
||||
You can search notes, read them, update frontmatter tags, rename files, move files to folders, and insert wiki-links.
|
||||
CRITICAL RULE: When you need to take action, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
When organizing:
|
||||
- Suggest consistent tag vocabularies.
|
||||
@@ -122,8 +121,7 @@ When organizing:
|
||||
description: 'Deep vault search and synthesis across multiple notes.',
|
||||
systemPrompt: `You are a research assistant that dives deep into the user's Obsidian vault.
|
||||
Your job is to synthesize information across multiple notes, find connections, and produce comprehensive summaries.
|
||||
IMPORTANT: When the user asks about tags or vault structure, use list_vault_tags or get_vault_stats FIRST before searching.
|
||||
When you need vault information, do NOT say you will search or read files. You MUST immediately emit a tool_call to search_vault_files or read_vault_file.
|
||||
CRITICAL RULE: When you need vault information, you MUST immediately emit the tool_call(s). Do NOT output text like "Let me search..." or "I will..." or "Now I...". Either emit the tool calls immediately, or provide the final answer.
|
||||
Only respond to the user after you have received and analyzed the tool results.
|
||||
Search broadly, read key sources, and cross-reference information.
|
||||
Cite specific notes and quotes where possible.
|
||||
|
||||
+64
-2
@@ -522,13 +522,14 @@ export class ChatView extends ItemView {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'search_vault_files',
|
||||
description: 'Searches for files in the vault that match a given query',
|
||||
description:
|
||||
'Searches for files in the vault by content, tags, titles, and headings using a given query. Returns matching file metadata including paths, titles, and tags.',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
query: {
|
||||
type: 'string',
|
||||
description: 'The search query to use',
|
||||
description: 'The search query to use (can be a keyword, tag, or phrase)',
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
@@ -1234,6 +1235,67 @@ export class ChatView extends ItemView {
|
||||
);
|
||||
}
|
||||
|
||||
// Auto-nudge for tool-capable modes if assistant didn't emit tools but seems to intend to
|
||||
const toolCapableModes: AgentMode[] = ['edit', 'organize', 'research'];
|
||||
if (
|
||||
toolCalls.length === 0 &&
|
||||
toolCapableModes.includes(this.currentAgentMode) &&
|
||||
fullResponse.trim().length > 0
|
||||
) {
|
||||
const intentPhrases = [
|
||||
'let me',
|
||||
'i will',
|
||||
'i need to',
|
||||
'search for',
|
||||
'find',
|
||||
'read',
|
||||
'explore',
|
||||
'look for',
|
||||
'check',
|
||||
'move',
|
||||
'rename',
|
||||
'create',
|
||||
];
|
||||
const lowerResponse = fullResponse.toLowerCase();
|
||||
const seemsToWantTools = intentPhrases.some((p) => lowerResponse.includes(p));
|
||||
if (seemsToWantTools) {
|
||||
const nudgeMessages: OllamaMessage[] = [
|
||||
...messagesWithMemory,
|
||||
{ role: 'assistant', content: fullResponse },
|
||||
{
|
||||
role: 'user',
|
||||
content:
|
||||
'You indicated you would take action but did not emit any tool_calls. Please emit the required tool_calls now. Do not output explanatory text.',
|
||||
},
|
||||
];
|
||||
const nudgeStream = activeClient.streamChat(nudgeMessages, tools);
|
||||
fullResponse = '';
|
||||
toolCalls = [];
|
||||
for await (const chunk of nudgeStream) {
|
||||
if (chunk.content) {
|
||||
fullResponse += chunk.content;
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
content: fullResponse,
|
||||
isStreaming: true,
|
||||
isThinking: false,
|
||||
});
|
||||
}
|
||||
if (chunk.tool_calls) {
|
||||
toolCalls = [...toolCalls, ...chunk.tool_calls];
|
||||
}
|
||||
}
|
||||
if (toolCalls.length > 0) {
|
||||
await this.processToolCalls(
|
||||
toolCalls,
|
||||
nudgeMessages,
|
||||
tools,
|
||||
fullResponse,
|
||||
assistantMessageId
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update assistant message immutably — only if no tool calls were processed
|
||||
if (toolCalls.length === 0) {
|
||||
this.updateMessageById(assistantMessageId, {
|
||||
|
||||
Reference in New Issue
Block a user