@audiofool/moondog 0.1.0
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 +125 -0
- package/assets/brand/moondog-lunar-record/moondog-logo-1x1.png +0 -0
- package/contracts/v1/capability-policy.schema.json +572 -0
- package/contracts/v1/definitions.schema.json +365 -0
- package/contracts/v1/library-track-observation.schema.json +138 -0
- package/contracts/v1/listening-event.schema.json +111 -0
- package/contracts/v1/profile-evidence.schema.json +237 -0
- package/contracts/v1/taste-event.schema.json +258 -0
- package/contracts/v1/tool-invocation.schema.json +318 -0
- package/contracts/v1/tool-receipt.schema.json +1066 -0
- package/contracts/v1/track-ref.schema.json +275 -0
- package/contracts/v2/profile-evidence.schema.json +284 -0
- package/package.json +105 -0
- package/scripts/contract-lib.mjs +361 -0
- package/scripts/contract-semantics.mjs +2630 -0
- package/scripts/demo-studio.mjs +58 -0
- package/scripts/moondog +52 -0
- package/scripts/moondog.mjs +954 -0
- package/src/core/apple-data-migration.mjs +50 -0
- package/src/core/apple-library-source-status.mjs +220 -0
- package/src/core/apple-projection-domain-services.mjs +2356 -0
- package/src/core/capability-catalog.mjs +577 -0
- package/src/core/listening-profile-domain-services.mjs +1010 -0
- package/src/core/lyric-library.mjs +121 -0
- package/src/core/lyric-profile.mjs +50 -0
- package/src/core/lyric-service.mjs +41 -0
- package/src/core/moondog-application.mjs +1827 -0
- package/src/core/state-directory.mjs +19 -0
- package/src/core/synthetic-domain-services.mjs +1485 -0
- package/src/core/uuid-v5.mjs +42 -0
- package/src/demo/fictional-spotify-history.mjs +400 -0
- package/src/demo/moondog-demo.mjs +355 -0
- package/src/demo/moondog-interactive-tasteprint-demo.mjs +293 -0
- package/src/demo/moondog-tasteprint-demo.mjs +631 -0
- package/src/importers/apple-music-library/import-batch.mjs +290 -0
- package/src/importers/apple-music-library/index.mjs +76 -0
- package/src/importers/apple-music-library/normalize.mjs +1126 -0
- package/src/importers/apple-music-library/parse-plist.mjs +357 -0
- package/src/importers/apple-music-library/projection-records.mjs +557 -0
- package/src/importers/apple-music-library/read-batch.mjs +276 -0
- package/src/importers/apple-music-library/sqlite-projection.mjs +1307 -0
- package/src/importers/apple-music-library/stable-ids.mjs +19 -0
- package/src/importers/apple-music-library/track-snapshot.schema.json +136 -0
- package/src/integrations/apple-music/catalog.mjs +770 -0
- package/src/integrations/cross-catalog-artist-identity.mjs +222 -0
- package/src/integrations/listenbrainz/history-file.mjs +560 -0
- package/src/integrations/lyrics/lrclib.mjs +55 -0
- package/src/integrations/open-music-similarity/artist-radio.mjs +806 -0
- package/src/integrations/public-playlists.mjs +104 -0
- package/src/integrations/spotify/account-data-history.mjs +545 -0
- package/src/integrations/spotify/account-data-profile.mjs +918 -0
- package/src/integrations/spotify/authentication.mjs +791 -0
- package/src/integrations/spotify/catalog-resolver.mjs +657 -0
- package/src/integrations/spotify/connection.mjs +125 -0
- package/src/integrations/spotify/credential-store.mjs +26 -0
- package/src/integrations/spotify/extended-streaming-history.mjs +525 -0
- package/src/integrations/spotify/history-archive.mjs +59 -0
- package/src/integrations/spotify/index.mjs +80 -0
- package/src/integrations/spotify/recent-activity.mjs +198 -0
- package/src/integrations/spotify/resolution-cache.mjs +260 -0
- package/src/integrations/spotify/service.mjs +713 -0
- package/src/integrations/spotify/settings.mjs +89 -0
- package/src/integrations/spotify/web-api-client.mjs +761 -0
- package/src/integrations/web/codex-web.mjs +263 -0
- package/src/integrations/youtube-music/takeout.mjs +143 -0
- package/src/memory/local-memory-store.mjs +1705 -0
- package/src/memory/reflection-worker.mjs +87 -0
- package/src/profile/apple-library-import.mjs +28 -0
- package/src/profile/history-import.mjs +163 -0
- package/src/profile/listener-corrections.mjs +217 -0
- package/src/profile/listening-history-store.mjs +2055 -0
- package/src/profile/listening-profile-projection.mjs +2520 -0
- package/src/profile/local-music-data.mjs +812 -0
- package/src/profile/music-import-bundle.mjs +91 -0
- package/src/profile/music-providers.mjs +25 -0
- package/src/profile/spotify-archive-catalog-hints.mjs +210 -0
- package/src/profile/spotify-archive-taste.mjs +482 -0
- package/src/runtime/pi/agent-runtime.mjs +6444 -0
- package/src/runtime/pi/authentication.mjs +104 -0
- package/src/runtime/pi/configured-runtime.mjs +98 -0
- package/src/runtime/pi/memory-agent-runtime.mjs +337 -0
- package/src/runtime/pi/model-catalog.mjs +62 -0
- package/src/runtime/pi/model-transport.mjs +117 -0
- package/src/runtime/pi/persistent-credential-store.mjs +670 -0
- package/src/runtime/pi/provider-registry.mjs +74 -0
- package/src/runtime/pi/runtime-settings.mjs +81 -0
- package/src/surfaces/cli/auth-command.mjs +355 -0
- package/src/surfaces/cli/brand-components.mjs +390 -0
- package/src/surfaces/cli/brand-theme.mjs +231 -0
- package/src/surfaces/cli/catalog-command.mjs +509 -0
- package/src/surfaces/cli/command-completions.mjs +113 -0
- package/src/surfaces/cli/data-command.mjs +214 -0
- package/src/surfaces/cli/format-output.mjs +750 -0
- package/src/surfaces/cli/history-import-view.mjs +445 -0
- package/src/surfaces/cli/import-guides.mjs +9 -0
- package/src/surfaces/cli/listenbrainz-command.mjs +129 -0
- package/src/surfaces/cli/listening-menu.mjs +171 -0
- package/src/surfaces/cli/profile-command.mjs +290 -0
- package/src/surfaces/cli/spotify-command.mjs +849 -0
- package/src/surfaces/cli/taste-profile-model.mjs +306 -0
- package/src/surfaces/cli/taste-profile-view.mjs +272 -0
- package/src/surfaces/cli/terminal-art.mjs +295 -0
- package/src/surfaces/cli/tui.mjs +1714 -0
- package/src/surfaces/cli/web-command.mjs +52 -0
- package/src/surfaces/html/tasteprint-artifact.mjs +96 -0
- package/src/surfaces/html/tasteprint.mjs +3575 -0
- package/src/surfaces/web/showcase.mjs +272 -0
- package/src/surfaces/web/studio-page.mjs +4148 -0
- package/src/surfaces/web/studio.mjs +2288 -0
|
@@ -0,0 +1,577 @@
|
|
|
1
|
+
const catalog = [
|
|
2
|
+
{
|
|
3
|
+
id: "web.search", version: "1", state: "enabled", effect: "read_external",
|
|
4
|
+
description: "Search public music reviews, news, interviews and event information through the local Codex CLI.",
|
|
5
|
+
requires_web_research: true,
|
|
6
|
+
agent_tool: { name: "moondog_web_search", label: "Search the public web" },
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
id: "web.read", version: "1", state: "enabled", effect: "read_external",
|
|
10
|
+
description: "Read and summarize a public web page with dated source attribution through the local Codex CLI.",
|
|
11
|
+
requires_web_research: true,
|
|
12
|
+
agent_tool: { name: "moondog_web_read", label: "Read a public web page" },
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: "source.apple_music.status",
|
|
16
|
+
version: "1",
|
|
17
|
+
state: "enabled",
|
|
18
|
+
effect: "read_local",
|
|
19
|
+
description: "Inspect aggregate Apple Music import readiness.",
|
|
20
|
+
agent_tool: {
|
|
21
|
+
name: "moondog_source_status",
|
|
22
|
+
label: "Check your music sources",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: "profile.status",
|
|
27
|
+
version: "1",
|
|
28
|
+
state: "enabled",
|
|
29
|
+
effect: "read_local",
|
|
30
|
+
description: "Inspect evidence-backed profile readiness.",
|
|
31
|
+
agent_tool: {
|
|
32
|
+
name: "moondog_profile_status",
|
|
33
|
+
label: "Check your profile",
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "memory.status",
|
|
38
|
+
version: "1",
|
|
39
|
+
state: "enabled",
|
|
40
|
+
effect: "read_local",
|
|
41
|
+
description: "Inspect conversation and long-term memory readiness.",
|
|
42
|
+
agent_tool: {
|
|
43
|
+
name: "moondog_memory_status",
|
|
44
|
+
label: "Check what I remember",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "capability.status",
|
|
49
|
+
version: "1",
|
|
50
|
+
state: "enabled",
|
|
51
|
+
effect: "read_local",
|
|
52
|
+
description: "Inspect the Moondog capability registry.",
|
|
53
|
+
agent_tool: {
|
|
54
|
+
name: "moondog_capability_status",
|
|
55
|
+
label: "Check what I can do",
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
id: "runtime.status",
|
|
60
|
+
version: "1",
|
|
61
|
+
state: "enabled",
|
|
62
|
+
effect: "read_runtime",
|
|
63
|
+
description: "Inspect the configured model runtime.",
|
|
64
|
+
agent_tool: {
|
|
65
|
+
name: "moondog_runtime_status",
|
|
66
|
+
label: "Check the model connection",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: "library.search",
|
|
71
|
+
version: "1",
|
|
72
|
+
state: "enabled",
|
|
73
|
+
effect: "read_local",
|
|
74
|
+
description: "Search a bounded view of the private normalized music library.",
|
|
75
|
+
requires_domain_services: true,
|
|
76
|
+
agent_tool: {
|
|
77
|
+
name: "moondog_library_search",
|
|
78
|
+
label: "Search your music library",
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: "profile.summary",
|
|
83
|
+
version: "1",
|
|
84
|
+
state: "enabled",
|
|
85
|
+
effect: "read_local",
|
|
86
|
+
description: "Read a compact evidence-backed personal music profile.",
|
|
87
|
+
requires_profile_services: true,
|
|
88
|
+
agent_tool: {
|
|
89
|
+
name: "moondog_profile_summary",
|
|
90
|
+
label: "Read your music profile",
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: "profile.rediscovery",
|
|
95
|
+
version: "1",
|
|
96
|
+
state: "enabled",
|
|
97
|
+
effect: "read_local",
|
|
98
|
+
description:
|
|
99
|
+
"Create a prompt-local playlist candidate set from meaningful older listening that has gone quiet.",
|
|
100
|
+
requires_rediscovery_services: true,
|
|
101
|
+
agent_tool: {
|
|
102
|
+
name: "moondog_rediscovery_candidates",
|
|
103
|
+
label: "Find music worth another listen",
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "profile.historical_returns",
|
|
108
|
+
version: "1",
|
|
109
|
+
state: "enabled",
|
|
110
|
+
effect: "read_local",
|
|
111
|
+
description:
|
|
112
|
+
"Create a prompt-local playlist candidate set from tracks that reappeared after long gaps in retained listening history.",
|
|
113
|
+
requires_historical_return_services: true,
|
|
114
|
+
agent_tool: {
|
|
115
|
+
name: "moondog_historical_return_candidates",
|
|
116
|
+
label: "Find music that came back",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "profile.time_capsule",
|
|
121
|
+
version: "1",
|
|
122
|
+
state: "enabled",
|
|
123
|
+
effect: "read_local",
|
|
124
|
+
description:
|
|
125
|
+
"Create a prompt-local chronological candidate set from representative listening years.",
|
|
126
|
+
requires_time_capsule_services: true,
|
|
127
|
+
agent_tool: {
|
|
128
|
+
name: "moondog_time_capsule_candidates",
|
|
129
|
+
label: "Travel through your years",
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: "profile.back_to_back",
|
|
134
|
+
version: "1",
|
|
135
|
+
state: "enabled",
|
|
136
|
+
effect: "read_local",
|
|
137
|
+
description:
|
|
138
|
+
"Create a prompt-local playlist candidate set from bounded adjacent same-track sequences in retained Spotify Extended History.",
|
|
139
|
+
requires_back_to_back_services: true,
|
|
140
|
+
agent_tool: {
|
|
141
|
+
name: "moondog_back_to_back_candidates",
|
|
142
|
+
label: "Find music played back to back",
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: "profile.explain",
|
|
147
|
+
version: "1",
|
|
148
|
+
state: "enabled",
|
|
149
|
+
effect: "read_local",
|
|
150
|
+
description: "Explain one bounded profile evidence record.",
|
|
151
|
+
requires_profile_services: true,
|
|
152
|
+
agent_tool: {
|
|
153
|
+
name: "moondog_profile_explain",
|
|
154
|
+
label: "Look at why it's in your profile",
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: "playlist.plan",
|
|
159
|
+
version: "1",
|
|
160
|
+
state: "enabled",
|
|
161
|
+
effect: "derive_local",
|
|
162
|
+
description: "Validate and derive an inspectable in-memory playlist plan.",
|
|
163
|
+
requires_playlist_services: true,
|
|
164
|
+
agent_tool: {
|
|
165
|
+
name: "moondog_playlist_plan",
|
|
166
|
+
label: "Build a playlist plan",
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "music.catalog.artist_releases",
|
|
171
|
+
version: "1",
|
|
172
|
+
state: "enabled",
|
|
173
|
+
effect: "read_external",
|
|
174
|
+
description:
|
|
175
|
+
"Find dated artist releases in a bounded external music catalog.",
|
|
176
|
+
requires_music_catalog: true,
|
|
177
|
+
agent_tool: {
|
|
178
|
+
name: "moondog_music_artist_releases",
|
|
179
|
+
label: "Find current artist releases",
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: "music.catalog.track_search",
|
|
184
|
+
version: "1",
|
|
185
|
+
state: "enabled",
|
|
186
|
+
effect: "read_external",
|
|
187
|
+
description:
|
|
188
|
+
"Search bounded external catalog candidates and register them for prompt-local planning.",
|
|
189
|
+
requires_music_discovery: true,
|
|
190
|
+
agent_tool: {
|
|
191
|
+
name: "moondog_music_catalog_search",
|
|
192
|
+
label: "Search outside your library",
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
id: "music.discovery.artist_similarity",
|
|
197
|
+
version: "1",
|
|
198
|
+
state: "enabled",
|
|
199
|
+
effect: "read_external",
|
|
200
|
+
description:
|
|
201
|
+
"Find bounded external candidates through open listening-derived artist similarity.",
|
|
202
|
+
requires_music_similarity: true,
|
|
203
|
+
agent_tool: {
|
|
204
|
+
name: "moondog_music_artist_similarity",
|
|
205
|
+
label: "Find music nearby",
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
id: "memory.inspect",
|
|
210
|
+
version: "1",
|
|
211
|
+
state: "enabled",
|
|
212
|
+
effect: "read_local",
|
|
213
|
+
description: "Inspect short-term episodes and explicit long-term memory claims.",
|
|
214
|
+
requires_memory: true,
|
|
215
|
+
agent_tool: {
|
|
216
|
+
name: "moondog_memory_recall",
|
|
217
|
+
label: "Remember what you've told me",
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
id: "memory.remember",
|
|
222
|
+
version: "1",
|
|
223
|
+
state: "enabled",
|
|
224
|
+
effect: "write_local",
|
|
225
|
+
description:
|
|
226
|
+
"Persist a durable general fact, relationship preference, constraint, or goal explicitly stated by the user.",
|
|
227
|
+
requires_memory: true,
|
|
228
|
+
agent_tool: {
|
|
229
|
+
name: "moondog_memory_remember",
|
|
230
|
+
label: "Remember something you said",
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: "memory.forget",
|
|
235
|
+
version: "1",
|
|
236
|
+
state: "enabled",
|
|
237
|
+
effect: "write_local",
|
|
238
|
+
description: "Forget one explicit long-term memory when the user directly requests it.",
|
|
239
|
+
requires_memory: true,
|
|
240
|
+
agent_tool: {
|
|
241
|
+
name: "moondog_memory_forget",
|
|
242
|
+
label: "Forget something",
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
id: "spotify.history.import",
|
|
247
|
+
version: "1",
|
|
248
|
+
state: "enabled",
|
|
249
|
+
effect: "write_local",
|
|
250
|
+
description:
|
|
251
|
+
"Import Spotify Account Data or Extended Streaming History into private local music records.",
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
id: "spotify.player.status",
|
|
255
|
+
version: "1",
|
|
256
|
+
state: "enabled",
|
|
257
|
+
effect: "read_external",
|
|
258
|
+
description: "Inspect metadata-free Spotify playback state.",
|
|
259
|
+
requires_spotify: true,
|
|
260
|
+
agent_tool: {
|
|
261
|
+
name: "moondog_spotify_player_status",
|
|
262
|
+
label: "Check what Spotify is playing",
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
id: "spotify.player.control",
|
|
267
|
+
version: "1",
|
|
268
|
+
state: "enabled",
|
|
269
|
+
effect: "write_external",
|
|
270
|
+
description: "Control the active Spotify player after a direct user request.",
|
|
271
|
+
requires_spotify: true,
|
|
272
|
+
agent_tool: {
|
|
273
|
+
name: "moondog_spotify_player_control",
|
|
274
|
+
label: "Control Spotify playback",
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
id: "spotify.queue.add",
|
|
279
|
+
version: "1",
|
|
280
|
+
state: "enabled",
|
|
281
|
+
effect: "write_external",
|
|
282
|
+
description: "Add one explicit Spotify URI to the playback queue.",
|
|
283
|
+
requires_spotify: true,
|
|
284
|
+
agent_tool: {
|
|
285
|
+
name: "moondog_spotify_queue_add",
|
|
286
|
+
label: "Add to Spotify queue",
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: "spotify.device.transfer",
|
|
291
|
+
version: "1",
|
|
292
|
+
state: "enabled",
|
|
293
|
+
effect: "write_external",
|
|
294
|
+
description: "Transfer Spotify playback to an explicit device ID.",
|
|
295
|
+
requires_spotify: true,
|
|
296
|
+
agent_tool: {
|
|
297
|
+
name: "moondog_spotify_device_transfer",
|
|
298
|
+
label: "Move Spotify playback",
|
|
299
|
+
},
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: "spotify.catalog.resolve",
|
|
303
|
+
version: "1",
|
|
304
|
+
state: "enabled",
|
|
305
|
+
effect: "read_external",
|
|
306
|
+
description:
|
|
307
|
+
"Resolve trusted library tracks to deterministic Spotify catalog identities.",
|
|
308
|
+
requires_spotify: true,
|
|
309
|
+
requires_playlist_services: true,
|
|
310
|
+
agent_tool: {
|
|
311
|
+
name: "moondog_spotify_resolve_tracks",
|
|
312
|
+
label: "Find your songs on Spotify",
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: "spotify.library.check",
|
|
317
|
+
version: "1",
|
|
318
|
+
state: "enabled",
|
|
319
|
+
effect: "read_external",
|
|
320
|
+
description: "Check whether resolved tracks are already saved in the Spotify library.",
|
|
321
|
+
requires_spotify: true,
|
|
322
|
+
requires_playlist_services: true,
|
|
323
|
+
agent_tool: {
|
|
324
|
+
name: "moondog_spotify_library_check",
|
|
325
|
+
label: "Check Spotify saved tracks",
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
id: "spotify.library.save",
|
|
330
|
+
version: "1",
|
|
331
|
+
state: "enabled",
|
|
332
|
+
effect: "write_external",
|
|
333
|
+
description: "Save explicitly requested resolved tracks to the Spotify library.",
|
|
334
|
+
requires_spotify: true,
|
|
335
|
+
requires_playlist_services: true,
|
|
336
|
+
agent_tool: {
|
|
337
|
+
name: "moondog_spotify_library_save",
|
|
338
|
+
label: "Save tracks to Spotify library",
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
id: "spotify.playlist.read",
|
|
343
|
+
version: "1",
|
|
344
|
+
state: "enabled",
|
|
345
|
+
effect: "read_external",
|
|
346
|
+
description:
|
|
347
|
+
"List and inspect owned private Spotify playlists through prompt-local opaque references.",
|
|
348
|
+
requires_spotify: true,
|
|
349
|
+
agent_tool: {
|
|
350
|
+
name: "moondog_spotify_playlist_read",
|
|
351
|
+
label: "Look at your Spotify playlists",
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
id: "spotify.playlist.edit.preview",
|
|
356
|
+
version: "1",
|
|
357
|
+
state: "enabled",
|
|
358
|
+
effect: "derive_local",
|
|
359
|
+
description:
|
|
360
|
+
"Preview an exact existing-playlist rewrite without changing Spotify.",
|
|
361
|
+
requires_spotify: true,
|
|
362
|
+
agent_tool: {
|
|
363
|
+
name: "moondog_spotify_playlist_edit_preview",
|
|
364
|
+
label: "Preview a playlist change",
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
id: "spotify.playlist.edit.apply",
|
|
369
|
+
version: "1",
|
|
370
|
+
state: "enabled",
|
|
371
|
+
effect: "write_external",
|
|
372
|
+
description:
|
|
373
|
+
"Apply the exact host-retained Spotify playlist edit after later explicit confirmation.",
|
|
374
|
+
requires_spotify: true,
|
|
375
|
+
agent_tool: {
|
|
376
|
+
name: "moondog_spotify_playlist_edit_apply",
|
|
377
|
+
label: "Change a Spotify playlist",
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
id: "spotify.playlist.write",
|
|
382
|
+
version: "1",
|
|
383
|
+
state: "enabled",
|
|
384
|
+
effect: "write_external",
|
|
385
|
+
description:
|
|
386
|
+
"Create one private Spotify playlist from the exact validated playlist plan explicitly requested by the user.",
|
|
387
|
+
requires_spotify: true,
|
|
388
|
+
requires_playlist_services: true,
|
|
389
|
+
agent_tool: {
|
|
390
|
+
name: "moondog_spotify_playlist_write",
|
|
391
|
+
label: "Save the playlist to Spotify",
|
|
392
|
+
},
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
id: "music.generate",
|
|
396
|
+
version: "1",
|
|
397
|
+
state: "disabled",
|
|
398
|
+
effect: "spend_and_write_external",
|
|
399
|
+
description: "Call a music generation provider.",
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
id: "gateway.openclaw",
|
|
403
|
+
version: "1",
|
|
404
|
+
state: "deferred",
|
|
405
|
+
effect: "external_ingress_and_delivery",
|
|
406
|
+
description: "Expose Moondog through OpenClaw and Telegram.",
|
|
407
|
+
},
|
|
408
|
+
];
|
|
409
|
+
|
|
410
|
+
function withRuntimeAvailability(
|
|
411
|
+
capability,
|
|
412
|
+
domainServicesReady,
|
|
413
|
+
profileServicesReady,
|
|
414
|
+
playlistServicesReady,
|
|
415
|
+
rediscoveryReady,
|
|
416
|
+
historicalReturnReady,
|
|
417
|
+
timeCapsuleReady,
|
|
418
|
+
backToBackReady,
|
|
419
|
+
memoryReady,
|
|
420
|
+
spotifyReady,
|
|
421
|
+
musicCatalogReady,
|
|
422
|
+
musicDiscoveryReady,
|
|
423
|
+
musicSimilarityReady,
|
|
424
|
+
webResearchReady,
|
|
425
|
+
) {
|
|
426
|
+
if (capability.requires_web_research && !webResearchReady) {
|
|
427
|
+
return { ...capability, state: "blocked", blocked_by: "codex_web_not_ready" };
|
|
428
|
+
}
|
|
429
|
+
if (capability.requires_domain_services && !domainServicesReady) {
|
|
430
|
+
return {
|
|
431
|
+
...capability,
|
|
432
|
+
state: "blocked",
|
|
433
|
+
blocked_by: "agent_domain_services_not_ready",
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
if (capability.requires_profile_services && !profileServicesReady) {
|
|
437
|
+
return {
|
|
438
|
+
...capability,
|
|
439
|
+
state: "blocked",
|
|
440
|
+
blocked_by: "profile_services_not_ready",
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
if (capability.requires_playlist_services && !playlistServicesReady) {
|
|
444
|
+
return {
|
|
445
|
+
...capability,
|
|
446
|
+
state: "blocked",
|
|
447
|
+
blocked_by: "playlist_services_not_ready",
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
if (capability.requires_rediscovery_services && !rediscoveryReady) {
|
|
451
|
+
return {
|
|
452
|
+
...capability,
|
|
453
|
+
state: "blocked",
|
|
454
|
+
blocked_by: "listening_history_rediscovery_not_ready",
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
if (
|
|
458
|
+
capability.requires_historical_return_services &&
|
|
459
|
+
!historicalReturnReady
|
|
460
|
+
) {
|
|
461
|
+
return {
|
|
462
|
+
...capability,
|
|
463
|
+
state: "blocked",
|
|
464
|
+
blocked_by: "listening_history_historical_returns_not_ready",
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
if (capability.requires_time_capsule_services && !timeCapsuleReady) {
|
|
468
|
+
return {
|
|
469
|
+
...capability,
|
|
470
|
+
state: "blocked",
|
|
471
|
+
blocked_by: "listening_history_time_capsule_not_ready",
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
if (capability.requires_back_to_back_services && !backToBackReady) {
|
|
475
|
+
return {
|
|
476
|
+
...capability,
|
|
477
|
+
state: "blocked",
|
|
478
|
+
blocked_by: "listening_history_back_to_back_not_ready",
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
if (capability.requires_memory && !memoryReady) {
|
|
482
|
+
return {
|
|
483
|
+
...capability,
|
|
484
|
+
state: "blocked",
|
|
485
|
+
blocked_by: "persistent_memory_not_ready",
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
if (capability.requires_spotify && !spotifyReady) {
|
|
489
|
+
return {
|
|
490
|
+
...capability,
|
|
491
|
+
state: "blocked",
|
|
492
|
+
blocked_by: "spotify_connection_not_ready",
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
if (capability.requires_music_catalog && !musicCatalogReady) {
|
|
496
|
+
return {
|
|
497
|
+
...capability,
|
|
498
|
+
state: "blocked",
|
|
499
|
+
blocked_by: "music_catalog_not_ready",
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
if (capability.requires_music_discovery && !musicDiscoveryReady) {
|
|
503
|
+
return {
|
|
504
|
+
...capability,
|
|
505
|
+
state: "blocked",
|
|
506
|
+
blocked_by: "music_discovery_not_ready",
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
if (capability.requires_music_similarity && !musicSimilarityReady) {
|
|
510
|
+
return {
|
|
511
|
+
...capability,
|
|
512
|
+
state: "blocked",
|
|
513
|
+
blocked_by: "music_similarity_not_ready",
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
return capability;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function listCapabilities({
|
|
520
|
+
domainServicesReady = false,
|
|
521
|
+
profileServicesReady = domainServicesReady,
|
|
522
|
+
playlistServicesReady = domainServicesReady,
|
|
523
|
+
rediscoveryReady = false,
|
|
524
|
+
historicalReturnReady = false,
|
|
525
|
+
timeCapsuleReady = false,
|
|
526
|
+
backToBackReady = false,
|
|
527
|
+
memoryReady = false,
|
|
528
|
+
spotifyReady = false,
|
|
529
|
+
musicCatalogReady = false,
|
|
530
|
+
musicDiscoveryReady = false,
|
|
531
|
+
musicSimilarityReady = false,
|
|
532
|
+
webResearchReady = false,
|
|
533
|
+
} = {}) {
|
|
534
|
+
return structuredClone(
|
|
535
|
+
catalog.map((capability) =>
|
|
536
|
+
withRuntimeAvailability(
|
|
537
|
+
capability,
|
|
538
|
+
domainServicesReady,
|
|
539
|
+
profileServicesReady,
|
|
540
|
+
playlistServicesReady,
|
|
541
|
+
rediscoveryReady,
|
|
542
|
+
historicalReturnReady,
|
|
543
|
+
timeCapsuleReady,
|
|
544
|
+
backToBackReady,
|
|
545
|
+
memoryReady,
|
|
546
|
+
spotifyReady,
|
|
547
|
+
musicCatalogReady,
|
|
548
|
+
musicDiscoveryReady,
|
|
549
|
+
musicSimilarityReady,
|
|
550
|
+
webResearchReady,
|
|
551
|
+
),
|
|
552
|
+
),
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function listAgentCapabilityDescriptors(options = {}) {
|
|
557
|
+
return listCapabilities(options)
|
|
558
|
+
.filter(
|
|
559
|
+
(capability) =>
|
|
560
|
+
capability.state === "enabled" && capability.agent_tool,
|
|
561
|
+
)
|
|
562
|
+
.map((capability) => ({
|
|
563
|
+
capability_id: capability.id,
|
|
564
|
+
capability_version: capability.version,
|
|
565
|
+
effect: capability.effect,
|
|
566
|
+
tool_name: capability.agent_tool.name,
|
|
567
|
+
label: capability.agent_tool.label,
|
|
568
|
+
}));
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
export function getAgentCapabilityByToolName(toolName, options = {}) {
|
|
572
|
+
return (
|
|
573
|
+
listAgentCapabilityDescriptors(options).find(
|
|
574
|
+
(capability) => capability.tool_name === toolName,
|
|
575
|
+
) ?? null
|
|
576
|
+
);
|
|
577
|
+
}
|