Skip to content

Commit 854cf01

Browse files
hanziliclaudejackwener
authored
feat(linkedin): add messaging commands (#1597)
* feat(linkedin): add messaging commands Add fail-closed LinkedIn inbox, connect, safe-send, and thread-snapshot commands with adapter tests and docs. * fix(linkedin): align commands with current UI Update inbox to read LinkedIn's normalized messaging API response and connect to use the current custom-invite route. * chore(linkedin): sync cli-manifest.json with rebuilt inbox command Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(linkedin): pass silent-column-drop gate Drop the intermediate timestamp_ms field from inbox rows (it is converted to the timestamp column) and baseline the connect command internal profile-probe object. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(linkedin): validate inbox --limit with a typed error Reject an out-of-range --limit with ArgumentError instead of silently clamping it, satisfying the typed-error lint gate. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(linkedin): harden messaging command contracts * fix(linkedin): reject inbox conversations without thread id --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: jackwener <jakevingoo@gmail.com>
1 parent baf1522 commit 854cf01

11 files changed

Lines changed: 1892 additions & 10 deletions

File tree

cli-manifest.json

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14343,6 +14343,162 @@
1434314343
"modulePath": "lichess/user.js",
1434414344
"sourceFile": "lichess/user.js"
1434514345
},
14346+
{
14347+
"site": "linkedin",
14348+
"name": "connect",
14349+
"description": "Fail-closed LinkedIn connection request sender that verifies the exact profile before optionally sending a note",
14350+
"access": "write",
14351+
"domain": "www.linkedin.com",
14352+
"strategy": "ui",
14353+
"browser": true,
14354+
"args": [
14355+
{
14356+
"name": "profile-url",
14357+
"type": "string",
14358+
"required": true,
14359+
"positional": true,
14360+
"help": "Exact LinkedIn profile URL to open and verify"
14361+
},
14362+
{
14363+
"name": "expected-name",
14364+
"type": "string",
14365+
"required": true,
14366+
"help": "Expected visible profile name"
14367+
},
14368+
{
14369+
"name": "note",
14370+
"type": "string",
14371+
"default": "",
14372+
"required": false,
14373+
"help": "Optional connection note, max 300 chars"
14374+
},
14375+
{
14376+
"name": "send",
14377+
"type": "bool",
14378+
"default": false,
14379+
"required": false,
14380+
"help": "Actually click Send. Default is dry-run verification only."
14381+
}
14382+
],
14383+
"columns": [
14384+
"status",
14385+
"recipient",
14386+
"reason",
14387+
"profile_url",
14388+
"note_chars"
14389+
],
14390+
"type": "js",
14391+
"modulePath": "linkedin/connect.js",
14392+
"sourceFile": "linkedin/connect.js",
14393+
"navigateBefore": true
14394+
},
14395+
{
14396+
"site": "linkedin",
14397+
"name": "inbox",
14398+
"description": "List LinkedIn messaging inbox conversations and unread messages",
14399+
"access": "read",
14400+
"domain": "www.linkedin.com",
14401+
"strategy": "cookie",
14402+
"browser": true,
14403+
"args": [
14404+
{
14405+
"name": "limit",
14406+
"type": "int",
14407+
"default": 40,
14408+
"required": false,
14409+
"help": "Maximum conversations to return (1-100)"
14410+
},
14411+
{
14412+
"name": "unread-only",
14413+
"type": "bool",
14414+
"default": false,
14415+
"required": false,
14416+
"help": "Return only conversations with unread messages"
14417+
}
14418+
],
14419+
"columns": [
14420+
"rank",
14421+
"thread_url",
14422+
"thread_id",
14423+
"person_name",
14424+
"last_message_preview",
14425+
"unread",
14426+
"counterparty_type",
14427+
"category",
14428+
"timestamp"
14429+
],
14430+
"type": "js",
14431+
"modulePath": "linkedin/inbox.js",
14432+
"sourceFile": "linkedin/inbox.js",
14433+
"navigateBefore": "https://www.linkedin.com"
14434+
},
14435+
{
14436+
"site": "linkedin",
14437+
"name": "safe-send",
14438+
"description": "Fail-closed LinkedIn message sender that verifies exact thread, recipient, and latest message before filling/sending",
14439+
"access": "write",
14440+
"domain": "www.linkedin.com",
14441+
"strategy": "ui",
14442+
"browser": true,
14443+
"args": [
14444+
{
14445+
"name": "thread-url",
14446+
"type": "str",
14447+
"required": true,
14448+
"help": "Exact LinkedIn messaging thread URL to open and verify"
14449+
},
14450+
{
14451+
"name": "expected-name",
14452+
"type": "str",
14453+
"required": true,
14454+
"help": "Expected visible recipient name in the active thread header"
14455+
},
14456+
{
14457+
"name": "message",
14458+
"type": "str",
14459+
"required": true,
14460+
"help": "Message body to send or dry-run"
14461+
},
14462+
{
14463+
"name": "expected-last-text",
14464+
"type": "str",
14465+
"required": false,
14466+
"help": "Substring expected in the currently visible latest conversation context"
14467+
},
14468+
{
14469+
"name": "expected-last-hash",
14470+
"type": "str",
14471+
"required": false,
14472+
"help": "SHA-256 hash of expected latest visible message text"
14473+
},
14474+
{
14475+
"name": "send",
14476+
"type": "bool",
14477+
"default": false,
14478+
"required": false,
14479+
"help": "Actually click Send. Default is dry-run verification only."
14480+
},
14481+
{
14482+
"name": "screenshot",
14483+
"type": "bool",
14484+
"default": false,
14485+
"required": false,
14486+
"help": "Capture a screenshot during verification"
14487+
}
14488+
],
14489+
"columns": [
14490+
"status",
14491+
"recipient",
14492+
"reason",
14493+
"thread_url",
14494+
"message_chars",
14495+
"screenshot"
14496+
],
14497+
"type": "js",
14498+
"modulePath": "linkedin/safe-send.js",
14499+
"sourceFile": "linkedin/safe-send.js",
14500+
"navigateBefore": true
14501+
},
1434614502
{
1434714503
"site": "linkedin",
1434814504
"name": "search",
@@ -14431,6 +14587,48 @@
1443114587
"sourceFile": "linkedin/search.js",
1443214588
"navigateBefore": "https://www.linkedin.com"
1443314589
},
14590+
{
14591+
"site": "linkedin",
14592+
"name": "thread-snapshot",
14593+
"description": "Load a LinkedIn messaging thread, scroll for available history, and return a full context snapshot",
14594+
"access": "read",
14595+
"domain": "www.linkedin.com",
14596+
"strategy": "ui",
14597+
"browser": true,
14598+
"args": [
14599+
{
14600+
"name": "thread-url",
14601+
"type": "str",
14602+
"required": true,
14603+
"help": "Exact LinkedIn messaging thread URL to open and snapshot"
14604+
},
14605+
{
14606+
"name": "max-scrolls",
14607+
"type": "number",
14608+
"default": 30,
14609+
"required": false,
14610+
"help": "Maximum upward scroll attempts to load older messages"
14611+
},
14612+
{
14613+
"name": "json",
14614+
"type": "bool",
14615+
"default": false,
14616+
"required": false,
14617+
"help": "Return only JSON snapshot string in the snapshot_json field"
14618+
}
14619+
],
14620+
"columns": [
14621+
"thread_url",
14622+
"recipient",
14623+
"message_count",
14624+
"latest_text",
14625+
"snapshot_json"
14626+
],
14627+
"type": "js",
14628+
"modulePath": "linkedin/thread-snapshot.js",
14629+
"sourceFile": "linkedin/thread-snapshot.js",
14630+
"navigateBefore": true
14631+
},
1443414632
{
1443514633
"site": "linkedin",
1443614634
"name": "timeline",

0 commit comments

Comments
 (0)