@floomhq/signaldash 0.39.19 → 0.41.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 +92 -14
- package/bin/sd.mjs +385 -26
- package/lib/x-signal-collector.cjs +257 -0
- package/package.json +3 -2
- package/scripts/collect-x-signals.mjs +133 -0
- package/skills/signaldash/SKILL.md +68 -11
- package/skills/signaldash-safe-usage/SKILL.md +3 -2
package/bin/sd.mjs
CHANGED
|
@@ -423,6 +423,182 @@ const TOOLS = [
|
|
|
423
423
|
description: "Enable or disable the database-gated content pipeline. Enabling captures only new free text from the verified Secretary group. It never publishes or schedules a post.",
|
|
424
424
|
inputSchema: { type:"object",properties:{enabled:{type:"boolean"},confirm:{type:"boolean",const:true}},required:["enabled","confirm"],additionalProperties:false },
|
|
425
425
|
},
|
|
426
|
+
{
|
|
427
|
+
name: "sd_x_signal_set", path: "/sd/x-signals/set",
|
|
428
|
+
description: "Enable or disable the importer-only X signal review lane for this SignalDash user. The deployment-level capability must already be enabled. This starts no collector and makes zero provider calls.",
|
|
429
|
+
inputSchema: {
|
|
430
|
+
type: "object",
|
|
431
|
+
properties: { enabled: { type: "boolean" }, confirm: { type: "boolean", const: true } },
|
|
432
|
+
required: ["enabled", "confirm"],
|
|
433
|
+
additionalProperties: false,
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
{
|
|
437
|
+
name: "sd_x_signal_import", path: "/sd/x-signals/import",
|
|
438
|
+
description: "Import one already-collected X post into the read-only review lane with exact provenance and one engagement snapshot. SignalDash canonicalizes the X URL, deduplicates deterministically, and makes zero external calls.",
|
|
439
|
+
inputSchema: {
|
|
440
|
+
type: "object",
|
|
441
|
+
properties: {
|
|
442
|
+
feed: { type: "string", enum: ["fede", "rocketlist"] },
|
|
443
|
+
claim_key: { type: "string", pattern: "^[a-z0-9][a-z0-9._:/|-]{2,199}$" },
|
|
444
|
+
topic: { type: "string", minLength: 1, maxLength: 100 },
|
|
445
|
+
title: { type: "string", minLength: 1, maxLength: 1000 },
|
|
446
|
+
claim_text: { type: "string", minLength: 1, maxLength: 12000 },
|
|
447
|
+
why_now: { type: "string", minLength: 1, maxLength: 4000 },
|
|
448
|
+
editorial_angle: { type: "string", minLength: 1, maxLength: 4000 },
|
|
449
|
+
source: {
|
|
450
|
+
type: "object",
|
|
451
|
+
properties: {
|
|
452
|
+
url: { type: "string", minLength: 1, maxLength: 2048 },
|
|
453
|
+
author_handle: { type: "string", minLength: 1, maxLength: 50 },
|
|
454
|
+
author_or_publisher: { type: "string", minLength: 1, maxLength: 500 },
|
|
455
|
+
text: { type: "string", minLength: 1, maxLength: 65536 },
|
|
456
|
+
media_refs: { type: "array", maxItems: 20, items: { type: "string", minLength: 1, maxLength: 2048 } },
|
|
457
|
+
published_at: { type: "string", format: "date-time" },
|
|
458
|
+
fetched_at: { type: "string", format: "date-time" },
|
|
459
|
+
collector_kind: { type: "string", enum: ["manual_import", "apify_dataset_export"] },
|
|
460
|
+
collector_actor_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
461
|
+
collector_actor_build_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
462
|
+
collector_actor_build_number: { type: "string", minLength: 1, maxLength: 100 },
|
|
463
|
+
collector_run_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
464
|
+
collector_dataset_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
465
|
+
collector_dataset_item_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
466
|
+
collector_dataset_item_index: { type: "integer", minimum: 0 },
|
|
467
|
+
collector_registry_version: { type: "string", minLength: 1, maxLength: 100 },
|
|
468
|
+
collector_query_id: { type: "string", minLength: 1, maxLength: 100 },
|
|
469
|
+
collector_input_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
470
|
+
collector_initiated_by: { type: "string", minLength: 1, maxLength: 100 },
|
|
471
|
+
raw_record_json: { type: "string", minLength: 2, maxLength: 131072 },
|
|
472
|
+
raw_record_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
473
|
+
},
|
|
474
|
+
required: ["url", "author_or_publisher", "text", "published_at"],
|
|
475
|
+
additionalProperties: false,
|
|
476
|
+
},
|
|
477
|
+
snapshot: {
|
|
478
|
+
type: "object",
|
|
479
|
+
properties: {
|
|
480
|
+
captured_at: { type: "string", format: "date-time" },
|
|
481
|
+
likes: { type: ["integer", "null"], minimum: 0 },
|
|
482
|
+
reposts: { type: ["integer", "null"], minimum: 0 },
|
|
483
|
+
quotes: { type: ["integer", "null"], minimum: 0 },
|
|
484
|
+
replies: { type: ["integer", "null"], minimum: 0 },
|
|
485
|
+
views: { type: ["integer", "null"], minimum: 0 },
|
|
486
|
+
bookmarks: { type: ["integer", "null"], minimum: 0 },
|
|
487
|
+
collector_actor_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
488
|
+
collector_actor_build_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
489
|
+
collector_actor_build_number: { type: "string", minLength: 1, maxLength: 100 },
|
|
490
|
+
collector_run_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
491
|
+
collector_dataset_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
492
|
+
collector_dataset_item_index: { type: "integer", minimum: 0 },
|
|
493
|
+
collector_registry_version: { type: "string", minLength: 1, maxLength: 100 },
|
|
494
|
+
collector_query_id: { type: "string", minLength: 1, maxLength: 100 },
|
|
495
|
+
collector_input_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
496
|
+
collector_initiated_by: { type: "string", minLength: 1, maxLength: 100 },
|
|
497
|
+
raw_record_json: { type: "string", minLength: 2, maxLength: 131072 },
|
|
498
|
+
raw_record_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
499
|
+
provider_payload_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
500
|
+
},
|
|
501
|
+
required: ["captured_at"],
|
|
502
|
+
additionalProperties: false,
|
|
503
|
+
},
|
|
504
|
+
confirm: { type: "boolean", const: true },
|
|
505
|
+
},
|
|
506
|
+
required: ["feed", "claim_key", "topic", "title", "claim_text", "source", "snapshot", "confirm"],
|
|
507
|
+
additionalProperties: false,
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
name: "sd_x_signal_add_evidence", path: "/sd/x-signals/evidence",
|
|
512
|
+
description: "Append one immutable primary or reporting source to an X signal candidate. This stores supplied evidence only and fetches nothing.",
|
|
513
|
+
inputSchema: {
|
|
514
|
+
type: "object",
|
|
515
|
+
properties: {
|
|
516
|
+
id: { type: "string", minLength: 1, maxLength: 200 },
|
|
517
|
+
expected_version: { type: "integer", minimum: 0 },
|
|
518
|
+
source_kind: { type: "string", enum: ["primary", "reporting"] },
|
|
519
|
+
source: {
|
|
520
|
+
type: "object",
|
|
521
|
+
properties: {
|
|
522
|
+
url: { type: "string", minLength: 1, maxLength: 2048 },
|
|
523
|
+
provider_source_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
524
|
+
author_or_publisher: { type: "string", minLength: 1, maxLength: 500 },
|
|
525
|
+
text: { type: "string", minLength: 1, maxLength: 65536 },
|
|
526
|
+
media_refs: { type: "array", maxItems: 20, items: { type: "string", minLength: 1, maxLength: 2048 } },
|
|
527
|
+
published_at: { type: "string", format: "date-time" },
|
|
528
|
+
fetched_at: { type: "string", format: "date-time" },
|
|
529
|
+
collector_kind: { type: "string", enum: ["manual_import", "apify_dataset_export"] },
|
|
530
|
+
collector_actor_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
531
|
+
collector_run_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
532
|
+
collector_dataset_item_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
533
|
+
raw_record_sha256: { type: "string", pattern: "^[0-9a-f]{64}$" },
|
|
534
|
+
},
|
|
535
|
+
required: ["url", "author_or_publisher", "text"],
|
|
536
|
+
additionalProperties: false,
|
|
537
|
+
},
|
|
538
|
+
confirm: { type: "boolean", const: true },
|
|
539
|
+
},
|
|
540
|
+
required: ["id", "expected_version", "source_kind", "source", "confirm"],
|
|
541
|
+
additionalProperties: false,
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
name: "sd_x_signal_propose", path: "/sd/x-signals/propose",
|
|
546
|
+
description: "Store exact proposed LinkedIn copy plus a claim-to-source manifest for human verification. It creates no LinkedIn draft, schedule, or provider request.",
|
|
547
|
+
inputSchema: {
|
|
548
|
+
type: "object",
|
|
549
|
+
properties: {
|
|
550
|
+
id: { type: "string", minLength: 1, maxLength: 200 },
|
|
551
|
+
expected_version: { type: "integer", minimum: 0 },
|
|
552
|
+
proposed_text: { type: "string", minLength: 1, maxLength: 12000 },
|
|
553
|
+
proposed_claims: {
|
|
554
|
+
type: "array",
|
|
555
|
+
maxItems: 100,
|
|
556
|
+
items: {
|
|
557
|
+
type: "object",
|
|
558
|
+
properties: {
|
|
559
|
+
start: { type: "integer", minimum: 0 },
|
|
560
|
+
end: { type: "integer", minimum: 1 },
|
|
561
|
+
text: { type: "string", minLength: 1, maxLength: 12000 },
|
|
562
|
+
supporting_source_ids: { type: "array", maxItems: 20, items: { type: "string", minLength: 1, maxLength: 200 } },
|
|
563
|
+
source_excerpts: {
|
|
564
|
+
type: "array",
|
|
565
|
+
maxItems: 20,
|
|
566
|
+
items: {
|
|
567
|
+
type: "object",
|
|
568
|
+
properties: {
|
|
569
|
+
source_id: { type: "string", minLength: 1, maxLength: 200 },
|
|
570
|
+
excerpt: { type: "string", minLength: 1, maxLength: 65536 },
|
|
571
|
+
},
|
|
572
|
+
required: ["source_id", "excerpt"],
|
|
573
|
+
additionalProperties: false,
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
verdict: { type: "string", enum: ["supported", "contradicts", "missing"] },
|
|
577
|
+
},
|
|
578
|
+
required: ["start", "end", "text", "supporting_source_ids", "source_excerpts", "verdict"],
|
|
579
|
+
additionalProperties: false,
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
confirm: { type: "boolean", const: true },
|
|
583
|
+
},
|
|
584
|
+
required: ["id", "expected_version", "proposed_text", "proposed_claims", "confirm"],
|
|
585
|
+
additionalProperties: false,
|
|
586
|
+
},
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
name: "sd_x_signal_list", path: "/sd/x-signals/list",
|
|
590
|
+
description: "List one explicit Fede or RocketList X signal review queue with exact sources, snapshots, score components, proposal copy, and verification state. Makes zero provider calls.",
|
|
591
|
+
inputSchema: {
|
|
592
|
+
type: "object",
|
|
593
|
+
properties: {
|
|
594
|
+
feed: { type: "string", enum: ["fede", "rocketlist"] },
|
|
595
|
+
state: { type: "string", enum: ["all", "new", "shortlisted", "drafted", "approved", "changes_requested", "dismissed"] },
|
|
596
|
+
limit: { type: "integer", minimum: 1, maximum: 100 },
|
|
597
|
+
},
|
|
598
|
+
required: ["feed"],
|
|
599
|
+
additionalProperties: false,
|
|
600
|
+
},
|
|
601
|
+
},
|
|
426
602
|
{
|
|
427
603
|
name: "sd_content_pipeline_list", path: "/sd/content/list",
|
|
428
604
|
description: "Read the durable idea to measured state machine with zero provider calls.",
|
|
@@ -468,6 +644,33 @@ const TOOLS = [
|
|
|
468
644
|
description: "Generate the static board HTML from the same pipeline and stored shared-calendar rows. Makes zero provider calls.",
|
|
469
645
|
inputSchema: { type:"object",properties:{},additionalProperties:false },
|
|
470
646
|
},
|
|
647
|
+
{
|
|
648
|
+
name: "sd_content_automation_report", path: "/sd/content/automations/report",
|
|
649
|
+
description: "Record the latest lifecycle state of one account-scoped content automation for the SignalDash calendar. This reports status only and starts no scheduler, queue, publication, or provider request.",
|
|
650
|
+
inputSchema: {
|
|
651
|
+
type: "object",
|
|
652
|
+
properties: {
|
|
653
|
+
automation_key: { type: "string", pattern: "^[a-z0-9][a-z0-9._-]{2,79}$" },
|
|
654
|
+
name: { type: "string", minLength: 1, maxLength: 120 },
|
|
655
|
+
description: { type: "string", maxLength: 500 },
|
|
656
|
+
schedule: { type: "string", minLength: 1, maxLength: 240 },
|
|
657
|
+
state: { type: "string", enum: ["running", "success", "failed", "skipped"] },
|
|
658
|
+
detail: { type: "string", maxLength: 1000 },
|
|
659
|
+
step: { type: "string", maxLength: 120 },
|
|
660
|
+
next_run_at: { type: "string", format: "date-time" },
|
|
661
|
+
artifact_kind: { type: "string", enum: ["draft", "scheduled_post"] },
|
|
662
|
+
artifact_id: { type: "string", format: "uuid" },
|
|
663
|
+
confirm: { type: "boolean", const: true },
|
|
664
|
+
},
|
|
665
|
+
required: ["automation_key", "name", "schedule", "state", "confirm"],
|
|
666
|
+
additionalProperties: false,
|
|
667
|
+
},
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
name: "sd_content_automations", path: "/sd/content/automations/list",
|
|
671
|
+
description: "List the latest account-scoped content automation states rendered in the SignalDash calendar. Makes zero provider calls.",
|
|
672
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
673
|
+
},
|
|
471
674
|
{
|
|
472
675
|
name: "sd_inspiration_list",
|
|
473
676
|
path: "/sd/inspiration/list",
|
|
@@ -594,6 +797,21 @@ const TOOLS = [
|
|
|
594
797
|
additionalProperties: false,
|
|
595
798
|
},
|
|
596
799
|
},
|
|
800
|
+
{
|
|
801
|
+
name: "li_get_attachment",
|
|
802
|
+
path: "/li/get_attachment",
|
|
803
|
+
description: "Download one attachment (a PDF, image or other file) of one LinkedIn message in a chat this account owns and store it on the SignalDash host. Read the chat first with li_read_messages to obtain the exact message_id and attachment_id (the attachment's `id`, not its att:// url). Returns the stored path, mimetype, byte size, sha256 and file_name.",
|
|
804
|
+
inputSchema: {
|
|
805
|
+
type: "object",
|
|
806
|
+
properties: {
|
|
807
|
+
chat_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
808
|
+
message_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
809
|
+
attachment_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
810
|
+
},
|
|
811
|
+
required: ["chat_id", "message_id", "attachment_id"],
|
|
812
|
+
additionalProperties: false,
|
|
813
|
+
},
|
|
814
|
+
},
|
|
597
815
|
{
|
|
598
816
|
name: "li_mark_read",
|
|
599
817
|
ch: "li",
|
|
@@ -615,6 +833,7 @@ const TOOLS = [
|
|
|
615
833
|
inputSchema: {
|
|
616
834
|
type: "object",
|
|
617
835
|
properties: {
|
|
836
|
+
mark_read: { type: "boolean", default: true, description: "Clear unread after confirmed success; false preserves unread state." },
|
|
618
837
|
member_ids: { type: "array", minItems: 1, maxItems: 10, uniqueItems: true, items: { type: "string", minLength: 3, maxLength: 500, pattern: "^(?:ACo|ACw|AE)[A-Za-z0-9_-]+$" } },
|
|
619
838
|
text: { type: "string", minLength: 1, maxLength: 5000 },
|
|
620
839
|
confirm: { type: "boolean", default: false },
|
|
@@ -636,7 +855,7 @@ const TOOLS = [
|
|
|
636
855
|
chat_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
637
856
|
text: { type: "string", minLength: 1, maxLength: 5000 },
|
|
638
857
|
expected_watermark: { type: "string", minLength: 64, maxLength: 64, pattern: "^[0-9a-f]{64}$", description: "Bind the send to the exact current_watermark returned by the read or a thread_changed response." },
|
|
639
|
-
mark_read: { type: "boolean", default:
|
|
858
|
+
mark_read: { type: "boolean", default: true, description: "Clear unread after confirmed success; false preserves unread state." },
|
|
640
859
|
secretary_receipt_id: { type: "string", minLength: 1, maxLength: 200, description: "Single-use receipt from sd_secretary_approve. Pass this field alone." },
|
|
641
860
|
},
|
|
642
861
|
additionalProperties: false,
|
|
@@ -645,12 +864,14 @@ const TOOLS = [
|
|
|
645
864
|
{
|
|
646
865
|
name: "li_send_invitation",
|
|
647
866
|
path: "/li/send_invitation",
|
|
648
|
-
description: "Preview or send one exact LinkedIn invitation. First call without confirm, obtain approval, then repeat the exact provider_id and
|
|
867
|
+
description: "Preview or send one exact LinkedIn invitation. First call without confirm, obtain approval, then repeat the exact provider_id, note, follow_up and note_mode with confirm:true. DEFAULT: a note is NOT put on the invitation (free accounts get notes refused); the invitation goes out bare and the note text is sent once as the first message after the person is proven to have accepted. Set note_mode \"inline\" only when the note must ride on the invitation itself. The preview shows the exact follow-up text; list or cancel pending follow-ups with sd_invitation_followups / sd_invitation_followup_cancel.",
|
|
649
868
|
inputSchema: {
|
|
650
869
|
type: "object",
|
|
651
870
|
properties: {
|
|
652
871
|
provider_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
653
|
-
note: { type: "string", maxLength: 300 },
|
|
872
|
+
note: { type: "string", maxLength: 300, description: "With the default note_mode follow_up this text becomes the after-acceptance message; with note_mode inline it rides on the invitation." },
|
|
873
|
+
follow_up: { type: "string", minLength: 1, maxLength: 5000, description: "Exact message to send once after acceptance. Use instead of note (default mode), or alongside an inline note." },
|
|
874
|
+
note_mode: { type: "string", enum: ["follow_up", "inline"], default: "follow_up" },
|
|
654
875
|
confirm: { type: "boolean", default: false },
|
|
655
876
|
},
|
|
656
877
|
required: ["provider_id"],
|
|
@@ -1267,7 +1488,7 @@ const TOOLS = [
|
|
|
1267
1488
|
name: "wa_list_chats",
|
|
1268
1489
|
ch: "wa",
|
|
1269
1490
|
action: "list_chats",
|
|
1270
|
-
description: "List or search your WhatsApp chats. Resolved 1:1 chats expose the contact in both name and attendee_name; unresolved names stay null. A search reports exactly how far
|
|
1491
|
+
description: "List or search your WhatsApp chats. Resolved 1:1 chats expose the contact in both name and attendee_name; unresolved names stay null. A search checks SignalDash's local chat index first (built from paced chat-list pages, so it reaches old chats), then falls back to a bounded live scan; the response reports `search.source`, `search.index` coverage, and exactly how far any live scan went.",
|
|
1271
1492
|
inputSchema: {
|
|
1272
1493
|
type: "object",
|
|
1273
1494
|
properties: {
|
|
@@ -1342,12 +1563,14 @@ const TOOLS = [
|
|
|
1342
1563
|
{
|
|
1343
1564
|
name: "wa_start_chat",
|
|
1344
1565
|
path: "/wa/start_chat",
|
|
1345
|
-
description: "Preview or start one WhatsApp direct or group chat with 1 to 10 exact @s.whatsapp.net or @lid member IDs and one exact first message. First call without confirm. If the provider maps an @lid alias to a canonical ID, repeat the preview with the returned resolved_member_id so the human approves the exact provider-write identity. After human approval of the complete member set and text, repeat the exact payload with confirm:true and approval_hash. dry_run:true runs the full live preflight twice and stops immediately before the provider write. One created chat spends one WhatsApp/email send action regardless of member count. Existing exact member sets are returned without creating or sending anything.",
|
|
1566
|
+
description: "Preview or start one WhatsApp direct or group chat with 1 to 10 exact @s.whatsapp.net or @lid member IDs and one exact first message. First call without confirm. If the provider maps an @lid alias to a canonical ID, repeat the preview with the returned resolved_member_id so the human approves the exact provider-write identity. After human approval of the complete member set and text, repeat the exact payload with confirm:true and approval_hash. dry_run:true runs the full live preflight twice and stops immediately before the provider write. One created chat spends one WhatsApp/email send action regardless of member count. Existing exact member sets are returned without creating or sending anything. Optional subject sets the group name of a NEW group chat (2+ members only); it is part of the approved payload, so confirm must repeat the exact same subject. A chat cannot be renamed later, so set it here; an existing member set is returned unchanged.",
|
|
1346
1567
|
inputSchema: {
|
|
1347
1568
|
type: "object",
|
|
1348
1569
|
properties: {
|
|
1570
|
+
mark_read: { type: "boolean", default: true, description: "Clear unread after confirmed success; false preserves unread state." },
|
|
1349
1571
|
member_ids: { type: "array", minItems: 1, maxItems: 10, uniqueItems: true, items: { type: "string", minLength: 5, maxLength: 500, pattern: "^[A-Za-z0-9._-]+@(?:s\\.whatsapp\\.net|lid)$" } },
|
|
1350
1572
|
text: { type: "string", minLength: 1, maxLength: 5000 },
|
|
1573
|
+
subject: { type: "string", minLength: 1, maxLength: 100, description: "Group name for a new WhatsApp group chat (requires 2+ member_ids). Without it the group is created unnamed." },
|
|
1351
1574
|
confirm: { type: "boolean", default: false },
|
|
1352
1575
|
approval_hash: { type: "string", minLength: 64, maxLength: 64, pattern: "^[0-9a-f]{64}$" },
|
|
1353
1576
|
dry_run: { type: "boolean", const: true },
|
|
@@ -1360,7 +1583,7 @@ const TOOLS = [
|
|
|
1360
1583
|
name: "wa_send_message",
|
|
1361
1584
|
ch: "wa",
|
|
1362
1585
|
action: "send",
|
|
1363
|
-
description: "Send a WhatsApp message (rate-safe). args: chat_id, text, attachments, expected_watermark, mark_read. Read the chat first: the read returns current_watermark and a send into a thread this account has not read recently is refused. Own outbound messages added after that read do not invalidate the draft, but a counterparty message or mutation returns 409 thread_changed with new_messages, changed_kind, and current_watermark. Optional expected_watermark binds the send to that exact reviewed state. A re-read that fails is 502 thread_preflight_unavailable and nothing was sent. attachments optionally carries up to 4 base64 files as exact {filename, content_type, content_base64} objects, at most 16 MiB per file and 16 MiB per message, and accepts images, PDF, CSV, plain text, JSON, xlsx and
|
|
1586
|
+
description: "Send a WhatsApp message (rate-safe). args: chat_id, text, attachments, expected_watermark, mark_read. Read the chat first: the read returns current_watermark and a send into a thread this account has not read recently is refused. Own outbound messages added after that read do not invalidate the draft, but a counterparty message or mutation returns 409 thread_changed with new_messages, changed_kind, and current_watermark. Optional expected_watermark binds the send to that exact reviewed state. A re-read that fails is 502 thread_preflight_unavailable and nothing was sent. attachments optionally carries up to 4 base64 files as exact {filename, content_type, content_base64} objects, at most 16 MiB per file and 16 MiB per message, and accepts images, PDF, CSV, plain text, JSON, xlsx, zip and mp4/mov video. text is the caption and may be omitted when a file is attached, but a call carrying neither text nor an attachment is refused. Defaults to mark_read:true after confirmed success; mark_read:false preserves unread state. An attachment send is rate-limited, deduplicated and recorded exactly like a text send, and spends the same daily budget. If a send times out or the provider never confirms it, the message may still have been delivered: SignalDash records it and refuses an identical retry with 409 send_outcome_unknown. Read the chat, and only if the message is genuinely absent, resend the identical payload with confirm_resend:true.",
|
|
1364
1587
|
inputSchema: {
|
|
1365
1588
|
type: "object",
|
|
1366
1589
|
properties: {
|
|
@@ -1385,6 +1608,8 @@ const TOOLS = [
|
|
|
1385
1608
|
"application/json",
|
|
1386
1609
|
"application/zip",
|
|
1387
1610
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
1611
|
+
"video/mp4",
|
|
1612
|
+
"video/quicktime",
|
|
1388
1613
|
],
|
|
1389
1614
|
},
|
|
1390
1615
|
content_base64: { type: "string", minLength: 1 },
|
|
@@ -1394,7 +1619,7 @@ const TOOLS = [
|
|
|
1394
1619
|
},
|
|
1395
1620
|
confirm_resend: { type: "boolean", const: true },
|
|
1396
1621
|
expected_watermark: { type: "string", minLength: 64, maxLength: 64, pattern: "^[0-9a-f]{64}$", description: "Bind the send to the exact current_watermark returned by the read or a thread_changed response." },
|
|
1397
|
-
mark_read: { type: "boolean", default:
|
|
1622
|
+
mark_read: { type: "boolean", default: true, description: "Clear unread after confirmed success; false preserves unread state." },
|
|
1398
1623
|
},
|
|
1399
1624
|
// `text` alone is no longer required: a document with no caption is a
|
|
1400
1625
|
// legitimate message.
|
|
@@ -1636,15 +1861,32 @@ const TOOLS = [
|
|
|
1636
1861
|
additionalProperties: false,
|
|
1637
1862
|
},
|
|
1638
1863
|
},
|
|
1864
|
+
{
|
|
1865
|
+
name: "li_delete_post",
|
|
1866
|
+
path: "/li/delete_post",
|
|
1867
|
+
description: "Delete ONE LinkedIn post authored by this authenticated account. Irreversible; disabled unless the operator enables the linkedin_post_delete capability. Acts only as the account bound to this SignalDash session. Requires the exact social_id from li_my_posts (urn:li:activity:<digits>), expected_text_prefix (the first 10-500 characters of the post text, exactly) and confirm:true. Before deleting, SignalDash reads the post with the same account and refuses unless the author is this sender (post_not_own), it is not a repost, and the text starts with expected_text_prefix (text_prefix_mismatch). Returns the post evidence and a post-delete readback; a replay of the same post is refused as duplicate_delete. Deletion is remediation, not rollback.",
|
|
1868
|
+
inputSchema: {
|
|
1869
|
+
type: "object",
|
|
1870
|
+
properties: {
|
|
1871
|
+
post_id: { type: "string", pattern: "^urn:li:activity:[0-9]{1,30}$", maxLength: 60 },
|
|
1872
|
+
expected_text_prefix: { type: "string", minLength: 10, maxLength: 500 },
|
|
1873
|
+
confirm: { type: "boolean", const: true },
|
|
1874
|
+
},
|
|
1875
|
+
required: ["post_id", "expected_text_prefix", "confirm"],
|
|
1876
|
+
additionalProperties: false,
|
|
1877
|
+
},
|
|
1878
|
+
},
|
|
1639
1879
|
{
|
|
1640
1880
|
name: "li_draft_post",
|
|
1641
1881
|
path: "/li/create_post",
|
|
1642
|
-
description: "Draft, publish, or schedule a LinkedIn post.
|
|
1882
|
+
description: "Draft, publish, or schedule a LinkedIn post. A schedule with attachments requires an offset-qualified scheduled_at, a preview, then publish:true with confirm:true and the preview's single-use approval_hash bound to the exact text, time, mentions, attachments, first comment, and content-pipeline item. When the content pipeline is enabled, use an approved content_pipeline_id or preview one exact reasoned content_pipeline_override and repeat it with confirm:true plus its nested single-use approval_hash. Optional mentions, up to 20 attachments, and an account-owner-authored first_comment are preserved for the scheduled publish. An attachment is EITHER one of the four image types carrying content_base64, OR video/mp4 carrying content_url and no bytes: one absolute https URL streamed at publish time, at most 64 MiB, refused if it is not https, resolves to a private address, redirects to one, exceeds the ceiling, answers a different content type, or times out. A video attachment must be the only attachment on the post.",
|
|
1643
1883
|
inputSchema: {
|
|
1644
1884
|
type: "object",
|
|
1645
1885
|
properties: {
|
|
1646
1886
|
text: { type: "string", minLength: 1, maxLength: 3000 },
|
|
1647
1887
|
publish: { type: "boolean" },
|
|
1888
|
+
confirm: { type: "boolean", const: true },
|
|
1889
|
+
approval_hash: { type: "string", minLength: 64, maxLength: 64, pattern: "^[0-9a-f]{64}$" },
|
|
1648
1890
|
scheduled_at: { type: "string", format: "date-time" },
|
|
1649
1891
|
content_pipeline_id: { type: "string", minLength: 1, maxLength: 200 },
|
|
1650
1892
|
content_pipeline_override: {
|
|
@@ -1675,10 +1917,12 @@ const TOOLS = [
|
|
|
1675
1917
|
type: "object",
|
|
1676
1918
|
properties: {
|
|
1677
1919
|
filename: { type: "string", minLength: 1, maxLength: 180 },
|
|
1678
|
-
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif"] },
|
|
1679
|
-
content_base64: { type: "string", minLength: 1 },
|
|
1920
|
+
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif", "video/mp4"] },
|
|
1921
|
+
content_base64: { type: "string", minLength: 1, description: "Required for the four image types. Never sent for video/mp4." },
|
|
1922
|
+
content_url: { type: "string", minLength: 1, maxLength: 2048, description: "Required for video/mp4 and never sent for an image: one absolute https URL the bytes are streamed from at publish time. Nothing is stored locally." },
|
|
1923
|
+
content_sha256: { type: "string", minLength: 64, maxLength: 64, description: "Optional, video only: the exact hex SHA-256 of the bytes at content_url, case-insensitive and stored lowercase. Supply it and the approval binds the bytes; omit it and the approval binds only the URL, so whoever controls that host decides what reaches LinkedIn." },
|
|
1680
1924
|
},
|
|
1681
|
-
required: ["filename", "content_type"
|
|
1925
|
+
required: ["filename", "content_type"],
|
|
1682
1926
|
},
|
|
1683
1927
|
},
|
|
1684
1928
|
},
|
|
@@ -1704,7 +1948,7 @@ const TOOLS = [
|
|
|
1704
1948
|
{
|
|
1705
1949
|
name: "li_save_post_draft",
|
|
1706
1950
|
path: "/li/save_post_draft",
|
|
1707
|
-
description: "Persist one arbitrary LinkedIn post draft without scheduling or publishing it. Stores exact text, ordered
|
|
1951
|
+
description: "Persist one arbitrary LinkedIn post draft without scheduling or publishing it. Stores exact text, ordered attachments, mentions, and an optional first comment. An image attachment carries content_base64; a video/mp4 attachment carries content_url instead, one absolute https URL fetched only at publish time, and must be the only attachment. Duplicate drafts are allowed. No provider call or action budget is used.",
|
|
1708
1952
|
inputSchema: {
|
|
1709
1953
|
type: "object",
|
|
1710
1954
|
properties: {
|
|
@@ -1727,10 +1971,12 @@ const TOOLS = [
|
|
|
1727
1971
|
type: "object",
|
|
1728
1972
|
properties: {
|
|
1729
1973
|
filename: { type: "string", minLength: 1, maxLength: 180 },
|
|
1730
|
-
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif"] },
|
|
1731
|
-
content_base64: { type: "string", minLength: 1 },
|
|
1974
|
+
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif", "video/mp4"] },
|
|
1975
|
+
content_base64: { type: "string", minLength: 1, description: "Required for the four image types. Never sent for video/mp4." },
|
|
1976
|
+
content_url: { type: "string", minLength: 1, maxLength: 2048, description: "Required for video/mp4 and never sent for an image: one absolute https URL the bytes are streamed from at publish time. Nothing is stored locally." },
|
|
1977
|
+
content_sha256: { type: "string", minLength: 64, maxLength: 64, description: "Optional, video only: the exact hex SHA-256 of the bytes at content_url, case-insensitive and stored lowercase. Supply it and the approval binds the bytes; omit it and the approval binds only the URL, so whoever controls that host decides what reaches LinkedIn." },
|
|
1732
1978
|
},
|
|
1733
|
-
required: ["filename", "content_type"
|
|
1979
|
+
required: ["filename", "content_type"],
|
|
1734
1980
|
additionalProperties: false,
|
|
1735
1981
|
},
|
|
1736
1982
|
},
|
|
@@ -1801,7 +2047,7 @@ const TOOLS = [
|
|
|
1801
2047
|
{
|
|
1802
2048
|
name: "li_update_post_draft",
|
|
1803
2049
|
path: "/li/update_post_draft",
|
|
1804
|
-
description: "Atomically replace one complete saved LinkedIn draft using its exact UUID and expected_version. Omitted mentions, attachments, or first_comment are cleared. A stale version is refused. No provider call or action budget is used.",
|
|
2050
|
+
description: "Atomically replace one complete saved LinkedIn draft using its exact UUID and expected_version. Omitted mentions, attachments, or first_comment are cleared. An image attachment carries content_base64; a video/mp4 attachment carries content_url instead and must be the only attachment. A stale version is refused. No provider call or action budget is used.",
|
|
1805
2051
|
inputSchema: {
|
|
1806
2052
|
type: "object",
|
|
1807
2053
|
properties: {
|
|
@@ -1825,10 +2071,12 @@ const TOOLS = [
|
|
|
1825
2071
|
type: "object",
|
|
1826
2072
|
properties: {
|
|
1827
2073
|
filename: { type: "string", minLength: 1, maxLength: 180 },
|
|
1828
|
-
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif"] },
|
|
1829
|
-
content_base64: { type: "string", minLength: 1 },
|
|
2074
|
+
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif", "video/mp4"] },
|
|
2075
|
+
content_base64: { type: "string", minLength: 1, description: "Required for the four image types. Never sent for video/mp4." },
|
|
2076
|
+
content_url: { type: "string", minLength: 1, maxLength: 2048, description: "Required for video/mp4 and never sent for an image: one absolute https URL the bytes are streamed from at publish time. Nothing is stored locally." },
|
|
2077
|
+
content_sha256: { type: "string", minLength: 64, maxLength: 64, description: "Optional, video only: the exact hex SHA-256 of the bytes at content_url, case-insensitive and stored lowercase. Supply it and the approval binds the bytes; omit it and the approval binds only the URL, so whoever controls that host decides what reaches LinkedIn." },
|
|
1830
2078
|
},
|
|
1831
|
-
required: ["filename", "content_type"
|
|
2079
|
+
required: ["filename", "content_type"],
|
|
1832
2080
|
additionalProperties: false,
|
|
1833
2081
|
},
|
|
1834
2082
|
},
|
|
@@ -1892,11 +2140,11 @@ const TOOLS = [
|
|
|
1892
2140
|
{
|
|
1893
2141
|
name: "sd_share_list",
|
|
1894
2142
|
path: "/sd/share_list",
|
|
1895
|
-
description: "Share one selection as a standalone signaldash.dev link,
|
|
2143
|
+
description: "Share one selection as a standalone signaldash.dev link, list and revoke live links, and process intro requests submitted from people lists. Pass `people` instead of `rows` for a shortlist of humans: each entry renders as a card with a photo when the provider gives one and initials when it does not, plus an optional `score` out of 100 and the `reason` that earned it. A score without a reason is a claim without evidence, so send both or neither, and put the scoring rule in `rubric` where the reader can see it. action:create returns the url ONCE and stores only its hash. action:list shows live links, open counts, and pending intro-request counts. A new request is durably queued and promptly alerts the owner through the verified WhatsApp notification channel when that channel is enabled. action:requests returns selected people, timestamps, and notification delivery state, filtered by status pending/completed/all. After the introductions are handled, action:complete with request_id removes the request from the pending queue. action:revoke kills one link by token or list_id.",
|
|
1896
2144
|
inputSchema: {
|
|
1897
2145
|
type: "object",
|
|
1898
2146
|
properties: {
|
|
1899
|
-
action: { type: "string", enum: ["create", "list", "revoke"] },
|
|
2147
|
+
action: { type: "string", enum: ["create", "list", "revoke", "requests", "complete"] },
|
|
1900
2148
|
title: { type: "string", minLength: 1, maxLength: 200 },
|
|
1901
2149
|
note: { type: "string", maxLength: 4000 },
|
|
1902
2150
|
columns: { type: "array", minItems: 1, maxItems: 12, items: { type: "string", minLength: 1, maxLength: 80 } },
|
|
@@ -1939,6 +2187,8 @@ const TOOLS = [
|
|
|
1939
2187
|
rubric: { type: "string", maxLength: 1200 },
|
|
1940
2188
|
token: { type: "string", minLength: 1, maxLength: 200 },
|
|
1941
2189
|
list_id: { type: "string", minLength: 1, maxLength: 64 },
|
|
2190
|
+
status: { type: "string", enum: ["pending", "completed", "all"] },
|
|
2191
|
+
request_id: { type: "string", format: "uuid" },
|
|
1942
2192
|
},
|
|
1943
2193
|
additionalProperties: false,
|
|
1944
2194
|
},
|
|
@@ -1960,7 +2210,7 @@ const TOOLS = [
|
|
|
1960
2210
|
{
|
|
1961
2211
|
name: "li_scheduled_post_attachment",
|
|
1962
2212
|
path: "/li/scheduled_post_attachment",
|
|
1963
|
-
description: "Read the exact bytes of one stored attachment on one active SignalDash scheduled post, as base64. Requires the exact post UUID returned by li_draft_post or li_scheduled_posts and a zero-based index strictly below the attachment_count reported by li_scheduled_post_preview or li_scheduled_posts. Returns filename, the stored content_type verbatim, and content_base64. A cancelled or published post, a post belonging to someone else, or an index that does not exist is scheduled_post_attachment_not_found. One image can be hundreds of kilobytes of base64, so fetch it only when the bytes themselves are needed rather than the post text and time.",
|
|
2213
|
+
description: "Read the exact bytes of one stored attachment on one active SignalDash scheduled post, as base64. Requires the exact post UUID returned by li_draft_post or li_scheduled_posts and a zero-based index strictly below the attachment_count reported by li_scheduled_post_preview or li_scheduled_posts. Returns filename, the stored content_type verbatim, and either content_base64 for an image or content_url for a video, whose bytes are never stored here. A cancelled or published post, a post belonging to someone else, or an index that does not exist is scheduled_post_attachment_not_found. One image can be hundreds of kilobytes of base64, so fetch it only when the bytes themselves are needed rather than the post text and time.",
|
|
1964
2214
|
inputSchema: {
|
|
1965
2215
|
type: "object",
|
|
1966
2216
|
properties: {
|
|
@@ -1974,7 +2224,7 @@ const TOOLS = [
|
|
|
1974
2224
|
{
|
|
1975
2225
|
name: "li_edit_scheduled_post",
|
|
1976
2226
|
path: "/li/edit_scheduled_post",
|
|
1977
|
-
description: "Atomically replace the text, time, mentions,
|
|
2227
|
+
description: "Atomically replace the text, time, mentions, attachments, and optional first comment of one exact SignalDash post while it is still scheduled. An image attachment carries content_base64; a video/mp4 attachment carries content_url instead and must be the only attachment. The first call previews the complete replacement. Repeat the identical full payload with confirm:true, the single-use approval_hash, expected_version, and expected_updated_at returned by the preview. The post UUID, created_at, provider account, and content-pipeline audit binding are preserved; no provider call occurs.",
|
|
1978
2228
|
inputSchema: {
|
|
1979
2229
|
type: "object",
|
|
1980
2230
|
properties: {
|
|
@@ -1999,10 +2249,12 @@ const TOOLS = [
|
|
|
1999
2249
|
type: "object",
|
|
2000
2250
|
properties: {
|
|
2001
2251
|
filename: { type: "string", minLength: 1, maxLength: 180 },
|
|
2002
|
-
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif"] },
|
|
2003
|
-
content_base64: { type: "string", minLength: 1 },
|
|
2252
|
+
content_type: { type: "string", enum: ["image/png", "image/jpeg", "image/webp", "image/gif", "video/mp4"] },
|
|
2253
|
+
content_base64: { type: "string", minLength: 1, description: "Required for the four image types. Never sent for video/mp4." },
|
|
2254
|
+
content_url: { type: "string", minLength: 1, maxLength: 2048, description: "Required for video/mp4 and never sent for an image: one absolute https URL the bytes are streamed from at publish time. Nothing is stored locally." },
|
|
2255
|
+
content_sha256: { type: "string", minLength: 64, maxLength: 64, description: "Optional, video only: the exact hex SHA-256 of the bytes at content_url, case-insensitive and stored lowercase. Supply it and the approval binds the bytes; omit it and the approval binds only the URL, so whoever controls that host decides what reaches LinkedIn." },
|
|
2004
2256
|
},
|
|
2005
|
-
required: ["filename", "content_type"
|
|
2257
|
+
required: ["filename", "content_type"],
|
|
2006
2258
|
additionalProperties: false,
|
|
2007
2259
|
},
|
|
2008
2260
|
},
|
|
@@ -2042,6 +2294,7 @@ const TOOLS = [
|
|
|
2042
2294
|
inputSchema: {
|
|
2043
2295
|
type: "object",
|
|
2044
2296
|
properties: {
|
|
2297
|
+
mark_read: { type: "boolean", default: true, description: "Clear unread after confirmed success; false preserves unread state." },
|
|
2045
2298
|
channel: { type: "string", enum: ["whatsapp", "linkedin"] },
|
|
2046
2299
|
chat_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
2047
2300
|
text: { type: "string", minLength: 1, maxLength: 5000 },
|
|
@@ -2089,6 +2342,112 @@ const TOOLS = [
|
|
|
2089
2342
|
additionalProperties: false,
|
|
2090
2343
|
},
|
|
2091
2344
|
},
|
|
2345
|
+
{
|
|
2346
|
+
name: "sd_invitation_followups",
|
|
2347
|
+
path: "/sd/invitation_followups",
|
|
2348
|
+
description: "List this user's invitation follow-ups: exact messages that are sent once a LinkedIn invitation is proven accepted. States: pending (waiting for acceptance, or accepted and waiting for a send slot), sending, sent, cancelled, expired (not accepted within 30 days), needs_review (the thread moved, e.g. they wrote first, or the outcome is unknown; never retried automatically).",
|
|
2349
|
+
inputSchema: {
|
|
2350
|
+
type: "object",
|
|
2351
|
+
properties: {
|
|
2352
|
+
state: { type: "string", enum: ["pending", "sending", "sent", "cancelled", "expired", "needs_review"] },
|
|
2353
|
+
},
|
|
2354
|
+
additionalProperties: false,
|
|
2355
|
+
},
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2358
|
+
name: "sd_invitation_followup_create",
|
|
2359
|
+
path: "/sd/invitation_followup_create",
|
|
2360
|
+
description: "Register an after-acceptance follow-up message for an invitation that was ALREADY sent. First call without confirm: SignalDash proves a pending sent invitation to this exact provider_id exists and shows the exact text. After the human approves, repeat the same provider_id, text and invitation_id with confirm:true.",
|
|
2361
|
+
inputSchema: {
|
|
2362
|
+
type: "object",
|
|
2363
|
+
properties: {
|
|
2364
|
+
provider_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
2365
|
+
text: { type: "string", minLength: 1, maxLength: 5000 },
|
|
2366
|
+
invitation_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
2367
|
+
confirm: { type: "boolean", default: false },
|
|
2368
|
+
},
|
|
2369
|
+
required: ["provider_id", "text"],
|
|
2370
|
+
additionalProperties: false,
|
|
2371
|
+
},
|
|
2372
|
+
},
|
|
2373
|
+
{
|
|
2374
|
+
name: "sd_invitation_followup_cancel",
|
|
2375
|
+
path: "/sd/invitation_followup_cancel",
|
|
2376
|
+
description: "Cancel one exact invitation follow-up while it is still pending. Requires id and confirm:true. It cannot stop or unsend one already being sent or sent.",
|
|
2377
|
+
inputSchema: {
|
|
2378
|
+
type: "object",
|
|
2379
|
+
properties: {
|
|
2380
|
+
id: { type: "string", format: "uuid" },
|
|
2381
|
+
confirm: { type: "boolean", const: true },
|
|
2382
|
+
},
|
|
2383
|
+
required: ["id", "confirm"],
|
|
2384
|
+
additionalProperties: false,
|
|
2385
|
+
},
|
|
2386
|
+
},
|
|
2387
|
+
{
|
|
2388
|
+
name: "sd_followup_create",
|
|
2389
|
+
path: "/sd/followup_create",
|
|
2390
|
+
description: "Record one task-level follow-up inside an ordinary LinkedIn, WhatsApp, email, or Slack thread. Multiple distinct tasks may coexist in one conversation. This monitors only and never sends.",
|
|
2391
|
+
inputSchema: {
|
|
2392
|
+
type: "object",
|
|
2393
|
+
properties: {
|
|
2394
|
+
channel: { type: "string", enum: ["linkedin", "whatsapp", "email", "slack"] },
|
|
2395
|
+
thread_id: { type: "string", minLength: 1, maxLength: 2048 },
|
|
2396
|
+
recipient_label: { type: "string", minLength: 1, maxLength: 500 },
|
|
2397
|
+
context: { type: "string", minLength: 1, maxLength: 4000 },
|
|
2398
|
+
completion_condition: { type: "string", minLength: 1, maxLength: 2000 },
|
|
2399
|
+
auto_close_on_reply: { type: "boolean" },
|
|
2400
|
+
origin: { type: "string", enum: ["manual", "outbound", "application"] },
|
|
2401
|
+
source_message_id: { type: "string", minLength: 1, maxLength: 2048 },
|
|
2402
|
+
baseline_at: { type: "string", format: "date-time" },
|
|
2403
|
+
due_at: { type: "string", format: "date-time" },
|
|
2404
|
+
},
|
|
2405
|
+
required: ["channel", "thread_id", "context", "due_at"],
|
|
2406
|
+
additionalProperties: false,
|
|
2407
|
+
},
|
|
2408
|
+
},
|
|
2409
|
+
{
|
|
2410
|
+
name: "sd_followups",
|
|
2411
|
+
path: "/sd/followups",
|
|
2412
|
+
description: "List ordinary communication reply expectations. The list first reconciles exact channel/thread matches against observed inbound messages.",
|
|
2413
|
+
inputSchema: {
|
|
2414
|
+
type: "object",
|
|
2415
|
+
properties: {
|
|
2416
|
+
status: { type: "string", enum: ["waiting", "needs_review", "complete", "cancelled"] },
|
|
2417
|
+
channel: { type: "string", enum: ["linkedin", "whatsapp", "email", "slack"] },
|
|
2418
|
+
overdue: { type: "boolean" },
|
|
2419
|
+
},
|
|
2420
|
+
additionalProperties: false,
|
|
2421
|
+
},
|
|
2422
|
+
},
|
|
2423
|
+
{
|
|
2424
|
+
name: "sd_followup_cancel",
|
|
2425
|
+
path: "/sd/followup_cancel",
|
|
2426
|
+
description: "Cancel one exact waiting reply expectation. This sends nothing and does not delete communication history.",
|
|
2427
|
+
inputSchema: {
|
|
2428
|
+
type: "object",
|
|
2429
|
+
properties: {
|
|
2430
|
+
id: { type: "string", format: "uuid" },
|
|
2431
|
+
confirm: { type: "boolean", const: true },
|
|
2432
|
+
},
|
|
2433
|
+
required: ["id", "confirm"],
|
|
2434
|
+
additionalProperties: false,
|
|
2435
|
+
},
|
|
2436
|
+
},
|
|
2437
|
+
{
|
|
2438
|
+
name: "sd_followup_complete",
|
|
2439
|
+
path: "/sd/followup_complete",
|
|
2440
|
+
description: "Mark one exact task-level follow-up complete after its completion condition has been verified. This sends nothing.",
|
|
2441
|
+
inputSchema: {
|
|
2442
|
+
type: "object",
|
|
2443
|
+
properties: {
|
|
2444
|
+
id: { type: "string", format: "uuid" },
|
|
2445
|
+
confirm: { type: "boolean", const: true },
|
|
2446
|
+
},
|
|
2447
|
+
required: ["id", "confirm"],
|
|
2448
|
+
additionalProperties: false,
|
|
2449
|
+
},
|
|
2450
|
+
},
|
|
2092
2451
|
];
|
|
2093
2452
|
// No catch-all fallback. It advertised one union of keys for every tool that
|
|
2094
2453
|
// had no schema of its own -- which is how `li_list_chats` came to offer `text`
|