@love-moon/chat-web 0.5.0 → 0.6.0
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 +22 -0
- package/dist/core/browser.js +11 -2
- package/dist/core/browser.js.map +1 -1
- package/dist/core/errors.d.ts +4 -1
- package/dist/core/errors.js +12 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/profile-lock.d.ts +15 -0
- package/dist/core/profile-lock.js +182 -0
- package/dist/core/profile-lock.js.map +1 -0
- package/dist/session.js +5 -0
- package/dist/session.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @love-moon/chat-web
|
|
2
2
|
|
|
3
|
+
## 0.6.0
|
|
4
|
+
|
|
5
|
+
## 0.5.1
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- 39a49fc: fix: reclaim orphaned chat-web browser and cap chat-web task lifetime
|
|
10
|
+
|
|
11
|
+
chat-web persists one Chromium profile per provider, guarded by a per-profile
|
|
12
|
+
SingletonLock. A task whose browser was not cleaned up (e.g. the ai-sdk worker
|
|
13
|
+
was SIGKILLed) left an orphaned Chromium holding that lock, so the next task for
|
|
14
|
+
the same provider failed to launch with `Opening in existing browser session`.
|
|
15
|
+
|
|
16
|
+
- chat-web now reclaims stale/orphaned profile locks before launching (kills an
|
|
17
|
+
orphan whose owner process is gone, clears dead locks) and refuses with a
|
|
18
|
+
clear `ProfileLockedError` when a genuine live chat still holds the profile.
|
|
19
|
+
- The ai-sdk worker now closes its session (and browser) on SIGTERM/SIGINT and
|
|
20
|
+
bounds the close so it can't hang, preventing browser leaks on shutdown.
|
|
21
|
+
- conductor fire caps a chat-web task's active lifetime (default 24h,
|
|
22
|
+
`CONDUCTOR_CHATWEB_MAX_ACTIVE_MS`) and auto-stops it as
|
|
23
|
+
`KILLED / max_active_duration`; chat history is preserved.
|
|
24
|
+
|
|
3
25
|
## 0.5.0
|
|
4
26
|
|
|
5
27
|
## 0.4.2
|
package/dist/core/browser.js
CHANGED
|
@@ -2,6 +2,7 @@ import { chromium } from "playwright";
|
|
|
2
2
|
import { BrowserLaunchError } from "./errors.js";
|
|
3
3
|
import { autoInstallDisabled, hasAttemptedAutoInstall, installChromium, isBrowserMissingError, markAutoInstallAttempted, } from "./install-chromium.js";
|
|
4
4
|
import { defaultLogger } from "./logger.js";
|
|
5
|
+
import { reclaimProfileLock, writeProfileOwner } from "./profile-lock.js";
|
|
5
6
|
import { createProfileManager } from "./profile-manager.js";
|
|
6
7
|
/**
|
|
7
8
|
* Launch (or reattach to) a persistent Chromium context for a provider.
|
|
@@ -30,8 +31,14 @@ export async function launchProviderBrowser(provider, options = {}) {
|
|
|
30
31
|
],
|
|
31
32
|
...resolveBrowserBinary(options),
|
|
32
33
|
};
|
|
34
|
+
// Enforce "one live chat per profile" and self-heal stale/orphaned locks
|
|
35
|
+
// before launching. Throws ProfileLockedError if a genuine live chat for
|
|
36
|
+
// this provider is still running (see profile-lock.ts).
|
|
37
|
+
await reclaimProfileLock({ userDataDir, provider, logger });
|
|
33
38
|
try {
|
|
34
|
-
|
|
39
|
+
const launched = await launch(userDataDir, launchArgs);
|
|
40
|
+
writeProfileOwner(userDataDir, provider);
|
|
41
|
+
return launched;
|
|
35
42
|
}
|
|
36
43
|
catch (err) {
|
|
37
44
|
// First-failure recovery path: if Chromium isn't installed, try to
|
|
@@ -51,7 +58,9 @@ export async function launchProviderBrowser(provider, options = {}) {
|
|
|
51
58
|
throw new BrowserLaunchError(provider, `Auto-install of Chromium failed for "${provider}". Run manually: \`npx playwright install chromium\` (cause: ${installErr.message})`, installErr);
|
|
52
59
|
}
|
|
53
60
|
try {
|
|
54
|
-
|
|
61
|
+
const launched = await launch(userDataDir, launchArgs);
|
|
62
|
+
writeProfileOwner(userDataDir, provider);
|
|
63
|
+
return launched;
|
|
55
64
|
}
|
|
56
65
|
catch (retryErr) {
|
|
57
66
|
throw new BrowserLaunchError(provider, `Failed to launch Chromium for "${provider}" at ${userDataDir} even after auto-install: ${retryErr.message}`, retryErr);
|
package/dist/core/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/core/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAkC,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAA8B,MAAM,sBAAsB,CAAC;AA+DxF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAgB,EAChB,UAAyB,EAAE;IAE3B,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,oBAAoB,EAAE,CAAC;IACxE,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACjE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;IAE/C,MAAM,UAAU,GAAyB;QACvC,QAAQ,EAAE,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC3C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAC1D,IAAI,EAAE;YACJ,kEAAkE;YAClE,uDAAuD;YACvD,+CAA+C;YAC/C,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;SACxB;QACD,GAAG,oBAAoB,CAAC,OAAO,CAAC;KACjC,CAAC;IAEF,IAAI,CAAC;QACH,
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/core/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/core/errors.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* field (human-friendly next action), so CLI / daemon callers can both
|
|
6
6
|
* branch on the code and surface a useful remediation step.
|
|
7
7
|
*/
|
|
8
|
-
export type ChatWebErrorCode = "NOT_LOGGED_IN" | "INPUT_NOT_FOUND" | "SEND_BUTTON_NOT_FOUND" | "RESPONSE_TIMEOUT" | "RESPONSE_EXTRACTION" | "PROVIDER_RATE_LIMITED" | "PROVIDER_CAPTCHA" | "PROVIDER_API_KEY_REQUIRED" | "PROVIDER_PERMISSION_DENIED" | "PROVIDER_AUTOMATION_BLOCKED" | "SELECTOR_VERIFICATION" | "UNKNOWN_PROVIDER" | "PROFILE_ERROR" | "BROWSER_LAUNCH_FAILED";
|
|
8
|
+
export type ChatWebErrorCode = "NOT_LOGGED_IN" | "INPUT_NOT_FOUND" | "SEND_BUTTON_NOT_FOUND" | "RESPONSE_TIMEOUT" | "RESPONSE_EXTRACTION" | "PROVIDER_RATE_LIMITED" | "PROVIDER_CAPTCHA" | "PROVIDER_API_KEY_REQUIRED" | "PROVIDER_PERMISSION_DENIED" | "PROVIDER_AUTOMATION_BLOCKED" | "SELECTOR_VERIFICATION" | "UNKNOWN_PROVIDER" | "PROFILE_ERROR" | "PROFILE_LOCKED" | "BROWSER_LAUNCH_FAILED";
|
|
9
9
|
export declare class ChatWebError extends Error {
|
|
10
10
|
readonly code: ChatWebErrorCode;
|
|
11
11
|
readonly hint?: string;
|
|
@@ -55,6 +55,9 @@ export declare class UnknownProviderError extends ChatWebError {
|
|
|
55
55
|
export declare class ProfileError extends ChatWebError {
|
|
56
56
|
constructor(provider: string, message: string, cause?: unknown);
|
|
57
57
|
}
|
|
58
|
+
export declare class ProfileLockedError extends ChatWebError {
|
|
59
|
+
constructor(provider: string, browserPid: number, ownerPid: number);
|
|
60
|
+
}
|
|
58
61
|
export declare class BrowserLaunchError extends ChatWebError {
|
|
59
62
|
constructor(provider: string, message: string, cause?: unknown);
|
|
60
63
|
}
|
package/dist/core/errors.js
CHANGED
|
@@ -140,6 +140,18 @@ export class ProfileError extends ChatWebError {
|
|
|
140
140
|
this.name = "ProfileError";
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
|
+
export class ProfileLockedError extends ChatWebError {
|
|
144
|
+
constructor(provider, browserPid, ownerPid) {
|
|
145
|
+
super("PROFILE_LOCKED", `Provider "${provider}" already has a live chat session ` +
|
|
146
|
+
`(Chromium pid ${browserPid}, owned by pid ${ownerPid}). ` +
|
|
147
|
+
`chat-web allows only one live chat per profile at a time.`, {
|
|
148
|
+
provider,
|
|
149
|
+
hint: `Wait for the active "${provider}" chat to finish, or stop its owner ` +
|
|
150
|
+
`process (kill ${ownerPid}) before starting another.`,
|
|
151
|
+
});
|
|
152
|
+
this.name = "ProfileLockedError";
|
|
153
|
+
}
|
|
154
|
+
}
|
|
143
155
|
export class BrowserLaunchError extends ChatWebError {
|
|
144
156
|
constructor(provider, message, cause) {
|
|
145
157
|
super("BROWSER_LAUNCH_FAILED", message, {
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAwBA,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAmB;IACvB,IAAI,CAAU;IACd,QAAQ,CAAU;IAE3B,YACE,IAAsB,EACtB,OAAe,EACf,UAAiE,EAAE;QAEnE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAA4B,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtD,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IAChD,YAAY,QAAgB;QAC1B,KAAK,CAAC,eAAe,EAAE,aAAa,QAAQ,qBAAqB,EAAE;YACjE,QAAQ;YACR,IAAI,EAAE,uBAAuB,QAAQ,EAAE;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,QAAgB;QAC1B,KAAK,CAAC,iBAAiB,EAAE,uCAAuC,QAAQ,IAAI,EAAE;YAC5E,QAAQ;YACR,IAAI,EAAE,wBAAwB,QAAQ,aAAa;SACpD,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,YAAY;IACvD,YAAY,QAAgB;QAC1B,KAAK,CAAC,uBAAuB,EAAE,yCAAyC,QAAQ,IAAI,EAAE;YACpF,QAAQ;YACR,IAAI,EAAE,wBAAwB,QAAQ,aAAa;SACpD,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,QAAgB,EAAE,SAAiB;QAC7C,KAAK,CACH,kBAAkB,EAClB,mBAAmB,SAAS,mBAAmB,QAAQ,aAAa,EACpE;YACE,QAAQ;YACR,IAAI,EAAE,qBAAqB,QAAQ,cAAc,SAAS,GAAG,CAAC,QAAQ;SACvE,CACF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,uBAAwB,SAAQ,YAAY;IACvD,YAAY,QAAgB,EAAE,OAAO,GAAG,sCAAsC;QAC5E,KAAK,CAAC,qBAAqB,EAAE,OAAO,EAAE;YACpC,QAAQ;YACR,IAAI,EAAE,wBAAwB,QAAQ,aAAa;SACpD,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,YAAY;IACxD,YAAY,QAAgB;QAC1B,KAAK,CAAC,uBAAuB,EAAE,aAAa,QAAQ,mCAAmC,EAAE;YACvF,QAAQ;YACR,IAAI,EAAE,gEAAgE;SACvE,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,QAAgB;QAC1B,KAAK,CAAC,kBAAkB,EAAE,aAAa,QAAQ,qCAAqC,EAAE;YACpF,QAAQ;YACR,IAAI,EAAE,uBAAuB,QAAQ,wDAAwD;SAC9F,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,YAAY;IAC3D,YAAY,QAAgB,EAAE,MAAe;QAC3C,MAAM,IAAI,GAAG,aAAa,QAAQ,mDAAmD,CAAC;QACtF,KAAK,CAAC,2BAA2B,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;YACtE,QAAQ;YACR,IAAI,EACF,QAAQ,KAAK,QAAQ;gBACnB,CAAC,CAAC,sEAAsE;oBACtE,wEAAwE;oBACxE,iFAAiF;oBACjF,kFAAkF;oBAClF,6BAA6B;gBAC/B,CAAC,CAAC,4BAA4B,QAAQ,sBAAsB;SACjE,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,6BAA6B,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,OAAO,8BAA+B,SAAQ,YAAY;IAC9D,YAAY,QAAgB,EAAE,MAAe;QAC3C,MAAM,IAAI,GACR,aAAa,QAAQ,4CAA4C;YACjE,2GAA2G,CAAC;QAC9G,KAAK,CACH,6BAA6B,EAC7B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EACnC;YACE,QAAQ;YACR,IAAI,EACF,QAAQ,KAAK,QAAQ;gBACnB,CAAC,CAAC,iFAAiF;oBACjF,uEAAuE;oBACvE,6GAA6G;oBAC7G,mHAAmH;oBACnH,uDAAuD;gBACzD,CAAC,CAAC,iGAAiG;SACxG,CACF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,gCAAgC,CAAC;IAC/C,CAAC;CACF;AAED,MAAM,OAAO,6BAA8B,SAAQ,YAAY;IAC7D,YAAY,QAAgB,EAAE,MAAe;QAC3C,MAAM,IAAI,GAAG,aAAa,QAAQ,2CAA2C,CAAC;QAC9E,KAAK,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;YACvE,QAAQ;YACR,IAAI,EACF,4JAA4J;SAC/J,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAC;IAC9C,CAAC;CACF;AAED,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACzD,YAAY,QAAgB,EAAE,IAAY;QACxC,KAAK,CACH,uBAAuB,EACvB,qCAAqC,QAAQ,mBAAmB,IAAI,GAAG,EACvE;YACE,QAAQ;YACR,IAAI,EAAE,wBAAwB,QAAQ,aAAa;SACpD,CACF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,QAAgB,EAAE,KAAwB;QACpD,KAAK,CACH,kBAAkB,EAClB,qBAAqB,QAAQ,uBAAuB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACtE,EAAE,QAAQ,EAAE,IAAI,EAAE,eAAe,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CACtD,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,YAAY;IAC5C,YAAY,QAAgB,EAAE,OAAe,EAAE,KAAe;QAC5D,KAAK,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,QAAgB,EAAE,UAAkB,EAAE,QAAgB;QAChE,KAAK,CACH,gBAAgB,EAChB,aAAa,QAAQ,oCAAoC;YACvD,iBAAiB,UAAU,kBAAkB,QAAQ,KAAK;YAC1D,2DAA2D,EAC7D;YACE,QAAQ;YACR,IAAI,EACF,wBAAwB,QAAQ,sCAAsC;gBACtE,iBAAiB,QAAQ,4BAA4B;SACxD,CACF,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAClD,YAAY,QAAgB,EAAE,OAAe,EAAE,KAAe;QAC5D,KAAK,CAAC,uBAAuB,EAAE,OAAO,EAAE;YACtC,QAAQ;YACR,KAAK;YACL,IAAI,EAAE,6DAA6D;SACpE,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Logger } from "./logger.js";
|
|
2
|
+
/** Record the current process as the owner of this profile's browser. */
|
|
3
|
+
export declare function writeProfileOwner(userDataDir: string, provider: string): void;
|
|
4
|
+
/** Remove the owner sidecar once the browser context is closed. */
|
|
5
|
+
export declare function clearProfileOwner(userDataDir: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Reclaim stale/orphaned Chromium locks for a profile, or throw
|
|
8
|
+
* `ProfileLockedError` if a genuine live chat is still using it.
|
|
9
|
+
* Call this immediately before `launchPersistentContext`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function reclaimProfileLock(params: {
|
|
12
|
+
userDataDir: string;
|
|
13
|
+
provider: string;
|
|
14
|
+
logger?: Logger;
|
|
15
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { ProfileLockedError } from "./errors.js";
|
|
5
|
+
import { defaultLogger } from "./logger.js";
|
|
6
|
+
/**
|
|
7
|
+
* "One live chat per profile" enforcement + stale/orphan lock reclaim.
|
|
8
|
+
*
|
|
9
|
+
* chat-web persists a full Chromium `userDataDir` per provider (RFC §19.1),
|
|
10
|
+
* and Chromium guards that directory with a `SingletonLock` symlink. Because
|
|
11
|
+
* every fire task is its own process, two tasks for the same provider would
|
|
12
|
+
* otherwise race for the same profile and the second one fails with
|
|
13
|
+
* `launchPersistentContext: Opening in existing browser session`.
|
|
14
|
+
*
|
|
15
|
+
* We make that contract explicit and self-healing:
|
|
16
|
+
* - no lock / lock pid dead → clear stale lock, proceed
|
|
17
|
+
* - lock pid alive, not our Chromium → pid reuse, clear stale lock, proceed
|
|
18
|
+
* - lock pid alive, our Chromium, but
|
|
19
|
+
* its owning worker is gone → orphan, kill + reclaim, proceed
|
|
20
|
+
* - lock pid alive, owner alive → genuine live chat → throw
|
|
21
|
+
*
|
|
22
|
+
* The "owner" is the worker/process that launched the browser; we record its
|
|
23
|
+
* pid in a small sidecar file so a later launch can tell an orphaned browser
|
|
24
|
+
* (owner died, e.g. worker SIGKILLed) apart from one a live task still uses.
|
|
25
|
+
*/
|
|
26
|
+
const OWNER_FILE = ".chat-web-owner.json";
|
|
27
|
+
const SINGLETON_FILES = ["SingletonLock", "SingletonCookie", "SingletonSocket"];
|
|
28
|
+
function ownerFilePath(userDataDir) {
|
|
29
|
+
return path.join(userDataDir, OWNER_FILE);
|
|
30
|
+
}
|
|
31
|
+
function isProcessAlive(pid) {
|
|
32
|
+
if (pid === null || !Number.isInteger(pid) || pid <= 0)
|
|
33
|
+
return false;
|
|
34
|
+
try {
|
|
35
|
+
// Signal 0 performs error checking without actually sending a signal.
|
|
36
|
+
process.kill(pid, 0);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
// EPERM means the process exists but we can't signal it → still alive.
|
|
41
|
+
return err.code === "EPERM";
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function waitForProcessExit(pid, timeoutMs) {
|
|
45
|
+
const deadline = Date.now() + timeoutMs;
|
|
46
|
+
while (Date.now() < deadline) {
|
|
47
|
+
if (!isProcessAlive(pid))
|
|
48
|
+
return true;
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
50
|
+
}
|
|
51
|
+
return !isProcessAlive(pid);
|
|
52
|
+
}
|
|
53
|
+
function readSingletonLockPid(userDataDir) {
|
|
54
|
+
try {
|
|
55
|
+
// Chromium writes SingletonLock as a symlink: "<hostname>-<pid>".
|
|
56
|
+
const target = fs.readlinkSync(path.join(userDataDir, "SingletonLock"));
|
|
57
|
+
const match = /-(\d+)\s*$/.exec(target);
|
|
58
|
+
if (!match)
|
|
59
|
+
return null;
|
|
60
|
+
const pid = Number.parseInt(match[1], 10);
|
|
61
|
+
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Not a symlink / does not exist → nothing decipherable to reclaim.
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function processCommandLine(pid) {
|
|
69
|
+
if (process.platform === "win32")
|
|
70
|
+
return "";
|
|
71
|
+
try {
|
|
72
|
+
return execFileSync("ps", ["-p", String(pid), "-o", "command="], {
|
|
73
|
+
encoding: "utf8",
|
|
74
|
+
timeout: 2_000,
|
|
75
|
+
}).trim();
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return "";
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function clearSingletonFiles(userDataDir) {
|
|
82
|
+
for (const name of SINGLETON_FILES) {
|
|
83
|
+
try {
|
|
84
|
+
fs.rmSync(path.join(userDataDir, name), { force: true });
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// best effort
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function readOwner(userDataDir) {
|
|
92
|
+
try {
|
|
93
|
+
const parsed = JSON.parse(fs.readFileSync(ownerFilePath(userDataDir), "utf8"));
|
|
94
|
+
return parsed && Number.isInteger(parsed.ownerPid) ? parsed : null;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/** Record the current process as the owner of this profile's browser. */
|
|
101
|
+
export function writeProfileOwner(userDataDir, provider) {
|
|
102
|
+
try {
|
|
103
|
+
const owner = {
|
|
104
|
+
ownerPid: process.pid,
|
|
105
|
+
provider,
|
|
106
|
+
startedAt: new Date().toISOString(),
|
|
107
|
+
};
|
|
108
|
+
fs.writeFileSync(ownerFilePath(userDataDir), JSON.stringify(owner), "utf8");
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Non-fatal: the owner file is only an optimisation for orphan detection.
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/** Remove the owner sidecar once the browser context is closed. */
|
|
115
|
+
export function clearProfileOwner(userDataDir) {
|
|
116
|
+
try {
|
|
117
|
+
fs.rmSync(ownerFilePath(userDataDir), { force: true });
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
// best effort
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Reclaim stale/orphaned Chromium locks for a profile, or throw
|
|
125
|
+
* `ProfileLockedError` if a genuine live chat is still using it.
|
|
126
|
+
* Call this immediately before `launchPersistentContext`.
|
|
127
|
+
*/
|
|
128
|
+
export async function reclaimProfileLock(params) {
|
|
129
|
+
const { userDataDir, provider } = params;
|
|
130
|
+
const logger = params.logger ?? defaultLogger;
|
|
131
|
+
const lockPid = readSingletonLockPid(userDataDir);
|
|
132
|
+
if (lockPid === null) {
|
|
133
|
+
return; // No decipherable lock → let Playwright proceed normally.
|
|
134
|
+
}
|
|
135
|
+
if (!isProcessAlive(lockPid)) {
|
|
136
|
+
logger.warn(`chat-web: clearing stale SingletonLock for "${provider}" (pid ${lockPid} no longer running).`);
|
|
137
|
+
clearSingletonFiles(userDataDir);
|
|
138
|
+
clearProfileOwner(userDataDir);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// The pid is alive — make sure it is actually this profile's Chromium and
|
|
142
|
+
// not an unrelated process that reused the pid number.
|
|
143
|
+
if (!processCommandLine(lockPid).includes(`--user-data-dir=${userDataDir}`)) {
|
|
144
|
+
logger.warn(`chat-web: SingletonLock pid ${lockPid} is not this profile's Chromium; ` +
|
|
145
|
+
`clearing stale lock for "${provider}".`);
|
|
146
|
+
clearSingletonFiles(userDataDir);
|
|
147
|
+
clearProfileOwner(userDataDir);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// It is a live Chromium for this profile. Orphan (owner gone) or in use?
|
|
151
|
+
const owner = readOwner(userDataDir);
|
|
152
|
+
if (!owner || !isProcessAlive(owner.ownerPid)) {
|
|
153
|
+
logger.warn(`chat-web: reclaiming orphaned Chromium for "${provider}" ` +
|
|
154
|
+
`(browser pid ${lockPid}, owner ${owner ? `pid ${owner.ownerPid}` : "unknown"} no longer running).`);
|
|
155
|
+
// Terminate gracefully so the orphan flushes profile data (cookies /
|
|
156
|
+
// login state), then WAIT for it to exit before clearing the lock. If we
|
|
157
|
+
// cleared the lock while the orphan was still shutting down, its own
|
|
158
|
+
// cleanup could unlink the fresh SingletonLock the new browser writes —
|
|
159
|
+
// reintroducing exactly the lock contention we're fixing.
|
|
160
|
+
try {
|
|
161
|
+
process.kill(lockPid, "SIGTERM");
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
// already gone
|
|
165
|
+
}
|
|
166
|
+
if (!(await waitForProcessExit(lockPid, 4_000))) {
|
|
167
|
+
try {
|
|
168
|
+
process.kill(lockPid, "SIGKILL");
|
|
169
|
+
}
|
|
170
|
+
catch {
|
|
171
|
+
// already gone
|
|
172
|
+
}
|
|
173
|
+
await waitForProcessExit(lockPid, 2_000);
|
|
174
|
+
}
|
|
175
|
+
clearSingletonFiles(userDataDir);
|
|
176
|
+
clearProfileOwner(userDataDir);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
// Browser alive AND its owner alive → a real live chat. Refuse to launch.
|
|
180
|
+
throw new ProfileLockedError(provider, lockPid, owner.ownerPid);
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=profile-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-lock.js","sourceRoot":"","sources":["../../src/core/profile-lock.ts"],"names":[],"mappings":"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"}
|
package/dist/session.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { launchProviderBrowser } from "./core/browser.js";
|
|
2
2
|
import { NotLoggedInError } from "./core/errors.js";
|
|
3
|
+
import { clearProfileOwner } from "./core/profile-lock.js";
|
|
3
4
|
import { defaultLogger } from "./core/logger.js";
|
|
4
5
|
import { getProvider, } from "./core/provider.js";
|
|
5
6
|
import { takeSnapshot } from "./core/snapshot.js";
|
|
@@ -39,6 +40,7 @@ export class ChatSession {
|
|
|
39
40
|
catch (err) {
|
|
40
41
|
// Don't leak the browser if open() throws.
|
|
41
42
|
await context.close().catch(() => undefined);
|
|
43
|
+
clearProfileOwner(userDataDir);
|
|
42
44
|
throw err;
|
|
43
45
|
}
|
|
44
46
|
return session;
|
|
@@ -185,6 +187,9 @@ export class ChatSession {
|
|
|
185
187
|
return;
|
|
186
188
|
this.closed = true;
|
|
187
189
|
await this.context.close().catch(() => undefined);
|
|
190
|
+
// Drop the owner sidecar so a later launch doesn't mistake a cleanly
|
|
191
|
+
// closed profile for a live chat (see core/profile-lock.ts).
|
|
192
|
+
clearProfileOwner(this.userDataDir);
|
|
188
193
|
}
|
|
189
194
|
/** Enables `await using session = …` (TC39 explicit resource management). */
|
|
190
195
|
async [Symbol.asyncDispose]() {
|
package/dist/session.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAsB,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAe,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EACL,WAAW,GAGZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAqB,MAAM,oBAAoB,CAAC;AA0CrE;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,WAAW;
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|