@teamclaw/feishu-agent 1.0.3 → 1.0.5

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.
Files changed (3) hide show
  1. package/README.md +5 -2
  2. package/dist/cli.js +38 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,9 +5,10 @@ Feishu Agent is a TypeScript/Node.js middleware layer for Feishu (Lark) API inte
5
5
  ## Features
6
6
 
7
7
  - 📅 Calendar management (list calendars, events, create/delete events)
8
+ - ⚠️ **Automatic conflict detection** when creating events (uses FreeBusy API)
8
9
  - ✅ Todo management via Bitable
9
10
  - 👥 Contact management (list users, search by name/email)
10
- - 🔐 OAuth 2.0 authentication support
11
+ - 🔐 OAuth 2.0 authentication with auto token refresh
11
12
  - 🚀 CLI interface with commander
12
13
 
13
14
  ## Installation
@@ -71,7 +72,7 @@ feishu_agent calendar list
71
72
  # List events
72
73
  feishu_agent calendar events
73
74
 
74
- # Create event
75
+ # Create event (automatically checks for time conflicts)
75
76
  feishu_agent calendar create --summary "Meeting" --start "2026-03-01 14:00" --end "2026-03-01 15:00"
76
77
 
77
78
  # Create event with attendees
@@ -173,6 +174,8 @@ Global config is stored at `~/.feishu-agent/config.json`:
173
174
  }
174
175
  ```
175
176
 
177
+ **Note:** User access tokens are automatically refreshed when expired. Just run `feishu_agent auth` again if the refresh token expires.
178
+
176
179
  ## License
177
180
 
178
181
  MIT
package/dist/cli.js CHANGED
@@ -2131,7 +2131,7 @@ var {
2131
2131
  // src/cli/commands/setup.ts
2132
2132
  import { createServer } from "node:http";
2133
2133
  import { exec } from "node:child_process";
2134
- import { writeFile, mkdir as mkdir2 } from "node:fs/promises";
2134
+ import { writeFile } from "node:fs/promises";
2135
2135
 
2136
2136
  // src/core/config.ts
2137
2137
  import { homedir } from "node:os";
@@ -2231,11 +2231,11 @@ class AuthManager {
2231
2231
  userToken = null;
2232
2232
  constructor(config) {
2233
2233
  this.config = config;
2234
- if (config.userAccessToken) {
2234
+ if (config.userAccessToken && config.refreshToken) {
2235
2235
  this.userToken = {
2236
2236
  accessToken: config.userAccessToken,
2237
- refreshToken: config.refreshToken || "",
2238
- expireTime: Date.now() + 2 * 60 * 60 * 1000
2237
+ refreshToken: config.refreshToken,
2238
+ expireTime: 0
2239
2239
  };
2240
2240
  }
2241
2241
  }
@@ -2317,7 +2317,7 @@ class AuthManager {
2317
2317
  clearTimeout(timeoutId);
2318
2318
  }
2319
2319
  }
2320
- async refreshToken() {
2320
+ async refreshUserToken() {
2321
2321
  if (!this.userToken?.refreshToken) {
2322
2322
  throw new FeishuError("Refresh token not available", 401);
2323
2323
  }
@@ -2636,15 +2636,11 @@ async function setupCommand() {
2636
2636
  console.log(` User ID: ${user_id}`);
2637
2637
  console.log(` Name: ${name}`);
2638
2638
  console.log("");
2639
- await mkdir2(".feishu_agent", { recursive: true });
2640
- await writeFile(".feishu_agent/config.json", JSON.stringify({
2641
- appId,
2642
- appSecret,
2639
+ await saveGlobalConfig({
2643
2640
  userAccessToken: access_token,
2644
- refreshToken: refresh_token,
2645
- userId: user_id
2646
- }, null, 2));
2647
- console.log(`Configuration saved to .feishu_agent/config.json
2641
+ refreshToken: refresh_token
2642
+ });
2643
+ console.log(`Configuration saved to ~/.feishu-agent/config.json
2648
2644
  `);
2649
2645
  console.log("Step 3: Feishu Bitable (\u591A\u7EF4\u8868\u683C)");
2650
2646
  console.log("-".repeat(40));
@@ -3166,6 +3162,9 @@ class CalendarManager {
3166
3162
  return res;
3167
3163
  }
3168
3164
  async createEvent(calendarId, event) {
3165
+ if (event.checkConflict !== false) {
3166
+ await this.checkTimeConflict(event.startTime, event.endTime);
3167
+ }
3169
3168
  const body = {
3170
3169
  summary: event.summary,
3171
3170
  description: event.description,
@@ -3198,6 +3197,31 @@ class CalendarManager {
3198
3197
  const res = await this.client.post("/open-apis/calendar/v4/freebusy/list", body, { user_id_type: userIdType }, true);
3199
3198
  return res;
3200
3199
  }
3200
+ async checkTimeConflict(startTime, endTime) {
3201
+ const currentUser = await this.client.getCurrentUser();
3202
+ if (!currentUser?.user_id) {
3203
+ return;
3204
+ }
3205
+ const timeMin = this.toRFC3339(startTime);
3206
+ const timeMax = this.toRFC3339(endTime);
3207
+ const freeBusy = await this.getUserFreeBusy(currentUser.user_id, timeMin, timeMax);
3208
+ if (freeBusy.freebusy_list && freeBusy.freebusy_list.length > 0) {
3209
+ const conflicts = freeBusy.freebusy_list.map((slot) => `${new Date(slot.start_time).toLocaleString()} - ${new Date(slot.end_time).toLocaleString()}`);
3210
+ throw new Error(`Time conflict detected. The following time slots are already busy:
3211
+ ` + ` ${conflicts.join(`
3212
+ `)}`);
3213
+ }
3214
+ }
3215
+ toRFC3339(time) {
3216
+ if (time.timestamp) {
3217
+ const date = new Date(parseInt(time.timestamp) * 1000);
3218
+ return date.toISOString();
3219
+ }
3220
+ if (time.date) {
3221
+ return time.date;
3222
+ }
3223
+ return new Date().toISOString();
3224
+ }
3201
3225
  async updateEvent(calendarId, eventId, updates) {
3202
3226
  const body = {};
3203
3227
  if (updates.summary !== undefined)
@@ -3727,7 +3751,7 @@ async function handleSearch(config, query) {
3727
3751
  // package.json
3728
3752
  var package_default = {
3729
3753
  name: "@teamclaw/feishu-agent",
3730
- version: "1.0.3",
3754
+ version: "1.0.5",
3731
3755
  description: "Feishu Agent CLI for AI assistants",
3732
3756
  type: "module",
3733
3757
  private: false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamclaw/feishu-agent",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Feishu Agent CLI for AI assistants",
5
5
  "type": "module",
6
6
  "private": false,