@aurora-foundation/obsidian-next 0.4.8 → 0.4.10

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.
Files changed (61) hide show
  1. package/dist/chunk-2JWDGXTR.js +42 -0
  2. package/dist/chunk-3UCL6RYE.js +7272 -0
  3. package/dist/chunk-3VZGPA3N.js +42 -0
  4. package/dist/chunk-3XR3GZLX.js +7809 -0
  5. package/dist/chunk-6YJSTQKN.js +7817 -0
  6. package/dist/chunk-7XFP3ZUD.js +42 -0
  7. package/dist/chunk-ASDVTRIQ.js +7805 -0
  8. package/dist/chunk-BAKREPY2.js +439 -0
  9. package/dist/chunk-BFRO5BO2.js +42 -0
  10. package/dist/chunk-CHNVBJN3.js +7272 -0
  11. package/dist/chunk-DAR45YDV.js +42 -0
  12. package/dist/chunk-FNXAI27K.js +7812 -0
  13. package/dist/chunk-HKPL675M.js +42 -0
  14. package/dist/chunk-INEXRRON.js +42 -0
  15. package/dist/chunk-ISO6GNIB.js +429 -0
  16. package/dist/chunk-MGDY5JUY.js +581 -0
  17. package/dist/chunk-OFTKVOQ2.js +7828 -0
  18. package/dist/chunk-PD4ZKYTJ.js +7838 -0
  19. package/dist/chunk-PQSPCOJ7.js +7616 -0
  20. package/dist/chunk-QSEH5NXV.js +7807 -0
  21. package/dist/chunk-RUEIA6Z5.js +42 -0
  22. package/dist/chunk-S5IDXE2L.js +42 -0
  23. package/dist/chunk-UG3HWGIO.js +42 -0
  24. package/dist/chunk-UOESII6R.js +42 -0
  25. package/dist/chunk-VWMT4HCP.js +7668 -0
  26. package/dist/chunk-YFQI44IA.js +42 -0
  27. package/dist/chunk-ZR7MEF3B.js +7605 -0
  28. package/dist/context-NI6N46WG.js +10 -0
  29. package/dist/index.js +585 -345
  30. package/dist/memory-GXW2OA2T.js +13 -0
  31. package/dist/resume-EA6ISWW2.js +15 -0
  32. package/dist/resume-EIM5FN42.js +15 -0
  33. package/dist/resume-FBVK6NAI.js +15 -0
  34. package/dist/resume-H6J5PQIA.js +15 -0
  35. package/dist/resume-JDDVTMM4.js +15 -0
  36. package/dist/resume-JFYYR7DJ.js +15 -0
  37. package/dist/resume-KGFAZY34.js +15 -0
  38. package/dist/resume-MF5TM2ZB.js +15 -0
  39. package/dist/resume-O6PLICAA.js +15 -0
  40. package/dist/resume-PZU3PWCJ.js +15 -0
  41. package/dist/resume-YD76GI2J.js +15 -0
  42. package/dist/resume-YKAKOXWV.js +15 -0
  43. package/dist/session-37MDDCWV.js +14 -0
  44. package/dist/session-56ZI3GZV.js +14 -0
  45. package/dist/session-5OFIDWGU.js +14 -0
  46. package/dist/session-7LPACLRV.js +14 -0
  47. package/dist/session-CJ6HSKDI.js +14 -0
  48. package/dist/session-CUXGN26I.js +14 -0
  49. package/dist/session-DCGNGGMV.js +14 -0
  50. package/dist/session-LEVSW6JH.js +14 -0
  51. package/dist/session-MHZAYMLC.js +14 -0
  52. package/dist/session-NNU7OW5K.js +14 -0
  53. package/dist/session-R5UG5PZR.js +14 -0
  54. package/dist/session-T64DMDAU.js +14 -0
  55. package/dist/settings-4ALCRT5S.js +8 -0
  56. package/dist/skills/defaults/clipboard.mjs +46 -0
  57. package/dist/skills/defaults/notify.mjs +36 -0
  58. package/dist/skills/defaults/open_app.mjs +53 -0
  59. package/dist/skills/defaults/speak.mjs +47 -0
  60. package/dist/skills/defaults/spotify_control.mjs +187 -0
  61. package/package.json +7 -4
@@ -0,0 +1,187 @@
1
+ export default {
2
+ name: 'spotify_control',
3
+ description: 'Control Spotify playback on macOS - play music by name, pause, resume, skip, get current track. Uses AppleScript for native control.',
4
+ inputSchema: {
5
+ action: {
6
+ type: 'string',
7
+ description: 'Action: play, pause, resume, next, previous, current, search_and_play, volume, shuffle'
8
+ },
9
+ query: {
10
+ type: 'string',
11
+ description: 'Search query for play/search_and_play (e.g. "lofi beats", "Drake - Gods Plan")'
12
+ },
13
+ volume: {
14
+ type: 'number',
15
+ description: 'Volume level 0-100 (for volume action)'
16
+ }
17
+ },
18
+ requiredParams: ['action'],
19
+
20
+ async execute(args) {
21
+ const { execSync } = await import('child_process');
22
+ const action = (args.action || '').toLowerCase().trim();
23
+ const query = args.query || '';
24
+
25
+ const osascript = (script) => {
26
+ try {
27
+ return execSync(`osascript -e '${script.replace(/'/g, "'\\''")}'`, {
28
+ encoding: 'utf-8',
29
+ timeout: 10000
30
+ }).trim();
31
+ } catch (e) {
32
+ throw new Error(`AppleScript failed: ${e.message}`);
33
+ }
34
+ };
35
+
36
+ // Ensure Spotify is running
37
+ const ensureRunning = () => {
38
+ try {
39
+ osascript('tell application "Spotify" to activate');
40
+ } catch {
41
+ // Spotify not installed
42
+ throw new Error('Spotify is not installed');
43
+ }
44
+ };
45
+
46
+ // Search via Spotify AppleScript and play track URI directly
47
+ const searchAndPlay = async (searchQuery) => {
48
+ ensureRunning();
49
+
50
+ // Use open with spotify URI to trigger search
51
+ // Then use keyboard simulation via AppleScript to play the first result
52
+ const encoded = encodeURIComponent(searchQuery);
53
+
54
+ // Method 1: Use spotify:search URI then simulate keyboard to play first result
55
+ execSync(`open "spotify:search:${encoded}"`, { timeout: 5000 });
56
+
57
+ // Wait for Spotify to load search results
58
+ await new Promise(r => setTimeout(r, 2500));
59
+
60
+ // Simulate pressing Enter/Return to play the first result
61
+ // This works because Spotify focuses the first result after search
62
+ osascript(`
63
+ tell application "System Events"
64
+ tell process "Spotify"
65
+ set frontmost to true
66
+ delay 0.5
67
+ key code 36
68
+ end tell
69
+ end tell
70
+ `);
71
+
72
+ // Wait for track to start
73
+ await new Promise(r => setTimeout(r, 1500));
74
+
75
+ // Verify playback started
76
+ try {
77
+ const state = osascript('tell application "Spotify" to player state as string');
78
+ if (state === 'playing') {
79
+ const track = osascript('tell application "Spotify" to name of current track');
80
+ const artist = osascript('tell application "Spotify" to artist of current track');
81
+ return {
82
+ success: true,
83
+ output: `Now playing: "${track}" by ${artist}\nSearched for: ${searchQuery}`
84
+ };
85
+ }
86
+ } catch { /* fall through */ }
87
+
88
+ // Fallback: try clicking play button via AppleScript
89
+ try {
90
+ osascript('tell application "Spotify" to play');
91
+ await new Promise(r => setTimeout(r, 1000));
92
+ const track = osascript('tell application "Spotify" to name of current track');
93
+ const artist = osascript('tell application "Spotify" to artist of current track');
94
+ return {
95
+ success: true,
96
+ output: `Playing: "${track}" by ${artist}\nNote: Searched for "${searchQuery}" - verify this is the right track`
97
+ };
98
+ } catch {
99
+ return {
100
+ success: true,
101
+ output: `Opened Spotify search for "${searchQuery}". Press play on the result you want.`
102
+ };
103
+ }
104
+ };
105
+
106
+ try {
107
+ switch (action) {
108
+ case 'play':
109
+ case 'search_and_play': {
110
+ if (!query) {
111
+ ensureRunning();
112
+ osascript('tell application "Spotify" to play');
113
+ const track = osascript('tell application "Spotify" to name of current track');
114
+ const artist = osascript('tell application "Spotify" to artist of current track');
115
+ return { success: true, output: `Resumed: "${track}" by ${artist}` };
116
+ }
117
+ return await searchAndPlay(query);
118
+ }
119
+
120
+ case 'pause':
121
+ osascript('tell application "Spotify" to pause');
122
+ return { success: true, output: 'Paused playback' };
123
+
124
+ case 'resume':
125
+ osascript('tell application "Spotify" to play');
126
+ return { success: true, output: 'Resumed playback' };
127
+
128
+ case 'next': {
129
+ osascript('tell application "Spotify" to next track');
130
+ await new Promise(r => setTimeout(r, 500));
131
+ const nTrack = osascript('tell application "Spotify" to name of current track');
132
+ const nArtist = osascript('tell application "Spotify" to artist of current track');
133
+ return { success: true, output: `Skipped to: "${nTrack}" by ${nArtist}` };
134
+ }
135
+
136
+ case 'previous': {
137
+ osascript('tell application "Spotify" to previous track');
138
+ await new Promise(r => setTimeout(r, 500));
139
+ const pTrack = osascript('tell application "Spotify" to name of current track');
140
+ const pArtist = osascript('tell application "Spotify" to artist of current track');
141
+ return { success: true, output: `Back to: "${pTrack}" by ${pArtist}` };
142
+ }
143
+
144
+ case 'current': {
145
+ const state = osascript('tell application "Spotify" to player state as string');
146
+ if (state === 'stopped') {
147
+ return { success: true, output: 'Spotify is stopped - nothing playing' };
148
+ }
149
+ const name = osascript('tell application "Spotify" to name of current track');
150
+ const art = osascript('tell application "Spotify" to artist of current track');
151
+ const album = osascript('tell application "Spotify" to album of current track');
152
+ const pos = osascript('tell application "Spotify" to player position');
153
+ const dur = osascript('tell application "Spotify" to duration of current track');
154
+ const durSec = Math.round(parseInt(dur) / 1000);
155
+ return {
156
+ success: true,
157
+ output: `${state === 'playing' ? '[PLAYING]' : '[PAUSED]'} "${name}" by ${art}\nAlbum: ${album}\nPosition: ${Math.round(parseFloat(pos))}s / ${durSec}s`
158
+ };
159
+ }
160
+
161
+ case 'volume': {
162
+ const vol = Math.max(0, Math.min(100, parseInt(args.volume) || 50));
163
+ osascript(`tell application "Spotify" to set sound volume to ${vol}`);
164
+ return { success: true, output: `Volume set to ${vol}%` };
165
+ }
166
+
167
+ case 'shuffle': {
168
+ const current = osascript('tell application "Spotify" to shuffling');
169
+ const newState = current === 'true' ? false : true;
170
+ osascript(`tell application "Spotify" to set shuffling to ${newState}`);
171
+ return { success: true, output: `Shuffle ${newState ? 'ON' : 'OFF'}` };
172
+ }
173
+
174
+ default:
175
+ return {
176
+ success: false,
177
+ error: `Unknown action: ${action}. Use: play, pause, resume, next, previous, current, search_and_play, volume, shuffle`
178
+ };
179
+ }
180
+ } catch (error) {
181
+ return {
182
+ success: false,
183
+ error: `Spotify control failed: ${error.message}. Is Spotify installed and running?`
184
+ };
185
+ }
186
+ }
187
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurora-foundation/obsidian-next",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Next-gen AI Agent CLI",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -33,14 +33,17 @@
33
33
  },
34
34
  "scripts": {
35
35
  "dev": "tsup src/index.ts --format esm --watch",
36
- "build": "tsup src/index.ts src/mcp/index.ts --format esm",
36
+ "build": "tsup src/index.ts src/mcp/index.ts --format esm && cp -r src/skills dist/",
37
+ "build:check": "npm run lint && npm run format:check && tsup src/index.ts src/mcp/index.ts --format esm",
37
38
  "start": "node dist/index.js",
38
39
  "mcp": "node dist/mcp/index.js",
39
40
  "test": "vitest",
41
+ "test:ci": "vitest run --reporter=verbose",
40
42
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
41
43
  "format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
42
- "lint": "eslint src --ext .ts,.tsx",
43
- "lint:fix": "eslint src --ext .ts,.tsx --fix"
44
+ "lint": "eslint .",
45
+ "lint:fix": "eslint . --fix",
46
+ "precommit": "npm run lint:fix && npm run format && npm test"
44
47
  },
45
48
  "dependencies": {
46
49
  "@anthropic-ai/sandbox-runtime": "^0.0.32",