@qnote/q-ai-note 1.0.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 +50 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +55 -0
- package/dist/cli.js.map +1 -0
- package/dist/server/aiClient.d.ts +11 -0
- package/dist/server/aiClient.d.ts.map +1 -0
- package/dist/server/aiClient.js +83 -0
- package/dist/server/aiClient.js.map +1 -0
- package/dist/server/api/batchRecovery.d.ts +11 -0
- package/dist/server/api/batchRecovery.d.ts.map +1 -0
- package/dist/server/api/batchRecovery.js +68 -0
- package/dist/server/api/batchRecovery.js.map +1 -0
- package/dist/server/api/chat.d.ts +3 -0
- package/dist/server/api/chat.d.ts.map +1 -0
- package/dist/server/api/chat.js +485 -0
- package/dist/server/api/chat.js.map +1 -0
- package/dist/server/api/diary.d.ts +3 -0
- package/dist/server/api/diary.d.ts.map +1 -0
- package/dist/server/api/diary.js +102 -0
- package/dist/server/api/diary.js.map +1 -0
- package/dist/server/api/sandbox.d.ts +3 -0
- package/dist/server/api/sandbox.d.ts.map +1 -0
- package/dist/server/api/sandbox.js +87 -0
- package/dist/server/api/sandbox.js.map +1 -0
- package/dist/server/api/settings.d.ts +3 -0
- package/dist/server/api/settings.d.ts.map +1 -0
- package/dist/server/api/settings.js +45 -0
- package/dist/server/api/settings.js.map +1 -0
- package/dist/server/api/workItem.d.ts +3 -0
- package/dist/server/api/workItem.d.ts.map +1 -0
- package/dist/server/api/workItem.js +290 -0
- package/dist/server/api/workItem.js.map +1 -0
- package/dist/server/chatUtils.d.ts +15 -0
- package/dist/server/chatUtils.d.ts.map +1 -0
- package/dist/server/chatUtils.js +52 -0
- package/dist/server/chatUtils.js.map +1 -0
- package/dist/server/config.d.ts +14 -0
- package/dist/server/config.d.ts.map +1 -0
- package/dist/server/config.js +56 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/db.d.ts +6 -0
- package/dist/server/db.d.ts.map +1 -0
- package/dist/server/db.js +106 -0
- package/dist/server/db.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +72 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/react/agent.d.ts +56 -0
- package/dist/server/react/agent.d.ts.map +1 -0
- package/dist/server/react/agent.js +219 -0
- package/dist/server/react/agent.js.map +1 -0
- package/dist/server/react/prompts.d.ts +13 -0
- package/dist/server/react/prompts.d.ts.map +1 -0
- package/dist/server/react/prompts.js +84 -0
- package/dist/server/react/prompts.js.map +1 -0
- package/dist/server/react/tools.d.ts +67 -0
- package/dist/server/react/tools.d.ts.map +1 -0
- package/dist/server/react/tools.js +208 -0
- package/dist/server/react/tools.js.map +1 -0
- package/dist/server/types.d.ts +59 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/web/app.js +1081 -0
- package/dist/web/chatView.js +31 -0
- package/dist/web/index.html +218 -0
- package/dist/web/shared.js +49 -0
- package/dist/web/styles.css +1320 -0
- package/dist/web/vueRenderers.js +191 -0
- package/package.json +46 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function tryParseAssistantAction(content) {
|
|
2
|
+
if (typeof content !== 'string' || !content.trim().startsWith('{')) {
|
|
3
|
+
return null;
|
|
4
|
+
}
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(content);
|
|
7
|
+
if (parsed && typeof parsed.action === 'string') {
|
|
8
|
+
return parsed;
|
|
9
|
+
}
|
|
10
|
+
return null;
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function renderChatEntry(chat, helpers) {
|
|
17
|
+
const { safeText, renderAIActionMessage } = helpers;
|
|
18
|
+
|
|
19
|
+
if (!('role' in chat)) {
|
|
20
|
+
return `<div class="chat-message diary">[日记] ${safeText(chat.content)}</div>`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (chat.role === 'assistant') {
|
|
24
|
+
const parsedAction = tryParseAssistantAction(chat.content);
|
|
25
|
+
if (parsedAction) {
|
|
26
|
+
return renderAIActionMessage(parsedAction);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return `<div class="chat-message ${chat.role}">${safeText(chat.content)}</div>`;
|
|
31
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="zh-CN">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Personal AI Notebook</title>
|
|
7
|
+
<link rel="stylesheet" href="/styles.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="app">
|
|
11
|
+
<nav class="sidebar">
|
|
12
|
+
<div class="sidebar-header">
|
|
13
|
+
<h1>AI Notebook</h1>
|
|
14
|
+
</div>
|
|
15
|
+
<ul class="nav-list">
|
|
16
|
+
<li><a href="#/" data-nav="home">对话</a></li>
|
|
17
|
+
<li><a href="#/sandboxes" data-nav="sandboxes">沙盘</a></li>
|
|
18
|
+
<li><a href="#/diaries" data-nav="diaries">日记</a></li>
|
|
19
|
+
<li><a href="#/changes" data-nav="changes">变化</a></li>
|
|
20
|
+
<li><a href="#/settings" data-nav="settings">设置</a></li>
|
|
21
|
+
</ul>
|
|
22
|
+
</nav>
|
|
23
|
+
<main class="content">
|
|
24
|
+
<div id="page-home" class="page">
|
|
25
|
+
<h2>对话</h2>
|
|
26
|
+
<div class="chat-container">
|
|
27
|
+
<div id="chat-messages" class="chat-messages"></div>
|
|
28
|
+
<div class="chat-input">
|
|
29
|
+
<input type="text" id="chat-input" placeholder="输入消息...">
|
|
30
|
+
<button id="send-btn">发送</button>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div id="page-sandboxes" class="page hidden">
|
|
36
|
+
<h2>沙盘</h2>
|
|
37
|
+
<div class="summary-strip" id="sandboxes-summary"></div>
|
|
38
|
+
<div class="sandbox-grid" id="sandbox-grid"></div>
|
|
39
|
+
<button class="btn btn-primary" id="add-sandbox-btn">+ 新建沙盘</button>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div id="page-sandbox-detail" class="page hidden">
|
|
43
|
+
<a href="#/sandboxes" class="back-link">← 返回</a>
|
|
44
|
+
<h2 id="sandbox-title">沙盘</h2>
|
|
45
|
+
<div class="summary-strip" id="sandbox-overview"></div>
|
|
46
|
+
<div class="action-strip">
|
|
47
|
+
<button class="btn btn-secondary btn-sm" id="generate-insight-btn">智能总结</button>
|
|
48
|
+
<button class="btn btn-secondary btn-sm" id="generate-report-btn">生成汇报</button>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="insight-box hidden" id="sandbox-insight-output"></div>
|
|
51
|
+
<div class="sandbox-layout">
|
|
52
|
+
<div class="sandbox-tree-section">
|
|
53
|
+
<div class="section-header">
|
|
54
|
+
<span>工作项</span>
|
|
55
|
+
<div class="inline-actions">
|
|
56
|
+
<input type="text" id="work-item-search" placeholder="搜索任务">
|
|
57
|
+
<select id="work-item-status-filter">
|
|
58
|
+
<option value="all">全部状态</option>
|
|
59
|
+
<option value="pending">待处理</option>
|
|
60
|
+
<option value="in_progress">进行中</option>
|
|
61
|
+
<option value="done">已完成</option>
|
|
62
|
+
<option value="archived">已归档</option>
|
|
63
|
+
</select>
|
|
64
|
+
<button class="btn btn-primary btn-sm" id="add-item-btn">+ 添加</button>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div class="work-tree" id="work-tree"></div>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="sandbox-chat-section">
|
|
70
|
+
<div class="section-header">
|
|
71
|
+
<span>AI 助手</span>
|
|
72
|
+
</div>
|
|
73
|
+
<div class="chat-container">
|
|
74
|
+
<div id="sandbox-chat-messages" class="chat-messages"></div>
|
|
75
|
+
<div class="chat-input">
|
|
76
|
+
<input type="text" id="sandbox-chat-input" placeholder="输入指令或问题...">
|
|
77
|
+
<button id="sandbox-send-btn">发送</button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div id="page-diaries" class="page hidden">
|
|
85
|
+
<h2>日记</h2>
|
|
86
|
+
<div class="action-strip">
|
|
87
|
+
<input type="text" id="diary-search" placeholder="搜索日记内容">
|
|
88
|
+
<select id="diary-processed-filter">
|
|
89
|
+
<option value="all">全部处理状态</option>
|
|
90
|
+
<option value="unprocessed">仅未处理</option>
|
|
91
|
+
<option value="processed">仅已处理</option>
|
|
92
|
+
</select>
|
|
93
|
+
</div>
|
|
94
|
+
<div class="diary-form">
|
|
95
|
+
<select id="diary-sandbox-select">
|
|
96
|
+
<option value="">关联沙盘(可选)</option>
|
|
97
|
+
</select>
|
|
98
|
+
<textarea id="diary-content" placeholder="记录日记..."></textarea>
|
|
99
|
+
<button class="btn btn-primary" id="save-diary-btn">保存</button>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="diary-timeline" id="diary-timeline"></div>
|
|
102
|
+
</div>
|
|
103
|
+
|
|
104
|
+
<div id="page-changes" class="page hidden">
|
|
105
|
+
<h2>变化追踪</h2>
|
|
106
|
+
<div class="action-strip">
|
|
107
|
+
<select id="changes-sandbox-filter">
|
|
108
|
+
<option value="">全部沙盘</option>
|
|
109
|
+
</select>
|
|
110
|
+
<select id="changes-type-filter">
|
|
111
|
+
<option value="all">全部操作</option>
|
|
112
|
+
<option value="create">创建</option>
|
|
113
|
+
<option value="update">更新</option>
|
|
114
|
+
<option value="delete">删除</option>
|
|
115
|
+
</select>
|
|
116
|
+
<select id="changes-quick-filter">
|
|
117
|
+
<option value="all">全部变化</option>
|
|
118
|
+
<option value="key">仅关键变化(状态/高优先级)</option>
|
|
119
|
+
</select>
|
|
120
|
+
<button class="btn btn-secondary btn-sm" id="refresh-changes-btn">刷新</button>
|
|
121
|
+
<button class="btn btn-primary btn-sm" id="export-weekly-summary-btn">导出周报摘要</button>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="changes-list" id="changes-list"></div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<div id="page-settings" class="page hidden">
|
|
127
|
+
<h2>设置</h2>
|
|
128
|
+
<div class="settings-form">
|
|
129
|
+
<div class="setting-group">
|
|
130
|
+
<label>API URL</label>
|
|
131
|
+
<input type="text" id="setting-api-url" placeholder="https://api.minimax.io/v1">
|
|
132
|
+
</div>
|
|
133
|
+
<div class="setting-group">
|
|
134
|
+
<label>API Key</label>
|
|
135
|
+
<input type="password" id="setting-api-key" placeholder="sk-...">
|
|
136
|
+
</div>
|
|
137
|
+
<div class="setting-group">
|
|
138
|
+
<label>Model</label>
|
|
139
|
+
<input type="text" id="setting-model" placeholder="abab6.5s-chat">
|
|
140
|
+
</div>
|
|
141
|
+
<button class="btn btn-primary" id="save-settings-btn">保存</button>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</main>
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<dialog id="sandbox-dialog">
|
|
148
|
+
<div class="dialog-content">
|
|
149
|
+
<h3>新建沙盘</h3>
|
|
150
|
+
<input type="text" id="new-sandbox-name" placeholder="沙盘名称" required>
|
|
151
|
+
<textarea id="new-sandbox-desc" placeholder="描述(可选)" rows="3"></textarea>
|
|
152
|
+
</div>
|
|
153
|
+
<div class="dialog-actions">
|
|
154
|
+
<button type="button" class="cancel" id="cancel-sandbox-btn">取消</button>
|
|
155
|
+
<button type="button" class="submit" id="confirm-sandbox-btn">创建</button>
|
|
156
|
+
</div>
|
|
157
|
+
</dialog>
|
|
158
|
+
|
|
159
|
+
<dialog id="item-dialog">
|
|
160
|
+
<div class="dialog-content">
|
|
161
|
+
<h3 id="item-dialog-title">添加任务</h3>
|
|
162
|
+
<input type="text" id="new-item-name" placeholder="任务名称" required>
|
|
163
|
+
<textarea id="new-item-desc" placeholder="描述" rows="2"></textarea>
|
|
164
|
+
<input type="text" id="new-item-assignee" placeholder="负责人">
|
|
165
|
+
<select id="new-item-status">
|
|
166
|
+
<option value="pending">待处理</option>
|
|
167
|
+
<option value="in_progress">进行中</option>
|
|
168
|
+
<option value="done">已完成</option>
|
|
169
|
+
<option value="archived">已归档</option>
|
|
170
|
+
</select>
|
|
171
|
+
<select id="new-item-priority">
|
|
172
|
+
<option value="low">低优先级</option>
|
|
173
|
+
<option value="medium">中优先级</option>
|
|
174
|
+
<option value="high">高优先级</option>
|
|
175
|
+
</select>
|
|
176
|
+
<select id="new-item-parent">
|
|
177
|
+
<option value="">顶级任务</option>
|
|
178
|
+
</select>
|
|
179
|
+
</div>
|
|
180
|
+
<div class="dialog-actions">
|
|
181
|
+
<button type="button" class="cancel" id="cancel-item-btn">取消</button>
|
|
182
|
+
<button type="button" class="submit" id="confirm-item-btn">保存</button>
|
|
183
|
+
</div>
|
|
184
|
+
</dialog>
|
|
185
|
+
|
|
186
|
+
<dialog id="report-dialog">
|
|
187
|
+
<div class="dialog-content">
|
|
188
|
+
<h3>沙盘汇报</h3>
|
|
189
|
+
<select id="report-template">
|
|
190
|
+
<option value="management">管理层版(概览与风险)</option>
|
|
191
|
+
<option value="execution">执行层版(任务与动作)</option>
|
|
192
|
+
</select>
|
|
193
|
+
<textarea id="report-content" rows="16" readonly></textarea>
|
|
194
|
+
</div>
|
|
195
|
+
<div class="dialog-actions">
|
|
196
|
+
<button type="button" class="cancel" id="close-report-btn">关闭</button>
|
|
197
|
+
<button type="button" class="submit" id="copy-report-btn">复制</button>
|
|
198
|
+
</div>
|
|
199
|
+
</dialog>
|
|
200
|
+
|
|
201
|
+
<dialog id="weekly-summary-dialog">
|
|
202
|
+
<div class="dialog-content">
|
|
203
|
+
<h3>变化周报摘要</h3>
|
|
204
|
+
<select id="weekly-summary-template">
|
|
205
|
+
<option value="management">管理层版(概览与关注项)</option>
|
|
206
|
+
<option value="execution">执行层版(任务变化明细)</option>
|
|
207
|
+
</select>
|
|
208
|
+
<textarea id="weekly-summary-content" rows="16" readonly></textarea>
|
|
209
|
+
</div>
|
|
210
|
+
<div class="dialog-actions">
|
|
211
|
+
<button class="btn btn-secondary" id="close-weekly-summary-btn">关闭</button>
|
|
212
|
+
<button class="btn btn-primary" id="copy-weekly-summary-btn">复制摘要</button>
|
|
213
|
+
</div>
|
|
214
|
+
</dialog>
|
|
215
|
+
|
|
216
|
+
<script type="module" src="/app.js"></script>
|
|
217
|
+
</body>
|
|
218
|
+
</html>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const API_BASE = '/api';
|
|
2
|
+
|
|
3
|
+
export async function apiRequest(url, options = {}) {
|
|
4
|
+
const response = await fetch(url, {
|
|
5
|
+
...options,
|
|
6
|
+
headers: {
|
|
7
|
+
'Content-Type': 'application/json',
|
|
8
|
+
...options.headers,
|
|
9
|
+
},
|
|
10
|
+
});
|
|
11
|
+
const result = await response.json();
|
|
12
|
+
if (!result.success) {
|
|
13
|
+
throw new Error(result.error);
|
|
14
|
+
}
|
|
15
|
+
return result.data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function escapeHtml(text) {
|
|
19
|
+
const div = document.createElement('div');
|
|
20
|
+
div.textContent = text;
|
|
21
|
+
return div.innerHTML;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function safeText(value) {
|
|
25
|
+
return escapeHtml(String(value ?? ''));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function appendLoadingMessage(container, text = 'AI思考中...') {
|
|
29
|
+
if (!container) return null;
|
|
30
|
+
const loading = document.createElement('div');
|
|
31
|
+
loading.className = 'chat-message assistant loading';
|
|
32
|
+
const dots = document.createElement('span');
|
|
33
|
+
dots.className = 'loading-dots';
|
|
34
|
+
dots.textContent = text;
|
|
35
|
+
loading.appendChild(dots);
|
|
36
|
+
container.appendChild(loading);
|
|
37
|
+
return loading;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function setButtonState(button, options = {}) {
|
|
41
|
+
if (!button) return;
|
|
42
|
+
const { disabled, text } = options;
|
|
43
|
+
if (typeof disabled === 'boolean') {
|
|
44
|
+
button.disabled = disabled;
|
|
45
|
+
}
|
|
46
|
+
if (typeof text === 'string') {
|
|
47
|
+
button.textContent = text;
|
|
48
|
+
}
|
|
49
|
+
}
|