Last active
January 23, 2025 17:20
-
-
Save grahama1970/fddfc3c9a3a175a8b6e4bdf45b02dd7f to your computer and use it in GitHub Desktop.
Debug for an Raycast extension that tries to access Obsidian's Smart Chat Conversations (within Raycast) to ask questions of local documents
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Action, Detail, LaunchProps } from "@raycast/api"; | |
import { getConfig } from "./utils/preferences"; | |
interface Preferences { | |
obsidianVaultPath: string; | |
} | |
export default function ResultView(props: LaunchProps<{ context: { answer: string } }>) { | |
const { obsidianVaultPath } = getConfig(); | |
// Add defensive check for context and answer | |
if (!props.context || !props.context.answer) { | |
return <Detail markdown="No response content available" />; | |
} | |
const answer = props.context.answer; | |
// Extract a note path from the answer (if present in [title](path) format) | |
const notePath = answer.match(/\[.*?\]\((.*?)\)/)?.[1] || ""; | |
const obsidianUri = `obsidian://open?path=${encodeURIComponent(`${obsidianVaultPath}/${notePath}`)}`; | |
return ( | |
<Detail | |
markdown={answer} | |
actions={ | |
notePath ? ( | |
<Action.Open | |
title="Open in Obsidian" | |
target={obsidianUri} | |
shortcut={{ modifiers: ["cmd"], key: "o" }} | |
/> | |
) : null | |
} | |
/> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { LaunchType, LaunchProps, closeMainWindow, launchCommand, showToast, Toast, ErrorBoundary } from "@raycast/api"; | |
import open from "open"; | |
import { getConfig } from "./utils/preferences"; | |
interface Preferences { | |
obsidianApiKey: string; | |
obsidianPort: string; | |
obsidianChatFolder: string; | |
obsidianVaultPath: string; | |
} | |
function AskObsidianImplementation(props: LaunchProps<{ arguments: { query: string } }>) { | |
const { query } = props.arguments; | |
const { obsidianApiKey, obsidianPort, obsidianChatFolder, obsidianVaultPath } = getConfig(); | |
const processQuery = async () => { | |
try { | |
await open(`obsidian://advanced-uri?command=smart-chat&query=${encodeURIComponent(query)}`); | |
await closeMainWindow(); | |
let retries = 3; | |
while (retries-- > 0) { | |
await new Promise(resolve => setTimeout(resolve, 2000)); | |
const search = await fetch( | |
`http://localhost:${obsidianPort}/vault/search?query=path:${encodeURIComponent(obsidianChatFolder)}&sort=modified`, | |
{ headers: { Authorization: `Bearer ${obsidianApiKey}` } } | |
); | |
const response = await search.json(); | |
// Check if response exists and has results | |
if (!response || !Array.isArray(response.results)) { | |
showToast({ | |
style: Toast.Style.Failure, | |
title: "Invalid API response", | |
message: "No results found or API error", | |
}); | |
return; | |
} | |
const results = response.results; | |
const latestNote = results[0]?.path; | |
if (latestNote) { | |
const note = await fetch( | |
`http://localhost:${obsidianPort}/vault/open?path=${encodeURIComponent(latestNote)}`, | |
{ headers: { Authorization: `Bearer ${obsidianApiKey}` } } | |
); | |
await launchCommand({ | |
name: "ask-obsidian-result", | |
type: LaunchType.UserInitiated, | |
context: { answer: await note.text() } | |
}); | |
return; | |
} | |
} | |
throw new Error("No response found after 3 attempts"); | |
} catch (error) { | |
showToast({ | |
style: Toast.Style.Failure, | |
title: "Error", | |
message: error instanceof Error ? error.message : "Failed to query Obsidian" | |
}); | |
} | |
}; | |
processQuery(); | |
return null; | |
} | |
export default function Command(props: LaunchProps<{ arguments: { query: string } }>) { | |
return ( | |
<ErrorBoundary> | |
<AskObsidianImplementation {...props} /> | |
</ErrorBoundary> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const DEV_CONFIG = { | |
obsidianApiKey: "12345", | |
obsidianPort: "27124", | |
obsidianVaultPath: "/Users/me/Documents/Obsidian Vault/", | |
obsidianChatFolder: "Chats" | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
npm run dev | |
> [email protected] dev | |
> ray develop | |
error - TypeError: Cannot read properties of undefined (reading 'map') | |
at qxe (/Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:751:1593) | |
at /Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:757:2825 | |
at /Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:757:3572 | |
at FMt (/Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:757:3903) | |
at BKe (/Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:757:3544) | |
at u.run (/Users/robert/scripts/obsidian-raycast-script/node_modules/@raycast/api/dist/commands/develop/index.js:757:2730) | |
at async u._run (/Users/robert/scripts/obsidian-raycast-script/node_modules/@oclif/core/lib/command.js:312:22) | |
at async Config.runCommand (/Users/robert/scripts/obsidian-raycast-script/node_modules/@oclif/core/lib/config/config.js:435:25) | |
at async run (/Users/robert/scripts/obsidian-raycast-script/node_modules/@oclif/core/lib/main.js:96:16) | |
16:15:22 Unable to install extension "obsidian-raycast-script": | |
> Development session couldn't start due to inability to install from local sources | |
16:15:22 Unable to install extension "obsidian-raycast-script": | |
> Unable to handle development session build notification due to inability to install from local sources |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "obsidian-raycast-script", | |
"version": "1.0.0", | |
"license": "MIT", | |
"main": "dist/index.js", | |
"scripts": { | |
"dev": "ray develop", | |
"build": "ray build -e dist", | |
"lint": "ray lint" | |
}, | |
"dependencies": { | |
"@raycast/api": "^1.57.0", | |
"open": "^9.1.0", | |
"react": "^18.2.0", | |
"react-dom": "^18.2.0" | |
}, | |
"devDependencies": { | |
"@types/node": "^20.11.0", | |
"@types/react": "^18.2.45", | |
"@types/react-dom": "^18.2.18", | |
"typescript": "^5.3.3" | |
}, | |
"raycast": { | |
"schemaVersion": 1, | |
"title": "Ask Obsidian", | |
"description": "Query Obsidian Smart Chat from Raycast", | |
"icon": "command-icon.png", | |
"author": "robert", | |
"categories": ["Productivity"], | |
"commands": [ | |
{ | |
"name": "ask-obsidian", | |
"title": "Ask Obsidian", | |
"description": "Query your Obsidian notes", | |
"mode": "view", | |
"component": "dist/src/ask-obsidian.js", | |
"arguments": [ | |
{ | |
"name": "query", | |
"placeholder": "Enter your query", | |
"type": "text", | |
"required": true | |
} | |
] | |
}, | |
{ | |
"name": "ask-obsidian-result", | |
"title": "Chat Result", | |
"description": "Displays Smart Chat response", | |
"mode": "view", | |
"component": "dist/src/ask-obsidian-result.js" | |
} | |
], | |
"preferences": [ | |
{ | |
"name": "obsidianApiKey", | |
"title": "API Key", | |
"type": "password", | |
"required": true | |
}, | |
{ | |
"name": "obsidianPort", | |
"title": "API Port", | |
"type": "textfield", | |
"required": true | |
}, | |
{ | |
"name": "obsidianVaultPath", | |
"title": "Vault Path", | |
"type": "textfield", | |
"required": true | |
}, | |
{ | |
"name": "obsidianChatFolder", | |
"title": "Chat Folder", | |
"type": "textfield", | |
"default": "Chats", | |
"required": true | |
} | |
] | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { getPreferenceValues } from "@raycast/api"; | |
import { DEV_CONFIG } from "../config.dev"; | |
const isDev = process.env.NODE_ENV === "development"; | |
export function getConfig() { | |
if (isDev) { | |
return DEV_CONFIG; | |
} | |
return getPreferenceValues(); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"$schema": "https://json.schemastore.org/tsconfig", | |
"include": ["src/**/*"], | |
"compilerOptions": { | |
"strict": true, | |
"esModuleInterop": true, | |
"lib": ["ES2021"], | |
"module": "CommonJS", | |
"moduleResolution": "node", | |
"outDir": "dist", | |
"target": "ES2021", | |
"jsx": "react-jsx" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment