screenhand 0.1.1 → 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/README.md +458 -93
- package/dist/.audit-log.jsonl +55 -0
- package/dist/.screenhand/memory/.lock +1 -0
- package/dist/.screenhand/memory/actions.jsonl +85 -0
- package/dist/.screenhand/memory/errors.jsonl +5 -0
- package/dist/.screenhand/memory/errors.jsonl.bak +4 -0
- package/dist/.screenhand/memory/state.json +35 -0
- package/dist/.screenhand/memory/state.json.bak +35 -0
- package/dist/.screenhand/memory/strategies.jsonl +12 -0
- package/dist/agent/cli.js +73 -0
- package/dist/agent/loop.js +258 -0
- package/dist/config.js +9 -0
- package/dist/index.js +56 -0
- package/dist/logging/timeline-logger.js +29 -0
- package/dist/mcp/mcp-stdio-server.js +448 -0
- package/dist/mcp/server.js +347 -0
- package/dist/mcp-desktop.js +2731 -0
- package/dist/mcp-entry.js +59 -0
- package/dist/memory/recall.js +160 -0
- package/dist/memory/research.js +98 -0
- package/dist/memory/seeds.js +89 -0
- package/dist/memory/session.js +161 -0
- package/dist/memory/store.js +391 -0
- package/dist/memory/types.js +4 -0
- package/dist/monitor/codex-monitor.js +377 -0
- package/dist/monitor/task-queue.js +84 -0
- package/dist/monitor/types.js +49 -0
- package/dist/native/bridge-client.js +174 -0
- package/dist/native/macos-bridge-client.js +5 -0
- package/dist/npm-publish-helper.js +117 -0
- package/dist/npm-token-cdp.js +113 -0
- package/dist/npm-token-create.js +135 -0
- package/dist/npm-token-finish.js +126 -0
- package/dist/playbook/engine.js +193 -0
- package/dist/playbook/index.js +4 -0
- package/dist/playbook/recorder.js +519 -0
- package/dist/playbook/runner.js +392 -0
- package/dist/playbook/store.js +166 -0
- package/dist/playbook/types.js +4 -0
- package/dist/runtime/accessibility-adapter.js +377 -0
- package/dist/runtime/app-adapter.js +48 -0
- package/dist/runtime/applescript-adapter.js +283 -0
- package/dist/runtime/ax-role-map.js +80 -0
- package/dist/runtime/browser-adapter.js +36 -0
- package/dist/runtime/cdp-chrome-adapter.js +505 -0
- package/dist/runtime/composite-adapter.js +205 -0
- package/dist/runtime/executor.js +250 -0
- package/dist/runtime/locator-cache.js +12 -0
- package/dist/runtime/planning-loop.js +47 -0
- package/dist/runtime/service.js +372 -0
- package/dist/runtime/session-manager.js +28 -0
- package/dist/runtime/state-observer.js +105 -0
- package/dist/runtime/vision-adapter.js +208 -0
- package/dist/scripts/codex-monitor-daemon.js +335 -0
- package/dist/scripts/supervisor-daemon.js +272 -0
- package/dist/scripts/worker-daemon.js +228 -0
- package/dist/src/agent/cli.js +82 -0
- package/dist/src/agent/loop.js +274 -0
- package/{src/config.ts → dist/src/config.js} +5 -10
- package/{src/index.ts → dist/src/index.js} +32 -52
- package/dist/src/jobs/manager.js +237 -0
- package/dist/src/jobs/runner.js +683 -0
- package/dist/src/jobs/store.js +102 -0
- package/dist/src/jobs/types.js +30 -0
- package/dist/src/jobs/worker.js +97 -0
- package/dist/src/logging/timeline-logger.js +45 -0
- package/dist/src/mcp/mcp-stdio-server.js +464 -0
- package/dist/src/mcp/server.js +363 -0
- package/dist/src/mcp-entry.js +60 -0
- package/dist/src/memory/recall.js +170 -0
- package/dist/src/memory/research.js +104 -0
- package/dist/src/memory/seeds.js +101 -0
- package/dist/src/memory/service.js +421 -0
- package/dist/src/memory/session.js +169 -0
- package/dist/src/memory/store.js +422 -0
- package/dist/src/memory/types.js +17 -0
- package/dist/src/monitor/codex-monitor.js +382 -0
- package/dist/src/monitor/task-queue.js +97 -0
- package/dist/src/monitor/types.js +62 -0
- package/dist/src/native/bridge-client.js +190 -0
- package/{src/native/macos-bridge-client.ts → dist/src/native/macos-bridge-client.js} +0 -1
- package/dist/src/playbook/engine.js +201 -0
- package/dist/src/playbook/index.js +20 -0
- package/dist/src/playbook/recorder.js +535 -0
- package/dist/src/playbook/runner.js +408 -0
- package/dist/src/playbook/store.js +183 -0
- package/dist/src/playbook/types.js +17 -0
- package/dist/src/runtime/accessibility-adapter.js +393 -0
- package/dist/src/runtime/app-adapter.js +64 -0
- package/dist/src/runtime/applescript-adapter.js +299 -0
- package/dist/src/runtime/ax-role-map.js +96 -0
- package/dist/src/runtime/browser-adapter.js +52 -0
- package/dist/src/runtime/cdp-chrome-adapter.js +521 -0
- package/dist/src/runtime/composite-adapter.js +221 -0
- package/dist/src/runtime/execution-contract.js +159 -0
- package/dist/src/runtime/executor.js +266 -0
- package/{src/runtime/locator-cache.ts → dist/src/runtime/locator-cache.js} +10 -15
- package/dist/src/runtime/planning-loop.js +63 -0
- package/dist/src/runtime/service.js +388 -0
- package/dist/src/runtime/session-manager.js +60 -0
- package/dist/src/runtime/state-observer.js +121 -0
- package/dist/src/runtime/vision-adapter.js +224 -0
- package/dist/src/supervisor/locks.js +186 -0
- package/dist/src/supervisor/supervisor.js +403 -0
- package/dist/src/supervisor/types.js +30 -0
- package/dist/src/test-mcp-protocol.js +154 -0
- package/dist/src/types.js +17 -0
- package/dist/src/util/atomic-write.js +118 -0
- package/dist/test-mcp-protocol.js +138 -0
- package/dist/types.js +1 -0
- package/package.json +18 -4
- package/.claude/commands/automate.md +0 -28
- package/.claude/commands/debug-ui.md +0 -19
- package/.claude/commands/screenshot.md +0 -15
- package/.github/FUNDING.yml +0 -1
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -27
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.mcp.json +0 -8
- package/DESKTOP_MCP_GUIDE.md +0 -92
- package/SECURITY.md +0 -44
- package/docs/architecture.md +0 -47
- package/install-skills.sh +0 -19
- package/mcp-bridge.ts +0 -271
- package/mcp-desktop.ts +0 -1221
- package/native/macos-bridge/Package.swift +0 -21
- package/native/macos-bridge/Sources/AccessibilityBridge.swift +0 -261
- package/native/macos-bridge/Sources/AppManagement.swift +0 -129
- package/native/macos-bridge/Sources/CoreGraphicsBridge.swift +0 -242
- package/native/macos-bridge/Sources/ObserverBridge.swift +0 -120
- package/native/macos-bridge/Sources/VisionBridge.swift +0 -80
- package/native/macos-bridge/Sources/main.swift +0 -345
- package/native/windows-bridge/AppManagement.cs +0 -234
- package/native/windows-bridge/InputBridge.cs +0 -436
- package/native/windows-bridge/Program.cs +0 -265
- package/native/windows-bridge/ScreenCapture.cs +0 -329
- package/native/windows-bridge/UIAutomationBridge.cs +0 -571
- package/native/windows-bridge/WindowsBridge.csproj +0 -17
- package/playbooks/devpost.json +0 -186
- package/playbooks/instagram.json +0 -41
- package/playbooks/instagram_v2.json +0 -201
- package/playbooks/x_v1.json +0 -211
- package/scripts/devpost-live-loop.mjs +0 -421
- package/src/logging/timeline-logger.ts +0 -55
- package/src/mcp/server.ts +0 -449
- package/src/memory/recall.ts +0 -191
- package/src/memory/research.ts +0 -146
- package/src/memory/seeds.ts +0 -123
- package/src/memory/session.ts +0 -201
- package/src/memory/store.ts +0 -434
- package/src/memory/types.ts +0 -69
- package/src/native/bridge-client.ts +0 -239
- package/src/runtime/accessibility-adapter.ts +0 -487
- package/src/runtime/app-adapter.ts +0 -169
- package/src/runtime/applescript-adapter.ts +0 -376
- package/src/runtime/ax-role-map.ts +0 -102
- package/src/runtime/browser-adapter.ts +0 -129
- package/src/runtime/cdp-chrome-adapter.ts +0 -676
- package/src/runtime/composite-adapter.ts +0 -274
- package/src/runtime/executor.ts +0 -396
- package/src/runtime/planning-loop.ts +0 -81
- package/src/runtime/service.ts +0 -448
- package/src/runtime/session-manager.ts +0 -50
- package/src/runtime/state-observer.ts +0 -136
- package/src/runtime/vision-adapter.ts +0 -297
- package/src/types.ts +0 -297
- package/tests/bridge-client.test.ts +0 -176
- package/tests/browser-stealth.test.ts +0 -210
- package/tests/composite-adapter.test.ts +0 -64
- package/tests/mcp-server.test.ts +0 -151
- package/tests/memory-recall.test.ts +0 -339
- package/tests/memory-research.test.ts +0 -159
- package/tests/memory-seeds.test.ts +0 -120
- package/tests/memory-store.test.ts +0 -392
- package/tests/types.test.ts +0 -92
- package/tsconfig.check.json +0 -17
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -8
package/playbooks/devpost.json
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"platform": "devpost",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"updated": "2026-03-05",
|
|
5
|
-
"description": "Devpost — hackathon platform for project submissions, portfolios, and team collaboration",
|
|
6
|
-
|
|
7
|
-
"urls": {
|
|
8
|
-
"signup": "https://secure.devpost.com/users/register?ref_content=signup_global_nav&ref_feature=signup&ref_medium=button",
|
|
9
|
-
"login": "https://secure.devpost.com/users/login",
|
|
10
|
-
"welcome": "https://devpost.com/users/welcome",
|
|
11
|
-
"onboarding": "https://devpost.com/settings/hackathon-recommendations?return_to=https%3A%2F%2Fdevpost.com%2F",
|
|
12
|
-
"settings": "https://devpost.com/settings",
|
|
13
|
-
"portfolio": "https://devpost.com/portfolio/redirect?page=projects",
|
|
14
|
-
"profile": "https://devpost.com/{username}",
|
|
15
|
-
"create_project": "https://devpost.com/software/new",
|
|
16
|
-
"edit_project": "https://devpost.com/software/{slug}/edit",
|
|
17
|
-
"public_project": "https://devpost.com/software/{slug}",
|
|
18
|
-
"hackathons": "https://devpost.com/hackathons",
|
|
19
|
-
"software_gallery": "https://devpost.com/software",
|
|
20
|
-
"logout": "https://devpost.com/users/logout"
|
|
21
|
-
},
|
|
22
|
-
|
|
23
|
-
"flows": {
|
|
24
|
-
"signup": {
|
|
25
|
-
"steps": [
|
|
26
|
-
"Navigate to signup URL",
|
|
27
|
-
"Click 'Sign up with email' link to reveal email form",
|
|
28
|
-
"Fill #user_first_name, #user_last_name, #user_email, #user_password",
|
|
29
|
-
"MANUAL: Solve reCAPTCHA (cannot be automated)",
|
|
30
|
-
"Click 'Sign up with email' submit button",
|
|
31
|
-
"MANUAL: Verify email via link in inbox",
|
|
32
|
-
"Redirects to /users/welcome → onboarding"
|
|
33
|
-
],
|
|
34
|
-
"selectors": {
|
|
35
|
-
"first_name": "#user_first_name",
|
|
36
|
-
"last_name": "#user_last_name",
|
|
37
|
-
"email": "#user_email",
|
|
38
|
-
"password": "#user_password",
|
|
39
|
-
"email_signup_button": "button or a matching /sign up with email/i",
|
|
40
|
-
"recaptcha_token": "#g-recaptcha-response",
|
|
41
|
-
"recaptcha_iframe": "iframe[src*='recaptcha']"
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
"onboarding": {
|
|
46
|
-
"steps": [
|
|
47
|
-
"Navigate to onboarding URL",
|
|
48
|
-
"Select specialty checkbox",
|
|
49
|
-
"Fill skills tag list",
|
|
50
|
-
"Check interest checkboxes",
|
|
51
|
-
"Fill location and select timezone",
|
|
52
|
-
"Select career status (Professional to skip school fields)",
|
|
53
|
-
"Click Continue button",
|
|
54
|
-
"May need multiple fill+continue passes"
|
|
55
|
-
],
|
|
56
|
-
"selectors": {
|
|
57
|
-
"specialty_fullstack": "#user_employed_as_full-stack_developer",
|
|
58
|
-
"skills": "#user_tag_list",
|
|
59
|
-
"interest_ai": "#user_theme_ids_6",
|
|
60
|
-
"interest_web": "#user_theme_ids_25",
|
|
61
|
-
"interest_beginner": "#user_theme_ids_23",
|
|
62
|
-
"interest_open_ended": "#user_theme_ids_22",
|
|
63
|
-
"location": "#user_address",
|
|
64
|
-
"timezone": "#user_timezone",
|
|
65
|
-
"career_professional": "#user_career_status_professional__post_grad",
|
|
66
|
-
"employed_in_tech": "#user_employed_in_software_or_tech_true",
|
|
67
|
-
"no_company_hackathons": "#user_company_has_internal_hackathons_false",
|
|
68
|
-
"school_name": "#user_school_name",
|
|
69
|
-
"grad_month": "#user_graduation_date_2i",
|
|
70
|
-
"grad_year": "#user_graduation_date_1i",
|
|
71
|
-
"continue_button": "input[type='submit'] or button matching /continue|next/i"
|
|
72
|
-
},
|
|
73
|
-
"tips": [
|
|
74
|
-
"Choose 'Professional (post grad)' to bypass school-required fields",
|
|
75
|
-
"Timezone: search for 'chennai' or 'kolkata' or 'new delhi' in select options"
|
|
76
|
-
]
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
"settings": {
|
|
80
|
-
"steps": [
|
|
81
|
-
"Navigate to /settings",
|
|
82
|
-
"Fill tagline, GitHub, website, Twitter fields",
|
|
83
|
-
"Click Save button"
|
|
84
|
-
],
|
|
85
|
-
"selectors": {
|
|
86
|
-
"first_name": "#user_first_name",
|
|
87
|
-
"last_name": "#user_last_name",
|
|
88
|
-
"tagline": "#user_user_setting_attributes_tagline",
|
|
89
|
-
"github": "#user_user_setting_attributes_github_login",
|
|
90
|
-
"website": "#user_user_setting_attributes_website",
|
|
91
|
-
"twitter": "#user_user_setting_attributes_twitter",
|
|
92
|
-
"save_button": "button matching /save changes|save|update/i"
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
|
|
96
|
-
"create_project": {
|
|
97
|
-
"steps": [
|
|
98
|
-
"Navigate to portfolio or /software/new",
|
|
99
|
-
"Click 'Add a new project' if on portfolio page",
|
|
100
|
-
"Fill project name in #software_name",
|
|
101
|
-
"Click #software_name_save_button or submit form",
|
|
102
|
-
"Redirects to /software/{slug}/edit",
|
|
103
|
-
"Fill tagline, description, built-with, try-it URL",
|
|
104
|
-
"Click Save (#software-save)",
|
|
105
|
-
"Click Publish button",
|
|
106
|
-
"MANUAL: May need reCAPTCHA solve again"
|
|
107
|
-
],
|
|
108
|
-
"selectors": {
|
|
109
|
-
"add_project_button": "a or button matching /add a new project/i",
|
|
110
|
-
"project_name": "#software_name",
|
|
111
|
-
"project_name_save": "#software_name_save_button",
|
|
112
|
-
"hackathon_picker_modal": "#hackathon-picker",
|
|
113
|
-
"project_form": "#software_editor",
|
|
114
|
-
"tagline": "#software_tagline",
|
|
115
|
-
"built_with": "#software_tag_list",
|
|
116
|
-
"try_it_url": "#software_urls_attributes_0_url",
|
|
117
|
-
"description": "#software_description",
|
|
118
|
-
"save_draft": "#software-save",
|
|
119
|
-
"publish_button": "button matching /publish|submit|post/i"
|
|
120
|
-
},
|
|
121
|
-
"description_template": "## Inspiration\n[Why you built it]\n\n## What it does\n[Core functionality]\n\n## How we built it\n[Tech stack and architecture]\n\n## Challenges we ran into\n[Problems solved]\n\n## Accomplishments that we're proud of\n[Key wins]\n\n## What we learned\n[Takeaways]\n\n## What's next for [Project Name]\n[Future plans]"
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
"detection": {
|
|
126
|
-
"is_logged_in": "!!document.querySelector('a[href*=\"/users/logout\"]')",
|
|
127
|
-
"on_signup": "location.href.includes('/users/register')",
|
|
128
|
-
"on_welcome": "location.href.includes('/users/welcome')",
|
|
129
|
-
"on_onboarding": "location.href.includes('/settings/hackathon-recommendations')",
|
|
130
|
-
"on_settings": "location.href.startsWith('https://devpost.com/settings') && !location.href.includes('/hackathon-recommendations')",
|
|
131
|
-
"on_profile": "/^https:\\/\\/devpost\\.com\\/[^\\/?#]+\\/?$/.test(location.href)",
|
|
132
|
-
"has_captcha": "!!document.querySelector('iframe[src*=\"recaptcha\"], iframe[title*=\"reCAPTCHA\"], #g-recaptcha-response')",
|
|
133
|
-
"captcha_solved": "(document.querySelector('#g-recaptcha-response')?.value?.length || 0) > 0"
|
|
134
|
-
},
|
|
135
|
-
|
|
136
|
-
"errors": [
|
|
137
|
-
{
|
|
138
|
-
"error": "reCAPTCHA cannot be automated",
|
|
139
|
-
"context": "Signup and project creation both have reCAPTCHA",
|
|
140
|
-
"solution": "Must be solved manually by user. Use browser_wait to poll for captcha_solved state, then continue automation after user solves it.",
|
|
141
|
-
"severity": "blocker"
|
|
142
|
-
},
|
|
143
|
-
{
|
|
144
|
-
"error": "Email signup form not visible / collapses back to social signup",
|
|
145
|
-
"context": "The signup page shows Google/GitHub buttons by default, email form is hidden",
|
|
146
|
-
"solution": "Click the 'Sign up with email' link first. If it collapses, force visibility via JS: find the container and set display:block",
|
|
147
|
-
"severity": "medium"
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
"error": "el.value = text ignored by form (React-style)",
|
|
151
|
-
"context": "Devpost forms use event-driven validation",
|
|
152
|
-
"solution": "After setting el.value, dispatch both 'input' and 'change' events with bubbles:true. Or use browser_fill_form for CDP keyboard events.",
|
|
153
|
-
"severity": "high"
|
|
154
|
-
},
|
|
155
|
-
{
|
|
156
|
-
"error": "el.click() on submit button doesn't work",
|
|
157
|
-
"context": "Some Devpost buttons require real mouse events",
|
|
158
|
-
"solution": "Use browser_human_click with CSS selector, or browser_click (now uses CDP Input.dispatchMouseEvent)",
|
|
159
|
-
"severity": "high"
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
"error": "Onboarding has required fields that block Continue",
|
|
163
|
-
"context": "School fields are required if career status is 'Student'",
|
|
164
|
-
"solution": "Select 'Professional (post grad)' career status to bypass school-required fields entirely",
|
|
165
|
-
"severity": "medium"
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
"error": "Project name save button hidden or disabled",
|
|
169
|
-
"context": "The #software_name_save_button may be display:none",
|
|
170
|
-
"solution": "Set saveBtn.style.display = 'inline-block' and saveBtn.disabled = false before clicking. Or submit the form directly.",
|
|
171
|
-
"severity": "medium"
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
"error": "Tab/window coordinate mismatch for click",
|
|
175
|
-
"context": "CDP targets a tab but native click targets screen coordinates — if Chrome shows a different tab, clicks hit wrong content",
|
|
176
|
-
"solution": "Always use browser_click or browser_human_click with CSS selector instead of native click with coordinates. Or ensure correct tab is focused with browser_navigate first.",
|
|
177
|
-
"severity": "high"
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
"error": "navigator.webdriver detected by site",
|
|
181
|
-
"context": "Sites with anti-bot detection check this flag",
|
|
182
|
-
"solution": "Call browser_stealth tool once after navigating to the site. It hides webdriver flag and patches plugins/languages/permissions.",
|
|
183
|
-
"severity": "high"
|
|
184
|
-
}
|
|
185
|
-
]
|
|
186
|
-
}
|
package/playbooks/instagram.json
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"platform": "instagram",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"updated": "2026-03-05",
|
|
5
|
-
"description": "Instagram platform knowledge discovered via Screenhand exploration",
|
|
6
|
-
"urls": {
|
|
7
|
-
"home": "https://www.instagram.com/",
|
|
8
|
-
"accounts_activity_": "https://www.instagram.com/accounts/activity/",
|
|
9
|
-
"accounts_center_": "https://www.instagram.com/accounts/center/",
|
|
10
|
-
"accounts_edit_": "https://www.instagram.com/accounts/edit/",
|
|
11
|
-
"accounts_emailsignup_": "https://www.instagram.com/accounts/emailsignup/",
|
|
12
|
-
"create_select_": "https://www.instagram.com/create/select/",
|
|
13
|
-
"direct_inbox_": "https://www.instagram.com/direct/inbox/",
|
|
14
|
-
"explore_": "https://www.instagram.com/explore/",
|
|
15
|
-
"notifications_": "https://www.instagram.com/notifications/",
|
|
16
|
-
"professional_dashboard_": "https://www.instagram.com/professional_dashboard/",
|
|
17
|
-
"reels_": "https://www.instagram.com/reels/",
|
|
18
|
-
"reels_DVEhlImkuX5_": "https://www.instagram.com/reels/DVEhlImkuX5/",
|
|
19
|
-
"reels_DVOV4_KjRVo_": "https://www.instagram.com/reels/DVOV4_KjRVo/",
|
|
20
|
-
"reels_DVc8QemCByv_": "https://www.instagram.com/reels/DVc8QemCByv/"
|
|
21
|
-
},
|
|
22
|
-
"flows": {
|
|
23
|
-
"discovered": {
|
|
24
|
-
"steps": [
|
|
25
|
-
"No strategies recorded yet. Use the platform, then call export_playbook again."
|
|
26
|
-
],
|
|
27
|
-
"selectors": {
|
|
28
|
-
"switch_display_language": "[aria-label=\"Switch Display Language\"]"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
"detection": {
|
|
33
|
-
"is_logged_in": "// Add detection JS for logged-in state"
|
|
34
|
-
},
|
|
35
|
-
"errors": [],
|
|
36
|
-
"_meta": {
|
|
37
|
-
"exported_from": "screenhand",
|
|
38
|
-
"actions_count": 31,
|
|
39
|
-
"strategies_count": 0
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"platform": "instagram",
|
|
3
|
-
"playbook": "instagram_v2",
|
|
4
|
-
"version": "2.0.0",
|
|
5
|
-
"updated": "2026-03-05",
|
|
6
|
-
"description": "Instagram Web automation playbook with verified selectors from a live logged-in session.",
|
|
7
|
-
"urls": {
|
|
8
|
-
"home": "https://www.instagram.com/",
|
|
9
|
-
"reels": "https://www.instagram.com/reels/",
|
|
10
|
-
"messages": "https://www.instagram.com/direct/inbox/",
|
|
11
|
-
"notifications": "https://www.instagram.com/notifications/",
|
|
12
|
-
"edit_profile": "https://www.instagram.com/accounts/edit/"
|
|
13
|
-
},
|
|
14
|
-
"selectors": {
|
|
15
|
-
"navigation": {
|
|
16
|
-
"home": "a[href='/']",
|
|
17
|
-
"reels": "a[href='/reels/']",
|
|
18
|
-
"messages": "a[href='/direct/inbox/']",
|
|
19
|
-
"explore": "a[href='/explore/']",
|
|
20
|
-
"notifications": "a[href='/notifications/'], a[href='/accounts/activity/']",
|
|
21
|
-
"create_href": "a[href='/create/']",
|
|
22
|
-
"create_text_fallback": "a,button,[role='button'] (text=/new post|create/i)",
|
|
23
|
-
"profile_generic": "a[href^='/'][href$='/'] (exclude known static routes)"
|
|
24
|
-
},
|
|
25
|
-
"engagement": {
|
|
26
|
-
"like": "[aria-label='Like'], svg[aria-label='Like']",
|
|
27
|
-
"comment": "[aria-label='Comment'], svg[aria-label='Comment']",
|
|
28
|
-
"share": "[aria-label='Share'], [aria-label='Send'], svg[aria-label='Share']",
|
|
29
|
-
"save": "[aria-label='Save'], svg[aria-label='Save']",
|
|
30
|
-
"follow_text": "button,[role='button'] (text=/^Follow$/i)",
|
|
31
|
-
"comment_input": "textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…'], textarea[placeholder*='comment']"
|
|
32
|
-
},
|
|
33
|
-
"dm": {
|
|
34
|
-
"search_input": "input[name='searchInput'], input[placeholder='Search'], input[aria-label='Search input']",
|
|
35
|
-
"new_message": "a[href='/direct/new/'], [aria-label='New message'], button[aria-label='New message']",
|
|
36
|
-
"composer_fallback": "textarea[placeholder*='Message'], div[contenteditable='true'][role='textbox']"
|
|
37
|
-
},
|
|
38
|
-
"settings": {
|
|
39
|
-
"website": "input[placeholder='Website']",
|
|
40
|
-
"bio": "textarea#pepBio, textarea[placeholder='Bio']",
|
|
41
|
-
"submit": "button[type='submit']",
|
|
42
|
-
"avatar_file": "input[type='file']",
|
|
43
|
-
"account_suggestions_toggle": "input[role='switch'][aria-label='Show account suggestions on profiles']"
|
|
44
|
-
},
|
|
45
|
-
"create_post": {
|
|
46
|
-
"trigger": "a,button,[role='button'] (text=/new post|create/i)",
|
|
47
|
-
"file_input": "input[type='file']",
|
|
48
|
-
"caption": "textarea[aria-label*='caption' i], textarea[placeholder*='caption' i]",
|
|
49
|
-
"next": "button (text=/^Next$/i)",
|
|
50
|
-
"share": "button (text=/^Share$/i)"
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
"flows": {
|
|
54
|
-
"create_post": {
|
|
55
|
-
"steps": [
|
|
56
|
-
"Navigate to home URL.",
|
|
57
|
-
"Click create trigger by text match (new post/create).",
|
|
58
|
-
"Upload media via input[type='file'].",
|
|
59
|
-
"Fill caption field.",
|
|
60
|
-
"Click Next, then Share."
|
|
61
|
-
],
|
|
62
|
-
"selectors": {
|
|
63
|
-
"entry": "a,button,[role='button'] (text=/new post|create/i)",
|
|
64
|
-
"file_input": "input[type='file']",
|
|
65
|
-
"caption": "textarea[aria-label*='caption' i], textarea[placeholder*='caption' i]",
|
|
66
|
-
"next": "button (text=/^Next$/i)",
|
|
67
|
-
"share": "button (text=/^Share$/i)"
|
|
68
|
-
},
|
|
69
|
-
"notes": [
|
|
70
|
-
"Do not rely on /create/select/ directly; it can resolve to @create profile in some sessions.",
|
|
71
|
-
"Prefer text-based create trigger from left nav when href selector is absent."
|
|
72
|
-
]
|
|
73
|
-
},
|
|
74
|
-
"reel_engagement": {
|
|
75
|
-
"steps": [
|
|
76
|
-
"Navigate to reels URL.",
|
|
77
|
-
"Use like/comment/share/save selectors on active reel.",
|
|
78
|
-
"Use follow_text selector for creator follow button."
|
|
79
|
-
],
|
|
80
|
-
"selectors": {
|
|
81
|
-
"like": "[aria-label='Like'], svg[aria-label='Like']",
|
|
82
|
-
"comment": "[aria-label='Comment'], svg[aria-label='Comment']",
|
|
83
|
-
"share": "[aria-label='Share'], [aria-label='Send'], svg[aria-label='Share']",
|
|
84
|
-
"save": "[aria-label='Save'], svg[aria-label='Save']",
|
|
85
|
-
"follow_text": "button,[role='button'] (text=/^Follow$/i)"
|
|
86
|
-
}
|
|
87
|
-
},
|
|
88
|
-
"dm_send_message": {
|
|
89
|
-
"steps": [
|
|
90
|
-
"Navigate to messages URL.",
|
|
91
|
-
"Use dm.search_input to find recipient.",
|
|
92
|
-
"Click dm.new_message if inbox is empty.",
|
|
93
|
-
"Type in dm.composer_fallback once thread opens."
|
|
94
|
-
],
|
|
95
|
-
"selectors": {
|
|
96
|
-
"search_input": "input[name='searchInput'], input[placeholder='Search'], input[aria-label='Search input']",
|
|
97
|
-
"new_message": "a[href='/direct/new/'], [aria-label='New message'], button[aria-label='New message']",
|
|
98
|
-
"composer_fallback": "textarea[placeholder*='Message'], div[contenteditable='true'][role='textbox']"
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
"comment_on_post": {
|
|
102
|
-
"steps": [
|
|
103
|
-
"On home/reels, click engagement.comment selector.",
|
|
104
|
-
"Wait for post page/dialog to open.",
|
|
105
|
-
"Type into engagement.comment_input and submit."
|
|
106
|
-
],
|
|
107
|
-
"selectors": {
|
|
108
|
-
"comment_button": "[aria-label='Comment'], svg[aria-label='Comment']",
|
|
109
|
-
"comment_input": "textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…'], textarea[placeholder*='comment']"
|
|
110
|
-
},
|
|
111
|
-
"notes": [
|
|
112
|
-
"Verified path opened https://www.instagram.com/p/... and exposed aria-label='Add a comment…'."
|
|
113
|
-
]
|
|
114
|
-
},
|
|
115
|
-
"follow_account": {
|
|
116
|
-
"steps": [
|
|
117
|
-
"Use follow_text (text=/^Follow$/i) on feed/reels/profile context.",
|
|
118
|
-
"Avoid class-based selectors; they are unstable."
|
|
119
|
-
],
|
|
120
|
-
"selectors": {
|
|
121
|
-
"follow_text": "button,[role='button'] (text=/^Follow$/i)"
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
"update_profile_settings": {
|
|
125
|
-
"steps": [
|
|
126
|
-
"Navigate to edit_profile URL.",
|
|
127
|
-
"Set settings.website and settings.bio.",
|
|
128
|
-
"Submit via settings.submit (type='submit')."
|
|
129
|
-
],
|
|
130
|
-
"selectors": {
|
|
131
|
-
"website": "input[placeholder='Website']",
|
|
132
|
-
"bio": "textarea#pepBio, textarea[placeholder='Bio']",
|
|
133
|
-
"submit": "button[type='submit']"
|
|
134
|
-
},
|
|
135
|
-
"notes": [
|
|
136
|
-
"Verified on Edit profile page title: 'Edit profile • Instagram'."
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
},
|
|
140
|
-
"detection": {
|
|
141
|
-
"is_logged_in": "!!document.querySelector(\"a[href='/direct/inbox/']\")",
|
|
142
|
-
"on_home": "location.pathname === '/'",
|
|
143
|
-
"on_reels": "location.pathname.startsWith('/reels')",
|
|
144
|
-
"on_messages": "location.pathname.startsWith('/direct/inbox')",
|
|
145
|
-
"on_notifications": "location.pathname.startsWith('/notifications')",
|
|
146
|
-
"on_edit_profile": "location.pathname.startsWith('/accounts/edit')",
|
|
147
|
-
"has_comment_input": "!!document.querySelector(\"textarea[aria-label='Add a comment…'], textarea[placeholder='Add a comment…']\")"
|
|
148
|
-
},
|
|
149
|
-
"errors": [
|
|
150
|
-
{
|
|
151
|
-
"error": "Create route resolves to profile @create instead of composer",
|
|
152
|
-
"context": "Direct open of /create/select/ in this session",
|
|
153
|
-
"solution": "Use UI create trigger by text (new post/create) from home navigation.",
|
|
154
|
-
"severity": "high"
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"error": "Notifications nav href not always present in left rail",
|
|
158
|
-
"context": "Selector a[href='/notifications/'] may be absent",
|
|
159
|
-
"solution": "Navigate directly to /notifications/ or click Notifications by text/aria.",
|
|
160
|
-
"severity": "medium"
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
"error": "Follow button lacks stable unique CSS attributes",
|
|
164
|
-
"context": "Follow discovered as plain button text in multiple contexts",
|
|
165
|
-
"solution": "Use text-based matcher: button,[role='button'] with /^Follow$/i.",
|
|
166
|
-
"severity": "medium"
|
|
167
|
-
}
|
|
168
|
-
],
|
|
169
|
-
"verification": {
|
|
170
|
-
"audit_date": "2026-03-05",
|
|
171
|
-
"home": {
|
|
172
|
-
"like_count": 3,
|
|
173
|
-
"comment_count": 3,
|
|
174
|
-
"share_count": 3,
|
|
175
|
-
"save_count": 3,
|
|
176
|
-
"follow_text_buttons": 8,
|
|
177
|
-
"create_by_text": true
|
|
178
|
-
},
|
|
179
|
-
"reels": {
|
|
180
|
-
"like_count": 2,
|
|
181
|
-
"comment_count": 2,
|
|
182
|
-
"share_count": 2,
|
|
183
|
-
"save_count": 2,
|
|
184
|
-
"follow_text_buttons": 2
|
|
185
|
-
},
|
|
186
|
-
"messages": {
|
|
187
|
-
"search_input_present": true,
|
|
188
|
-
"new_message_present": true
|
|
189
|
-
},
|
|
190
|
-
"edit_profile": {
|
|
191
|
-
"website_present": true,
|
|
192
|
-
"bio_present": true,
|
|
193
|
-
"submit_type_button_present": true
|
|
194
|
-
},
|
|
195
|
-
"comment_flow": {
|
|
196
|
-
"comment_click_result": "Clicked: \"Comment\"",
|
|
197
|
-
"comment_input_present_after_click": true,
|
|
198
|
-
"comment_page_pattern": "https://www.instagram.com/p/..."
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
package/playbooks/x_v1.json
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"platform": "x",
|
|
3
|
-
"playbook": "x_v1",
|
|
4
|
-
"version": "1.0.0",
|
|
5
|
-
"updated": "2026-03-06",
|
|
6
|
-
"description": "X (Twitter) web automation playbook for ScreenHand using Chrome CDP + OCR fallback.",
|
|
7
|
-
"urls": {
|
|
8
|
-
"home": "https://x.com/home",
|
|
9
|
-
"explore": "https://x.com/explore",
|
|
10
|
-
"notifications": "https://x.com/notifications",
|
|
11
|
-
"messages": "https://x.com/messages",
|
|
12
|
-
"compose": "https://x.com/compose/post",
|
|
13
|
-
"profile": "https://x.com/{handle}",
|
|
14
|
-
"status": "https://x.com/{handle}/status/{status_id}",
|
|
15
|
-
"settings_profile": "https://x.com/settings/profile"
|
|
16
|
-
},
|
|
17
|
-
"selectors": {
|
|
18
|
-
"compose": {
|
|
19
|
-
"textbox_primary": "[data-testid='tweetTextarea_0']",
|
|
20
|
-
"textbox_fallback": "div[role='textbox'][contenteditable='true']",
|
|
21
|
-
"post_button_inline": "[data-testid='tweetButtonInline']",
|
|
22
|
-
"post_button_generic": "[data-testid='tweetButton']",
|
|
23
|
-
"media_input": "[data-testid='fileInput'], input[type='file']"
|
|
24
|
-
},
|
|
25
|
-
"engagement": {
|
|
26
|
-
"reply": "[data-testid='reply']",
|
|
27
|
-
"like": "[data-testid='like']",
|
|
28
|
-
"unlike": "[data-testid='unlike']",
|
|
29
|
-
"repost": "[data-testid='retweet']",
|
|
30
|
-
"unrepost": "[data-testid='unretweet']",
|
|
31
|
-
"bookmark": "[data-testid='bookmark']",
|
|
32
|
-
"remove_bookmark": "[data-testid='removeBookmark']"
|
|
33
|
-
},
|
|
34
|
-
"post_menu": {
|
|
35
|
-
"open": "[data-testid='caret'], button[aria-label='More']",
|
|
36
|
-
"menu": "[role='menu']",
|
|
37
|
-
"menu_item": "[role='menuitem']",
|
|
38
|
-
"delete_item_text": "Delete",
|
|
39
|
-
"edit_item_text": "Edit"
|
|
40
|
-
},
|
|
41
|
-
"delete_confirm": {
|
|
42
|
-
"primary": "[data-testid='confirmationSheetConfirm']",
|
|
43
|
-
"dialog": "[role='dialog']",
|
|
44
|
-
"button_text": "Delete"
|
|
45
|
-
},
|
|
46
|
-
"edit": {
|
|
47
|
-
"editor": "[data-testid='tweetTextarea_0'], div[role='textbox'][contenteditable='true']",
|
|
48
|
-
"submit_update_or_save": "button matching /update|save/i",
|
|
49
|
-
"must_not_click": "button matching /reply/i"
|
|
50
|
-
},
|
|
51
|
-
"dm": {
|
|
52
|
-
"new_message": "[data-testid='DM_New_Direct_Message_Button'], a[href='/messages/compose'], [aria-label*='New message']",
|
|
53
|
-
"search_people": "input[data-testid='searchPeople'], input[placeholder*='Search'], input[aria-label*='Search']",
|
|
54
|
-
"composer": "[data-testid='dmComposerTextInput'], div[role='textbox'][data-testid='dmComposerTextInput'], div[role='textbox'][contenteditable='true']",
|
|
55
|
-
"send": "[data-testid='dmComposerSendButton'], [aria-label='Send']"
|
|
56
|
-
},
|
|
57
|
-
"profile": {
|
|
58
|
-
"edit_profile_button_text": "Edit profile",
|
|
59
|
-
"name_input_label": "Name",
|
|
60
|
-
"bio_input_label": "Bio",
|
|
61
|
-
"location_input_label": "Location",
|
|
62
|
-
"website_input_label": "Website",
|
|
63
|
-
"save_profile": "[data-testid='Profile_Save_Button']"
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
"flows": {
|
|
67
|
-
"create_post": {
|
|
68
|
-
"steps": [
|
|
69
|
-
"Focus Chrome and use browser_tabs to get current X tab.",
|
|
70
|
-
"Navigate to compose URL or home.",
|
|
71
|
-
"Prefer CDP: fill [data-testid='tweetTextarea_0'] then click [data-testid='tweetButtonInline'].",
|
|
72
|
-
"Fallback: click_text('What's happening?'), type_text, key('cmd+enter').",
|
|
73
|
-
"Verify by opening profile and reading latest /status/{id} link."
|
|
74
|
-
],
|
|
75
|
-
"guards": [
|
|
76
|
-
"If X returns 'Whoops! You already said that.', regenerate unique copy and repost.",
|
|
77
|
-
"If type_text times out on long text, shorten copy and retry.",
|
|
78
|
-
"Keep one active Chrome window; avoid about:blank target drift."
|
|
79
|
-
]
|
|
80
|
-
},
|
|
81
|
-
"replace_post_without_premium": {
|
|
82
|
-
"steps": [
|
|
83
|
-
"Open target status URL.",
|
|
84
|
-
"Open post menu (caret).",
|
|
85
|
-
"Click Delete and then confirm Delete in modal.",
|
|
86
|
-
"Create a fresh replacement post from compose.",
|
|
87
|
-
"Optionally pin replacement post."
|
|
88
|
-
],
|
|
89
|
-
"why": "Non-Premium accounts cannot edit posts reliably; delete+repost is the primary workflow."
|
|
90
|
-
},
|
|
91
|
-
"edit_post_premium_only": {
|
|
92
|
-
"steps": [
|
|
93
|
-
"Open target status URL and open post menu.",
|
|
94
|
-
"Click 'Edit'.",
|
|
95
|
-
"Replace content in edit editor.",
|
|
96
|
-
"Submit only via button text matching Update/Save.",
|
|
97
|
-
"Reload status URL and verify updated text."
|
|
98
|
-
],
|
|
99
|
-
"guards": [
|
|
100
|
-
"Abort if no Update/Save button is detected.",
|
|
101
|
-
"Do not click Reply when intending to edit.",
|
|
102
|
-
"Edit availability is restricted by account plan and post state."
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
|
-
"delete_post": {
|
|
106
|
-
"steps": [
|
|
107
|
-
"Open target status URL.",
|
|
108
|
-
"Open post menu and click Delete.",
|
|
109
|
-
"Confirm via [data-testid='confirmationSheetConfirm'] or dialog Delete button.",
|
|
110
|
-
"Reload status URL and verify deleted marker text."
|
|
111
|
-
],
|
|
112
|
-
"verification_text_patterns": [
|
|
113
|
-
"this post was deleted",
|
|
114
|
-
"post not found",
|
|
115
|
-
"doesn't exist",
|
|
116
|
-
"try searching for something else"
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
|
-
"engagement_actions": {
|
|
120
|
-
"steps": [
|
|
121
|
-
"Like: click [data-testid='like'].",
|
|
122
|
-
"Reply: click [data-testid='reply'], fill composer, click tweetButtonInline.",
|
|
123
|
-
"Repost: click [data-testid='retweet'] and choose repost option.",
|
|
124
|
-
"Bookmark: click [data-testid='bookmark']."
|
|
125
|
-
]
|
|
126
|
-
},
|
|
127
|
-
"dm_send": {
|
|
128
|
-
"steps": [
|
|
129
|
-
"Navigate to /messages.",
|
|
130
|
-
"Click new message button.",
|
|
131
|
-
"Search recipient.",
|
|
132
|
-
"Type in DM composer.",
|
|
133
|
-
"Send via dmComposerSendButton."
|
|
134
|
-
]
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
"detection": {
|
|
138
|
-
"is_logged_in": "!/log in|sign in|join x|create account/i.test((document.body?.innerText||''))",
|
|
139
|
-
"on_compose": "location.href.includes('/compose/post')",
|
|
140
|
-
"on_messages": "location.pathname.startsWith('/messages')",
|
|
141
|
-
"has_compose_box": "!!document.querySelector('[data-testid=\"tweetTextarea_0\"], div[role=\"textbox\"][contenteditable=\"true\"]')",
|
|
142
|
-
"has_post_menu_caret": "document.querySelectorAll('[data-testid=\"caret\"], button[aria-label=\"More\"]').length > 0",
|
|
143
|
-
"has_delete_confirm": "!!document.querySelector('[data-testid=\"confirmationSheetConfirm\"], [role=\"dialog\"]')"
|
|
144
|
-
},
|
|
145
|
-
"errors": [
|
|
146
|
-
{
|
|
147
|
-
"error": "Edit option missing",
|
|
148
|
-
"context": "Post menu shows Delete/Pin/etc but no Edit",
|
|
149
|
-
"solution": "Treat as non-editable; use delete+repost flow.",
|
|
150
|
-
"severity": "high"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"error": "Reply clicked instead of update",
|
|
154
|
-
"context": "Edit flow opened composer-like surface and submit hit Reply",
|
|
155
|
-
"solution": "Submit only when button label matches Update/Save; abort otherwise.",
|
|
156
|
-
"severity": "high"
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
"error": "Duplicate post rejection",
|
|
160
|
-
"context": "X message: 'Whoops! You already said that.'",
|
|
161
|
-
"solution": "Regenerate unique copy and retry post.",
|
|
162
|
-
"severity": "medium"
|
|
163
|
-
},
|
|
164
|
-
{
|
|
165
|
-
"error": "about:blank window steals OCR clicks",
|
|
166
|
-
"context": "Multiple Chrome windows; OCR target drifts to about:blank",
|
|
167
|
-
"solution": "Close/ignore about:blank window and bind to X-titled window before click_text/type_text.",
|
|
168
|
-
"severity": "high"
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"error": "CDP DOM missing tweet controls",
|
|
172
|
-
"context": "No article/caret nodes despite visible tweet in UI",
|
|
173
|
-
"solution": "Fallback to OCR+Accessibility sequence; then return to CDP for verification.",
|
|
174
|
-
"severity": "high"
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
"error": "type_text timeout on long content",
|
|
178
|
-
"context": "Bridge timeout on long multiline posts",
|
|
179
|
-
"solution": "Use shorter copy or DOM insert in editor where available.",
|
|
180
|
-
"severity": "medium"
|
|
181
|
-
}
|
|
182
|
-
],
|
|
183
|
-
"policy_notes": {
|
|
184
|
-
"editing": [
|
|
185
|
-
"Editing requires X Premium tier support.",
|
|
186
|
-
"Editing is time-limited and state-limited (post history/reply state may block edit).",
|
|
187
|
-
"Without edit capability, use delete+repost."
|
|
188
|
-
],
|
|
189
|
-
"safety": [
|
|
190
|
-
"Always verify target status URL before destructive actions.",
|
|
191
|
-
"Never auto-confirm delete without detecting delete dialog/button.",
|
|
192
|
-
"Never use Reply button as edit submit fallback."
|
|
193
|
-
]
|
|
194
|
-
},
|
|
195
|
-
"verification": {
|
|
196
|
-
"audit_date": "2026-03-06",
|
|
197
|
-
"account": "@screenhand_",
|
|
198
|
-
"known_post_ids": [
|
|
199
|
-
"2029617823178424794",
|
|
200
|
-
"2029620157203763699"
|
|
201
|
-
],
|
|
202
|
-
"observed_menu_items": [
|
|
203
|
-
"Delete",
|
|
204
|
-
"Edit",
|
|
205
|
-
"Pin to your profile",
|
|
206
|
-
"Highlight on your profile",
|
|
207
|
-
"View post analytics"
|
|
208
|
-
],
|
|
209
|
-
"known_rejection_message": "Whoops! You already said that."
|
|
210
|
-
}
|
|
211
|
-
}
|