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.",
|
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.
|
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.
|
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.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
When editing notes:
|
When editing notes:
|
||||||
- Prefer modifying existing content over creating duplicates.
|
- Prefer modifying existing content over creating duplicates.
|
||||||
@@ -3196,9 +3196,8 @@ When editing notes:
|
|||||||
label: "Organize",
|
label: "Organize",
|
||||||
description: "Tag, rename, move, and link notes to keep the vault tidy.",
|
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.
|
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.
|
You can search notes, read them, 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.
|
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.
|
||||||
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.
|
|
||||||
Only respond to the user after you have received and analyzed the tool results.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
When organizing:
|
When organizing:
|
||||||
- Suggest consistent tag vocabularies.
|
- Suggest consistent tag vocabularies.
|
||||||
@@ -3214,8 +3213,7 @@ When organizing:
|
|||||||
description: "Deep vault search and synthesis across multiple notes.",
|
description: "Deep vault search and synthesis across multiple notes.",
|
||||||
systemPrompt: `You are a research assistant that dives deep into the user's Obsidian vault.
|
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.
|
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.
|
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.
|
||||||
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.
|
|
||||||
Only respond to the user after you have received and analyzed the tool results.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
Search broadly, read key sources, and cross-reference information.
|
Search broadly, read key sources, and cross-reference information.
|
||||||
Cite specific notes and quotes where possible.
|
Cite specific notes and quotes where possible.
|
||||||
@@ -11285,13 +11283,13 @@ var ChatView = class extends import_obsidian5.ItemView {
|
|||||||
type: "function",
|
type: "function",
|
||||||
function: {
|
function: {
|
||||||
name: "search_vault_files",
|
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: {
|
parameters: {
|
||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: {
|
query: {
|
||||||
type: "string",
|
type: "string",
|
||||||
description: "The search query to use"
|
description: "The search query to use (can be a keyword, tag, or phrase)"
|
||||||
},
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: "number",
|
type: "number",
|
||||||
@@ -11893,6 +11891,60 @@ ${actualMessage}` : actualMessage;
|
|||||||
assistantMessageId
|
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) {
|
if (toolCalls.length === 0) {
|
||||||
this.updateMessageById(assistantMessageId, {
|
this.updateMessageById(assistantMessageId, {
|
||||||
content: fullResponse,
|
content: fullResponse,
|
||||||
|
|||||||
+4
-6
@@ -86,7 +86,7 @@ Do not make up facts.`,
|
|||||||
description: 'Create, modify, and organize notes with full editing tools.',
|
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.
|
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.
|
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.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
When editing notes:
|
When editing notes:
|
||||||
- Prefer modifying existing content over creating duplicates.
|
- Prefer modifying existing content over creating duplicates.
|
||||||
@@ -103,9 +103,8 @@ When editing notes:
|
|||||||
label: 'Organize',
|
label: 'Organize',
|
||||||
description: 'Tag, rename, move, and link notes to keep the vault tidy.',
|
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.
|
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.
|
You can search notes, read them, 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.
|
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.
|
||||||
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.
|
|
||||||
Only respond to the user after you have received and analyzed the tool results.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
When organizing:
|
When organizing:
|
||||||
- Suggest consistent tag vocabularies.
|
- Suggest consistent tag vocabularies.
|
||||||
@@ -122,8 +121,7 @@ When organizing:
|
|||||||
description: 'Deep vault search and synthesis across multiple notes.',
|
description: 'Deep vault search and synthesis across multiple notes.',
|
||||||
systemPrompt: `You are a research assistant that dives deep into the user's Obsidian vault.
|
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.
|
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.
|
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.
|
||||||
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.
|
|
||||||
Only respond to the user after you have received and analyzed the tool results.
|
Only respond to the user after you have received and analyzed the tool results.
|
||||||
Search broadly, read key sources, and cross-reference information.
|
Search broadly, read key sources, and cross-reference information.
|
||||||
Cite specific notes and quotes where possible.
|
Cite specific notes and quotes where possible.
|
||||||
|
|||||||
+64
-2
@@ -522,13 +522,14 @@ export class ChatView extends ItemView {
|
|||||||
type: 'function',
|
type: 'function',
|
||||||
function: {
|
function: {
|
||||||
name: 'search_vault_files',
|
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: {
|
parameters: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
query: {
|
query: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'The search query to use',
|
description: 'The search query to use (can be a keyword, tag, or phrase)',
|
||||||
},
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: 'number',
|
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
|
// Update assistant message immutably — only if no tool calls were processed
|
||||||
if (toolCalls.length === 0) {
|
if (toolCalls.length === 0) {
|
||||||
this.updateMessageById(assistantMessageId, {
|
this.updateMessageById(assistantMessageId, {
|
||||||
|
|||||||
Reference in New Issue
Block a user