@keyou007/agent-bot 0.1.14-alpha.1 → 0.1.14-alpha.3

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 (80) hide show
  1. package/CHANGELOG.md +19 -1
  2. package/README.md +48 -15
  3. package/README.zh.md +48 -15
  4. package/config.example.yaml +1 -1
  5. package/dist/cli/AutostartManager.js +431 -0
  6. package/dist/cli/AutostartManager.js.map +1 -0
  7. package/dist/cli/FeishuAppConfiguration.js +21 -13
  8. package/dist/cli/FeishuAppConfiguration.js.map +1 -1
  9. package/dist/cli/Initializer.js +35 -0
  10. package/dist/cli/Initializer.js.map +1 -1
  11. package/dist/cli/SelfUpdateRunner.js +552 -0
  12. package/dist/cli/SelfUpdateRunner.js.map +1 -0
  13. package/dist/cli/SelfUpdater.js +431 -0
  14. package/dist/cli/SelfUpdater.js.map +1 -0
  15. package/dist/cli/autostartOutput.js +63 -0
  16. package/dist/cli/autostartOutput.js.map +1 -0
  17. package/dist/cli/controlProtocol.js.map +1 -1
  18. package/dist/cli/help.js +94 -18
  19. package/dist/cli/help.js.map +1 -1
  20. package/dist/cli/taskGroupOptions.js +14 -11
  21. package/dist/cli/taskGroupOptions.js.map +1 -1
  22. package/dist/cli/taskListOutput.js +3 -0
  23. package/dist/cli/taskListOutput.js.map +1 -1
  24. package/dist/cli/taskTarget.js +99 -0
  25. package/dist/cli/taskTarget.js.map +1 -0
  26. package/dist/cli.js +661 -58
  27. package/dist/cli.js.map +1 -1
  28. package/dist/codex/CodexRuntime.js +8 -2
  29. package/dist/codex/CodexRuntime.js.map +1 -1
  30. package/dist/commands/CommandRouter.js +16 -1
  31. package/dist/commands/CommandRouter.js.map +1 -1
  32. package/dist/feishu/CardRenderer.js +266 -38
  33. package/dist/feishu/CardRenderer.js.map +1 -1
  34. package/dist/feishu/FeishuMarkdown.js +25 -1
  35. package/dist/feishu/FeishuMarkdown.js.map +1 -1
  36. package/dist/feishu/FeishuMessageClient.js +16 -0
  37. package/dist/feishu/FeishuMessageClient.js.map +1 -1
  38. package/dist/feishu/FeishuTurnPresenter.js +42 -6
  39. package/dist/feishu/FeishuTurnPresenter.js.map +1 -1
  40. package/dist/index.js +136 -2
  41. package/dist/index.js.map +1 -1
  42. package/dist/presentation/OutboundRouter.js +7 -0
  43. package/dist/presentation/OutboundRouter.js.map +1 -1
  44. package/dist/presentation/TurnStateReducer.js +21 -7
  45. package/dist/presentation/TurnStateReducer.js.map +1 -1
  46. package/dist/proxy/ProxySessionController.js +537 -13
  47. package/dist/proxy/ProxySessionController.js.map +1 -1
  48. package/dist/state/StateStore.js +53 -0
  49. package/dist/state/StateStore.js.map +1 -1
  50. package/docs/technical-reference.md +17 -7
  51. package/docs/technical-reference.zh.md +17 -7
  52. package/npm-shrinkwrap.json +2 -2
  53. package/package.json +2 -2
  54. package/skills/agent-bot/SKILL.md +109 -188
  55. package/src/cli/AutostartManager.ts +579 -0
  56. package/src/cli/FeishuAppConfiguration.ts +26 -7
  57. package/src/cli/Initializer.ts +57 -0
  58. package/src/cli/SelfUpdateRunner.ts +817 -0
  59. package/src/cli/SelfUpdater.ts +688 -0
  60. package/src/cli/autostartOutput.ts +75 -0
  61. package/src/cli/controlProtocol.ts +119 -1
  62. package/src/cli/help.ts +94 -18
  63. package/src/cli/taskGroupOptions.ts +27 -17
  64. package/src/cli/taskListOutput.ts +10 -0
  65. package/src/cli/taskTarget.ts +168 -0
  66. package/src/cli.ts +809 -65
  67. package/src/codex/CodexRuntime.ts +8 -2
  68. package/src/commands/CommandRouter.ts +14 -1
  69. package/src/commands/commandTypes.ts +2 -0
  70. package/src/feishu/CardRenderer.ts +313 -35
  71. package/src/feishu/FeishuMarkdown.ts +27 -1
  72. package/src/feishu/FeishuMessageClient.ts +33 -0
  73. package/src/feishu/FeishuTurnPresenter.ts +43 -6
  74. package/src/feishu/types.ts +1 -0
  75. package/src/index.ts +174 -2
  76. package/src/presentation/OutboundRouter.ts +7 -0
  77. package/src/presentation/TurnStateReducer.ts +21 -7
  78. package/src/proxy/ProxySessionController.ts +661 -16
  79. package/src/runtime/types.ts +1 -0
  80. package/src/state/StateStore.ts +56 -0
@@ -24,6 +24,10 @@ const REQUIRED_SCOPE_REQUIREMENTS: ScopeRequirement[] = [
24
24
  requested: "im:chat:create",
25
25
  accepted: ["im:chat:create", "im:chat"],
26
26
  },
27
+ {
28
+ requested: "im:chat:delete",
29
+ accepted: ["im:chat:delete", "im:chat:operate_as_owner", "im:chat"],
30
+ },
27
31
  {
28
32
  requested: "im:chat:read",
29
33
  accepted: ["im:chat:read", "im:chat:readonly", "im:chat"],
@@ -72,7 +76,8 @@ const CORE_FEISHU_SCOPES = new Set([
72
76
  "im:message:send_as_bot",
73
77
  ]);
74
78
  const CORE_FEISHU_EVENTS = new Set<string>(["im.message.receive_v1"]);
75
- const MANUAL_FEISHU_SCOPES = new Set(["im:message.group_msg"]);
79
+ const ALL_GROUP_MESSAGE_SCOPES = new Set(["im:message.group_msg"]);
80
+ const MANUAL_FEISHU_SCOPES = ALL_GROUP_MESSAGE_SCOPES;
76
81
 
77
82
  export interface FeishuAppConfiguration {
78
83
  scopes: string[];
@@ -96,6 +101,7 @@ export interface FeishuConfigurationChallenge {
96
101
  export interface EnsureFeishuAppConfigurationOptions {
97
102
  fetch?: typeof globalThis.fetch;
98
103
  sleep?: (milliseconds: number) => Promise<void>;
104
+ respondToAllGroupMessages?: boolean;
99
105
  signal?: AbortSignal;
100
106
  manualPermissionSkipSignal?: AbortSignal;
101
107
  optionalSkipSignal?: AbortSignal;
@@ -124,6 +130,9 @@ export async function ensureFeishuAppConfiguration(
124
130
  const timeoutMs = positiveInteger(options.timeoutMs) ?? DEFAULT_COMPLETION_TIMEOUT_MS;
125
131
  const optionalTimeoutMs = positiveInteger(options.optionalTimeoutMs)
126
132
  ?? DEFAULT_OPTIONAL_COMPLETION_TIMEOUT_MS;
133
+ const excludedScopes = options.respondToAllGroupMessages === false
134
+ ? ALL_GROUP_MESSAGE_SCOPES
135
+ : new Set<string>();
127
136
 
128
137
  let configuration: FeishuAppConfiguration;
129
138
  try {
@@ -133,7 +142,7 @@ export async function ensureFeishuAppConfiguration(
133
142
  configuration = emptyConfiguration();
134
143
  }
135
144
 
136
- const missing = missingFeishuAppConfiguration(configuration);
145
+ const missing = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
137
146
  if (!hasMissingConfiguration(missing)) {
138
147
  return {
139
148
  status: "ready",
@@ -154,6 +163,8 @@ export async function ensureFeishuAppConfiguration(
154
163
  pollIntervalMs,
155
164
  optionalTimeoutMs,
156
165
  options,
166
+ new Set(),
167
+ excludedScopes,
157
168
  );
158
169
  }
159
170
 
@@ -179,7 +190,7 @@ export async function ensureFeishuAppConfiguration(
179
190
 
180
191
  try {
181
192
  configuration = await readFeishuAppConfiguration(credentials, fetchImpl, options.signal);
182
- const remaining = missingFeishuAppConfiguration(configuration);
193
+ const remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
183
194
  const unresolvedCore = coreMissingFeishuAppConfiguration(remaining);
184
195
  if (!hasBlockingCoreConfiguration(unresolvedCore, options.manualPermissionSkipSignal)) {
185
196
  return completeOptionalFeishuConfiguration(
@@ -192,12 +203,16 @@ export async function ensureFeishuAppConfiguration(
192
203
  optionalTimeoutMs,
193
204
  options,
194
205
  skippedManualScopes(coreMissing, options.manualPermissionSkipSignal),
206
+ excludedScopes,
195
207
  );
196
208
  }
197
209
  lastError = undefined;
198
210
  } catch (error) {
199
211
  if (options.signal?.aborted) throw abortError(options.signal);
200
- const knownRemaining = missingFeishuAppConfiguration(configuration);
212
+ const knownRemaining = withoutIgnoredScopes(
213
+ missingFeishuAppConfiguration(configuration),
214
+ excludedScopes,
215
+ );
201
216
  if (!hasBlockingCoreConfiguration(
202
217
  coreMissingFeishuAppConfiguration(knownRemaining),
203
218
  options.manualPermissionSkipSignal,
@@ -212,6 +227,7 @@ export async function ensureFeishuAppConfiguration(
212
227
  optionalTimeoutMs,
213
228
  options,
214
229
  skippedManualScopes(coreMissing, options.manualPermissionSkipSignal),
230
+ excludedScopes,
215
231
  );
216
232
  }
217
233
  lastError = error;
@@ -267,9 +283,10 @@ async function completeOptionalFeishuConfiguration(
267
283
  timeoutMs: number,
268
284
  options: EnsureFeishuAppConfigurationOptions,
269
285
  ignoredScopes: ReadonlySet<string> = new Set(),
286
+ excludedScopes: ReadonlySet<string> = new Set(),
270
287
  ): Promise<EnsureFeishuAppConfigurationResult> {
271
288
  let configuration = initialConfiguration;
272
- let remaining = missingFeishuAppConfiguration(configuration);
289
+ let remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
273
290
  const requested = withoutIgnoredScopes(remaining, ignoredScopes);
274
291
  if (hasMissingConfiguration(requested)) {
275
292
  await requestMissingFeishuConfiguration(
@@ -289,6 +306,7 @@ async function completeOptionalFeishuConfiguration(
289
306
  options.signal,
290
307
  options.optionalSkipSignal,
291
308
  ignoredScopes,
309
+ excludedScopes,
292
310
  );
293
311
  configuration = completed.configuration;
294
312
  remaining = completed.remaining;
@@ -312,12 +330,13 @@ async function waitForOptionalFeishuConfiguration(
312
330
  signal?: AbortSignal,
313
331
  optionalSkipSignal?: AbortSignal,
314
332
  ignoredScopes: ReadonlySet<string> = new Set(),
333
+ excludedScopes: ReadonlySet<string> = new Set(),
315
334
  ): Promise<{
316
335
  configuration: FeishuAppConfiguration;
317
336
  remaining: MissingFeishuAppConfiguration;
318
337
  }> {
319
338
  let configuration = initialConfiguration;
320
- let remaining = missingFeishuAppConfiguration(configuration);
339
+ let remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
321
340
  let remainingMs = timeoutMs;
322
341
  while (remainingMs > 0 && hasMissingConfiguration(withoutIgnoredScopes(remaining, ignoredScopes))) {
323
342
  if (optionalSkipSignal?.aborted) break;
@@ -332,7 +351,7 @@ async function waitForOptionalFeishuConfiguration(
332
351
  remainingMs -= waitMs;
333
352
  try {
334
353
  configuration = await readFeishuAppConfiguration(credentials, fetchImpl, signal);
335
- remaining = missingFeishuAppConfiguration(configuration);
354
+ remaining = withoutIgnoredScopes(missingFeishuAppConfiguration(configuration), excludedScopes);
336
355
  } catch (error) {
337
356
  if (signal?.aborted) throw abortError(signal);
338
357
  }
@@ -43,6 +43,12 @@ export function shouldConfigureAgentsDuringInitialization(status: Initialization
43
43
  return status === "created" || status === "reset";
44
44
  }
45
45
 
46
+ export function shouldConfigureGroupMessagesDuringInitialization(status: InitializationStatus): boolean {
47
+ return status === "created" || status === "reset";
48
+ }
49
+
50
+ export type GroupMessageResponseMode = "all" | "mention-only";
51
+
46
52
  export interface ConfiguredAgentOption {
47
53
  name: string;
48
54
  title: string;
@@ -238,6 +244,57 @@ export function writeConfiguredAgentSelection(
238
244
  return true;
239
245
  }
240
246
 
247
+ export function readGroupMessageResponseMode(configPath: string): GroupMessageResponseMode {
248
+ const document = parseConfigurationDocument(fs.readFileSync(configPath, "utf8"), configPath);
249
+ if (!isMap(document.contents)) {
250
+ throw new Error(cliText(
251
+ `Configuration file must contain a YAML mapping: ${configPath}`,
252
+ `配置文件必须包含 YAML 映射:${configPath}`,
253
+ ));
254
+ }
255
+ const feishu = document.contents.get("feishu", true);
256
+ if (!isMap(feishu)) {
257
+ throw new Error(cliText(
258
+ `Configuration feishu must contain a YAML mapping: ${configPath}`,
259
+ `配置文件的 feishu 必须是 YAML 映射:${configPath}`,
260
+ ));
261
+ }
262
+ const enabled = document.getIn(["feishu", "respondToAllGroupMessages"]);
263
+ if (typeof enabled !== "boolean") {
264
+ throw new Error(cliText(
265
+ `Configuration feishu.respondToAllGroupMessages must be a boolean: ${configPath}`,
266
+ `配置项 feishu.respondToAllGroupMessages 必须是布尔值:${configPath}`,
267
+ ));
268
+ }
269
+ return enabled ? "all" : "mention-only";
270
+ }
271
+
272
+ export function writeGroupMessageResponseMode(
273
+ configPath: string,
274
+ mode: GroupMessageResponseMode,
275
+ ): boolean {
276
+ const original = fs.readFileSync(configPath, "utf8");
277
+ const document = parseConfigurationDocument(original, configPath);
278
+ if (!isMap(document.contents)) {
279
+ throw new Error(cliText(
280
+ `Configuration file must contain a YAML mapping: ${configPath}`,
281
+ `配置文件必须包含 YAML 映射:${configPath}`,
282
+ ));
283
+ }
284
+ const feishu = document.contents.get("feishu", true);
285
+ if (!isMap(feishu)) {
286
+ throw new Error(cliText(
287
+ `Configuration feishu must contain a YAML mapping: ${configPath}`,
288
+ `配置文件的 feishu 必须是 YAML 映射:${configPath}`,
289
+ ));
290
+ }
291
+ const enabled = mode === "all";
292
+ if (document.getIn(["feishu", "respondToAllGroupMessages"]) === enabled) return false;
293
+ feishu.set("respondToAllGroupMessages", enabled);
294
+ writeFileAtomically(configPath, document.toString());
295
+ return true;
296
+ }
297
+
241
298
  export function readFeishuCredentials(envPath: string, env: NodeJS.ProcessEnv = process.env): FeishuCredentialState {
242
299
  const fileValues = fs.existsSync(envPath) ? parseDotEnv(fs.readFileSync(envPath, "utf8")) : {};
243
300
  const appId = firstNonBlank(env.FEISHU_APP_ID, fileValues.FEISHU_APP_ID);