@floomhq/signaldash 0.42.0 → 0.43.1
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 +38 -2
- package/bin/sd.mjs +5 -3
- package/package.json +1 -1
- package/skills/signaldash/SKILL.md +2 -2
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ setup installs both from the same pinned npm package
|
|
|
121
121
|
the human chose to execute:
|
|
122
122
|
|
|
123
123
|
```bash
|
|
124
|
-
npx -y @floomhq/signaldash@0.
|
|
124
|
+
npx -y @floomhq/signaldash@0.43.1 <invite-code>
|
|
125
125
|
```
|
|
126
126
|
|
|
127
127
|
Run that command in a terminal, not in an agent chat. Do not ask an agent to
|
|
@@ -201,7 +201,7 @@ timer, scheduler entry, Buffer item, or provider write.
|
|
|
201
201
|
- `sd_withdrawal_batch_approve(withdrawal_batch_id, confirm_token)`
|
|
202
202
|
- `sd_withdrawal_batch_cancel(withdrawal_batch_id, approval_view_hash, confirm)`
|
|
203
203
|
- `wa_list_chats`
|
|
204
|
-
- `wa_read_messages(chat_id)`
|
|
204
|
+
- `wa_read_messages(chat_id, limit?, cursor?)`
|
|
205
205
|
- `wa_mark_read(chat_id)`
|
|
206
206
|
- `wa_get_attachment(chat_id, message_id, attachment_id)`
|
|
207
207
|
- `wa_transcribe_voice(chat_id, message_id, attachment_id)`
|
|
@@ -209,6 +209,42 @@ timer, scheduler entry, Buffer item, or provider write.
|
|
|
209
209
|
- `wa_send_message(chat_id, text?, attachments?, expected_watermark?, mark_read?)` — confirmed sends clear unread by default; `mark_read:false` preserves unread.
|
|
210
210
|
- `wa_delete_message(chat_id, message_id)`
|
|
211
211
|
- `wa_delete_messages(messages)`
|
|
212
|
+
|
|
213
|
+
WhatsApp history is paginated, not limited to the newest 100 messages. Read
|
|
214
|
+
`wa_read_messages` with `limit:250`, then pass the exact returned `cursor`
|
|
215
|
+
unchanged to the same chat to read older pages. Each call fetches at most one
|
|
216
|
+
provider message page; there is no automatic bulk scan. Pace requests, set a
|
|
217
|
+
finite page/message budget, and stop on provider warnings, authentication
|
|
218
|
+
errors, 403/429, a repeated cursor, or an explicit null cursor. Empty pages
|
|
219
|
+
with a new cursor can still lead to more history.
|
|
220
|
+
|
|
221
|
+
The provider's `items` or `messages` envelope and cursor are preserved.
|
|
222
|
+
`history_pagination` reports `response_shape_supported`, requested limit, returned item count, next cursor,
|
|
223
|
+
`has_more` (null when unknown), `provider_exhausted`, and `cursor_advancing`.
|
|
224
|
+
Only an explicit null cursor on a recognized list proves provider exhaustion;
|
|
225
|
+
missing pagination or an unfamiliar envelope is unknown, never proof that a
|
|
226
|
+
message does not exist. Even exhausted provider history may be incomplete if
|
|
227
|
+
older history was never synchronized by the provider.
|
|
228
|
+
|
|
229
|
+
Continuation cursors must have been issued to this authenticated user, account
|
|
230
|
+
and exact chat. They live in a bounded in-memory registry for 60 minutes;
|
|
231
|
+
restart, expiry or an unissued/wrong-scope cursor requires a fresh first page
|
|
232
|
+
without cursor. At most one read per cursor runs concurrently. Successful
|
|
233
|
+
continuation consumes that receipt and registers the next cursor atomically;
|
|
234
|
+
provider/validation failures preserve it for retry. Registry bounds are 4,096
|
|
235
|
+
globally, 512 per user and 128 per account/chat, with no live-entry eviction.
|
|
236
|
+
Capacity returns an explicit error. Invalid provider cursors, mismatched
|
|
237
|
+
account/chat rows and unsupported historical response shapes are refused
|
|
238
|
+
without returning message contents.
|
|
239
|
+
|
|
240
|
+
Cursor pages return `history_page:true` and `current_watermark:null`. They
|
|
241
|
+
neither create nor refresh a send-read proof nor update reply/contact
|
|
242
|
+
observations or mark the chat read. Existing latest-page proofs are preserved.
|
|
243
|
+
Before sending, read the latest page again **without cursor**. Cursor support
|
|
244
|
+
does not change provider base URLs/API versions, send budgets, or account limits.
|
|
245
|
+
The default stays 30 messages. WhatsApp's explicit per-page maximum is 250,
|
|
246
|
+
matching the [provider's message endpoint](https://developer.unipile.com/reference/chatscontroller_listchatmessages.md);
|
|
247
|
+
LinkedIn/Instagram reads and chat-list caps remain 100.
|
|
212
248
|
- `ig_list_chats(limit?, cursor?, search?, max_scan?, unread?)`
|
|
213
249
|
- `ig_read_messages(chat_id, limit?)`
|
|
214
250
|
- `ig_mark_read(chat_id)`
|
package/bin/sd.mjs
CHANGED
|
@@ -1504,12 +1504,13 @@ const TOOLS = [
|
|
|
1504
1504
|
name: "wa_read_messages",
|
|
1505
1505
|
ch: "wa",
|
|
1506
1506
|
action: "read",
|
|
1507
|
-
description: "Read messages and the resolved chat
|
|
1507
|
+
description: "Read one bounded page of messages and the resolved WhatsApp chat. Use limit up to 250 and the returned cursor to reach older history, one paced page at a time. Cursor pages never authorize sends or update reply observations; read without cursor immediately before sending. Missing history is not proof of absence. args: chat_id, limit, cursor",
|
|
1508
1508
|
inputSchema: {
|
|
1509
1509
|
type: "object",
|
|
1510
1510
|
properties: {
|
|
1511
1511
|
chat_id: { type: "string", minLength: 1, maxLength: 500 },
|
|
1512
|
-
limit: { type: "integer", minimum: 1, maximum:
|
|
1512
|
+
limit: { type: "integer", minimum: 1, maximum: 250 },
|
|
1513
|
+
cursor: { type: "string", minLength: 1, maxLength: 4000, description: "Exact opaque cursor from the preceding page, unchanged. Omit for the latest page." },
|
|
1513
1514
|
},
|
|
1514
1515
|
required: ["chat_id"],
|
|
1515
1516
|
additionalProperties: false,
|
|
@@ -1958,11 +1959,12 @@ const TOOLS = [
|
|
|
1958
1959
|
{
|
|
1959
1960
|
name: "li_draft_post",
|
|
1960
1961
|
path: "/li/create_post",
|
|
1961
|
-
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.",
|
|
1962
|
+
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. Optional repost_post_id republishes an existing LinkedIn post with text as the commentary on top: it needs scheduled_at, is resolved read-only and shown in the preview (post_id, author, opening text), and always needs the preview's approval_hash with confirm:true; mentions and first_comment work as on any post.",
|
|
1962
1963
|
inputSchema: {
|
|
1963
1964
|
type: "object",
|
|
1964
1965
|
properties: {
|
|
1965
1966
|
text: { type: "string", minLength: 1, maxLength: 3000 },
|
|
1967
|
+
repost_post_id: { type: "string", minLength: 6, maxLength: 60, pattern: "^(?:\\d{6,30}|urn:li:(?:activity|ugcPost|share):\\d{6,30})$", description: "Optional. The LinkedIn post to repost with commentary: the numeric activity id (e.g. 7516090667429748736) or its urn:li:activity|ugcPost|share URN. Scheduled posts only." },
|
|
1966
1968
|
publish: { type: "boolean" },
|
|
1967
1969
|
confirm: { type: "boolean", const: true },
|
|
1968
1970
|
approval_hash: { type: "string", minLength: 64, maxLength: 64, pattern: "^[0-9a-f]{64}$" },
|
package/package.json
CHANGED
|
@@ -446,7 +446,7 @@ Use the exact tool names and argument keys below. Limits are optional.
|
|
|
446
446
|
| `sd_withdrawal_batch_approve` | `withdrawal_batch_id` required; `confirm_token` required in the exact `sd-xxxx-xxxx-xxxx` form the human read off the approval page | Record the human's approval using the single-use code that authenticated page minted for them. An agent cannot mint, guess, or bypass that code. |
|
|
447
447
|
| `sd_withdrawal_batch_cancel` | `withdrawal_batch_id` required; `approval_view_hash` required string or null exactly as inspected; `confirm:true` required | Revoke the approval and stop every withdrawal that has not started. It cannot recall one already submitted, and it cannot restore the three-week re-invite block for people already withdrawn. |
|
|
448
448
|
| `wa_list_chats` | `limit` integer 1-100, default 20; `cursor` optional; `search` optional string, max 200 characters; `max_scan` optional integer 1-500, default 200, and never more than five provider pages | Find an existing WhatsApp conversation and exact `chat_id`. Direct chats expose a resolved contact in both `name` and `attendee_name` when available; groups retain their provider group `name` and return `attendee_name:null`. With `search` it filters case-insensitively on `name`, `subject`, `id`, `provider_id`, `attendee_provider_id`, `attendee_public_identifier`, and `attendee_name`. The attendee identifiers can carry a phone JID or `@lid`, and digit normalization makes bare or formatted identifiers match their stored form, such as `+49 151 67609512`, `004915167609512`, `4915167609512@s.whatsapp.net`, or the bare digits from `202726935924973@lid`. The provider CANNOT filter a chat list, so SignalDash scans and filters: read `search.exhaustive` before you conclude anything, `search.limit_reached` to know whether the matches were truncated by `limit`, and `search.searched_fields` for what was actually compared. `false` means "not among the `scanned_chats` scanned", never "does not exist" -- continue from the returned `cursor`. When `started_from_cursor` is true the scan began mid-list, so even `exhaustive` says nothing about the chats before that cursor. Search an exact phone number, lid, or known attendee name rather than guessing. Any other key, including `text` and `member_id`, is refused with `unsupported_parameter`. |
|
|
449
|
-
| `wa_read_messages` | `chat_id` required; `limit` 1-
|
|
449
|
+
| `wa_read_messages` | `chat_id` required; `limit` 1-250, default 30; optional `cursor` from the previous page, unchanged, max 4000 characters | Read one bounded WhatsApp page. Start without cursor; follow issued `history_pagination.next_cursor` with paced calls and a finite page/message budget. Historical pages return `history_page:true`, `current_watermark:null`, and never refresh send-read proofs or reply/contact observations. Cursors are scoped to this user/account/chat, expire after 60 minutes or restart, and permit one active read at a time; an invalid cursor requires a fresh first page. Inspect `has_more`, `provider_exhausted`, and `cursor_advancing`; missing pagination is unknown, not absence, and repeated cursors require stopping. Stop on provider warnings, authentication errors or 403/429. Read the latest page again without cursor before sending. |
|
|
450
450
|
| `wa_mark_read` | `chat_id` required | Explicitly clear one WhatsApp chat's unread state. Reading never clears unread automatically. |
|
|
451
451
|
| `wa_get_attachment` | `chat_id`, `message_id`, `attachment_id` all required, max 500 characters each | Download one attachment of one message in a chat this account owns. Read the chat first: the exact `message_id` and `attachment_id` come from `wa_read_messages`. Returns the stored path on the SignalDash host, mimetype, byte size and sha256. |
|
|
452
452
|
| `wa_transcribe_voice` | `chat_id`, `message_id`, `attachment_id` all required, max 500 characters each; `backend` optional, exactly `gemini` or `whisper` | Turn one WhatsApp voice note into text through SignalDash instead of fetching provider bytes yourself. Always read the returned `backend`: `gemini` is the accurate default, `whisper-small` is the weak local fallback and mangles German with English terms mixed in, and a fallback also carries `fallback_reason`. Non-audio attachments are refused with `415 not_audio`; an unknown backend with `400 unknown_backend`; a transcription that exceeds its time limit returns `504 transcription_timeout` with the stored audio path. |
|
|
@@ -469,7 +469,7 @@ Use the exact tool names and argument keys below. Limits are optional.
|
|
|
469
469
|
| `li_like_comment` | `post_id`, `parent_comment_id`, and `comment_id` required; `expected_watermark` optional exact 64-character watermark | Like once one exact inbound comment on this sender's own post after `li_post_comments`. SignalDash re-proves post ownership, the unchanged comment, its author and parent, no own like, sender generation, budget, and provider health immediately before writing. A 2xx is not success until bounded readback finds exactly one own like. |
|
|
470
470
|
| `li_delete_message` | `chat_id`, `message_id`, and `confirm:true` required | Remediate one exact own LinkedIn message within 60 minutes of sending. SignalDash proves account, exact chat, own authorship, timestamp eligibility, a separate remediation budget, and the provider's post-delete state. Success requires `deleted:1` or a genuine 404. A present row or failed readback returns `502 deleted_unconfirmed`, locks the sender, and is never retried automatically. This cannot undo delivery, reading, or notifications and never relaxes a send gate. |
|
|
471
471
|
| `li_delete_comment` | `post_id`, `comment_id`, and `confirm:true` required | Currently unavailable: the fixture-tested Unipile v2 wrapper is held at database capability state `untested` until live compatibility is proved against Federico's own removable comment. When enabled it proves own comment identity and readback. Deletion is remediation, not rollback. |
|
|
472
|
-
| `li_draft_post` | `text` required, max 3000; `publish` optional; `scheduled_at` optional offset-qualified ISO date-time; `content_pipeline_id` normally required for scheduling while that user's pipeline is enabled; `content_pipeline_override` optional exact `{reason,confirm?,approval_hash?}`; `mentions` optional array of up to 25 exact `{name,profile_id}` objects; `attachments` optional array of up to 20 exact objects, each either an image as `{filename,content_type,content_base64}` (max 5 MiB each and 12 MiB total) or one video as `{filename,content_type:"video/mp4",content_url,content_sha256?}`; `first_comment` optional, max 1250; scheduled attachments require top-level `confirm:true` plus the preview's `approval_hash` | Create a server-confirmed draft, publish now, or persist an exact future LinkedIn post and its approved first comment. A scheduled attachment preview returns a single-use approval bound to the exact text, time, mentions, attachment filenames/types plus image-byte digests or video URL/digest, first comment, and pipeline item. An enabled pipeline normally runs its fact, exact-text-and-attachment, shared-calendar, frequency, and breathing preflight. For one deliberate exception, preview the exact payload with `{reason}`, show it to the human, then repeat it with nested `confirm:true` and the returned single-use payload-bound `approval_hash`. The audit record preserves the reason, preview ID, and approval time; every non-pipeline provider safety guard remains active. |
|
|
472
|
+
| `li_draft_post` | `text` required, max 3000; `publish` optional; `scheduled_at` optional offset-qualified ISO date-time; `content_pipeline_id` normally required for scheduling while that user's pipeline is enabled; `content_pipeline_override` optional exact `{reason,confirm?,approval_hash?}`; `mentions` optional array of up to 25 exact `{name,profile_id}` objects; `attachments` optional array of up to 20 exact objects, each either an image as `{filename,content_type,content_base64}` (max 5 MiB each and 12 MiB total) or one video as `{filename,content_type:"video/mp4",content_url,content_sha256?}`; `first_comment` optional, max 1250; `repost_post_id` optional, scheduled only, the numeric activity id or `urn:li:activity|ugcPost|share:<digits>` of a post to repost with `text` as commentary; scheduled attachments and every repost require top-level `confirm:true` plus the preview's `approval_hash` | Create a server-confirmed draft, publish now, or persist an exact future LinkedIn post and its approved first comment. A scheduled attachment preview returns a single-use approval bound to the exact text, time, mentions, attachment filenames/types plus image-byte digests or video URL/digest, first comment, and pipeline item. A repost preview resolves the target read-only and returns `repost` (post_id, social_id, author, share_url, text_excerpt) so the human approves which post is republished; the approval is bound to that post id. An enabled pipeline normally runs its fact, exact-text-and-attachment, shared-calendar, frequency, and breathing preflight. For one deliberate exception, preview the exact payload with `{reason}`, show it to the human, then repeat it with nested `confirm:true` and the returned single-use payload-bound `approval_hash`. The audit record preserves the reason, preview ID, and approval time; every non-pipeline provider safety guard remains active. |
|
|
473
473
|
| `li_set_scheduled_post_first_comment` | `id` required UUID; `first_comment` required, max 1250; `confirm:true` required | Attach one exact approved first comment to a scheduled post. SignalDash publishes it through the same connected account after the post and never republishes the post if the comment fails. |
|
|
474
474
|
| `li_save_post_draft` | `text` required, max 3000; `mentions` optional up to 25; `attachments` optional up to 20, images by `content_base64` (max 5 MiB each and 12 MiB total) or one video/mp4 by `content_url`; `first_comment` optional, max 1250; `source_key` optional tenant-scoped idempotency key, max 256; `metadata` optional bounded structured source/editorial context | Persist one arbitrary LinkedIn draft without scheduling or publishing. Exact ordered image bytes and ordinary duplicate drafts are retained. An identical `source_key` replay returns the existing draft; changed content under that key is refused. Tenant limits are 1,000 drafts and 100 MiB decoded attachment bytes. No provider call or action budget is used. |
|
|
475
475
|
| `li_post_drafts` | optional `review_ttl_hours` (`1` or `24`) | List durable SignalDash drafts with attachment metadata, never base64, and return a fresh one-use calendar link. The default handoff and review session last 60 minutes; pass `24` for a full day. The calendar uses the scheduled-post card design for unscheduled SignalDash and Buffer drafts, with a visible `DRAFT` tag. Its review session saves copy, notes, and up to four private feedback images inline without reloading the calendar. Reviewers can explicitly replace the post's current images with those uploads; unchecked uploads remain private references. Each SignalDash draft card also displays its exact version and next verified free 08:00 UTC slot. `Approve & schedule` rechecks the complete SignalDash and Buffer calendar, then atomically moves the exact draft into that slot without a provider call. Stored drafts remain separate from scheduled posts until this explicit approval succeeds. |
|