From 201a987ff9d0483dc691da497a03012b6caa5ab5 Mon Sep 17 00:00:00 2001 From: jmorganca Date: Sun, 28 Apr 2024 12:40:52 -0400 Subject: [PATCH] some more menu options... --- app/app_darwin.go | 4 ++- app/app_darwin.m | 70 +++++++++++++++++++++++++++++++++++++++++++++++ app/server.go | 26 ++++++++++++++++-- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/app/app_darwin.go b/app/app_darwin.go index d7d8fa6b..dcf9cba2 100644 --- a/app/app_darwin.go +++ b/app/app_darwin.go @@ -44,10 +44,12 @@ func run() { panic(err) } + var options ServerOptions + ctx, cancel := context.WithCancel(context.Background()) var done chan int - done, err = SpawnServer(ctx, filepath.Join(filepath.Dir(exe), "..", "Resources", "ollama")) + done, err = SpawnServer(ctx, filepath.Join(filepath.Dir(exe), "..", "Resources", "ollama"), options) if err != nil { slog.Error(fmt.Sprintf("Failed to spawn ollama server %s", err)) done = make(chan int, 1) diff --git a/app/app_darwin.m b/app/app_darwin.m index 76ead9d5..782d2e3d 100644 --- a/app/app_darwin.m +++ b/app/app_darwin.m @@ -16,7 +16,38 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { // show status menu NSMenu *menu = [[NSMenu alloc] init]; + + NSMenuItem *aboutMenuItem = [[NSMenuItem alloc] initWithTitle:@"About Ollama" action:@selector(aboutOllama) keyEquivalent:@""]; + [aboutMenuItem setTarget:self]; + [menu addItem:aboutMenuItem]; + + // Settings submenu + NSMenu *settingsMenu = [[NSMenu alloc] initWithTitle:@"Settings"]; + + // Submenu items + NSMenuItem *chooseModelDirectoryItem = [[NSMenuItem alloc] initWithTitle:@"Choose model directory..." action:@selector(chooseModelDirectory) keyEquivalent:@""]; + [chooseModelDirectoryItem setTarget:self]; + [chooseModelDirectoryItem setEnabled:YES]; + [settingsMenu addItem:chooseModelDirectoryItem]; + + NSMenuItem *exposeExternallyItem = [[NSMenuItem alloc] initWithTitle:@"Allow external connections" action:@selector(toggleExposeExternally:) keyEquivalent:@""]; + [exposeExternallyItem setTarget:self]; + [exposeExternallyItem setState:NSOffState]; // Set initial state to off + [exposeExternallyItem setEnabled:YES]; + [settingsMenu addItem:exposeExternallyItem]; + + NSMenuItem *allowCrossOriginItem = [[NSMenuItem alloc] initWithTitle:@"Allow browser requests" action:@selector(toggleCrossOrigin:) keyEquivalent:@""]; + [allowCrossOriginItem setTarget:self]; + [allowCrossOriginItem setState:NSOffState]; // Set initial state to off + [allowCrossOriginItem setEnabled:YES]; + [settingsMenu addItem:allowCrossOriginItem]; + + NSMenuItem *settingsMenuItem = [[NSMenuItem alloc] initWithTitle:@"Settings" action:nil keyEquivalent:@""]; + [settingsMenuItem setSubmenu:settingsMenu]; + [menu addItem:settingsMenuItem]; + [menu addItemWithTitle:@"Quit Ollama" action:@selector(quit) keyEquivalent:@"q"]; + self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; [self.statusItem addObserver:self forKeyPath:@"button.effectiveAppearance" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil]; @@ -24,6 +55,45 @@ [self showIcon]; } +- (void)aboutOllama { + [[NSApplication sharedApplication] orderFrontStandardAboutPanel:nil]; +} + +- (void)toggleCrossOrigin:(id)sender { + NSMenuItem *item = (NSMenuItem *)sender; + if ([item state] == NSOffState) { + // Do something when cross-origin requests are allowed + [item setState:NSOnState]; + } else { + // Do something when cross-origin requests are disallowed + [item setState:NSOffState]; + } +} + +- (void)toggleExposeExternally:(id)sender { + NSMenuItem *item = (NSMenuItem *)sender; + if ([item state] == NSOffState) { + // Do something when Ollama is exposed externally + [item setState:NSOnState]; + } else { + // Do something when Ollama is not exposed externally + [item setState:NSOffState]; + } +} + +- (void)chooseModelDirectory { + NSOpenPanel *openPanel = [NSOpenPanel openPanel]; + [openPanel setCanChooseFiles:NO]; + [openPanel setCanChooseDirectories:YES]; + [openPanel setAllowsMultipleSelection:NO]; + + NSInteger result = [openPanel runModal]; + if (result == NSModalResponseOK) { + NSURL *selectedDirectoryURL = [openPanel URLs].firstObject; + // Do something with the selected directory URL + } +} + -(void) showIcon { NSAppearance* appearance = self.statusItem.button.effectiveAppearance; NSString* appearanceName = (NSString*)(appearance.name); diff --git a/app/server.go b/app/server.go index bf27d31d..2b9554dd 100644 --- a/app/server.go +++ b/app/server.go @@ -14,8 +14,28 @@ import ( "github.com/ollama/ollama/api" ) -func start(ctx context.Context, command string) (*exec.Cmd, error) { +type ServerOptions struct { + Cors bool + Expose bool + ModelsPath string +} + +func start(ctx context.Context, command string, options ServerOptions) (*exec.Cmd, error) { cmd := getCmd(ctx, command) + + // set environment variables + if options.ModelsPath != "" { + cmd.Env = append(cmd.Env, fmt.Sprintf("OLLAMA_MODELS=%s", options.ModelsPath)) + } + + if options.Cors { + cmd.Env = append(cmd.Env, "OLLAMA_ORIGINS=*") + } + + if options.Expose { + cmd.Env = append(cmd.Env, "OLLAMA_HOST=0.0.0.0") + } + stdout, err := cmd.StdoutPipe() if err != nil { return nil, fmt.Errorf("failed to spawn server stdout pipe: %w", err) @@ -83,7 +103,7 @@ func start(ctx context.Context, command string) (*exec.Cmd, error) { return cmd, nil } -func SpawnServer(ctx context.Context, command string) (chan int, error) { +func SpawnServer(ctx context.Context, command string, options ServerOptions) (chan int, error) { logDir := filepath.Dir(ServerLogFile) _, err := os.Stat(logDir) if errors.Is(err, os.ErrNotExist) { @@ -99,7 +119,7 @@ func SpawnServer(ctx context.Context, command string) (chan int, error) { crashCount := 0 for { slog.Info(fmt.Sprintf("starting server...")) - cmd, err := start(ctx, command) + cmd, err := start(ctx, command, options) if err != nil { slog.Error(fmt.Sprintf("failed to start server %s", err)) }