@gobing-ai/knowledge-kit 0.1.10 → 0.1.11
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/.claude-plugin/marketplace.json +1 -1
- package/dist/index.js +128 -25
- package/package.json +1 -1
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/scripts/daily-scheduled-run.ts +298 -0
- package/plugins/kk/scripts/daily-stages.ts +1057 -108
- package/plugins/kk/scripts/kk-workflow-stages.ts +76 -10
- package/plugins/kk/scripts/safety-artifact-check.ts +235 -0
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +168 -121
- package/plugins/kk/workflows/kk-daily-safety.yaml +129 -50
- package/plugins/publishings/bilibili-pub/dist/index.js +2 -1
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/cnblogs-pub/dist/index.js +2 -1
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/csdn-pub/dist/index.js +2 -1
- package/plugins/publishings/csdn-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/infoq-pub/dist/index.js +2 -1
- package/plugins/publishings/infoq-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/jike-pub/dist/index.js +2 -1
- package/plugins/publishings/jike-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/juejin-pub/dist/index.js +2 -1
- package/plugins/publishings/juejin-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/podcast-pub/dist/index.js +46 -8
- package/plugins/publishings/podcast-pub/src/index.ts +62 -5
- package/plugins/publishings/shipinhao-pub/dist/index.js +2 -1
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/sspai-pub/dist/index.js +2 -1
- package/plugins/publishings/sspai-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/substack-pub/dist/index.js +2 -1
- package/plugins/publishings/substack-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/surfdash-pub/dist/index.js +460 -52
- package/plugins/publishings/surfdash-pub/src/digest-check.ts +85 -19
- package/plugins/publishings/surfdash-pub/src/index.ts +589 -64
- package/plugins/publishings/wechatmp-pub/dist/index.js +933 -98
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +60 -3
- package/plugins/publishings/wechatmp-pub/src/flow.ts +1125 -85
- package/plugins/publishings/wechatmp-pub/src/index.ts +112 -30
- package/plugins/publishings/wechatmp-pub/src/page.ts +105 -0
- package/plugins/publishings/weibo-pub/dist/index.js +2 -1
- package/plugins/publishings/weibo-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/x-pub/dist/index.js +2 -1
- package/plugins/publishings/x-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/xhs-pub/dist/index.js +2 -1
- package/plugins/publishings/xhs-pub/dist/profile-check.js +2 -1
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +2 -1
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +2 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { parseArgs } from 'node:util';
|
|
2
3
|
import { type Content, ContentSchema, type Result, ResultSchema } from '@gobing-ai/kk-core';
|
|
3
4
|
import {
|
|
@@ -6,7 +7,7 @@ import {
|
|
|
6
7
|
type PublishTransportPayload,
|
|
7
8
|
resolveBrowserProfileDir,
|
|
8
9
|
} from '@gobing-ai/publish-harness';
|
|
9
|
-
import { kkBrowserLauncher, waitUntil } from '@gobing-ai/publish-harness/browser';
|
|
10
|
+
import { chmod, createExclusiveFile, kkBrowserLauncher, waitUntil } from '@gobing-ai/publish-harness/browser';
|
|
10
11
|
import { BrowserProfileMissingError, openPersistentBrowser } from '@gobing-ai/ts-browser-automation';
|
|
11
12
|
import { createNodeFileSystem } from '@gobing-ai/ts-runtime';
|
|
12
13
|
import { echoError } from '@gobing-ai/ts-utils';
|
|
@@ -21,7 +22,14 @@ import {
|
|
|
21
22
|
validateModeInput,
|
|
22
23
|
WECHATMP_OPERATIONS,
|
|
23
24
|
} from './modes';
|
|
24
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
type OpenConsole,
|
|
27
|
+
type OpenedConsole,
|
|
28
|
+
POLL_MS,
|
|
29
|
+
STEP_TIMEOUT_MS,
|
|
30
|
+
sanitizeSessionEvidence,
|
|
31
|
+
wrapPlaywrightContext,
|
|
32
|
+
} from './page';
|
|
25
33
|
|
|
26
34
|
/**
|
|
27
35
|
* The wechatmp publish CHANNEL (ADR-029, ADR-026): one plugin, four mode `operations`.
|
|
@@ -49,7 +57,7 @@ const DRAFT_SIGNAL_TIMEOUT_MS = 15_000;
|
|
|
49
57
|
const SUBMIT_ATTEMPTS = 2;
|
|
50
58
|
|
|
51
59
|
function fail(error: string): Result {
|
|
52
|
-
return ResultSchema.parse({ ok: false, target: TARGET, error });
|
|
60
|
+
return ResultSchema.parse({ ok: false, target: TARGET, error: sanitizeSessionEvidence(error) });
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
/** Console home readiness: an authenticated route carries the session token (discovery §1/§9-W9). */
|
|
@@ -74,6 +82,35 @@ export function storageStatePath(profileDir: string): string {
|
|
|
74
82
|
return `${profileDir}/storage-state.json`;
|
|
75
83
|
}
|
|
76
84
|
|
|
85
|
+
/**
|
|
86
|
+
* Persist a positively authenticated browser state without exposing a partially-written state
|
|
87
|
+
* file to the next launch. The temporary file stays beside the target so the final rename is
|
|
88
|
+
* atomic on the profile filesystem; cleanup is deliberately best-effort and never masks the
|
|
89
|
+
* storageState/rename error.
|
|
90
|
+
*/
|
|
91
|
+
export async function persistWechatSessionState(
|
|
92
|
+
context: { storageState(options: { path: string }): Promise<unknown> },
|
|
93
|
+
profileDir: string,
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
const target = storageStatePath(profileDir);
|
|
96
|
+
const temporary = `${target}.${process.pid}.${randomUUID()}.tmp`;
|
|
97
|
+
const fs = createNodeFileSystem();
|
|
98
|
+
let reserved = false;
|
|
99
|
+
try {
|
|
100
|
+
createExclusiveFile(temporary);
|
|
101
|
+
reserved = true;
|
|
102
|
+
await context.storageState({ path: temporary });
|
|
103
|
+
chmod(temporary, 0o600);
|
|
104
|
+
await fs.rename(temporary, target);
|
|
105
|
+
} finally {
|
|
106
|
+
if (reserved) {
|
|
107
|
+
await Promise.resolve()
|
|
108
|
+
.then(() => fs.deleteFile(temporary))
|
|
109
|
+
.catch(() => undefined);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
77
114
|
/** Headless session preflight: throws (incl. BrowserProfileMissingError) when the profile cannot drive the console.
|
|
78
115
|
* 0216: `headless: false` probes headed only and `timeoutMs` overrides the ready deadline. */
|
|
79
116
|
export async function checkWechatSession(
|
|
@@ -110,6 +147,8 @@ export async function openWechatLogin(opts: { profileDir: string; timeoutMs?: nu
|
|
|
110
147
|
headless: false,
|
|
111
148
|
launcher: kkBrowserLauncher,
|
|
112
149
|
});
|
|
150
|
+
let failed = false;
|
|
151
|
+
let failure: unknown;
|
|
113
152
|
try {
|
|
114
153
|
const page = context.pages()[0] ?? (await context.newPage());
|
|
115
154
|
await page.goto(CONSOLE_URL);
|
|
@@ -120,10 +159,29 @@ export async function openWechatLogin(opts: { profileDir: string; timeoutMs?: nu
|
|
|
120
159
|
);
|
|
121
160
|
if (!ready) throw new Error(`QR scan not completed within ${timeoutMs / 1000}s`);
|
|
122
161
|
await page.waitForTimeout(10_000); // settle: let the console finish its post-auth Set-Cookies
|
|
123
|
-
|
|
124
|
-
|
|
162
|
+
try {
|
|
163
|
+
await persistWechatSessionState(context, opts.profileDir);
|
|
164
|
+
} catch {
|
|
165
|
+
// Storage-state errors can contain cookie values. Keep the profile-check surface
|
|
166
|
+
// actionable without relaying an exception that may include session material.
|
|
167
|
+
throw new Error('wechatmp authenticated session snapshot failed');
|
|
168
|
+
}
|
|
169
|
+
} catch (error: unknown) {
|
|
170
|
+
failed = true;
|
|
171
|
+
failure = error;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
125
174
|
await context.close();
|
|
175
|
+
} catch {
|
|
176
|
+
// A successful atomic snapshot is already durable; a close failure must not turn it into
|
|
177
|
+
// a retryable login. Keep the diagnostic generic because browser errors may contain session
|
|
178
|
+
// material, and never replace an authentication or snapshot failure with shutdown noise.
|
|
179
|
+
if (!failed)
|
|
180
|
+
echoError(
|
|
181
|
+
'wechatmp browser context close failed after authenticated session snapshot; saved state preserved',
|
|
182
|
+
);
|
|
126
183
|
}
|
|
184
|
+
if (failed) throw failure;
|
|
127
185
|
}
|
|
128
186
|
|
|
129
187
|
/**
|
|
@@ -201,7 +259,10 @@ async function openWithState(
|
|
|
201
259
|
*/
|
|
202
260
|
async function defaultOpenConsole(profileDir: string): Promise<OpenedConsole> {
|
|
203
261
|
const { page, context } = await openWithState(profileDir, true);
|
|
204
|
-
return
|
|
262
|
+
return {
|
|
263
|
+
...wrapPlaywrightContext(context, page),
|
|
264
|
+
persistSession: () => persistWechatSessionState(context, profileDir),
|
|
265
|
+
};
|
|
205
266
|
}
|
|
206
267
|
|
|
207
268
|
type BrowserDriverName = 'script' | 'agent';
|
|
@@ -291,42 +352,63 @@ export class WechatmpBrowserTransport implements PublishTransport {
|
|
|
291
352
|
} catch (error: unknown) {
|
|
292
353
|
return fail(error instanceof Error ? error.message : String(error));
|
|
293
354
|
}
|
|
355
|
+
let result: Result;
|
|
294
356
|
try {
|
|
295
357
|
const ready = await waitUntil(
|
|
296
358
|
() => Promise.resolve(isConsoleReady(opened.page)),
|
|
297
359
|
this.consoleReadyTimeoutMs,
|
|
298
360
|
);
|
|
299
361
|
if (!ready) {
|
|
300
|
-
|
|
362
|
+
result = fail(
|
|
301
363
|
`no authenticated ${TARGET} console within ${this.consoleReadyTimeoutMs}ms — the preflight passed but the console did not report a session route (profile ${profileDir})`,
|
|
302
364
|
);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
365
|
+
} else {
|
|
366
|
+
// The 草稿箱 baseline is read before the editor opens: MP auto-saves continuously, so a
|
|
367
|
+
// row that already carried a stamp says nothing about this run's save (discovery §5.1).
|
|
368
|
+
const title = typeof content.title === 'string' ? content.title.trim() : '';
|
|
369
|
+
const draftBaseline =
|
|
370
|
+
publishStatus === 'draft' ? await readDraftBaseline(opened.page, title) : { stamp: null };
|
|
309
371
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
372
|
+
result = await runMode(validation.input, {
|
|
373
|
+
entry: opened.page,
|
|
374
|
+
pages: opened.pages,
|
|
375
|
+
newPage: opened.newPage,
|
|
376
|
+
content,
|
|
377
|
+
publishStatus,
|
|
378
|
+
profileDir,
|
|
379
|
+
driver: this.driver,
|
|
380
|
+
stepTimeoutMs: this.stepTimeoutMs,
|
|
381
|
+
pollMs: this.pollMs,
|
|
382
|
+
submitSettleMs: this.submitSettleMs,
|
|
383
|
+
draftTimeoutMs: this.draftTimeoutMs,
|
|
384
|
+
submitAttempts: this.submitAttempts,
|
|
385
|
+
draftBaseline,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
325
388
|
} catch (error: unknown) {
|
|
326
|
-
|
|
389
|
+
result = fail(error instanceof Error ? error.message : String(error));
|
|
327
390
|
} finally {
|
|
328
|
-
|
|
391
|
+
if (opened.persistSession !== undefined) {
|
|
392
|
+
try {
|
|
393
|
+
// A positive authenticated route is the only evidence that rotating state is
|
|
394
|
+
// safe to persist. Read-only preflight uses openWithState directly and never
|
|
395
|
+
// receives this callback.
|
|
396
|
+
if (isConsoleReady(opened.page)) await opened.persistSession();
|
|
397
|
+
} catch {
|
|
398
|
+
// Storage-state errors can contain cookie values; the publication result is
|
|
399
|
+
// already determined and must survive this best-effort session refresh.
|
|
400
|
+
echoError('wechatmp-pub: authenticated session snapshot failed; publication result preserved');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
try {
|
|
404
|
+
await opened.close();
|
|
405
|
+
} catch {
|
|
406
|
+
// Context shutdown is not publication evidence. Never turn an already determined
|
|
407
|
+
// Result into a retryable throw, and never relay browser diagnostics verbatim.
|
|
408
|
+
echoError('wechatmp-pub: browser context close failed; publication result preserved');
|
|
409
|
+
}
|
|
329
410
|
}
|
|
411
|
+
return result;
|
|
330
412
|
}
|
|
331
413
|
}
|
|
332
414
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { trySelectors } from '@gobing-ai/publish-harness';
|
|
2
2
|
import { waitUntil } from '@gobing-ai/publish-harness/browser';
|
|
3
|
+
import type { Page, Request } from 'playwright';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* The console's page seam (ADR-029) and the probes every wechatmp operation shares.
|
|
@@ -17,6 +18,11 @@ import { waitUntil } from '@gobing-ai/publish-harness/browser';
|
|
|
17
18
|
export const POLL_MS = 500;
|
|
18
19
|
export const STEP_TIMEOUT_MS = 30_000;
|
|
19
20
|
|
|
21
|
+
/** Browser evidence may retain navigation context, but never its session query credentials. */
|
|
22
|
+
export function sanitizeSessionEvidence(value: string): string {
|
|
23
|
+
return value.replace(/([?&](?:token|ticket|authkey)=)[^&\s"'<>)]*/gi, '$1[REDACTED]');
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
/** The playwright-shaped locator surface the flows and the shared helpers read. */
|
|
21
27
|
export interface WechatLocator {
|
|
22
28
|
count(): Promise<number>;
|
|
@@ -36,6 +42,8 @@ export interface WechatLocator {
|
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
export interface WechatPage {
|
|
45
|
+
/** Click the native article save and await its successful, fully received acknowledgement. */
|
|
46
|
+
saveDraftAndWait?(selector: string, timeoutMs: number): Promise<void>;
|
|
39
47
|
goto(url: string, options?: { timeout?: number }): Promise<void>;
|
|
40
48
|
locator(selector: string): { first(): WechatLocator; count(): Promise<number> };
|
|
41
49
|
setInputFiles(selector: string, paths: readonly string[] | string): Promise<void>;
|
|
@@ -63,6 +71,8 @@ export interface OpenedConsole {
|
|
|
63
71
|
pages(): WechatPage[];
|
|
64
72
|
/** Opens an extra tab; the token-derived editor fallback uses it so the home stays readable. */
|
|
65
73
|
newPage(): Promise<WechatPage>;
|
|
74
|
+
/** Best-effort authenticated state snapshot owned by the launcher; absent for read-only seams. */
|
|
75
|
+
persistSession?: () => Promise<void>;
|
|
66
76
|
close(): Promise<void>;
|
|
67
77
|
}
|
|
68
78
|
|
|
@@ -213,9 +223,104 @@ interface RawFrame {
|
|
|
213
223
|
locator(selector: string): { count(): Promise<number> };
|
|
214
224
|
}
|
|
215
225
|
|
|
226
|
+
/** Match a new full-article save, excluding reads and other operations at the shared endpoint. */
|
|
227
|
+
function isArticleSave(request: Request, origin: string): boolean {
|
|
228
|
+
if (request.method() !== 'POST') return false;
|
|
229
|
+
const url = new URL(request.url());
|
|
230
|
+
if (url.origin !== origin || url.pathname !== '/cgi-bin/operate_appmsg') return false;
|
|
231
|
+
if (!['create', 'update', 'edit'].includes(url.searchParams.get('sub') ?? '')) return false;
|
|
232
|
+
const data = request.postData() ?? '';
|
|
233
|
+
const form = new URLSearchParams(data);
|
|
234
|
+
return (
|
|
235
|
+
(form.has('content0') && form.has('title0')) ||
|
|
236
|
+
(data.includes('name="content0"') && data.includes('name="title0"'))
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function saveResponseSucceeded(value: unknown): boolean {
|
|
241
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
242
|
+
const body = value as Record<string, unknown>;
|
|
243
|
+
const base =
|
|
244
|
+
body.base_resp !== null && typeof body.base_resp === 'object'
|
|
245
|
+
? (body.base_resp as Record<string, unknown>)
|
|
246
|
+
: {};
|
|
247
|
+
const codes = [body.ret, body.errcode, base.ret].filter((code) => code !== undefined);
|
|
248
|
+
// The live editor returns top-level ret as "0" alongside numeric base_resp.ret.
|
|
249
|
+
if (codes.some((code) => code !== 0 && code !== '0')) return false;
|
|
250
|
+
if (codes.length > 0) return true;
|
|
251
|
+
const info =
|
|
252
|
+
body.appMsgInfo !== null && typeof body.appMsgInfo === 'object'
|
|
253
|
+
? (body.appMsgInfo as Record<string, unknown>)
|
|
254
|
+
: body;
|
|
255
|
+
return typeof info.appMsgId === 'string' || typeof info.appMsgId === 'number'
|
|
256
|
+
? /^\d{1,12}$/.test(String(info.appMsgId))
|
|
257
|
+
: false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** Observe the native request before clicking; neither response headers nor a URL change is completion. */
|
|
261
|
+
async function saveNativeDraft(raw: Page, selector: string, timeoutMs: number): Promise<void> {
|
|
262
|
+
const origin = new URL(raw.url()).origin;
|
|
263
|
+
const marker = `__kkNativeSave_${crypto.randomUUID()}`;
|
|
264
|
+
const button = raw.locator(selector).first();
|
|
265
|
+
await button.evaluate((element, key) => {
|
|
266
|
+
const state = { clickedAt: 0 };
|
|
267
|
+
const handler = () => {
|
|
268
|
+
state.clickedAt = Date.now();
|
|
269
|
+
};
|
|
270
|
+
(globalThis as unknown as Record<string, unknown>)[key] = { state, element, handler };
|
|
271
|
+
element.addEventListener('click', handler, { capture: true, once: true });
|
|
272
|
+
}, marker);
|
|
273
|
+
let deadline: ReturnType<typeof setTimeout> | undefined;
|
|
274
|
+
const responseComplete = raw
|
|
275
|
+
.waitForRequest(
|
|
276
|
+
async (request) => {
|
|
277
|
+
if (!isArticleSave(request, origin)) return false;
|
|
278
|
+
const clickedAt = await raw
|
|
279
|
+
.evaluate(`globalThis[${JSON.stringify(marker)}]?.state?.clickedAt ?? 0`)
|
|
280
|
+
.catch(() => 0);
|
|
281
|
+
if (typeof clickedAt !== 'number' || clickedAt <= 0) return false;
|
|
282
|
+
// Playwright populates request timing when response headers arrive; before that
|
|
283
|
+
// the live Chrome request reports startTime=0. Keep the click stamp across navigation.
|
|
284
|
+
if (!(await request.response())) return false;
|
|
285
|
+
return request.timing().startTime >= clickedAt;
|
|
286
|
+
},
|
|
287
|
+
{ timeout: timeoutMs },
|
|
288
|
+
)
|
|
289
|
+
.then(async (request) => {
|
|
290
|
+
const response = await request.response();
|
|
291
|
+
if (response === null || response.status() < 200 || response.status() >= 300)
|
|
292
|
+
throw new Error('HTTP refusal');
|
|
293
|
+
if (await response.finished()) throw new Error('Incomplete response');
|
|
294
|
+
if (!saveResponseSucceeded(await response.json())) throw new Error('Save refused');
|
|
295
|
+
});
|
|
296
|
+
try {
|
|
297
|
+
await Promise.race([
|
|
298
|
+
Promise.all([responseComplete, button.click({ timeout: timeoutMs })]),
|
|
299
|
+
new Promise<never>((_resolve, reject) => {
|
|
300
|
+
deadline = setTimeout(() => reject(new Error('Save timeout')), timeoutMs);
|
|
301
|
+
}),
|
|
302
|
+
]);
|
|
303
|
+
} catch {
|
|
304
|
+
// Playwright errors and server bodies may contain session URLs; retain no vendor payload.
|
|
305
|
+
throw new Error('Native article save was not acknowledged successfully before the deadline');
|
|
306
|
+
} finally {
|
|
307
|
+
if (deadline !== undefined) clearTimeout(deadline);
|
|
308
|
+
await raw
|
|
309
|
+
.evaluate(`(() => {
|
|
310
|
+
const key = ${JSON.stringify(marker)};
|
|
311
|
+
const records = globalThis;
|
|
312
|
+
const value = records[key];
|
|
313
|
+
if (value?.element && value.handler) value.element.removeEventListener('click', value.handler, true);
|
|
314
|
+
delete records[key];
|
|
315
|
+
})()`)
|
|
316
|
+
.catch(() => undefined);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
216
320
|
export function wrapPlaywrightPage(raw: unknown): WechatPage {
|
|
217
321
|
const pw = raw as PlaywrightLike;
|
|
218
322
|
return {
|
|
323
|
+
saveDraftAndWait: (selector, timeoutMs) => saveNativeDraft(raw as Page, selector, timeoutMs),
|
|
219
324
|
goto: (url, options) => pw.goto(url, { waitUntil: 'domcontentloaded', ...options }).then(() => undefined),
|
|
220
325
|
locator: (selector) => ({
|
|
221
326
|
count: () => pw.locator(selector).count(),
|
|
@@ -20458,9 +20458,11 @@ import { isAbsolute, join as join4, relative, resolve as resolve4, sep } from "p
|
|
|
20458
20458
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20459
20459
|
import {
|
|
20460
20460
|
chmodSync,
|
|
20461
|
+
closeSync,
|
|
20461
20462
|
copyFileSync,
|
|
20462
20463
|
lstatSync,
|
|
20463
20464
|
mkdirSync as mkdirSync2,
|
|
20465
|
+
openSync,
|
|
20464
20466
|
readdirSync as readdirSync2,
|
|
20465
20467
|
realpathSync as realpathSync2,
|
|
20466
20468
|
rmdirSync
|
|
@@ -20705,7 +20707,6 @@ class BotError extends Error {
|
|
|
20705
20707
|
this.code = code;
|
|
20706
20708
|
}
|
|
20707
20709
|
}
|
|
20708
|
-
|
|
20709
20710
|
// ../../packages/publish-harness/src/profile-dir.ts
|
|
20710
20711
|
import { mkdir as mkdir2, stat } from "fs/promises";
|
|
20711
20712
|
async function ensureProfileDir2(profileDir, headless) {
|
|
@@ -20119,9 +20119,11 @@ import { isAbsolute, join as join3, relative, resolve as resolve3, sep } from "p
|
|
|
20119
20119
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20120
20120
|
import {
|
|
20121
20121
|
chmodSync,
|
|
20122
|
+
closeSync,
|
|
20122
20123
|
copyFileSync,
|
|
20123
20124
|
lstatSync,
|
|
20124
20125
|
mkdirSync as mkdirSync2,
|
|
20126
|
+
openSync,
|
|
20125
20127
|
readdirSync as readdirSync2,
|
|
20126
20128
|
realpathSync as realpathSync2,
|
|
20127
20129
|
rmdirSync
|
|
@@ -20373,7 +20375,6 @@ class BotError extends Error {
|
|
|
20373
20375
|
this.code = code;
|
|
20374
20376
|
}
|
|
20375
20377
|
}
|
|
20376
|
-
|
|
20377
20378
|
// ../../packages/publish-harness/src/index.ts
|
|
20378
20379
|
import { homedir as homedir4 } from "os";
|
|
20379
20380
|
import { join as join4, resolve as resolve4 } from "path";
|
|
@@ -20483,9 +20483,11 @@ import { isAbsolute, join as join4, relative, resolve as resolve4, sep } from "p
|
|
|
20483
20483
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20484
20484
|
import {
|
|
20485
20485
|
chmodSync,
|
|
20486
|
+
closeSync,
|
|
20486
20487
|
copyFileSync,
|
|
20487
20488
|
lstatSync,
|
|
20488
20489
|
mkdirSync as mkdirSync2,
|
|
20490
|
+
openSync,
|
|
20489
20491
|
readdirSync as readdirSync2,
|
|
20490
20492
|
realpathSync as realpathSync2,
|
|
20491
20493
|
rmdirSync
|
|
@@ -20730,7 +20732,6 @@ class BotError extends Error {
|
|
|
20730
20732
|
this.code = code;
|
|
20731
20733
|
}
|
|
20732
20734
|
}
|
|
20733
|
-
|
|
20734
20735
|
// ../../packages/publish-harness/src/profile-dir.ts
|
|
20735
20736
|
import { mkdir as mkdir2, stat } from "fs/promises";
|
|
20736
20737
|
async function ensureProfileDir2(profileDir, headless) {
|
|
@@ -20119,9 +20119,11 @@ import { isAbsolute, join as join3, relative, resolve as resolve3, sep } from "p
|
|
|
20119
20119
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20120
20120
|
import {
|
|
20121
20121
|
chmodSync,
|
|
20122
|
+
closeSync,
|
|
20122
20123
|
copyFileSync,
|
|
20123
20124
|
lstatSync,
|
|
20124
20125
|
mkdirSync as mkdirSync2,
|
|
20126
|
+
openSync,
|
|
20125
20127
|
readdirSync as readdirSync2,
|
|
20126
20128
|
realpathSync as realpathSync2,
|
|
20127
20129
|
rmdirSync
|
|
@@ -20373,7 +20375,6 @@ class BotError extends Error {
|
|
|
20373
20375
|
this.code = code;
|
|
20374
20376
|
}
|
|
20375
20377
|
}
|
|
20376
|
-
|
|
20377
20378
|
// ../../packages/publish-harness/src/index.ts
|
|
20378
20379
|
import { homedir as homedir4 } from "os";
|
|
20379
20380
|
import { join as join4, resolve as resolve4 } from "path";
|
|
@@ -20458,9 +20458,11 @@ import { isAbsolute, join as join4, relative, resolve as resolve4, sep } from "p
|
|
|
20458
20458
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20459
20459
|
import {
|
|
20460
20460
|
chmodSync,
|
|
20461
|
+
closeSync,
|
|
20461
20462
|
copyFileSync,
|
|
20462
20463
|
lstatSync,
|
|
20463
20464
|
mkdirSync as mkdirSync2,
|
|
20465
|
+
openSync,
|
|
20464
20466
|
readdirSync as readdirSync2,
|
|
20465
20467
|
realpathSync as realpathSync2,
|
|
20466
20468
|
rmdirSync
|
|
@@ -20705,7 +20707,6 @@ class BotError extends Error {
|
|
|
20705
20707
|
this.code = code;
|
|
20706
20708
|
}
|
|
20707
20709
|
}
|
|
20708
|
-
|
|
20709
20710
|
// ../../packages/publish-harness/src/profile-dir.ts
|
|
20710
20711
|
import { mkdir as mkdir2, stat } from "fs/promises";
|
|
20711
20712
|
async function ensureProfileDir2(profileDir, headless) {
|
|
@@ -20127,9 +20127,11 @@ import { isAbsolute, join as join3, relative, resolve as resolve3, sep } from "p
|
|
|
20127
20127
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20128
20128
|
import {
|
|
20129
20129
|
chmodSync,
|
|
20130
|
+
closeSync,
|
|
20130
20131
|
copyFileSync,
|
|
20131
20132
|
lstatSync,
|
|
20132
20133
|
mkdirSync as mkdirSync2,
|
|
20134
|
+
openSync,
|
|
20133
20135
|
readdirSync as readdirSync2,
|
|
20134
20136
|
realpathSync as realpathSync2,
|
|
20135
20137
|
rmdirSync
|
|
@@ -20374,7 +20376,6 @@ class BotError extends Error {
|
|
|
20374
20376
|
this.code = code;
|
|
20375
20377
|
}
|
|
20376
20378
|
}
|
|
20377
|
-
|
|
20378
20379
|
// ../../packages/publish-harness/src/index.ts
|
|
20379
20380
|
import { homedir as homedir4 } from "os";
|
|
20380
20381
|
import { join as join4, resolve as resolve4 } from "path";
|
|
@@ -20464,9 +20464,11 @@ import { isAbsolute, join as join4, relative, resolve as resolve4, sep } from "p
|
|
|
20464
20464
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
20465
20465
|
import {
|
|
20466
20466
|
chmodSync,
|
|
20467
|
+
closeSync,
|
|
20467
20468
|
copyFileSync,
|
|
20468
20469
|
lstatSync,
|
|
20469
20470
|
mkdirSync as mkdirSync2,
|
|
20471
|
+
openSync,
|
|
20470
20472
|
readdirSync as readdirSync2,
|
|
20471
20473
|
realpathSync as realpathSync2,
|
|
20472
20474
|
rmdirSync
|
|
@@ -20711,7 +20713,6 @@ class BotError extends Error {
|
|
|
20711
20713
|
this.code = code;
|
|
20712
20714
|
}
|
|
20713
20715
|
}
|
|
20714
|
-
|
|
20715
20716
|
// ../../packages/publish-harness/src/profile-dir.ts
|
|
20716
20717
|
import { mkdir as mkdir2, stat } from "fs/promises";
|
|
20717
20718
|
async function ensureProfileDir2(profileDir, headless) {
|
|
@@ -19847,9 +19847,11 @@ import { isAbsolute, join as join3, relative, resolve as resolve3, sep } from "p
|
|
|
19847
19847
|
// ../../packages/publish-harness/src/bot-fs.ts
|
|
19848
19848
|
import {
|
|
19849
19849
|
chmodSync,
|
|
19850
|
+
closeSync,
|
|
19850
19851
|
copyFileSync,
|
|
19851
19852
|
lstatSync,
|
|
19852
19853
|
mkdirSync as mkdirSync2,
|
|
19854
|
+
openSync,
|
|
19853
19855
|
readdirSync as readdirSync2,
|
|
19854
19856
|
realpathSync as realpathSync2,
|
|
19855
19857
|
rmdirSync
|
|
@@ -20101,7 +20103,6 @@ class BotError extends Error {
|
|
|
20101
20103
|
this.code = code;
|
|
20102
20104
|
}
|
|
20103
20105
|
}
|
|
20104
|
-
|
|
20105
20106
|
// ../../packages/publish-harness/src/index.ts
|
|
20106
20107
|
import { homedir as homedir4 } from "os";
|
|
20107
20108
|
import { join as join4, resolve as resolve4 } from "path";
|