diff --git a/ai-path/FAILURES.md b/ai-path/FAILURES.md index 7593588..6f98ce4 100644 --- a/ai-path/FAILURES.md +++ b/ai-path/FAILURES.md @@ -396,6 +396,12 @@ Every finding traces back to a specific project. This section documents the sour ## Pending Integration +### connect() `onProgress` no longer receives `'log'` events +**Category:** API-CONTRACT +**Summary:** Prior to this change, `connect({ onProgress })` received both the structured stage events (`'wallet'`, `'session'`, `'tunnel'`, etc.) AND a raw `'log'` event for every internal SDK log line. Consumers ended up logging every line twice — once from `[log]` and once from the structured stage. +**Fix:** `onProgress` now only fires for the documented structured stages. Raw logs go to a new optional `onLog(message)` callback. To suppress the SDK's own built-in `[STEP X/Y]` lines, pass `silent: true`. +**Migration:** If you were filtering `stage === 'log'` in your callback, you can drop the check. If you depended on log lines, add `onLog: (msg) => …` to your `connect()` opts. + ### [PENDING] fix-registry-backup.md **Category:** BUG-FIX **Summary:** `setSystemProxy()` overwrites Windows proxy settings with `/f` (force), no backup/restore of previous state. If user had corporate proxy, `clearSystemProxy()` sets "no proxy" instead of restoring their previous configuration. diff --git a/ai-path/README.md b/ai-path/README.md index bc87eaa..fccd234 100644 --- a/ai-path/README.md +++ b/ai-path/README.md @@ -187,7 +187,9 @@ const vpn = await connect({ | `killSwitch` | `boolean` | `false` | Block all non-tunnel traffic while connected. **UNTESTED — code exists but never verified on mainnet. WireGuard only.** | | `maxAttempts` | `number` | `3` | Max nodes to try on auto-connect before failing | | `timeout` | `number` | `120000` | Connection timeout in milliseconds (2 minutes) | -| `onProgress` | `function` | `null` | `(step: string, detail: string) => void` | +| `onProgress` | `function` | `null` | `(stage: string, detail: string) => void` — structured stages only (`wallet`/`node-check`/`session`/`handshake`/`tunnel`/`verify`). Fires once per stage. | +| `onLog` | `function` | `null` | `(message: string) => void` — raw SDK log lines. Use for verbose tracing; otherwise prefer `onProgress`. | +| `silent` | `boolean` | `false` | Suppress the SDK's built-in `[STEP X/Y]` console output (consumer drives its own log via `onProgress`). | | `signal` | `AbortSignal` | `null` | AbortController signal for cancellation | | `v2rayExePath` | `string` | `auto` | Path to V2Ray binary. Auto-detected from `bin/` | diff --git a/ai-path/connect.js b/ai-path/connect.js index 24cba34..71a60b1 100644 --- a/ai-path/connect.js +++ b/ai-path/connect.js @@ -283,7 +283,11 @@ async function preValidateBalance(mnemonic) { * @param {string|number} [opts.subscriptionId] - Connect via existing subscription (operator-provisioned) * @param {string|number} [opts.planId] - Connect via plan (subscribes + starts session) * @param {string} [opts.feeGranter] - Operator address that pays gas (sent1...). Skips balance check. - * @param {function} [opts.onProgress] - Progress callback: (stage, message) => void + * @param {function} [opts.onProgress] - Structured stage callback: (stage, message) => void. + * Stages: 'wallet'|'node-check'|'validate'|'session'|'handshake'|'tunnel'|'verify'|'dry-run'. + * Each stage fires exactly once per transition — no 'log' duplicates. + * @param {function} [opts.onLog] - Raw SDK log callback: (message) => void. Receives every + * internal log line. Use this for verbose tracing; otherwise prefer onProgress. * @param {number} [opts.timeout] - Connection timeout in ms (default: 120000 — 2 minutes) * @param {boolean} [opts.silent] - If true, suppress step-by-step console output * @returns {Promise<{ @@ -507,7 +511,9 @@ export async function connect(opts = {}) { } }, log: (msg) => { - if (opts.onProgress) opts.onProgress('log', msg); + // Raw SDK logs go to opts.onLog only. Do NOT forward to onProgress — + // that duplicates every structured stage event with a 'log' sibling. + if (opts.onLog) opts.onLog(msg); }, };