@hraness/message-like-me 0.8.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/LICENSE +21 -0
  3. package/README.md +698 -0
  4. package/SECURITY.md +318 -0
  5. package/dist/agentic-messaging-v1.d.ts +179 -0
  6. package/dist/agentic-messaging-v1.js +52 -0
  7. package/dist/canonical-json.d.ts +3 -0
  8. package/dist/cli-bs3db5jr.js +643 -0
  9. package/dist/cli-d7qv38ab.js +485 -0
  10. package/dist/cli-kw20gkk3.js +5 -0
  11. package/dist/cli-qqafdvz9.js +5 -0
  12. package/dist/cli-ry4128kz.js +584 -0
  13. package/dist/cli-ththzwja.js +20 -0
  14. package/dist/cli-x1qncxm7.js +1078 -0
  15. package/dist/cli.js +9436 -0
  16. package/dist/ensoul-source-v1.d.ts +121 -0
  17. package/dist/ensoul-source-v1.js +24 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.js +47 -0
  20. package/dist/message-bundle-v1-identity.d.ts +2 -0
  21. package/dist/message-bundle-v1.d.ts +205 -0
  22. package/dist/message-bundle-v1.js +37 -0
  23. package/dist/message-bundle-v2-identity.d.ts +2 -0
  24. package/dist/message-bundle-v2.d.ts +215 -0
  25. package/dist/message-bundle-v2.js +43 -0
  26. package/dist/metrics.d.ts +41 -0
  27. package/dist/types.d.ts +568 -0
  28. package/docs/local-message-bundle-v1.md +245 -0
  29. package/docs/local-message-bundle-v2.md +167 -0
  30. package/docs/methodology.md +322 -0
  31. package/docs/research.md +164 -0
  32. package/package.json +82 -0
  33. package/schema/ensoul-messages-source-v1.schema.json +248 -0
  34. package/schema/local-message-bundle-v1.schema.json +449 -0
  35. package/schema/local-message-bundle-v2.schema.json +462 -0
  36. package/schema/style-profile-v1.schema.json +223 -0
  37. package/schema/style-profile-v2.schema.json +202 -0
  38. package/skills/ensoul/LICENSE +23 -0
  39. package/skills/ensoul/NOTICE.md +7 -0
  40. package/skills/ensoul/SKILL.md +226 -0
  41. package/skills/ensoul/VENDORED_FROM.md +7 -0
  42. package/skills/ensoul/agents/openai.yaml +4 -0
  43. package/skills/ensoul/references/ensoul-source-packet-v1.schema.json +187 -0
  44. package/skills/ensoul/references/evidence-method.md +148 -0
  45. package/skills/ensoul/references/output-blueprint.md +143 -0
  46. package/skills/ensoul/references/source-packets.md +139 -0
  47. package/skills/ensoul/scripts/prepare_x_archive.py +467 -0
  48. package/skills/ensoul/scripts/validate_source_packet.py +477 -0
  49. package/skills/message-like-me/SKILL.md +229 -0
  50. package/skills/message-like-me/agents/openai.yaml +4 -0
  51. package/skills/message-like-me/references/analysis.md +159 -0
  52. package/skills/message-like-me/references/drafting.md +86 -0
  53. package/skills/message-like-me/references/ensoul.md +94 -0
  54. package/skills/message-like-me/references/evaluation.md +81 -0
  55. package/skills/message-like-me/references/privacy.md +106 -0
  56. package/skills/message-like-me/references/profile-schema.md +148 -0
package/SECURITY.md ADDED
@@ -0,0 +1,318 @@
1
+ # Security
2
+
3
+ Report suspected vulnerabilities privately through
4
+ [GitHub Security Advisories](https://github.com/hraness/message-like-me/security/advisories/new).
5
+ Do not open a public issue containing a message, handle, contact name, group
6
+ title, attachment, local path, profile, study or Ensoul packet, installation key, or
7
+ database detail that could identify a person.
8
+
9
+ Include the affected version, platform, command or library call, expected
10
+ boundary, observed result, and a reproduction built from synthetic data.
11
+
12
+ ## Private-data boundary
13
+
14
+ Message Like Me reads private messaging history to derive local analysis. The
15
+ following values are sensitive even when they do not contain an obvious name:
16
+
17
+ - the source Messages and AddressBook databases and their SQLite sidecars;
18
+ - X data archive ZIPs and their archive, account, and overlap provenance;
19
+ - local message bundles, manifests, connected-account metadata, and provider
20
+ provenance;
21
+ - contact names, email addresses, and phone numbers;
22
+ - message bodies, timestamps, reply links, tapbacks, and attachment metadata;
23
+ - contact, participant, conversation, and group metadata;
24
+ - the per-install HMAC key and all normalized corpus records;
25
+ - aggregate metrics, study packets, style profiles, drafting context, and
26
+ unsent drafts;
27
+ - opaque Wrench route and context references, private handoff files, and full
28
+ Wrench receipts before their body-free audit projection.
29
+
30
+ The default data root is
31
+ `~/Library/Application Support/Message Like Me/` on macOS. The CLI creates
32
+ owned physical directories with mode `0700` and private files with mode
33
+ `0600`. It rejects symbolic-link redirection and foreign-owned source files at
34
+ the checked boundaries.
35
+
36
+ These filesystem permissions protect against accidental disclosure to other
37
+ local users. They are not encryption and do not protect data from another
38
+ process already running as the same user, a compromised agent host, malware,
39
+ device backup access, or an administrator.
40
+
41
+ ## Private agent handoffs
42
+
43
+ `routes list` writes source-conversation candidates only to an explicit
44
+ mode-`0600` file. Its stdout contains a digest, counts, and selection state.
45
+ The explicit `--private` file view contains only exact provider account,
46
+ source, and conversation coordinates already observed during ingestion. It
47
+ does not derive a send locator from a contact name, handle, title, or
48
+ participant set. X archives are evidence-only. Handoff v1 also rejects group
49
+ candidates, and an ambiguous direct-candidate inventory does not choose a
50
+ route automatically.
51
+
52
+ `handoff prepare` reads a mode-`0600`, singly linked route request, Wrench
53
+ context file, and draft file through stable file descriptors. A route candidate
54
+ never appears in argv or stdout. It rejects symlinks,
55
+ foreign ownership, broader permissions, file replacement, invalid UTF-8,
56
+ unknown contract fields, unsupported contract hashes, stale context, controls,
57
+ duplicate bubble IDs, and byte or count overages. The output is another
58
+ explicit mode-`0600` file. Message text and raw Wrench route or context
59
+ references never enter argv, ordinary stdout, diagnostics, or the SQLite audit
60
+ table.
61
+
62
+ The body-free Wrench receipt binding contains no raw route or context
63
+ reference. Its pinned contract binds hashes of those references, the client
64
+ intent, the exact ordered turn, and the private preview. The generic Wrench
65
+ field is `clientIntentSha256`; Message Like Me sets it to the exact private
66
+ handoff digest. The binding also carries its proven-prefix state and canonical
67
+ receipt digest. The local handoff audit stores those hashes, counts,
68
+ timestamps, and pseudonymous run and handoff IDs. Recording a
69
+ submitted, failed, partial, or indeterminate receipt cannot create corpus
70
+ messages or style evidence. Only later independent provider ingestion can do
71
+ that.
72
+
73
+ ## Messages ingestion
74
+
75
+ The original `chat.db` is the source of authority. The iMessage reader opens it
76
+ only after copying a byte-stable snapshot of the database and active journal or
77
+ WAL into a private temporary directory. It validates but does not copy shared
78
+ memory, then opens only the isolated copy with SQLite query-only mode inside one
79
+ transaction. It checks ownership and file identity before and after copying,
80
+ validates the required schema dynamically, and bounds source and result sizes.
81
+ It does not modify Messages, contacts, attachments, the source database, or its
82
+ sidecars.
83
+
84
+ Grant Messages or Full Disk Access only to the terminal or agent application
85
+ you intend to use. Message Like Me does not bypass macOS privacy controls.
86
+ `--database` should name only a caller-owned physical database whose contents
87
+ you intend to analyze.
88
+
89
+ Message text recovered from ordinary or attributed bodies retains its source
90
+ provenance. Missing or unsupported text remains unavailable rather than being
91
+ guessed. Reply targets and tapbacks remain separate from prose so they cannot
92
+ silently become authored style evidence.
93
+
94
+ ## X data archive ingestion
95
+
96
+ `messagelikeme ingest x-archive` accepts only a normalized absolute path to a
97
+ caller-owned, owner-only physical ZIP. It validates the archive container and
98
+ reads only bounded supported entries directly from the ZIP. It does not extract
99
+ files, evaluate the archive's JavaScript wrappers, open linked media, access X,
100
+ or make another network request. X Chat is not part of the supported archive
101
+ source.
102
+
103
+ The importer treats the complete ZIP as untrusted private input. It selects
104
+ direct-message and account evidence plus bounded reply and mention identity
105
+ metadata from reviewed tweet members. Tweet bodies do not become messaging
106
+ corpus or prose evidence. A normal X archive can contain other private account
107
+ data that Message Like Me does not need. Keep the original archive outside Git,
108
+ logs, issues, packages, and ordinary agent context.
109
+
110
+ The normalized source retains exact archive and account provenance. If the
111
+ caller supplies `--overlap-source`, the named source must be a compatible
112
+ Beeper X source for the same exact account. Only one-to-one direct conversations
113
+ with an exact peer handle and exact shared-message evidence can reconcile.
114
+ Group DMs remain separate because direction alone cannot prove which incoming
115
+ participant authored a message across providers. Missing, conflicting, or
116
+ ambiguous evidence fails closed before partial state is accepted. Reconciliation
117
+ retains both provenances while one proven exact message contributes once to
118
+ analysis. Reimporting the same or a later archive preserves the deduplication;
119
+ omission from a later archive is not a deletion signal.
120
+
121
+ X archive direct messages do not reveal whether an explicit reply link was
122
+ used. The importer records reply observability as unavailable rather than
123
+ inventing a reply target or treating absence as an observed non-reply.
124
+
125
+ ## Local message bundle ingestion
126
+
127
+ `messagelikeme ingest bundle` accepts only a normalized absolute path to a
128
+ current-user-owned physical mode-`0700` directory. Frozen Beeper v1 and native
129
+ WhatsApp v2 directories contain exactly `manifest.json` and six mode-`0600`
130
+ canonical UTF-8 NDJSON artifacts. Files must be regular, singly linked,
131
+ owner-controlled, stable while read, and free of symbolic-link traversal.
132
+
133
+ The importer validates the manifest before allocating for its artifacts. It
134
+ caps one line at 2 MiB, the complete bundle at 500,000 records and 512 MiB, and
135
+ connected accounts at 128 for v1 and exactly one for v2. It streams each
136
+ artifact, rejects invalid UTF-8, requires canonical JSON plus final newlines,
137
+ and verifies exact record counts, bytes, SHA-256 artifact digests, and the
138
+ canonical manifest projection digest. These checks detect malformed or changed
139
+ local input. They do not establish that the provider data is truthful or
140
+ complete.
141
+
142
+ V2 accepts only source `wacli-local@1.0.0`, provider `whatsapp@0.15.0`, and
143
+ network `whatsapp`. It requires canonical supported WhatsApp JIDs, complete
144
+ exact direct rosters, and proven message direction. Group rosters may remain
145
+ explicitly incomplete, and a direction-proven group row may retain a null
146
+ sender. Only a user JID's exact E.164 projection may become a Contacts-match
147
+ handle. It rejects status, broadcast, newsletter, ambiguous JID, credential,
148
+ session-state, provider-URL, and media-byte surfaces. Message Like Me never
149
+ discovers or starts Wacli, authenticates WhatsApp, synchronizes a linked device,
150
+ or accesses a network.
151
+
152
+ When `--overlap-source` names Beeper WhatsApp evidence, reconciliation requires
153
+ the same exact self E.164, exact one-to-one peer E.164, and unambiguous shared
154
+ text-message evidence. Bodyless records, groups, names, phone suffixes, and
155
+ approximate timestamps cannot establish equivalence. Both sources remain;
156
+ native Wacli evidence is preferred and the proven Beeper route is marked
157
+ `superseded-route`.
158
+
159
+ The accepted privacy declaration permits attachment metadata only and requires
160
+ provider URLs and credentials to be excluded. The bundle may still contain
161
+ message bodies, names, handles, timestamps, account identifiers, and graph
162
+ coordinates. Keep it under the same controls as the normalized store, and do
163
+ not place it in Git, logs, issues, packages, or ordinary agent context.
164
+
165
+ Each connected account is stored in its own per-install HMAC namespace.
166
+ Bounded, truncated, and unknown source absence never deletes retained history.
167
+ Explicit tombstones and terminal message or reaction state suppress their
168
+ validated targets. A later matching record can clear suppression, while an
169
+ older or conflicting equal-time snapshot is rejected. `sources list` is
170
+ redacted. `sources show --private` deliberately reveals provider account and
171
+ source metadata.
172
+
173
+ ## Contacts enrichment
174
+
175
+ Contacts enrichment is optional. The reader discovers populated
176
+ `Sources/*/AddressBook-vN.abcddb` stores and reads only the contact identifier,
177
+ name components, organization, email address, and phone-number columns needed
178
+ for labeling. It does not read notes, images, postal addresses, birthdays,
179
+ social profiles, or other AddressBook fields. It resolves contact entities and
180
+ their descendants through source metadata and uses the actual `ZOWNER` foreign
181
+ key rather than model-number discriminator columns.
182
+
183
+ Each source database and active journal or WAL is copied into a private
184
+ temporary directory only after bounded ownership, link, path, and byte-stability
185
+ checks. Shared memory is validated but never copied or opened. The original
186
+ AddressBook database and sidecars are never opened through SQLite, and the
187
+ complete discovered source set is checked again before any enrichment is
188
+ stored.
189
+
190
+ Email and phone matching is exact and conservative. The reader does not infer
191
+ a country, compare number suffixes, accept extensions or vanity numbers, or
192
+ choose between several contacts that claim one method. Ambiguous methods remain
193
+ unresolved. Group conversations are never collapsed to a single contact.
194
+
195
+ The private store retains contact labels and keyed HMAC match identifiers, not
196
+ raw AddressBook email addresses or phone numbers. Contact labels have their own
197
+ revision, so a rename does not change the message corpus revision or invalidate
198
+ a prose profile.
199
+
200
+ ## Local identifiers
201
+
202
+ Source, contact, participant, conversation, message, and reaction identifiers
203
+ are derived with an HMAC key
204
+ created for one local installation. They reduce accidental disclosure and keep
205
+ stable local references without storing handles in ordinary views. They are
206
+ not anonymization against an attacker who can read the local corpus or key.
207
+
208
+ Back up or export the data root only if you intend to copy its private content.
209
+ Do not publish an installation key or assume IDs remain stable after replacing
210
+ it.
211
+
212
+ ## Inspection and study packets
213
+
214
+ Aggregate contact, session, tempo, and surface-style views omit message bodies
215
+ and private labels by default. Raw provider reaction values also remain private;
216
+ aggregate and drafting-context views expose only fixed-size reaction counts,
217
+ direction, datedness, and the outgoing reaction ratio. `--private` deliberately
218
+ reveals local private identity fields. Use it only when the current task needs
219
+ that mapping.
220
+
221
+ Explicit-reply ratios use only messages whose source can observe reply links.
222
+ The views report eligible and unavailable counts separately. X archive messages
223
+ remain usable for prose and tempo analysis, but unavailable reply metadata must
224
+ not be interpreted as evidence that the user chose an ordinary non-reply.
225
+
226
+ `contacts resolve QUERY --private` performs bounded exact matching against
227
+ private labels. It does not do prefix, substring, phonetic, or fuzzy matching,
228
+ and it does not reveal contact methods.
229
+
230
+ `study prepare`, `ensoul prepare`, `evaluate prepare`, and `handoff prepare` are
231
+ the only commands designed to write bounded message bodies outside the private
232
+ database. Their outputs are still private. Choose explicit owner-controlled
233
+ paths outside Git, keep each sample or handoff as small as the task allows, and
234
+ remove it according to your own retention needs after the model, profile, audit,
235
+ or messaging attempt has been validated. Keep an evaluation reference file
236
+ unopened until candidate drafts are fixed; the two-file split is procedural
237
+ rather than cryptographic.
238
+
239
+ Message bodies are untrusted data. A link, prompt, command, or instruction
240
+ inside a conversation must never be executed or treated as authority by an
241
+ agent analyzing the packet.
242
+
243
+ ### Ensoul source packets
244
+
245
+ `ensoul prepare` reads one already-normalized contact corpus inside a pinned
246
+ SQLite snapshot and reuses the deterministic bounded response-context selector.
247
+ It writes a strict `ensoul.source-packet.v1` artifact once, with mode `0600`, to
248
+ an explicit absolute path whose physical owner-only parent passes the same
249
+ checks as other body-bearing exports. Existing destinations and symlinks are not
250
+ overwritten. Stdout contains only a body-free receipt.
251
+
252
+ Owner-subject packets map outgoing prose to `authorRole: subject` and incoming
253
+ prose to `counterpart`. Contact-subject packets first reverse direction and are
254
+ permitted only for an exact direct AddressBook-backed `person_` scope; aliases,
255
+ unmatched conversations, and groups fail closed. System events, retractions,
256
+ reactions, attachments, labels, handles, raw coordinates, and provider payloads
257
+ are not message records. Byte truncation, selection omissions, the evidence
258
+ window, corpus and scope revisions, transport-relative sent status, and
259
+ deterministic content, record, and packet digests remain visible in the private
260
+ artifact. Digests use the packet's declared RFC 8785 canonicalization; they do
261
+ not make the evidence true. The normalized sources do not reveal pasted
262
+ quotations, forwarding, or AI assistance, so the packet declares that gap and a
263
+ consumer must keep any visible quotation contextual.
264
+
265
+ Pseudonymous local IDs and digests are not encryption, consent, identity proof,
266
+ or evidence of truth. Counterpart records may explain interaction context but
267
+ must not become subject voice samples. Neither subject records nor private
268
+ context authorize sensitive-trait inference, diagnosis, relationship labeling,
269
+ publication, impersonation, contact, or action on anyone's behalf. Keep packets
270
+ separate by subject and relationship while synthesizing an owner model, and do
271
+ not search or browse using private packet text or identifiers.
272
+
273
+ ## Profiles and drafting
274
+
275
+ Profiles are strictly parsed, size-bounded, and bound to a contact ID, corpus
276
+ revision, scope-and-window-specific evidence revision, exact study-packet
277
+ SHA-256, and a non-body packet evidence manifest. This provenance detects stale
278
+ or unrelated analysis; it does not prove that a semantic interpretation is
279
+ true.
280
+
281
+ Only outgoing user-authored messages are evidence of the user's voice.
282
+ Incoming messages may explain context but must not be learned as the user's
283
+ style. Profiles should contain behavioral descriptions and study-example IDs,
284
+ not copied private prose or identifying contact fields.
285
+
286
+ Message Like Me has no command that sends, reacts to, schedules, or deletes a
287
+ message. A draft remains unsent text in the current agent task. Do not connect
288
+ the CLI or skill to a messaging automation without treating that as a separate
289
+ product and security boundary.
290
+
291
+ ## Network and credential boundary
292
+
293
+ The CLI and library have no AI provider, remote API, auth flow, account,
294
+ telemetry, analytics, or synchronization surface. They do not read an API key
295
+ or product credential. The Agent Skill relies on the agent already executing
296
+ the user's task; it must not make a second network or model call with message
297
+ data.
298
+
299
+ X archive ingestion uses only the ZIP path the caller supplies. It does not log
300
+ in to X, refresh an export, resolve a URL, or download media referenced by the
301
+ archive.
302
+
303
+ When that agent runs as a hosted service, opening a study or Ensoul packet
304
+ exposes its bounded excerpts to the agent provider under the provider's own data terms.
305
+ Message Like Me does not control or disguise that transfer. Use an agent
306
+ environment you authorize to process private conversations, and keep the
307
+ packet out of every additional tool or delegated agent unless the user
308
+ explicitly expands the scope.
309
+
310
+ The `messagelikeme.com` name does not authorize upload. The CLI does not
311
+ connect to that domain, and a future public website must remain data-blind
312
+ unless a separately reviewed product explicitly changes this boundary.
313
+
314
+ ## Supported versions
315
+
316
+ Security fixes are provided for the latest immutable GitHub Release. Verify
317
+ the tag and repository before installing from GitHub. Message Like Me is not
318
+ published to npm.
@@ -0,0 +1,179 @@
1
+ export declare const AGENTIC_MESSAGING_V1_SCHEMA_VERSION: 1;
2
+ export declare const AGENT_MESSAGE_DRAFT_V1_FORMAT: "message-like-me.agent-message-draft";
3
+ export declare const AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT: "message-like-me.agent-message-handoff-request";
4
+ export declare const AGENT_MESSAGE_HANDOFF_V1_FORMAT: "message-like-me.agent-message-handoff";
5
+ export declare const AGENT_MESSAGE_AUDIT_V1_FORMAT: "message-like-me.agent-message-handoff-audit";
6
+ export declare const WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT: "wrench.messaging-context-binding";
7
+ export declare const WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT: "wrench.messaging-receipt-binding";
8
+ export declare const WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID: "wrench.messaging-context-binding.v1";
9
+ export declare const WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH: "5e64da6a3d826e7f6fa3db7dca0a4ba92c10cfb784981e71a25aed9513a5c687";
10
+ export declare const WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_DESCRIPTOR: Readonly<{
11
+ contractId: "wrench.messaging-context-binding.v1";
12
+ fields: readonly string[];
13
+ format: "wrench.messaging-contract-descriptor";
14
+ schemaVersion: 1;
15
+ }>;
16
+ export declare const WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID: "wrench.messaging-receipt-binding.v1";
17
+ export declare const WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH: "7f6cf724f0200b2399e4f4641c637b20b48914fc5c9b13755127a8ec69fe66f4";
18
+ export declare const WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_DESCRIPTOR: Readonly<{
19
+ contractId: "wrench.messaging-receipt-binding.v1";
20
+ fields: readonly string[];
21
+ format: "wrench.messaging-contract-descriptor";
22
+ schemaVersion: 1;
23
+ }>;
24
+ export declare const AGENTIC_MESSAGING_V1_LIMITS: Readonly<{
25
+ readonly bubbles: 8;
26
+ readonly bubbleBytes: number;
27
+ readonly totalBubbleBytes: number;
28
+ readonly identifierBytes: 1024;
29
+ readonly privateJsonBytes: number;
30
+ readonly handoffLifetimeMilliseconds: number;
31
+ readonly maximumContextLifetimeMilliseconds: number;
32
+ }>;
33
+ export type WrenchMessagingContextBindingV1 = Readonly<{
34
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
35
+ format: typeof WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT;
36
+ contractId: typeof WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID;
37
+ contractHash: typeof WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH;
38
+ routeRef: string;
39
+ contextRef: string;
40
+ exactDataRevision: string;
41
+ latestMessageRevision: string;
42
+ validatedAt: string;
43
+ expiresAt: string;
44
+ }>;
45
+ export type AgentMessageBubbleV1 = Readonly<{
46
+ id: string;
47
+ text: string;
48
+ replyToRef: string | null;
49
+ }>;
50
+ export type AgentMessageDraftV1 = Readonly<{
51
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
52
+ format: typeof AGENT_MESSAGE_DRAFT_V1_FORMAT;
53
+ bubbles: readonly AgentMessageBubbleV1[];
54
+ }>;
55
+ export type AgentMessageHandoffRequestV1 = Readonly<{
56
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
57
+ format: typeof AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT;
58
+ routeCandidateId: string;
59
+ }>;
60
+ export type AgentMessageProfileStateV1 = "current" | "missing" | "stale";
61
+ export type AgentMessageHandoffV1 = Readonly<{
62
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
63
+ format: typeof AGENT_MESSAGE_HANDOFF_V1_FORMAT;
64
+ handoffId: string;
65
+ createdAt: string;
66
+ expiresAt: string;
67
+ contact: Readonly<{
68
+ contactId: string;
69
+ routeCandidateId: string;
70
+ sourceId: string;
71
+ conversationId: string;
72
+ }>;
73
+ evidence: Readonly<{
74
+ corpusRevision: string;
75
+ sourceRevision: string;
76
+ profileState: AgentMessageProfileStateV1;
77
+ profileEvidenceRevision: string | null;
78
+ }>;
79
+ wrench: Readonly<{
80
+ contractId: typeof WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID;
81
+ contractHash: typeof WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH;
82
+ routeRef: string;
83
+ routeRefSha256: string;
84
+ contextRef: string;
85
+ contextRefSha256: string;
86
+ exactDataRevision: string;
87
+ latestMessageRevision: string;
88
+ validatedAt: string;
89
+ contextExpiresAt: string;
90
+ }>;
91
+ turn: Readonly<{
92
+ bubbles: readonly AgentMessageBubbleV1[];
93
+ }>;
94
+ privacy: Readonly<{
95
+ classification: "private-local";
96
+ excludedFields: readonly [
97
+ "attachments",
98
+ "credentials",
99
+ "provider-coordinates",
100
+ "provider-payloads"
101
+ ];
102
+ }>;
103
+ integrity: Readonly<{
104
+ algorithm: "sha256";
105
+ canonicalSha256: string;
106
+ }>;
107
+ }>;
108
+ export type AgentMessageRouteCandidateV1 = Readonly<{
109
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
110
+ format: "message-like-me.source-conversation-route";
111
+ id: string;
112
+ contactId: string;
113
+ sourceId: string;
114
+ conversationId: string;
115
+ sourceKind: "bundle" | "imessage" | "x-archive";
116
+ provider: string;
117
+ network: string | null;
118
+ service: string | null;
119
+ group: boolean;
120
+ sourceRevision: string;
121
+ actionability: Readonly<{
122
+ state: "evidence-only" | "wrench-binding-eligible";
123
+ reason: "archive-source" | "group-conversation" | "requires-exact-wrench-binding" | "superseded-route" | "unsupported-route";
124
+ }>;
125
+ privateBinding: Readonly<{
126
+ sourceAccountId: string | null;
127
+ sourceExternalId: string;
128
+ coordinate: Readonly<{
129
+ kind: "beeperConversation";
130
+ network: string;
131
+ conversationId: string;
132
+ }> | Readonly<{
133
+ kind: "imessageChat";
134
+ chatGuid: string;
135
+ service: string | null;
136
+ observedChatRowId: number | null;
137
+ }> | Readonly<{
138
+ kind: "whatsappJid";
139
+ jid: string;
140
+ }>;
141
+ }> | null;
142
+ }>;
143
+ export type WrenchMessagingReceiptStateV1 = "failed" | "indeterminate" | "partial" | "submitted";
144
+ export type WrenchMessagingReceiptBindingV1 = Readonly<{
145
+ schemaVersion: typeof AGENTIC_MESSAGING_V1_SCHEMA_VERSION;
146
+ format: typeof WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT;
147
+ contractId: typeof WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID;
148
+ contractHash: typeof WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH;
149
+ clientIntentSha256: string;
150
+ routeRefSha256: string;
151
+ contextRefSha256: string;
152
+ turnDigest: string;
153
+ previewDigest: string;
154
+ runId: string;
155
+ state: WrenchMessagingReceiptStateV1;
156
+ partCount: number;
157
+ provenPartCount: number;
158
+ receiptSha256: string;
159
+ recordedAt: string;
160
+ }>;
161
+ export declare class AgenticMessagingV1ContractError extends TypeError {
162
+ readonly code: "agentic-messaging-v1-contract";
163
+ constructor(message: string, options?: ErrorOptions);
164
+ }
165
+ export declare function parseWrenchMessagingContextBindingV1(value: unknown): WrenchMessagingContextBindingV1;
166
+ export declare function parseAgentMessageDraftV1(value: unknown): AgentMessageDraftV1;
167
+ export declare function parseAgentMessageHandoffRequestV1(value: unknown): AgentMessageHandoffRequestV1;
168
+ export declare function createAgentMessageHandoffV1(input: Readonly<{
169
+ createdAt: string;
170
+ expiresAt: string;
171
+ contact: AgentMessageHandoffV1["contact"];
172
+ evidence: AgentMessageHandoffV1["evidence"];
173
+ wrenchContext: WrenchMessagingContextBindingV1;
174
+ draft: AgentMessageDraftV1;
175
+ }>): AgentMessageHandoffV1;
176
+ export declare function parseAgentMessageHandoffV1(value: unknown): AgentMessageHandoffV1;
177
+ export declare function wrenchMessagingTurnDigestV1(value: unknown): string;
178
+ export declare function parseWrenchMessagingReceiptBindingV1(value: unknown): WrenchMessagingReceiptBindingV1;
179
+ export declare function agentMessageRouteCandidateId(sourceId: string, conversationId: string): string;
@@ -0,0 +1,52 @@
1
+ // @bun
2
+ import {
3
+ AGENTIC_MESSAGING_V1_LIMITS,
4
+ AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
5
+ AGENT_MESSAGE_AUDIT_V1_FORMAT,
6
+ AGENT_MESSAGE_DRAFT_V1_FORMAT,
7
+ AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT,
8
+ AGENT_MESSAGE_HANDOFF_V1_FORMAT,
9
+ AgenticMessagingV1ContractError,
10
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_DESCRIPTOR,
11
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH,
12
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID,
13
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT,
14
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_DESCRIPTOR,
15
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH,
16
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID,
17
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT,
18
+ agentMessageRouteCandidateId,
19
+ createAgentMessageHandoffV1,
20
+ parseAgentMessageDraftV1,
21
+ parseAgentMessageHandoffRequestV1,
22
+ parseAgentMessageHandoffV1,
23
+ parseWrenchMessagingContextBindingV1,
24
+ parseWrenchMessagingReceiptBindingV1,
25
+ wrenchMessagingTurnDigestV1
26
+ } from "./cli-d7qv38ab.js";
27
+ import"./cli-ththzwja.js";
28
+ export {
29
+ wrenchMessagingTurnDigestV1,
30
+ parseWrenchMessagingReceiptBindingV1,
31
+ parseWrenchMessagingContextBindingV1,
32
+ parseAgentMessageHandoffV1,
33
+ parseAgentMessageHandoffRequestV1,
34
+ parseAgentMessageDraftV1,
35
+ createAgentMessageHandoffV1,
36
+ agentMessageRouteCandidateId,
37
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT,
38
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID,
39
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH,
40
+ WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_DESCRIPTOR,
41
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT,
42
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID,
43
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH,
44
+ WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_DESCRIPTOR,
45
+ AgenticMessagingV1ContractError,
46
+ AGENT_MESSAGE_HANDOFF_V1_FORMAT,
47
+ AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT,
48
+ AGENT_MESSAGE_DRAFT_V1_FORMAT,
49
+ AGENT_MESSAGE_AUDIT_V1_FORMAT,
50
+ AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
51
+ AGENTIC_MESSAGING_V1_LIMITS
52
+ };
@@ -0,0 +1,3 @@
1
+ export declare function canonicalJson(value: unknown): string;
2
+ export declare function sha256(value: string | Uint8Array): string;
3
+ export declare function prettyJson(value: unknown): string;