xiaozuoassistant 0.2.49 → 0.2.50
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/dist/server/index.js
CHANGED
|
@@ -509,8 +509,44 @@ app.get('/api/plugins', (req, res) => {
|
|
|
509
509
|
});
|
|
510
510
|
// 存储 OAuth 状态以防止 CSRF 攻击
|
|
511
511
|
const oauthStates = new Map();
|
|
512
|
-
// 模拟的 Token 存储 (
|
|
512
|
+
// 模拟的 Token 存储 (持久化到文件)
|
|
513
|
+
const tokensFilePath = path.join(process.cwd(), 'data', 'oauth-tokens.json');
|
|
513
514
|
const oauthTokens = new Map();
|
|
515
|
+
// 初始化时加载 Token
|
|
516
|
+
try {
|
|
517
|
+
if (fs.existsSync(tokensFilePath)) {
|
|
518
|
+
const data = JSON.parse(fs.readFileSync(tokensFilePath, 'utf8'));
|
|
519
|
+
for (const key of Object.keys(data)) {
|
|
520
|
+
oauthTokens.set(key, data[key]);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
catch (e) {
|
|
525
|
+
console.warn('[OAuth] Failed to load tokens:', e);
|
|
526
|
+
}
|
|
527
|
+
function saveTokens() {
|
|
528
|
+
try {
|
|
529
|
+
const dir = path.dirname(tokensFilePath);
|
|
530
|
+
if (!fs.existsSync(dir))
|
|
531
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
532
|
+
const data = Object.fromEntries(oauthTokens);
|
|
533
|
+
fs.writeFileSync(tokensFilePath, JSON.stringify(data, null, 2));
|
|
534
|
+
}
|
|
535
|
+
catch (e) {
|
|
536
|
+
console.error('[OAuth] Failed to save tokens:', e);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
// 暴露一个简单的内部 API 供插件获取 Token
|
|
540
|
+
app.get('/internal/api/auth/tokens/:provider', (req, res) => {
|
|
541
|
+
// 这个接口仅供本地/内部调用
|
|
542
|
+
const token = oauthTokens.get(req.params.provider);
|
|
543
|
+
if (token) {
|
|
544
|
+
res.json(token);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
res.status(404).json({ error: 'Token not found' });
|
|
548
|
+
}
|
|
549
|
+
});
|
|
514
550
|
// Mock OAuth 授权接口
|
|
515
551
|
app.get('/api/auth/:provider/authorize', (req, res) => {
|
|
516
552
|
const provider = req.params.provider;
|
|
@@ -583,7 +619,8 @@ app.get('/api/auth/:provider/callback', async (req, res) => {
|
|
|
583
619
|
headers: { 'Authorization': `Bearer ${appAccessToken}` }
|
|
584
620
|
});
|
|
585
621
|
tokenData = userTokenRes.data.data;
|
|
586
|
-
oauthTokens.set('lark', tokenData);
|
|
622
|
+
oauthTokens.set('lark', tokenData);
|
|
623
|
+
saveTokens();
|
|
587
624
|
}
|
|
588
625
|
else if (provider === 'wps') {
|
|
589
626
|
const appId = process.env.WPS_APP_ID || '';
|
|
@@ -599,7 +636,8 @@ app.get('/api/auth/:provider/callback', async (req, res) => {
|
|
|
599
636
|
code: code
|
|
600
637
|
});
|
|
601
638
|
tokenData = tokenRes.data;
|
|
602
|
-
oauthTokens.set('wps', tokenData);
|
|
639
|
+
oauthTokens.set('wps', tokenData);
|
|
640
|
+
saveTokens();
|
|
603
641
|
}
|
|
604
642
|
console.log(`[OAuth] Successfully authenticated with ${provider}`);
|
|
605
643
|
// 更新内存中的插件状态为已启用
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { BaseSkill } from '../../../skills/base-skill.js';
|
|
2
2
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
// 获取可能通过网页授权获取到的 user_access_token
|
|
6
|
+
function getUserAccessToken() {
|
|
7
|
+
try {
|
|
8
|
+
const tokensFilePath = path.join(process.cwd(), 'data', 'oauth-tokens.json');
|
|
9
|
+
if (fs.existsSync(tokensFilePath)) {
|
|
10
|
+
const data = JSON.parse(fs.readFileSync(tokensFilePath, 'utf8'));
|
|
11
|
+
if (data.lark && data.lark.access_token) {
|
|
12
|
+
return data.lark.access_token;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch (e) {
|
|
17
|
+
// Ignore errors
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
3
21
|
// Helper function to resolve document token, especially handling /wiki/ URLs
|
|
4
22
|
async function resolveDocumentToken(client, urlOrToken) {
|
|
5
23
|
let token = urlOrToken;
|
|
@@ -19,10 +37,12 @@ async function resolveDocumentToken(client, urlOrToken) {
|
|
|
19
37
|
else if (urlOrToken.startsWith('wikcn')) {
|
|
20
38
|
isWiki = true;
|
|
21
39
|
}
|
|
40
|
+
const userToken = getUserAccessToken();
|
|
41
|
+
const options = userToken ? lark.withUserAccessToken(userToken) : undefined;
|
|
22
42
|
if (isWiki) {
|
|
23
43
|
const res = await client.wiki.space.getNode({
|
|
24
44
|
params: { token }
|
|
25
|
-
});
|
|
45
|
+
}, options);
|
|
26
46
|
if (res.code !== 0) {
|
|
27
47
|
throw new Error(`Failed to resolve wiki token. Code: ${res.code}, Msg: ${res.msg}`);
|
|
28
48
|
}
|
|
@@ -96,11 +116,13 @@ export class ReadLarkDocSkill extends BaseSkill {
|
|
|
96
116
|
}
|
|
97
117
|
// We use the drive/v1/export API or docx/v1/documents API to read content
|
|
98
118
|
// Let's try the newer DOCX API first to get raw content
|
|
119
|
+
const userToken = getUserAccessToken();
|
|
120
|
+
const options = userToken ? lark.withUserAccessToken(userToken) : undefined;
|
|
99
121
|
const res = await client.docx.document.rawContent({
|
|
100
122
|
path: {
|
|
101
123
|
document_id: documentToken,
|
|
102
124
|
},
|
|
103
|
-
});
|
|
125
|
+
}, options);
|
|
104
126
|
if (res.code !== 0) {
|
|
105
127
|
return { error: `Failed to read Lark document. Code: ${res.code}, Msg: ${res.msg}. Make sure the App has the "docs:doc:readonly" permission and has been added as a collaborator to the document.` };
|
|
106
128
|
}
|
|
@@ -167,12 +189,14 @@ export class CreateLarkDocSkill extends BaseSkill {
|
|
|
167
189
|
}
|
|
168
190
|
}
|
|
169
191
|
const client = new lark.Client({ appId: appId, appSecret: appSecret });
|
|
192
|
+
const userToken = getUserAccessToken();
|
|
193
|
+
const options = userToken ? lark.withUserAccessToken(userToken) : undefined;
|
|
170
194
|
const res = await client.docx.document.create({
|
|
171
195
|
data: {
|
|
172
196
|
title: args.title,
|
|
173
197
|
folder_token: args.folder_token || ''
|
|
174
198
|
}
|
|
175
|
-
});
|
|
199
|
+
}, options);
|
|
176
200
|
if (res.code !== 0) {
|
|
177
201
|
return { error: `Failed to create document. Code: ${res.code}, Msg: ${res.msg}` };
|
|
178
202
|
}
|
|
@@ -253,6 +277,8 @@ export class AppendLarkDocSkill extends BaseSkill {
|
|
|
253
277
|
}));
|
|
254
278
|
if (children.length === 0)
|
|
255
279
|
return { success: true, message: 'Nothing to append' };
|
|
280
|
+
const userToken = getUserAccessToken();
|
|
281
|
+
const options = userToken ? lark.withUserAccessToken(userToken) : undefined;
|
|
256
282
|
const res = await client.docx.documentBlockChildren.create({
|
|
257
283
|
path: {
|
|
258
284
|
document_id: documentToken,
|
|
@@ -262,7 +288,7 @@ export class AppendLarkDocSkill extends BaseSkill {
|
|
|
262
288
|
children: children,
|
|
263
289
|
index: -1
|
|
264
290
|
}
|
|
265
|
-
});
|
|
291
|
+
}, options);
|
|
266
292
|
if (res.code !== 0) {
|
|
267
293
|
return { error: `Failed to append to document. Code: ${res.code}, Msg: ${res.msg}` };
|
|
268
294
|
}
|