1688-cli 0.1.42 → 0.1.43

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 (60) hide show
  1. package/ARCHITECTURE.md +3 -2
  2. package/CHANGELOG.md +79 -0
  3. package/README.md +102 -24
  4. package/dist/cli.js +33 -25
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/checkout-confirm.js +8 -8
  7. package/dist/commands/checkout-confirm.js.map +1 -1
  8. package/dist/commands/doctor.js +46 -43
  9. package/dist/commands/doctor.js.map +1 -1
  10. package/dist/commands/inbox.js +1 -1
  11. package/dist/commands/inbox.js.map +1 -1
  12. package/dist/commands/login.js +14 -14
  13. package/dist/commands/login.js.map +1 -1
  14. package/dist/commands/logout.js +6 -4
  15. package/dist/commands/logout.js.map +1 -1
  16. package/dist/commands/profile.js +25 -9
  17. package/dist/commands/profile.js.map +1 -1
  18. package/dist/commands/seller-chat.js +1 -1
  19. package/dist/commands/seller-chat.js.map +1 -1
  20. package/dist/commands/seller-inquire.js +1 -1
  21. package/dist/commands/seller-inquire.js.map +1 -1
  22. package/dist/commands/seller-messages.js +1 -1
  23. package/dist/commands/seller-messages.js.map +1 -1
  24. package/dist/commands/whoami.js +6 -3
  25. package/dist/commands/whoami.js.map +1 -1
  26. package/dist/daemon/client.js +10 -6
  27. package/dist/daemon/client.js.map +1 -1
  28. package/dist/daemon/manager.js +53 -37
  29. package/dist/daemon/manager.js.map +1 -1
  30. package/dist/daemon/server.js +26 -22
  31. package/dist/daemon/server.js.map +1 -1
  32. package/dist/session/context.js +1 -1
  33. package/dist/session/context.js.map +1 -1
  34. package/dist/session/dispatch.js +23 -22
  35. package/dist/session/dispatch.js.map +1 -1
  36. package/dist/session/lock.js +14 -14
  37. package/dist/session/lock.js.map +1 -1
  38. package/dist/session/paths.js +39 -18
  39. package/dist/session/paths.js.map +1 -1
  40. package/dist/session/shared.js +17 -7
  41. package/dist/session/shared.js.map +1 -1
  42. package/dist/session/state.js +7 -7
  43. package/dist/session/state.js.map +1 -1
  44. package/docs/COMMANDS.md +9 -3
  45. package/docs/JSON_CONTRACTS.md +86 -0
  46. package/docs/QUALITY_SCORE.md +2 -1
  47. package/docs/README.md +1 -0
  48. package/docs/RELIABILITY.md +13 -5
  49. package/docs/SAFETY.md +1 -2
  50. package/docs/exec-plans/completed/2026-06-16-profile-daemon.md +146 -0
  51. package/docs/generated/command-index.md +5 -5
  52. package/docs/generated/json-shapes.md +1 -1
  53. package/docs/generated/test-index.md +1 -1
  54. package/docs/playbooks/update-cli-release.md +56 -6
  55. package/docs/records/release-omissions.md +34 -0
  56. package/docs/specs/index.md +9 -0
  57. package/docs/specs/profile-daemon.md +114 -0
  58. package/package.json +11 -4
  59. package/scripts/check_agent_map.mjs +2 -1
  60. package/scripts/check_release.mjs +40 -0
@@ -1,15 +1,16 @@
1
1
  import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
2
  import lockfile from 'proper-lockfile';
4
- import { lockFile, ensureRoot, root } from './paths.js';
3
+ import { defaultProfileName, ensureProfileRuntimeDir, lockFile, pidFile, } from './paths.js';
5
4
  import { CliError } from '../io/errors.js';
6
- export async function acquireLock() {
7
- await ensureRoot();
5
+ export async function acquireLock(profile) {
6
+ const profileName = defaultProfileName(profile);
7
+ await ensureProfileRuntimeDir(profileName);
8
+ const target = lockFile(profileName);
8
9
  // proper-lockfile requires the target file to exist
9
- await fs.writeFile(lockFile(), '', { flag: 'a' });
10
+ await fs.writeFile(target, '', { flag: 'a' });
10
11
  const lockOpts = { retries: 0, stale: 5 * 60 * 1000 };
11
12
  try {
12
- return await lockfile.lock(lockFile(), lockOpts);
13
+ return await lockfile.lock(target, lockOpts);
13
14
  }
14
15
  catch (e) {
15
16
  if (e.code !== 'ELOCKED')
@@ -18,22 +19,21 @@ export async function acquireLock() {
18
19
  // a stale dir left over by an abruptly-killed process (Ctrl+C in
19
20
  // --headed flow, SIGKILL on the daemon, etc.). If no daemon is running,
20
21
  // we can safely clean up and retry — the dead process can't be using it.
21
- if (await daemonIsAlive()) {
22
- throw new CliError(5, 'LOCK_BUSY', 'Another 1688 command is running. Close it and retry.');
22
+ if (await daemonIsAlive(profileName)) {
23
+ throw new CliError(5, 'LOCK_BUSY', `Another 1688 command is running for profile "${profileName}". Close it and retry.`);
23
24
  }
24
- await fs.rm(lockFile() + '.lock', { recursive: true, force: true });
25
+ await fs.rm(target + '.lock', { recursive: true, force: true });
25
26
  try {
26
- return await lockfile.lock(lockFile(), lockOpts);
27
+ return await lockfile.lock(target, lockOpts);
27
28
  }
28
29
  catch {
29
- throw new CliError(5, 'LOCK_BUSY', 'Another 1688 command is running. Close it and retry.');
30
+ throw new CliError(5, 'LOCK_BUSY', `Another 1688 command is running for profile "${profileName}". Close it and retry.`);
30
31
  }
31
32
  }
32
33
  }
33
- async function daemonIsAlive() {
34
- const pidFile = path.join(root(), 'daemon.pid');
34
+ async function daemonIsAlive(profile) {
35
35
  try {
36
- const pid = parseInt((await fs.readFile(pidFile, 'utf8')).trim(), 10);
36
+ const pid = parseInt((await fs.readFile(pidFile(profile), 'utf8')).trim(), 10);
37
37
  if (!Number.isFinite(pid) || pid <= 0)
38
38
  return false;
39
39
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/session/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,UAAU,EAAE,CAAC;IACnB,oDAAoD;IACpD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAElD,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAEtD,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAAuB,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM,CAAC,CAAC;QAEzD,mEAAmE;QACnE,iEAAiE;QACjE,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,MAAM,aAAa,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,QAAQ,CAChB,CAAC,EACD,WAAW,EACX,sDAAsD,CACvD,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,CAAC,EACD,WAAW,EACX,sDAAsD,CACvD,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,6CAA6C;YACnE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/session/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,QAAQ,EACR,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAgB;IAChD,MAAM,WAAW,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAChD,MAAM,uBAAuB,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC;IACrC,oDAAoD;IACpD,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAE9C,MAAM,QAAQ,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAEtD,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAAuB,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM,CAAC,CAAC;QAEzD,mEAAmE;QACnE,iEAAiE;QACjE,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,MAAM,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,QAAQ,CAChB,CAAC,EACD,WAAW,EACX,gDAAgD,WAAW,wBAAwB,CACpF,CAAC;QACJ,CAAC;QAED,MAAM,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,QAAQ,CAChB,CAAC,EACD,WAAW,EACX,gDAAgD,WAAW,wBAAwB,CACpF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,OAAgB;IAC3C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,6CAA6C;YACnE,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -8,24 +8,35 @@ export function root() {
8
8
  export function profilesDir() {
9
9
  return path.join(root(), 'profiles');
10
10
  }
11
- export function stateFile() {
12
- return path.join(root(), 'state.json');
11
+ export function defaultProfileName(profile) {
12
+ const name = profile?.trim();
13
+ return name ? name : 'default';
13
14
  }
14
- export function lockFile() {
15
- return path.join(root(), '.lock');
15
+ export function profileRuntimeDir(profile) {
16
+ const name = defaultProfileName(profile);
17
+ return name === 'default' ? root() : profilePath(name);
16
18
  }
17
- export function socketPath() {
18
- return socketPathForPlatform(process.platform, root());
19
+ export function stateFile(profile) {
20
+ return path.join(profileRuntimeDir(profile), 'state.json');
19
21
  }
20
- export function socketPathForPlatform(platform, rootPath) {
22
+ export function lockFile(profile) {
23
+ return path.join(profileRuntimeDir(profile), '.lock');
24
+ }
25
+ export function socketPath(profile) {
26
+ return socketPathForPlatform(process.platform, root(), profile);
27
+ }
28
+ export function socketPathForPlatform(platform, rootPath, profile) {
29
+ const name = defaultProfileName(profile);
21
30
  // Windows: Node's net.listen()/createConnection() can't bind a Unix-style
22
31
  // filesystem path on win32 (EACCES). Use a named pipe instead. Include a
23
- // stable root hash so different users, BB1688_HOME values, and tests do not
24
- // collide on one global pipe name.
32
+ // stable root hash so different users and BB1688_HOME values do not collide,
33
+ // and include the profile hash so profiles under one root can run together.
25
34
  if (platform === 'win32') {
26
- return `\\\\.\\pipe\\1688-cli-daemon-${rootHash(rootPath)}`;
35
+ const base = `\\\\.\\pipe\\1688-cli-daemon-${rootHash(rootPath)}`;
36
+ return name === 'default' ? base : `${base}-${profileHash(name)}`;
27
37
  }
28
- return path.join(rootPath, 'daemon.sock');
38
+ const dir = name === 'default' ? rootPath : path.join(rootPath, 'profiles', name);
39
+ return path.join(dir, 'daemon.sock');
29
40
  }
30
41
  export function rootHash(rootPath) {
31
42
  return crypto
@@ -34,14 +45,21 @@ export function rootHash(rootPath) {
34
45
  .digest('hex')
35
46
  .slice(0, 12);
36
47
  }
37
- export function pidFile() {
38
- return path.join(root(), 'daemon.pid');
48
+ export function profileHash(profile) {
49
+ return crypto
50
+ .createHash('sha1')
51
+ .update(defaultProfileName(profile).toLowerCase())
52
+ .digest('hex')
53
+ .slice(0, 12);
54
+ }
55
+ export function pidFile(profile) {
56
+ return path.join(profileRuntimeDir(profile), 'daemon.pid');
39
57
  }
40
- export function daemonVersionFile() {
41
- return path.join(root(), 'daemon.version');
58
+ export function daemonVersionFile(profile) {
59
+ return path.join(profileRuntimeDir(profile), 'daemon.version');
42
60
  }
43
- export function daemonLogFile() {
44
- return path.join(root(), 'daemon.log');
61
+ export function daemonLogFile(profile) {
62
+ return path.join(profileRuntimeDir(profile), 'daemon.log');
45
63
  }
46
64
  export function runsDir() {
47
65
  return path.join(root(), 'runs');
@@ -56,9 +74,12 @@ export function loginQrFile() {
56
74
  return path.join(root(), 'login-qr.png');
57
75
  }
58
76
  export function profilePath(name = 'default') {
59
- return path.join(profilesDir(), name);
77
+ return path.join(profilesDir(), defaultProfileName(name));
60
78
  }
61
79
  export async function ensureRoot() {
62
80
  await fs.mkdir(root(), { recursive: true });
63
81
  }
82
+ export async function ensureProfileRuntimeDir(profile) {
83
+ await fs.mkdir(profileRuntimeDir(profile), { recursive: true });
84
+ }
64
85
  //# sourceMappingURL=paths.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/session/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC,MAAM,UAAU,IAAI;IAClB,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,QAAyB,EAAE,QAAgB;IAC/E,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,mCAAmC;IACnC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,gCAAgC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,QAAgB;IACvC,OAAO,MAAM;SACV,UAAU,CAAC,MAAM,CAAC;SAClB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;SAC5C,MAAM,CAAC,KAAK,CAAC;SACb,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,cAAc,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAI,GAAG,SAAS;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC9C,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/session/paths.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  import fs from 'node:fs/promises';
5
5
  import { chromium } from 'playwright-extra';
6
6
  import stealth from 'puppeteer-extra-plugin-stealth';
7
- import { profilePath } from './paths.js';
7
+ import { defaultProfileName, profilePath } from './paths.js';
8
8
  import { acquireLock } from './lock.js';
9
9
  import { CliError } from '../io/errors.js';
10
10
  import { clearStaleSingleton } from './context.js';
@@ -22,14 +22,21 @@ const LAUNCH_OPTS = {
22
22
  let sharedCtx = null;
23
23
  let lockRelease = null;
24
24
  let opChain = Promise.resolve();
25
- export async function getSharedContext() {
26
- if (sharedCtx)
25
+ let sharedProfile = null;
26
+ export async function getSharedContext(profile) {
27
+ const profileName = defaultProfileName(profile);
28
+ if (sharedCtx) {
29
+ if (sharedProfile !== profileName) {
30
+ throw new CliError(5, 'DAEMON_PROFILE_MISMATCH', `Daemon shared context is bound to profile "${sharedProfile}", not "${profileName}".`);
31
+ }
27
32
  return sharedCtx;
28
- lockRelease = await acquireLock();
29
- const dir = profilePath('default');
33
+ }
34
+ lockRelease = await acquireLock(profileName);
35
+ const dir = profilePath(profileName);
30
36
  await fs.mkdir(dir, { recursive: true });
31
37
  await clearStaleSingleton(dir);
32
38
  sharedCtx = await launchPreferringChrome(dir, true);
39
+ sharedProfile = profileName;
33
40
  await sharedCtx.addInitScript(() => {
34
41
  try {
35
42
  Object.defineProperty(navigator, 'languages', {
@@ -42,7 +49,7 @@ export async function getSharedContext() {
42
49
  });
43
50
  return sharedCtx;
44
51
  }
45
- export async function runOnSharedCtx(fn, meta) {
52
+ export async function runOnSharedCtx(fn, meta, profile) {
46
53
  // Append to serial queue. Each op waits for the previous one to finish.
47
54
  const prev = opChain;
48
55
  let resolveOp;
@@ -53,7 +60,7 @@ export async function runOnSharedCtx(fn, meta) {
53
60
  });
54
61
  opChain = prev.then(async () => {
55
62
  try {
56
- const ctx = await getSharedContext();
63
+ const ctx = await getSharedContext(profile);
57
64
  resolveOp(await fn(ctx));
58
65
  }
59
66
  catch (e) {
@@ -71,6 +78,7 @@ export async function runOnSharedCtx(fn, meta) {
71
78
  export async function getSharedContextStatus() {
72
79
  if (!sharedCtx) {
73
80
  return {
81
+ profile: sharedProfile,
74
82
  browserAlive: false,
75
83
  pageCount: 0,
76
84
  currentUrl: null,
@@ -82,6 +90,7 @@ export async function getSharedContextStatus() {
82
90
  const page = pages.at(-1) ?? null;
83
91
  const pageState = page ? await detectPageState(page).catch(() => null) : null;
84
92
  return {
93
+ profile: sharedProfile,
85
94
  browserAlive: true,
86
95
  pageCount: pages.length,
87
96
  currentUrl: page?.url() ?? null,
@@ -100,6 +109,7 @@ export async function releaseSharedContext() {
100
109
  await sharedCtx.close().catch(() => { });
101
110
  sharedCtx = null;
102
111
  }
112
+ sharedProfile = null;
103
113
  if (lockRelease) {
104
114
  await lockRelease().catch(() => { });
105
115
  lockRelease = null;
@@ -1 +1 @@
1
- {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/session/shared.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/session/shared.ts"],"names":[],"mappings":"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"}
@@ -2,9 +2,9 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { stateFile, ensureRoot } from './paths.js';
4
4
  const EMPTY = { version: 1 };
5
- export async function readState() {
5
+ export async function readState(profile) {
6
6
  try {
7
- const buf = await fs.readFile(stateFile(), 'utf8');
7
+ const buf = await fs.readFile(stateFile(profile), 'utf8');
8
8
  const parsed = JSON.parse(buf);
9
9
  if (parsed?.version !== 1)
10
10
  return { ...EMPTY };
@@ -16,12 +16,12 @@ export async function readState() {
16
16
  throw e;
17
17
  }
18
18
  }
19
- export async function writeState(s) {
19
+ export async function writeState(s, profile) {
20
20
  await ensureRoot();
21
- await fs.mkdir(path.dirname(stateFile()), { recursive: true });
22
- await fs.writeFile(stateFile(), JSON.stringify(s, null, 2));
21
+ await fs.mkdir(path.dirname(stateFile(profile)), { recursive: true });
22
+ await fs.writeFile(stateFile(profile), JSON.stringify(s, null, 2));
23
23
  }
24
- export async function clearState() {
25
- await writeState({ ...EMPTY });
24
+ export async function clearState(profile) {
25
+ await writeState({ ...EMPTY }, profile);
26
26
  }
27
27
  //# sourceMappingURL=state.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/session/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAUnD,MAAM,KAAK,GAAU,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QACjD,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QACxE,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAQ;IACvC,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/session/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAUnD,MAAM,KAAK,GAAU,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;QACjD,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QAC/C,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,MAAM,EAAE,CAAC;IACjC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAK,CAA2B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;QACxE,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,CAAQ,EAAE,OAAgB;IACzD,MAAM,UAAU,EAAE,CAAC;IACnB,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAgB;IAC/C,MAAM,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC"}
package/docs/COMMANDS.md CHANGED
@@ -148,11 +148,17 @@ given.
148
148
  1688 login --force
149
149
  1688 logout [--yes]
150
150
  1688 whoami [--verify]
151
- 1688 doctor [--no-launch]
152
- 1688 daemon start | stop | status | reload
153
- 1688 serve
151
+ 1688 doctor [--no-launch] [--profile <name>]
152
+ 1688 daemon start | stop | status | reload [--profile <name>]
153
+ 1688 serve [--profile <name>]
154
+ 1688 profile list
155
+ 1688 profile status [name]
154
156
  ```
155
157
 
158
+ All account, browser, daemon, and buyer-workflow commands default to the
159
+ `default` profile. Passing `--profile <name>` uses that profile's persistent
160
+ browser directory, state file, daemon process, lock, and daemon artifacts.
161
+
156
162
  ## Output Flags
157
163
 
158
164
  Every command supports:
@@ -20,6 +20,92 @@ without an explicit breaking-change decision.
20
20
  { loggedIn: false }
21
21
  ```
22
22
 
23
+ ## `daemon status`
24
+
25
+ `daemon status` is profile-scoped. When `--profile` is omitted, `profile` is
26
+ `default`.
27
+
28
+ ```ts
29
+ {
30
+ profile: string,
31
+ running: boolean,
32
+ pid?: number,
33
+ reachable?: boolean,
34
+ version?: string | null,
35
+ expectedVersion?: string,
36
+ versionMatches?: boolean,
37
+ stats?: {
38
+ profile: string,
39
+ version: string,
40
+ startedAt: string,
41
+ pid: number,
42
+ commandCount: number,
43
+ lastRequestAt: string | null,
44
+ lastError: string | null,
45
+ uptimeMs: number,
46
+ activeClients: number,
47
+ browser: {
48
+ profile: string | null,
49
+ browserAlive: boolean,
50
+ pageCount: number,
51
+ currentUrl: string | null,
52
+ pageState: object | null,
53
+ loggedIn: boolean | null,
54
+ },
55
+ health: object,
56
+ },
57
+ }
58
+ ```
59
+
60
+ ## `profile status`
61
+
62
+ ```ts
63
+ {
64
+ profile: {
65
+ name: string,
66
+ path: string,
67
+ exists: boolean,
68
+ locked: boolean,
69
+ loggedIn: boolean,
70
+ recentRequestId: string | null,
71
+ recentStatus: string | null,
72
+ recentErrorCode: string | null,
73
+ daemon: {
74
+ profile: string,
75
+ running: boolean,
76
+ pid?: number,
77
+ reachable?: boolean,
78
+ version?: string | null,
79
+ expectedVersion?: string,
80
+ versionMatches?: boolean,
81
+ },
82
+ },
83
+ state: {
84
+ version: 1,
85
+ memberId?: string,
86
+ nick?: string,
87
+ loggedInAt?: string,
88
+ lastVerifiedAt?: string,
89
+ } | null,
90
+ }
91
+ ```
92
+
93
+ ## `doctor`
94
+
95
+ `doctor --profile <name>` checks that profile's directory, lock, state,
96
+ daemon, and live daemon socket. JSON output includes the selected `profile` and
97
+ the matching profile-scoped daemon status.
98
+
99
+ ```ts
100
+ {
101
+ ok: boolean,
102
+ profile: string,
103
+ checks: Array<{ name: string, status: "ok" | "warn" | "fail", message: string, fix?: string }>,
104
+ version: VersionInfo,
105
+ daemon: DaemonStatus | null,
106
+ }
107
+ ```
108
+
23
109
  ## `search`, `similar`, `image-search`
24
110
 
25
111
  ```ts
@@ -14,7 +14,8 @@ Overall: 6 / 10
14
14
  - Commands expose JSON automatically when piped and support `--json`,
15
15
  `--pretty`, `--get`, and `--pick`.
16
16
  - Real browser/session behavior is centralized under `src/session`.
17
- - The daemon gives agents a warm, shared browser context.
17
+ - Profile-scoped daemons give agents warm browser contexts without forcing
18
+ unrelated profiles through one global lock.
18
19
  - Checkout and feedback write actions already have explicit safety protocols.
19
20
  - Deterministic Vitest coverage exists for output, mtop parsing, recovery,
20
21
  page-state, inbox cards, and fixtures through `pnpm test:unit`.
package/docs/README.md CHANGED
@@ -20,6 +20,7 @@ This directory is the canonical knowledge base for agents and humans working on
20
20
 
21
21
  - Specs: [`specs/`](specs/)
22
22
  - Repeatable playbooks: [`playbooks/`](playbooks/)
23
+ - Records and postmortems: [`records/`](records/)
23
24
  - Generated repository indexes: [`generated/`](generated/)
24
25
  - Long-running plans: [`exec-plans/`](exec-plans/)
25
26
 
@@ -6,20 +6,28 @@ and recoverable for agents.
6
6
 
7
7
  ## Daemon
8
8
 
9
- The daemon routes commands through one persistent Chromium context.
9
+ Each daemon routes commands for one profile through one persistent Chromium
10
+ context. Different profiles use different daemon processes, locks, sockets or
11
+ named pipes, pid/version/log files, state files, and persistent browser
12
+ directories.
10
13
 
11
14
  Benefits:
12
15
 
13
16
  - Saves Chrome cold-start time.
14
- - Keeps one continuous logged-in session.
17
+ - Keeps one continuous logged-in session per profile.
15
18
  - Adds inter-command jitter.
19
+ - Allows different profiles to run at the same time without sharing one
20
+ process lock.
16
21
 
17
22
  Use `1688 daemon start` near the beginning of a session with multiple 1688
18
- commands. The daemon auto-stops after inactivity. Run `1688 daemon reload`
19
- after package updates.
23
+ commands. Use `1688 daemon start --profile <name>` for a non-default profile.
24
+ The daemon auto-stops after inactivity. Run `1688 daemon reload --profile
25
+ <name>` after package updates or after manually resolving profile-specific
26
+ browser issues.
20
27
 
21
28
  `login`, `logout`, and `doctor` stay inline because they need interactive UI,
22
- browser windows, or environment checks.
29
+ browser windows, or environment checks. `login --profile <name>` can
30
+ auto-start that profile daemon after the login state is available.
23
31
 
24
32
  ## Watch Mode
25
33
 
package/docs/SAFETY.md CHANGED
@@ -12,7 +12,7 @@ place orders. Treat write actions as explicit user-authorized operations.
12
12
  | 2 | Bad invocation | Fix arguments or report the bad input. |
13
13
  | 3 | Not logged in / session expired | Tell the user to run `1688 login`; do not loop. |
14
14
  | 4 | Risk control / slider verification | Tell the user to rerun once with `--headed`; do not silently retry. |
15
- | 5 | Another 1688 command is running | Wait only if the task naturally allows it; otherwise report lock busy. |
15
+ | 5 | Another 1688 command is running for the selected profile | Wait only if the task naturally allows it; otherwise report lock busy. |
16
16
  | 6 | Chromium missing | Report dependency issue. |
17
17
  | 7 | Login wait timeout | Report timeout. |
18
18
  | 8 | Login finished but cookies missing | Report login cookie issue. |
@@ -97,4 +97,3 @@ Rules:
97
97
  command.
98
98
  - In non-interactive loops, do not upgrade automatically.
99
99
  - After an approved package update, run `1688 daemon reload`.
100
-
@@ -0,0 +1,146 @@
1
+ # Plan: Profile Daemon
2
+
3
+ ## Goal
4
+
5
+ Deliver profile-scoped daemon mode for `1688-cli`: one daemon, persistent
6
+ browser context, lock, and runtime artifact set per profile, with default
7
+ profile compatibility and deterministic verification.
8
+
9
+ ## Context
10
+
11
+ - Source spec: `docs/specs/profile-daemon.md`.
12
+ - Read first:
13
+ - `AGENTS.md`
14
+ - `ARCHITECTURE.md`
15
+ - `docs/WORKFLOW.md`
16
+ - `docs/COMMANDS.md`
17
+ - `docs/JSON_CONTRACTS.md`
18
+ - `docs/SAFETY.md`
19
+ - `docs/RELIABILITY.md`
20
+ - `docs/playbooks/add-command.md`
21
+ - `src/session/paths.ts`
22
+ - `src/session/lock.ts`
23
+ - `src/session/context.ts`
24
+ - `src/session/shared.ts`
25
+ - `src/session/dispatch.ts`
26
+ - `src/daemon/client.ts`
27
+ - `src/daemon/manager.ts`
28
+ - `src/daemon/server.ts`
29
+ - `src/commands/login.ts`
30
+ - `src/commands/doctor.ts`
31
+ - `src/commands/profile.ts`
32
+ - `src/cli.ts`
33
+ - `tests/paths.test.ts`
34
+ - `tests/profile.test.ts`
35
+ - `tests/doctor.test.ts`
36
+
37
+ ## Non-goals
38
+
39
+ - Do not implement a multi-profile daemon process.
40
+ - Do not change checkout confirmation safety.
41
+ - Do not run external live login/search/browser flows during verification.
42
+ - Do not introduce new dependencies.
43
+ - Do not refactor unrelated command behavior.
44
+
45
+ ## Design
46
+
47
+ Use one profile-bound daemon process per profile. The profile is resolved to
48
+ `default` at the edge and then passed through path helpers, locks, daemon
49
+ client/manager/server, shared context, dispatch, login, doctor, and profile
50
+ status.
51
+
52
+ Runtime artifacts become profile-scoped via centralized helpers. Non-Windows
53
+ sockets live under a profile runtime directory; Windows named pipes include the
54
+ root hash plus a profile-derived hash/slug so profiles do not collide.
55
+
56
+ `dispatch` no longer treats `opts.profile` as a daemon skip condition. It
57
+ connects to the selected profile daemon, auto-starts or refreshes only that
58
+ daemon, and falls back inline only for that profile. Headed mode, `noDaemon`,
59
+ and `BB1688_NO_DAEMON=1` still skip daemon dispatch.
60
+
61
+ Inline fallback pauses only the selected profile daemon before opening an
62
+ inline context on that profile. Other profile daemons continue running.
63
+
64
+ `login --profile` writes profile-scoped state and attempts to start that
65
+ profile daemon unless `--no-daemon` is set. `doctor --profile` and
66
+ `profile status <name>` read profile-scoped state, lock, and daemon status.
67
+
68
+ Docs and generated indexes are updated because command flags, daemon behavior,
69
+ and source/test layout behavior changed.
70
+
71
+ ## Checklist
72
+
73
+ - [x] Create spec/index and active ExecPlan for profile-scoped daemon work.
74
+ - [x] Implement profile-scoped path helpers and lock acquisition.
75
+ - [x] Thread profile through session context, shared daemon context, daemon
76
+ client, daemon manager, and daemon server.
77
+ - [x] Update dispatch so explicit `--profile` uses the corresponding daemon and
78
+ inline fallback pauses only that profile daemon.
79
+ - [x] Update CLI daemon/serve commands, login auto-start, doctor checks, and
80
+ profile status to use selected profile state and diagnostics.
81
+ - [x] Update deterministic tests for paths, profile status, doctor, and daemon
82
+ profile plumbing.
83
+ - [x] Update durable docs and regenerate generated context.
84
+ - [x] Run focused and final verification, review diff, and record results.
85
+
86
+ ## Verification
87
+
88
+ - `pnpm typecheck`
89
+ - `pnpm test:unit`
90
+ - `pnpm agent-context`
91
+ - `pnpm docs-check`
92
+ - `pnpm agent-map-check`
93
+ - `pnpm agent-verify`
94
+
95
+ ## Decisions
96
+
97
+ - 2026-06-16: Use one daemon process per profile instead of one daemon managing
98
+ many browser contexts, matching the request and current daemon architecture.
99
+ - 2026-06-16: Keep `checkout-confirm` daemon-blocked; profile daemon support
100
+ does not weaken checkout safety.
101
+ - 2026-06-16: Use deterministic local verification only; live 1688 browser
102
+ checks require user/session state and are out of scope for automated tests.
103
+
104
+ ## Progress Log
105
+
106
+ - 2026-06-16: `/to-done` readiness path selected: clear complex request with no
107
+ existing matching durable spec or active plan, so create full spec and full
108
+ active ExecPlan before implementation.
109
+ - 2026-06-16: `/run` execution strategy selected. Goal tracking preference:
110
+ prefer Codex /goal. Goal tracking result: Codex /goal. Delegation: none.
111
+ Reason: the active plan has one objective, scoped non-goals, deterministic
112
+ verification, and an adaptive validation loop. Subagents skipped because the
113
+ core daemon/session files are tightly coupled and should be edited/reviewed
114
+ by the primary agent. Completed checklist item: durable spec/index and active
115
+ ExecPlan created.
116
+ - 2026-06-16: Implemented profile-scoped runtime helpers for socket, pid,
117
+ version, log, state, and lock artifacts. Default artifacts remain compatible
118
+ at the historical root paths; non-default profiles use their profile runtime
119
+ directory. Windows daemon pipes now include a profile hash.
120
+ - 2026-06-16: Threaded profile through locks, inline sessions, shared daemon
121
+ browser context, daemon client/manager/server, dispatch, login auto-start,
122
+ doctor, profile status, whoami state writes, seller/inbox state reads, and
123
+ checkout-confirm daemon pause/resume.
124
+ - 2026-06-16: Updated durable docs (`ARCHITECTURE.md`, `docs/COMMANDS.md`,
125
+ `docs/JSON_CONTRACTS.md`, `docs/RELIABILITY.md`, `docs/SAFETY.md`,
126
+ `docs/QUALITY_SCORE.md`) and refreshed generated context with
127
+ `pnpm agent-context`.
128
+ - 2026-06-16: Review result: diff stayed within the profile daemon spec and
129
+ plan; checkout confirmation remains daemon-blocked and approval behavior is
130
+ unchanged. A small doctor indentation/readability issue found during diff
131
+ review was fixed before final verification.
132
+ - 2026-06-16: Verification passed:
133
+ `pnpm typecheck`;
134
+ `pnpm vitest run tests/paths.test.ts tests/state.test.ts tests/profile.test.ts tests/doctor.test.ts --exclude tests/doctor-live.test.ts`;
135
+ `pnpm test:unit`;
136
+ `pnpm agent-context`;
137
+ `pnpm agent-verify`.
138
+ Final `pnpm agent-verify` passed with 27 test files and 174 deterministic
139
+ tests, fresh generated context, passing agent-map check, and passing release
140
+ check. No blockers or new open questions remain.
141
+
142
+ ## Rollback
143
+
144
+ Revert the profile daemon changes in `src/session`, `src/daemon`,
145
+ `src/commands`, `src/cli.ts`, tests, and docs. Existing profile browser data
146
+ under `~/.1688/profiles/<name>` is not modified by rollback.