pomera-ai-commander 1.2.3 → 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,4 +1,9 @@
1
1
  # Pomera AI Commander (PAC)
2
+
3
+ <p align="center">
4
+ <img src="resources/icon.png" alt="Pomera - the fluffy Pomeranian mascot" width="128" height="128">
5
+ </p>
6
+
2
7
  [![Download Latest Release](https://img.shields.io/badge/Download-Latest%20Release-blue?style=for-the-badge&logo=github)](https://github.com/matbanik/Pomera-AI-Commander/releases)
3
8
 
4
9
  A desktop text "workbench" + MCP server: clean, transform, extract, and analyze text fast—manually in a GUI or programmatically from AI assistants (Cursor / Claude Desktop / MCP clients).
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Create Desktop Shortcut for Pomera AI Commander
4
+
5
+ Cross-platform script to create desktop shortcuts/launchers:
6
+ - Windows: Creates .lnk shortcut
7
+ - macOS: Creates .command script in ~/Desktop
8
+ - Linux: Creates .desktop launcher
9
+
10
+ Can be run standalone or as npm postinstall hook.
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import stat
16
+ import platform
17
+ from pathlib import Path
18
+
19
+
20
+ def get_package_dir() -> Path:
21
+ """Get the pomera-ai-commander package directory."""
22
+ # First check if we're running from the package itself
23
+ script_dir = Path(__file__).parent.resolve()
24
+ if (script_dir / "pomera.py").exists():
25
+ return script_dir
26
+
27
+ # Check npm global installation
28
+ npm_global = os.environ.get("APPDATA", "") or os.path.expanduser("~")
29
+ if platform.system() == "Windows":
30
+ npm_path = Path(npm_global) / "npm" / "node_modules" / "pomera-ai-commander"
31
+ else:
32
+ npm_path = Path(npm_global) / ".npm-global" / "lib" / "node_modules" / "pomera-ai-commander"
33
+ if not npm_path.exists():
34
+ npm_path = Path("/usr/local/lib/node_modules/pomera-ai-commander")
35
+ if not npm_path.exists():
36
+ npm_path = Path.home() / ".npm-packages" / "lib" / "node_modules" / "pomera-ai-commander"
37
+
38
+ if npm_path.exists():
39
+ return npm_path
40
+
41
+ return script_dir
42
+
43
+
44
+ def get_desktop_path() -> Path:
45
+ """Get the user's desktop directory."""
46
+ if platform.system() == "Windows":
47
+ return Path(os.environ.get("USERPROFILE", "")) / "Desktop"
48
+ elif platform.system() == "Darwin": # macOS
49
+ return Path.home() / "Desktop"
50
+ else: # Linux
51
+ # Check XDG user dirs
52
+ xdg_desktop = os.environ.get("XDG_DESKTOP_DIR")
53
+ if xdg_desktop:
54
+ return Path(xdg_desktop)
55
+ return Path.home() / "Desktop"
56
+
57
+
58
+ def create_windows_shortcut(package_dir: Path, desktop: Path) -> bool:
59
+ """Create Windows .lnk shortcut."""
60
+ try:
61
+ import subprocess
62
+
63
+ shortcut_path = desktop / "Pomera AI Commander.lnk"
64
+ pomera_py = package_dir / "pomera.py"
65
+ icon_path = package_dir / "resources" / "icon.ico"
66
+
67
+ # Use PowerShell to create shortcut
68
+ ps_script = f'''
69
+ $WshShell = New-Object -ComObject WScript.Shell
70
+ $Shortcut = $WshShell.CreateShortcut("{shortcut_path}")
71
+ $Shortcut.TargetPath = "pythonw.exe"
72
+ $Shortcut.Arguments = '"{pomera_py}"'
73
+ $Shortcut.WorkingDirectory = "{package_dir}"
74
+ $Shortcut.Description = "Pomera AI Commander - Text Processing Toolkit"
75
+ '''
76
+ if icon_path.exists():
77
+ ps_script += f'$Shortcut.IconLocation = "{icon_path},0"\n'
78
+
79
+ ps_script += '$Shortcut.Save()'
80
+
81
+ result = subprocess.run(
82
+ ["powershell", "-Command", ps_script],
83
+ capture_output=True,
84
+ text=True
85
+ )
86
+
87
+ if result.returncode == 0:
88
+ print(f"✓ Created Windows shortcut: {shortcut_path}")
89
+ return True
90
+ else:
91
+ print(f"✗ Failed to create shortcut: {result.stderr}")
92
+ return False
93
+
94
+ except Exception as e:
95
+ print(f"✗ Error creating Windows shortcut: {e}")
96
+ return False
97
+
98
+
99
+ def create_macos_shortcut(package_dir: Path, desktop: Path) -> bool:
100
+ """Create macOS .command script."""
101
+ try:
102
+ shortcut_path = desktop / "Pomera AI Commander.command"
103
+ pomera_py = package_dir / "pomera.py"
104
+
105
+ script_content = f'''#!/bin/bash
106
+ # Pomera AI Commander Launcher
107
+ cd "{package_dir}"
108
+ python3 "{pomera_py}"
109
+ '''
110
+
111
+ shortcut_path.write_text(script_content)
112
+ # Make executable
113
+ shortcut_path.chmod(shortcut_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
114
+
115
+ print(f"✓ Created macOS launcher: {shortcut_path}")
116
+ return True
117
+
118
+ except Exception as e:
119
+ print(f"✗ Error creating macOS shortcut: {e}")
120
+ return False
121
+
122
+
123
+ def create_linux_shortcut(package_dir: Path, desktop: Path) -> bool:
124
+ """Create Linux .desktop launcher."""
125
+ try:
126
+ shortcut_path = desktop / "pomera-ai-commander.desktop"
127
+ pomera_py = package_dir / "pomera.py"
128
+ icon_path = package_dir / "resources" / "icon.png"
129
+
130
+ # Use icon if exists, otherwise use generic
131
+ icon = str(icon_path) if icon_path.exists() else "utilities-terminal"
132
+
133
+ desktop_entry = f'''[Desktop Entry]
134
+ Version=1.0
135
+ Type=Application
136
+ Name=Pomera AI Commander
137
+ Comment=Text Processing Toolkit with MCP tools for AI assistants
138
+ Exec=python3 "{pomera_py}"
139
+ Icon={icon}
140
+ Terminal=false
141
+ Categories=Development;Utility;TextTools;
142
+ StartupNotify=true
143
+ '''
144
+
145
+ shortcut_path.write_text(desktop_entry)
146
+ # Make executable
147
+ shortcut_path.chmod(shortcut_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
148
+
149
+ print(f"✓ Created Linux launcher: {shortcut_path}")
150
+
151
+ # Also try to add to applications menu
152
+ try:
153
+ apps_dir = Path.home() / ".local" / "share" / "applications"
154
+ apps_dir.mkdir(parents=True, exist_ok=True)
155
+ apps_shortcut = apps_dir / "pomera-ai-commander.desktop"
156
+ apps_shortcut.write_text(desktop_entry)
157
+ apps_shortcut.chmod(apps_shortcut.stat().st_mode | stat.S_IXUSR)
158
+ print(f"✓ Added to applications menu: {apps_shortcut}")
159
+ except Exception:
160
+ pass # Not critical
161
+
162
+ return True
163
+
164
+ except Exception as e:
165
+ print(f"✗ Error creating Linux shortcut: {e}")
166
+ return False
167
+
168
+
169
+ def create_shortcut():
170
+ """Create desktop shortcut for the current platform."""
171
+ print("\n🐕 Pomera AI Commander - Desktop Shortcut Creator")
172
+ print("=" * 50)
173
+
174
+ package_dir = get_package_dir()
175
+ desktop = get_desktop_path()
176
+
177
+ print(f"Package directory: {package_dir}")
178
+ print(f"Desktop directory: {desktop}")
179
+
180
+ if not (package_dir / "pomera.py").exists():
181
+ print(f"✗ Error: pomera.py not found in {package_dir}")
182
+ return False
183
+
184
+ if not desktop.exists():
185
+ print(f"✗ Error: Desktop directory not found: {desktop}")
186
+ return False
187
+
188
+ system = platform.system()
189
+ print(f"Platform: {system}")
190
+ print("-" * 50)
191
+
192
+ if system == "Windows":
193
+ return create_windows_shortcut(package_dir, desktop)
194
+ elif system == "Darwin":
195
+ return create_macos_shortcut(package_dir, desktop)
196
+ elif system == "Linux":
197
+ return create_linux_shortcut(package_dir, desktop)
198
+ else:
199
+ print(f"✗ Unsupported platform: {system}")
200
+ return False
201
+
202
+
203
+ def remove_shortcut():
204
+ """Remove desktop shortcut for the current platform."""
205
+ print("\n🐕 Removing Pomera AI Commander shortcut...")
206
+
207
+ desktop = get_desktop_path()
208
+ system = platform.system()
209
+
210
+ shortcuts = []
211
+ if system == "Windows":
212
+ shortcuts.append(desktop / "Pomera AI Commander.lnk")
213
+ elif system == "Darwin":
214
+ shortcuts.append(desktop / "Pomera AI Commander.command")
215
+ elif system == "Linux":
216
+ shortcuts.append(desktop / "pomera-ai-commander.desktop")
217
+ shortcuts.append(Path.home() / ".local" / "share" / "applications" / "pomera-ai-commander.desktop")
218
+
219
+ for shortcut in shortcuts:
220
+ if shortcut.exists():
221
+ try:
222
+ shortcut.unlink()
223
+ print(f"✓ Removed: {shortcut}")
224
+ except Exception as e:
225
+ print(f"✗ Failed to remove {shortcut}: {e}")
226
+
227
+
228
+ if __name__ == "__main__":
229
+ if len(sys.argv) > 1 and sys.argv[1] == "--remove":
230
+ remove_shortcut()
231
+ else:
232
+ success = create_shortcut()
233
+ if success:
234
+ print("\n✅ Desktop shortcut created successfully!")
235
+ else:
236
+ print("\n⚠️ Failed to create desktop shortcut")
237
+ sys.exit(1)
package/mcp.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pomera-ai-commander",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Text processing toolkit with 22 MCP tools including case transformation, encoding, hashing, text analysis, and notes management for AI assistants.",
5
5
  "homepage": "https://github.com/matbanik/Pomera-AI-Commander",
6
6
  "repository": "https://github.com/matbanik/Pomera-AI-Commander",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pomera-ai-commander",
3
- "version": "1.2.3",
3
+ "version": "1.2.4",
4
4
  "description": "Text processing toolkit with 22 MCP tools for AI assistants - case transformation, encoding, hashing, text analysis, and notes management",
5
5
  "main": "pomera_mcp_server.py",
6
6
  "bin": {
@@ -50,8 +50,10 @@
50
50
  "core/",
51
51
  "tools/",
52
52
  "scripts/",
53
+ "resources/",
53
54
  "pomera_mcp_server.py",
54
55
  "pomera.py",
56
+ "create_shortcut.py",
55
57
  "migrate_data.py",
56
58
  "mcp.json",
57
59
  "README.md",
package/pomera.py CHANGED
@@ -779,6 +779,9 @@ class PromeraAIApp(tk.Tk):
779
779
 
780
780
  self.title("Pomera AI Commander")
781
781
  self.geometry(AppConfig.DEFAULT_WINDOW_SIZE)
782
+
783
+ # Set window icon (Pomera dog mascot)
784
+ self._set_window_icon()
782
785
 
783
786
  self._after_id = None
784
787
  self._regex_cache = {}
@@ -1201,7 +1204,7 @@ class PromeraAIApp(tk.Tk):
1201
1204
  pyproject_path = Path(__file__).parent / "pyproject.toml"
1202
1205
  if pyproject_path.exists():
1203
1206
  content = pyproject_path.read_text()
1204
- match = re.search(r'version = "1.2.3"]+)"', content)
1207
+ match = re.search(r'version = "1.2.4"]+)"', content)
1205
1208
  if match:
1206
1209
  current_version = match.group(1)
1207
1210
  except Exception:
@@ -1212,7 +1215,7 @@ class PromeraAIApp(tk.Tk):
1212
1215
  import importlib.metadata
1213
1216
  current_version = importlib.metadata.version("pomera-ai-commander")
1214
1217
  except Exception:
1215
- current_version = "1.2.3"
1218
+ current_version = "1.2.4"
1216
1219
 
1217
1220
  # Detect OS for download link
1218
1221
  system = platform.system()
@@ -1351,7 +1354,7 @@ class PromeraAIApp(tk.Tk):
1351
1354
  def _show_about_dialog(self):
1352
1355
  """Show About dialog."""
1353
1356
  # Version managed by bump_version.py script
1354
- version = "1.2.3"
1357
+ version = "1.2.4"
1355
1358
 
1356
1359
  messagebox.showinfo(
1357
1360
  "About Pomera AI Commander",
@@ -1359,6 +1362,42 @@ class PromeraAIApp(tk.Tk):
1359
1362
  "Text processing toolkit with MCP tools for AI assistants.\n\n"
1360
1363
  "https://github.com/matbanik/Pomera-AI-Commander"
1361
1364
  )
1365
+
1366
+ def _set_window_icon(self):
1367
+ """Set the window icon (Pomera dog mascot)."""
1368
+ try:
1369
+ # Find icon file - check multiple locations
1370
+ script_dir = Path(__file__).parent.resolve()
1371
+ icon_locations = [
1372
+ script_dir / "resources" / "icon.ico",
1373
+ script_dir / "icon.ico",
1374
+ script_dir / "resources" / "icon.png",
1375
+ script_dir / "icon.png",
1376
+ ]
1377
+
1378
+ icon_path = None
1379
+ for loc in icon_locations:
1380
+ if loc.exists():
1381
+ icon_path = loc
1382
+ break
1383
+
1384
+ if icon_path is None:
1385
+ return # No icon found, use default
1386
+
1387
+ if platform.system() == "Windows" and icon_path.suffix == ".ico":
1388
+ # Windows: use iconbitmap for .ico files
1389
+ self.iconbitmap(str(icon_path))
1390
+ else:
1391
+ # Other platforms or PNG: use PhotoImage
1392
+ from PIL import Image, ImageTk
1393
+ img = Image.open(icon_path)
1394
+ # Resize to appropriate icon size - use NEAREST for sharp pixel art
1395
+ img = img.resize((32, 32), Image.Resampling.NEAREST)
1396
+ self._icon_photo = ImageTk.PhotoImage(img)
1397
+ self.iconphoto(True, self._icon_photo)
1398
+
1399
+ except Exception as e:
1400
+ self.logger.debug(f"Could not set window icon: {e}")
1362
1401
 
1363
1402
  def _auto_save_settings(self):
1364
1403
  """Auto-save settings periodically (called by Task Scheduler)."""
@@ -70,7 +70,7 @@ def main():
70
70
  parser.add_argument(
71
71
  "--version",
72
72
  action="version",
73
- version="pomera-mcp-server 1.2.3"
73
+ version="pomera-mcp-server 1.2.4"
74
74
  )
75
75
  parser.add_argument(
76
76
  "--list-tools",
@@ -160,7 +160,7 @@ def main():
160
160
  server = StdioMCPServer(
161
161
  tool_registry=registry,
162
162
  server_name="pomera-mcp-server",
163
- server_version="1.2.3"
163
+ server_version="1.2.4"
164
164
  )
165
165
 
166
166
  logger.info("Starting Pomera MCP Server...")
Binary file
Binary file
@@ -2,19 +2,23 @@
2
2
  /**
3
3
  * Pomera AI Commander - npm postinstall script
4
4
  *
5
- * This script runs after npm install/update and checks for
6
- * databases in the package directory that might be at risk.
7
- *
8
- * Displays a warning if portable mode data is detected.
5
+ * This script runs after npm install/update and:
6
+ * 1. Checks for databases in the package directory that might be at risk
7
+ * 2. Creates a desktop shortcut for easy access to the GUI
9
8
  */
10
9
 
11
10
  const fs = require('fs');
12
11
  const path = require('path');
12
+ const { execSync, spawn } = require('child_process');
13
+ const os = require('os');
13
14
 
14
15
  // Package root directory
15
16
  const packageDir = path.join(__dirname, '..');
16
17
 
17
- // Check for databases in package directory
18
+ // ============================================================
19
+ // Part 1: Database Warning Check
20
+ // ============================================================
21
+
18
22
  const databases = ['settings.db', 'notes.db', 'settings.json'];
19
23
  const foundDatabases = [];
20
24
 
@@ -30,7 +34,6 @@ databases.forEach(db => {
30
34
  }
31
35
  });
32
36
 
33
- // If databases found in package directory, show warning
34
37
  if (foundDatabases.length > 0) {
35
38
  console.log('\n' + '='.repeat(70));
36
39
  console.log('⚠️ POMERA DATA WARNING ⚠️');
@@ -56,7 +59,163 @@ if (foundDatabases.length > 0) {
56
59
  }
57
60
  console.log('\n' + '='.repeat(70) + '\n');
58
61
  } else {
59
- // No databases in package directory - safe configuration
60
62
  console.log('✅ Pomera AI Commander installed successfully.');
61
63
  console.log(' Data will be stored in platform-appropriate directory (safe from updates).');
62
64
  }
65
+
66
+ // ============================================================
67
+ // Part 2: Desktop Shortcut Creation
68
+ // ============================================================
69
+
70
+ function getDesktopPath() {
71
+ if (process.platform === 'win32') {
72
+ return path.join(os.homedir(), 'Desktop');
73
+ } else if (process.platform === 'darwin') {
74
+ return path.join(os.homedir(), 'Desktop');
75
+ } else {
76
+ // Linux - check XDG
77
+ const xdgDesktop = process.env.XDG_DESKTOP_DIR;
78
+ if (xdgDesktop) return xdgDesktop;
79
+ return path.join(os.homedir(), 'Desktop');
80
+ }
81
+ }
82
+
83
+ function createWindowsShortcut() {
84
+ const desktop = getDesktopPath();
85
+ const shortcutPath = path.join(desktop, 'Pomera AI Commander.lnk');
86
+ const pomeraPath = path.join(packageDir, 'pomera.py');
87
+ const iconPath = path.join(packageDir, 'resources', 'icon.ico');
88
+
89
+ let psScript = `
90
+ $WshShell = New-Object -ComObject WScript.Shell
91
+ $Shortcut = $WshShell.CreateShortcut("${shortcutPath.replace(/\\/g, '\\\\')}")
92
+ $Shortcut.TargetPath = "pythonw.exe"
93
+ $Shortcut.Arguments = '"${pomeraPath.replace(/\\/g, '\\\\')}"'
94
+ $Shortcut.WorkingDirectory = "${packageDir.replace(/\\/g, '\\\\')}"
95
+ $Shortcut.Description = "Pomera AI Commander - Text Processing Toolkit"
96
+ `;
97
+ if (fs.existsSync(iconPath)) {
98
+ psScript += `$Shortcut.IconLocation = "${iconPath.replace(/\\/g, '\\\\')},0"\n`;
99
+ }
100
+ psScript += '$Shortcut.Save()';
101
+
102
+ try {
103
+ execSync(`powershell -Command "${psScript.replace(/"/g, '\\"')}"`, { stdio: 'pipe' });
104
+ console.log(`\n🐕 Desktop shortcut created: ${shortcutPath}`);
105
+ return true;
106
+ } catch (e) {
107
+ console.log('\n⚠️ Could not create desktop shortcut automatically.');
108
+ console.log(' Run: python create_shortcut.py');
109
+ return false;
110
+ }
111
+ }
112
+
113
+ function createMacOSShortcut() {
114
+ const desktop = getDesktopPath();
115
+ const shortcutPath = path.join(desktop, 'Pomera AI Commander.command');
116
+ const pomeraPath = path.join(packageDir, 'pomera.py');
117
+
118
+ const script = `#!/bin/bash
119
+ # Pomera AI Commander Launcher
120
+ cd "${packageDir}"
121
+ python3 "${pomeraPath}"
122
+ `;
123
+
124
+ try {
125
+ fs.writeFileSync(shortcutPath, script);
126
+ fs.chmodSync(shortcutPath, 0o755);
127
+ console.log(`\n🐕 Desktop launcher created: ${shortcutPath}`);
128
+ return true;
129
+ } catch (e) {
130
+ console.log('\n⚠️ Could not create desktop shortcut automatically.');
131
+ return false;
132
+ }
133
+ }
134
+
135
+ function createLinuxShortcut() {
136
+ const desktop = getDesktopPath();
137
+ const shortcutPath = path.join(desktop, 'pomera-ai-commander.desktop');
138
+ const pomeraPath = path.join(packageDir, 'pomera.py');
139
+ const iconPath = path.join(packageDir, 'resources', 'icon.png');
140
+
141
+ const icon = fs.existsSync(iconPath) ? iconPath : 'utilities-terminal';
142
+
143
+ const desktopEntry = `[Desktop Entry]
144
+ Version=1.0
145
+ Type=Application
146
+ Name=Pomera AI Commander
147
+ Comment=Text Processing Toolkit with MCP tools for AI assistants
148
+ Exec=python3 "${pomeraPath}"
149
+ Icon=${icon}
150
+ Terminal=false
151
+ Categories=Development;Utility;TextTools;
152
+ StartupNotify=true
153
+ `;
154
+
155
+ try {
156
+ fs.writeFileSync(shortcutPath, desktopEntry);
157
+ fs.chmodSync(shortcutPath, 0o755);
158
+ console.log(`\n🐕 Desktop launcher created: ${shortcutPath}`);
159
+
160
+ // Also add to applications menu
161
+ const appsDir = path.join(os.homedir(), '.local', 'share', 'applications');
162
+ if (!fs.existsSync(appsDir)) {
163
+ fs.mkdirSync(appsDir, { recursive: true });
164
+ }
165
+ const appsPath = path.join(appsDir, 'pomera-ai-commander.desktop');
166
+ fs.writeFileSync(appsPath, desktopEntry);
167
+ console.log(` Also added to applications menu`);
168
+
169
+ return true;
170
+ } catch (e) {
171
+ console.log('\n⚠️ Could not create desktop shortcut automatically.');
172
+ return false;
173
+ }
174
+ }
175
+
176
+ function createDesktopShortcut() {
177
+ console.log('\n🐕 Creating desktop shortcut...');
178
+
179
+ const desktop = getDesktopPath();
180
+ if (!fs.existsSync(desktop)) {
181
+ console.log(` Desktop directory not found: ${desktop}`);
182
+ return false;
183
+ }
184
+
185
+ if (process.platform === 'win32') {
186
+ return createWindowsShortcut();
187
+ } else if (process.platform === 'darwin') {
188
+ return createMacOSShortcut();
189
+ } else {
190
+ return createLinuxShortcut();
191
+ }
192
+ }
193
+
194
+ // Check if Python/pythonw is available before creating shortcut
195
+ function checkPython() {
196
+ try {
197
+ if (process.platform === 'win32') {
198
+ execSync('where pythonw', { stdio: 'pipe' });
199
+ } else {
200
+ execSync('which python3', { stdio: 'pipe' });
201
+ }
202
+ return true;
203
+ } catch (e) {
204
+ return false;
205
+ }
206
+ }
207
+
208
+ // Create shortcut if Python is available
209
+ if (checkPython()) {
210
+ createDesktopShortcut();
211
+ } else {
212
+ console.log('\n⚠️ Python not found in PATH. Desktop shortcut not created.');
213
+ console.log(' Install Python and run: python create_shortcut.py');
214
+ }
215
+
216
+ console.log('\n📖 To start the GUI manually:');
217
+ console.log(' python pomera.py');
218
+ console.log('\n📖 To start the MCP server:');
219
+ console.log(' npx pomera-ai-commander');
220
+ console.log('');
221
+