feishu-user-plugin 1.3.6 → 1.3.8
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/.claude-plugin/plugin.json +2 -2
- package/CHANGELOG.md +71 -0
- package/README.md +72 -41
- package/package.json +10 -3
- package/scripts/capture-feishu-protobuf.js +86 -0
- package/scripts/check-changelog.js +31 -0
- package/scripts/check-docs-sync.js +41 -0
- package/scripts/check-tool-count.js +40 -0
- package/scripts/check-version.js +40 -0
- package/scripts/decode-feishu-protobuf.js +115 -0
- package/scripts/smoke.js +224 -0
- package/scripts/sync-claude-md.sh +12 -0
- package/scripts/sync-server-json.js +71 -0
- package/scripts/sync-team-skills.sh +22 -0
- package/scripts/test-all-tools.js +158 -0
- package/scripts/test-wiki-attach-fallback.js +71 -0
- package/scripts/test-ws-events.js +84 -0
- package/skills/feishu-user-plugin/SKILL.md +5 -5
- package/skills/feishu-user-plugin/references/CLAUDE.md +248 -318
- package/skills/feishu-user-plugin/references/table.md +18 -9
- package/src/auth/cookie.js +30 -0
- package/src/auth/credentials.js +399 -0
- package/src/auth/profile-router.js +248 -0
- package/src/auth/uat.js +231 -0
- package/src/cli.js +45 -13
- package/src/clients/official/base.js +188 -0
- package/src/clients/official/bitable.js +269 -0
- package/src/clients/official/calendar.js +176 -0
- package/src/clients/official/contacts.js +54 -0
- package/src/clients/official/docs.js +301 -0
- package/src/clients/official/drive.js +77 -0
- package/src/clients/official/groups.js +68 -0
- package/src/clients/official/im.js +414 -0
- package/src/clients/official/index.js +30 -0
- package/src/clients/official/okr.js +127 -0
- package/src/clients/official/tasks.js +142 -0
- package/src/clients/official/uploads.js +260 -0
- package/src/clients/official/wiki.js +207 -0
- package/src/{client.js → clients/user.js} +25 -33
- package/src/config.js +13 -8
- package/src/events/event-buffer.js +100 -0
- package/src/events/index.js +5 -0
- package/src/events/ws-server.js +86 -0
- package/src/index.js +4 -1977
- package/src/logger.js +20 -0
- package/src/oauth.js +5 -1
- package/src/official.js +5 -1944
- package/src/prompts/_registry.js +69 -0
- package/src/prompts/index.js +54 -0
- package/src/server.js +305 -0
- package/src/setup.js +16 -1
- package/src/test-all.js +2 -2
- package/src/test-comprehensive.js +3 -3
- package/src/test-send.js +1 -1
- package/src/tools/_registry.js +31 -0
- package/src/tools/bitable.js +246 -0
- package/src/tools/calendar.js +207 -0
- package/src/tools/contacts.js +66 -0
- package/src/tools/diagnostics.js +172 -0
- package/src/tools/docs.js +158 -0
- package/src/tools/drive.js +111 -0
- package/src/tools/events.js +64 -0
- package/src/tools/groups.js +81 -0
- package/src/tools/im-read.js +259 -0
- package/src/tools/messaging-bot.js +151 -0
- package/src/tools/messaging-user.js +292 -0
- package/src/tools/okr.js +159 -0
- package/src/tools/profile.js +74 -0
- package/src/tools/tasks.js +168 -0
- package/src/tools/uploads.js +63 -0
- package/src/tools/wiki.js +191 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
// Manual e2e: spawn MCP server, wait for WS connect, send a message to a test
|
|
4
|
+
// chat (configurable via TEST_CHAT_ID env), then call get_new_events and verify
|
|
5
|
+
// the message appears.
|
|
6
|
+
//
|
|
7
|
+
// Skipped on CI (POSIX 77) when no LARK_APP_ID/SECRET/UAT or no TEST_CHAT_ID.
|
|
8
|
+
|
|
9
|
+
const { spawn } = require('child_process');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { readCredentials } = require('../src/auth/credentials');
|
|
12
|
+
|
|
13
|
+
const creds = readCredentials();
|
|
14
|
+
const TEST_CHAT_ID = process.env.TEST_CHAT_ID;
|
|
15
|
+
if (!creds.LARK_APP_ID || !creds.LARK_APP_SECRET || !TEST_CHAT_ID) {
|
|
16
|
+
console.error('Skipped: needs LARK_APP_ID/SECRET (real, not mock) and TEST_CHAT_ID env.');
|
|
17
|
+
process.exit(77);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
(async () => {
|
|
21
|
+
console.log('Spawning MCP server with WS...');
|
|
22
|
+
const child = spawn('node', [path.join(__dirname, '..', 'src', 'index.js')], {
|
|
23
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
24
|
+
env: process.env,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
let buf = ''; const responses = new Map();
|
|
28
|
+
child.stdout.on('data', (d) => {
|
|
29
|
+
buf += d.toString();
|
|
30
|
+
const lines = buf.split('\n'); buf = lines.pop();
|
|
31
|
+
for (const line of lines) try { const m = JSON.parse(line); if (m.id != null) responses.set(m.id, m); } catch {}
|
|
32
|
+
});
|
|
33
|
+
let wsConnected = false;
|
|
34
|
+
child.stderr.on('data', (d) => {
|
|
35
|
+
const s = d.toString();
|
|
36
|
+
process.stderr.write(' child: ' + s);
|
|
37
|
+
if (/WS connected/i.test(s)) wsConnected = true;
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const send = (id, method, params) => child.stdin.write(JSON.stringify({jsonrpc:'2.0', id, method, params})+'\n');
|
|
41
|
+
const wait = (id, ms = 10000) => new Promise((res, rej) => {
|
|
42
|
+
const t = setInterval(() => { if (responses.has(id)) { clearInterval(t); res(responses.get(id)); } }, 50);
|
|
43
|
+
setTimeout(() => { clearInterval(t); rej(new Error('timeout id=' + id)); }, ms);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
send(1, 'initialize', { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'ws-test', version: '0' }});
|
|
47
|
+
await wait(1);
|
|
48
|
+
|
|
49
|
+
// Wait for WS to connect (up to 15s).
|
|
50
|
+
const wsStart = Date.now();
|
|
51
|
+
while (!wsConnected && Date.now() - wsStart < 15000) {
|
|
52
|
+
await new Promise(r => setTimeout(r, 200));
|
|
53
|
+
}
|
|
54
|
+
if (!wsConnected) {
|
|
55
|
+
console.error('FAIL: WS did not connect within 15s.');
|
|
56
|
+
child.kill();
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
console.log(' WS connected after', Date.now() - wsStart, 'ms');
|
|
60
|
+
|
|
61
|
+
// Send a test message via send_message_as_bot (requires bot to be in TEST_CHAT_ID).
|
|
62
|
+
const stamp = `ws-test-${Date.now()}`;
|
|
63
|
+
send(2, 'tools/call', { name: 'send_message_as_bot', arguments: { chat_id: TEST_CHAT_ID, msg_type: 'text', payload: { text: stamp } } });
|
|
64
|
+
await wait(2, 15000);
|
|
65
|
+
console.log(' sent test message:', stamp);
|
|
66
|
+
|
|
67
|
+
// Wait a few seconds for the WS round-trip.
|
|
68
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
69
|
+
|
|
70
|
+
send(3, 'tools/call', { name: 'get_new_events', arguments: { since_seconds: 30, max_events: 50 } });
|
|
71
|
+
const r3 = await wait(3, 5000);
|
|
72
|
+
const txt = r3.result?.content?.[0]?.text || '';
|
|
73
|
+
const found = txt.includes(stamp);
|
|
74
|
+
console.log(' get_new_events response includes stamp?', found);
|
|
75
|
+
|
|
76
|
+
child.kill();
|
|
77
|
+
|
|
78
|
+
if (!found) {
|
|
79
|
+
console.error('FAIL: WS did not deliver the test message via get_new_events.');
|
|
80
|
+
console.error('Response:', txt.slice(0, 500));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
console.log('PASS: WS delivered the test message.');
|
|
84
|
+
})().catch((e) => { console.error('Error:', e.message); process.exit(1); });
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: feishu-user-plugin
|
|
3
|
-
version: "1.3.
|
|
4
|
-
description: "All-in-one Feishu plugin — send messages as yourself (incl. batch_send), read group/P2P chats (auto-expands merge_forward), manage docs/tables/wiki
|
|
5
|
-
allowed-tools: send_to_user, send_to_group, send_as_user, send_image_as_user, send_file_as_user, send_post_as_user,
|
|
3
|
+
version: "1.3.8"
|
|
4
|
+
description: "All-in-one Feishu plugin — send messages as yourself (incl. batch_send), read group/P2P chats (auto-expands merge_forward), manage docs/tables/wiki (full CRUD)/drive, OKR (with progress writes), calendar (read+write), Tasks v2, multi-profile auto-switch, real-time WS events. v1.3.8: multi-profile auto-switch on read errors (B), WebSocket realtime im.message events via get_new_events (C), credential pointer-only mode (E), CI gates (F), auth/uat.js + auth/cookie.js extracts (D)."
|
|
5
|
+
allowed-tools: send_to_user, send_to_group, send_as_user, send_image_as_user, send_file_as_user, send_post_as_user, batch_send, send_card_as_user, search_contacts, create_p2p_chat, get_chat_info, get_user_info, get_login_status, list_profiles, switch_profile, manage_profile_hints, read_p2p_messages, list_user_chats, list_chats, read_messages, send_message_as_bot, reply_message, forward_message, delete_message, update_message, add_reaction, delete_reaction, pin_message, create_group, update_group, list_members, manage_members, search_docs, read_doc, get_doc_blocks, create_doc, manage_doc_block, manage_bitable_app, manage_bitable_table, manage_bitable_field, manage_bitable_view, manage_bitable_record, upload_bitable_attachment, list_wiki_spaces, search_wiki, list_wiki_nodes, get_wiki_node, create_wiki_node, update_wiki_node, move_wiki_node, copy_wiki_node, delete_wiki_node, list_files, create_folder, upload_drive_file, manage_drive_file, upload_image, upload_file, download_message_resource, download_doc_image, list_user_okrs, get_okrs, list_okr_periods, create_okr_progress_record, list_okr_progress_records, delete_okr_progress_record, list_calendars, list_calendar_events, get_calendar_event, create_calendar_event, update_calendar_event, delete_calendar_event, respond_calendar_event, get_freebusy, list_tasks, get_task, create_task, update_task, complete_task, delete_task, manage_task_members, get_new_events
|
|
6
6
|
user_invocable: true
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Feishu User Plugin
|
|
10
10
|
|
|
11
11
|
All-in-one Feishu plugin for Claude Code with three auth layers:
|
|
12
|
-
- **User Identity** (cookie auth): Send messages as yourself — text, image, file, rich text
|
|
12
|
+
- **User Identity** (cookie auth): Send messages as yourself — text, image, file, rich text (post)
|
|
13
13
|
- **Official API** (app credentials): Read group messages, docs, tables, wiki, drive, contacts
|
|
14
14
|
- **User OAuth** (user_access_token): Read P2P (direct message) chat history
|
|
15
15
|
|
|
@@ -43,7 +43,7 @@ Search users and groups by name, display results grouped by type.
|
|
|
43
43
|
Search (search_docs), read (read_doc), create (create_doc) — three in one.
|
|
44
44
|
|
|
45
45
|
### /table — Bitable operations
|
|
46
|
-
Query (list
|
|
46
|
+
Query (`manage_bitable_table(action=list)` → `manage_bitable_field(action=list)` → `manage_bitable_record(action=search)`), create / update / delete records via `manage_bitable_record(action=create|update|delete)`.
|
|
47
47
|
|
|
48
48
|
### /wiki — Wiki management
|
|
49
49
|
List spaces (list_wiki_spaces), search content (search_wiki), browse nodes (list_wiki_nodes).
|