@nextclaw/x-harness 0.2.61 → 0.2.63

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  # Corresponding source
2
2
 
3
- Version 0.2.61, commit 56f3c8a87df442687670edc9526d13d74e7e101c.
3
+ Version 0.2.63, commit 6e70dc4b7351bc7ec59936ed517465133001099b.
4
4
 
5
- Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/56f3c8a87df442687670edc9526d13d74e7e101c
5
+ Complete source, build scripts and dependencies: https://github.com/Peiiii/x-harness/tree/6e70dc4b7351bc7ec59936ed517465133001099b
6
6
 
7
7
  Clone this revision, run npm ci, npm run bootstrap and npm run release:build.
8
8
 
package/dist/api.js CHANGED
@@ -321,11 +321,14 @@ export class BusinessHarness {
321
321
  });
322
322
  }
323
323
  }
324
- if (result.status === "unknown")
325
- result = await this.verifySubmission({
326
- taskId: args.taskId,
327
- actionId: action.id,
328
- });
324
+ if (result.status === "unknown") {
325
+ const current = (await this.#store.load()).state.actions.find((a) => a.id === action.id);
326
+ if (current?.observedPublicURL && current?.observedPublicEvidenceRef)
327
+ result = await this.verifySubmission({
328
+ taskId: args.taskId,
329
+ actionId: action.id,
330
+ });
331
+ }
329
332
  results.push(result);
330
333
  if (["waiting", "needsCapability", "needsDecision"].includes(result.status))
331
334
  break;
@@ -14,7 +14,7 @@ export declare class DOMNavigation {
14
14
  private handleWaitForFolder;
15
15
  private handleWaitForPosts;
16
16
  private handleOpenObserved;
17
- private handleWaitPublicArticle;
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.handleWaitPublicArticle(detail.first(), command.url);
236
+ await this.handleWaitTargetContent(detail.first(), command.url);
239
237
  }
240
238
  return;
241
239
  }
242
- async handleWaitPublicArticle(detail, url) {
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("public-article-readiness-timeout");
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.handleWaitPublicArticle(this.#tab.playwright.getByRole("article").first(), command.url);
305
+ await this.handleWaitTargetContent(this.#tab.playwright.getByRole("article").first(), command.url);
310
306
  return;
311
307
  }
312
308
  }
package/package.json CHANGED
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/x-harness",
3
- "version": "0.2.61",
4
- "private": false,
3
+ "version": "0.2.63",
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": "6e70dc4b7351bc7ec59936ed517465133001099b"
69
46
  }
@@ -49,7 +49,7 @@ Optional independentExecution:{tabId,evidenceRef,scopeEvidenceRef} requires real
49
49
 
50
50
  ## Reply
51
51
 
52
- Additional fields: kind:'reply', postId, url, evidenceRef (observed parent), text; optional assets/activation as above. Common account/quality fields still required. The exact parent is verified by the API. `replyBatch({taskId,actions})` accepts 1–5 reviewed replies, submits serially and recovers an observed receipt once without resending; The batch owns one normal pacing wait (up to 30 seconds) per action and one read-only verification for an unknown result, including when no permalink was captured. Longer or renewed waits and capability/decision failures return unfinished work. Remaining unknowns without permalinks get one batched own-account lookup, then exact-parent verification of unique observed links; unknowns never resubmit. Incoming clicks have a ≥30s minimum gap, not a safety guarantee. Incoming conversations require reviewed conversation:{recipientHandle,rootId,round,automatedLoop?}; at most 3 own rounds per recipient/root, with intent/unknown counted. Mark observed automatic loops to stop earlier.
52
+ Additional fields: kind:'reply', postId, url, evidenceRef (observed parent), text; optional assets/activation as above. Common account/quality fields still required. The exact parent is verified by the API. `replyBatch({taskId,actions})` accepts 1–5 reviewed replies, submits serially and recovers an observed receipt once without resending; The batch owns one normal pacing wait (up to 30 seconds) per action and one read-only retry for an observed permalink. Longer or renewed waits and capability/decision failures return unfinished work. Remaining unknowns without permalinks get one batched own-account lookup, then exact-parent verification of unique observed links; unknowns never resubmit. Incoming clicks have a ≥30s minimum gap, not a safety guarantee. Incoming conversations require reviewed conversation:{recipientHandle,rootId,round,automatedLoop?}; at most 3 own rounds per recipient/root, with intent/unknown counted. Mark observed automatic loops to stop earlier.
53
53
 
54
54
  ```js
55
55
  var result = await x.replyToPost({