diff --git a/manifest.json b/manifest.json index 5017c29..af947e2 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "openaugi", "name": "OpenAugi", - "version": "0.5.1", + "version": "0.5.2", "minAppVersion": "1.8.9", "description": "Process information faster with augmented intelligence (AI for thinkers). Parse your voice notes into atomic notes, tasks, and summaries. Grab context from dataview queries and linked notes. De-duplicate and merge atomic ideas into a clean, organized vault.", "author": "Chris Lettieri", diff --git a/package.json b/package.json index deca8ca..b5287e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-augi", - "version": "0.5.1", + "version": "0.5.2", "description": "", "main": "main.js", "scripts": { diff --git a/src/main.ts b/src/main.ts index 6bc6e81..cca22ea 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,10 +1,12 @@ -import { Plugin, Notice, TFile } from 'obsidian'; +import { Plugin, Notice, TFile, Platform } from 'obsidian'; import { OpenAugiSettings, DEFAULT_SETTINGS } from './types/settings'; import { OpenAIService } from './services/openai-service'; import { FileService } from './services/file-service'; import { DistillService } from './services/distill-service'; import { ContextGatheringService } from './services/context-gathering-service'; -import { TaskDispatchService } from './services/task-dispatch-service'; +// Lazy-imported: TaskDispatchService uses Node.js modules (child_process, fs, path) +// that are unavailable on mobile. We dynamic-import it only on desktop. +import type { TaskDispatchService } from './services/task-dispatch-service'; import { OpenAugiSettingTab } from './ui/settings-tab'; import { LoadingIndicator } from './ui/loading-indicator'; import { SessionListModal } from './ui/session-list-modal'; @@ -32,7 +34,7 @@ export default class OpenAugiPlugin extends Plugin { fileService: FileService; distillService: DistillService; contextGatheringService: ContextGatheringService; - taskDispatchService: TaskDispatchService; + taskDispatchService: TaskDispatchService | null; loadingIndicator: LoadingIndicator; async onload() { @@ -116,52 +118,66 @@ export default class OpenAugiPlugin extends Plugin { } }); - // Task dispatch commands - this.addCommand({ - id: 'task-dispatch-launch', - name: 'Task dispatch: Launch or attach', - callback: async () => { - const activeFile = this.app.workspace.getActiveFile(); - if (activeFile && activeFile.extension === 'md') { - await this.taskDispatchService.launchOrAttach(activeFile); - } else { - new Notice('Please open a task note first'); - } - } - }); - - this.addCommand({ - id: 'task-dispatch-kill', - name: 'Task dispatch: Kill session', - callback: async () => { - const activeFile = this.app.workspace.getActiveFile(); - if (activeFile && activeFile.extension === 'md') { - await this.taskDispatchService.killSession(activeFile); - } else { - new Notice('Please open a task note first'); - } - } - }); - - this.addCommand({ - id: 'task-dispatch-list', - name: 'Task dispatch: List active sessions', - callback: async () => { - const sessions = await this.taskDispatchService.listActiveSessions(); - const modal = new SessionListModal( - this.app, - sessions, - async (session: TaskSession) => { - await this.taskDispatchService.openTerminal(session.tmuxSessionName); - }, - async (session: TaskSession) => { - await this.taskDispatchService.killSessionById(session.taskId); - new Notice(`Killed session: ${session.taskId}`); + // Task dispatch commands — desktop only + if (!Platform.isMobile) { + this.addCommand({ + id: 'task-dispatch-launch', + name: 'Task dispatch: Launch or attach', + callback: async () => { + if (!this.taskDispatchService) { + new Notice('Task dispatch is still loading, try again in a moment'); + return; } - ); - modal.open(); - } - }); + const activeFile = this.app.workspace.getActiveFile(); + if (activeFile && activeFile.extension === 'md') { + await this.taskDispatchService.launchOrAttach(activeFile); + } else { + new Notice('Please open a task note first'); + } + } + }); + + this.addCommand({ + id: 'task-dispatch-kill', + name: 'Task dispatch: Kill session', + callback: async () => { + if (!this.taskDispatchService) { + new Notice('Task dispatch is still loading, try again in a moment'); + return; + } + const activeFile = this.app.workspace.getActiveFile(); + if (activeFile && activeFile.extension === 'md') { + await this.taskDispatchService.killSession(activeFile); + } else { + new Notice('Please open a task note first'); + } + } + }); + + this.addCommand({ + id: 'task-dispatch-list', + name: 'Task dispatch: List active sessions', + callback: async () => { + if (!this.taskDispatchService) { + new Notice('Task dispatch is still loading, try again in a moment'); + return; + } + const sessions = await this.taskDispatchService.listActiveSessions(); + const modal = new SessionListModal( + this.app, + sessions, + async (session: TaskSession) => { + await this.taskDispatchService!.openTerminal(session.tmuxSessionName); + }, + async (session: TaskSession) => { + await this.taskDispatchService!.killSessionById(session.taskId); + new Notice(`Killed session: ${session.taskId}`); + } + ); + modal.open(); + } + }); + } // Add settings tab this.addSettingTab(new OpenAugiSettingTab(this.app, this)); @@ -195,11 +211,23 @@ export default class OpenAugiPlugin extends Plugin { this.distillService, this.settings ); - this.taskDispatchService = new TaskDispatchService( - this.app, - this.settings, - this.distillService - ); + + // TaskDispatchService uses Node.js modules (child_process, fs, path) + // unavailable on mobile. Skip entirely on mobile. + this.taskDispatchService = null; + if (!Platform.isMobile) { + import('./services/task-dispatch-service') + .then(({ TaskDispatchService }) => { + this.taskDispatchService = new TaskDispatchService( + this.app, + this.settings, + this.distillService + ); + }) + .catch(() => { + // Fallback: Node.js modules unavailable in this environment. + }); + } } /** diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 863060d..378d683 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -2,12 +2,12 @@ import { Plugin } from 'obsidian'; import { OpenAugiSettings } from './settings'; import { OpenAIService } from '../services/openai-service'; import { FileService } from '../services/file-service'; -import { TaskDispatchService } from '../services/task-dispatch-service'; +import type { TaskDispatchService } from '../services/task-dispatch-service'; export default interface OpenAugiPlugin extends Plugin { settings: OpenAugiSettings; openAIService: OpenAIService; fileService: FileService; - taskDispatchService: TaskDispatchService; + taskDispatchService: TaskDispatchService | null; saveSettings(): Promise; } \ No newline at end of file diff --git a/src/ui/settings-tab.ts b/src/ui/settings-tab.ts index af6b7cd..d4e8005 100644 --- a/src/ui/settings-tab.ts +++ b/src/ui/settings-tab.ts @@ -2,7 +2,8 @@ import { App, PluginSettingTab, Setting, Notice, DropdownComponent } from 'obsid import type OpenAugiPlugin from '../types/plugin'; import { OpenAIService } from '../services/openai-service'; import { TerminalApp } from '../types/task-dispatch'; -import { detectTmuxPath } from '../services/task-dispatch-service'; +// Lazy-imported: detectTmuxPath lives in task-dispatch-service which uses +// Node.js modules unavailable on mobile. export class OpenAugiSettingTab extends PluginSettingTab { plugin: OpenAugiPlugin; @@ -387,6 +388,7 @@ export class OpenAugiSettingTab extends PluginSettingTab { .addButton(button => button .setButtonText('Detect') .onClick(async () => { + const { detectTmuxPath } = await import('../services/task-dispatch-service'); const found = await detectTmuxPath(); if (found) { this.plugin.settings.taskDispatch.tmuxPath = found; diff --git a/tests/mocks/obsidian-module.ts b/tests/mocks/obsidian-module.ts index 51381bc..942f7ac 100644 --- a/tests/mocks/obsidian-module.ts +++ b/tests/mocks/obsidian-module.ts @@ -72,5 +72,11 @@ export class FileSystemAdapter { getBasePath(): string { return this.basePath; } } +export const Platform = { + isMobile: false, + isDesktop: true, + isDesktopApp: true, +}; + export class MarkdownView {} export class WorkspaceLeaf {}