oh-my-im 0.1.6 → 0.1.7

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.
@@ -47,9 +47,14 @@ function loadBotConfig() {
47
47
  const configuredNames = credentials.botAllowedUserNames ?? {};
48
48
  const allowedUserIds = [...new Set(configuredIds.map((id) => id.trim()).filter(Boolean))];
49
49
  if (allowedUserIds.length === 0) {
50
- throw new Error("请先在管理页配置机器人单聊授权人员");
50
+ // A fresh installation should still start so the management page can be
51
+ // used to configure the first authorized person. All incoming private
52
+ // messages remain denied by runApp until an ID is added.
53
+ console.log("[OmiBot] no private-chat authorization users configured; worker started in deny-all mode");
54
+ }
55
+ else {
56
+ console.log(`[OmiBot] loaded authorization users=${allowedUserIds.length} ids=[${allowedUserIds.join(",")}] names=${JSON.stringify(configuredNames)}`);
51
57
  }
52
- console.log(`[OmiBot] loaded authorization users=${allowedUserIds.length} ids=[${allowedUserIds.join(",")}] names=${JSON.stringify(configuredNames)}`);
53
58
  return {
54
59
  dingtalkClientId: clientId,
55
60
  dingtalkClientSecret: clientSecret,
@@ -103,8 +103,15 @@ export async function searchGroups(query) {
103
103
  });
104
104
  }
105
105
  export async function searchUsers(query) {
106
- const result = await runDwsJson(["contact", "+search-user", "--query", query]);
107
- return (result.users ?? result.items ?? []).flatMap((user) => {
106
+ // Keep this as the DWS contact search command. Do not use group members or
107
+ // any DingTalk HTTP API here; the value saved for robot authorization must be
108
+ // the contact userId returned by this command.
109
+ const result = await runDwsJson([
110
+ "contact", "+search-user", "--query", query,
111
+ ]);
112
+ const users = result.users ?? result.items ?? result.data?.users ?? result.data?.items
113
+ ?? result.data?.result?.users ?? result.data?.result?.items ?? [];
114
+ return users.flatMap((user) => {
108
115
  // Robot callbacks expose userId as senderStaffId. Prefer it for one-to-one
109
116
  // authorization; openDingTalkId belongs to a different identifier namespace.
110
117
  const senderId = (user.userId || user.openDingtalkId || user.openDingTalkId)?.trim();
@@ -2,7 +2,7 @@ import { mkdir, open, readdir, readFile, rename, unlink, writeFile } from "node:
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { unlinkSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
- import { join } from "node:path";
5
+ import { dirname, join } from "node:path";
6
6
  import { createInterface } from "node:readline";
7
7
  import { agentLabel, agentSwitchMessage, runAgent } from "./agents/index.js";
8
8
  import { DingTalkCardClient } from "./dingtalk-card.js";
@@ -36,6 +36,7 @@ const CONFIG_MIGRATION_FILE = join(DATA_DIR, ".config-location-v1");
36
36
  const LISTENER_LOCK_FILE = join(DATA_DIR, "dws-listener.lock");
37
37
  const CARD_STATE_FILE = join(DATA_DIR, "dws-cards.json");
38
38
  const DASHBOARD_CONFIG_FILE = join(DATA_DIR, "dws-dashboard.json");
39
+ const DEFAULT_DASHBOARD_CONFIG_FILE = join(dirname(new URL(import.meta.url).pathname), "..", "default-dashboard-config.json");
39
40
  const DASHBOARD_SERVER_CONFIG_FILE = join(DATA_DIR, "dws-dashboard-server.json");
40
41
  const REPLY_HISTORY_DIR = join(DATA_DIR, "replies");
41
42
  const LEGACY_REPLY_HISTORY_FILE = join(DATA_DIR, "dws-replies.json");
@@ -326,28 +327,33 @@ async function loadDashboardConfig() {
326
327
  const stored = await readStoredDashboardConfig(DASHBOARD_CONFIG_FILE);
327
328
  if (stored)
328
329
  return stored;
329
- const targets = createDefaultTargets();
330
- return {
331
- privateChatEnabled: true,
332
- cardUpdateIntervalMs: 3_000,
333
- showElapsed: true,
334
- historyGroupLimit: 10,
335
- historyMessageLimit: 20,
336
- historyPollIntervalSeconds: 5,
330
+ let defaults = {};
331
+ try {
332
+ defaults = JSON.parse(await readFile(DEFAULT_DASHBOARD_CONFIG_FILE, "utf8"));
333
+ }
334
+ catch (err) {
335
+ log.warn(`default dashboard config unavailable: ${String(err)}`);
336
+ }
337
+ const targets = Array.isArray(defaults.targets) ? defaults.targets : createDefaultTargets();
338
+ return normalizeDashboardConfig({
339
+ ...defaults,
337
340
  targets,
338
- botAllowedUserIds: defaultBotAllowedUserIds(targets),
339
- botAllowedUserNames: Object.fromEntries(targets.map((target) => [target.senderId, target.senderName])),
340
- botSuperAdminUserIds: [],
341
- botSuperAdminUserNames: {},
342
- robotSenderOpenDingTalkId: "",
343
- replyFormat: "markdown",
344
- agent: "codex",
345
- commandKeywords: structuredClone(EMPTY_COMMAND_KEYWORDS),
346
- groupPromptPrefix: "",
347
- robotName: DEFAULT_ROBOT_NAME,
348
- clientId: DEFAULT_DINGTALK_CLIENT_ID,
349
- clientSecret: DEFAULT_DINGTALK_CLIENT_SECRET,
350
- };
341
+ botAllowedUserIds: Array.isArray(defaults.botAllowedUserIds) ? defaults.botAllowedUserIds : defaultBotAllowedUserIds(targets),
342
+ botAllowedUserNames: defaults.botAllowedUserNames ?? Object.fromEntries(targets.map((target) => [target.senderId, target.senderName])),
343
+ commandKeywords: defaults.commandKeywords ?? structuredClone(EMPTY_COMMAND_KEYWORDS),
344
+ privateChatEnabled: defaults.privateChatEnabled ?? true,
345
+ cardUpdateIntervalMs: defaults.cardUpdateIntervalMs ?? 3_000,
346
+ showElapsed: defaults.showElapsed ?? true,
347
+ historyGroupLimit: defaults.historyGroupLimit ?? 10,
348
+ historyMessageLimit: defaults.historyMessageLimit ?? 20,
349
+ historyPollIntervalSeconds: defaults.historyPollIntervalSeconds ?? 5,
350
+ robotName: defaults.robotName ?? DEFAULT_ROBOT_NAME,
351
+ clientId: defaults.clientId ?? DEFAULT_DINGTALK_CLIENT_ID,
352
+ clientSecret: defaults.clientSecret ?? DEFAULT_DINGTALK_CLIENT_SECRET,
353
+ replyFormat: defaults.replyFormat ?? "markdown",
354
+ agent: defaults.agent ?? "codex",
355
+ groupPromptPrefix: defaults.groupPromptPrefix ?? "",
356
+ });
351
357
  }
352
358
  function normalizeDashboardServerConfig(value) {
353
359
  if (!value || typeof value !== "object")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-im",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "author": {
5
5
  "name": "杜振训",
6
6
  "email": "duzhenxun@126.com"