@swarmclawai/swarmclaw 1.2.0 → 1.2.2

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 (241) hide show
  1. package/README.md +19 -0
  2. package/package.json +5 -2
  3. package/skills/coding-agent/SKILL.md +111 -0
  4. package/skills/github/SKILL.md +140 -0
  5. package/skills/nano-banana-pro/SKILL.md +62 -0
  6. package/skills/nano-banana-pro/scripts/generate_image.py +235 -0
  7. package/skills/nano-pdf/SKILL.md +53 -0
  8. package/skills/openai-image-gen/SKILL.md +78 -0
  9. package/skills/openai-image-gen/scripts/gen.py +328 -0
  10. package/skills/resourceful-problem-solving/SKILL.md +49 -0
  11. package/skills/skill-creator/SKILL.md +147 -0
  12. package/skills/skill-creator/scripts/init_skill.py +378 -0
  13. package/skills/skill-creator/scripts/quick_validate.py +159 -0
  14. package/skills/summarize/SKILL.md +77 -0
  15. package/src/app/api/auth/route.ts +20 -5
  16. package/src/app/api/chats/[id]/deploy/route.ts +11 -6
  17. package/src/app/api/chats/[id]/devserver/route.ts +17 -20
  18. package/src/app/api/chats/[id]/messages/route.ts +15 -11
  19. package/src/app/api/chats/[id]/route.ts +9 -10
  20. package/src/app/api/chats/[id]/stop/route.ts +5 -7
  21. package/src/app/api/chats/messages-route.test.ts +8 -6
  22. package/src/app/api/chats/route.ts +9 -10
  23. package/src/app/api/credentials/[id]/route.ts +4 -1
  24. package/src/app/api/extensions/marketplace/route.ts +5 -2
  25. package/src/app/api/ip/route.ts +2 -2
  26. package/src/app/api/memory/maintenance/route.ts +5 -2
  27. package/src/app/api/preview-server/route.ts +15 -12
  28. package/src/app/api/projects/[id]/route.ts +7 -46
  29. package/src/app/api/system/status/route.ts +11 -0
  30. package/src/app/api/upload/route.ts +4 -1
  31. package/src/cli/index.js +7 -0
  32. package/src/cli/spec.js +1 -0
  33. package/src/components/agents/agent-files-editor.tsx +44 -32
  34. package/src/components/agents/personality-builder.tsx +13 -7
  35. package/src/components/agents/trash-list.tsx +1 -1
  36. package/src/components/chat/chat-area.tsx +45 -23
  37. package/src/components/chat/message-bubble.test.ts +35 -0
  38. package/src/components/chat/message-bubble.tsx +20 -9
  39. package/src/components/chat/message-list.tsx +62 -42
  40. package/src/components/chat/swarm-status-card.tsx +10 -3
  41. package/src/components/input/chat-input.tsx +34 -14
  42. package/src/components/layout/daemon-indicator.tsx +7 -8
  43. package/src/components/layout/update-banner.tsx +8 -13
  44. package/src/components/logs/log-list.tsx +1 -1
  45. package/src/components/memory/memory-card.tsx +3 -1
  46. package/src/components/org-chart/org-chart-view.tsx +4 -0
  47. package/src/components/projects/project-list.tsx +4 -2
  48. package/src/components/projects/tabs/overview-tab.tsx +3 -2
  49. package/src/components/secrets/secret-sheet.tsx +1 -1
  50. package/src/components/secrets/secrets-list.tsx +1 -1
  51. package/src/components/shared/agent-switch-dialog.tsx +12 -6
  52. package/src/components/shared/dir-browser.tsx +22 -18
  53. package/src/components/skills/skill-sheet.tsx +2 -3
  54. package/src/components/tasks/task-list.tsx +1 -1
  55. package/src/components/tasks/task-sheet.tsx +1 -1
  56. package/src/hooks/use-openclaw-gateway.ts +46 -27
  57. package/src/instrumentation.ts +10 -7
  58. package/src/lib/chat/assistant-render-id.ts +3 -0
  59. package/src/lib/chat/chat-streaming-state.test.ts +42 -3
  60. package/src/lib/chat/chat-streaming-state.ts +20 -8
  61. package/src/lib/chat/chat.ts +18 -2
  62. package/src/lib/chat/queued-message-queue.test.ts +23 -1
  63. package/src/lib/chat/queued-message-queue.ts +11 -2
  64. package/src/lib/providers/anthropic.ts +6 -3
  65. package/src/lib/providers/claude-cli.ts +9 -3
  66. package/src/lib/providers/cli-utils.test.ts +124 -0
  67. package/src/lib/providers/cli-utils.ts +15 -0
  68. package/src/lib/providers/codex-cli.ts +9 -3
  69. package/src/lib/providers/gemini-cli.ts +6 -2
  70. package/src/lib/providers/index.ts +4 -1
  71. package/src/lib/providers/ollama.ts +5 -2
  72. package/src/lib/providers/openai.ts +8 -5
  73. package/src/lib/providers/opencode-cli.ts +6 -2
  74. package/src/lib/server/activity/activity-log.ts +21 -0
  75. package/src/lib/server/agents/agent-availability.test.ts +10 -5
  76. package/src/lib/server/agents/agent-cascade.ts +79 -59
  77. package/src/lib/server/agents/agent-registry.ts +23 -4
  78. package/src/lib/server/agents/agent-repository.ts +90 -0
  79. package/src/lib/server/agents/delegation-job-repository.ts +53 -0
  80. package/src/lib/server/agents/delegation-jobs.ts +11 -4
  81. package/src/lib/server/agents/guardian-checkpoint-repository.ts +35 -0
  82. package/src/lib/server/agents/guardian.ts +2 -2
  83. package/src/lib/server/agents/main-agent-loop.ts +14 -6
  84. package/src/lib/server/agents/main-loop-state-repository.ts +38 -0
  85. package/src/lib/server/agents/subagent-runtime.ts +9 -6
  86. package/src/lib/server/agents/subagent-swarm.ts +3 -2
  87. package/src/lib/server/agents/task-session.ts +3 -4
  88. package/src/lib/server/approvals/approval-repository.ts +30 -0
  89. package/src/lib/server/autonomy/supervisor-incident-repository.ts +42 -0
  90. package/src/lib/server/autonomy/supervisor-reflection.ts +14 -1
  91. package/src/lib/server/chat-execution/chat-execution-types.ts +38 -0
  92. package/src/lib/server/chat-execution/chat-execution-utils.ts +1 -1
  93. package/src/lib/server/chat-execution/chat-execution.ts +84 -1914
  94. package/src/lib/server/chat-execution/chat-turn-finalization.ts +620 -0
  95. package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +221 -0
  96. package/src/lib/server/chat-execution/chat-turn-preflight.ts +133 -0
  97. package/src/lib/server/chat-execution/chat-turn-preparation.ts +817 -0
  98. package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +296 -0
  99. package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +5 -5
  100. package/src/lib/server/chat-execution/continuation-evaluator.ts +4 -3
  101. package/src/lib/server/chat-execution/continuation-limits.ts +6 -3
  102. package/src/lib/server/chat-execution/message-classifier.test.ts +329 -0
  103. package/src/lib/server/chat-execution/message-classifier.ts +5 -2
  104. package/src/lib/server/chat-execution/post-stream-finalization.ts +5 -2
  105. package/src/lib/server/chat-execution/prompt-builder.ts +22 -1
  106. package/src/lib/server/chat-execution/prompt-sections.ts +55 -13
  107. package/src/lib/server/chat-execution/response-completeness.ts +5 -2
  108. package/src/lib/server/chat-execution/situational-awareness.ts +12 -7
  109. package/src/lib/server/chat-execution/stream-agent-chat.ts +58 -25
  110. package/src/lib/server/chatrooms/chatroom-memory-bridge.ts +6 -3
  111. package/src/lib/server/chatrooms/chatroom-repository.ts +32 -0
  112. package/src/lib/server/connectors/bluebubbles.ts +7 -4
  113. package/src/lib/server/connectors/connector-inbound.ts +16 -13
  114. package/src/lib/server/connectors/connector-lifecycle.ts +11 -8
  115. package/src/lib/server/connectors/connector-outbound.ts +6 -3
  116. package/src/lib/server/connectors/connector-repository.ts +58 -0
  117. package/src/lib/server/connectors/discord.ts +10 -7
  118. package/src/lib/server/connectors/email.ts +17 -14
  119. package/src/lib/server/connectors/googlechat.ts +7 -4
  120. package/src/lib/server/connectors/inbound-audio-transcription.ts +5 -2
  121. package/src/lib/server/connectors/matrix.ts +6 -3
  122. package/src/lib/server/connectors/openclaw.ts +20 -17
  123. package/src/lib/server/connectors/outbox.ts +4 -1
  124. package/src/lib/server/connectors/runtime-state.test.ts +117 -0
  125. package/src/lib/server/connectors/runtime-state.ts +19 -0
  126. package/src/lib/server/connectors/session-consolidation.ts +5 -2
  127. package/src/lib/server/connectors/signal.ts +9 -6
  128. package/src/lib/server/connectors/slack.ts +13 -10
  129. package/src/lib/server/connectors/teams.ts +8 -5
  130. package/src/lib/server/connectors/telegram.ts +15 -12
  131. package/src/lib/server/connectors/whatsapp.ts +32 -29
  132. package/src/lib/server/credentials/credential-repository.ts +7 -0
  133. package/src/lib/server/embeddings.ts +4 -1
  134. package/src/lib/server/gateways/gateway-profile-repository.ts +4 -0
  135. package/src/lib/server/link-understanding.ts +4 -1
  136. package/src/lib/server/memory/memory-abstract.test.ts +59 -0
  137. package/src/lib/server/memory/memory-abstract.ts +59 -0
  138. package/src/lib/server/memory/memory-db.ts +40 -14
  139. package/src/lib/server/missions/mission-repository.ts +74 -0
  140. package/src/lib/server/missions/mission-service/actions.ts +6 -0
  141. package/src/lib/server/missions/mission-service/bindings.ts +9 -0
  142. package/src/lib/server/missions/mission-service/context.ts +4 -0
  143. package/src/lib/server/missions/mission-service/core.ts +2269 -0
  144. package/src/lib/server/missions/mission-service/queries.ts +12 -0
  145. package/src/lib/server/missions/mission-service/recovery.ts +5 -0
  146. package/src/lib/server/missions/mission-service/ticks.ts +9 -0
  147. package/src/lib/server/missions/mission-service.test.ts +9 -2
  148. package/src/lib/server/missions/mission-service.ts +6 -2263
  149. package/src/lib/server/openclaw/gateway.ts +8 -5
  150. package/src/lib/server/persistence/repository-utils.ts +154 -0
  151. package/src/lib/server/persistence/storage-context.ts +51 -0
  152. package/src/lib/server/persistence/transaction.ts +1 -0
  153. package/src/lib/server/project-utils.ts +13 -0
  154. package/src/lib/server/projects/project-repository.ts +36 -0
  155. package/src/lib/server/projects/project-service.ts +79 -0
  156. package/src/lib/server/protocols/protocol-agent-turn.ts +5 -2
  157. package/src/lib/server/protocols/protocol-normalization.test.ts +6 -4
  158. package/src/lib/server/protocols/protocol-run-lifecycle.ts +5 -2
  159. package/src/lib/server/protocols/protocol-step-helpers.ts +4 -1
  160. package/src/lib/server/provider-health.ts +18 -0
  161. package/src/lib/server/query-expansion.ts +4 -1
  162. package/src/lib/server/runtime/alert-dispatch.ts +8 -7
  163. package/src/lib/server/runtime/daemon-policy.ts +1 -1
  164. package/src/lib/server/runtime/daemon-state/core.ts +1570 -0
  165. package/src/lib/server/runtime/daemon-state/health.ts +6 -0
  166. package/src/lib/server/runtime/daemon-state/policy.ts +7 -0
  167. package/src/lib/server/runtime/daemon-state/supervisor.ts +6 -0
  168. package/src/lib/server/runtime/daemon-state.test.ts +48 -0
  169. package/src/lib/server/runtime/daemon-state.ts +3 -1331
  170. package/src/lib/server/runtime/estop-repository.ts +4 -0
  171. package/src/lib/server/runtime/estop.ts +3 -1
  172. package/src/lib/server/runtime/heartbeat-service.test.ts +2 -2
  173. package/src/lib/server/runtime/heartbeat-service.ts +78 -34
  174. package/src/lib/server/runtime/heartbeat-wake.ts +6 -4
  175. package/src/lib/server/runtime/idle-window.ts +6 -3
  176. package/src/lib/server/runtime/network.ts +11 -0
  177. package/src/lib/server/runtime/orchestrator-events.ts +2 -2
  178. package/src/lib/server/runtime/perf.ts +4 -1
  179. package/src/lib/server/runtime/process-manager.ts +7 -4
  180. package/src/lib/server/runtime/queue/claims.ts +4 -0
  181. package/src/lib/server/runtime/queue/core.ts +2079 -0
  182. package/src/lib/server/runtime/queue/execution.ts +7 -0
  183. package/src/lib/server/runtime/queue/followups.ts +4 -0
  184. package/src/lib/server/runtime/queue/queries.ts +12 -0
  185. package/src/lib/server/runtime/queue/recovery.ts +7 -0
  186. package/src/lib/server/runtime/queue-recovery.test.ts +48 -13
  187. package/src/lib/server/runtime/queue-repository.ts +17 -0
  188. package/src/lib/server/runtime/queue.ts +5 -2058
  189. package/src/lib/server/runtime/run-ledger.ts +6 -5
  190. package/src/lib/server/runtime/run-repository.ts +73 -0
  191. package/src/lib/server/runtime/runtime-lock-repository.ts +8 -0
  192. package/src/lib/server/runtime/runtime-settings.ts +1 -1
  193. package/src/lib/server/runtime/runtime-state.ts +99 -0
  194. package/src/lib/server/runtime/scheduler.ts +13 -8
  195. package/src/lib/server/runtime/session-run-manager/cancellation.ts +157 -0
  196. package/src/lib/server/runtime/session-run-manager/drain.ts +246 -0
  197. package/src/lib/server/runtime/session-run-manager/enqueue.ts +287 -0
  198. package/src/lib/server/runtime/session-run-manager/queries.ts +117 -0
  199. package/src/lib/server/runtime/session-run-manager/recovery.ts +238 -0
  200. package/src/lib/server/runtime/session-run-manager/state.ts +441 -0
  201. package/src/lib/server/runtime/session-run-manager/types.ts +74 -0
  202. package/src/lib/server/runtime/session-run-manager.ts +72 -1374
  203. package/src/lib/server/runtime/watch-job-repository.ts +35 -0
  204. package/src/lib/server/runtime/watch-jobs.ts +3 -1
  205. package/src/lib/server/sandbox/bridge-auth-registry.ts +6 -0
  206. package/src/lib/server/sandbox/novnc-auth.ts +10 -0
  207. package/src/lib/server/schedules/schedule-repository.ts +42 -0
  208. package/src/lib/server/session-tools/context.ts +14 -0
  209. package/src/lib/server/session-tools/discovery.ts +9 -6
  210. package/src/lib/server/session-tools/index.ts +3 -1
  211. package/src/lib/server/session-tools/platform.ts +1 -1
  212. package/src/lib/server/session-tools/subagent.ts +23 -2
  213. package/src/lib/server/session-tools/wallet.ts +4 -1
  214. package/src/lib/server/sessions/session-repository.ts +85 -0
  215. package/src/lib/server/settings/settings-repository.ts +25 -0
  216. package/src/lib/server/skills/clawhub-client.ts +4 -1
  217. package/src/lib/server/skills/runtime-skill-resolver.ts +8 -2
  218. package/src/lib/server/skills/skill-discovery.test.ts +2 -2
  219. package/src/lib/server/skills/skill-discovery.ts +2 -2
  220. package/src/lib/server/skills/skill-eligibility.ts +6 -0
  221. package/src/lib/server/skills/skill-repository.ts +14 -0
  222. package/src/lib/server/solana.ts +6 -0
  223. package/src/lib/server/storage-auth.ts +5 -5
  224. package/src/lib/server/storage-normalization.ts +4 -0
  225. package/src/lib/server/storage.ts +32 -32
  226. package/src/lib/server/tasks/task-followups.ts +4 -1
  227. package/src/lib/server/tasks/task-repository.ts +54 -0
  228. package/src/lib/server/tool-loop-detection.ts +8 -3
  229. package/src/lib/server/tool-planning.ts +226 -0
  230. package/src/lib/server/tool-retry.ts +4 -3
  231. package/src/lib/server/usage/usage-repository.ts +30 -0
  232. package/src/lib/server/wallet/wallet-portfolio.ts +29 -0
  233. package/src/lib/server/webhooks/webhook-repository.ts +10 -0
  234. package/src/lib/server/ws-hub.ts +5 -2
  235. package/src/lib/strip-internal-metadata.test.ts +78 -37
  236. package/src/lib/strip-internal-metadata.ts +20 -6
  237. package/src/stores/use-approval-store.ts +7 -1
  238. package/src/stores/use-chat-store.test.ts +54 -0
  239. package/src/stores/use-chat-store.ts +26 -6
  240. package/src/types/index.ts +6 -0
  241. /package/{bundled-skills → skills}/google-workspace/SKILL.md +0 -0
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: openai-image-gen
3
+ description: Generate images via OpenAI Images API (GPT Image, DALL-E 3, DALL-E 2). Supports batch generation with random prompt sampler and HTML gallery output. Use when asked to generate images with OpenAI and an OPENAI_API_KEY is available.
4
+ metadata:
5
+ {
6
+ "openclaw":
7
+ {
8
+ "emoji": "🎨",
9
+ "requires": { "bins": ["python3"], "env": ["OPENAI_API_KEY"] },
10
+ "primaryEnv": "OPENAI_API_KEY",
11
+ "install":
12
+ [
13
+ {
14
+ "id": "python-brew",
15
+ "kind": "brew",
16
+ "formula": "python",
17
+ "bins": ["python3"],
18
+ "label": "Install Python (brew)",
19
+ },
20
+ ],
21
+ },
22
+ }
23
+ ---
24
+
25
+ # OpenAI Image Gen
26
+
27
+ Generate images via the OpenAI Images API with an HTML gallery viewer.
28
+
29
+ ## Run
30
+
31
+ Note: Image generation can take longer than typical timeouts. Set a higher timeout when running via shell (e.g., 300 seconds).
32
+
33
+ ```bash
34
+ python3 {baseDir}/scripts/gen.py
35
+ ```
36
+
37
+ ## Useful Flags
38
+
39
+ ```bash
40
+ # GPT image models with various options
41
+ python3 {baseDir}/scripts/gen.py --count 16 --model gpt-image-1
42
+ python3 {baseDir}/scripts/gen.py --prompt "ultra-detailed studio photo of a lobster astronaut" --count 4
43
+ python3 {baseDir}/scripts/gen.py --size 1536x1024 --quality high --out-dir ./out/images
44
+ python3 {baseDir}/scripts/gen.py --model gpt-image-1.5 --background transparent --output-format webp
45
+
46
+ # DALL-E 3 (note: count is automatically limited to 1)
47
+ python3 {baseDir}/scripts/gen.py --model dall-e-3 --quality hd --size 1792x1024 --style vivid
48
+ python3 {baseDir}/scripts/gen.py --model dall-e-3 --style natural --prompt "serene mountain landscape"
49
+
50
+ # DALL-E 2
51
+ python3 {baseDir}/scripts/gen.py --model dall-e-2 --size 512x512 --count 4
52
+ ```
53
+
54
+ ## Model-Specific Parameters
55
+
56
+ ### Size
57
+
58
+ - **GPT image models** (`gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`): `1024x1024`, `1536x1024` (landscape), `1024x1536` (portrait), or `auto`. Default: `1024x1024`
59
+ - **dall-e-3**: `1024x1024`, `1792x1024`, or `1024x1792`. Default: `1024x1024`
60
+ - **dall-e-2**: `256x256`, `512x512`, or `1024x1024`. Default: `1024x1024`
61
+
62
+ ### Quality
63
+
64
+ - **GPT image models**: `auto`, `high`, `medium`, or `low`. Default: `high`
65
+ - **dall-e-3**: `hd` or `standard`. Default: `standard`
66
+ - **dall-e-2**: `standard` only
67
+
68
+ ### Other Parameters
69
+
70
+ - **GPT image models** support `--background` (`transparent`, `opaque`, `auto`) and `--output-format` (`png`, `jpeg`, `webp`)
71
+ - **dall-e-3** supports `--style` (`vivid` for hyper-real, `natural` for more natural looking)
72
+ - **dall-e-3** only supports `n=1`; the script automatically limits count to 1
73
+
74
+ ## Output
75
+
76
+ - Image files (`*.png`, `*.jpeg`, or `*.webp` depending on model and format)
77
+ - `prompts.json` (prompt-to-file mapping)
78
+ - `index.html` (thumbnail gallery — open in browser to review)
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import base64
4
+ import datetime as dt
5
+ import json
6
+ import os
7
+ import random
8
+ import re
9
+ import sys
10
+ import urllib.error
11
+ import urllib.request
12
+ from collections.abc import Callable
13
+ from html import escape as html_escape
14
+ from pathlib import Path
15
+
16
+
17
+ def slugify(text: str) -> str:
18
+ text = text.lower().strip()
19
+ text = re.sub(r"[^a-z0-9]+", "-", text)
20
+ text = re.sub(r"-{2,}", "-", text).strip("-")
21
+ return text or "image"
22
+
23
+
24
+ def default_out_dir() -> Path:
25
+ now = dt.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
26
+ preferred = Path.home() / "Projects" / "tmp"
27
+ base = preferred if preferred.is_dir() else Path("./tmp")
28
+ base.mkdir(parents=True, exist_ok=True)
29
+ return base / f"openai-image-gen-{now}"
30
+
31
+
32
+ def pick_prompts(count: int) -> list[str]:
33
+ subjects = [
34
+ "a lobster astronaut",
35
+ "a brutalist lighthouse",
36
+ "a cozy reading nook",
37
+ "a cyberpunk noodle shop",
38
+ "a Vienna street at dusk",
39
+ "a minimalist product photo",
40
+ "a surreal underwater library",
41
+ ]
42
+ styles = [
43
+ "ultra-detailed studio photo",
44
+ "35mm film still",
45
+ "isometric illustration",
46
+ "editorial photography",
47
+ "soft watercolor",
48
+ "architectural render",
49
+ "high-contrast monochrome",
50
+ ]
51
+ lighting = [
52
+ "golden hour",
53
+ "overcast soft light",
54
+ "neon lighting",
55
+ "dramatic rim light",
56
+ "candlelight",
57
+ "foggy atmosphere",
58
+ ]
59
+ prompts: list[str] = []
60
+ for _ in range(count):
61
+ prompts.append(
62
+ f"{random.choice(styles)} of {random.choice(subjects)}, {random.choice(lighting)}"
63
+ )
64
+ return prompts
65
+
66
+
67
+ def get_model_defaults(model: str) -> tuple[str, str]:
68
+ """Return (default_size, default_quality) for the given model."""
69
+ if model == "dall-e-2":
70
+ # quality will be ignored
71
+ return ("1024x1024", "standard")
72
+ elif model == "dall-e-3":
73
+ return ("1024x1024", "standard")
74
+ else:
75
+ # GPT image or future models
76
+ return ("1024x1024", "high")
77
+
78
+
79
+ def normalize_optional_flag(
80
+ *,
81
+ model: str,
82
+ raw_value: str,
83
+ flag_name: str,
84
+ supported: Callable[[str], bool],
85
+ allowed: set[str],
86
+ allowed_text: str,
87
+ unsupported_message: str,
88
+ aliases: dict[str, str] | None = None,
89
+ ) -> str:
90
+ """Normalize a string flag, warn when unsupported, and reject invalid values."""
91
+ value = raw_value.strip().lower()
92
+ if not value:
93
+ return ""
94
+
95
+ if not supported(model):
96
+ print(unsupported_message.format(model=model), file=sys.stderr)
97
+ return ""
98
+
99
+ if aliases:
100
+ value = aliases.get(value, value)
101
+
102
+ if value not in allowed:
103
+ raise ValueError(
104
+ f"Invalid --{flag_name} '{raw_value}'. Allowed values: {allowed_text}."
105
+ )
106
+ return value
107
+
108
+
109
+ def normalize_background(model: str, background: str) -> str:
110
+ """Validate --background for GPT image models."""
111
+ return normalize_optional_flag(
112
+ model=model,
113
+ raw_value=background,
114
+ flag_name="background",
115
+ supported=lambda candidate: candidate.startswith("gpt-image"),
116
+ allowed={"transparent", "opaque", "auto"},
117
+ allowed_text="transparent, opaque, auto",
118
+ unsupported_message=(
119
+ "Warning: --background is only supported for gpt-image models; "
120
+ "ignoring for '{model}'."
121
+ ),
122
+ )
123
+
124
+
125
+ def normalize_style(model: str, style: str) -> str:
126
+ """Validate --style for dall-e-3."""
127
+ return normalize_optional_flag(
128
+ model=model,
129
+ raw_value=style,
130
+ flag_name="style",
131
+ supported=lambda candidate: candidate == "dall-e-3",
132
+ allowed={"vivid", "natural"},
133
+ allowed_text="vivid, natural",
134
+ unsupported_message=(
135
+ "Warning: --style is only supported for dall-e-3; ignoring for '{model}'."
136
+ ),
137
+ )
138
+
139
+
140
+ def normalize_output_format(model: str, output_format: str) -> str:
141
+ """Normalize output format for GPT image models and validate allowed values."""
142
+ return normalize_optional_flag(
143
+ model=model,
144
+ raw_value=output_format,
145
+ flag_name="output-format",
146
+ supported=lambda candidate: candidate.startswith("gpt-image"),
147
+ allowed={"png", "jpeg", "webp"},
148
+ allowed_text="png, jpeg, webp",
149
+ unsupported_message=(
150
+ "Warning: --output-format is only supported for gpt-image models; "
151
+ "ignoring for '{model}'."
152
+ ),
153
+ aliases={"jpg": "jpeg"},
154
+ )
155
+
156
+
157
+ def request_images(
158
+ api_key: str,
159
+ prompt: str,
160
+ model: str,
161
+ size: str,
162
+ quality: str,
163
+ background: str = "",
164
+ output_format: str = "",
165
+ style: str = "",
166
+ ) -> dict:
167
+ url = "https://api.openai.com/v1/images/generations"
168
+ args = {
169
+ "model": model,
170
+ "prompt": prompt,
171
+ "size": size,
172
+ "n": 1,
173
+ }
174
+
175
+ # Quality parameter - dall-e-2 doesn't accept this parameter
176
+ if model != "dall-e-2":
177
+ args["quality"] = quality
178
+
179
+ # Note: response_format no longer supported by OpenAI Images API
180
+ # dall-e models now return URLs by default
181
+
182
+ if model.startswith("gpt-image"):
183
+ if background:
184
+ args["background"] = background
185
+ if output_format:
186
+ args["output_format"] = output_format
187
+
188
+ if model == "dall-e-3" and style:
189
+ args["style"] = style
190
+
191
+ body = json.dumps(args).encode("utf-8")
192
+ req = urllib.request.Request(
193
+ url,
194
+ method="POST",
195
+ headers={
196
+ "Authorization": f"Bearer {api_key}",
197
+ "Content-Type": "application/json",
198
+ },
199
+ data=body,
200
+ )
201
+ try:
202
+ with urllib.request.urlopen(req, timeout=300) as resp:
203
+ return json.loads(resp.read().decode("utf-8"))
204
+ except urllib.error.HTTPError as e:
205
+ payload = e.read().decode("utf-8", errors="replace")
206
+ raise RuntimeError(f"OpenAI Images API failed ({e.code}): {payload}") from e
207
+
208
+
209
+ def write_gallery(out_dir: Path, items: list[dict]) -> None:
210
+ thumbs = "\n".join(
211
+ [
212
+ f"""
213
+ <figure>
214
+ <a href="{html_escape(it["file"], quote=True)}"><img src="{html_escape(it["file"], quote=True)}" loading="lazy" /></a>
215
+ <figcaption>{html_escape(it["prompt"])}</figcaption>
216
+ </figure>
217
+ """.strip()
218
+ for it in items
219
+ ]
220
+ )
221
+ html = f"""<!doctype html>
222
+ <meta charset="utf-8" />
223
+ <title>openai-image-gen</title>
224
+ <style>
225
+ :root {{ color-scheme: dark; }}
226
+ body {{ margin: 24px; font: 14px/1.4 ui-sans-serif, system-ui; background: #0b0f14; color: #e8edf2; }}
227
+ h1 {{ font-size: 18px; margin: 0 0 16px; }}
228
+ .grid {{ display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; }}
229
+ figure {{ margin: 0; padding: 12px; border: 1px solid #1e2a36; border-radius: 14px; background: #0f1620; }}
230
+ img {{ width: 100%; height: auto; border-radius: 10px; display: block; }}
231
+ figcaption {{ margin-top: 10px; color: #b7c2cc; }}
232
+ code {{ color: #9cd1ff; }}
233
+ </style>
234
+ <h1>openai-image-gen</h1>
235
+ <p>Output: <code>{html_escape(out_dir.as_posix())}</code></p>
236
+ <div class="grid">
237
+ {thumbs}
238
+ </div>
239
+ """
240
+ (out_dir / "index.html").write_text(html, encoding="utf-8")
241
+
242
+
243
+ def main() -> int:
244
+ ap = argparse.ArgumentParser(description="Generate images via OpenAI Images API.")
245
+ ap.add_argument("--prompt", help="Single prompt. If omitted, random prompts are generated.")
246
+ ap.add_argument("--count", type=int, default=8, help="How many images to generate.")
247
+ ap.add_argument("--model", default="gpt-image-1", help="Image model id.")
248
+ ap.add_argument("--size", default="", help="Image size (e.g. 1024x1024, 1536x1024). Defaults based on model if not specified.")
249
+ ap.add_argument("--quality", default="", help="Image quality (e.g. high, standard). Defaults based on model if not specified.")
250
+ ap.add_argument("--background", default="", help="Background transparency (GPT models only): transparent, opaque, or auto.")
251
+ ap.add_argument("--output-format", default="", help="Output format (GPT models only): png, jpeg, or webp.")
252
+ ap.add_argument("--style", default="", help="Image style (dall-e-3 only): vivid or natural.")
253
+ ap.add_argument("--out-dir", default="", help="Output directory (default: ./tmp/openai-image-gen-<ts>).")
254
+ args = ap.parse_args()
255
+
256
+ api_key = (os.environ.get("OPENAI_API_KEY") or "").strip()
257
+ if not api_key:
258
+ print("Missing OPENAI_API_KEY", file=sys.stderr)
259
+ return 2
260
+
261
+ # Apply model-specific defaults if not specified
262
+ default_size, default_quality = get_model_defaults(args.model)
263
+ size = args.size or default_size
264
+ quality = args.quality or default_quality
265
+
266
+ count = args.count
267
+ if args.model == "dall-e-3" and count > 1:
268
+ print(f"Warning: dall-e-3 only supports generating 1 image at a time. Reducing count from {count} to 1.", file=sys.stderr)
269
+ count = 1
270
+
271
+ out_dir = Path(args.out_dir).expanduser() if args.out_dir else default_out_dir()
272
+ out_dir.mkdir(parents=True, exist_ok=True)
273
+
274
+ prompts = [args.prompt] * count if args.prompt else pick_prompts(count)
275
+
276
+ try:
277
+ normalized_background = normalize_background(args.model, args.background)
278
+ normalized_style = normalize_style(args.model, args.style)
279
+ normalized_output_format = normalize_output_format(args.model, args.output_format)
280
+ except ValueError as e:
281
+ print(str(e), file=sys.stderr)
282
+ return 2
283
+
284
+ # Determine file extension based on output format
285
+ if args.model.startswith("gpt-image") and normalized_output_format:
286
+ file_ext = normalized_output_format
287
+ else:
288
+ file_ext = "png"
289
+
290
+ items: list[dict] = []
291
+ for idx, prompt in enumerate(prompts, start=1):
292
+ print(f"[{idx}/{len(prompts)}] {prompt}")
293
+ res = request_images(
294
+ api_key,
295
+ prompt,
296
+ args.model,
297
+ size,
298
+ quality,
299
+ normalized_background,
300
+ normalized_output_format,
301
+ normalized_style,
302
+ )
303
+ data = res.get("data", [{}])[0]
304
+ image_b64 = data.get("b64_json")
305
+ image_url = data.get("url")
306
+ if not image_b64 and not image_url:
307
+ raise RuntimeError(f"Unexpected response: {json.dumps(res)[:400]}")
308
+
309
+ filename = f"{idx:03d}-{slugify(prompt)[:40]}.{file_ext}"
310
+ filepath = out_dir / filename
311
+ if image_b64:
312
+ filepath.write_bytes(base64.b64decode(image_b64))
313
+ else:
314
+ try:
315
+ urllib.request.urlretrieve(image_url, filepath)
316
+ except urllib.error.URLError as e:
317
+ raise RuntimeError(f"Failed to download image from {image_url}: {e}") from e
318
+
319
+ items.append({"prompt": prompt, "file": filename})
320
+
321
+ (out_dir / "prompts.json").write_text(json.dumps(items, indent=2), encoding="utf-8")
322
+ write_gallery(out_dir, items)
323
+ print(f"\nWrote: {(out_dir / 'index.html').as_posix()}")
324
+ return 0
325
+
326
+
327
+ if __name__ == "__main__":
328
+ raise SystemExit(main())
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: resourceful-problem-solving
3
+ description: Always-on guidance for solving tasks resourcefully. Teaches agents to escalate through skills, CLI tools, and custom scripts instead of refusing. Applies to any request where the agent lacks a dedicated tool.
4
+ always: true
5
+ ---
6
+
7
+ # Resourceful Problem Solving
8
+
9
+ When asked to do something and no dedicated tool exists, follow this escalation pattern:
10
+
11
+ ## 1. Check Skills
12
+
13
+ Use `use_skill` to search for a matching skill. Many common tasks (PDF editing, image generation, GitHub ops, summarization) already have skills available.
14
+
15
+ ## 2. Search for a CLI Tool
16
+
17
+ If no skill matches, check whether a CLI tool exists:
18
+
19
+ ```bash
20
+ which <tool> # already installed?
21
+ brew search <tool> # macOS
22
+ pip search <tool> # Python ecosystem
23
+ npm search <tool> # Node ecosystem
24
+ ```
25
+
26
+ If a suitable tool exists, install it and use it.
27
+
28
+ ## 3. Write a Script
29
+
30
+ If no CLI tool fits, write a short script (Python, Node, or bash) to accomplish the task. Common patterns:
31
+
32
+ - **PDF creation**: Use Python `reportlab` or `fpdf2`
33
+ - **Image manipulation**: Use Python `Pillow`
34
+ - **Spreadsheets**: Use Python `openpyxl` or `csv`
35
+ - **Data conversion**: Use `jq`, `csvkit`, or a short Python script
36
+ - **Web scraping**: Use `curl` + parsing or Python `requests` + `beautifulsoup4`
37
+
38
+ Install dependencies as needed: `pip install <package>` or `npm install <package>`.
39
+
40
+ ## 4. Save for Reuse
41
+
42
+ If the script solves a task that's likely to come up again, offer to save it as a reusable extension via the `extension_creator` tool.
43
+
44
+ ## Rules
45
+
46
+ - Never refuse a task when shell tools are available. Attempt a code-based solution first.
47
+ - Only report inability after genuinely trying and failing.
48
+ - Prefer lightweight, well-known packages over complex bespoke solutions.
49
+ - Always verify the output before reporting success.
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: skill-creator
3
+ description: Create, edit, improve, or audit skills for SwarmClaw agents. Use when creating a new skill from scratch or when asked to improve, review, audit, tidy up, or clean up an existing skill or SKILL.md file. Also use when editing or restructuring a skill directory. Triggers on phrases like "create a skill", "author a skill", "tidy up a skill", "improve this skill", "review the skill", "clean up the skill", "audit the skill".
4
+ ---
5
+
6
+ # Skill Creator
7
+
8
+ Guidance for creating effective skills that extend SwarmClaw agent capabilities.
9
+
10
+ ## About Skills
11
+
12
+ Skills are modular, self-contained packages that provide specialized knowledge, workflows, and tools. They transform a general-purpose agent into a specialized one equipped with procedural knowledge that no model can fully possess.
13
+
14
+ ### What Skills Provide
15
+
16
+ 1. Specialized workflows — multi-step procedures for specific domains
17
+ 2. Tool integrations — instructions for working with specific file formats or APIs
18
+ 3. Domain expertise — company-specific knowledge, schemas, business logic
19
+ 4. Bundled resources — scripts, references, and assets for complex and repetitive tasks
20
+
21
+ ## Core Principles
22
+
23
+ ### Concise is Key
24
+
25
+ The context window is a shared resource. Only add context the agent doesn't already have. Challenge each piece of information: "Does the agent really need this explanation?" Prefer concise examples over verbose explanations.
26
+
27
+ ### Set Appropriate Degrees of Freedom
28
+
29
+ - **High freedom** (text instructions): Multiple valid approaches, context-dependent decisions
30
+ - **Medium freedom** (pseudocode/parameterized scripts): Preferred pattern exists, some variation OK
31
+ - **Low freedom** (specific scripts): Fragile operations, consistency critical, exact sequence required
32
+
33
+ ### Anatomy of a Skill
34
+
35
+ ```
36
+ skill-name/
37
+ ├── SKILL.md (required)
38
+ │ ├── YAML frontmatter (name + description, required)
39
+ │ └── Markdown instructions (required)
40
+ └── Bundled Resources (optional)
41
+ ├── scripts/ — Executable code (Python/Bash/etc.)
42
+ ├── references/ — Documentation loaded into context as needed
43
+ └── assets/ — Files used in output (templates, icons, fonts)
44
+ ```
45
+
46
+ #### Frontmatter
47
+
48
+ - `name`: Skill name (hyphen-case, lowercase)
49
+ - `description`: Primary triggering mechanism. Include what the skill does AND when to use it. All "when to use" info goes here — not in the body.
50
+
51
+ #### Scripts (`scripts/`)
52
+
53
+ Executable code for tasks that require deterministic reliability or are repeatedly rewritten. Token efficient and may be executed without loading into context.
54
+
55
+ #### References (`references/`)
56
+
57
+ Documentation loaded as needed to inform the agent's process. Keep only essential instructions in SKILL.md; move detailed reference material here.
58
+
59
+ #### Assets (`assets/`)
60
+
61
+ Files not loaded into context but used in output (templates, images, fonts). Separates output resources from documentation.
62
+
63
+ ### What NOT to Include
64
+
65
+ - README.md, CHANGELOG.md, INSTALLATION_GUIDE.md, or other auxiliary docs
66
+ - Setup/testing procedures or user-facing documentation
67
+ - Information the agent already knows from general training
68
+
69
+ ## Skill Creation Process
70
+
71
+ 1. Understand the skill with concrete examples
72
+ 2. Plan reusable contents (scripts, references, assets)
73
+ 3. Initialize the skill
74
+ 4. Edit the skill (implement resources, write SKILL.md)
75
+ 5. Validate the skill
76
+ 6. Iterate based on real usage
77
+
78
+ ### Skill Naming
79
+
80
+ - Lowercase letters, digits, and hyphens only (hyphen-case)
81
+ - Under 64 characters
82
+ - Prefer short, verb-led phrases describing the action
83
+ - Name the skill folder exactly after the skill name
84
+
85
+ ### Step 1: Understanding with Concrete Examples
86
+
87
+ Ask the user clarifying questions:
88
+
89
+ - What functionality should the skill support?
90
+ - Can you give examples of how it would be used?
91
+ - What would a user say that should trigger this skill?
92
+
93
+ ### Step 2: Planning Reusable Contents
94
+
95
+ Analyze each example to identify what scripts, references, and assets would be helpful:
96
+
97
+ - **Repeated code** → `scripts/` (e.g., `scripts/rotate_pdf.py`)
98
+ - **Boilerplate** → `assets/` (e.g., `assets/hello-world/` template)
99
+ - **Domain knowledge** → `references/` (e.g., `references/schema.md`)
100
+
101
+ ### Step 3: Initializing the Skill
102
+
103
+ Use the bundled init script to create the directory structure:
104
+
105
+ ```bash
106
+ python3 {baseDir}/scripts/init_skill.py <skill-name> --path <output-directory> [--resources scripts,references,assets] [--examples]
107
+ ```
108
+
109
+ Examples:
110
+
111
+ ```bash
112
+ python3 {baseDir}/scripts/init_skill.py my-skill --path skills
113
+ python3 {baseDir}/scripts/init_skill.py my-skill --path skills --resources scripts,references
114
+ ```
115
+
116
+ ### Step 4: Edit the Skill
117
+
118
+ Write instructions that would help another agent instance execute tasks effectively. Include information that is beneficial and non-obvious.
119
+
120
+ **Writing guidelines:** Use imperative/infinitive form. Keep SKILL.md body under 500 lines.
121
+
122
+ **Frontmatter description:** Include both what the skill does and specific triggers for when to use it. This is the primary mechanism for skill selection.
123
+
124
+ ### Step 5: Validate the Skill
125
+
126
+ Run the validator to check structure and frontmatter:
127
+
128
+ ```bash
129
+ python3 {baseDir}/scripts/quick_validate.py <path/to/skill-folder>
130
+ ```
131
+
132
+ ### Step 6: Iterate
133
+
134
+ 1. Use the skill on real tasks
135
+ 2. Notice struggles or inefficiencies
136
+ 3. Update SKILL.md or bundled resources
137
+ 4. Test again
138
+
139
+ ## Progressive Disclosure
140
+
141
+ Skills use a three-level loading system:
142
+
143
+ 1. **Metadata** (name + description) — always in context (~100 words)
144
+ 2. **SKILL.md body** — when skill triggers (<5k words)
145
+ 3. **Bundled resources** — as needed (unlimited, since scripts can be executed without reading)
146
+
147
+ Keep SKILL.md lean. Move detailed information to reference files and describe clearly when to read them.