feat(obsidian): add Obsidian integration with 15 tools#3455
feat(obsidian): add Obsidian integration with 15 tools#3455waleedlatif1 merged 4 commits intostagingfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryMedium Risk Overview Implements 15 new Obsidian tools under Updates docs to include the new Written by Cursor Bugbot for commit d78eb62. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed: encodeURIComponent encodes slashes in vault file paths
- Fixed by splitting filenames on '/' and encoding each segment individually in all affected tools (get_note, create_note, append_note, patch_note, delete_note, open_file).
- ✅ Fixed: Params config drops most tool parameters
- Fixed by spreading all remaining parameters (...rest) in tools.config.params function, ensuring all input parameters are passed through to the tools.
Or push these changes by commenting:
@cursor push 2ee16c4ed1
Preview (2ee16c4ed1)
diff --git a/apps/sim/blocks/blocks/obsidian.ts b/apps/sim/blocks/blocks/obsidian.ts
--- a/apps/sim/blocks/blocks/obsidian.ts
+++ b/apps/sim/blocks/blocks/obsidian.ts
@@ -221,12 +221,13 @@
config: {
tool: (params) => `obsidian_${params.operation}`,
params: (params) => {
- const result: Record<string, unknown> = {}
+ const { patchOperation, ...rest } = params
+ const result: Record<string, unknown> = { ...rest }
if (params.contextLength) {
result.contextLength = Number(params.contextLength)
}
- if (params.patchOperation) {
- result.operation = params.patchOperation
+ if (patchOperation) {
+ result.operation = patchOperation
}
return result
},
diff --git a/apps/sim/tools/obsidian/append_note.ts b/apps/sim/tools/obsidian/append_note.ts
--- a/apps/sim/tools/obsidian/append_note.ts
+++ b/apps/sim/tools/obsidian/append_note.ts
@@ -37,7 +37,8 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
- return `${base}/vault/${encodeURIComponent(params.filename.trim())}`
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
+ return `${base}/vault/${encodedPath}`
},
method: 'POST',
headers: (params) => ({
diff --git a/apps/sim/tools/obsidian/create_note.ts b/apps/sim/tools/obsidian/create_note.ts
--- a/apps/sim/tools/obsidian/create_note.ts
+++ b/apps/sim/tools/obsidian/create_note.ts
@@ -37,7 +37,8 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
- return `${base}/vault/${encodeURIComponent(params.filename.trim())}`
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
+ return `${base}/vault/${encodedPath}`
},
method: 'PUT',
headers: (params) => ({
diff --git a/apps/sim/tools/obsidian/delete_note.ts b/apps/sim/tools/obsidian/delete_note.ts
--- a/apps/sim/tools/obsidian/delete_note.ts
+++ b/apps/sim/tools/obsidian/delete_note.ts
@@ -31,7 +31,8 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
- return `${base}/vault/${encodeURIComponent(params.filename.trim())}`
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
+ return `${base}/vault/${encodedPath}`
},
method: 'DELETE',
headers: (params) => ({
diff --git a/apps/sim/tools/obsidian/get_note.ts b/apps/sim/tools/obsidian/get_note.ts
--- a/apps/sim/tools/obsidian/get_note.ts
+++ b/apps/sim/tools/obsidian/get_note.ts
@@ -31,7 +31,8 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
- return `${base}/vault/${encodeURIComponent(params.filename.trim())}`
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
+ return `${base}/vault/${encodedPath}`
},
method: 'GET',
headers: (params) => ({
diff --git a/apps/sim/tools/obsidian/open_file.ts b/apps/sim/tools/obsidian/open_file.ts
--- a/apps/sim/tools/obsidian/open_file.ts
+++ b/apps/sim/tools/obsidian/open_file.ts
@@ -37,8 +37,9 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
const leafParam = params.newLeaf ? '?newLeaf=true' : ''
- return `${base}/open/${encodeURIComponent(params.filename.trim())}${leafParam}`
+ return `${base}/open/${encodedPath}${leafParam}`
},
method: 'POST',
headers: (params) => ({
diff --git a/apps/sim/tools/obsidian/patch_note.ts b/apps/sim/tools/obsidian/patch_note.ts
--- a/apps/sim/tools/obsidian/patch_note.ts
+++ b/apps/sim/tools/obsidian/patch_note.ts
@@ -69,7 +69,8 @@
request: {
url: (params) => {
const base = params.baseUrl.replace(/\/$/, '')
- return `${base}/vault/${encodeURIComponent(params.filename.trim())}`
+ const encodedPath = params.filename.trim().split('/').map(encodeURIComponent).join('/')
+ return `${base}/vault/${encodedPath}`
},
method: 'PATCH',
headers: (params) => {
Greptile SummaryThis PR adds a full Obsidian integration (15 tools) covering the Obsidian Local REST API, including vault CRUD, search, periodic notes, commands, and active-file operations. The implementation follows the established pattern for other tool integrations in this codebase — per-segment URL encoding, Two tools are missing the standard
Both are straightforward one-line fixes but do affect correctness. Confidence Score: 3/5
Sequence DiagramsequenceDiagram
participant UI as Sim UI (Block)
participant Engine as Tool Engine
participant OT as Obsidian Tool
participant API as Obsidian Local REST API
UI->>Engine: Run block (operation, apiKey, baseUrl, …)
Engine->>Engine: Resolve tool via obsidian_${operation}
Engine->>OT: Call tool with params
alt Vault file operations (get/create/append/patch/delete)
OT->>API: GET/PUT/POST/PATCH/DELETE /vault/{encoded-path}
else Active file operations
OT->>API: GET/POST/PATCH /active/
else Search
OT->>API: POST /search/simple/?query={query}
else Periodic notes
OT->>API: GET/POST /periodic/{period}/
else Commands
OT->>API: GET /commands/
OT->>API: POST /commands/{commandId}/
else Open file
OT->>API: POST /open/{encoded-path}
end
API-->>OT: Response (JSON or text/markdown)
OT->>OT: transformResponse (check ok, parse body)
OT-->>Engine: { success, output }
Engine-->>UI: Block output
|
|
@greptile |
|
@cursor review |
|
@greptile |
|
@cursor review |

Summary
Type of Change
Testing
Tested manually
Checklist