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.
@@ -509,8 +509,44 @@ app.get('/api/plugins', (req, res) => {
509
509
  });
510
510
  // 存储 OAuth 状态以防止 CSRF 攻击
511
511
  const oauthStates = new Map();
512
- // 模拟的 Token 存储 (实际应存入 SQLite 或加密文件)
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xiaozuoassistant",
3
- "version": "0.2.49",
3
+ "version": "0.2.50",
4
4
  "description": "A local-first personal AI assistant with multi-channel support and enhanced memory.",
5
5
  "author": "mantle.lau",
6
6
  "license": "MIT",