mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-02 18:10:47 +08:00
Compare commits
10 Commits
codex/add-
...
codex/refa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc349923e9 | ||
|
|
0d44c9a823 | ||
|
|
02645af321 | ||
|
|
c3a175f13f | ||
|
|
0821d447f7 | ||
|
|
257794ca00 | ||
|
|
6a527de3eb | ||
|
|
2313f90eb3 | ||
|
|
7fde984e7d | ||
|
|
042e5fdbe6 |
29
.github/workflows/coffee-bot.yml
vendored
Normal file
29
.github/workflows/coffee-bot.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Coffee Bot
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 1 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run-coffee-bot:
|
||||||
|
environment: Bots
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install --no-save @openai/agents tsx typescript
|
||||||
|
|
||||||
|
- name: Run coffee bot
|
||||||
|
env:
|
||||||
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
|
OPENISLE_TOKEN: ${{ secrets.OPENISLE_TOKEN }}
|
||||||
|
run: npx tsx bots/instance/coffee_bot.ts
|
||||||
@@ -5,22 +5,19 @@ export type WorkflowInput = { input_as_text: string };
|
|||||||
export abstract class BotFather {
|
export abstract class BotFather {
|
||||||
protected readonly allowedMcpTools = [
|
protected readonly allowedMcpTools = [
|
||||||
"search",
|
"search",
|
||||||
|
"create_post",
|
||||||
"reply_to_post",
|
"reply_to_post",
|
||||||
"reply_to_comment",
|
"reply_to_comment",
|
||||||
"recent_posts",
|
"recent_posts",
|
||||||
"get_post",
|
"get_post",
|
||||||
"list_unread_messages",
|
"list_unread_messages",
|
||||||
"mark_notifications_read",
|
"mark_notifications_read",
|
||||||
|
"create_post",
|
||||||
];
|
];
|
||||||
|
|
||||||
protected readonly mcp = hostedMcpTool({
|
protected readonly openisleToken = (process.env.OPENISLE_TOKEN ?? "").trim();
|
||||||
serverLabel: "openisle_mcp",
|
|
||||||
serverUrl: "https://www.open-isle.com/mcp",
|
|
||||||
allowedTools: this.allowedMcpTools,
|
|
||||||
requireApproval: "never",
|
|
||||||
});
|
|
||||||
|
|
||||||
protected readonly openisleToken = process.env.OPENISLE_TOKEN ?? "";
|
protected readonly mcp = this.createHostedMcpTool();
|
||||||
protected readonly agent: Agent;
|
protected readonly agent: Agent;
|
||||||
|
|
||||||
constructor(protected readonly name: string) {
|
constructor(protected readonly name: string) {
|
||||||
@@ -32,8 +29,8 @@ export abstract class BotFather {
|
|||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
this.openisleToken
|
this.openisleToken
|
||||||
? "🔑 OPENISLE_TOKEN detected in environment."
|
? "🔑 OPENISLE_TOKEN detected in environment; it will be attached to MCP requests."
|
||||||
: "🔓 OPENISLE_TOKEN not set; agent will request it if required."
|
: "🔓 OPENISLE_TOKEN not set; authenticated MCP tools may be unavailable."
|
||||||
);
|
);
|
||||||
|
|
||||||
this.agent = new Agent({
|
this.agent = new Agent({
|
||||||
@@ -64,13 +61,30 @@ export abstract class BotFather {
|
|||||||
"You are a helpful assistant for https://www.open-isle.com.",
|
"You are a helpful assistant for https://www.open-isle.com.",
|
||||||
"Finish tasks end-to-end before replying. If multiple MCP tools are needed, call them sequentially until the task is truly done.",
|
"Finish tasks end-to-end before replying. If multiple MCP tools are needed, call them sequentially until the task is truly done.",
|
||||||
"When presenting the result, reply in Chinese with a concise summary and include any important URLs or IDs.",
|
"When presenting the result, reply in Chinese with a concise summary and include any important URLs or IDs.",
|
||||||
this.openisleToken
|
|
||||||
? `If tools require auth, use this token exactly where the tool schema expects it: ${this.openisleToken}`
|
|
||||||
: "If a tool requires auth, ask me to provide OPENISLE_TOKEN via env.",
|
|
||||||
"After finishing replies, call mark_notifications_read with all processed notification IDs to keep the inbox clean.",
|
"After finishing replies, call mark_notifications_read with all processed notification IDs to keep the inbox clean.",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createHostedMcpTool() {
|
||||||
|
const token = this.openisleToken;
|
||||||
|
const authConfig = token
|
||||||
|
? {
|
||||||
|
authorization: `Bearer ${token}`,
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: {};
|
||||||
|
|
||||||
|
return hostedMcpTool({
|
||||||
|
serverLabel: "openisle_mcp",
|
||||||
|
serverUrl: "https://www.open-isle.com/mcp",
|
||||||
|
allowedTools: this.allowedMcpTools,
|
||||||
|
requireApproval: "never",
|
||||||
|
...authConfig,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
protected getAdditionalInstructions(): string[] {
|
protected getAdditionalInstructions(): string[] {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
63
bots/instance/coffee_bot.ts
Normal file
63
bots/instance/coffee_bot.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import { BotFather, WorkflowInput } from "../bot_father";
|
||||||
|
|
||||||
|
const WEEKDAY_NAMES = ["日", "一", "二", "三", "四", "五", "六"] as const;
|
||||||
|
|
||||||
|
class CoffeeBot extends BotFather {
|
||||||
|
constructor() {
|
||||||
|
super("Coffee Bot");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override getAdditionalInstructions(): string[] {
|
||||||
|
return [
|
||||||
|
"You are responsible for 发布每日抽奖早安贴。",
|
||||||
|
"创建帖子时,确保标题、奖品信息、开奖时间以及领奖方式完全符合 CLI 查询提供的细节。",
|
||||||
|
"正文需亲切友好,简洁明了,鼓励社区成员互动。",
|
||||||
|
"开奖说明需明确告知中奖者需私聊站长 @nagisa 领取奖励。",
|
||||||
|
"确保只发布一个帖子,避免重复调用 create_post。",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override getCliQuery(): string {
|
||||||
|
const now = new Date();
|
||||||
|
const beijingNow = new Date(
|
||||||
|
now.toLocaleString("en-US", { timeZone: "Asia/Shanghai" })
|
||||||
|
);
|
||||||
|
const weekday = WEEKDAY_NAMES[beijingNow.getDay()];
|
||||||
|
|
||||||
|
const drawTime = new Date(beijingNow);
|
||||||
|
drawTime.setHours(15, 0, 0, 0);
|
||||||
|
const drawTimeText = drawTime
|
||||||
|
.toLocaleTimeString("zh-CN", {
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
hour12: false,
|
||||||
|
timeZone: "Asia/Shanghai",
|
||||||
|
})
|
||||||
|
.replace(/^24:/, "00:");
|
||||||
|
|
||||||
|
return `
|
||||||
|
请立即在 https://www.open-isle.com 使用 create_post 发表一篇全新帖子,遵循以下要求:
|
||||||
|
1. 标题固定为「大家星期${weekday}早安--抽一杯咖啡」。
|
||||||
|
2. 正文包含:
|
||||||
|
- 亲切的早安问候;
|
||||||
|
- 明确奖品写作“Coffee x 1”;
|
||||||
|
- 奖品图片链接:https://openisle-1307107697.cos.accelerate.myqcloud.com/dynamic_assert/0d6a9b33e9ca4fe5a90540187d3f9ecb.png;
|
||||||
|
- 公布开奖时间为今天下午 15:00(北京时间,写成 ${drawTimeText});
|
||||||
|
- 标注“领奖请私聊站长 @nagisa”;
|
||||||
|
- 鼓励大家留言互动。
|
||||||
|
3. 帖子语言使用简体中文,格式可用 Markdown,使关键信息醒目。
|
||||||
|
4. 完成后只输出“已发布咖啡抽奖贴”,不额外生成总结。
|
||||||
|
`.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const coffeeBot = new CoffeeBot();
|
||||||
|
|
||||||
|
export const runWorkflow = async (workflow: WorkflowInput) => {
|
||||||
|
return coffeeBot.runWorkflow(workflow);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (require.main === module) {
|
||||||
|
coffeeBot.runCli();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// reply_bot.ts
|
// reply_bot.ts
|
||||||
import { BotFather, WorkflowInput } from "./bot_father";
|
import { BotFather, WorkflowInput } from "../bot_father";
|
||||||
|
|
||||||
class ReplyBot extends BotFather {
|
class ReplyBot extends BotFather {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -8,8 +8,10 @@ class ReplyBot extends BotFather {
|
|||||||
|
|
||||||
protected override getAdditionalInstructions(): string[] {
|
protected override getAdditionalInstructions(): string[] {
|
||||||
return [
|
return [
|
||||||
"You are a helpful and cute assistant for https://www.open-isle.com. Please use plenty of kawaii kaomoji (颜表情), such as (๑˃ᴗ˂)ﻭ, (•̀ω•́)✧, (。•ᴗ-)_♡, (⁎⁍̴̛ᴗ⁍̴̛⁎), etc., in your replies to create a friendly, adorable vibe.",
|
"You are a helpful and cute assistant for https://www.open-isle.com. Keep the lovable tone with plentiful kawaii kaomoji (颜表情) such as (๑˃ᴗ˂)ﻭ, (•̀ω•́)✧, (。•ᴗ-)_♡, (⁎⁍̴̛ᴗ⁍̴̛⁎), etc., while staying professional and informative.",
|
||||||
"When presenting the result, reply in Chinese with a concise, cute summary filled with kaomoji and include any important URLs or IDs.",
|
"OpenIsle 是一个由 Spring Boot + Vue 3 打造的开源社区平台,提供注册登录、OAuth 登录(Google/GitHub/Discord/Twitter)、帖子与评论互动、标签分类、草稿、统计分析、通知消息、全局搜索、Markdown 支持、图片上传(默认腾讯云 COS)、浏览器推送、DiceBear 头像等功能,旨在帮助团队快速搭建属于自己的技术社区。",
|
||||||
|
"回复时请主动结合上述站点背景,为用户提供有洞察力、可执行的建议或答案,并在需要时引用官网 https://www.open-isle.com、GitHub 仓库 https://github.com/nagisa77/OpenIsle 或相关文档链接,避免空泛的安慰或套话。",
|
||||||
|
"When presenting the result, reply in Chinese with a concise yet content-rich summary filled with kaomoji,并清晰列出关键结论、操作步骤、重要 URL 或 ID,确保用户能直接采取行动。",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user