@larktask/aamp-feishu-task-agent 0.1.0-dev.172 → 0.1.0-dev.174

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.
@@ -10,6 +10,7 @@ import { spawn } from 'node:child_process';
10
10
  import { EventEmitter } from 'node:events';
11
11
  import {
12
12
  agentStartRetryError,
13
+ bridgeAuthenticationRetryError,
13
14
  classifyNetworkError,
14
15
  createSerializedLineWriter,
15
16
  describeNetworkError,
@@ -236,7 +237,11 @@ async function runNetworkStage(operation, {
236
237
  shouldRetry,
237
238
  onRetry: async (event) => {
238
239
  await appendDiagnostic(logFile, { type: 'network.retry', stage, label, host: safeDiagnosticUrl(host), ...event });
239
- console.log(`[aamp-one-click] ${label}遇到网络波动,正在重试(${event.attempt + 1}/${event.maxAttempts})...`);
240
+ if (event.category === 'mail_auth') {
241
+ console.log(`[aamp-one-click] ${label}检测到 AAMP 邮箱凭据失效,正在重新注册并重试(${event.attempt + 1}/${event.maxAttempts})...`);
242
+ } else {
243
+ console.log(`[aamp-one-click] ${label}遇到网络波动,正在重试(${event.attempt + 1}/${event.maxAttempts})...`);
244
+ }
240
245
  launchDetachedDiagnostic(() => probeFailureEndpoints(host, logFile, environment, `${stage}-retry-probe`));
241
246
  },
242
247
  });
@@ -867,6 +872,7 @@ async function startManagedProcess({ label, packageSpec, executable, args, env,
867
872
  const safeLine = redact(line);
868
873
  record.outputTail.push(`[${streamName}] ${safeLine}`);
869
874
  if (record.outputTail.length > 30) record.outputTail.shift();
875
+ record.emitter.emit('output', safeLine);
870
876
  if (streamName === 'stdout' && line.trim()) {
871
877
  try {
872
878
  const event = JSON.parse(line.trim());
@@ -948,6 +954,8 @@ async function stopManagedProcess(record) {
948
954
  }
949
955
 
950
956
  async function waitForEvent(record, predicate, timeoutMs = READY_TIMEOUT_MS) {
957
+ const authenticationError = bridgeAuthenticationRetryError(record.outputTail);
958
+ if (authenticationError) throw authenticationError;
951
959
  const existing = record.events.find(predicate);
952
960
  if (existing) return existing;
953
961
  if (record.exited) {
@@ -970,13 +978,21 @@ async function waitForEvent(record, predicate, timeoutMs = READY_TIMEOUT_MS) {
970
978
  const tail = record.outputTail.slice(-10).join('\n');
971
979
  reject(new Error(`${record.label} exited before ready (${exit.signal || exit.code})${tail ? `:\n${tail}` : ''}\n日志:${record.logFile}`));
972
980
  };
981
+ const onOutput = () => {
982
+ const error = bridgeAuthenticationRetryError(record.outputTail);
983
+ if (!error) return;
984
+ cleanup();
985
+ reject(error);
986
+ };
973
987
  const cleanup = () => {
974
988
  clearTimeout(timeout);
975
989
  record.emitter.off('event', onEvent);
976
990
  record.emitter.off('exit', onExit);
991
+ record.emitter.off('output', onOutput);
977
992
  };
978
993
  record.emitter.on('event', onEvent);
979
994
  record.emitter.on('exit', onExit);
995
+ record.emitter.on('output', onOutput);
980
996
  });
981
997
  }
982
998
 
@@ -1333,6 +1349,8 @@ async function pairingConsumed(pairingFile) {
1333
1349
  async function waitForInitialBinding(record, pairingFile) {
1334
1350
  const deadline = Date.now() + READY_TIMEOUT_MS;
1335
1351
  while (Date.now() < deadline) {
1352
+ const authenticationError = bridgeAuthenticationRetryError(record.outputTail);
1353
+ if (authenticationError) throw authenticationError;
1336
1354
  if (record.exited) {
1337
1355
  const tail = record.outputTail.slice(-10).join('\n');
1338
1356
  throw new Error(`${record.label} exited before binding completed${tail ? `:\n${tail}` : ''}\n日志:${record.logFile}`);
@@ -24,6 +24,7 @@ const TLS_CODES = new Set([
24
24
  'UNABLE_TO_GET_ISSUER_CERT_LOCALLY',
25
25
  'UNABLE_TO_VERIFY_LEAF_SIGNATURE',
26
26
  ]);
27
+ const MAIL_AUTH_CODES = new Set(['EAAMPMAILAUTH']);
27
28
 
28
29
  function asErrorDetails(error) {
29
30
  return error && typeof error === 'object' ? error : {};
@@ -95,6 +96,7 @@ export function classifyNetworkError(error) {
95
96
  if (status !== undefined) return status >= 500 ? 'http_5xx' : 'http_4xx';
96
97
 
97
98
  const codes = errorCodes(error);
99
+ if (codes.some((code) => MAIL_AUTH_CODES.has(code))) return 'mail_auth';
98
100
  if (codes.some((code) => DNS_CODES.has(code))) return 'dns';
99
101
  if (codes.some((code) => CONNECT_TIMEOUT_CODES.has(code))) return 'connect_timeout';
100
102
  if (codes.some((code) => TIMEOUT_CODES.has(code))) return 'timeout';
@@ -121,10 +123,18 @@ export function isRetryableHttpStatus(status) {
121
123
  export function isRetryableNetworkError(error) {
122
124
  const status = errorStatus(error);
123
125
  if (status !== undefined) return isRetryableHttpStatus(status);
124
- return ['dns', 'connect_timeout', 'timeout', 'connection_reset', 'unreachable', 'network']
126
+ return ['mail_auth', 'dns', 'connect_timeout', 'timeout', 'connection_reset', 'unreachable', 'network']
125
127
  .includes(classifyNetworkError(error));
126
128
  }
127
129
 
130
+ export function bridgeAuthenticationRetryError(outputLines) {
131
+ const output = (outputLines || []).slice(-30).join('\n');
132
+ if (!/\b535(?:\s+5\.7\.8)?\b[^\n]*authentication credentials invalid/i.test(output)) return undefined;
133
+ const error = new Error('AAMP 邮箱认证凭据已失效');
134
+ error.code = 'EAAMPMAILAUTH';
135
+ return error;
136
+ }
137
+
128
138
  function defaultSleep(ms) {
129
139
  if (ms <= 0) return Promise.resolve();
130
140
  return new Promise((resolve) => setTimeout(resolve, ms));
@@ -47,6 +47,7 @@ CODEM_INSTALLER_URL="${CODEM_INSTALLER_URL:-https://sf-unpkg-src.bytedance.net/@
47
47
  CODEM_INSTALLER_CONFIRM="${CODEM_INSTALLER_CONFIRM:-}"
48
48
  CODEM_PROVIDER_PREFLIGHT="${CODEM_PROVIDER_PREFLIGHT:-true}"
49
49
  CODEM_PROVIDER_PREFLIGHT_TIMEOUT_SECONDS="${CODEM_PROVIDER_PREFLIGHT_TIMEOUT_SECONDS:-60}"
50
+ CODEX_CHATGPT_APP_CLI="/Applications/ChatGPT.app/Contents/Resources/codex"
50
51
  CODEX_APP_CLI="/Applications/Codex.app/Contents/Resources/codex"
51
52
  CODEX_AUTO_UPDATE="${CODEX_AUTO_UPDATE:-true}"
52
53
  CODEX_NPM_PACKAGE="${CODEX_NPM_PACKAGE:-@openai/codex}"
@@ -65,7 +66,7 @@ CLI_BRIDGE_PKG="${CLI_BRIDGE_PKG:-@zengxingyuan/aamp-cli-bridge@0.1.7-dev.14}"
65
66
  FEISHU_BRIDGE_PKG="${FEISHU_BRIDGE_PKG:-@zengxingyuan/aamp-feishu-bridge@0.1.51}"
66
67
  AAMP_TASK_AGENT_NAME="${AAMP_TASK_AGENT_NAME:-@larktask/aamp-feishu-task-agent}"
67
68
  AAMP_TASK_AGENT_LEGACY_NAME="${AAMP_TASK_AGENT_LEGACY_NAME:-@zengxingyuan/aamp-feishu-task-agent}"
68
- AAMP_TASK_AGENT_VERSION="0.1.0-dev.172"
69
+ AAMP_TASK_AGENT_VERSION="0.1.0-dev.174"
69
70
  AAMP_TASK_AGENT_CHANNEL="${AAMP_TASK_AGENT_CHANNEL:-dev}"
70
71
  AAMP_STALE_PROCESS_CLEANUP="${AAMP_STALE_PROCESS_CLEANUP:-false}"
71
72
  AAMP_STALE_PROCESS_SECONDS="${AAMP_STALE_PROCESS_SECONDS:-86400}"
@@ -3453,6 +3454,11 @@ resolve_codex_cli_for_acp() {
3453
3454
  return 0
3454
3455
  fi
3455
3456
 
3457
+ if is_macos && [ -x "$CODEX_CHATGPT_APP_CLI" ]; then
3458
+ printf '%s\n' "$CODEX_CHATGPT_APP_CLI"
3459
+ return 0
3460
+ fi
3461
+
3456
3462
  if is_macos && [ -x "$CODEX_APP_CLI" ]; then
3457
3463
  printf '%s\n' "$CODEX_APP_CLI"
3458
3464
  return 0
@@ -3484,7 +3490,7 @@ validate_codex_acp_command() {
3484
3490
  if [ "$status" -ne 0 ]; then
3485
3491
  agent_log "Codex ACP command validation failed:"
3486
3492
  printf '%s\n' "$output" >&2
3487
- agent_fail "codex ACP command is unavailable; check Codex.app or reinstall codex CLI"
3493
+ agent_fail "codex ACP command is unavailable; check ChatGPT.app, Codex.app, or reinstall codex CLI"
3488
3494
  fi
3489
3495
  }
3490
3496
 
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "README.md"
7
7
  ],
8
8
  "license": "MIT",
9
- "version": "0.1.0-dev.172",
9
+ "version": "0.1.0-dev.174",
10
10
  "description": "One-click manager for local Agent and Feishu Bot bindings.",
11
11
  "type": "module",
12
12
  "bin": {