diff --git a/AIClasses/Claude/Claude.ts b/AIClasses/Claude/Claude.ts
index 9acc56a..4b4d427 100644
--- a/AIClasses/Claude/Claude.ts
+++ b/AIClasses/Claude/Claude.ts
@@ -175,12 +175,20 @@ export class Claude implements IAIClass {
if (isValidJson(content.functionCall)) {
try {
const parsedContent = JSON.parse(content.functionCall) as StoredFunctionCall;
- contentBlocks.push({
- type: "tool_use",
- id: parsedContent.functionCall.id,
- name: parsedContent.functionCall.name,
- input: parsedContent.functionCall.args
- });
+
+ if (parsedContent.functionCall.id && parsedContent.functionCall.id.trim() !== "") {
+ contentBlocks.push({
+ type: "tool_use",
+ id: parsedContent.functionCall.id,
+ name: parsedContent.functionCall.name,
+ input: parsedContent.functionCall.args
+ });
+ } else {
+ contentBlocks.push({
+ type: "text",
+ text: this.convertFunctionCallToText(parsedContent)
+ });
+ }
} catch (error) {
console.error("Failed to parse function call:", error);
// Fall back to treating as text
@@ -208,11 +216,19 @@ export class Claude implements IAIClass {
if (isValidJson(contentToExtract)) {
try {
const parsedContent = JSON.parse(contentToExtract) as StoredFunctionResponse;
- contentBlocks.push({
- type: "tool_result",
- tool_use_id: parsedContent.id,
- content: JSON.stringify(parsedContent.functionResponse.response)
- });
+
+ if (parsedContent.id && parsedContent.id.trim() !== "") {
+ contentBlocks.push({
+ type: "tool_result",
+ tool_use_id: parsedContent.id,
+ content: JSON.stringify(parsedContent.functionResponse.response)
+ });
+ } else {
+ contentBlocks.push({
+ type: "text",
+ text: this.convertFunctionResponseToText(parsedContent)
+ });
+ }
} catch (error) {
console.error("Failed to parse function response:", error);
contentBlocks.push({
@@ -248,4 +264,19 @@ export class Claude implements IAIClass {
}
}));
}
+
+ /*
+ If a conversation used another provider it may not have function id's required by Claude.
+ Instead provide the function call and response as plain text to preserve context without breaking.
+ */
+
+ private convertFunctionCallToText(parsedContent: StoredFunctionCall): string {
+ const inputJson = JSON.stringify(parsedContent.functionCall.args);
+ return `[Legacy Tool Call] ${parsedContent.functionCall.name}\nInput: ${inputJson}`;
+ }
+
+ private convertFunctionResponseToText(parsedContent: StoredFunctionResponse): string {
+ const resultJson = JSON.stringify(parsedContent.functionResponse.response);
+ return `[Legacy Tool Result] ${parsedContent.functionResponse.name}\nResult: ${resultJson}`;
+ }
}
diff --git a/AIClasses/SystemPrompt.ts b/AIClasses/SystemPrompt.ts
index b522d9f..9a92bb1 100644
--- a/AIClasses/SystemPrompt.ts
+++ b/AIClasses/SystemPrompt.ts
@@ -26,6 +26,34 @@ Examples:
**The cost of an unnecessary search is negligible. Missing relevant information is costly.**
+**Regex Pattern Matching - POWERFUL PRIMARY TOOL**
+Regex is your most versatile search capability. Use it aggressively and creatively:
+
+
+- **Case-insensitive partial matching**: \`/maui/i\` finds MAUI, Maui, maui anywhere
+- **Word boundary patterns**: \`/\bmaui\b/i\` matches whole words only
+- **Prefix/suffix patterns**: \`/maui.*dev/i\` or \`/.*mobile.*app.*/i\`
+- **Alternative spellings**: \`/gr(a|e)y/i\` matches gray or grey
+- **Optional characters**: \`/dockers?/i\` matches docker or dockers
+- **Wildcard sequences**: \`/proj.*alpha/i\` matches "project alpha", "proj_alpha", etc.
+- **Multiple alternatives**: \`/(kubernetes|k8s|kube)/i\` catches all variations
+- **Character classes**: \`/[Dd]ocker/\` for case variations
+- **Numeric patterns**: \`/vd+.d+/\` for version numbers like v1.2
+
+
+When to deploy regex (use frequently):
+1. **Initial search fails** → Immediately try regex pattern
+2. **Abbreviations likely** → Search both full term and abbreviated pattern
+3. **Multiple spellings** → Use alternation patterns
+4. **Partial name known** → Use wildcard matching
+5. **Version/date references** → Use numeric patterns
+6. **Technical terms** → Search with common abbreviations
+
+Example workflow:
+- Search "kubernetes" fails → Try \`/k8s|kubernetes|kube/i\`
+- Search "Docker" fails → Try \`/docker.*/i\` to catch "Docker-compose", "Dockerfile"
+- Search "Project Alpha" fails → Try \`/proj.*alpha/i\` for flexible matching
+
#### IMMEDIATE VAULT SEARCH Required When:
- Query contains definite articles suggesting specific reference ("the project", "the prices", "the data")
- Query uses possessive pronouns ("my ideas", "our plans", "my notes about")
@@ -48,6 +76,8 @@ Acknowledge the search, then provide general assistance:
**NEVER accept a failed search as final. Always try multiple approaches before concluding information doesn't exist.**
+#### Multi-Tier Search Approach
+
When searching the vault, use a progressive strategy that automatically escalates:
**Tier 1: Entity Extraction & Broad Search**
@@ -74,44 +104,73 @@ When searching the vault, use a progressive strategy that automatically escalate
## Multi-Tool Workflow Architecture
-### Planning Phase (for complex queries)
-Establish a clear execution strategy:
+### Planning Phase (Essential for Complex Queries)
-1. **Intent Analysis**: Determine query scope and required information depth
-2. **Tool Selection**: Identify which search approaches are needed
-3. **Search Strategy Design**: Plan progressive search tiers and fallbacks
-4. **Execution Order**: Sequence operations for optimal information gathering
+Modern agentic AI systems succeed through orchestrated multi-step workflows where tasks are decomposed into subgoals, with each step building on the previous one. Before executing any complex query:
+
+1. **Intent Analysis**: Determine scope, depth, and complexity level
+2. **Query Decomposition**: Break into searchable components
+3. **Strategy Design**: Plan search progression (entity → regex → domain → relationships)
+4. **Tool Selection**: Identify which searches need regex, which need domain expansion
+5. **Execution Sequence**: Order operations for optimal information flow
+6. **Success Criteria**: Define what "complete" looks like
+
+**Key Principle**: Agents that plan multi-step workflows autonomously before executing outperform those using single-step approaches.
### Execution Phase
-Execute with adaptive intelligence:
-1. **Initial Broad Search**: Start with core entities extracted from query
-2. **Progressive Refinement**: Apply Tier 1 → Tier 2 → Tier 3 → Tier 4 as needed
-3. **Dynamic Evaluation**: After each result, reason about next action
-4. **Cross-Reference**: Look for connections between different information sources
+Execute systematically with adaptive intelligence:
+
+1. **Entity Extraction**: Extract core entities, remove query noise
+2. **Initial Search**: Broad search with clean entities
+3. **Regex Deployment**: If initial search weak, immediately apply regex patterns
+4. **Domain Expansion**: Apply knowledge for related concepts (search with regex alternations)
+5. **Relationship Inference**: Read found content, infer connections
+6. **Cross-Reference**: Link findings, identify patterns
+7. **Adaptive Strategy**: Evaluate after each step, adjust approach as needed
+
+
+**Regex Usage Throughout Execution:**
+- After any failed exact match → Deploy regex pattern immediately
+- When searching tech terms → Include abbreviation patterns from start
+- For people/project names → Use flexible matching patterns
+- With version numbers → Use numeric patterns
+- When multiple spellings possible → Use alternation patterns
+
+Example execution with regex:
+1. Search "docker" → Limited results
+2. Immediately search \`/docker.*/i\` → Finds "Docker-compose", "Dockerfile", "docker-notes"
+3. Search \`/container|docker|k8s/i\` → Domain expansion with regex
+4. Success: Comprehensive results through regex flexibility
+
### Synthesis Phase
-Aggregate findings and construct response:
+
+Integrate all findings into cohesive response:
1. **Information Integration**: Combine results from all search attempts
-2. **Relationship Mapping**: Identify connections between different sources
-3. **Wiki-Link Application**: Link ALL vault references in final response
-4. **Gap Identification**: Suggest missing connections or new notes when appropriate
+2. **Relationship Mapping**: Identify connections between sources
+3. **Universal Wiki-Linking**: Apply [[wiki-links]] to ALL vault references
+4. **Gap Identification**: Note missing connections or suggest new notes
+5. **Structured Response**: Present findings clearly with proper [[wiki-links]]
-### Workflow Scaling Guidelines
-**Simple queries** (1 search): Direct factual lookups with clear, single source
-**Moderate queries** (2-4 searches): Comparisons, validations, or multi-source synthesis
-**Complex queries** (5-10 searches): Comprehensive research requiring multiple angles
-**Deep research** (10+ searches): Extensive cross-domain synthesis with relationship mapping
+### Workflow Scaling by Complexity
-## Query Decomposition Strategy
+**Simple (1-3 operations)**: Direct lookup + optional regex
+- "What did I write about React?"
+- Entity extraction → Search → Done
-Transform complex queries into actionable search components:
-- "Who is X's Y?" → Search X first, infer Y from context in found content
-- "Compare X and Y" → Search X, search Y, then synthesize findings
-- "What did I learn about X?" → Search X + related tags + check backlinks
+**Moderate (4-7 operations)**: Multiple searches with regex and domain expansion
+- "Find all my notes about Docker and Kubernetes"
+- Search "docker" → Regex \`/docker.*/i\` → Domain search "container" → Regex \`/k8s|kubernetes/i\` → Cross-reference
-**Critical**: Extract key entities and search broadly first. Never search exact literal phrases.
+**Complex (8-15 operations)**: Full multi-step planning with progressive strategy
+- "Compare my approaches to microservices vs monoliths and relate to current projects"
+- Plan: 5-step strategy → Execute: Search microservices (regex) → Search monoliths (regex) → Search projects (directory) → Read each → Infer relationships → Synthesize
+
+**Research-Grade (15+ operations)**: Comprehensive analysis across vault
+- "Create a comprehensive overview of my learning journey in machine learning"
+- Full planning framework → Systematic search across tags, dates, topics → Regex patterns for all variations → Deep synthesis with temporal analysis
## Core Capabilities
diff --git a/Enums/Copy.ts b/Enums/Copy.ts
index 52e37b4..8d69cd8 100644
--- a/Enums/Copy.ts
+++ b/Enums/Copy.ts
@@ -199,6 +199,9 @@ Each AI provider has their own data policies:
- [Google (Gemini)](https://policies.google.com/privacy)
- [OpenAI (ChatGPT)](https://openai.com/privacy/)`,
+ // Conversation Modal Copy
+ NoConversationsFound = "No conversations match your search.",
+
// Help Modal Additional Copy
HelpModalCloseAriaLabel = "Close Help Modal",
PluginVersionPrefix = "Plugin version: ",
diff --git a/Modals/ConversationHistoryModal.ts b/Modals/ConversationHistoryModal.ts
index 0033cd5..715d0cd 100644
--- a/Modals/ConversationHistoryModal.ts
+++ b/Modals/ConversationHistoryModal.ts
@@ -37,31 +37,27 @@ export class ConversationHistoryModal extends Modal {
super(plugin.app);
}
- private async loadConversations() {
+ onOpen() {
+ void this.initializeContent();
+ }
+
+ private async initializeContent() {
this.conversations = await this.conversationFileSystemService.getAllConversations();
this.items = this.conversations
- .sort((a, b) => b.updated.getTime() - a.updated.getTime())
- .map((conversation) => {
- const filePath = this.conversationFileSystemService.generateConversationPath(conversation);
- return {
- id: filePath,
- date: dateToString(conversation.created, false),
- updated: conversation.updated,
- title: conversation.title,
- selected: false,
- filePath: filePath
- };
- });
+ .sort((a, b) => b.updated.getTime() - a.updated.getTime())
+ .map((conversation) => {
+ const filePath = this.conversationFileSystemService.generateConversationPath(conversation);
+ return {
+ id: filePath,
+ date: dateToString(conversation.created, false),
+ updated: conversation.updated,
+ title: conversation.title,
+ selected: false,
+ filePath: filePath
+ };
+ });
- // Update the component with loaded items if it's already mounted
- if (this.component) {
- this.component.items = this.items;
- }
- }
-
- onOpen() {
- void this.loadConversations();
const { contentEl, modalEl, containerEl } = this;
containerEl.addClass(Selector.ConversationHistoryModal);
diff --git a/Modals/ConversationHistoryModalSvelte.svelte b/Modals/ConversationHistoryModalSvelte.svelte
index 305b72a..5f45492 100644
--- a/Modals/ConversationHistoryModalSvelte.svelte
+++ b/Modals/ConversationHistoryModalSvelte.svelte
@@ -1,4 +1,5 @@