@nextclaw/x-harness 0.2.60 → 0.2.62
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/SOURCE.md +2 -2
- package/dist/browser-dom-navigation.d.ts +1 -1
- package/dist/browser-dom-navigation.js +7 -11
- package/dist/growth-policy.js +4 -0
- package/dist/platform-rules.d.ts +1 -0
- package/dist/platform-rules.js +1 -0
- package/dist/reply-author-policy.d.ts +3 -0
- package/dist/reply-author-policy.js +33 -0
- package/dist/reply-root-policy.js +1 -1
- package/package.json +3 -26
package/SOURCE.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Corresponding source
|
|
2
2
|
|
|
3
|
-
Version 0.2.
|
|
3
|
+
Version 0.2.62, commit 4c5b571638ec2a9426a4e3e1e80c85af581ecff6.
|
|
4
4
|
|
|
5
|
-
Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/
|
|
5
|
+
Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/4c5b571638ec2a9426a4e3e1e80c85af581ecff6
|
|
6
6
|
|
|
7
7
|
Clone this revision, run npm ci, npm run bootstrap and npm run release:build.
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ export declare class DOMNavigation {
|
|
|
14
14
|
private handleWaitForFolder;
|
|
15
15
|
private handleWaitForPosts;
|
|
16
16
|
private handleOpenObserved;
|
|
17
|
-
private
|
|
17
|
+
private handleWaitTargetContent;
|
|
18
18
|
private handleRefreshPerson;
|
|
19
19
|
private handleRefreshPosts;
|
|
20
20
|
}
|
|
@@ -211,9 +211,7 @@ export class DOMNavigation {
|
|
|
211
211
|
}
|
|
212
212
|
if (command.view === "person") {
|
|
213
213
|
// Profile readiness belongs to profile content; self profiles have no Follow button.
|
|
214
|
-
await this.#tab.playwright
|
|
215
|
-
.locator('[data-testid="UserName"]')
|
|
216
|
-
.waitFor({ state: "visible", timeoutMs: 5000 });
|
|
214
|
+
await this.handleWaitTargetContent(this.#tab.playwright.locator('[data-testid="UserName"]'), command.url);
|
|
217
215
|
}
|
|
218
216
|
else if (command.view === "people") {
|
|
219
217
|
await this.#tab.playwright
|
|
@@ -235,16 +233,16 @@ export class DOMNavigation {
|
|
|
235
233
|
has: this.#tab.playwright.locator(`a[href=${JSON.stringify(path)}]`),
|
|
236
234
|
})
|
|
237
235
|
: articles;
|
|
238
|
-
await this.
|
|
236
|
+
await this.handleWaitTargetContent(detail.first(), command.url);
|
|
239
237
|
}
|
|
240
238
|
return;
|
|
241
239
|
}
|
|
242
|
-
async
|
|
240
|
+
async handleWaitTargetContent(detail, url) {
|
|
243
241
|
const deadline = Date.now() + 15000;
|
|
244
242
|
for (let attempt = 0; attempt < 4; attempt++) {
|
|
245
243
|
const remaining = deadline - Date.now();
|
|
246
244
|
if (remaining <= 0)
|
|
247
|
-
throw Error("
|
|
245
|
+
throw Error("target-content-readiness-timeout");
|
|
248
246
|
try {
|
|
249
247
|
await detail.waitFor({
|
|
250
248
|
state: "visible",
|
|
@@ -286,11 +284,9 @@ export class DOMNavigation {
|
|
|
286
284
|
idleTimedOut = true;
|
|
287
285
|
}
|
|
288
286
|
await this.#tab.reload();
|
|
289
|
-
await this.#tab.playwright
|
|
290
|
-
.getByRole("button", {
|
|
287
|
+
await this.handleWaitTargetContent(this.#tab.playwright.getByRole("button", {
|
|
291
288
|
name: new RegExp(`^(?:正在关注|取消关注|关注|回关) @${command.handle}$`, "i"),
|
|
292
|
-
})
|
|
293
|
-
.waitFor({ state: "visible", timeoutMs: 5000 });
|
|
289
|
+
}), command.url);
|
|
294
290
|
if (idleTimedOut)
|
|
295
291
|
this.#session.refreshNotice =
|
|
296
292
|
"networkidle超时,已沿真实reload与目标关系控件恢复核验";
|
|
@@ -306,7 +302,7 @@ export class DOMNavigation {
|
|
|
306
302
|
// Native observation settles the real loading transition when the tab exposes it.
|
|
307
303
|
if (typeof this.#tab.getAXState === "function")
|
|
308
304
|
await this.#tab.getAXState({ emit: false });
|
|
309
|
-
await this.
|
|
305
|
+
await this.handleWaitTargetContent(this.#tab.playwright.getByRole("article").first(), command.url);
|
|
310
306
|
return;
|
|
311
307
|
}
|
|
312
308
|
}
|
package/dist/growth-policy.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DraftSchedule } from "./draft-schedule.js";
|
|
2
2
|
import { xURL } from "./platform-rules.js";
|
|
3
|
+
import { replyAuthorReason } from "./reply-author-policy.js";
|
|
3
4
|
import { replyRootAgeReason } from "./reply-root-policy.js";
|
|
4
5
|
import { kinds, followWindows, operations, same } from "./growth-constants.js";
|
|
5
6
|
import { followObservationAuthorized } from "./follow-observation-policy.js";
|
|
@@ -131,6 +132,9 @@ export class GrowthPolicy {
|
|
|
131
132
|
if (!independentExecution && !this.handleScope(state).includes(action.kind))
|
|
132
133
|
return "kind-outside-round-scope";
|
|
133
134
|
if (action.kind === "reply") {
|
|
135
|
+
const authorReason = replyAuthorReason(state, action, this.#evidenceExists);
|
|
136
|
+
if (authorReason)
|
|
137
|
+
return authorReason;
|
|
134
138
|
const reason = replyRootAgeReason(action, executor?.replyMaxRootAgeHours, this.#clock());
|
|
135
139
|
if (reason)
|
|
136
140
|
return reason;
|
package/dist/platform-rules.d.ts
CHANGED
package/dist/platform-rules.js
CHANGED
|
@@ -30,6 +30,7 @@ export const source = (post, page) => ({
|
|
|
30
30
|
datetime: post.datetime,
|
|
31
31
|
url: post.primary ? new URL(post.primary, page).href : null,
|
|
32
32
|
body: post.body,
|
|
33
|
+
replyToId: post.replyToId,
|
|
33
34
|
images: post.images ?? [],
|
|
34
35
|
media: post.media ?? [],
|
|
35
36
|
links: post.links ?? [],
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { BoundaryRecord } from "./boundary.js";
|
|
2
|
+
/** Account policy counts distinct original actions, including unresolved submissions. */
|
|
3
|
+
export declare function replyAuthorReason(state: BoundaryRecord, action: BoundaryRecord, evidenceExists: (path: string) => boolean): string | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Account policy counts distinct original actions, including unresolved submissions. */
|
|
2
|
+
export function replyAuthorReason(state, action, evidenceExists) {
|
|
3
|
+
const policy = state.replyAuthorPolicy;
|
|
4
|
+
if (action.kind !== "reply" ||
|
|
5
|
+
!policy ||
|
|
6
|
+
!(action.followGapContribution ||
|
|
7
|
+
["mutual", "casual"].includes(action.sourceCategory)))
|
|
8
|
+
return null;
|
|
9
|
+
if (policy.userAuthorized !== true ||
|
|
10
|
+
policy.max !== 2 ||
|
|
11
|
+
!evidenceExists(policy.evidenceRef ?? ""))
|
|
12
|
+
return "reply-author-policy-unconfirmed";
|
|
13
|
+
const handle = action.conversation?.recipientHandle
|
|
14
|
+
?.replace(/^@/, "")
|
|
15
|
+
.toLowerCase();
|
|
16
|
+
if (!/^[a-z0-9_]{1,15}$/.test(handle ?? ""))
|
|
17
|
+
return "reply-author-identity-required";
|
|
18
|
+
const history = state.replyAuthorHistory;
|
|
19
|
+
if (!history?.complete || !evidenceExists(history.evidenceRef ?? ""))
|
|
20
|
+
return "reply-author-history-unconfirmed";
|
|
21
|
+
const ids = new Set();
|
|
22
|
+
for (const a of [...(history.entries ?? []), ...(state.actions ?? [])]) {
|
|
23
|
+
const author = (a.author ?? a.conversation?.recipientHandle)
|
|
24
|
+
?.replace(/^@/, "")
|
|
25
|
+
.toLowerCase();
|
|
26
|
+
if (a.id !== action.id &&
|
|
27
|
+
a.kind === "reply" &&
|
|
28
|
+
author === handle &&
|
|
29
|
+
["intent", "unknown", "verified", "preexisting"].includes(a.status))
|
|
30
|
+
ids.add(a.id);
|
|
31
|
+
}
|
|
32
|
+
return ids.size >= policy.max ? "reply-author-limit" : null;
|
|
33
|
+
}
|
|
@@ -12,7 +12,7 @@ export function replyRootAgeReason(action, maximumHours, now) {
|
|
|
12
12
|
return "reply-root-identity-required";
|
|
13
13
|
try {
|
|
14
14
|
const observation = JSON.parse(readFileSync(action.evidenceRef, "utf8")).observation;
|
|
15
|
-
const nodes = ["posts", "context", "threadPosts"].flatMap((key) => Array.isArray(observation?.[key]) ? observation[key] : []);
|
|
15
|
+
const nodes = ["posts", "context", "threadPosts", "sources"].flatMap((key) => (Array.isArray(observation?.[key]) ? observation[key] : []));
|
|
16
16
|
const root = nodes.find((node) => node?.id === rootId);
|
|
17
17
|
if (!nodes.some((node) => node?.id === action.postId) || !root)
|
|
18
18
|
return "reply-root-publication-proof-required";
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/x-harness",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"private": false,
|
|
3
|
+
"version": "0.2.62",
|
|
5
4
|
"type": "module",
|
|
6
5
|
"description": "Typed X task harness with compact business results and explicit diagnostics.",
|
|
7
6
|
"main": "./dist/index.js",
|
|
@@ -25,29 +24,6 @@
|
|
|
25
24
|
"LICENSE",
|
|
26
25
|
"SOURCE.md"
|
|
27
26
|
],
|
|
28
|
-
"scripts": {
|
|
29
|
-
"build": "npm run maintainability && tsc -p tsconfig.json && node scripts/generate-observation.mjs",
|
|
30
|
-
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
31
|
-
"test": "node --test test/*.test.mjs",
|
|
32
|
-
"check": "npm run maintainability && npm run format:check && npm run typecheck && npm run typecheck:cli && npm run build && npm run typecheck:contracts && npm run test && node scripts/check-skill.mjs && node scripts/generate-observation.mjs --check",
|
|
33
|
-
"prepack": "node release/build.mjs --root-pack",
|
|
34
|
-
"typecheck:contracts": "tsc -p tsconfig.contracts.json",
|
|
35
|
-
"format:check": "prettier --check src test scripts release site",
|
|
36
|
-
"maintainability": "node scripts/check-maintainability.mjs",
|
|
37
|
-
"release:build": "node release/build.mjs",
|
|
38
|
-
"test:release": "node --test release/test/*.test.mjs",
|
|
39
|
-
"site:build": "node site/build.mjs",
|
|
40
|
-
"site:deploy": "node site/deploy.mjs",
|
|
41
|
-
"bootstrap": "node scripts/bootstrap.mjs",
|
|
42
|
-
"ai:check": "qingtian check --target .",
|
|
43
|
-
"typecheck:cli": "tsc -p release/tsconfig.json --noEmit"
|
|
44
|
-
},
|
|
45
|
-
"devDependencies": {
|
|
46
|
-
"@types/node": "22",
|
|
47
|
-
"typescript": "^5.9.3",
|
|
48
|
-
"prettier": "^3.9.9",
|
|
49
|
-
"@nextclaw/qingtian": "0.1.3"
|
|
50
|
-
},
|
|
51
27
|
"license": "AGPL-3.0-only",
|
|
52
28
|
"homepage": "https://x-harness.gemigo.app/",
|
|
53
29
|
"repository": {
|
|
@@ -65,5 +41,6 @@
|
|
|
65
41
|
},
|
|
66
42
|
"publishConfig": {
|
|
67
43
|
"access": "public"
|
|
68
|
-
}
|
|
44
|
+
},
|
|
45
|
+
"gitHead": "4c5b571638ec2a9426a4e3e1e80c85af581ecff6"
|
|
69
46
|
}
|