personalac 1.3.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.
- package/README.md +249 -0
- package/bin/personalac.js +215 -0
- package/dist/agent/context.d.ts +39 -0
- package/dist/agent/context.d.ts.map +1 -0
- package/dist/agent/context.js +163 -0
- package/dist/agent/context.js.map +1 -0
- package/dist/agent/executors.d.ts +40 -0
- package/dist/agent/executors.d.ts.map +1 -0
- package/dist/agent/executors.js +177 -0
- package/dist/agent/executors.js.map +1 -0
- package/dist/agent/index.d.ts +61 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +907 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/planner.d.ts +15 -0
- package/dist/agent/planner.d.ts.map +1 -0
- package/dist/agent/planner.js +81 -0
- package/dist/agent/planner.js.map +1 -0
- package/dist/agent/scheduler.d.ts +22 -0
- package/dist/agent/scheduler.d.ts.map +1 -0
- package/dist/agent/scheduler.js +178 -0
- package/dist/agent/scheduler.js.map +1 -0
- package/dist/database/index.d.ts +5 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +283 -0
- package/dist/database/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.middleware.d.ts +6 -0
- package/dist/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/middleware/auth.middleware.js +19 -0
- package/dist/middleware/auth.middleware.js.map +1 -0
- package/dist/routes/agent.routes.d.ts +3 -0
- package/dist/routes/agent.routes.d.ts.map +1 -0
- package/dist/routes/agent.routes.js +101 -0
- package/dist/routes/agent.routes.js.map +1 -0
- package/dist/routes/auth.routes.d.ts +3 -0
- package/dist/routes/auth.routes.d.ts.map +1 -0
- package/dist/routes/auth.routes.js +66 -0
- package/dist/routes/auth.routes.js.map +1 -0
- package/dist/routes/chat.routes.d.ts +3 -0
- package/dist/routes/chat.routes.d.ts.map +1 -0
- package/dist/routes/chat.routes.js +80 -0
- package/dist/routes/chat.routes.js.map +1 -0
- package/dist/routes/data.routes.d.ts +3 -0
- package/dist/routes/data.routes.d.ts.map +1 -0
- package/dist/routes/data.routes.js +16 -0
- package/dist/routes/data.routes.js.map +1 -0
- package/dist/routes/email.routes.d.ts +3 -0
- package/dist/routes/email.routes.d.ts.map +1 -0
- package/dist/routes/email.routes.js +18 -0
- package/dist/routes/email.routes.js.map +1 -0
- package/dist/routes/goals.routes.d.ts +3 -0
- package/dist/routes/goals.routes.d.ts.map +1 -0
- package/dist/routes/goals.routes.js +45 -0
- package/dist/routes/goals.routes.js.map +1 -0
- package/dist/routes/plans.routes.d.ts +3 -0
- package/dist/routes/plans.routes.d.ts.map +1 -0
- package/dist/routes/plans.routes.js +19 -0
- package/dist/routes/plans.routes.js.map +1 -0
- package/dist/routes/settings.routes.d.ts +3 -0
- package/dist/routes/settings.routes.d.ts.map +1 -0
- package/dist/routes/settings.routes.js +29 -0
- package/dist/routes/settings.routes.js.map +1 -0
- package/dist/routes/workspace.routes.d.ts +3 -0
- package/dist/routes/workspace.routes.d.ts.map +1 -0
- package/dist/routes/workspace.routes.js +28 -0
- package/dist/routes/workspace.routes.js.map +1 -0
- package/dist/services/auth.service.d.ts +32 -0
- package/dist/services/auth.service.d.ts.map +1 -0
- package/dist/services/auth.service.js +110 -0
- package/dist/services/auth.service.js.map +1 -0
- package/dist/services/data.service.d.ts +47 -0
- package/dist/services/data.service.d.ts.map +1 -0
- package/dist/services/data.service.js +139 -0
- package/dist/services/data.service.js.map +1 -0
- package/dist/services/email.service.d.ts +23 -0
- package/dist/services/email.service.d.ts.map +1 -0
- package/dist/services/email.service.js +316 -0
- package/dist/services/email.service.js.map +1 -0
- package/dist/services/notify.service.d.ts +2 -0
- package/dist/services/notify.service.d.ts.map +1 -0
- package/dist/services/notify.service.js +21 -0
- package/dist/services/notify.service.js.map +1 -0
- package/dist/services/plan.service.d.ts +21 -0
- package/dist/services/plan.service.d.ts.map +1 -0
- package/dist/services/plan.service.js +96 -0
- package/dist/services/plan.service.js.map +1 -0
- package/dist/services/resource.service.d.ts +27 -0
- package/dist/services/resource.service.d.ts.map +1 -0
- package/dist/services/resource.service.js +150 -0
- package/dist/services/resource.service.js.map +1 -0
- package/dist/services/settings.service.d.ts +41 -0
- package/dist/services/settings.service.d.ts.map +1 -0
- package/dist/services/settings.service.js +254 -0
- package/dist/services/settings.service.js.map +1 -0
- package/dist/services/sobriety.service.d.ts +41 -0
- package/dist/services/sobriety.service.d.ts.map +1 -0
- package/dist/services/sobriety.service.js +243 -0
- package/dist/services/sobriety.service.js.map +1 -0
- package/dist/services/workspace.service.d.ts +71 -0
- package/dist/services/workspace.service.d.ts.map +1 -0
- package/dist/services/workspace.service.js +265 -0
- package/dist/services/workspace.service.js.map +1 -0
- package/dist/tools/chat-tools.d.ts +2 -0
- package/dist/tools/chat-tools.d.ts.map +1 -0
- package/dist/tools/chat-tools.js +419 -0
- package/dist/tools/chat-tools.js.map +1 -0
- package/dist/tools/index.d.ts +19 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +27 -0
- package/dist/tools/index.js.map +1 -0
- package/package.json +38 -0
- package/public/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/public/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/public/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/public/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/public/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/public/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/public/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/public/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/public/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/public/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/public/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/public/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/public/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/public/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/public/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/public/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/public/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/public/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/public/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/public/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/public/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/public/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/public/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/public/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/public/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/public/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/public/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/public/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/public/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/public/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/public/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/public/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/public/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/public/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/public/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/public/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/public/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/public/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/public/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/public/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/public/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/public/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/public/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/public/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/public/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/public/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/public/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/public/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/public/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/public/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/public/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/public/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/public/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/public/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/public/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/public/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/public/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/public/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/public/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/public/assets/_baseUniq-DiHtXYsr.js +1 -0
- package/public/assets/arc-Bv1zbXf7.js +1 -0
- package/public/assets/architectureDiagram-Q4EWVU46-EbiUvXBr.js +36 -0
- package/public/assets/blockDiagram-DXYQGD6D-B-4wwQNT.js +132 -0
- package/public/assets/c4Diagram-AHTNJAMY-brLyKMPJ.js +10 -0
- package/public/assets/channel-Me4d6Y1x.js +1 -0
- package/public/assets/chunk-4BX2VUAB-DMh-4Nye.js +1 -0
- package/public/assets/chunk-4TB4RGXK-CSr1z2CQ.js +206 -0
- package/public/assets/chunk-55IACEB6-xN0xmcvD.js +1 -0
- package/public/assets/chunk-EDXVE4YY-CkCM3j5E.js +1 -0
- package/public/assets/chunk-FMBD7UC4-B-mDgsjM.js +15 -0
- package/public/assets/chunk-OYMX7WX6-DK8dg9K4.js +231 -0
- package/public/assets/chunk-QZHKN3VN-BZGbFOdK.js +1 -0
- package/public/assets/chunk-YZCP3GAM-BTmFmMer.js +1 -0
- package/public/assets/classDiagram-6PBFFD2Q-BXgAb5m4.js +1 -0
- package/public/assets/classDiagram-v2-HSJHXN6E-BXgAb5m4.js +1 -0
- package/public/assets/clone-rnECnpTI.js +1 -0
- package/public/assets/cose-bilkent-S5V4N54A-BBqCwo63.js +1 -0
- package/public/assets/cytoscape.esm-BQk4lpUV.js +331 -0
- package/public/assets/dagre-KV5264BT-DLeQYvAA.js +4 -0
- package/public/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/public/assets/diagram-5BDNPKRD-D85z2LaM.js +10 -0
- package/public/assets/diagram-G4DWMVQ6-4AvBmvcP.js +24 -0
- package/public/assets/diagram-MMDJMWI5-DRNEGNZA.js +43 -0
- package/public/assets/diagram-TYMM5635-C_oGwrmX.js +24 -0
- package/public/assets/erDiagram-SMLLAGMA-DDSp8ANa.js +85 -0
- package/public/assets/flowDiagram-DWJPFMVM-B1Wy36da.js +162 -0
- package/public/assets/ganttDiagram-T4ZO3ILL-CQ7VWheo.js +292 -0
- package/public/assets/gitGraphDiagram-UUTBAWPF-BhvM7s41.js +106 -0
- package/public/assets/graph-fatjTp1h.js +1 -0
- package/public/assets/index-1PrEnCZL.js +677 -0
- package/public/assets/index-DcsnItNp.css +1 -0
- package/public/assets/infoDiagram-42DDH7IO-4eawOC2G.js +2 -0
- package/public/assets/init-Gi6I4Gst.js +1 -0
- package/public/assets/ishikawaDiagram-UXIWVN3A-CJWfG1fv.js +70 -0
- package/public/assets/journeyDiagram-VCZTEJTY-C4Zx3dpF.js +139 -0
- package/public/assets/kanban-definition-6JOO6SKY-CV1vDcC8.js +89 -0
- package/public/assets/layout-CX0IDv3q.js +1 -0
- package/public/assets/linear-C8hMcu9f.js +1 -0
- package/public/assets/min-BaxMGW9J.js +1 -0
- package/public/assets/mindmap-definition-QFDTVHPH-KzGyX4Em.js +96 -0
- package/public/assets/ordinal-Cboi1Yqb.js +1 -0
- package/public/assets/pieDiagram-DEJITSTG-Dp2x5kvP.js +30 -0
- package/public/assets/quadrantDiagram-34T5L4WZ-B4yqA6XF.js +7 -0
- package/public/assets/requirementDiagram-MS252O5E-DEjN_2tG.js +84 -0
- package/public/assets/sankeyDiagram-XADWPNL6-BKm_F5FA.js +10 -0
- package/public/assets/sequenceDiagram-FGHM5R23-07BCMKjW.js +157 -0
- package/public/assets/stateDiagram-FHFEXIEX-DVz6GtR8.js +1 -0
- package/public/assets/stateDiagram-v2-QKLJ7IA2-DYiYr0PB.js +1 -0
- package/public/assets/timeline-definition-GMOUNBTQ-C0u67FqY.js +120 -0
- package/public/assets/vennDiagram-DHZGUBPP-BiAlMVLe.js +34 -0
- package/public/assets/wardley-RL74JXVD-BnWyuHzf.js +162 -0
- package/public/assets/wardleyDiagram-NUSXRM2D-DEL2Lx6S.js +20 -0
- package/public/assets/xychartDiagram-5P7HB3ND-ILdmj7ok.js +7 -0
- package/public/index.html +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# PersonalAC
|
|
2
|
+
|
|
3
|
+
个性化学习辅助系统。AI 驱动的学习跟踪、知识点分析和主动提醒,支持本地运行和服务器部署两种模式。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 两种版本
|
|
8
|
+
|
|
9
|
+
| | 本地版 | 服务器版 |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| 安装方式 | `npm install -g personalac` | Node 直接部署 / Docker |
|
|
12
|
+
| 数据存储 | `~/.personalac/` | 服务器磁盘 |
|
|
13
|
+
| 访问方式 | `localhost:7575` | 域名 / IP |
|
|
14
|
+
| 自唤醒通知 | 系统级推送(OS 通知) | 不支持 |
|
|
15
|
+
| 适合场景 | 个人使用 | 自托管、多人部署 |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 本地版
|
|
20
|
+
|
|
21
|
+
### 安装
|
|
22
|
+
|
|
23
|
+
需要 Node.js 18+。
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install -g personalac
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 启动
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
personalac
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
首次启动自动创建账号,终端显示 Sync Token,并在浏览器打开登录页。输入 Token 登录后浏览器会记住状态,之后直接访问即可。
|
|
36
|
+
|
|
37
|
+
### CLI 命令
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
personalac [command] [options]
|
|
41
|
+
|
|
42
|
+
命令:
|
|
43
|
+
start 启动服务器(默认)
|
|
44
|
+
token 显示登录 Token
|
|
45
|
+
open 在浏览器中打开界面
|
|
46
|
+
status 检查服务器状态和 Token
|
|
47
|
+
version 显示版本号
|
|
48
|
+
|
|
49
|
+
选项:
|
|
50
|
+
--port, -p <n> 端口号(默认 7575)
|
|
51
|
+
--data, -d <dir> 数据目录(默认 ~/.personalac)
|
|
52
|
+
--no-open 启动时不自动打开浏览器
|
|
53
|
+
--help, -h 显示帮助
|
|
54
|
+
--version, -v 显示版本号
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**示例:**
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# 启动(默认端口 7575,自动打开浏览器)
|
|
61
|
+
personalac
|
|
62
|
+
|
|
63
|
+
# 自定义端口
|
|
64
|
+
personalac --port 8080
|
|
65
|
+
|
|
66
|
+
# 不打开浏览器
|
|
67
|
+
personalac --no-open
|
|
68
|
+
|
|
69
|
+
# 查看 Token(服务器未运行时也可用)
|
|
70
|
+
personalac token
|
|
71
|
+
|
|
72
|
+
# 检查状态
|
|
73
|
+
personalac status
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 自唤醒通知
|
|
77
|
+
|
|
78
|
+
本地版运行时会在后台监控学习活动。如果你在 **08:00–22:00** 之间超过 **90 分钟** 没有打开对话,就会弹出系统通知提醒你学习。
|
|
79
|
+
|
|
80
|
+
- Linux:使用 `notify-send`(需安装 libnotify)
|
|
81
|
+
- macOS:系统通知中心
|
|
82
|
+
- Windows:PowerShell Toast 通知
|
|
83
|
+
|
|
84
|
+
只要你在和 AI 对话,通知就不会打扰你。
|
|
85
|
+
|
|
86
|
+
### 数据目录
|
|
87
|
+
|
|
88
|
+
默认存储在 `~/.personalac/`:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
~/.personalac/
|
|
92
|
+
├── personalac.db # SQLite 数据库(账号、知识点、学习记录)
|
|
93
|
+
└── workspace/ # 工作区文件
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
自定义位置:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
personalac --data /path/to/data
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 使用方法
|
|
105
|
+
|
|
106
|
+
### 登录
|
|
107
|
+
|
|
108
|
+
打开浏览器访问 `http://localhost:7575`,输入终端显示的 Sync Token 登录。
|
|
109
|
+
|
|
110
|
+
**注意**:Sync Token 是你的唯一凭证,相当于密码,请妥善保存。可以随时用 `personalac token` 查看。
|
|
111
|
+
|
|
112
|
+
### 聊天
|
|
113
|
+
|
|
114
|
+
登录后直接进入聊天界面,所有功能都通过对话完成:
|
|
115
|
+
|
|
116
|
+
| 操作 | 说明 |
|
|
117
|
+
|---|---|
|
|
118
|
+
| 发送消息 | 输入后回车或点击发送 |
|
|
119
|
+
| 上传图片 | 点击图片按钮,或直接粘贴截图 |
|
|
120
|
+
| 停止生成 | 点击停止按钮或 Ctrl+Enter |
|
|
121
|
+
| Shift+Enter | 换行(不发送) |
|
|
122
|
+
|
|
123
|
+
**极简模式**:访问 `/quick` 路径,全屏无侧边栏的纯聊天界面。
|
|
124
|
+
|
|
125
|
+
### AI 能做什么
|
|
126
|
+
|
|
127
|
+
AI 内置工具,能主动操作你的学习数据,无需你手动填表:
|
|
128
|
+
|
|
129
|
+
- **上传试卷/成绩截图** → AI 自动识别题目和得分,更新知识点掌握度
|
|
130
|
+
- **问"我最近哪里薄弱"** → AI 查询数据库,结合遗忘曲线给出分析
|
|
131
|
+
- **说"我学了 XX"** → AI 会出题验证,答对后才记录为掌握
|
|
132
|
+
- **监护人发送成绩数据** → AI 以高可信度记录,来源标注为"监护人上传"
|
|
133
|
+
|
|
134
|
+
### 首次配置
|
|
135
|
+
|
|
136
|
+
登录后前往**配置**页面,填入 AI 接口信息:
|
|
137
|
+
|
|
138
|
+
**OpenAI 兼容接口**(OpenAI / DeepSeek / Moonshot / 本地 Ollama 等):
|
|
139
|
+
- Base URL:如 `https://api.deepseek.com/v1`
|
|
140
|
+
- Model ID:如 `deepseek-chat`
|
|
141
|
+
- API Key:你的 Key
|
|
142
|
+
|
|
143
|
+
**Anthropic 接口**(Claude 系列):
|
|
144
|
+
- Base URL:`https://api.anthropic.com/anthropic`
|
|
145
|
+
- Model ID:如 `claude-opus-4-7`
|
|
146
|
+
- API Key:sk-ant-... 开头的 Key
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 服务器版
|
|
151
|
+
|
|
152
|
+
### 部署
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
cd codescore/1.3
|
|
156
|
+
|
|
157
|
+
# 安装依赖
|
|
158
|
+
cd server && npm install
|
|
159
|
+
cd ../frontend && npm install
|
|
160
|
+
|
|
161
|
+
# 构建前端
|
|
162
|
+
cd frontend && npm run build
|
|
163
|
+
|
|
164
|
+
# 启动
|
|
165
|
+
cd server && npm start
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
终端显示 Sync Token,用于首次登录。
|
|
169
|
+
|
|
170
|
+
### 环境变量
|
|
171
|
+
|
|
172
|
+
| 变量 | 说明 | 默认值 |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `PORT` | 监听端口 | `3000` |
|
|
175
|
+
| `DATA_DIR` | 数据目录 | `./data` |
|
|
176
|
+
| `CORS_ORIGIN` | 允许的前端来源 | `http://localhost:5173` |
|
|
177
|
+
| `FRONTEND_DIST` | 前端静态文件目录 | `../frontend/dist` |
|
|
178
|
+
|
|
179
|
+
### pac CLI(本地 Workspace 代理)
|
|
180
|
+
|
|
181
|
+
服务器版支持 `pac` CLI,将工作区文件存在用户本机而不占服务器磁盘:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
# 从服务器安装
|
|
185
|
+
curl -fsSL http://your-server/cli/install.sh | sh
|
|
186
|
+
|
|
187
|
+
# 登录
|
|
188
|
+
pac login http://your-server
|
|
189
|
+
|
|
190
|
+
# 启动本地代理(在 127.0.0.1:7474 运行)
|
|
191
|
+
pac start
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
前端自动检测本地代理,优先使用本地存储。
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Agent 工作原理
|
|
199
|
+
|
|
200
|
+
PersonalAC 的 AI 采用 **ReAct 框架**(Reason + Act):
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
用户发消息
|
|
204
|
+
│
|
|
205
|
+
▼
|
|
206
|
+
AI 思考:需要调用哪些工具?
|
|
207
|
+
│
|
|
208
|
+
├─ get_student_summary ← 查学习状态、薄弱点、本周活动
|
|
209
|
+
├─ update_knowledge ← 更新知识点掌握度(含遗忘曲线)
|
|
210
|
+
├─ set_plan ← 设置/更新学习计划
|
|
211
|
+
└─ record_learning ← 记录学习活动
|
|
212
|
+
│
|
|
213
|
+
▼
|
|
214
|
+
工具执行完毕,AI 组织结果流式回复
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**知识点置信度模型**:每个知识点有 `confidence`(掌握度)和 `stability`(记忆稳定性)。复习成功时 stability 增长,遗忘时 stability 下降。AI 计算 `estimatedRetention = e^(-days / stability×5)` 来估计当前记忆留存率。
|
|
218
|
+
|
|
219
|
+
**数据可信度来源**:
|
|
220
|
+
- `guardian_upload`:监护人上传的成绩数据,最可信
|
|
221
|
+
- `agent_observed`:AI 出题后学生当场验证
|
|
222
|
+
- `student_report`:学生自报(不信任,AI 会出题验证)
|
|
223
|
+
|
|
224
|
+
背景 Agent 还会定时触发:
|
|
225
|
+
- 每日学习回顾
|
|
226
|
+
- 薄弱点专项练习
|
|
227
|
+
- 学习报告推送
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 开发
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# 本地版:重新构建
|
|
235
|
+
cd codescore/local
|
|
236
|
+
npm run build # 编译服务端 + 构建前端,复制到 dist/ 和 public/
|
|
237
|
+
personalac # 直接运行
|
|
238
|
+
|
|
239
|
+
# 服务器版:开发模式
|
|
240
|
+
cd codescore/1.3/server && npm run dev
|
|
241
|
+
cd codescore/1.3/frontend && npm run dev
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 版本历史
|
|
247
|
+
|
|
248
|
+
- **v1.3** — Web 服务版,Tool Use / ReAct 框架,图片上传,知识点遗忘曲线,自唤醒通知,SSE 流式对话,pac CLI
|
|
249
|
+
- **v1.2** — Electron 桌面版
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
const os = require('os')
|
|
5
|
+
const path = require('path')
|
|
6
|
+
const fs = require('fs')
|
|
7
|
+
const http = require('http')
|
|
8
|
+
const { exec, execSync } = require('child_process')
|
|
9
|
+
|
|
10
|
+
const PKG = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8'))
|
|
11
|
+
const VER = PKG.version
|
|
12
|
+
|
|
13
|
+
// ── 参数解析 ─────────────────────────────────────────────────────────
|
|
14
|
+
const argv = process.argv.slice(2)
|
|
15
|
+
|
|
16
|
+
function flag(name) { return argv.includes(name) }
|
|
17
|
+
function opt(name, fallback) {
|
|
18
|
+
const i = argv.indexOf(name)
|
|
19
|
+
return i !== -1 && argv[i + 1] ? argv[i + 1] : fallback
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const cmd = argv.find(a => !a.startsWith('-')) || 'start'
|
|
23
|
+
const PORT = opt('--port', opt('-p', process.env.PORT || '7575'))
|
|
24
|
+
const DDIR = opt('--data', opt('-d', process.env.PERSONALAC_DATA || path.join(os.homedir(), '.personalac')))
|
|
25
|
+
const NOOPEN = flag('--no-open')
|
|
26
|
+
const URL = `http://localhost:${PORT}`
|
|
27
|
+
|
|
28
|
+
const PKG_ROOT = path.join(__dirname, '..')
|
|
29
|
+
const DIST_DIR = path.join(PKG_ROOT, 'dist')
|
|
30
|
+
const PUBLIC_DIR = path.join(PKG_ROOT, 'public')
|
|
31
|
+
|
|
32
|
+
// ── 帮助 ─────────────────────────────────────────────────────────────
|
|
33
|
+
const HELP = `
|
|
34
|
+
PersonalAC v${VER} — 个性化学习辅助系统
|
|
35
|
+
|
|
36
|
+
用法:
|
|
37
|
+
personalac [command] [options]
|
|
38
|
+
|
|
39
|
+
命令:
|
|
40
|
+
start 启动服务器(默认)
|
|
41
|
+
token 显示登录 Token
|
|
42
|
+
open 在浏览器中打开界面
|
|
43
|
+
status 检查服务器是否运行中
|
|
44
|
+
version 显示版本号
|
|
45
|
+
|
|
46
|
+
选项:
|
|
47
|
+
--port, -p <n> 端口号(默认 7575)
|
|
48
|
+
--data, -d <dir> 数据目录(默认 ~/.personalac)
|
|
49
|
+
--no-open 启动时不自动打开浏览器
|
|
50
|
+
--help, -h 显示此帮助
|
|
51
|
+
--version, -v 显示版本号
|
|
52
|
+
`
|
|
53
|
+
|
|
54
|
+
// ── 工具函数 ─────────────────────────────────────────────────────────
|
|
55
|
+
function openBrowser() {
|
|
56
|
+
const c = process.platform === 'darwin' ? `open "${URL}"` :
|
|
57
|
+
process.platform === 'win32' ? `start "" "${URL}"` : `xdg-open "${URL}"`
|
|
58
|
+
exec(c, err => { if (err) console.log(`\n 请手动打开: ${URL}\n`) })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function ping(cb) {
|
|
62
|
+
const req = http.get(`${URL}/api/auth/me`, { timeout: 1500 }, res => {
|
|
63
|
+
cb(res.statusCode === 200 || res.statusCode === 401)
|
|
64
|
+
})
|
|
65
|
+
req.on('error', () => cb(false))
|
|
66
|
+
req.on('timeout', () => { req.destroy(); cb(false) })
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getToken() {
|
|
70
|
+
const dbPath = path.join(DDIR, 'personalac.db')
|
|
71
|
+
if (!fs.existsSync(dbPath)) return null
|
|
72
|
+
try {
|
|
73
|
+
const Database = require('better-sqlite3')
|
|
74
|
+
const db = new Database(dbPath, { readonly: true })
|
|
75
|
+
const row = db.prepare("SELECT sync_token FROM User WHERE username='superadmin' AND delete_flag=0").get()
|
|
76
|
+
db.close()
|
|
77
|
+
return row ? row.sync_token : null
|
|
78
|
+
} catch { return null }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function checkBuilt() {
|
|
82
|
+
if (!fs.existsSync(path.join(DIST_DIR, 'index.js'))) {
|
|
83
|
+
console.error('\n[PersonalAC] 服务端未编译,请先运行:\n npm run build\n')
|
|
84
|
+
process.exit(1)
|
|
85
|
+
}
|
|
86
|
+
if (!fs.existsSync(path.join(PUBLIC_DIR, 'index.html'))) {
|
|
87
|
+
console.error('\n[PersonalAC] 前端未编译,请先运行:\n npm run build\n')
|
|
88
|
+
process.exit(1)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── 命令路由 ─────────────────────────────────────────────────────────
|
|
93
|
+
if (flag('--help') || flag('-h') || cmd === 'help') {
|
|
94
|
+
console.log(HELP); process.exit(0)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (flag('--version') || flag('-v') || cmd === 'version') {
|
|
98
|
+
console.log(`PersonalAC v${VER}`); process.exit(0)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (cmd === 'token') {
|
|
102
|
+
const t = getToken()
|
|
103
|
+
if (t) {
|
|
104
|
+
console.log(`\nSync Token: ${t}\n`)
|
|
105
|
+
console.log(`登录地址: ${URL}\n`)
|
|
106
|
+
} else {
|
|
107
|
+
console.log('\n尚未初始化,请先运行: personalac start\n')
|
|
108
|
+
}
|
|
109
|
+
process.exit(0)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (cmd === 'open') {
|
|
113
|
+
ping(running => {
|
|
114
|
+
if (running) {
|
|
115
|
+
openBrowser()
|
|
116
|
+
} else {
|
|
117
|
+
console.log(`\n服务器未运行,请先执行: personalac start\n`)
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (cmd === 'status') {
|
|
124
|
+
ping(running => {
|
|
125
|
+
if (running) {
|
|
126
|
+
console.log(`\n运行中 ${URL}`)
|
|
127
|
+
const t = getToken()
|
|
128
|
+
if (t) console.log(`Token ${t}`)
|
|
129
|
+
console.log()
|
|
130
|
+
} else {
|
|
131
|
+
console.log(`\n未运行 — 执行 personalac start 启动\n`)
|
|
132
|
+
}
|
|
133
|
+
process.exit(0)
|
|
134
|
+
})
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── 自我唤醒通知 ─────────────────────────────────────────────────────
|
|
139
|
+
// 在 study hours 内、学生长时间没有活动时推送 OS 系统通知
|
|
140
|
+
const NOTIFY_FILE = path.join(os.tmpdir(), 'personalac_notify.json')
|
|
141
|
+
const STUDY_HOUR_START = 8 // 08:00
|
|
142
|
+
const STUDY_HOUR_END = 22 // 22:00
|
|
143
|
+
const MIN_IDLE_MINUTES = 90 // 超过 90 分钟未活动才提醒
|
|
144
|
+
const CHECK_INTERVAL = 15 * 60 * 1000 // 每 15 分钟检查一次
|
|
145
|
+
|
|
146
|
+
function sendOsNotify(title, body) {
|
|
147
|
+
const p = process.platform
|
|
148
|
+
if (p === 'linux') {
|
|
149
|
+
exec(`notify-send -u normal -t 8000 "${title}" "${body}"`, () => {})
|
|
150
|
+
} else if (p === 'darwin') {
|
|
151
|
+
exec(`osascript -e 'display notification "${body}" with title "${title}" sound name "Ping"'`, () => {})
|
|
152
|
+
} else if (p === 'win32') {
|
|
153
|
+
// PowerShell toast (Windows 10+)
|
|
154
|
+
const ps = `[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType=WindowsRuntime] > $null
|
|
155
|
+
$template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)
|
|
156
|
+
$template.GetElementsByTagName('text')[0].AppendChild($template.CreateTextNode('${title}')) > $null
|
|
157
|
+
$template.GetElementsByTagName('text')[1].AppendChild($template.CreateTextNode('${body}')) > $null
|
|
158
|
+
[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier('PersonalAC').Show([Windows.UI.Notifications.ToastNotification]::new($template))`
|
|
159
|
+
exec(`powershell -Command "${ps.replace(/\n/g, '; ')}"`, () => {})
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function recordActivity() {
|
|
164
|
+
try { fs.writeFileSync(NOTIFY_FILE, JSON.stringify({ lastActivity: Date.now() })) } catch { /* ignore */ }
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function getLastActivity() {
|
|
168
|
+
try {
|
|
169
|
+
const d = JSON.parse(fs.readFileSync(NOTIFY_FILE, 'utf8'))
|
|
170
|
+
return d.lastActivity || 0
|
|
171
|
+
} catch { return 0 }
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const NUDGES = [
|
|
175
|
+
'该学习了!',
|
|
176
|
+
'知识不等人,打开 PersonalAC 看看今天的计划吧',
|
|
177
|
+
'距离上次学习已经有一段时间了,继续加油!',
|
|
178
|
+
'坚持每天学一点,进步看得见',
|
|
179
|
+
'今天还没打开学习记录?来开始吧',
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
function startWakeupScheduler() {
|
|
183
|
+
setInterval(() => {
|
|
184
|
+
const h = new Date().getHours()
|
|
185
|
+
if (h < STUDY_HOUR_START || h >= STUDY_HOUR_END) return // 夜间不打扰
|
|
186
|
+
|
|
187
|
+
const idleMs = Date.now() - getLastActivity()
|
|
188
|
+
if (idleMs < MIN_IDLE_MINUTES * 60 * 1000) return // 最近有活动,不打扰
|
|
189
|
+
|
|
190
|
+
const msg = NUDGES[Math.floor(Math.random() * NUDGES.length)]
|
|
191
|
+
sendOsNotify('PersonalAC 学习提醒', msg)
|
|
192
|
+
}, CHECK_INTERVAL)
|
|
193
|
+
|
|
194
|
+
// 监听来自服务器的活动心跳(每次 /api/chat/stream 调用都记录一次)
|
|
195
|
+
// 这里只注册一个定时检查;服务器会通过写文件来刷新 lastActivity
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// ── start(默认)────────────────────────────────────────────────────
|
|
199
|
+
if (cmd === 'start' || cmd === (argv.find(a => !a.startsWith('-')) || 'start')) {
|
|
200
|
+
checkBuilt()
|
|
201
|
+
fs.mkdirSync(DDIR, { recursive: true })
|
|
202
|
+
|
|
203
|
+
process.env.DATA_DIR = DDIR
|
|
204
|
+
process.env.PORT = PORT
|
|
205
|
+
process.env.CORS_ORIGIN = URL
|
|
206
|
+
process.env.FRONTEND_DIST = PUBLIC_DIR
|
|
207
|
+
process.env.NOTIFY_FILE = NOTIFY_FILE
|
|
208
|
+
|
|
209
|
+
if (!NOOPEN) setTimeout(openBrowser, 1800)
|
|
210
|
+
|
|
211
|
+
// 启动自我唤醒调度器
|
|
212
|
+
startWakeupScheduler()
|
|
213
|
+
|
|
214
|
+
require(path.join(DIST_DIR, 'index.js'))
|
|
215
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface AgentContextData {
|
|
2
|
+
studentId: string;
|
|
3
|
+
studentName: string;
|
|
4
|
+
activePlan: {
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
subjects: string[];
|
|
8
|
+
} | null;
|
|
9
|
+
weakPoints: Array<{
|
|
10
|
+
subject: string;
|
|
11
|
+
topic: string;
|
|
12
|
+
weakness_score: number;
|
|
13
|
+
attempt_count: number;
|
|
14
|
+
last_practiced: number | null;
|
|
15
|
+
}>;
|
|
16
|
+
recentRecords: Array<{
|
|
17
|
+
subject: string;
|
|
18
|
+
topic: string;
|
|
19
|
+
score: number | null;
|
|
20
|
+
duration_minutes: number;
|
|
21
|
+
record_date: number;
|
|
22
|
+
}>;
|
|
23
|
+
resources: Array<{
|
|
24
|
+
file_name: string;
|
|
25
|
+
subject: string | null;
|
|
26
|
+
file_type: string;
|
|
27
|
+
source_email: string | null;
|
|
28
|
+
}>;
|
|
29
|
+
recentSuggestions: Array<{
|
|
30
|
+
action_type: string;
|
|
31
|
+
action_detail: string | null;
|
|
32
|
+
create_time: number;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export declare class AgentContext {
|
|
36
|
+
buildContext(studentId: string): AgentContextData;
|
|
37
|
+
buildPrompt(studentId: string, task: string): string;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE;QACV,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,QAAQ,EAAE,MAAM,EAAE,CAAA;KACnB,GAAG,IAAI,CAAA;IACR,UAAU,EAAE,KAAK,CAAC;QAChB,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,cAAc,EAAE,MAAM,CAAA;QACtB,aAAa,EAAE,MAAM,CAAA;QACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;KAC9B,CAAC,CAAA;IACF,aAAa,EAAE,KAAK,CAAC;QACnB,OAAO,EAAE,MAAM,CAAA;QACf,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;QACpB,gBAAgB,EAAE,MAAM,CAAA;QACxB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAC,CAAA;IACF,SAAS,EAAE,KAAK,CAAC;QACf,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,SAAS,EAAE,MAAM,CAAA;QACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAC5B,CAAC,CAAA;IACF,iBAAiB,EAAE,KAAK,CAAC;QACvB,WAAW,EAAE,MAAM,CAAA;QACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;QAC5B,WAAW,EAAE,MAAM,CAAA;KACpB,CAAC,CAAA;CACH;AAED,qBAAa,YAAY;IACvB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,gBAAgB;IAwEjD,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;CAsHrD"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentContext = void 0;
|
|
4
|
+
const database_1 = require("../database");
|
|
5
|
+
class AgentContext {
|
|
6
|
+
buildContext(studentId) {
|
|
7
|
+
const db = (0, database_1.getDB)();
|
|
8
|
+
// SuperAdmin mode: no User table lookup needed
|
|
9
|
+
const studentName = studentId === 'superadmin' ? 'SuperAdmin' : studentId;
|
|
10
|
+
const planRow = db
|
|
11
|
+
.prepare("SELECT title, description, subjects FROM Plan WHERE student_id = ? AND status = 'active' AND delete_flag = 0 ORDER BY create_time DESC LIMIT 1")
|
|
12
|
+
.get(studentId);
|
|
13
|
+
const activePlan = planRow
|
|
14
|
+
? {
|
|
15
|
+
title: planRow.title,
|
|
16
|
+
description: planRow.description,
|
|
17
|
+
subjects: JSON.parse(planRow.subjects)
|
|
18
|
+
}
|
|
19
|
+
: null;
|
|
20
|
+
const weakPoints = db
|
|
21
|
+
.prepare(`SELECT subject, topic, weakness_score, attempt_count, last_practiced
|
|
22
|
+
FROM KnowledgePoint
|
|
23
|
+
WHERE student_id = ? AND delete_flag = 0
|
|
24
|
+
ORDER BY weakness_score DESC
|
|
25
|
+
LIMIT 10`)
|
|
26
|
+
.all(studentId);
|
|
27
|
+
const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
|
28
|
+
const recentRecords = db
|
|
29
|
+
.prepare(`SELECT subject, topic, score, duration_minutes, record_date
|
|
30
|
+
FROM LearningRecord
|
|
31
|
+
WHERE student_id = ? AND record_date >= ? AND delete_flag = 0
|
|
32
|
+
ORDER BY record_date DESC
|
|
33
|
+
LIMIT 20`)
|
|
34
|
+
.all(studentId, sevenDaysAgo);
|
|
35
|
+
const resources = db
|
|
36
|
+
.prepare(`SELECT file_name, subject, file_type, source_email
|
|
37
|
+
FROM Resource
|
|
38
|
+
WHERE delete_flag = 0
|
|
39
|
+
ORDER BY create_time DESC
|
|
40
|
+
LIMIT 20`)
|
|
41
|
+
.all();
|
|
42
|
+
const recentSuggestions = db
|
|
43
|
+
.prepare(`SELECT action_type, action_detail, create_time
|
|
44
|
+
FROM AgentLog
|
|
45
|
+
WHERE student_id = ? AND status = 'success' AND delete_flag = 0
|
|
46
|
+
ORDER BY create_time DESC
|
|
47
|
+
LIMIT 5`)
|
|
48
|
+
.all(studentId);
|
|
49
|
+
return {
|
|
50
|
+
studentId,
|
|
51
|
+
studentName,
|
|
52
|
+
activePlan,
|
|
53
|
+
weakPoints,
|
|
54
|
+
recentRecords,
|
|
55
|
+
resources,
|
|
56
|
+
recentSuggestions
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
buildPrompt(studentId, task) {
|
|
60
|
+
let context;
|
|
61
|
+
try {
|
|
62
|
+
context = this.buildContext(studentId);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
console.error('Failed to build context:', err);
|
|
66
|
+
return `你是一个个性化学习辅助 AI Agent。\n\n当前任务:${task}\n\n请根据情况提供建议。`;
|
|
67
|
+
}
|
|
68
|
+
const systemRole = `你是一个专业的个性化学习辅助 AI Agent,名为 PersonalAC。
|
|
69
|
+
你的职责是:分析学生的学习数据,识别薄弱知识点,生成个性化学习建议,并主动推送提醒。
|
|
70
|
+
你的回答应该简洁、专业、友好,适合中学生或大学生理解。
|
|
71
|
+
|
|
72
|
+
## 富文本输出格式说明
|
|
73
|
+
当你认为使用图表或知识卡片能更好地呈现信息时,可以在回答中使用以下格式:
|
|
74
|
+
|
|
75
|
+
### Mermaid 图表
|
|
76
|
+
如果需要展示知识结构、流程或思维导图,使用:
|
|
77
|
+
<MERMAID>
|
|
78
|
+
graph TD
|
|
79
|
+
A[概念A] --> B[概念B]
|
|
80
|
+
A --> C[概念C]
|
|
81
|
+
</MERMAID>
|
|
82
|
+
支持 graph、flowchart、mindmap、sequenceDiagram 等类型。
|
|
83
|
+
|
|
84
|
+
### 知识卡片
|
|
85
|
+
如果需要展示某个知识点的结构化卡片,使用:
|
|
86
|
+
<KNOWLEDGE_CARD>
|
|
87
|
+
{
|
|
88
|
+
"title": "知识点标题",
|
|
89
|
+
"subject": "科目",
|
|
90
|
+
"keyPoints": ["重点1", "重点2", "重点3"],
|
|
91
|
+
"formula": "LaTeX公式(可选)",
|
|
92
|
+
"example": "例题(可选)",
|
|
93
|
+
"tips": "记忆技巧(可选)",
|
|
94
|
+
"difficulty": "easy | medium | hard"
|
|
95
|
+
}
|
|
96
|
+
</KNOWLEDGE_CARD>
|
|
97
|
+
|
|
98
|
+
每次回答只能使用一个富文本块(MERMAID 或 KNOWLEDGE_CARD 二选一),其余内容以普通文本/Markdown 形式输出。`;
|
|
99
|
+
const planSection = context.activePlan
|
|
100
|
+
? `## 当前学习方向
|
|
101
|
+
标题:${context.activePlan.title}
|
|
102
|
+
描述:${context.activePlan.description}
|
|
103
|
+
科目:${context.activePlan.subjects.join('、')}`
|
|
104
|
+
: '## 当前学习方向\n(尚未设置学习方向)';
|
|
105
|
+
const weakSection = context.weakPoints.length > 0
|
|
106
|
+
? `## 薄弱知识点(按薄弱程度排序)
|
|
107
|
+
${context.weakPoints
|
|
108
|
+
.map((p, i) => `${i + 1}. [${p.subject}] ${p.topic} - 薄弱度: ${(p.weakness_score * 100).toFixed(0)}%,练习次数: ${p.attempt_count}`)
|
|
109
|
+
.join('\n')}`
|
|
110
|
+
: '## 薄弱知识点\n(暂无数据)';
|
|
111
|
+
const recentSection = context.recentRecords.length > 0
|
|
112
|
+
? `## 最近7天学习记录
|
|
113
|
+
${context.recentRecords
|
|
114
|
+
.slice(0, 10)
|
|
115
|
+
.map((r) => `- [${r.subject}] ${r.topic},得分: ${r.score ?? '未记录'},时长: ${r.duration_minutes} 分钟`)
|
|
116
|
+
.join('\n')}`
|
|
117
|
+
: '## 最近学习记录\n(暂无数据)';
|
|
118
|
+
const resourceSection = context.resources.length > 0
|
|
119
|
+
? `## 可用学习资源
|
|
120
|
+
${context.resources.map((r) => `- ${r.file_name} [${r.subject || '通用'}] (.${r.file_type})${r.source_email ? ' 来自邮件:' + r.source_email : ''}`).join('\n')}`
|
|
121
|
+
: '## 可用学习资源\n(暂无资源)';
|
|
122
|
+
const suggestionSection = context.recentSuggestions.length > 0
|
|
123
|
+
? `## 最近 Agent 建议(避免重复)
|
|
124
|
+
${context.recentSuggestions.map((s) => `- [${s.action_type}] ${s.action_detail || ''}`).join('\n')}`
|
|
125
|
+
: '';
|
|
126
|
+
return `${systemRole}
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
# 学生信息
|
|
131
|
+
学生名称:${context.studentName}
|
|
132
|
+
学生ID:${context.studentId}
|
|
133
|
+
|
|
134
|
+
${planSection}
|
|
135
|
+
|
|
136
|
+
${weakSection}
|
|
137
|
+
|
|
138
|
+
${recentSection}
|
|
139
|
+
|
|
140
|
+
${resourceSection}
|
|
141
|
+
|
|
142
|
+
${suggestionSection}
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
# 当前任务
|
|
147
|
+
${task}
|
|
148
|
+
|
|
149
|
+
请以 JSON 格式返回你的决策,格式如下:
|
|
150
|
+
{
|
|
151
|
+
"thinking": "你的分析过程",
|
|
152
|
+
"actions": [
|
|
153
|
+
{
|
|
154
|
+
"type": "push_suggestion | send_bot_message | set_schedule | update_weakness | no_action | generate_diagram | proactive_report | daily_review | weakness_quiz",
|
|
155
|
+
"detail": "动作详情(如使用富文本输出,将 MERMAID 或 KNOWLEDGE_CARD 标签放在 detail 字段中)",
|
|
156
|
+
"priority": "high | medium | low"
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.AgentContext = AgentContext;
|
|
163
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/agent/context.ts"],"names":[],"mappings":"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"}
|