@nextclaw/x-harness 0.1.0 → 0.2.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/LICENSE +231 -6
- package/README.md +17 -3
- package/SOURCE.md +9 -0
- package/cli/main.js +232 -188
- package/dist/api.d.ts +56 -2
- package/dist/api.js +178 -75
- package/dist/boundary.js +1 -0
- package/dist/browser-common.d.ts +11 -0
- package/dist/browser-common.js +34 -18
- package/dist/browser-dom-capabilities.d.ts +9 -0
- package/dist/browser-dom-capabilities.js +131 -0
- package/dist/browser-dom-dependencies.d.ts +16 -0
- package/dist/browser-dom-dependencies.js +1 -0
- package/dist/browser-dom-editing.d.ts +166 -0
- package/dist/browser-dom-editing.js +418 -0
- package/dist/browser-dom-navigation.d.ts +18 -0
- package/dist/browser-dom-navigation.js +181 -0
- package/dist/browser-dom-network.d.ts +1 -0
- package/dist/browser-dom-network.js +128 -0
- package/dist/browser-dom-submission.d.ts +7 -0
- package/dist/browser-dom-submission.js +101 -0
- package/dist/browser-dom.d.ts +14 -2
- package/dist/browser-dom.js +120 -824
- package/dist/browser-native.d.ts +14 -1
- package/dist/browser-native.js +180 -143
- package/dist/browser.js +6 -2
- package/dist/creator-native.d.ts +3 -0
- package/dist/creator-native.js +113 -0
- package/dist/creator.js +1 -1
- package/dist/diagnostics.d.ts +11 -0
- package/dist/diagnostics.js +10 -0
- package/dist/growth-batch.d.ts +8 -0
- package/dist/growth-batch.js +190 -0
- package/dist/growth-constants.d.ts +5 -0
- package/dist/growth-constants.js +13 -0
- package/dist/growth-dependencies.d.ts +33 -0
- package/dist/growth-dependencies.js +1 -0
- package/dist/growth-execution.d.ts +17 -0
- package/dist/growth-execution.js +346 -0
- package/dist/growth-parallel.d.ts +8 -0
- package/dist/growth-parallel.js +332 -0
- package/dist/growth-plan.d.ts +9 -0
- package/dist/growth-plan.js +229 -0
- package/dist/growth-policy.d.ts +18 -0
- package/dist/growth-policy.js +208 -0
- package/dist/growth-publishing.d.ts +10 -0
- package/dist/growth-publishing.js +266 -0
- package/dist/growth-reading.d.ts +8 -0
- package/dist/growth-reading.js +157 -0
- package/dist/growth-recovery.d.ts +9 -0
- package/dist/growth-recovery.js +187 -0
- package/dist/growth-state.d.ts +16 -0
- package/dist/growth-state.js +220 -0
- package/dist/growth-tasks.d.ts +20 -0
- package/dist/growth-tasks.js +164 -0
- package/dist/growth.d.ts +26 -1
- package/dist/growth.js +211 -1908
- package/dist/platform-capabilities.d.ts +8 -0
- package/dist/platform-capabilities.js +29 -0
- package/dist/platform-collections.d.ts +14 -0
- package/dist/platform-collections.js +250 -0
- package/dist/platform-dependencies.d.ts +43 -0
- package/dist/platform-dependencies.js +1 -0
- package/dist/platform-diagnostics.d.ts +14 -0
- package/dist/platform-diagnostics.js +63 -0
- package/dist/platform-observation.d.ts +16 -0
- package/dist/platform-observation.js +96 -0
- package/dist/platform-rules.d.ts +17 -0
- package/dist/platform-rules.js +41 -0
- package/dist/platform-targets.d.ts +14 -0
- package/dist/platform-targets.js +154 -0
- package/dist/platform-writing.d.ts +16 -0
- package/dist/platform-writing.js +202 -0
- package/dist/platform.d.ts +23 -2
- package/dist/platform.js +125 -678
- package/dist/readers-actions.d.ts +2 -0
- package/dist/readers-actions.js +66 -0
- package/dist/readers-ax-host.d.ts +12 -0
- package/dist/readers-ax-host.js +134 -0
- package/dist/readers-ax-parser.d.ts +1 -0
- package/dist/readers-ax-parser.js +69 -0
- package/dist/readers-ax-program.d.ts +1 -0
- package/dist/readers-ax-program.js +5 -0
- package/dist/readers-ax-tree.d.ts +19 -0
- package/dist/readers-ax-tree.js +111 -0
- package/dist/readers-ax-views.d.ts +87 -0
- package/dist/readers-ax-views.js +247 -0
- package/dist/readers-cli.d.ts +6 -0
- package/dist/readers-cli.js +79 -0
- package/dist/readers-composer.d.ts +2 -0
- package/dist/readers-composer.js +131 -0
- package/dist/readers-navigation.d.ts +2 -0
- package/dist/readers-navigation.js +66 -0
- package/dist/readers-posts.d.ts +2 -0
- package/dist/readers-posts.js +141 -0
- package/dist/readers-profile.d.ts +3 -0
- package/dist/readers-profile.js +157 -0
- package/dist/readers.d.ts +9 -20
- package/dist/readers.js +9 -1045
- package/dist/results.js +1 -1
- package/dist/round-state.js +20 -3
- package/dist/store.d.ts +22 -4
- package/dist/store.js +173 -151
- package/dist/types.d.ts +10 -0
- package/dist/types.js +1 -0
- package/generated/observation.mjs +3 -2
- package/package.json +23 -9
- package/skill/SKILL.md +17 -36
- package/skill/references/api.md +7 -34
- package/skill/references/reads.md +23 -0
- package/skill/references/recovery.md +25 -0
- package/skill/references/setup.md +23 -0
- package/skill/references/writes.md +51 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Self-contained, read-only DOM function for cua_repl's documented evaluate.
|
|
2
|
+
export function readPosts({ offset = 0, limit = 5, targetId = "", } = {}) {
|
|
3
|
+
if (!Number.isInteger(offset) ||
|
|
4
|
+
offset < 0 ||
|
|
5
|
+
!Number.isInteger(limit) ||
|
|
6
|
+
limit < 1 ||
|
|
7
|
+
limit > 5)
|
|
8
|
+
throw new Error("offset>=0;limit为1~5");
|
|
9
|
+
if (targetId && !/^\d+$/.test(targetId))
|
|
10
|
+
throw new Error("targetId必须是数字公开ID");
|
|
11
|
+
const visible = (el) => el.getClientRects().length > 0;
|
|
12
|
+
const primaryTime = (a) => Array.from(a.querySelectorAll("time")).find((t) => visible(t) &&
|
|
13
|
+
/\/status\/\d+(?:$|[/?#])/.test(t.closest("a")?.getAttribute("href") ?? "")) ?? null;
|
|
14
|
+
const all = Array.from(document.querySelectorAll("article")).filter(visible);
|
|
15
|
+
const candidates = targetId
|
|
16
|
+
? all.filter((a) => {
|
|
17
|
+
const primary = primaryTime(a)?.closest("a")?.getAttribute("href");
|
|
18
|
+
return (primary && new RegExp(`/status/${targetId}(?:$|[/?#])`).test(primary));
|
|
19
|
+
})
|
|
20
|
+
: all;
|
|
21
|
+
const posts = candidates.slice(offset, offset + limit).map((a) => {
|
|
22
|
+
const time = primaryTime(a);
|
|
23
|
+
const primary = time?.closest("a")?.getAttribute("href") ?? null;
|
|
24
|
+
const links = [
|
|
25
|
+
...new Set(Array.from(a.querySelectorAll("a[href]"))
|
|
26
|
+
.filter(visible)
|
|
27
|
+
.map((l) => l.getAttribute("href"))),
|
|
28
|
+
];
|
|
29
|
+
const buttons = Array.from(a.querySelectorAll("button"))
|
|
30
|
+
.filter(visible)
|
|
31
|
+
.map((b) => ({
|
|
32
|
+
label: b.getAttribute("aria-label") || b.innerText,
|
|
33
|
+
disabled: b.hasAttribute("disabled"),
|
|
34
|
+
}));
|
|
35
|
+
const text = a.innerText;
|
|
36
|
+
const datetime = time?.getAttribute("datetime") ?? null;
|
|
37
|
+
const id = primary?.match(/\/status\/(\d+)/)?.[1] ?? null;
|
|
38
|
+
const author = primary?.match(/\/([^/]+)\/status\//)?.[1] ?? null;
|
|
39
|
+
const images = Array.from(a.querySelectorAll('[data-testid="tweetPhoto"] img'))
|
|
40
|
+
.filter(visible)
|
|
41
|
+
.map((img) => ({
|
|
42
|
+
alt: img.getAttribute("alt"),
|
|
43
|
+
src: img.getAttribute("src"),
|
|
44
|
+
}));
|
|
45
|
+
const media = Array.from(a.querySelectorAll('[data-testid="videoPlayer"],video'))
|
|
46
|
+
.filter(visible)
|
|
47
|
+
.map((el) => ({
|
|
48
|
+
kind: "video",
|
|
49
|
+
label: el.getAttribute("aria-label"),
|
|
50
|
+
poster: el.getAttribute("poster"),
|
|
51
|
+
requiresViewing: true,
|
|
52
|
+
}));
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
author,
|
|
56
|
+
datetime,
|
|
57
|
+
primary,
|
|
58
|
+
text,
|
|
59
|
+
links,
|
|
60
|
+
buttons,
|
|
61
|
+
// View/quote counts may be visible links rather than buttons; collect in this same read.
|
|
62
|
+
metrics: [
|
|
63
|
+
...buttons,
|
|
64
|
+
...Array.from(a.querySelectorAll('a[href$="/analytics"],a[href$="/quotes"]'))
|
|
65
|
+
.filter(visible)
|
|
66
|
+
.map((link) => ({
|
|
67
|
+
label: link.getAttribute("aria-label") ||
|
|
68
|
+
`${link.getAttribute("href").endsWith("/analytics") ? "观看" : "引用"} ${link.innerText}`,
|
|
69
|
+
})),
|
|
70
|
+
],
|
|
71
|
+
images,
|
|
72
|
+
media,
|
|
73
|
+
needsExpansion: /显示更多|Show more/i.test(text),
|
|
74
|
+
missing: [
|
|
75
|
+
!id && "id",
|
|
76
|
+
!author && "author",
|
|
77
|
+
!datetime && "datetime",
|
|
78
|
+
!text && "text",
|
|
79
|
+
].filter(Boolean),
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
const versionLinks = Array.from(document.querySelectorAll("a[href]"))
|
|
83
|
+
.filter(visible)
|
|
84
|
+
.filter((a) => /最新版本|查看最新帖子|Latest version|View latest/i.test(a.innerText))
|
|
85
|
+
.slice(0, 5)
|
|
86
|
+
.map((a) => ({ label: a.innerText, href: a.getAttribute("href") }));
|
|
87
|
+
const emptyEvidence = all.length === 0
|
|
88
|
+
? [
|
|
89
|
+
...new Set(Array.from(document.querySelectorAll("main span"))
|
|
90
|
+
.filter(visible)
|
|
91
|
+
.map((e) => e.innerText?.trim())
|
|
92
|
+
.filter((text) => text &&
|
|
93
|
+
text.length <= 400 &&
|
|
94
|
+
!text.includes("\n") &&
|
|
95
|
+
/^(?:没有.*结果|未找到.*结果|No results for)/i.test(text))),
|
|
96
|
+
].slice(0, 2)
|
|
97
|
+
: [];
|
|
98
|
+
return {
|
|
99
|
+
renderedArticles: all.length,
|
|
100
|
+
matched: candidates.length,
|
|
101
|
+
offset,
|
|
102
|
+
moreInDOM: candidates.length > offset + posts.length,
|
|
103
|
+
pageComplete: false,
|
|
104
|
+
needsStateCheck: all.length === 0 && emptyEvidence.length === 0,
|
|
105
|
+
posts,
|
|
106
|
+
versionLinks,
|
|
107
|
+
emptyEvidence,
|
|
108
|
+
alerts: Array.from(document.querySelectorAll('[role="alert"]'))
|
|
109
|
+
.filter(visible)
|
|
110
|
+
.map((e) => e.innerText),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export function changes(result, cache, page, fresh = false) {
|
|
114
|
+
const unchangedIds = [];
|
|
115
|
+
const posts = result.posts.filter((post) => {
|
|
116
|
+
if (!post.id)
|
|
117
|
+
return true;
|
|
118
|
+
const key = `${page}|${post.id}`;
|
|
119
|
+
const value = JSON.stringify(post);
|
|
120
|
+
const changed = cache[key] !== value;
|
|
121
|
+
cache[key] = value;
|
|
122
|
+
if (!fresh && !changed)
|
|
123
|
+
unchangedIds.push(post.id);
|
|
124
|
+
return fresh || changed;
|
|
125
|
+
});
|
|
126
|
+
const outputChars = JSON.stringify({ ...result, posts, unchangedIds }).length;
|
|
127
|
+
const optimizationHint = outputChars > 8000
|
|
128
|
+
? posts.length > 1
|
|
129
|
+
? "缩小读取窗口或按已观察ID定向读取;保留完整正文"
|
|
130
|
+
: "单篇证据本身长,保留全文,不截断"
|
|
131
|
+
: null;
|
|
132
|
+
return {
|
|
133
|
+
...result,
|
|
134
|
+
posts,
|
|
135
|
+
unchanged: result.posts.length - posts.length,
|
|
136
|
+
unchangedIds,
|
|
137
|
+
fresh,
|
|
138
|
+
outputChars,
|
|
139
|
+
optimizationHint,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// Profile selectors are the visible controls observed in the live X workflow.
|
|
2
|
+
// Missing/ambiguous counters remain unknown; rounded counts carry their precision.
|
|
3
|
+
export function readProfile({ handle } = {}) {
|
|
4
|
+
if (!/^[A-Za-z0-9_]{1,15}$/.test(handle ?? ""))
|
|
5
|
+
throw new Error("需要已观察的X handle");
|
|
6
|
+
const visible = (el) => el.getClientRects().length > 0;
|
|
7
|
+
const main = document.querySelector("main");
|
|
8
|
+
if (!main)
|
|
9
|
+
return {
|
|
10
|
+
handle,
|
|
11
|
+
blue: null,
|
|
12
|
+
relationship: "unknown",
|
|
13
|
+
alerts: ["missing-main"],
|
|
14
|
+
observedAt: new Date().toISOString(),
|
|
15
|
+
};
|
|
16
|
+
const buttons = Array.from(main.querySelectorAll("button")).filter(visible);
|
|
17
|
+
const labels = buttons.map((b) => b.getAttribute("aria-label") || b.innerText);
|
|
18
|
+
const relationship = labels.includes(`正在关注 @${handle}`) ||
|
|
19
|
+
labels.includes(`取消关注 @${handle}`)
|
|
20
|
+
? "following"
|
|
21
|
+
: labels.includes(`回关 @${handle}`)
|
|
22
|
+
? "follows-you"
|
|
23
|
+
: labels.includes(`关注 @${handle}`)
|
|
24
|
+
? "not-following"
|
|
25
|
+
: "unknown";
|
|
26
|
+
const badges = buttons
|
|
27
|
+
.filter((b) => b.getAttribute("aria-label") === "提供已验证账号的详细信息。")
|
|
28
|
+
.map((b) => b.querySelector("svg"))
|
|
29
|
+
.filter(Boolean);
|
|
30
|
+
const blue = badges.length === 1
|
|
31
|
+
? [
|
|
32
|
+
getComputedStyle(badges[0]).color,
|
|
33
|
+
getComputedStyle(badges[0]).fill,
|
|
34
|
+
].includes("rgb(29, 155, 240)")
|
|
35
|
+
: null;
|
|
36
|
+
const links = Array.from(main.querySelectorAll("a[href]")).filter(visible);
|
|
37
|
+
const counter = (suffixes) => {
|
|
38
|
+
const matched = links.filter((a) => suffixes.some((s) => a.getAttribute("href")?.toLowerCase() ===
|
|
39
|
+
`/${handle}/${s}`.toLowerCase()));
|
|
40
|
+
const texts = [...new Set(matched.map((a) => a.innerText.trim()))];
|
|
41
|
+
if (texts.length !== 1)
|
|
42
|
+
return { value: null, text: texts, precision: "unknown" };
|
|
43
|
+
const match = texts[0].match(/^([\d,.]+)\s*(万|亿|[KMB])?/i);
|
|
44
|
+
const factors = {
|
|
45
|
+
万: 1e4,
|
|
46
|
+
亿: 1e8,
|
|
47
|
+
K: 1e3,
|
|
48
|
+
M: 1e6,
|
|
49
|
+
B: 1e9,
|
|
50
|
+
};
|
|
51
|
+
const value = match
|
|
52
|
+
? Number(match[1].replaceAll(",", "")) *
|
|
53
|
+
(factors[match[2]?.toUpperCase()] ?? 1)
|
|
54
|
+
: null;
|
|
55
|
+
const hrefs = [...new Set(matched.map((a) => a.getAttribute("href")))];
|
|
56
|
+
return {
|
|
57
|
+
value: Number.isFinite(value) ? value : null,
|
|
58
|
+
text: texts[0],
|
|
59
|
+
precision: match?.[2] ? "rounded" : "exact",
|
|
60
|
+
url: hrefs.length === 1 ? "https://x.com" + hrefs[0] : null,
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
handle,
|
|
65
|
+
blue,
|
|
66
|
+
relationship,
|
|
67
|
+
relationshipControls: labels
|
|
68
|
+
.filter((label) => label.includes("@" + handle) || /取消关注|订阅/.test(label))
|
|
69
|
+
.slice(0, 5),
|
|
70
|
+
biography: main.querySelector('[data-testid="UserDescription"]')
|
|
71
|
+
?.innerText ?? null,
|
|
72
|
+
following: counter(["following"]),
|
|
73
|
+
followers: counter(["followers", "verified_followers"]),
|
|
74
|
+
alerts: Array.from(document.querySelectorAll('[role="alert"]'))
|
|
75
|
+
.filter(visible)
|
|
76
|
+
.map((a) => a.innerText),
|
|
77
|
+
observedAt: new Date().toISOString(),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Bounded visible person cells for a currently loaded follower/following list.
|
|
81
|
+
export function readPeople({ offset = 0, limit = 5 } = {}) {
|
|
82
|
+
if (!Number.isInteger(offset) ||
|
|
83
|
+
offset < 0 ||
|
|
84
|
+
!Number.isInteger(limit) ||
|
|
85
|
+
limit < 1 ||
|
|
86
|
+
limit > 5)
|
|
87
|
+
throw new Error("人物窗口须为非负offset及1–5 limit");
|
|
88
|
+
const visible = (el) => el.getClientRects().length > 0;
|
|
89
|
+
const cells = Array.from(document.querySelectorAll('main [data-testid="UserCell"]')).filter(visible);
|
|
90
|
+
const people = cells.slice(offset, offset + limit).map((cell) => {
|
|
91
|
+
const links = Array.from(cell.querySelectorAll("a[href]"))
|
|
92
|
+
.filter(visible)
|
|
93
|
+
.map((a) => ({ text: a.innerText, href: a.getAttribute("href") }));
|
|
94
|
+
const buttons = Array.from(cell.querySelectorAll("button"))
|
|
95
|
+
.filter(visible)
|
|
96
|
+
.map((b) => ({
|
|
97
|
+
label: b.getAttribute("aria-label") || b.innerText,
|
|
98
|
+
disabled: b.disabled,
|
|
99
|
+
}));
|
|
100
|
+
return { text: cell.innerText, links, buttons };
|
|
101
|
+
});
|
|
102
|
+
return {
|
|
103
|
+
page: location.href,
|
|
104
|
+
people,
|
|
105
|
+
offset,
|
|
106
|
+
renderedPeople: cells.length,
|
|
107
|
+
moreInDOM: offset + limit < cells.length,
|
|
108
|
+
pageComplete: false,
|
|
109
|
+
needsStateCheck: !people.length,
|
|
110
|
+
missing: people.length ? [] : ["people-cells-not-found"],
|
|
111
|
+
alerts: Array.from(document.querySelectorAll('[role="alert"]'))
|
|
112
|
+
.filter(visible)
|
|
113
|
+
.map((a) => a.innerText),
|
|
114
|
+
observedAt: new Date().toISOString(),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// This ranks observed clues, never a predicted follow-back probability.
|
|
118
|
+
export function screenCandidates(profiles, { minRatio = 0.8 } = {}) {
|
|
119
|
+
if (!Array.isArray(profiles) || !Number.isFinite(minRatio) || minRatio <= 0)
|
|
120
|
+
throw new Error("profiles数组和正minRatio必填");
|
|
121
|
+
const seen = new Set();
|
|
122
|
+
return profiles
|
|
123
|
+
.map((p) => {
|
|
124
|
+
const key = String(p.handle ?? "").toLowerCase();
|
|
125
|
+
const duplicate = seen.has(key);
|
|
126
|
+
seen.add(key);
|
|
127
|
+
const following = p.following?.value, followers = p.followers?.value;
|
|
128
|
+
const ratio = Number.isFinite(following) &&
|
|
129
|
+
Number.isFinite(followers) &&
|
|
130
|
+
followers > 0
|
|
131
|
+
? following / followers
|
|
132
|
+
: null;
|
|
133
|
+
const clues = [];
|
|
134
|
+
if (typeof p.mutualEvidence === "string" && p.mutualEvidence.trim())
|
|
135
|
+
clues.push({ kind: "explicit-mutual", evidence: p.mutualEvidence });
|
|
136
|
+
if (ratio !== null && ratio >= minRatio)
|
|
137
|
+
clues.push({
|
|
138
|
+
kind: "following-ratio",
|
|
139
|
+
ratio,
|
|
140
|
+
following: p.following,
|
|
141
|
+
followers: p.followers,
|
|
142
|
+
evidence: "关注/粉丝比例线索,非回关概率",
|
|
143
|
+
});
|
|
144
|
+
const rejected = [
|
|
145
|
+
duplicate && "duplicate",
|
|
146
|
+
p.blue !== true && "blue-unconfirmed",
|
|
147
|
+
p.relationship !== "not-following" && "relationship-ineligible",
|
|
148
|
+
p.alerts?.length && "page-alert",
|
|
149
|
+
!clues.length && "no-followback-clue",
|
|
150
|
+
!/^[A-Za-z0-9_]{1,15}$/.test(p.handle ?? "") && "invalid-handle",
|
|
151
|
+
].filter(Boolean);
|
|
152
|
+
return { ...p, ratio, clues, eligible: rejected.length === 0, rejected };
|
|
153
|
+
})
|
|
154
|
+
.sort((a, b) => Number(b.eligible) - Number(a.eligible) ||
|
|
155
|
+
Number(b.clues.some((c) => c.kind === "explicit-mutual")) -
|
|
156
|
+
Number(a.clues.some((c) => c.kind === "explicit-mutual")));
|
|
157
|
+
}
|
package/dist/readers.d.ts
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
10
|
-
export declare function readMenu(): any;
|
|
11
|
-
export declare function readNavigation({ targetLabel }?: any): any;
|
|
12
|
-
export declare function readMediaEditor(): any;
|
|
13
|
-
export declare function attachImage(tab: any, { path }?: any): Promise<any>;
|
|
14
|
-
export declare function openReply(tab: any, { postId }?: any): Promise<any>;
|
|
15
|
-
export declare function screenCandidates(profiles: any, { minRatio }?: any): any;
|
|
16
|
-
export declare function profileCode({ tab, handle }?: any): any;
|
|
17
|
-
export declare function profilesCode(entries: any): any;
|
|
18
|
-
export declare function browserCode({ handle, offset, limit, targetId, fresh, }?: any): any;
|
|
19
|
-
export declare function axCode({ handle, mode, offset, limit, targetId, targetHandle, fresh, }?: any): any;
|
|
20
|
-
export declare function runReaderCLI(): void;
|
|
1
|
+
/** Compatibility exports only. Implementation owners are task-specific modules. */
|
|
2
|
+
export { readPosts, changes } from "./readers-posts.js";
|
|
3
|
+
export { readAX } from "./readers-ax-parser.js";
|
|
4
|
+
export { createAXTabHarness, createAXHarness } from "./readers-ax-host.js";
|
|
5
|
+
export { readProfile, readPeople, screenCandidates, } from "./readers-profile.js";
|
|
6
|
+
export { readComposer, readMediaEditor } from "./readers-composer.js";
|
|
7
|
+
export { readMenu, readNavigation } from "./readers-navigation.js";
|
|
8
|
+
export { attachImage, openReply } from "./readers-actions.js";
|
|
9
|
+
export { setupCode, profileCode, profilesCode, browserCode, axCode, runReaderCLI, } from "./readers-cli.js";
|