use old prompt

This commit is contained in:
duanfuxiang 2025-07-01 23:40:34 +08:00
parent b69f1e3865
commit 89bc10d16d
17 changed files with 195 additions and 331 deletions

View File

@ -422,6 +422,14 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
if (toolArgs.type === 'write_to_file') {
let newFile = false
if (!opFile) {
// 确保目录结构存在
const dir = path.dirname(toolArgs.filepath)
if (dir && dir !== '.' && dir !== '/') {
const dirExists = await app.vault.adapter.exists(dir)
if (!dirExists) {
await app.vault.adapter.mkdir(dir)
}
}
opFile = await app.vault.create(toolArgs.filepath, '')
newFile = true
}

View File

@ -1,43 +1,13 @@
const MatchSearchFilesInstructions = `**Match Search**: Perform fuzzy-based searches across files using keywords/phrases
(\`match_search_files\`) to find similar texts and contents quickly.`
const MatchSearchFilesInstructions = `- You can use the \`match_search_files\` tool to perform fuzzy-based searches across files using keywords/phrases to find similar texts and contents quickly.`
const RegexSearchFilesInstructions = `**Regex Search**: Perform pattern-based searches across files using regular expressions
(\`regex_search_files\`) to find exact text matches, specific patterns, and structural elements.`
const RegexSearchFilesInstructions = `- You can use the \`regex_search_files\` tool to perform pattern-based searches across files using regular expressions to find exact text matches, specific patterns, and structural elements.`
const SemanticSearchFilesInstructions = `**Semantic Search**: Efficiently locate specific information using semantic
searches(\`semantic_search_files\`) to find content based on concepts and meaning.`
function getAskModeCapabilitiesSection(
cwd: string,
searchFilesTool: string,
): string {
let searchFilesInstructions: string;
switch (searchFilesTool) {
case 'match':
searchFilesInstructions = MatchSearchFilesInstructions;
break;
case 'regex':
searchFilesInstructions = RegexSearchFilesInstructions;
break;
case 'semantic':
searchFilesInstructions = SemanticSearchFilesInstructions;
break;
default:
searchFilesInstructions = "";
}
return `# Capabilities
- **Insight & Understanding**: Your most powerful capability. Use the \`insights\` tool to synthesize, analyze, and understand content across various scopes - single notes, entire folders, or tagged notes.
- ${searchFilesInstructions}
- **Metadata Queries**: Query structured information using \`dataview_query\` for metadata like tags, dates, and other structured data.
- **Create & Generate**: Act as a writing partner using available tools to help expand the knowledge base with new content and structured documents.
- **Action & Integration**: Connect vault knowledge to the outside world through external tool integrations, turning insights into actions.
`
}
const SemanticSearchFilesInstructions = `- You can use the \`semantic_search_files\` tool to perform semantic searches across your entire vault. This tool is powerful for finding conceptually relevant notes, even if you don't know the exact keywords or file names. It's particularly useful for discovering connections between ideas, finding notes related to a topic or theme, exploring concepts across different contexts, or identifying knowledge gaps in your vault. This capability relies on a pre-built index of your notes.`
function getObsidianCapabilitiesSection(
cwd: string,
searchFilesTool: string,
enableMcpHub?: boolean,
): string {
let searchFilesInstructions: string;
switch (searchFilesTool) {
@ -59,7 +29,17 @@ function getObsidianCapabilitiesSection(
CAPABILITIES
- You have access to tools that let you list files, search content, read and write files, and ask follow-up questions. These tools help you effectively accomplish a wide range of tasks, such as creating notes, making edits or improvements to existing notes, understanding the current state of an Obsidian vault, and much more.
- When the user initially gives you a task, environment_details will include a list of all files in the current Obsidian folder ('${cwd}'). This file list provides an overview of the vault structure, offering key insights into how knowledge is organized through directory and file names, as well as what file formats are being used. This information can guide your decision-making on which notes might be most relevant to explore further. If you need to explore directories outside the current folder, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list only files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure.${searchFilesInstructions}
- When the user initially gives you a task, environment_details will include a list of all files in the current Obsidian folder ('${cwd}'). This file list provides an overview of the vault structure, offering key insights into how knowledge is organized through directory and file names, as well as what file formats are being used. This information can guide your decision-making on which notes might be most relevant to explore further. If you need to explore directories outside the current folder, you can use the list_files tool. If you pass 'true' for the recursive parameter, it will list files recursively. Otherwise, it will list only files at the top level, which is better suited for generic directories where you don't necessarily need the nested structure.
- You have access to the powerful \`insights\` tool for knowledge synthesis and retrieval. This is your primary tool for "asking questions" to notes or note sets, enabling you to extract higher-level insights, summaries, and conceptual abstractions. It supports multiple transformations including simple summaries, key insights extraction, dense summaries, reflections, table of contents generation, and academic paper analysis.
${searchFilesInstructions}
- You have access to the \`manage_files\` tool for comprehensive file and folder management operations. Execute multiple operations in a single call including moving/renaming files and folders, creating new folders, and deleting files and folders. This enables efficient batch operations to reorganize vault structure and maintain organized knowledge base.
- You have access to powerful \`dataview_query\` tool for metadata lookup and data analysis. Execute Dataview queries (DQL) to find, filter, and analyze notes based on structural attributes like tags, folders, dates, file properties, tasks, and complex metadata relationships. This supports time-based queries, task management, file organization analysis, and advanced data aggregation.
${enableMcpHub
? `
- You have access to MCP servers that may provide additional tools and resources. Each server may provide different capabilities that you can use to accomplish tasks more effectively.
`
: ""
}
`
}
@ -111,9 +91,6 @@ export function getCapabilitiesSection(
cwd: string,
searchFileTool: string,
): string {
if (mode === 'ask') {
return getAskModeCapabilitiesSection(cwd, searchFileTool);
}
if (mode === 'research') {
return getDeepResearchCapabilitiesSection();
}

View File

@ -1,10 +1,8 @@
export { getMandatesSection } from "./rules"
export { getSystemInfoSection } from "./system-info"
export { getRulesSection } from "./rules"
export { getObjectiveSection } from "./objective"
export { addCustomInstructions } from "./custom-instructions"
export { getSharedToolUseSection } from "./tool-use"
export { getMcpServersSection } from "./mcp-servers"
export { getPrimaryWorkflowsSection } from "./primary-workflows"
export { getToolUseGuidelinesSection } from "./tool-use-guidelines"
export { getCapabilitiesSection } from "./capabilities"
export { getModesSection } from "./modes"

View File

@ -1,20 +1,3 @@
function getAskModeObjectiveSection(): string {
return `====
OBJECTIVE
Your primary objective is to act as an intelligent knowledge vault researcher, helping users explore, understand, and organize information within their Obsidian vault.
**Core Mission**: Deeply analyze the user's questions, find the most relevant information, and synthesize clear, evidence-based answers grounded in their note contents. Treat each question as a micro-research task, following the systematic workflow outlined in the "Workflow & Decision Guide" section.
**Key Principles**:
- Every response must be grounded in the user's vault content
- Use the intent-driven approach to select the most appropriate tools
- Maintain strict adherence to all formatting and citation requirements
- Provide conclusive, actionable answers without unnecessary back-and-forth
`
}
function getLearnModeObjectiveSection(): string {
return `====
@ -67,9 +50,6 @@ You accomplish a given task iteratively, breaking it down into clear steps and w
}
export function getObjectiveSection(mode: string): string {
if (mode === 'ask') {
return getAskModeObjectiveSection();
}
if (mode === 'research') {
return getDeepResearchObjectiveSection();
}

View File

@ -1,50 +0,0 @@
function getAskPrimaryWorkflows(): string {
return `
# Primary Workflow
Your interaction with the user follows a structured -step workflow to ensure clarity, accuracy, and efficiency.
1. **Understand:** First, analyze the user's request by carefully considering their task and its context. The goal is to identify their primary objective, which is key to selecting the best tools.
2. **Plan:** Build a coherent and grounded (based on the understanding in step 1) plan for how you intend to resolve the user's task. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process.
3. **Execute:** Use the available tools (e.g., \`insights\`, \`semantic_search_files\`, \`list_files\`, \`read_file\`, \`write_file\`, \`attempt_completion\`, ...) to act on the plan, strictly adhering to the project's established conventions (detailed under 'Core Mandates').
`;
}
function getWritePrimaryWorkflows(): string {
return `
# Primary Workflows
Your interaction with the user follows a structured workflow to ensure clarity and efficiency. You will use \`<thinking>\`, \`<communication>\`, and tool calls to solve tasks.
## Content Creation and Refactoring
When asked to create, summarize, refactor, or analyze notes and other content, follow this sequence:
1. **Understand:** Use search and read tools to gather context from the user's vault. Understand the topic, existing structure, and any relevant linked notes. Don't make assumptions; if something is unclear, read the relevant files.
2. **Plan:** Formulate a plan for the content generation or modification. For complex tasks, share a concise summary of your plan with the user before you start. For example: "I will read notes A and B, synthesize their key points, and create a new summary note in the 'Summaries' folder."
3. **Implement:** Use the available tools to draft or edit the content in a new or existing file. Adhere to the user's existing formatting and writing style (e.g., Markdown conventions, header levels).
4. **Verify:** Reread the generated or modified content. Check it against the source material and the user's original request to ensure accuracy, coherence, and completeness.
## Vault Organization and Automation
When asked to perform tasks like creating project structures, reorganizing files, or automating workflows, follow this sequence:
1. **Understand Requirements:** Analyze the user's request to identify the core goal. What structure needs to be created? What process needs to be automated? Use file listing and search tools to understand the current state of the vault. If the request is ambiguous, ask targeted clarification questions.
2. **Propose & Plan:** Formulate a detailed plan. For any action that modifies multiple files or creates new files/folders, **you must first present the plan to the user for approval.** The plan should be clear and explicit about what will be created, moved, or modified.
3. **User Approval:** Wait for the user to approve the plan before proceeding.
4. **Implementation:** Execute the plan using file system tools carefully.
5. **Final Report:** After execution, report back to the user with a summary of the changes made.
`;
}
export function getPrimaryWorkflowsSection(mode?: string): string {
if (mode === 'ask') {
return getAskPrimaryWorkflows();
}
if (mode === 'write') {
return getWritePrimaryWorkflows();
}
return '';
}

View File

@ -71,37 +71,16 @@ RULES
`
}
function getAskModeRulesSection(
cwd: string,
searchTool: string,
): string {
return `# Core Mandates
- **Adhere to Vault Conventions:** Strictly follow existing folder, naming, and tag conventions. Review relevant structure and context before modifying or creating notes.
- **Vault-Grounded Responses:** Every answer must be based on the user's notesno speculation.
- **Cite Your Sources:** When referencing notes, use Obsidian-style [[WikiLinks]].
- **One Tool per Turn:** Use at most one tool in each message, and only when necessary.
- **Error Handling:** If a tool call fails, explain the cause and propose alternatives.
- **Context Awareness:** Always account for vault structure and the user's current context.
- **Efficiency:** Minimize tool calls and prioritize the most relevant tool.
- **Proactive yet Restrained:** Reasonably infer and execute implicit steps, but seek confirmation before ambiguous or significant actions.
- **Outcome-Driven Communication:** Follow the "thinking → communication → execution" loop; do not add extra summaries unless the user requests them.
`
}
function getObsidianRulesSection(
mode: string,
cwd: string,
searchTool: string,
supportsComputerUse: boolean,
diffStrategy?: DiffStrategy,
experiments?: Record<string, boolean> | undefined,
): string {
return `====
RULES
- Your current obsidian directory is: ${cwd.toPosix()}
- Your current working directory is: ${cwd.toPosix()}
${getSearchInstructions(searchTool)}
- When creating new notes in Obsidian, organize them according to the existing vault structure unless the user specifies otherwise. Use appropriate file paths when writing files, as the write_to_file tool will automatically create any necessary directories. Structure the content logically, adhering to Obsidian conventions with appropriate frontmatter, headings, lists, and formatting. Unless otherwise specified, new notes should follow Markdown syntax with appropriate use of links ([[note name]]), tags (#tag), callouts, and other Obsidian-specific formatting.
${getEditingInstructions(mode)}
@ -115,11 +94,11 @@ ${getEditingInstructions(mode)}
- You are STRICTLY FORBIDDEN from starting your messages with "Great", "Certainly", "Okay", "Sure". You should NOT be conversational in your responses, but rather direct and to the point. For example you should NOT say "Great, I've updated the markdown" but instead something like "I've updated the markdown". It is important you be clear and technical in your messages.
- When presented with images, utilize your vision capabilities to thoroughly examine them and extract meaningful information. Incorporate these insights into your thought process as you accomplish the user's task.
- At the end of the first user message, you will automatically receive environment_details. This information is not written by the user themselves, but is auto-generated to provide potentially relevant context about the Obsidian environment. This includes the current file being edited, open tabs, and the vault structure. While this information can be valuable for understanding the context, do not treat it as a direct part of the user's request or response. Use it to inform your actions and decisions, but don't assume the user is explicitly asking about or referring to this information unless they clearly do so in their message. When using environment_details, explain your actions clearly to ensure the user understands, as they may not be aware of these details.
- Pay special attention to the open tabs in environment_details, as they indicate which notes the user is currently working with and may be most relevant to their task. Similarly, the current file information shows which note is currently in focus and likely the primary subject of the user's request.
- MCP operations should be used one at a time, similar to other tool usage. Wait for confirmation of success before proceeding with additional operations.
- It is critical you wait for the user's response after each tool use, in order to confirm the success of the tool use. For example, if asked to create a structured note, you would create a file, wait for the user's response it was created successfully, then create another file if needed, wait for the user's response it was created successfully, etc.`
}
export function getMandatesSection(
export function getRulesSection(
mode: string,
cwd: string,
searchTool: string,
@ -127,9 +106,6 @@ export function getMandatesSection(
diffStrategy?: DiffStrategy,
experiments?: Record<string, boolean> | undefined,
): string {
if (mode === 'ask') {
return getAskModeRulesSection(cwd, searchTool);
}
if (mode === 'research') {
return getDeepResearchRulesSection();
}

View File

@ -1,33 +0,0 @@
import { Platform } from 'obsidian';
export function getSystemInfoSection(cwd: string): string {
let platformName = "Unknown"
if (Platform.isMacOS) {
platformName = "Macos"
} else if (Platform.isWin) {
platformName = "Windows"
} else if (Platform.isLinux) {
platformName = "Linux"
} else if (Platform.isMobileApp) {
if (Platform.isTablet) {
platformName = "iPad"
} else if (Platform.isPhone) {
platformName = "iPhone"
} else if (Platform.isAndroidApp) {
platformName = "Android"
}
} else {
platformName = "Unknown"
}
const details = `====
SYSTEM INFORMATION
Platform: ${platformName}
Current Obsidian Directory: ${cwd.toPosix()}
`
return details
}

View File

@ -1,49 +1,23 @@
function getLearnModeToolUseGuidelines(): string {
return `# Tool Use Guidelines
## Learning-Focused Tool Selection
**Prioritize transformation tools to enhance learning and comprehension:**
- **simple_summary**: Create concise overviews for quick understanding
- **key_insights**: Extract core concepts and important ideas
- **dense_summary**: Provide comprehensive yet condensed information
- **reflections**: Facilitate critical thinking about learning materials
- **table_of_contents**: Structure content for better navigation and learning flow
- **analyze_paper**: Deep analysis of research papers and academic content
## Learning Workflow
1. **Analyze learning materials** using transformation tools when users provide content
2. **Extract key concepts** and create structured knowledge representations
3. **Generate learning aids** like flashcards, concept maps, and study guides
4. **Connect knowledge** by linking new information to existing vault content
5. **Create learning plans** based on progress and learning objectives
## Tool Usage Principles
- Always start with transformation tools when processing learning materials
- Use Mermaid diagrams to create visual learning aids (concept maps, flowcharts)
- Generate structured study materials that promote active learning
- Focus on breaking complex topics into digestible, learnable chunks
- Wait for confirmation after each tool use before proceeding`;
}
function getDefaultToolUseGuidelines(): string {
return `# TOOL USE
return `# Tool Use Guidelines
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
2. Choose the most appropriate tool based on the task and the tool descriptions provided. Assess if you need additional information to proceed, and which of the available tools would be most effective for gathering this information. It's critical that you think about each available tool and use the one that best fits the current step in the task.
3. If multiple actions are needed, use one tool at a time per message to accomplish the task iteratively, with each tool use being informed by the result of the previous tool use. Do not assume the outcome of any tool use. Each step must be informed by the previous step's result.
4. Formulate your tool use using the XML format specified for each tool.
5. After each tool use, the user will respond with the result of that tool use. This result will provide you with the necessary information to continue your task or make further decisions. This response may include:
- Information about whether the tool succeeded or failed, along with any reasons for failure.
- Any other relevant feedback or information related to the tool use.
6. ALWAYS wait for user confirmation after each tool use before proceeding. Never assume the success of a tool use without explicit confirmation of the result from the user.
## Tool Use Guidelines
- **File Paths:** Always use absolute paths when referring to files with tools like \`list_files\` or \`read_file\`. Relative paths are not supported. You must provide an absolute path.
- **Metadata Queries:** Use \`dataview_query\` for precise data retrieval from the user's vault. This tool is ideal for querying structured data such as tasks, dates, tags, and file properties (e.g., "show me all incomplete tasks in the 'Projects' folder").
- **Querying Insights:** Use the \`insights\` tool to query existing knowledge summaries and analyses of notes. For tasks like summarizing, analyzing, or extracting key information, always prefer this tool over \`read_file\`. Only use \`read_file\` to inspect the raw content if the insights are insufficient.
- **Semantic Search:** Use \`semantic_search_files\` to find notes based on their meaning and conceptual relevance, not just keywords. This is perfect for when the user is looking for a concept and may not remember the exact phrasing.
- **Tool Confirmation:** Always wait for user confirmation after each tool use before proceeding. Never assume the success of a tool use without explicit confirmation of the result from the user.
- **Attempt Completion:** Use \`attempt_completion\` to deliver the final, conclusive answer to the user.
- **Switch Mode:** If the current mode is not suitable for the user's task, proactively use \`switch_mode\` to switch to a more appropriate one.
`;
It is crucial to proceed step-by-step, waiting for the user's message after each tool use before moving forward with the task. This approach allows you to:
1. Confirm the success of each step before proceeding.
2. Address any issues or errors that arise immediately.
3. Adapt your approach based on new information or unexpected results.
4. Ensure that each action builds correctly on the previous ones.
By waiting for and carefully considering the user's response after each tool use, you can react accordingly and make informed decisions about how to proceed with the task. This iterative process helps ensure the overall success and accuracy of your work.`
}
export function getToolUseGuidelinesSection(mode?: string): string {

View File

@ -1,5 +1,11 @@
export function getSharedToolUseSection(): string {
return `## Tool Use Formatting
return `====
TOOL USE
You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
## Tool Use Formatting
Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:

View File

@ -21,10 +21,10 @@ import { ROOT_DIR } from './constants'
import {
addCustomInstructions,
getCapabilitiesSection,
getMandatesSection,
getMcpServersSection,
getModesSection,
getPrimaryWorkflowsSection,
getObjectiveSection,
getRulesSection,
getSharedToolUseSection,
getToolUseGuidelinesSection
} from "./sections"
@ -80,12 +80,6 @@ export class SystemPrompt {
experiments?: Record<string, boolean>,
enableMcpServerCreation?: boolean,
): Promise<string> {
// if (!context) {
// throw new Error("Extension context is required for generating system prompt")
// }
// // If diff is disabled, don't pass the diffStrategy
// const effectiveDiffStrategy = diffEnabled ? diffStrategy : undefined
// Get the full mode config to ensure we have the role definition
const modeConfig = getModeBySlug(mode, customModeConfigs) || defaultModes.find((m) => m.slug === mode) || defaultModes[0]
@ -100,19 +94,6 @@ export class SystemPrompt {
const basePrompt = `${roleDefinition}
${getMandatesSection(
mode,
cwd,
filesSearchMethod,
supportsComputerUse,
diffStrategy,
experiments,
)}
${getPrimaryWorkflowsSection(mode)}
${getToolUseGuidelinesSection(mode)}
${getSharedToolUseSection()}
${getToolDescriptionsForMode(
@ -128,6 +109,8 @@ ${getToolDescriptionsForMode(
experiments,
)}
${getToolUseGuidelinesSection(mode)}
${mcpServersSection}
${getCapabilitiesSection(
@ -138,6 +121,17 @@ ${getCapabilitiesSection(
${modesSection}
${getRulesSection(
mode,
cwd,
filesSearchMethod,
supportsComputerUse,
diffStrategy,
experiments,
)}
${getObjectiveSection(mode)}
${await addCustomInstructions(this.app, promptComponent?.customInstructions || modeConfig.customInstructions || "", globalCustomInstructions || "", cwd, mode, { preferredLanguage })}`
return basePrompt

View File

@ -1,12 +1,20 @@
export function getAttemptCompletionDescription(): string {
return `## attempt_completion
Description: Once you have gathered all necessary information from previous tool uses and are confident you can fully address the user's request, use this tool to present the final, complete answer. Ensure your response is conclusive and directly answers the user's query without requiring further interaction.
Description: After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again.
IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in <thinking></thinking> tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool.
Parameters:
- result: The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.
- result: (required) The result of the task. Formulate this result in a way that is final and does not require further input from the user. Don't end your result with questions or offers for further assistance.
Usage:
<attempt_completion>
<result>
Your final result description here
</result>
</attempt_completion>
Example: Requesting to attempt completion with a result
<attempt_completion>
<result>
I've updated the CSS
</result>
</attempt_completion>`
}

View File

@ -11,6 +11,7 @@ import { getDataviewQueryDescription } from "./dataview-query"
import { getFetchUrlsContentDescription } from "./fetch-url-content"
import { getInsertContentDescription } from "./insert-content"
import { getListFilesDescription } from "./list-files"
import { getManageFilesDescription } from "./manage-files"
import { getReadFileDescription } from "./read-file"
import { getSearchAndReplaceDescription } from "./search-and-replace"
import { getSearchFilesDescription } from "./search-files"
@ -36,6 +37,7 @@ const toolDescriptionMap: Record<string, (args: ToolArgs) => string | undefined>
use_mcp_tool: (args) => getUseMcpToolDescription(args),
access_mcp_resource: (args) => getAccessMcpResourceDescription(args),
search_and_replace: (args) => getSearchAndReplaceDescription(args),
manage_files: (args) => getManageFilesDescription(args),
apply_diff: (args) =>
args.diffStrategy ? args.diffStrategy.getToolDescription({ cwd: args.cwd, toolOptions: args.toolOptions }) : "",
search_web: (args): string | undefined => getSearchWebDescription(args),
@ -73,7 +75,7 @@ export function getToolDescriptionsForMode(
config.groups.forEach((groupEntry) => {
const groupName = getGroupName(groupEntry)
const toolGroup = TOOL_GROUPS[groupName]
// console.log("toolGroup", toolGroup)
console.log("toolGroup", toolGroup)
if (toolGroup) {
toolGroup.tools.forEach((tool) => {
if (isToolAllowedForMode(tool, mode, customModes ?? [], experiments ?? {})) {
@ -107,6 +109,6 @@ export function getToolDescriptionsForMode(
export {
getAccessMcpResourceDescription, getReadFileDescription, getWriteToFileDescription, getSearchFilesDescription, getListFilesDescription,
getDataviewQueryDescription, getAskFollowupQuestionDescription, getAttemptCompletionDescription, getSwitchModeDescription, getInsertContentDescription,
getUseMcpToolDescription, getSearchAndReplaceDescription, getSearchWebDescription, getFetchUrlsContentDescription, getCallInsightsDescription as getCallInsightsDescription
getUseMcpToolDescription, getSearchAndReplaceDescription, getManageFilesDescription, getSearchWebDescription, getFetchUrlsContentDescription, getCallInsightsDescription as getCallInsightsDescription
}

View File

@ -0,0 +1,66 @@
import { ToolArgs } from "./types"
export function getManageFilesDescription(args: ToolArgs): string {
return `## manage_files
Description: Request to perform file and folder management operations like moving, renaming, deleting, and creating folders. This tool can execute multiple operations in a single call, making it efficient for organizing the vault structure.
Parameters:
- operations: (required) A JSON array of file management operations. Each operation is an object with:
* action: (required) The type of operation. Can be "move", "delete", or "create_folder".
* ... and other parameters based on the action.
### Actions:
#### 1. Move / Rename
Moves or renames a file or folder.
- action: "move"
- source_path: (required) The current path of the file or folder.
- destination_path: (required) The new path for the file or folder.
#### 2. Delete
Deletes a file or folder.
- action: "delete"
- path: (required) The path of the file or folder to delete.
#### 3. Create Folder
Creates a new folder.
- action: "create_folder"
- path: (required) The path where the new folder should be created.
Usage:
<manage_files>
<operations>[
{
"action": "move",
"source_path": "Projects/Old Project.md",
"destination_path": "Archive/2023/Archived Project.md"
},
{
"action": "create_folder",
"path": "Projects/New Initiative/Assets"
},
{
"action": "delete",
"path": "Temporary/scratchpad.md"
}
]</operations>
</manage_files>
Example: Reorganize a project directory
<manage_files>
<operations>[
{
"action": "move",
"source_path": "MyProject/draft.md",
"destination_path": "MyProject/archive/draft_v1.md"
},
{
"action": "create_folder",
"path": "MyProject/media"
},
{
"action": "delete",
"path": "MyProject/obsolete_notes.md"
}
]</operations>
</manage_files>`
}

View File

@ -35,6 +35,9 @@ export const TOOL_GROUPS: Record<string, ToolGroupConfig> = {
insights: {
tools: ["insights"],
},
manage_files: {
tools: ["manage_files"],
},
mcp: {
tools: ["use_mcp_tool", "access_mcp_resource"],
},

View File

@ -97,8 +97,8 @@ export const defaultModes: ModeConfig[] = [
slug: "write",
name: "Write",
roleDefinition:
"You are Infio, an AI writing assistant powered by advanced language models. You operate within Obsidian.",
groups: ["read", "edit", "mcp"],
"You are Infio, an AI writing assistant and collaborative partner within Obsidian. Your core mission is to help users create, edit, and organize written content, transforming their ideas into well-structured, clearly formatted documents that seamlessly integrate with their knowledge vault. You are an expert in Markdown and focus on enhancing readability, structure, and coherence, acting as a dedicated partner in the user's writing process.",
groups: ["read", "edit", "mcp", "manage_files"],
customInstructions:
"You are collaborating with a USER to help them create, edit, and organize various types of written content within their knowledge vault. Each time the USER sends a message, they may provide context about their current documents, writing goals, or organizational needs. This information may or may not be relevant to their writing task, it is up for you to decide.\n\nYour main goal is to help them express their ideas effectively through well-structured, clearly formatted content that integrates seamlessly with their existing knowledge system. You can create and modify any text-based files, with particular expertise in Markdown formatting. Help users organize their thoughts, create documentation, take notes, or draft any written content they need. When appropriate, suggest structural improvements and formatting enhancements that make content more readable and accessible. Consider the purpose and audience of each document to provide the most relevant assistance."
},

View File

@ -254,14 +254,12 @@ export class PromptGenerator {
}
private async getEnvironmentDetails(): Promise<string> {
const currentNoteContext = await this.getCurrentNoteContext()
const noteConnectivity = await this.getNoteConnectivity()
const currentFile = await this.getCurrentFile()
const workspaceOverview = await this.getWorkspaceOverview()
const assistantState = await this.getAssistantState()
const details = [
currentNoteContext,
noteConnectivity,
currentFile,
workspaceOverview,
assistantState,
]
@ -275,37 +273,12 @@ export class PromptGenerator {
return `<environment_details>\n${details.trim()}\n</environment_details>`
}
private async getCurrentNoteContext(): Promise<string | null> {
private async getCurrentFile(): Promise<string | null> {
const currentNote = this.app.workspace.getActiveFile()
if (!currentNote) {
return formatSection("Current Tab Note", "(No current tab active)")
return formatSection("Current File", "(No current file active)")
}
const fileCache = this.app.metadataCache.getFileCache(currentNote)
if (!fileCache) {
return formatSection("Current Tab Note", currentNote.path)
}
let context = ``
if (fileCache.frontmatter) {
const frontmatterString = Object.entries(fileCache.frontmatter)
.filter(([key]) => key !== 'position')
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join('\n')
if (frontmatterString) {
context += `\n\n## Metadata (Frontmatter)\n${frontmatterString}`
}
}
if (fileCache.headings && fileCache.headings.length > 0) {
const outline = fileCache.headings
.map(h => `${' '.repeat(h.level - 1)}- ${h.heading}`)
.join('\n')
context += `\n\n## Outline\n${outline}`
}
return formatSection("Current Note Context", context)
return formatSection("Current File", currentNote.path)
}
private async getFileMetadataContext(file: TFile): Promise<string> {
@ -398,40 +371,40 @@ export class PromptGenerator {
}
}
private async getNoteConnectivity(): Promise<string | null> {
const currentFile = this.app.workspace.getActiveFile()
if (!currentFile) {
return null
}
// private async getNoteConnectivity(): Promise<string | null> {
// const currentFile = this.app.workspace.getActiveFile()
// if (!currentFile) {
// return null
// }
const fileCache = this.app.metadataCache.getFileCache(currentFile)
if (!fileCache) {
return null
}
// const fileCache = this.app.metadataCache.getFileCache(currentFile)
// if (!fileCache) {
// return null
// }
let connectivity = ""
// let connectivity = ""
if (fileCache.links && fileCache.links.length > 0) {
const outgoingLinks = fileCache.links.map(l => `- [[${l.link}]]`).join('\n')
connectivity += `\n## Outgoing Links\n${outgoingLinks}`
}
// if (fileCache.links && fileCache.links.length > 0) {
// const outgoingLinks = fileCache.links.map(l => `- [[${l.link}]]`).join('\n')
// connectivity += `\n## Outgoing Links\n${outgoingLinks}`
// }
const backlinks: string[] = []
const resolvedLinks = this.app.metadataCache.resolvedLinks
if (resolvedLinks) {
for (const sourcePath in resolvedLinks) {
if (currentFile.path in resolvedLinks[sourcePath]) {
backlinks.push(`- [[${sourcePath}]]`)
}
}
}
// const backlinks: string[] = []
// const resolvedLinks = this.app.metadataCache.resolvedLinks
// if (resolvedLinks) {
// for (const sourcePath in resolvedLinks) {
// if (currentFile.path in resolvedLinks[sourcePath]) {
// backlinks.push(`- [[${sourcePath}]]`)
// }
// }
// }
if (backlinks.length > 0) {
connectivity += `\n\n## Backlinks\n${backlinks.join('\n')}`
}
// if (backlinks.length > 0) {
// connectivity += `\n\n## Backlinks\n${backlinks.join('\n')}`
// }
return formatSection("Note Connectivity", connectivity.trim())
}
// return formatSection("Note Connectivity", connectivity.trim())
// }
private async getWorkspaceOverview(): Promise<string> {
let overview = ''
@ -440,33 +413,13 @@ export class PromptGenerator {
if (currentWorkspaceName && currentWorkspaceName !== 'vault') {
const workspace = await this.workspaceManager.findByName(currentWorkspaceName)
if (workspace) {
overview += `\n\n## Current Workspace\n${workspace.name}`
overview += `\n\n# Current Workspace\n${workspace.name}`
}
} else {
overview += `\n\n## Current Workspace\n${this.app.vault.getName()} (entire vault)`
overview += `\n\n# Current Workspace\n${this.app.vault.getName()} (entire vault)`
}
const recentFiles = this.app.vault.getMarkdownFiles()
.sort((a, b) => b.stat.mtime - a.stat.mtime)
.slice(0, 5)
.map(f => `- ${f.path}`)
.join('\n')
if (recentFiles) {
overview += `\n\n## Recently Edited Notes\n${recentFiles}`
}
// @ts-expect-error - getTags() is not in the public API but is widely used.
const tags: Record<string, number> = this.app.metadataCache.getTags()
const sortedTags = Object.entries(tags)
.sort(([, a], [, b]) => b - a)
.slice(0, 10)
.map(([tag, count]) => `- ${tag} (${count})`)
.join('\n')
if (sortedTags) {
overview += `\n\n## Global Tag Cloud (Top 10)\n${sortedTags}`
}
return formatSection('Workspace Overview', overview)
return overview
}
private async getAssistantState(): Promise<string> {

View File

@ -15,15 +15,11 @@ export const TOOL_DISPLAY_NAMES = {
use_mcp_tool: "use mcp tools",
access_mcp_resource: "access mcp resources",
ask_followup_question: "ask questions",
dataview_query: "query dataview",
attempt_completion: "complete tasks",
switch_mode: "switch modes",
new_task: "create new task",
analyze_paper: "analyze papers",
key_insights: "extract key insights",
dense_summary: "create dense summaries",
reflections: "generate reflections",
table_of_contents: "create table of contents",
simple_summary: "create simple summaries",
insights: "call insights",
manage_files: "manage files",
} as const
// Define available tool groups
@ -34,6 +30,9 @@ export const TOOL_GROUPS: Record<string, ToolGroupConfig> = {
edit: {
tools: ["apply_diff", "write_to_file", "insert_content", "search_and_replace"],
},
manage_files: {
tools: ["manage_files"],
},
research: {
tools: ["search_web", "fetch_urls_content"],
},
@ -74,8 +73,11 @@ export function getToolOptions(toolConfig: string | readonly [ToolName, ...any[]
export const GROUP_DISPLAY_NAMES: Record<ToolGroup, string> = {
read: "Read Files",
edit: "Edit Files",
manage_files: "Manage Files",
research: "Research",
browser: "Use Browser",
command: "Run Commands",
dataview_query: "Query Dataview",
insights: "Call Insights",
mcp: "Use MCP",
}