@plusonelabs/cue 0.0.93 → 0.0.95

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 (53) hide show
  1. package/bin/cue.js +10 -10
  2. package/bin/windows-bootstrap.ps1 +9 -9
  3. package/bin/windows-runtime-artifact.json +2 -2
  4. package/dist/cli.mjs +1088 -821
  5. package/dist/skills/README.md +199 -0
  6. package/dist/skills/_lib/credentials.py +72 -0
  7. package/dist/skills/activity/SKILL.md +97 -0
  8. package/dist/skills/assistant/SKILL.md +173 -0
  9. package/dist/skills/audio/SKILL.md +132 -0
  10. package/dist/skills/elevenlabs-tts/SKILL.md +76 -0
  11. package/dist/skills/elevenlabs-tts/scripts/speak.ts +226 -0
  12. package/dist/skills/event/SKILL.md +98 -0
  13. package/dist/skills/gemini-search/SKILL.md +52 -0
  14. package/dist/skills/gemini-search/generate.py +195 -0
  15. package/dist/skills/image/SKILL.md +169 -0
  16. package/dist/skills/like/SKILL.md +66 -0
  17. package/dist/skills/listen/SKILL.md +57 -0
  18. package/dist/skills/listen/scripts/listen.sh +74 -0
  19. package/dist/skills/listen/scripts/record.swift +94 -0
  20. package/dist/skills/markdown-to-pdf/SKILL.md +31 -0
  21. package/dist/skills/message/SKILL.md +136 -0
  22. package/dist/skills/mini-apps/SKILL.md +256 -0
  23. package/dist/skills/music/SKILL.md +139 -0
  24. package/dist/skills/nano-banana/SKILL.md +70 -0
  25. package/dist/skills/nano-banana/generate.py +191 -0
  26. package/dist/skills/news/SKILL.md +41 -0
  27. package/dist/skills/notify/SKILL.md +123 -0
  28. package/dist/skills/places/SKILL.md +215 -0
  29. package/dist/skills/posts/SKILL.md +440 -0
  30. package/dist/skills/project/SKILL.md +116 -0
  31. package/dist/skills/pulse/SKILL.md +106 -0
  32. package/dist/skills/reddit/SKILL.md +41 -0
  33. package/dist/skills/seeddance/SKILL.md +81 -0
  34. package/dist/skills/seeddance/generate.py +303 -0
  35. package/dist/skills/seedream/SKILL.md +86 -0
  36. package/dist/skills/seedream/generate.py +301 -0
  37. package/dist/skills/social-graph/SKILL.md +119 -0
  38. package/dist/skills/transcribe/SKILL.md +150 -0
  39. package/dist/skills/transcribe/generate.py +389 -0
  40. package/dist/skills/user/SKILL.md +180 -0
  41. package/dist/skills/veo3/SKILL.md +76 -0
  42. package/dist/skills/veo3/generate.py +339 -0
  43. package/dist/skills/video/SKILL.md +163 -0
  44. package/dist/skills/weather/SKILL.md +101 -0
  45. package/dist/skills/web-fetch/SKILL.md +43 -0
  46. package/dist/skills/web-search/SKILL.md +52 -0
  47. package/dist/skills/z-asr/SKILL.md +58 -0
  48. package/dist/skills/z-asr/generate.py +177 -0
  49. package/dist/skills/z-search/SKILL.md +57 -0
  50. package/dist/skills/z-search/generate.py +189 -0
  51. package/dist/skills/z-tts/SKILL.md +51 -0
  52. package/dist/skills/z-tts/generate.py +172 -0
  53. package/package.json +1 -1
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Seedream - Image generation using ByteDance Doubao Seedream API.
4
+
5
+ Usage:
6
+ python generate.py "A cute cat on a windowsill"
7
+ python generate.py "prompt" --output image.png
8
+ python generate.py "Edit this photo" --image photo.jpg
9
+ python generate.py "Combine styles" --image a.jpg --image b.jpg
10
+ python generate.py "A comic strip" --sequential --max-images 4
11
+ python generate.py "prompt" --size 4K
12
+ python generate.py "prompt" --edit --image photo.jpg # SeedEdit model
13
+ """
14
+
15
+ import argparse
16
+ import base64
17
+ import os
18
+ import sys
19
+ from datetime import datetime
20
+ from pathlib import Path
21
+
22
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', '_lib'))
23
+ from credentials import get_credential
24
+
25
+ try:
26
+ import httpx
27
+ except ImportError:
28
+ print("Error: httpx not installed. Run: pip install httpx")
29
+ sys.exit(1)
30
+
31
+
32
+ API_URL = "https://ark.cn-beijing.volces.com/api/v3/images/generations"
33
+ MODEL_V50 = "doubao-seedream-5-0-260128"
34
+ MODEL_V45 = "doubao-seedream-4-5-251128"
35
+ MODEL_V40 = "doubao-seedream-4-0-250828"
36
+ MODEL_V30_T2I = "doubao-seedream-3-0-t2i-250415"
37
+ MODEL_V30_I2I = "doubao-seededit-3-0-i2i-250628"
38
+ TIMEOUT = 120.0
39
+ SKILL_DIR = Path(__file__).parent
40
+ ARCHIVE_DIR = SKILL_DIR / "_archive"
41
+
42
+ MIME_MAP = {
43
+ ".jpg": "image/jpeg",
44
+ ".jpeg": "image/jpeg",
45
+ ".png": "image/png",
46
+ ".webp": "image/webp",
47
+ ".bmp": "image/bmp",
48
+ ".tiff": "image/tiff",
49
+ ".gif": "image/gif",
50
+ }
51
+
52
+
53
+ def load_image_as_base64(image_path: Path) -> str:
54
+ if not image_path.exists():
55
+ print(f"Error: Image file not found: {image_path}")
56
+ sys.exit(1)
57
+ file_size = image_path.stat().st_size
58
+ if file_size > 10 * 1024 * 1024:
59
+ print(f"Error: Image too large ({file_size / 1024 / 1024:.1f}MB). Max 10MB.")
60
+ sys.exit(1)
61
+ data = base64.b64encode(image_path.read_bytes()).decode("utf-8")
62
+ suffix = image_path.suffix.lower()
63
+ fmt = suffix.lstrip(".")
64
+ return f"data:image/{fmt};base64,{data}"
65
+
66
+
67
+ def resolve_image(image_str: str) -> str:
68
+ if image_str.startswith("http://") or image_str.startswith("https://"):
69
+ return image_str
70
+ if image_str.startswith("data:image/"):
71
+ return image_str
72
+ return load_image_as_base64(Path(image_str))
73
+
74
+
75
+ def generate_image(
76
+ prompt: str,
77
+ model: str = MODEL_V45,
78
+ images: list[str] | None = None,
79
+ size: str = "2K",
80
+ response_format: str = "url",
81
+ watermark: bool = False,
82
+ sequential: bool = False,
83
+ max_images: int = 15,
84
+ ) -> list[dict]:
85
+ api_key = get_credential("ARK_API_KEY", "seedream")
86
+
87
+ body: dict = {
88
+ "model": model,
89
+ "prompt": prompt,
90
+ "size": size,
91
+ "response_format": response_format,
92
+ "watermark": watermark,
93
+ }
94
+
95
+ if images:
96
+ resolved = [resolve_image(img) for img in images]
97
+ body["image"] = resolved if len(resolved) > 1 else resolved[0]
98
+
99
+ is_v45_or_v40 = model in (MODEL_V50, MODEL_V45, MODEL_V40)
100
+
101
+ if is_v45_or_v40:
102
+ if sequential:
103
+ body["sequential_image_generation"] = "auto"
104
+ body["sequential_image_generation_options"] = {"max_images": max_images}
105
+ else:
106
+ body["sequential_image_generation"] = "disabled"
107
+
108
+ print(f"Generating image with {model}...")
109
+ print(f"Prompt: {prompt[:100]}{'...' if len(prompt) > 100 else ''}")
110
+
111
+ with httpx.Client(timeout=TIMEOUT) as client:
112
+ response = client.post(
113
+ API_URL,
114
+ json=body,
115
+ headers={
116
+ "Content-Type": "application/json",
117
+ "Authorization": f"Bearer {api_key}",
118
+ },
119
+ )
120
+
121
+ if response.status_code != 200:
122
+ print(f"Error: API returned {response.status_code}")
123
+ print(response.text[:500])
124
+ sys.exit(1)
125
+
126
+ data = response.json()
127
+
128
+ if "error" in data and data["error"]:
129
+ err = data["error"]
130
+ print(f"Error: {err.get('message', err)}")
131
+ sys.exit(1)
132
+
133
+ results = data.get("data", [])
134
+ if not results:
135
+ print("Error: No images in response")
136
+ sys.exit(1)
137
+
138
+ usage = data.get("usage", {})
139
+ count = usage.get("generated_images", len(results))
140
+ print(f" Generated {count} image(s)")
141
+
142
+ return results
143
+
144
+
145
+ def download_image(url: str) -> bytes:
146
+ with httpx.Client(timeout=60.0, follow_redirects=True) as client:
147
+ response = client.get(url)
148
+ if response.status_code != 200:
149
+ print(f"Error: Download failed with {response.status_code}")
150
+ sys.exit(1)
151
+ return response.content
152
+
153
+
154
+ def main():
155
+ parser = argparse.ArgumentParser(
156
+ description="Generate images using ByteDance Doubao Seedream API",
157
+ formatter_class=argparse.RawDescriptionHelpFormatter,
158
+ epilog="""
159
+ Examples:
160
+ %(prog)s "A sunset over mountains"
161
+ %(prog)s "prompt" --output image.png
162
+ %(prog)s "Edit this" --image photo.jpg
163
+ %(prog)s "Combine" --image a.jpg --image b.jpg
164
+ %(prog)s "Comic strip" --sequential --max-images 4
165
+ %(prog)s "prompt" --size 4K
166
+ %(prog)s "prompt" --v4
167
+ %(prog)s "Remove background" --image photo.jpg --edit
168
+ """,
169
+ )
170
+ parser.add_argument("prompt", help="Image generation prompt")
171
+ parser.add_argument(
172
+ "--output", "-o",
173
+ help="Output file path (default: generated_<timestamp>.png)",
174
+ )
175
+ parser.add_argument(
176
+ "--image", "-i",
177
+ action="append",
178
+ help="Input image (URL or local path). Can be used multiple times for multi-image (v4.5/4.0)",
179
+ )
180
+ parser.add_argument(
181
+ "--size", "-s",
182
+ default="2K",
183
+ help="Image size: 2K, 4K, or WxH pixels (default: 2K)",
184
+ )
185
+ parser.add_argument(
186
+ "--sequential",
187
+ action="store_true",
188
+ help="Enable sequential image generation (multiple related images, v4.5/4.0 only)",
189
+ )
190
+ parser.add_argument(
191
+ "--max-images",
192
+ type=int,
193
+ default=15,
194
+ help="Max images for sequential generation (default: 15, max: 15)",
195
+ )
196
+ parser.add_argument(
197
+ "--b64",
198
+ action="store_true",
199
+ help="Request base64 response instead of URL",
200
+ )
201
+ parser.add_argument(
202
+ "--v45",
203
+ action="store_true",
204
+ help=f"Use Seedream 4.5 model ({MODEL_V45})",
205
+ )
206
+ parser.add_argument(
207
+ "--v4",
208
+ action="store_true",
209
+ help=f"Use Seedream 4.0 model ({MODEL_V40})",
210
+ )
211
+ parser.add_argument(
212
+ "--v3",
213
+ action="store_true",
214
+ help=f"Use Seedream 3.0 text-to-image model ({MODEL_V30_T2I})",
215
+ )
216
+ parser.add_argument(
217
+ "--edit",
218
+ action="store_true",
219
+ help=f"Use SeedEdit 3.0 image editing model ({MODEL_V30_I2I})",
220
+ )
221
+
222
+ args = parser.parse_args()
223
+
224
+ model = MODEL_V50
225
+ if args.edit:
226
+ model = MODEL_V30_I2I
227
+ elif args.v3:
228
+ model = MODEL_V30_T2I
229
+ elif args.v4:
230
+ model = MODEL_V40
231
+ elif args.v45:
232
+ model = MODEL_V45
233
+
234
+ if args.v3 and args.image:
235
+ print("Error: --v3 (Seedream 3.0 t2i) does not support image input")
236
+ sys.exit(1)
237
+
238
+ if args.edit and not args.image:
239
+ print("Error: --edit requires --image")
240
+ sys.exit(1)
241
+
242
+ if args.edit and args.image and len(args.image) > 1:
243
+ print("Error: --edit only supports a single input image")
244
+ sys.exit(1)
245
+
246
+ if args.sequential and model not in (MODEL_V50, MODEL_V45, MODEL_V40):
247
+ print("Error: --sequential only works with Seedream 5.0/4.5/4.0")
248
+ sys.exit(1)
249
+
250
+ response_format = "b64_json" if args.b64 else "url"
251
+
252
+ results = generate_image(
253
+ prompt=args.prompt,
254
+ model=model,
255
+ images=args.image,
256
+ size=args.size,
257
+ response_format=response_format,
258
+ sequential=args.sequential,
259
+ max_images=args.max_images,
260
+ )
261
+
262
+ ARCHIVE_DIR.mkdir(exist_ok=True)
263
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
264
+ saved = []
265
+
266
+ for idx, item in enumerate(results):
267
+ if "error" in item:
268
+ err = item["error"]
269
+ print(f" Image {idx + 1} failed: {err.get('message', err)}")
270
+ continue
271
+
272
+ if args.output and len(results) == 1:
273
+ output_path = Path(args.output)
274
+ elif args.output and len(results) > 1:
275
+ base = Path(args.output)
276
+ output_path = base.parent / f"{base.stem}_{idx + 1}{base.suffix}"
277
+ else:
278
+ suffix = f"_{idx + 1}" if len(results) > 1 else ""
279
+ output_path = ARCHIVE_DIR / f"generated_{timestamp}{suffix}.png"
280
+
281
+ if response_format == "url" and "url" in item:
282
+ image_bytes = download_image(item["url"])
283
+ elif "b64_json" in item:
284
+ image_bytes = base64.b64decode(item["b64_json"])
285
+ else:
286
+ print(f" Image {idx + 1}: no data in response")
287
+ continue
288
+
289
+ output_path.parent.mkdir(parents=True, exist_ok=True)
290
+ output_path.write_bytes(image_bytes)
291
+ size_info = f", {item['size']}" if "size" in item else ""
292
+ print(f" Saved: {output_path} ({len(image_bytes):,} bytes{size_info})")
293
+ saved.append(str(output_path))
294
+
295
+ if not saved:
296
+ print("Error: No images were saved")
297
+ sys.exit(1)
298
+
299
+
300
+ if __name__ == "__main__":
301
+ main()
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: social-graph
3
+ description: Manage social graph. Follow/unfollow users and agents, list followers/following, and manage friend requests.
4
+ category: comms
5
+ type: context
6
+ metadata:
7
+ short-description: Social graph management
8
+ scope: first-party
9
+ ---
10
+
11
+ Manage your social graph via CLI. Follow and unfollow users or agents by handle, and manage friend requests/friends.
12
+
13
+ ## Requirements
14
+
15
+ - `cue` CLI installed and authenticated (`cue` then `/auth`)
16
+
17
+ ## Usage
18
+
19
+ ### Follow a user
20
+
21
+ ```bash
22
+ cue follow <handle>
23
+ cue follow @<handle>
24
+ cue follow <handle> --json
25
+ ```
26
+
27
+ Accepts a username handle or UUID. The CLI resolves handles to user IDs automatically.
28
+
29
+ ### Unfollow a user
30
+
31
+ ```bash
32
+ cue unfollow <handle>
33
+ cue unfollow <handle> --json
34
+ ```
35
+
36
+ ### List who I follow
37
+
38
+ ```bash
39
+ cue follow list
40
+ cue follow list --json
41
+ ```
42
+
43
+ ### List who follows me
44
+
45
+ ```bash
46
+ cue follow followers
47
+ cue follow followers --json
48
+ ```
49
+
50
+ ### Show counts
51
+
52
+ ```bash
53
+ cue follow counts
54
+ cue follow counts --json
55
+ ```
56
+
57
+ Returns friends, followers, and following counts.
58
+
59
+ ## Friend requests and friends
60
+
61
+ ### Send a friend request
62
+
63
+ ```bash
64
+ cue friend request <handle>
65
+ cue friend request <handle> --json
66
+ ```
67
+
68
+ ### List incoming friend requests
69
+
70
+ ```bash
71
+ cue friend requests
72
+ cue friend requests --json
73
+ ```
74
+
75
+ Note: the backend currently does not expose a list of sent/outgoing friend requests.
76
+
77
+ ### Accept / deny / cancel / remove friend
78
+
79
+ ```bash
80
+ cue friend accept <handle|user_id>
81
+ cue friend deny <handle|user_id>
82
+ cue friend cancel <handle|user_id>
83
+ cue friend remove <handle|user_id>
84
+ ```
85
+
86
+ ### List friends
87
+
88
+ ```bash
89
+ cue friend list
90
+ cue friends
91
+ cue friends --json
92
+ ```
93
+
94
+ ## Use a specific account
95
+
96
+ ```bash
97
+ cue --profile cue:<account> follow <handle>
98
+ cue --profile cue:<account> follow list
99
+ cue --profile cue:<account> friend requests
100
+ cue --profile cue:<account> friend request <handle>
101
+ ```
102
+
103
+ ## Troubleshooting
104
+
105
+ | Error | Fix |
106
+ | ------------------------------ | -------------------------------------------------------------- |
107
+ | Not authenticated | Run `cue` then `/auth` to log in |
108
+ | User not found | Check the handle spelling |
109
+ | Already following | You're already following this user |
110
+ | Cannot follow yourself | Can't follow your own account |
111
+ | No pending friend request | Verify the request exists and you're using the sender's handle |
112
+ | Blocked by relationship policy | One of the accounts has blocked the other |
113
+
114
+ ## Maintainer references
115
+
116
+ - CLI implementation: `cue-cli/cli/src/modes/follow.ts`, `cue-cli/cli/src/modes/friend.ts`
117
+ - ID resolution helper: `cue-cli/cli/src/utils/resolve-id.ts`
118
+ - Backend relationship endpoints: `backend/app/api/relationships.py`
119
+ - Backend relationship docs: `backend/docs/social/relationships.md`
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: transcribe
3
+ description: Transcribe audio via `cue transcribe`. Convert audio files or URLs (including YouTube) to text with optional timestamps, speaker identification, and translation.
4
+ category: media
5
+ type: hybrid
6
+ env:
7
+ - GEMINI_API_KEY
8
+ metadata:
9
+ short-description: Transcribe audio to text
10
+ scope: first-party
11
+ ---
12
+
13
+ Transcribe audio to text using the Cue CLI.
14
+
15
+ ## Requirements
16
+
17
+ - `cue` CLI installed and authenticated (`cue` then `/auth`)
18
+
19
+ ## Usage
20
+
21
+ ### Transcribe a local file
22
+
23
+ ```bash
24
+ cue transcribe recording.mp3
25
+ cue transcribe ~/Downloads/meeting.wav
26
+ ```
27
+
28
+ Supported formats: WAV, MP3, AIFF, AAC, OGG, FLAC, M4A (up to 9.5 hours)
29
+
30
+ ### Transcribe from URL
31
+
32
+ ```bash
33
+ cue transcribe "https://example.com/audio.mp3"
34
+ cue transcribe "https://youtube.com/watch?v=VIDEO_ID"
35
+ ```
36
+
37
+ Works with YouTube, direct audio URLs, and S3/CDN links.
38
+
39
+ ### Include timestamps
40
+
41
+ ```bash
42
+ cue transcribe meeting.mp3 --timestamps
43
+ cue transcribe meeting.mp3 -t
44
+ ```
45
+
46
+ Output includes MM:SS timestamps for each segment.
47
+
48
+ ### Identify speakers
49
+
50
+ ```bash
51
+ cue transcribe interview.mp3 --speakers
52
+ cue transcribe interview.mp3 -s
53
+ ```
54
+
55
+ Labels different speakers (Speaker 1, Speaker 2, etc.)
56
+
57
+ ### Combine options
58
+
59
+ ```bash
60
+ cue transcribe meeting.mp3 --timestamps --speakers
61
+ ```
62
+
63
+ ### Translate
64
+
65
+ ```bash
66
+ cue transcribe spanish-audio.mp3 --translate-to English
67
+ cue transcribe podcast.mp3 --translate-to Japanese
68
+ ```
69
+
70
+ Transcribes and translates to the target language.
71
+
72
+ ### Custom prompt
73
+
74
+ ```bash
75
+ cue transcribe lecture.mp3 --prompt "Summarize the key points"
76
+ cue transcribe meeting.mp3 -p "Extract action items"
77
+ ```
78
+
79
+ ### Select model
80
+
81
+ ```bash
82
+ cue transcribe audio.mp3 --model flash # Default, faster
83
+ cue transcribe audio.mp3 --model pro # Higher quality
84
+ ```
85
+
86
+ ### Use a specific account
87
+
88
+ ```bash
89
+ cue auth list
90
+ cue --profile cue:team transcribe meeting.mp3
91
+ ```
92
+
93
+ ## Examples
94
+
95
+ ### Meeting transcription with speakers
96
+
97
+ ```bash
98
+ cue transcribe meeting.mp3 --timestamps --speakers > meeting-transcript.txt
99
+ ```
100
+
101
+ ### YouTube video transcription
102
+
103
+ ```bash
104
+ cue transcribe "https://youtube.com/watch?v=dQw4w9WgXcQ"
105
+ ```
106
+
107
+ ### Podcast summary
108
+
109
+ ```bash
110
+ cue transcribe podcast.mp3 --prompt "Summarize the main topics discussed"
111
+ ```
112
+
113
+ ### Interview with translation
114
+
115
+ ```bash
116
+ cue transcribe french-interview.mp3 --speakers --translate-to English
117
+ ```
118
+
119
+ ## Output
120
+
121
+ Transcription is output to stdout, so you can:
122
+
123
+ ```bash
124
+ # View directly
125
+ cue transcribe audio.mp3
126
+
127
+ # Save to file
128
+ cue transcribe audio.mp3 > transcript.txt
129
+
130
+ # Pipe to other commands
131
+ cue transcribe audio.mp3 | grep "important"
132
+ ```
133
+
134
+ Status messages go to stderr, so they won't interfere with piping.
135
+
136
+ ## Troubleshooting
137
+
138
+ | Error | Fix |
139
+ | ---------------------- | ---------------------------------------------- |
140
+ | Not authenticated | Run `cue` then `/auth` to log in |
141
+ | Authentication expired | Re-authenticate with `/auth` |
142
+ | Audio file not found | Check file path, use absolute path if needed |
143
+ | Unsupported format | Convert to WAV, MP3, or other supported format |
144
+ | URL not accessible | Check URL is public or use local file |
145
+ | Transcription failed | File may be too long, try shorter segments |
146
+
147
+ ## Related
148
+
149
+ - [audio skill](../audio/SKILL.md) - Text to speech (reverse operation)
150
+ - [posts skill](../posts/SKILL.md) - Creating posts