zames_pro 2.72.1 → 2.72.2

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.72.2] - 2026-10-09
11
+
12
+ ### Added
13
+
14
+ - **self-smoke:** add --reuse-profile and a bounded, explicit login failure (exit 2)
15
+
16
+ ### Added
17
+
18
+ - **self-smoke:** add --reuse-profile and a bounded, explicit login failure (exit 2)
19
+
10
20
  ## [2.72.1] - 2026-10-09
11
21
 
12
22
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zames_pro",
3
- "version": "2.72.1",
3
+ "version": "2.72.2",
4
4
  "description": "Terminal coding agent that drives chat.deepseek.com through Playwright — no API key required. Reads and edits files, runs commands, commits to git, like Claude Code / Codex CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -7,18 +7,35 @@
7
7
  // config.json (so auto-login works) and symlinks the Playwright browser cache.
8
8
  // Nothing in the operator's profile is written.
9
9
  //
10
- // Usage: npm run self-smoke (headless)
10
+ // Usage: npm run self-smoke (headless, empty profile)
11
11
  // npm run self-smoke -- --headed
12
- // Exit code 0 = all scenarios passed.
12
+ // npm run self-smoke -- --reuse-profile (logged-in profile, see below)
13
+ // Exit code 0 = all scenarios passed; 2 = login failed (could not start).
14
+ //
15
+ // --reuse-profile: copy the REAL profile (~/.zames/profile) read-only into the
16
+ // throwaway HOME so the browser starts ALREADY SIGNED IN. Reason: DeepSeek's
17
+ // anti-bot increasingly blocks a COLD login on a fresh profile (captcha / rate
18
+ // limit), so a smoke that logs in from scratch fails for reasons unrelated to
19
+ // the agent. Copying (never opening the live profile) keeps isolation intact.
13
20
 
14
21
  import fs from 'fs'
15
22
  import path from 'path'
16
23
  import os from 'os'
17
24
 
25
+ // --- flags -----------------------------------------------------------------
18
26
  const HEADED = process.argv.includes('--headed')
27
+ const REUSE_PROFILE =
28
+ process.argv.includes('--reuse-profile') ||
29
+ process.env.ZAMES_SMOKE_REUSE_PROFILE === '1'
30
+ // Optional explicit source profile (default: the real ~/.zames/profile).
31
+ const profileArgIdx = process.argv.indexOf('--profile')
32
+ const REAL_HOME = os.homedir()
33
+ const PROFILE_SRC =
34
+ profileArgIdx >= 0 && process.argv[profileArgIdx + 1]
35
+ ? path.resolve(process.argv[profileArgIdx + 1])
36
+ : path.join(REAL_HOME, '.zames', 'profile')
19
37
 
20
38
  // --- isolate HOME before importing project modules -------------------------
21
- const REAL_HOME = os.homedir()
22
39
  if (!process.env.ZAMES_SMOKE_HOME) {
23
40
  const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'zames-smoke-'))
24
41
  process.env.HOME = tmp
@@ -35,6 +52,16 @@ if (!process.env.ZAMES_SMOKE_HOME) {
35
52
  if (fs.existsSync(realPw)) {
36
53
  fs.symlinkSync(realPw, path.join(tmp, '.cache', 'ms-playwright'))
37
54
  }
55
+ // Reuse a logged-in profile: COPY it (the live one is never opened) and drop
56
+ // the Singleton* files — Chrome refuses to start on a profile whose lock is
57
+ // present, and the live browser may hold it. The cookies survive the copy
58
+ // because Playwright launches with --password-store=basic.
59
+ if (REUSE_PROFILE && fs.existsSync(PROFILE_SRC)) {
60
+ fs.cpSync(PROFILE_SRC, path.join(tmp, '.zames', 'profile'), {
61
+ recursive: true,
62
+ filter: (src) => !/^Singleton/.test(path.basename(src)),
63
+ })
64
+ }
38
65
  }
39
66
  const SMOKE_HOME = process.env.ZAMES_SMOKE_HOME
40
67
  const WORK = path.join(SMOKE_HOME, 'work')
@@ -54,6 +81,9 @@ interface SmokeResult {
54
81
  note?: string
55
82
  }
56
83
  const results: SmokeResult[] = []
84
+ // Set when we could not even start (login failed): exit code 2, distinct from a
85
+ // scenario failure (1).
86
+ let loginFailed = false
57
87
  const record = (name: string, ok: boolean, note?: string): void => {
58
88
  results.push({ name, ok, note })
59
89
  console.log((ok ? 'PASS ' : 'FAIL ') + name + (note ? ' — ' + note : ''))
@@ -76,9 +106,33 @@ const browser = new DeepSeekBrowser({
76
106
  })
77
107
 
78
108
  async function main() {
79
- console.log('self-smoke: HOME=' + SMOKE_HOME + ' headed=' + HEADED)
109
+ console.log(
110
+ 'self-smoke: HOME=' +
111
+ SMOKE_HOME +
112
+ ' headed=' +
113
+ HEADED +
114
+ ' reuse-profile=' +
115
+ REUSE_PROFILE,
116
+ )
80
117
  await browser.launch()
81
- await browser.waitForLogin()
118
+ // waitForLogin() can block on a manual Enter in a pipe. Bound it so a cold
119
+ // login (anti-bot / captcha) fails fast with a clear hint instead of hanging
120
+ // until the caller's tool timeout. On failure exit code 2 signals "could not
121
+ // even start" — distinct from a scenario failure.
122
+ const loggedIn = await Promise.race([
123
+ browser.waitForLogin().then(() => true),
124
+ new Promise<boolean>((r) => setTimeout(() => r(false), 120_000)),
125
+ ])
126
+ if (!loggedIn) {
127
+ console.error(
128
+ '\nself-smoke: LOGIN FAILED — a cold login on a fresh profile is often\n' +
129
+ 'blocked by DeepSeek anti-bot/captcha. Re-run against a signed-in profile:\n' +
130
+ ' npm run self-smoke -- --reuse-profile\n' +
131
+ '(or sign in once with: npm run self-smoke -- --headed).',
132
+ )
133
+ loginFailed = true
134
+ return
135
+ }
82
136
  record('login', true, 'DeepSeek session is active')
83
137
 
84
138
  const tools = createTools(WORK, {})
@@ -252,4 +306,4 @@ if (!process.env.ZAMES_SMOKE_KEEP) {
252
306
  fs.rmSync(SMOKE_HOME, { recursive: true, force: true })
253
307
  } catch {}
254
308
  }
255
- process.exit(anyFail ? 1 : 0)
309
+ process.exit(loginFailed ? 2 : anyFail ? 1 : 0)