galaxy-opc-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +166 -0
  2. package/index.ts +145 -0
  3. package/openclaw.plugin.json +17 -0
  4. package/package.json +47 -0
  5. package/skills/basic-crm/SKILL.md +81 -0
  6. package/skills/basic-finance/SKILL.md +100 -0
  7. package/skills/business-monitoring/SKILL.md +120 -0
  8. package/skills/company-lifecycle/SKILL.md +99 -0
  9. package/skills/company-registration/SKILL.md +80 -0
  10. package/skills/finance-tax/SKILL.md +150 -0
  11. package/skills/hr-assistant/SKILL.md +127 -0
  12. package/skills/investment-management/SKILL.md +101 -0
  13. package/skills/legal-assistant/SKILL.md +113 -0
  14. package/skills/media-ops/SKILL.md +101 -0
  15. package/skills/procurement-management/SKILL.md +91 -0
  16. package/skills/project-management/SKILL.md +125 -0
  17. package/src/api/companies.ts +193 -0
  18. package/src/api/dashboard.ts +25 -0
  19. package/src/api/routes.ts +14 -0
  20. package/src/db/index.ts +63 -0
  21. package/src/db/migrations.ts +67 -0
  22. package/src/db/schema.ts +518 -0
  23. package/src/db/sqlite-adapter.ts +366 -0
  24. package/src/opc/company-manager.ts +82 -0
  25. package/src/opc/context-injector.ts +186 -0
  26. package/src/opc/reminder-service.ts +289 -0
  27. package/src/opc/types.ts +330 -0
  28. package/src/opc/workspace-factory.ts +189 -0
  29. package/src/tools/acquisition-tool.ts +150 -0
  30. package/src/tools/asset-package-tool.ts +283 -0
  31. package/src/tools/finance-tool.ts +244 -0
  32. package/src/tools/hr-tool.ts +211 -0
  33. package/src/tools/investment-tool.ts +201 -0
  34. package/src/tools/legal-tool.ts +191 -0
  35. package/src/tools/lifecycle-tool.ts +251 -0
  36. package/src/tools/media-tool.ts +174 -0
  37. package/src/tools/monitoring-tool.ts +207 -0
  38. package/src/tools/opb-tool.ts +193 -0
  39. package/src/tools/opc-tool.ts +206 -0
  40. package/src/tools/procurement-tool.ts +191 -0
  41. package/src/tools/project-tool.ts +203 -0
  42. package/src/tools/schemas.ts +163 -0
  43. package/src/tools/staff-tool.ts +211 -0
  44. package/src/utils/tool-helper.ts +16 -0
  45. package/src/web/config-ui.ts +3501 -0
  46. package/src/web/landing-page.ts +269 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * 星环OPC中心 — opc_staff AI 员工岗位配置工具
3
+ *
4
+ * 为每家一人公司配置 AI 员工角色(行政/HR/财务/法务等),
5
+ * 实现"一人 = AI 团队"的核心理念。
6
+ */
7
+
8
+ import { Type, type Static } from "@sinclair/typebox";
9
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
10
+ import type { OpcDatabase } from "../db/index.js";
11
+ import { json } from "../utils/tool-helper.js";
12
+
13
+ /** 内置 AI 岗位定义 */
14
+ const BUILTIN_ROLES: Record<string, { name: string; prompt: string; skills: string[] }> = {
15
+ admin: {
16
+ name: "行政助理",
17
+ prompt: "你是公司行政助理,负责日程管理、文件归档、会议安排、行政事务协调。用专业、简洁的方式处理行政工作。",
18
+ skills: ["schedule", "document", "meeting"],
19
+ },
20
+ hr: {
21
+ name: "HR 专员",
22
+ prompt: "你是公司 HR 专员,负责员工招聘、入职手续、薪酬核算、劳动合同管理、社保公积金事务。熟悉劳动法规。",
23
+ skills: ["recruit", "payroll", "labor-law"],
24
+ },
25
+ finance: {
26
+ name: "财务顾问",
27
+ prompt: "你是公司财务顾问,负责账务记录、发票管理、税务申报、现金流分析、财务报表。熟悉中国财税法规。",
28
+ skills: ["bookkeeping", "tax", "invoice", "cashflow"],
29
+ },
30
+ legal: {
31
+ name: "法务助理",
32
+ prompt: "你是公司法务助理,负责合同审查、风险评估、合规检查、法律文件起草。熟悉中国商业法律。",
33
+ skills: ["contract-review", "compliance", "risk-assessment"],
34
+ },
35
+ marketing: {
36
+ name: "市场推广",
37
+ prompt: "你是公司市场推广专员,负责品牌推广、内容营销、社交媒体运营、客户获取策略。",
38
+ skills: ["content", "social-media", "brand"],
39
+ },
40
+ ops: {
41
+ name: "运营经理",
42
+ prompt: "你是公司运营经理,负责项目管理、流程优化、供应链协调、KPI 跟踪与分析。",
43
+ skills: ["project-mgmt", "process", "kpi"],
44
+ },
45
+ };
46
+
47
+ const StaffSchema = Type.Union([
48
+ Type.Object({
49
+ action: Type.Literal("configure_staff"),
50
+ company_id: Type.String({ description: "公司 ID" }),
51
+ role: Type.String({ description: "岗位角色: admin/hr/finance/legal/marketing/ops 或自定义" }),
52
+ role_name: Type.Optional(Type.String({ description: "岗位显示名称,不填则使用内置名称" })),
53
+ enabled: Type.Optional(Type.Boolean({ description: "是否启用,默认 true" })),
54
+ system_prompt: Type.Optional(Type.String({ description: "自定义系统提示词,不填则使用内置提示词" })),
55
+ skills: Type.Optional(Type.String({ description: "技能列表 JSON 数组,如 [\"finance\",\"tax\"]" })),
56
+ notes: Type.Optional(Type.String({ description: "备注" })),
57
+ }),
58
+ Type.Object({
59
+ action: Type.Literal("list_staff"),
60
+ company_id: Type.String({ description: "公司 ID" }),
61
+ enabled_only: Type.Optional(Type.Boolean({ description: "仅返回已启用岗位,默认 false" })),
62
+ }),
63
+ Type.Object({
64
+ action: Type.Literal("toggle_staff"),
65
+ company_id: Type.String({ description: "公司 ID" }),
66
+ role: Type.String({ description: "岗位角色" }),
67
+ enabled: Type.Boolean({ description: "true=启用, false=停用" }),
68
+ }),
69
+ Type.Object({
70
+ action: Type.Literal("init_default_staff"),
71
+ company_id: Type.String({ description: "公司 ID,将初始化 6 个默认 AI 岗位" }),
72
+ }),
73
+ Type.Object({
74
+ action: Type.Literal("list_builtin_roles"),
75
+ }),
76
+ ]);
77
+
78
+ type StaffParams = Static<typeof StaffSchema>;
79
+
80
+ export function registerStaffTool(api: OpenClawPluginApi, db: OpcDatabase): void {
81
+ api.registerTool(
82
+ {
83
+ name: "opc_staff",
84
+ label: "OPC AI 员工配置",
85
+ description:
86
+ "AI 员工岗位配置工具。实现\"一人公司 = AI 团队\"。" +
87
+ "操作: configure_staff(配置/更新岗位), list_staff(岗位列表), " +
88
+ "toggle_staff(启用/停用岗位), init_default_staff(一键初始化6个默认岗位), " +
89
+ "list_builtin_roles(查看内置岗位模板)",
90
+ parameters: StaffSchema,
91
+ async execute(_toolCallId, params) {
92
+ const p = params as StaffParams;
93
+ try {
94
+ switch (p.action) {
95
+ case "configure_staff": {
96
+ const builtin = BUILTIN_ROLES[p.role];
97
+ const roleName = p.role_name ?? builtin?.name ?? p.role;
98
+ const prompt = p.system_prompt ?? builtin?.prompt ?? "";
99
+ const skills = p.skills ?? JSON.stringify(builtin?.skills ?? []);
100
+ const now = new Date().toISOString();
101
+
102
+ // UPSERT: 存在则更新,不存在则插入
103
+ const existing = db.queryOne(
104
+ "SELECT id FROM opc_staff_config WHERE company_id = ? AND role = ?",
105
+ p.company_id, p.role,
106
+ );
107
+
108
+ if (existing) {
109
+ const sets: string[] = ["role_name = ?", "system_prompt = ?", "skills = ?", "updated_at = ?"];
110
+ const vals: unknown[] = [roleName, prompt, skills, now];
111
+ if (p.enabled !== undefined) { sets.push("enabled = ?"); vals.push(p.enabled ? 1 : 0); }
112
+ if (p.notes !== undefined) { sets.push("notes = ?"); vals.push(p.notes); }
113
+ vals.push(p.company_id, p.role);
114
+ db.execute(
115
+ `UPDATE opc_staff_config SET ${sets.join(", ")} WHERE company_id = ? AND role = ?`,
116
+ ...vals,
117
+ );
118
+ } else {
119
+ const id = db.genId();
120
+ db.execute(
121
+ `INSERT INTO opc_staff_config (id, company_id, role, role_name, enabled, system_prompt, skills, notes, created_at, updated_at)
122
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
123
+ id, p.company_id, p.role, roleName,
124
+ (p.enabled ?? true) ? 1 : 0,
125
+ prompt, skills, p.notes ?? "", now, now,
126
+ );
127
+ }
128
+
129
+ return json(db.queryOne(
130
+ "SELECT * FROM opc_staff_config WHERE company_id = ? AND role = ?",
131
+ p.company_id, p.role,
132
+ ));
133
+ }
134
+
135
+ case "list_staff": {
136
+ let sql = "SELECT * FROM opc_staff_config WHERE company_id = ?";
137
+ const args: unknown[] = [p.company_id];
138
+ if (p.enabled_only) { sql += " AND enabled = 1"; }
139
+ sql += " ORDER BY created_at ASC";
140
+ const rows = db.query(sql, ...args);
141
+ return json({ staff: rows, count: (rows as unknown[]).length });
142
+ }
143
+
144
+ case "toggle_staff": {
145
+ const now = new Date().toISOString();
146
+ db.execute(
147
+ "UPDATE opc_staff_config SET enabled = ?, updated_at = ? WHERE company_id = ? AND role = ?",
148
+ p.enabled ? 1 : 0, now, p.company_id, p.role,
149
+ );
150
+ return json(db.queryOne(
151
+ "SELECT * FROM opc_staff_config WHERE company_id = ? AND role = ?",
152
+ p.company_id, p.role,
153
+ ) ?? { error: "岗位配置不存在,请先调用 configure_staff 或 init_default_staff" });
154
+ }
155
+
156
+ case "init_default_staff": {
157
+ const company = db.queryOne("SELECT * FROM opc_companies WHERE id = ?", p.company_id);
158
+ if (!company) return json({ error: "公司不存在" });
159
+
160
+ const now = new Date().toISOString();
161
+ const created: string[] = [];
162
+ const skipped: string[] = [];
163
+
164
+ for (const [role, def] of Object.entries(BUILTIN_ROLES)) {
165
+ const exists = db.queryOne(
166
+ "SELECT id FROM opc_staff_config WHERE company_id = ? AND role = ?",
167
+ p.company_id, role,
168
+ );
169
+ if (exists) { skipped.push(role); continue; }
170
+
171
+ const id = db.genId();
172
+ db.execute(
173
+ `INSERT INTO opc_staff_config (id, company_id, role, role_name, enabled, system_prompt, skills, notes, created_at, updated_at)
174
+ VALUES (?, ?, ?, ?, 1, ?, ?, '', ?, ?)`,
175
+ id, p.company_id, role, def.name,
176
+ def.prompt, JSON.stringify(def.skills), now, now,
177
+ );
178
+ created.push(role);
179
+ }
180
+
181
+ return json({
182
+ company_id: p.company_id,
183
+ created,
184
+ skipped,
185
+ message: `已初始化 ${created.length} 个 AI 岗位${skipped.length > 0 ? `,跳过 ${skipped.length} 个已存在岗位` : ""}`,
186
+ });
187
+ }
188
+
189
+ case "list_builtin_roles": {
190
+ const roles = Object.entries(BUILTIN_ROLES).map(([role, def]) => ({
191
+ role,
192
+ name: def.name,
193
+ skills: def.skills,
194
+ prompt_preview: def.prompt.slice(0, 50) + "…",
195
+ }));
196
+ return json({ builtin_roles: roles, count: roles.length });
197
+ }
198
+
199
+ default:
200
+ return json({ error: `未知操作: ${(p as { action: string }).action}` });
201
+ }
202
+ } catch (err) {
203
+ return json({ error: err instanceof Error ? err.message : String(err) });
204
+ }
205
+ },
206
+ },
207
+ { name: "opc_staff" },
208
+ );
209
+
210
+ api.logger.info("opc: 已注册 opc_staff 工具");
211
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 星环OPC中心 — 工具辅助函数
3
+ */
4
+
5
+ /** 将数据封装为 AI 工具标准响应格式 */
6
+ export function json(data: unknown) {
7
+ return {
8
+ content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }],
9
+ details: data,
10
+ };
11
+ }
12
+
13
+ /** 生成标准错误响应 */
14
+ export function toolError(message: string) {
15
+ return json({ ok: false, error: message });
16
+ }