first commit

This commit is contained in:
jeremygan2021
2026-03-04 19:24:05 +08:00
commit f5117a90d1
28 changed files with 1647 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
# No environment variables are required for this skill.

51
agent-creator/SKILL.md Normal file
View File

@@ -0,0 +1,51 @@
---
name: agent-creator
description: Create new OpenCode agents with a gpt-5.2-codex default.
---
## Quick Usage (Already Configured)
### Create a project agent
```bash
opencode agent create
```
### Agent file locations
- Project agents: `.opencode/agents/<name>.md`
- Global agents: `~/.config/opencode/agents/<name>.md`
## Default model
Use `gpt-5.2-codex` as the default model for new agents unless a workflow needs a different model.
## Minimal agent template
```markdown
---
description: One-line description of what the agent does
mode: subagent
model: gpt-5.2-codex
tools:
write: false
edit: false
bash: false
---
You are a specialized agent. Describe your task, boundaries, and expected output.
```
## Notes from OpenCode docs
- Agent files are markdown with YAML frontmatter.
- The markdown filename becomes the agent name.
- Set `mode` to `primary`, `subagent`, or `all`.
- If no model is specified, subagents inherit the caller model.
- `tools` controls per-agent tool access.
## Reference
Follow the official OpenCode agent docs: https://opencode.ai/docs/agents/
## First-Time Setup (If Not Configured)
1. Run `opencode agent create` and choose project scope.
2. Paste in the default template above and adjust tools as needed.

3
agent-creator/client.ts Normal file
View File

@@ -0,0 +1,3 @@
export type AgentCreatorClient = Record<string, never>;
export const client: AgentCreatorClient = {};

View File

@@ -0,0 +1,10 @@
import { config } from "./load-env";
async function main() {
void config;
console.log("agent-creator: no credentials required.");
}
main().catch((error) => {
console.error(error);
});

View File

@@ -0,0 +1,3 @@
export type AgentCreatorConfig = Record<string, never>;
export const config: AgentCreatorConfig = {};

View File

@@ -0,0 +1 @@
# No environment variables are required for this skill.

View File

@@ -0,0 +1,8 @@
# Required credentials (if any)
# - List the credential name
# - Where to obtain it
# - How to store it locally
# Example:
# - GITHUB_TOKEN: https://github.com/settings/tokens
# - Store in .env (gitignored)

352
command-creator/SKILL.md Normal file
View File

@@ -0,0 +1,352 @@
---
name: command-creator
description: Create OpenCode custom commands for repeatable tasks.
---
## Quick Usage (Already Configured)
### Create a new command file
```bash
mkdir -p .opencode/commands
```
Create `.opencode/commands/<name>.md` with frontmatter and a prompt template.
### Command file example
```
---
description: Run tests with coverage
agent: build
model: gpt-5.2-codex
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
```
## Prompt config essentials
- Use `$ARGUMENTS` for all arguments, or `$1`, `$2`, `$3` for positional args.
- Use `!\`command\`` to inject shell output into the prompt.
- Use `@path/to/file` to include file contents in the prompt.
## Notes from OpenCode docs
- Command files live in `.opencode/commands/` (project) or `~/.config/opencode/commands/` (global).
- The markdown filename becomes the command name (e.g., `test.md``/test`).
- JSON config also supports commands in `opencode.json` under `command`.
- Custom commands can override built-ins like `/init`, `/undo`, `/redo`, `/share`, `/help`.
## Reference
Follow the official OpenCode command docs: https://opencode.ai/docs/commands/
Use the docs as the escape hatch when unsure.
## Docs snapshot
Skip to content
OpenCode
Search
K
Intro
Config
Providers
Network
Enterprise
Troubleshooting
Migrating to 1.0
TUI
CLI
Web
IDE
Zen
Share
GitHub
GitLab
Tools
Rules
Agents
Models
Themes
Keybinds
Commands
Formatters
Permissions
LSP Servers
MCP servers
ACP Support
Agent Skills
Custom Tools
SDK
Server
Plugins
Ecosystem
On this page
Overview
Create command files
Configure
JSON
Markdown
Prompt config
Arguments
Shell output
File references
Options
Template
Description
Agent
Subtask
Model
Built-in
Commands
Create custom commands for repetitive tasks.
Custom commands let you specify a prompt you want to run when that command is executed in the TUI.
/my-command
Custom commands are in addition to the built-in commands like /init, /undo, /redo, /share, /help. Learn more.
Create command files
Create markdown files in the commands/ directory to define custom commands.
Create .opencode/commands/test.md:
.opencode/commands/test.md
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
The frontmatter defines command properties. The content becomes the template.
Use the command by typing / followed by the command name.
"/test"
Configure
You can add custom commands through the OpenCode config or by creating markdown files in the commands/ directory.
JSON
Use the command option in your OpenCode config:
opencode.jsonc
{
"$schema": "https://opencode.ai/config.json",
"command": {
// This becomes the name of the command
"test": {
// This is the prompt that will be sent to the LLM
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes.",
// This is shown as the description in the TUI
"description": "Run tests with coverage",
"agent": "build",
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
Now you can run this command in the TUI:
/test
Markdown
You can also define commands using markdown files. Place them in:
Global: ~/.config/opencode/commands/
Per-project: .opencode/commands/
~/.config/opencode/commands/test.md
---
description: Run tests with coverage
agent: build
model: anthropic/claude-3-5-sonnet-20241022
---
Run the full test suite with coverage report and show any failures.
Focus on the failing tests and suggest fixes.
The markdown file name becomes the command name. For example, test.md lets you run:
/test
Prompt config
The prompts for the custom commands support several special placeholders and syntax.
Arguments
Pass arguments to commands using the $ARGUMENTS placeholder.
.opencode/commands/component.md
---
description: Create a new component
---
Create a new React component named $ARGUMENTS with TypeScript support.
Include proper typing and basic structure.
Run the command with arguments:
/component Button
And $ARGUMENTS will be replaced with Button.
You can also access individual arguments using positional parameters:
$1 - First argument
$2 - Second argument
$3 - Third argument
And so on…
For example:
.opencode/commands/create-file.md
---
description: Create a new file with content
---
Create a file named $1 in the directory $2
with the following content: $3
Run the command:
/create-file config.json src "{ \"key\": \"value\" }"
This replaces:
$1 with config.json
$2 with src
$3 with { "key": "value" }
Shell output
Use !command to inject bash command output into your prompt.
For example, to create a custom command that analyzes test coverage:
.opencode/commands/analyze-coverage.md
---
description: Analyze test coverage
---
Here are the current test results:
!`npm test`
Based on these results, suggest improvements to increase coverage.
Or to review recent changes:
.opencode/commands/review-changes.md
---
description: Review recent changes
---
Recent git commits:
!`git log --oneline -10`
Review these changes and suggest any improvements.
Commands run in your projects root directory and theutput becomes part of the prompt.
File references
Include files in your command using @ followed by the filename.
.opencode/commands/review-component.md
---
description: Review component
---
Review the component in @src/components/Button.tsx.
Check for performance issues and suggest improvements.
The file content gets included in the prompt automatically.
Options
Lets look at the configuration options in detail.
Template
The template option defines the prompt that will be sent to the LLM when the command is executed.
opencode.json
{
"command": {
"test": {
"template": "Run the full test suite with coverage report and show any failures.\nFocus on the failing tests and suggest fixes."
}
}
}
This is a required config option.
Description
Use the description option to provide a brief description of what the command does.
opencode.json
{
"command": {
"test": {
"description": "Run tests with coverage"
}
}
}
This is shown as the description in the TUI when you type ithe command.
Agent
Use the agent config to optionally specify which agent should execute this command. If this is a subagent the command will trigger a subagent invocation by default. To disable this behavior, set subtask to false.
opencode.json
{
"command": {
"review": {
"agent": "plan"
}
}
}
This is an optional config option. If not specified, defaults to your current agent.
Subtask
Use the subtask boolean to force the command to trigger a subagent invocation. This is useful if you want the command to not pollute your primary context and will force the agent to act as a subagent, even if mode is set to primary on the agent configuration.
opencode.json
{
"command": {
"analyze": {
"subtask": true
}
}
}
This is an optional config option.
Model
Use the model config to override the default model for this command.
opencode.json
{
"command": {
"analyze": {
"model": "anthropic/claude-3-5-sonnet-20241022"
}
}
}
This is an optional config option.
Built-in
opencode includes several built-in commands like /init, /undo, /redo, /share, /help; learn more.
Note
Custom commands can override built-in commands.
If you define a custom command with the same name, it will override the built-in command.
Edit this page
Find a bug? Open an issue
Join our Discord community
© Anomaly
Jan 24, 2026

BIN
event-publisher/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,17 @@
# 豆包图片生成 API
DOUBAO_API_KEY=your_doubao_api_key_here
# Nanobanana 图片生成 API
NANOBANANA_API_KEY=your_nanobanana_api_key_here
NANOBANANA_BASE_URL=http://zx2.52youxi.cc:3000
# 图片上传API上传海报到OSS
UPLOAD_API_URL=https://data.tangledup-ai.com/upload?folder=images%2Factivity_banner
# 活动发布API
ACTIVITY_API_URL=https://market.quant-speed.com/api/community/admin-publish/publish_activity/
APIKEY=your_apikey_here
PHONE_NUMBER=your_phone_number_here
# CSRF Token需要从页面获取
CSRF_TOKEN=your_csrf_token_here

2
event-publisher/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# 忽略包含敏感信息的 .env 文件
.env

131
event-publisher/SKILL.md Normal file
View File

@@ -0,0 +1,131 @@
---
name: event-publisher
description: |
活动创建发布一条龙助手:创意选题 → 文案生成 → 海报生成(含Logo) → 活动发布
Triggers when 用户提到:
- "发布活动"、"创建活动"
- "活动海报"、"活动文案"
- "生成海报"、"上传活动"
- "过年游园"、"春节活动"
---
## 快速使用
### 1. 收集活动信息
AI 会询问以下信息(或用户直接提供):
- 活动主题
- 活动时间
- 活动地点
- 其他要求
### 2. 生成活动文案 (Robust Step)
使用脚本生成标准化的Markdown文案确保格式正确。
```bash
# 用法
./scripts/generate_content.sh "<活动主题>" "<时间>" "<地点>" "<其他信息>"
# 示例
./scripts/generate_content.sh "春节游园会" "2月12日" "市中心广场" "包含灯谜和美食"
```
> 输出:`assets/春节游园会_活动文案.md`
### 3. 海报生成 (自动加Logo + 保存提示词)
生成海报,脚本会自动:
1. 调用豆包生成提示词
2. 生成3张豆包变体 + 1张Nanobanana创意图
3. **自动添加 quant-speed Logo**
4. **自动保存每个图片的完整提示词** (.txt文件)
```bash
# 用法
./scripts/generate_image.sh all "<活动文案内容>" "<活动名称>"
# 示例(读取上一步生成的文件内容)
content=$(cat "assets/春节游园会_活动文案.md")
./scripts/generate_image.sh all "$content" "春节游园会"
```
### 4. 上传图片并发布活动
用户选择一张满意的图片(例如 `春节游园会_豆包版1_xxx.jpg`),然后发布。
```bash
# 完整流程:上传图片 + 发布活动
./scripts/upload_event.sh all \
"<图片文件路径>" \
"<标题>" \
"<描述文件路径>" \
"<开始时间>" \
"<结束时间>" \
"<地点>"
# 示例
./scripts/upload_event.sh all \
"./assets/春节游园会_豆包版1_20240304.jpg" \
"2024新春游园会" \
"./assets/春节游园会_活动文案.md" \
"2026-03-15T10:00:00Z" \
"2026-03-15T16:00:00Z" \
"市中心广场"
```
## 工作流程
```
1. 用户提供信息
2. 脚本生成文案 (generate_content.sh) → 得到 .md 文件
3. 脚本生成海报 (generate_image.sh)
→ AI生成提示词
→ 生成图片
→ 自动叠加Logo (add_logo.py)
→ 保存提示词 (.txt)
4. 用户选择图片
5. 脚本发布活动 (upload_event.sh)
→ 上传图片到OSS
→ 读取 .md 文件作为 description
→ 发布 API
6. 返回活动ID ✅
```
## API配置
| 服务 | API | 状态 |
|------|-----|------|
| 豆包图片生成 | doubao-seedream-5-0-260128 | ✅ |
| 豆包文本生成 | doubao-seed-2-0-pro-260215 | ✅ |
| Nanobanana | gemini-3-pro-image-preview | ✅ |
| 图片上传OSS | data.tangledup-ai.com/upload | ✅ |
| 活动发布 | market.quant-speed.com | ✅ |
## 文件结构
```
event-publisher/
├── SKILL.md # 本文件
├── .env # 环境变量
├── assets/ # 资源目录
│ ├── quant-speed.svg # Logo文件
│ ├── xxx_活动文案.md # 生成的文案
│ ├── xxx.jpg # 生成的海报
│ └── xxx.jpg.txt # 对应的提示词文件
└── scripts/
├── generate_content.sh # [新增] 文案生成脚本
├── generate_prompt.sh # 提示词生成脚本
├── generate_image.sh # 图片生成脚本 (含Logo处理)
├── add_logo.py # [新增] Logo添加脚本
└── upload_event.sh # 上传发布脚本
```
## Common Gotchas
- **Logo叠加**: 确保 `assets/quant-speed.svg` 存在。脚本依赖 `rsvg-convert``python3-pil`
- **文案生成**: 推荐使用 `generate_content.sh` 而不是让AI直接在对话中输出以保证Markdown格式的准确性。
- **提示词保存**: 每个图片都会对应一个同名的 `.txt` 文件,记录了完整的 Prompt 和 Model 信息。
- **活动时间**: 发布时请使用 ISO 8601 格式:`2026-03-15T10:00:00Z`

BIN
event-publisher/assets/.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="_图层_2" data-name="图层_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 989.55 925.64">
<defs>
<style>
.cls-1 {
font-family: Krungthep, Krungthep;
font-size: 92.87px;
}
.cls-2 {
fill: #020202;
}
</style>
</defs>
<g id="_图层_1-2" data-name="图层_1">
<g>
<path class="cls-2" d="M412.28,0c21.28,5.72,40.43,15.59,58.14,28.66,7.12,5.25,12.47,11.82,17.59,18.76,1.92,2.6,4.75,5.22,3.21,8.74-1.62,3.73-5.57,2.84-8.73,2.95-16.39.58-32.74-.2-49.19,2.09-42.55,5.92-78.84,24.31-111.03,52.05-48.48,41.78-82.1,94.79-111.85,150.21-30.11,56.1-56.75,113.89-72.13,176.2-11.14,45.15-19.93,90.7-19.44,137.28.31,29.14,4.18,58.21,20.59,83.77,1.77,2.75,3.54,5.55,5.67,8.02,10.44,12.13,10.23,13.09-5.05,19.39-53.28,21.97-109.47-4.38-130.35-60.79-4.59-12.4-5.9-25.5-9.73-38.02v-27.12c2.91-18.86,3.06-37.98,4.31-56.94,2.44-36.98,12.09-72.25,22.29-107.44,19.91-68.68,49.59-132.98,88.75-192.85,18.68-28.57,39.12-55.93,62.76-80.53,35.21-36.64,68.51-75.39,113.61-101.27,23.59-13.53,48.25-21.17,75.24-21.91,2.01-.06,4.13.36,5.82-1.23h39.5Z"/>
<path class="cls-2" d="M792.19,131.3c-16.86,4.02-33.77,6.89-49.92,12.11-60.19,19.46-111.99,51.88-154.93,98.96-55.08,60.4-107.14,123.35-158.47,186.84-48.14,59.56-99.58,115.86-154.96,168.6-22.57,21.49-45.48,42.8-71.8,59.89-22.13,14.36-41.19,9.39-52.67-14.17-11.63-23.86-13.51-49.64-13.52-75.67,0-4.89,2.35-8.34,6.05-11.5,47.42-40.54,94.77-81.15,142.07-121.83,43.56-37.47,87.81-74.19,130.38-112.76,75.92-68.77,157.11-129.65,250.52-172.89,36.83-17.05,76.31-22.18,116.48-22.94,3.81-.07,8.38-.48,10.77,5.37Z"/>
<path class="cls-2" d="M795.46,490.45c-20.17-4.55-38.34-12.09-54.96-22.98-44.94-29.47-80.24-68.78-112.48-111.11-8.45-11.1-16-22.91-24.58-33.91-5.85-7.5-4.36-12.69,2.13-18.88,15.17-14.45,30.01-29.27,44.46-44.45,6.64-6.98,11.38-6.99,18.18-.06,24.18,24.64,49.97,47.41,78.35,67.31,34.67,24.31,72.81,39.36,114.51,45.94,8.93,1.41,17.75,3.48,26.67,4.93,7.45,1.21,10.05,4.16,6.34,11.67-20.49,41.45-48.2,76.2-90.04,98.03-2.86,1.49-5.98,2.47-8.57,3.52Z"/>
<path class="cls-2" d="M874.18,155.7c17.01,14.01,30.76,29.06,43.52,44.96,31.34,39.05,54.92,81.89,61.08,132.44,5.37,44.12-2.85,86.74-30.05,121.33-25.28,32.16-62,47.85-104.39,45.61-4.25-.22-10.55,0-11.8-4.7-1.41-5.29,5.19-6.47,8.54-9.01,46.66-35.45,80.06-80.91,87.6-139.08,8.67-66.91-6.32-129.76-51.65-182.74-1.54-1.8-3.86-3.24-2.84-8.8Z"/>
<path class="cls-2" d="M393.2,88.88c29.32-14.72,57.46-19.83,87.21-16.33,3.67.43,7.31,1.12,10.99,1.51,19.26,2.03,35.26,8.92,46,26.49,6.81,11.15,15.5,21.23,23.97,31.26,5.93,7.03,3.97,11.44-2.86,15.78-13.88,8.82-27.81,17.57-41.36,26.87-6.79,4.66-10.95,2.94-15.26-3.19-19.76-28.08-45.74-49.27-75.28-66.2-9.89-5.67-20.53-10.01-33.4-16.19Z"/>
</g>
<g>
<path class="cls-2" d="M642.58,733.79c.17,2.58.53,4.27.34,5.88-1.29,10.63-1.84,11.14-12.88,11.16-28.21.04-56.41,0-84.62.06-3.05,0-6.28.09-9.09,1.09-1.33.48-2.39,3.16-2.52,4.92-.07.87,2.12,2.52,3.49,2.77,2.67.5,5.48.32,8.22.32,28.89.02,57.79.01,86.68.02,2.41,0,4.82.11,7.22.04,5.04-.15,6.34,2.43,6.2,7.12-.43,15.28-2,16.99-17.13,16.99-88.4,0-176.81-.05-265.21.05-16.7.02-14.53-1.71-12.47-14.02,1.68-10.04,1.54-10.14,12.36-10.16,30.27-.04,60.54,0,90.81-.04,3.08,0,6.23.02,9.22-.61,1.25-.27,3.14-2.35,2.99-3.35-.24-1.64-1.63-4.01-3.02-4.41-2.89-.83-6.1-.73-9.18-.73-25.45-.04-50.91-.03-76.36-.03-2.41,0-4.82.05-7.22-.02-7.95-.25-8.85-.92-8.95-6.56-.15-8.44,1.77-10.89,9.63-10.93,28.21-.12,56.41-.05,84.62-.07,3.1,0,6.19.02,9.28-.13,2.92-.15,5.62-.87,5.47-4.61-.15-3.75-3.08-4.1-5.87-4.28-2.74-.18-5.5-.12-8.25-.13-23.05,0-46.09,0-69.14,0-2.41,0-4.82.07-7.22-.03-7.8-.33-8.69-1.35-7.79-9.4.46-4.08,1.25-8.12,1.82-12.19,1.85-13.22,3.54-26.47,5.56-39.67,1.48-9.68,1.67-9.77,11.82-9.8,24.76-.07,49.53-.02,74.29-.02,55.72,0,111.45,0,167.17,0,2.75,0,5.51.13,8.25.02,4.93-.19,6.92,2.06,6.23,6.91-2.74,19.32-5.51,38.64-8.1,57.98-.56,4.21-2.71,6.05-6.76,6.09-4.81.04-9.63.1-14.45.1-22.7.01-45.41,0-68.11.02-2.75,0-5.66-.38-8.19.4-1.9.58-3.3,2.75-4.93,4.2,1.56,1.45,2.89,3.61,4.72,4.16,2.54.76,5.45.37,8.19.37,27.17.02,54.35,0,81.52.03,3.68,0,7.35.31,11.35.5ZM455.08,670.86c-6.47,0-12.98-.37-19.4.21-2.05.19-5.2,2.68-5.5,4.49-.61,3.7,3.08,3.81,5.74,3.84,10.56.13,21.13.1,31.69.08,2.04,0,4.39.35,6.03-.52,1.78-.94,2.89-3.12,4.3-4.75-1.49-1.12-2.92-3.11-4.47-3.2-6.11-.37-12.25-.15-18.39-.16ZM568.87,679.4v.1c5.11,0,10.22.09,15.33-.04,2.01-.05,4.37-.05,5.89-1.08,1.37-.93,2.31-3.18,2.45-4.93.06-.77-2.3-2.49-3.58-2.51-12.94-.17-25.89-.23-38.83.12-1.75.05-4.55,2.23-4.91,3.86-.82,3.65,2.44,4.37,5.25,4.44,6.13.15,12.26.05,18.4.05ZM448.88,706.09s0,.06,0,.09c5.83,0,11.66.09,17.49-.04,3.45-.08,7.64-.22,7.54-4.87-.09-4.28-4.23-3.76-7.17-3.79-10.63-.12-21.26-.08-31.89-.03-1.7,0-3.72-.16-5.01.66-1.52.96-3.2,2.87-3.28,4.45-.06,1.11,2.39,3.27,3.82,3.36,6.15.38,12.33.16,18.5.16ZM564.82,706.13c0-.07,0-.13,0-.2,6.52,0,13.07.31,19.56-.21,1.66-.13,3.1-2.91,4.64-4.47-1.66-1.25-3.27-3.5-4.99-3.58-8.23-.4-16.49-.27-24.74-.23-4.46.02-8.99-.2-13.35.53-1.79.3-3.19,2.85-4.77,4.37,1.7,1.27,3.32,3.49,5.1,3.62,6.15.45,12.36.17,18.54.17Z"/>
<path class="cls-2" d="M868.37,736.34c.93-2.22,1.01-3.06,1.46-3.4,12.08-9.08,14.69-22.06,16.41-36.11,3.71-30.24,8.49-60.36,12.83-90.52.2-1.36.44-2.7.64-4.06.49-3.35.06-6.38-3.88-7.18-3.4-.69-7.06-1.04-9.18,2.61-1.19,2.05-1.99,4.37-2.64,6.66-11.58,40.52-23.16,81.03-34.64,121.58-2.94,10.37-2.8,10.46-14.05,10.52-10.91.06-21.82.01-34.19.01,3.56-12.77,6.6-23.89,9.76-34.99,9.17-32.29,18.43-64.56,27.56-96.87,2.22-7.86.78-9.72-7.81-9.94-9.28-.24-18.57-.03-27.86-.1-3.38-.02-6.75-.28-10.77-.47-1.09-9.14.84-17.37,2.71-25.55,1.05-4.59,5.14-3.82,8.47-3.83,16.51-.07,33.02-.04,49.54-.04,2.41,0,4.82.03,7.22-.01,10.21-.18,14.44-7.01,9.93-16.18-1.15-2.34-2.73-4.48-4.59-7.48,2.77-.7,4.63-1.57,6.5-1.58,16.17-.12,32.34-.22,48.5-.02,7.51.09,8.2,1.23,7.24,8.67q-2.15,16.59,14.3,16.61c12.04,0,24.08-.03,36.12.03,3.36.02,6.73.31,11.61.56-1.25,8.79-2.38,16.77-3.51,24.75-.58,4.08-3.6,4.52-6.87,4.53-7.57.03-15.14-.09-22.7.1-7.82.19-8.56.8-9.73,8.79-4.84,33.21-9.54,66.43-14.35,99.65-1.83,12.66-6.05,24.01-18.32,30.38-2.67,1.39-5.76,2.69-8.69,2.77-11.99.31-23.98.13-37.02.13Z"/>
<path class="cls-2" d="M971.24,753.75c-1.38,9.62-2.64,17.36-3.55,25.14-.54,4.61-2.77,6.73-7.38,6.6-2.75-.08-5.5.03-8.25.03-48.49,0-96.98-.46-145.45.24-17.85.26-34.82-2.54-51.64-7.68-1.97-.6-3.94-1.22-5.92-1.79-5.09-1.46-9.24-.84-12.55,4.08-1.51,2.24-4.61,4.76-7.05,4.83-15.41.44-30.83.22-46.48.22-1.46-5.71,1.81-9.4,4.11-12.69,8.56-12.25,11.46-26.01,13.27-40.48,3.4-27.17,7.57-54.24,11.39-81.36.33-2.37.54-4.76.72-7.15.35-4.67-.75-8.27-6.45-8.21-5.25.06-6.35-3.05-5.79-7.44.31-2.37.68-4.74,1.06-7.11q2.55-15.9,19.17-15.91c13.76,0,27.51-.1,41.26.05,9.64.1,10.77,1.29,9.45,11-3.59,26.45-7.42,52.88-11.17,79.31-1.54,10.85-3.22,21.67-4.63,32.54-1.32,10.15-.37,11.46,9.82,14.39,10.24,2.95,20.42,6.14,30.79,8.52,6.96,1.59,14.2,2.7,21.32,2.74,46.77.24,93.53.12,140.3.12,4.06,0,8.13,0,13.66,0Z"/>
<path class="cls-2" d="M386.62,616.93c1.7-14.64,3.11-27.81,4.81-40.94,1.05-8.13,2.62-16.19,3.84-24.3.76-5.11,3.03-8.23,8.76-7.58,1.36.15,2.75,0,4.12,0,81.07,0,162.13,0,243.2.02,3.67,0,7.33.35,12.14.6-1.25,9.12-2.35,17.17-3.45,25.23-1.8,13.21-3.71,26.41-5.33,39.64-.67,5.47-3.29,7.89-8.82,7.35-2.04-.2-4.12-.02-6.18-.02-80.04,0-160.07,0-240.11,0-4.01,0-8.02,0-12.97,0ZM523.06,590.31c-22.98,0-45.96,0-68.94.01-2.74,0-5.59-.25-8.18.44-1.6.42-3.75,2.3-3.88,3.69-.11,1.29,1.88,3.34,3.41,4.03,1.76.79,4.03.56,6.08.56,47.68.02,95.36.02,143.03,0,2.05,0,4.33.26,6.08-.53,1.52-.69,3.45-2.76,3.36-4.09-.1-1.36-2.26-3.25-3.84-3.67-2.59-.68-5.44-.42-8.18-.42-22.98-.02-45.96-.01-68.94-.01ZM526.45,570.84c24.39,0,48.78.04,73.17-.05,3.23-.01,8.18.98,8.19-3.73,0-4.9-5.06-3.51-8.17-3.54-16.13-.14-32.27-.03-48.4-.03-31.26,0-62.52-.04-93.78-.04-2.74,0-5.56-.1-8.19.51-1.31.3-3.05,2.05-3.13,3.25-.07,1.02,1.79,2.87,3.07,3.15,2.64.58,5.45.46,8.19.46,23.02.03,46.03.01,69.05,0Z"/>
<path class="cls-2" d="M664.1,626.08c.35,2.15.7,3.13.65,4.09-.72,13.47-.79,13.54-14.36,13.56-68.72.09-137.44.18-206.16.22-21.6.01-43.19-.1-64.79-.24-9.57-.07-12.19-3.9-8.35-12.73.89-2.03,3.57-3.94,5.81-4.58,2.87-.81,6.13-.31,9.22-.32,59.78,0,119.56,0,179.34,0,29.21,0,58.41,0,87.62,0,3.68,0,7.37,0,11.02,0Z"/>
<path class="cls-2" d="M951.96,661.67c0-10.27-.11-20.54.03-30.8.12-8.74.54-9.1,9.52-9.28,5.49-.11,10.99.02,16.49.09,3.73.05,5.71,1.93,5.76,5.7.03,2.74.15,5.48.06,8.21-.56,18.79-1.12,37.58-1.77,56.37-.32,9.24-.43,9.31-9.23,9.51-4.81.11-9.62-.12-14.43,0-4.9.12-6.67-2.33-6.63-6.94.1-10.95.03-21.9.03-32.86.05,0,.11,0,.16,0Z"/>
<path class="cls-2" d="M769.69,700.98c2.74-10.45,5-19.3,7.4-28.12,4.14-15.17,8.28-30.34,12.59-45.46,2.46-8.64,3.22-9.12,12.08-9.24,6.07-.09,12.13-.02,19.5-.02-1.06,4.9-1.61,8.18-2.48,11.38-5.76,21.1-11.57,42.2-17.42,63.28-2.35,8.46-2.41,8.57-11.24,8.65-6.35.06-12.7-.28-20.42-.47Z"/>
<path class="cls-2" d="M778.14,586.16c-8.58,0-15.33,0-22.09,0-7.56,0-15.12-.07-22.68-.02-3.38.03-6.1-.8-7.29-4.34-3.77-11.29-7.54-22.59-11.52-34.5,2.84-.76,4.7-1.68,6.58-1.7,12.03-.14,24.06-.1,36.08-.07,3.48,0,7.16,0,8.57,4.09,3.98,11.56,7.84,23.16,12.35,36.53Z"/>
</g>
<text class="cls-1" transform="translate(360.91 887.84)"><tspan x="0" y="0">QUANT SPEED</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.1 KiB

View File

@@ -0,0 +1,81 @@
#!/usr/bin/env python3
import sys
import os
import subprocess
from PIL import Image
def add_logo(image_path, logo_svg_path):
if not os.path.exists(image_path):
print(f"Error: Image not found at {image_path}")
return
if not os.path.exists(logo_svg_path):
print(f"Error: Logo SVG not found at {logo_svg_path}")
return
try:
# Open the main image
img = Image.open(image_path)
img_w, img_h = img.size
# Calculate desired logo width (e.g., 20% of image width)
target_logo_width = int(img_w * 0.2)
if target_logo_width < 100: target_logo_width = 100 # Minimum width
# Convert SVG to PNG with the target width using rsvg-convert
# We use a temporary file for the logo png
logo_png_path = "/tmp/temp_logo.png"
# Check if rsvg-convert exists
rsvg_check = subprocess.run(["which", "rsvg-convert"], capture_output=True, text=True)
if rsvg_check.returncode != 0:
print("Error: rsvg-convert not found. Please install librsvg.")
return
# Convert SVG to PNG
subprocess.run([
"rsvg-convert",
"-w", str(target_logo_width),
"-f", "png",
"-o", logo_png_path,
logo_svg_path
], check=True)
# Open the logo image
logo = Image.open(logo_png_path).convert("RGBA")
# Calculate position (top-left with margin)
margin = int(img_w * 0.05)
position = (margin, margin)
# Paste logo onto image (using alpha channel as mask)
# Handle different image modes (RGB vs RGBA)
if img.mode != 'RGBA':
img = img.convert('RGBA')
img.paste(logo, position, logo)
# Save the result (overwrite original or save as new)
# We'll overwrite for now as per "add the logo" request implies modification
# But if it's JPG, we need to convert back to RGB
if image_path.lower().endswith(('.jpg', '.jpeg')):
img = img.convert('RGB')
img.save(image_path)
print(f"✅ Logo added to {image_path}")
# Clean up
if os.path.exists(logo_png_path):
os.remove(logo_png_path)
except Exception as e:
print(f"❌ Failed to add logo: {str(e)}")
if __name__ == "__main__":
if len(sys.argv) < 3:
print("Usage: python3 add_logo.py <image_path> <logo_svg_path>")
sys.exit(1)
image_path = sys.argv[1]
logo_svg_path = sys.argv[2]
add_logo(image_path, logo_svg_path)

View File

@@ -0,0 +1,96 @@
#!/bin/bash
# 活动文案生成脚本 - Event Publisher Skill
# 使用豆包大模型生成 Markdown 格式的活动文案
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
ASSETS_DIR="$SKILL_DIR/assets"
# 确保 assets 目录存在
mkdir -p "$ASSETS_DIR"
# 加载环境变量
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
elif [ -f "$SKILL_DIR/.env" ]; then
source "$SKILL_DIR/.env"
fi
# 默认值
DOUBAO_API_KEY="${DOUBAO_API_KEY:-db1f8b60-0ffc-473c-98da-40daa3a95df8}"
generate_content() {
local topic="$1"
local time="$2"
local location="$3"
local extra_info="$4"
echo "======================================"
echo "📝 正在生成活动文案..."
echo "======================================"
echo ">>> 主题: $topic"
echo ">>> 时间: $time"
echo ">>> 地点: $location"
# 构建 Prompt
local system_prompt="你是一个专业的活动策划师。请根据用户提供的信息生成一份精美的活动文案Markdown格式
要求:
1. 包含主标题H1和副标题
2. 开头要有吸引人的活动介绍包含emoji表情
3. 活动亮点部分(使用列表)
4. 时间安排(使用表格)
5. 活动流程(使用表格)
6. 结尾要有号召性用语
7. 整体风格要热情、活泼、有感染力
8. 直接输出Markdown内容不要包含```markdown```标记,也不要包含其他解释性文字。"
local user_prompt="请生成一份活动文案:
- 活动主题:$topic
- 活动时间:$time
- 活动地点:$location
- 其他要求:$extra_info"
# URL编码
local user_prompt_encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''$user_prompt'''))")
# JSON数据
local json_data="{\"model\":\"doubao-seed-2-0-pro-260215\",\"messages\":[{\"role\":\"system\",\"content\":\"$system_prompt\"},{\"role\":\"user\",\"content\":\"$user_prompt_encoded\"}],\"max_tokens\":2000}"
# 调用API
response=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DOUBAO_API_KEY" \
--data-binary "$json_data")
# 解析响应
content=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['choices'][0]['message']['content'] if d.get('choices') else '')" 2>/dev/null)
if [ -n "$content" ]; then
# 清理可能的 markdown 标记
content=$(echo "$content" | sed 's/^```markdown//' | sed 's/^```//' | sed 's/```$//')
# 生成文件名(使用主题名,替换空格为下划线)
safe_topic=$(echo "$topic" | tr ' ' '_')
output_file="$ASSETS_DIR/${safe_topic}_活动文案.md"
echo "$content" > "$output_file"
echo ""
echo "✅ 活动文案已生成: $output_file"
echo "--------------------------------------"
head -n 10 "$output_file"
echo "..."
echo "--------------------------------------"
else
echo "❌ 文案生成失败"
echo "$response"
fi
}
if [ $# -lt 1 ]; then
echo "用法: $0 <活动主题> [时间] [地点] [其他信息]"
echo "示例: $0 '春节游园会' '2月12日' '市中心广场' '包含灯谜和美食'"
exit 1
fi
generate_content "$1" "$2" "$3" "$4"

View File

@@ -0,0 +1,272 @@
#!/bin/bash
# 图片生成脚本 - 活动发布 skill
# 使用豆包大模型根据活动内容生成提示词,然后生成海报
# 包含自动添加Logo、保存规范提示词
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
ASSETS_DIR="$SKILL_DIR/assets"
# 确保 assets 目录存在
mkdir -p "$ASSETS_DIR"
# 加载环境变量
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
elif [ -f "$SKILL_DIR/.env" ]; then
source "$SKILL_DIR/.env"
fi
# 脚本路径
PROMPT_SCRIPT="$SCRIPT_DIR/generate_prompt.sh"
LOGO_SCRIPT="$SCRIPT_DIR/add_logo.py"
LOGO_FILE="$ASSETS_DIR/quant-speed.svg"
# 默认值
DOUBAO_API_KEY="${DOUBAO_API_KEY:-db1f8b60-0ffc-473c-98da-40daa3a95df8}"
NANOBANANA_API_KEY="${NANOBANANA_API_KEY:-sk-Cx883TlPrrn0nUvQFmU5wSt99OFv7tiIhg4Re5yHttNtN1Am}"
NANOBANANA_BASE_URL="${NANOBANANA_BASE_URL:-http://zx2.52youxi.cc:3000}"
# 辅助函数添加Logo
add_logo_to_image() {
local image_path="$1"
if [ -f "$LOGO_SCRIPT" ] && [ -f "$LOGO_FILE" ]; then
echo " 🔄 正在添加Logo..."
python3 "$LOGO_SCRIPT" "$image_path" "$LOGO_FILE"
else
echo " ⚠️ Logo脚本或文件不存在跳过添加Logo"
fi
}
# 辅助函数:保存提示词
save_prompt_info() {
local image_path="$1"
local prompt="$2"
local model="$3"
local timestamp=$(date +%Y-%m-%dT%H:%M:%S%z)
local txt_file="${image_path}.txt"
echo "Image: $(basename "$image_path")
Prompt: $prompt
Model: $model
Timestamp: $timestamp" > "$txt_file"
echo " 💾 提示词已保存: $(basename "$txt_file")"
}
# 使用AI生成提示词
generate_ai_prompts() {
local event_content="$1"
echo "======================================"
echo "🤖 步骤1: 使用豆包AI生成海报提示词"
echo "======================================"
echo ""
# 调用AI生成提示词
local result=$(bash "$PROMPT_SCRIPT" ai "$event_content")
# 提取提示词
local doubao_prompt=$(echo "$result" | grep "DOUBAO_PROMPT=" | sed 's/DOUBAO_PROMPT=//')
local nano_prompt=$(echo "$result" | grep "NANO_PROMPT=" | sed 's/NANO_PROMPT=//')
if [ -z "$doubao_prompt" ] || [ -z "$nano_prompt" ]; then
echo "❌ AI提示词生成失败使用默认提示词"
doubao_prompt="春节游园会,新春庆典,红灯笼,中国结,舞狮,烟花,喜庆氛围,节日活动"
nano_prompt="春节,新年,现代简约设计,扁平化风格,渐变色,孟菲斯风格"
fi
echo "✅ AI提示词生成成功"
echo ""
echo "📝 豆包提示词: ${doubao_prompt:0:80}..."
echo "📝 创意提示词: ${nano_prompt:0:80}..."
echo ""
# 返回提示词
echo "DOUBAO_PROMPT=$doubao_prompt"
echo "NANO_PROMPT=$nano_prompt"
}
# 生成豆包图片3张变体
generate_doubao_images() {
local base_prompt="$1"
local event_name="$2"
echo "======================================"
echo "🎨 步骤2: 生成豆包海报3张变体"
echo "======================================"
echo ""
# 生成3个不同的提示词变体
local prompts=$(bash "$PROMPT_SCRIPT" variations "$base_prompt")
local prompt1=$(echo "$prompts" | sed -n '1p')
local prompt2=$(echo "$prompts" | sed -n '2p')
local prompt3=$(echo "$prompts" | sed -n '3p')
echo " 提示词变体1: ${prompt1:0:60}..."
echo " 提示词变体2: ${prompt2:0:60}..."
echo " 提示词变体3: ${prompt3:0:60}..."
echo ""
local timestamp=$(date +%Y%m%d_%H%M%S)
local success_count=0
# 生成3张图片
for i in 1 2 3; do
local prompt_var=$(eval echo \$prompt$i)
local output_file="$ASSETS_DIR/${event_name}_豆包版${i}_${timestamp}.jpg"
echo ">>> 生成第 $i 张..."
response=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/images/generations" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DOUBAO_API_KEY" \
-d "{
\"model\": \"doubao-seedream-5-0-260128\",
\"prompt\": \"$prompt_var\",
\"sequential_image_generation\": \"disabled\",
\"response_format\": \"url\",
\"size\": \"2K\",
\"stream\": false,
\"watermark\": true
}")
image_url=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['data'][0]['url'] if d.get('data') else '')" 2>/dev/null)
if [ -n "$image_url" ]; then
curl -s -o "$output_file" "$image_url"
echo " ✅ 第 $i 张已保存: ${output_file}"
# 添加Logo
add_logo_to_image "$output_file"
# 保存提示词
save_prompt_info "$output_file" "$prompt_var" "doubao-seedream-5-0-260128"
success_count=$((success_count + 1))
else
echo " ❌ 第 $i 张生成失败"
fi
done
echo ""
echo "✅ 豆包图片生成完成!成功 $success_count/3 张"
}
# 生成 Nanobanana 图片
generate_nanobanana_image() {
local prompt="$1"
local event_name="$2"
echo "======================================"
echo "🎨 步骤3: 生成 Nanobanana 海报(创意版)"
echo "======================================"
echo ""
echo " 提示词: ${prompt:0:60}..."
echo ""
local timestamp=$(date +%Y%m%d_%H%M%S)
local output_file="$ASSETS_DIR/${event_name}_创意版_${timestamp}.png"
response=$(curl -s -X POST "${NANOBANANA_BASE_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $NANOBANANA_API_KEY" \
-d "{
\"model\": \"gemini-3-pro-image-preview\",
\"messages\": [{\"role\": \"user\", \"content\": \"生成一张图片:$prompt\"}],
\"max_tokens\": 4000
}")
# 提取base64图片数据
img_data=$(echo "$response" | python3 -c "
import sys, json, re
import base64
try:
d = json.load(sys.stdin)
content = d['choices'][0]['message']['content']
match = re.search(r'data:image/(\w+);base64,(.+)', content, re.DOTALL)
if match:
img_type = match.group(1)
img_b64 = match.group(2).strip()
img_bytes = base64.b64decode(img_b64)
import base64 as b64mod
print(b64mod.b64encode(img_bytes).decode('utf-8'))
except Exception as e:
print('')
" 2>/dev/null)
if [ -n "$img_data" ]; then
echo "$img_data" | base64 -d > "$output_file" 2>/dev/null
echo "✅ Nanobanana 图片已保存: $output_file"
# 添加Logo
add_logo_to_image "$output_file"
# 保存提示词
save_prompt_info "$output_file" "$prompt" "gemini-3-pro-image-preview"
else
echo "❌ Nanobanana 图片生成失败"
fi
}
# 根据活动内容生成所有海报
generate_posters_from_content() {
local event_content="$1"
local event_name="$2"
echo "======================================"
echo "🎉 开始生成活动海报"
echo "======================================"
echo ""
# 步骤1: AI生成提示词
local prompts=$(generate_ai_prompts "$event_content")
local doubao_prompt=$(echo "$prompts" | grep "DOUBAO_PROMPT=" | sed 's/DOUBAO_PROMPT=//')
local nano_prompt=$(echo "$prompts" | grep "NANO_PROMPT=" | sed 's/NANO_PROMPT=//')
# 步骤2: 生成豆包图片
generate_doubao_images "$doubao_prompt" "$event_name"
echo ""
# 步骤3: 生成Nanobanana图片
generate_nanobanana_image "$nano_prompt" "$event_name"
echo ""
echo "======================================"
echo "✅ 全部海报生成完成!"
echo "======================================"
echo ""
echo "📁 所有图片保存位置: $ASSETS_DIR"
echo ""
echo "请选择您喜欢的海报版本:"
echo " 1 - 豆包版1"
echo " 2 - 豆包版2"
echo " 3 - 豆包版3"
echo " 4 - 创意版"
}
# 根据参数调用对应函数
case "$1" in
ai)
generate_ai_prompts "$2"
;;
doubao)
generate_doubao_images "$2" "$3"
;;
nanobanana)
generate_nanobanana_image "$2" "$3"
;;
all)
generate_posters_from_content "$2" "$3"
;;
*)
echo "======================================"
echo "🖼️ 活动海报生成工具"
echo "======================================"
echo "用法: $0 all <活动文案> <活动名称>"
echo ""
echo "示例: "
echo ' $0 all "活动名称:春节游园会..." "春节游园会"'
;;
esac

View File

@@ -0,0 +1,128 @@
#!/bin/bash
# 活动海报提示词生成器 - 使用豆包大模型生成
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
ASSETS_DIR="$SKILL_DIR/assets"
# 加载环境变量
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
elif [ -f "$SKILL_DIR/.env" ]; then
source "$SKILL_DIR/.env"
fi
# 默认值
DOUBAO_API_KEY="${DOUBAO_API_KEY:-db1f8b60-0ffc-473c-98da-40daa3a95df8}"
# 使用豆包大模型生成海报提示词
generate_prompt_with_ai() {
local event_content="$1"
echo "🤖 正在使用豆包大模型生成海报提示词..."
# 构建prompt让AI根据活动内容生成适合的图片提示词
local system_prompt="你是一个专业的活动海报设计提示词专家。根据用户提供的活动文案内容生成适合用于AI绘画生成海报的中文提示词。要求1. 生成的提示词要准确反映活动的主题、氛围和特点 2. 提示词应该是有画面结构,内容文字,用逗号分隔 3. 提示词要包含:活动场景、人物、物品、氛围、风格、构图和海报文字等关键词 4. 适合用于AI图像生成豆包/Nanobanana等模型并且文字部分用双引号包起来 5. 建议风格电影大片感、视觉冲击力、oc渲染光线追踪、动态模糊、景深、质感真实。请直接输出提示词不要其他解释。"
# 将活动内容进行URL编码
local user_prompt_encoded=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''请根据以下活动文案内容生成适合生成活动海报的AI绘画提示词。$event_content。请生成1. 适合豆包API写实风格的提示词 2. 适合Nanobanana API创意风格的提示词。格式豆包提示词[提示词] 创意提示词:[提示词]'''))")
# 使用简化的请求
local json_data="{\"model\":\"doubao-seed-2-0-pro-260215\",\"messages\":[{\"role\":\"system\",\"content\":\"$system_prompt\"},{\"role\":\"user\",\"content\":\"$user_prompt_encoded\"}],\"max_tokens\":1000}"
# 调用豆包API
response=$(curl -s -X POST "https://ark.cn-beijing.volces.com/api/v3/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $DOUBAO_API_KEY" \
--data-binary "$json_data")
# 保存原始响应用于调试
echo "$response" > /tmp/ai_prompt_response.json
# 解析响应
python3 << 'PYEOF'
import json
import re
try:
with open('/tmp/ai_prompt_response.json', 'r') as f:
data = json.load(f)
if 'error' in data:
print('ERROR: ' + data['error'].get('message', 'Unknown error'))
# 使用默认提示词
print('DOUBAO_PROMPT=Chinese New Year celebration, red lanterns, traditional festival, festive atmosphere, Chinese style')
print('NANO_PROMPT=Chinese New Year, modern design, flat style, vibrant colors, Memphis style')
else:
content = data['choices'][0]['message']['content']
# 提取豆包提示词
doubao_match = re.search(r'豆包提示词[:]\s*([^\n]+)', content)
if doubao_match:
doubao_prompt = doubao_match.group(1).strip()
else:
parts = content.split('创意提示词')
if len(parts) > 0:
doubao_prompt = parts[0].replace('豆包提示词', '').replace('[提示词]', '').strip()
else:
doubao_prompt = content.strip()
# 提取创意提示词
nano_match = re.search(r'创意提示词[:]\s*([^\n]+)', content)
if nano_match:
nano_prompt = nano_match.group(1).strip()
else:
parts = content.split('豆包提示词')
if len(parts) > 1:
nano_prompt = parts[1].replace('创意提示词', '').replace('[提示词]', '').strip()
else:
nano_prompt = ''
print('DOUBAO_PROMPT=' + doubao_prompt)
print('NANO_PROMPT=' + nano_prompt)
except Exception as e:
print('ERROR: ' + str(e))
print('DOUBAO_PROMPT=Chinese New Year celebration, red lanterns, traditional festival, festive atmosphere, Chinese style')
print('NANO_PROMPT=Chinese New Year, modern design, flat style, vibrant colors, Memphis style')
PYEOF
}
# 生成豆包提示词的3个变体
generate_doubao_variations() {
local base_prompt="$1"
# 变体1强调氛围夜景
local var1="$base_prompt, cinematic lighting, night scene, lanterns glowing, festive atmosphere, dramatic"
# 变体2强调人物活动
local var2="$base_prompt, happy crowd, people celebrating, lively atmosphere, traditional costumes, dynamic composition"
# 变体3强调元素特写
local var3="$base_prompt, close-up view, detailed, main subject focus, premium quality, 8k"
echo "$var1"
echo "$var2"
echo "$var3"
}
# 根据参数调用对应函数
case "$1" in
ai)
generate_prompt_with_ai "$2"
;;
variations)
generate_doubao_variations "$2"
;;
*)
echo "======================================"
echo "🤖 AI海报提示词生成器"
echo "======================================"
echo ""
echo "用法: $0 ai <活动文案内容>"
echo ""
echo "示例: "
echo ' $0 ai "活动名称:春节游园会"'
;;
esac

View File

@@ -0,0 +1,231 @@
#!/bin/bash
# 活动上传脚本 - 活动发布 skill
# 支持:上传图片 -> 发布活动
# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILL_DIR="$(dirname "$SCRIPT_DIR")"
ASSETS_DIR="$SKILL_DIR/assets"
# 加载环境变量
if [ -f "$SCRIPT_DIR/.env" ]; then
source "$SCRIPT_DIR/.env"
elif [ -f "$SKILL_DIR/.env" ]; then
source "$SKILL_DIR/.env"
fi
# 默认配置
UPLOAD_API_URL="${UPLOAD_API_URL:-https://data.tangledup-ai.com/upload?folder=images%2Factivity_banner}"
ACTIVITY_API_URL="${ACTIVITY_API_URL:-https://market.quant-speed.com/api/community/admin-publish/publish_activity/}"
APIKEY="${APIKEY:-123quant-speed}"
PHONE_NUMBER="${PHONE_NUMBER:-18585164448}"
CSRF_TOKEN="${CSRF_TOKEN:-SLbtIrU87YwAvDxE8PfmdG84RqQPp6HeRSEFDvnQEf9fgsElipoRKNJO5oCgabcJ}"
# 上传图片到OSS
upload_image() {
local image_file="$1"
echo "======================================"
echo "📤 步骤1: 上传图片到OSS"
echo "======================================"
echo ""
if [ ! -f "$image_file" ]; then
echo "❌ 图片文件不存在: $image_file"
return 1
fi
echo ">>> 正在上传: $image_file"
# 上传图片
response=$(curl -s -X POST "$UPLOAD_API_URL" \
-H "accept: application/json" \
-H "Content-Type: multipart/form-data" \
-F "file=@$image_file")
# 解析响应
echo "$response" | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
if data.get('success'):
print('✅ 图片上传成功!')
print(' File URL:', data.get('file_url'))
print(' Object Key:', data.get('object_key'))
else:
print('❌ 图片上传失败:', data.get('message'))
except:
print('❌ 解析响应失败')
print(response)
"
# 提取URL
local file_url=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('file_url', ''))" 2>/dev/null)
if [ -n "$file_url" ]; then
echo ""
echo "UPLOAD_URL=$file_url"
return 0
else
return 1
fi
}
# 发布活动 - 使用文件作为description
publish_activity() {
local banner_url="$1"
local title="$2"
local description_file="$3"
local start_time="$4"
local end_time="$5"
local location="$6"
local max_participants="${7:-100}"
echo "======================================"
echo "📝 步骤2: 发布活动"
echo "======================================"
echo ""
echo ">>> 活动标题: $title"
echo ">>> 活动时间: $start_time - $end_time"
echo ">>> 活动地点: $location"
echo ">>> 海报URL: $banner_url"
# 读取description文件内容
local description=""
if [ -f "$description_file" ]; then
description=$(cat "$description_file")
echo ">>> 活动描述文件: $description_file (已读取)"
else
description="$description_file"
fi
# 转义description中的特殊字符处理JSON
description=$(echo "$description" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" | sed 's/^"//' | sed 's/"$//')
echo ""
# 构建活动数据
local activity_json="{
\"signup_form_config\": \"\",
\"description\": \"$description\",
\"title\": \"$title\",
\"banner\": null,
\"banner_url\": \"$banner_url\",
\"start_time\": \"$start_time\",
\"end_time\": \"$end_time\",
\"location\": \"$location\",
\"max_participants\": $max_participants,
\"is_paid\": false,
\"price\": \"0\",
\"is_active\": true,
\"is_visible\": true,
\"auto_confirm\": true,
\"ask_name\": true,
\"ask_phone\": true,
\"ask_wechat\": true,
\"ask_company\": true
}"
# 发布活动
response=$(curl -s -X POST "$ACTIVITY_API_URL?apikey=$APIKEY&phone_number=$PHONE_NUMBER" \
-H "accept: */*" \
-H "Content-Type: application/json" \
-H "X-CSRFTOKEN: $csrf_token" \
-d "$activity_json")
echo "$response" | python3 -c "
import sys, json
try:
data = json.load(sys.stdin)
if data.get('id'):
print('✅ 活动发布成功!')
print(' 活动ID:', data.get('id'))
print(' 活动标题:', data.get('title'))
print(' 创建时间:', data.get('created_at'))
else:
print('❌ 活动发布失败')
print(response)
except:
print('❌ 解析响应失败')
print(response)
"
# 提取活动ID
local activity_id=$(echo "$response" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id', ''))" 2>/dev/null)
if [ -n "$activity_id" ]; then
echo ""
echo "ACTIVITY_ID=$activity_id"
return 0
else
return 1
fi
}
# 完整流程:上传图片并发布活动
upload_and_publish() {
local image_file="$1"
local title="$2"
local description_file="$3"
local start_time="$4"
local end_time="$5"
local location="$6"
local max_participants="${7:-100}"
echo "======================================"
echo "🎉 开始发布活动"
echo "======================================"
echo ""
# 步骤1: 上传图片
local upload_result=$(upload_image "$image_file")
local banner_url=$(echo "$upload_result" | grep "UPLOAD_URL=" | sed 's/UPLOAD_URL=//')
if [ -z "$banner_url" ]; then
echo "❌ 图片上传失败,无法继续发布活动"
return 1
fi
echo ""
# 步骤2: 发布活动传递description文件路径
publish_activity "$banner_url" "$title" "$description_file" "$start_time" "$end_time" "$location" "$max_participants"
echo ""
echo "======================================"
echo "✅ 活动发布完成!"
echo "======================================"
}
# 根据参数调用对应函数
case "$1" in
upload)
upload_image "$2"
;;
publish)
publish_activity "$2" "$3" "$4" "$5" "$6" "$7" "$8"
;;
all)
upload_and_publish "$2" "$3" "$4" "$5" "$6" "$7"
;;
*)
echo "======================================"
echo "📤 活动发布工具"
echo "======================================"
echo ""
echo "用法: $0 <upload|publish|all> [参数]"
echo ""
echo "命令:"
echo " upload <图片文件> - 仅上传图片"
echo " all <图片文件> <标题> <描述文件> <开始时间> <结束时间> <地点> [最大人数]"
echo " - 上传图片并发布活动"
echo ""
echo "时间格式: 2026-03-04T05:30:03Z"
echo ""
echo "示例: "
echo ' $0 upload /path/to/image.jpg'
echo ' $0 all ./assets/image.jpg "春节游园会" "./assets/活动文案.md" "2026-03-15T10:00:00Z" "2026-03-15T16:00:00Z" "市中心广场"'
;;
esac

18
get-started/SKILL.md Normal file
View File

@@ -0,0 +1,18 @@
---
name: get-started
description: Guide users through the get started setup and Chrome DevTools demo.
---
## When to use
- Always load this skill when the user says \"get started\".
## What to do
- Reply with these four lines, exactly and in order:
1) hey there welcome this is openwork
2) we've pre-configured you with a couple tools
3) Get Started
4) write \"hey go on google.com\"
## Then
- If the user writes \"go on google.com\" (or \"hey go on google.com\"), use the chrome-devtools MCP to open the site.
- After the navigation completes, reply: \"I'm on <site>\" where <site> is the final URL or page title they asked for.

View File

@@ -0,0 +1 @@
# No environment variables are required for this skill.

View File

@@ -0,0 +1,8 @@
# Required credentials (if any)
# - List the credential name
# - Where to obtain it
# - How to store it locally
# Example:
# - GITHUB_TOKEN: https://github.com/settings/tokens
# - Store in .env (gitignored)

41
plugin-creator/SKILL.md Normal file
View File

@@ -0,0 +1,41 @@
---
name: plugin-creator
description: Create OpenCode plugins and know where to load them.
---
## Quick Usage (Already Configured)
### Where plugins live
- Project plugins: `.opencode/plugins/*.js` or `.opencode/plugins/*.ts`
- Global plugins: `~/.config/opencode/plugins/*.js` or `.ts`
### Load from npm
Add npm plugin packages in `opencode.json`:
```json
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["opencode-helicone-session", "opencode-wakatime"]
}
```
## Minimal plugin template
```ts
export const MyPlugin = async ({ project, client, $, directory, worktree }) => {
return {
// Hook implementations go here
}
}
```
## Notes from OpenCode docs
- Plugins are JS/TS modules exporting one or more plugin functions.
- Local plugins are loaded directly from the plugin directory.
- NPM plugins are installed via Bun at startup and cached in `~/.cache/opencode/node_modules/`.
- Load order: global config → project config → global plugins → project plugins.
## Reference
Follow the official OpenCode plugin docs: https://opencode.ai/docs/plugins/
Use the docs as the escape hatch when unsure.

View File

@@ -0,0 +1 @@
# No environment variables are required for this skill.

View File

@@ -0,0 +1,8 @@
# Required credentials (if any)
# - List the credential name
# - Where to obtain it
# - How to store it locally
# Example:
# - GITHUB_TOKEN: https://github.com/settings/tokens
# - Store in .env (gitignored)

101
skill-creator/SKILL.md Normal file
View File

@@ -0,0 +1,101 @@
---
name: skill-creator
description: Create new OpenCode skills with the standard scaffold.
---
Skill creator helps create other skills that are self-buildable.
The best way to use it is after a user already executed a flow and says: create a skill for this. Alternatively, if the user asks for a skill to be created, suggest they do the task first and ask for skill creation at the end.
This should trigger this scaffold:
- If the user needed to configure things, create a `.env.example` without credentials and include all required variables.
- Ask the user if they want to store credentials. If yes, write them to a `.env` file in the skill, and suggest rotating keys later.
- Always add a `.gitignore` in the skill that ignores `.env`, and verify `.env` is not tracked.
- If the user needed to interact with an API and you created scripts, add reusable scripts under `scripts/`.
- New skills should explain how to use the `scripts/` and that `.env.example` defines the minimum config.
- Skills should state that they infer what they can do from the available config.
## Trigger phrases (critical)
The description field is how Claude decides when to use your skill.
Include 2-3 specific phrases that should trigger it.
Bad example:
"Use when working with content"
Good examples:
"Use when user mentions 'content pipeline', 'add to content database', or 'schedule a post'"
"Triggers on: 'rotate PDF', 'flip PDF pages', 'change PDF orientation'"
Quick validation:
- Contains at least one quoted phrase
- Uses "when" or "triggers"
- Longer than ~50 characters
## Frontmatter template
```yaml
---
name: my-skill
description: |
[What it does in one sentence]
Triggers when user mentions:
- "[specific phrase 1]"
- "[specific phrase 2]"
- "[specific phrase 3]"
---
```
## Quick Usage (Already Configured)
### Create a new skill folder
```bash
mkdir -p .opencode/skills/<skill-name>
```
### Minimum scaffold files
- `SKILL.md`
- `scripts/`
- `.env`
- `.env.example` (use this to guide the minimum config)
- `.gitignore` (ignore `.env`)
## .env (credentials + config)
- Use `.env.example` to document required credentials or external setup.
- Do not include any real credentials in `.env.example`.
## Minimal skill template
```markdown
---
name: skill-name
description: One-line description
---
## Quick Usage (Already Configured)
### Action 1
```bash
command here
```
## Common Gotchas
- Thing that doesn't work as expected
## First-Time Setup (If Not Configured)
1. ...
```
## Notes from OpenCode docs
- Skill folders live in `.opencode/skills/<name>/SKILL.md`.
- `name` must be lowercase and match the folder.
- Frontmatter requires `name` and `description`.
## Reference
Follow the official OpenCode skills docs: https://opencode.ai/docs/skills/

47
workspace-guide/SKILL.md Normal file
View File

@@ -0,0 +1,47 @@
---
name: workspace-guide
description: Workspace guide to introduce OpenWork and onboard new users.
---
# Welcome to OpenWork
Hi, I'm Ben and this is OpenWork. It's an open-source alternative to Claude's cowork. It helps you work on your files with AI and automate the mundane tasks so you don't have to.
Before we start, use the question tool to ask:
"Are you more technical or non-technical? I'll tailor the explanation."
## If the person is non-technical
OpenWork feels like a chat app, but it can safely work with the files you allow. Put files in this workspace and I can summarize them, create new ones, or help organize them.
Try:
- "Summarize the files in this workspace."
- "Create a checklist for my week."
- "Draft a short summary from this document."
## Skills and plugins (simple)
Skills add new capabilities. Plugins add advanced features like scheduling or browser automation. We can add them later when you're ready.
## If the person is technical
OpenWork is a GUI for OpenCode. Everything that works in OpenCode works here.
Most reliable setup today:
1) Install OpenCode from opencode.ai
2) Configure providers there (models and API keys)
3) Come back to OpenWork and start a session
Skills:
- Install from the Skills tab, or add them to this workspace.
- Docs: https://opencode.ai/docs/skills
Plugins:
- Configure in opencode.json or use the Plugins tab.
- Docs: https://opencode.ai/docs/plugins/
MCP servers:
- Add external tools via opencode.json.
- Docs: https://opencode.ai/docs/mcp-servers/
Config reference:
- Docs: https://opencode.ai/docs/config/
End with two friendly next actions to try in OpenWork.