@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
@@ -0,0 +1,485 @@
1
+ // @bun
2
+ import {
3
+ canonicalJson,
4
+ sha256
5
+ } from "./cli-ththzwja.js";
6
+
7
+ // src/agentic-messaging-v1.ts
8
+ import { types as nodeTypes } from "util";
9
+ var AGENTIC_MESSAGING_V1_SCHEMA_VERSION = 1;
10
+ var AGENT_MESSAGE_DRAFT_V1_FORMAT = "message-like-me.agent-message-draft";
11
+ var AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT = "message-like-me.agent-message-handoff-request";
12
+ var AGENT_MESSAGE_HANDOFF_V1_FORMAT = "message-like-me.agent-message-handoff";
13
+ var AGENT_MESSAGE_AUDIT_V1_FORMAT = "message-like-me.agent-message-handoff-audit";
14
+ var WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT = "wrench.messaging-context-binding";
15
+ var WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT = "wrench.messaging-receipt-binding";
16
+ var WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID = "wrench.messaging-context-binding.v1";
17
+ var WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH = "5e64da6a3d826e7f6fa3db7dca0a4ba92c10cfb784981e71a25aed9513a5c687";
18
+ var WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_DESCRIPTOR = Object.freeze({
19
+ contractId: WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID,
20
+ fields: Object.freeze([
21
+ "schemaVersion:1",
22
+ "format:wrench.messaging-context-binding",
23
+ "contractId:wrench.messaging-context-binding.v1",
24
+ "contractHash:sha256",
25
+ "routeRef:opaque",
26
+ "contextRef:opaque",
27
+ "exactDataRevision:sha256",
28
+ "latestMessageRevision:sha256",
29
+ "validatedAt:rfc3339",
30
+ "expiresAt:rfc3339"
31
+ ]),
32
+ format: "wrench.messaging-contract-descriptor",
33
+ schemaVersion: 1
34
+ });
35
+ var WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID = "wrench.messaging-receipt-binding.v1";
36
+ var WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH = "7f6cf724f0200b2399e4f4641c637b20b48914fc5c9b13755127a8ec69fe66f4";
37
+ var WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_DESCRIPTOR = Object.freeze({
38
+ contractId: WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID,
39
+ fields: Object.freeze([
40
+ "schemaVersion:1",
41
+ "format:wrench.messaging-receipt-binding",
42
+ "contractId:wrench.messaging-receipt-binding.v1",
43
+ "contractHash:sha256",
44
+ "clientIntentSha256:sha256",
45
+ "routeRefSha256:sha256",
46
+ "contextRefSha256:sha256",
47
+ "turnDigest:sha256",
48
+ "previewDigest:sha256",
49
+ "runId:opaque",
50
+ "state:submitted|failed|partial|indeterminate",
51
+ "partCount:uint",
52
+ "provenPartCount:uint",
53
+ "receiptSha256:sha256",
54
+ "recordedAt:rfc3339"
55
+ ]),
56
+ format: "wrench.messaging-contract-descriptor",
57
+ schemaVersion: 1
58
+ });
59
+ var AGENTIC_MESSAGING_V1_LIMITS = Object.freeze({
60
+ bubbles: 8,
61
+ bubbleBytes: 8 * 1024,
62
+ totalBubbleBytes: 32 * 1024,
63
+ identifierBytes: 1024,
64
+ privateJsonBytes: 128 * 1024,
65
+ handoffLifetimeMilliseconds: 10 * 60 * 1000,
66
+ maximumContextLifetimeMilliseconds: 24 * 60 * 60 * 1000
67
+ });
68
+
69
+ class AgenticMessagingV1ContractError extends TypeError {
70
+ code = "agentic-messaging-v1-contract";
71
+ constructor(message, options) {
72
+ super(message, options);
73
+ this.name = "AgenticMessagingV1ContractError";
74
+ }
75
+ }
76
+ function fail(message) {
77
+ throw new AgenticMessagingV1ContractError(message);
78
+ }
79
+ function object(value, label) {
80
+ if (value === null || typeof value !== "object" || Array.isArray(value) || nodeTypes.isProxy(value) || Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null)
81
+ return fail(`${label} must be a plain object`);
82
+ for (const key of Reflect.ownKeys(value)) {
83
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
84
+ if (typeof key !== "string" || descriptor === undefined || descriptor.enumerable !== true || !("value" in descriptor))
85
+ return fail(`${label} must contain only enumerable string data properties`);
86
+ }
87
+ return value;
88
+ }
89
+ function exactKeys(value, keys, label) {
90
+ const expected = [...keys].sort();
91
+ const observed = Reflect.ownKeys(value).map(String).sort();
92
+ if (expected.length !== observed.length || observed.some((key, index) => key !== expected[index])) {
93
+ fail(`${label} must contain exactly: ${keys.join(", ")}`);
94
+ }
95
+ }
96
+ function denseArray(value, label, minimum, maximum) {
97
+ if (!Array.isArray(value) || nodeTypes.isProxy(value) || Object.getPrototypeOf(value) !== Array.prototype || value.length < minimum || value.length > maximum)
98
+ return fail(`${label} must contain ${minimum} through ${maximum} items`);
99
+ const keys = Reflect.ownKeys(value);
100
+ const expected = new Set(["length", ...Array.from({ length: value.length }, (_item, index) => String(index))]);
101
+ for (const key of keys) {
102
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
103
+ if (typeof key !== "string" || !expected.has(key) || descriptor === undefined || !("value" in descriptor) || key !== "length" && descriptor.enumerable !== true)
104
+ return fail(`${label} must be a dense array of data properties`);
105
+ }
106
+ if (keys.length !== expected.size)
107
+ return fail(`${label} must be a dense array of data properties`);
108
+ return value;
109
+ }
110
+ function utf8Bytes(value) {
111
+ return new TextEncoder().encode(value).byteLength;
112
+ }
113
+ function isWellFormedUnicode(value) {
114
+ for (let index = 0;index < value.length; index += 1) {
115
+ const unit = value.charCodeAt(index);
116
+ if (unit >= 55296 && unit <= 56319) {
117
+ const next = value.charCodeAt(index + 1);
118
+ if (!(next >= 56320 && next <= 57343))
119
+ return false;
120
+ index += 1;
121
+ } else if (unit >= 56320 && unit <= 57343) {
122
+ return false;
123
+ }
124
+ }
125
+ return true;
126
+ }
127
+ function boundedText(value, label, maximum) {
128
+ if (typeof value !== "string" || !isWellFormedUnicode(value) || utf8Bytes(value) > maximum || value.includes("\x00"))
129
+ return fail(`${label} must be well-formed NUL-free text within ${maximum} UTF-8 bytes`);
130
+ return value;
131
+ }
132
+ function identifier(value, label, maximum = AGENTIC_MESSAGING_V1_LIMITS.identifierBytes) {
133
+ const result = boundedText(value, label, maximum);
134
+ if (result.length === 0 || /\p{Cc}|\p{Zl}|\p{Zp}/u.test(result) || result !== result.trim()) {
135
+ return fail(`${label} must be a bounded opaque identifier without controls or surrounding space`);
136
+ }
137
+ return result;
138
+ }
139
+ function digest(value, label) {
140
+ const result = boundedText(value, label, 64);
141
+ if (!/^[a-f0-9]{64}$/u.test(result))
142
+ return fail(`${label} must be lowercase SHA-256`);
143
+ return result;
144
+ }
145
+ function routeCandidateId(value, label) {
146
+ const result = identifier(value, label, 70);
147
+ if (!/^route_[a-f0-9]{64}$/u.test(result)) {
148
+ return fail(`${label} must be a canonical source-conversation route ID`);
149
+ }
150
+ return result;
151
+ }
152
+ function timestamp(value, label) {
153
+ const result = boundedText(value, label, 64);
154
+ const parsed = new Date(result);
155
+ if (!Number.isFinite(parsed.getTime()) || parsed.toISOString() !== result) {
156
+ return fail(`${label} must be a canonical UTC timestamp`);
157
+ }
158
+ return result;
159
+ }
160
+ function bubble(value, label) {
161
+ const record = object(value, label);
162
+ exactKeys(record, ["id", "text", "replyToRef"], label);
163
+ const text = boundedText(record.text, `${label}.text`, AGENTIC_MESSAGING_V1_LIMITS.bubbleBytes);
164
+ if (text.trim().length === 0 || /[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/u.test(text)) {
165
+ return fail(`${label}.text must contain visible text and no unsupported controls`);
166
+ }
167
+ return Object.freeze({
168
+ id: identifier(record.id, `${label}.id`, 128),
169
+ text,
170
+ replyToRef: record.replyToRef === null ? null : identifier(record.replyToRef, `${label}.replyToRef`)
171
+ });
172
+ }
173
+ function bubbles(value, label) {
174
+ const result = denseArray(value, label, 1, AGENTIC_MESSAGING_V1_LIMITS.bubbles).map((item, index) => bubble(item, `${label}[${index}]`));
175
+ if (new Set(result.map(({ id }) => id)).size !== result.length)
176
+ fail(`${label} repeats a bubble ID`);
177
+ if (result.reduce((sum, item) => sum + utf8Bytes(item.text), 0) > AGENTIC_MESSAGING_V1_LIMITS.totalBubbleBytes) {
178
+ fail(`${label} exceeds the total text bound`);
179
+ }
180
+ return Object.freeze(result);
181
+ }
182
+ function profileState(value, label) {
183
+ if (value !== "current" && value !== "missing" && value !== "stale") {
184
+ return fail(`${label} must be current, missing, or stale`);
185
+ }
186
+ return value;
187
+ }
188
+ function handoffCore(value) {
189
+ return value;
190
+ }
191
+ function handoffDigest(value) {
192
+ return sha256(canonicalJson(handoffCore(value)));
193
+ }
194
+ function parseWrenchMessagingContextBindingV1(value) {
195
+ const record = object(value, "Wrench messaging context binding");
196
+ exactKeys(record, [
197
+ "schemaVersion",
198
+ "format",
199
+ "contractId",
200
+ "contractHash",
201
+ "routeRef",
202
+ "contextRef",
203
+ "exactDataRevision",
204
+ "latestMessageRevision",
205
+ "validatedAt",
206
+ "expiresAt"
207
+ ], "Wrench messaging context binding");
208
+ if (record.schemaVersion !== AGENTIC_MESSAGING_V1_SCHEMA_VERSION || record.format !== WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT)
209
+ return fail("Wrench messaging context binding has the wrong schemaVersion or format");
210
+ if (record.contractId !== WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID || record.contractHash !== WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH)
211
+ return fail("Wrench messaging context binding has an unsupported contract identity");
212
+ const validatedAt = timestamp(record.validatedAt, "Wrench messaging context binding.validatedAt");
213
+ const expiresAt = timestamp(record.expiresAt, "Wrench messaging context binding.expiresAt");
214
+ const lifetime = Date.parse(expiresAt) - Date.parse(validatedAt);
215
+ if (lifetime <= 0 || lifetime > AGENTIC_MESSAGING_V1_LIMITS.maximumContextLifetimeMilliseconds) {
216
+ return fail("Wrench messaging context binding has an invalid lifetime");
217
+ }
218
+ return Object.freeze({
219
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
220
+ format: WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT,
221
+ contractId: WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID,
222
+ contractHash: WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH,
223
+ routeRef: identifier(record.routeRef, "Wrench messaging context binding.routeRef"),
224
+ contextRef: identifier(record.contextRef, "Wrench messaging context binding.contextRef"),
225
+ exactDataRevision: digest(record.exactDataRevision, "Wrench messaging context binding.exactDataRevision"),
226
+ latestMessageRevision: digest(record.latestMessageRevision, "Wrench messaging context binding.latestMessageRevision"),
227
+ validatedAt,
228
+ expiresAt
229
+ });
230
+ }
231
+ function parseAgentMessageDraftV1(value) {
232
+ const record = object(value, "Agent message draft");
233
+ exactKeys(record, ["schemaVersion", "format", "bubbles"], "Agent message draft");
234
+ if (record.schemaVersion !== AGENTIC_MESSAGING_V1_SCHEMA_VERSION || record.format !== AGENT_MESSAGE_DRAFT_V1_FORMAT)
235
+ return fail("Agent message draft has the wrong schemaVersion or format");
236
+ return Object.freeze({
237
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
238
+ format: AGENT_MESSAGE_DRAFT_V1_FORMAT,
239
+ bubbles: bubbles(record.bubbles, "Agent message draft.bubbles")
240
+ });
241
+ }
242
+ function parseAgentMessageHandoffRequestV1(value) {
243
+ const record = object(value, "Agent message handoff request");
244
+ exactKeys(record, ["schemaVersion", "format", "routeCandidateId"], "Agent message handoff request");
245
+ if (record.schemaVersion !== AGENTIC_MESSAGING_V1_SCHEMA_VERSION || record.format !== AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT)
246
+ return fail("Agent message handoff request has the wrong schemaVersion or format");
247
+ return Object.freeze({
248
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
249
+ format: AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT,
250
+ routeCandidateId: routeCandidateId(record.routeCandidateId, "Agent message handoff request.routeCandidateId")
251
+ });
252
+ }
253
+ function createAgentMessageHandoffV1(input) {
254
+ const context = parseWrenchMessagingContextBindingV1(input.wrenchContext);
255
+ const draft = parseAgentMessageDraftV1(input.draft);
256
+ const core = Object.freeze({
257
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
258
+ format: AGENT_MESSAGE_HANDOFF_V1_FORMAT,
259
+ createdAt: timestamp(input.createdAt, "Agent message handoff.createdAt"),
260
+ expiresAt: timestamp(input.expiresAt, "Agent message handoff.expiresAt"),
261
+ contact: Object.freeze({
262
+ contactId: identifier(input.contact.contactId, "Agent message handoff.contact.contactId"),
263
+ routeCandidateId: routeCandidateId(input.contact.routeCandidateId, "Agent message handoff.contact.routeCandidateId"),
264
+ sourceId: identifier(input.contact.sourceId, "Agent message handoff.contact.sourceId"),
265
+ conversationId: identifier(input.contact.conversationId, "Agent message handoff.contact.conversationId")
266
+ }),
267
+ evidence: Object.freeze({
268
+ corpusRevision: digest(input.evidence.corpusRevision, "Agent message handoff.evidence.corpusRevision"),
269
+ sourceRevision: digest(input.evidence.sourceRevision, "Agent message handoff.evidence.sourceRevision"),
270
+ profileState: profileState(input.evidence.profileState, "Agent message handoff.evidence.profileState"),
271
+ profileEvidenceRevision: input.evidence.profileEvidenceRevision === null ? null : digest(input.evidence.profileEvidenceRevision, "Agent message handoff.evidence.profileEvidenceRevision")
272
+ }),
273
+ wrench: Object.freeze({
274
+ contractId: context.contractId,
275
+ contractHash: context.contractHash,
276
+ routeRef: context.routeRef,
277
+ routeRefSha256: sha256(context.routeRef),
278
+ contextRef: context.contextRef,
279
+ contextRefSha256: sha256(context.contextRef),
280
+ exactDataRevision: context.exactDataRevision,
281
+ latestMessageRevision: context.latestMessageRevision,
282
+ validatedAt: context.validatedAt,
283
+ contextExpiresAt: context.expiresAt
284
+ }),
285
+ turn: Object.freeze({ bubbles: draft.bubbles }),
286
+ privacy: Object.freeze({
287
+ classification: "private-local",
288
+ excludedFields: Object.freeze([
289
+ "attachments",
290
+ "credentials",
291
+ "provider-coordinates",
292
+ "provider-payloads"
293
+ ])
294
+ })
295
+ });
296
+ const lifetime = Date.parse(core.expiresAt) - Date.parse(core.createdAt);
297
+ if (lifetime <= 0 || lifetime > AGENTIC_MESSAGING_V1_LIMITS.handoffLifetimeMilliseconds || core.createdAt < core.wrench.validatedAt) {
298
+ return fail("Agent message handoff timestamps are inconsistent");
299
+ }
300
+ if (core.expiresAt > core.wrench.contextExpiresAt) {
301
+ return fail("Agent message handoff outlives its Wrench context binding");
302
+ }
303
+ const canonicalSha256 = handoffDigest(core);
304
+ return Object.freeze({
305
+ ...core,
306
+ handoffId: `handoff_${canonicalSha256}`,
307
+ integrity: Object.freeze({ algorithm: "sha256", canonicalSha256 })
308
+ });
309
+ }
310
+ function parseAgentMessageHandoffV1(value) {
311
+ const record = object(value, "Agent message handoff");
312
+ exactKeys(record, [
313
+ "schemaVersion",
314
+ "format",
315
+ "handoffId",
316
+ "createdAt",
317
+ "expiresAt",
318
+ "contact",
319
+ "evidence",
320
+ "wrench",
321
+ "turn",
322
+ "privacy",
323
+ "integrity"
324
+ ], "Agent message handoff");
325
+ if (record.schemaVersion !== AGENTIC_MESSAGING_V1_SCHEMA_VERSION || record.format !== AGENT_MESSAGE_HANDOFF_V1_FORMAT)
326
+ return fail("Agent message handoff has the wrong schemaVersion or format");
327
+ const contactRecord = object(record.contact, "Agent message handoff.contact");
328
+ exactKeys(contactRecord, ["contactId", "routeCandidateId", "sourceId", "conversationId"], "Agent message handoff.contact");
329
+ const evidenceRecord = object(record.evidence, "Agent message handoff.evidence");
330
+ exactKeys(evidenceRecord, [
331
+ "corpusRevision",
332
+ "sourceRevision",
333
+ "profileState",
334
+ "profileEvidenceRevision"
335
+ ], "Agent message handoff.evidence");
336
+ const wrenchRecord = object(record.wrench, "Agent message handoff.wrench");
337
+ exactKeys(wrenchRecord, [
338
+ "contractId",
339
+ "contractHash",
340
+ "routeRef",
341
+ "routeRefSha256",
342
+ "contextRef",
343
+ "contextRefSha256",
344
+ "exactDataRevision",
345
+ "latestMessageRevision",
346
+ "validatedAt",
347
+ "contextExpiresAt"
348
+ ], "Agent message handoff.wrench");
349
+ const turnRecord = object(record.turn, "Agent message handoff.turn");
350
+ exactKeys(turnRecord, ["bubbles"], "Agent message handoff.turn");
351
+ const privacyRecord = object(record.privacy, "Agent message handoff.privacy");
352
+ exactKeys(privacyRecord, ["classification", "excludedFields"], "Agent message handoff.privacy");
353
+ const excluded = denseArray(privacyRecord.excludedFields, "Agent message handoff.privacy.excludedFields", 4, 4);
354
+ const expectedExcluded = ["attachments", "credentials", "provider-coordinates", "provider-payloads"];
355
+ if (excluded.some((item, index) => item !== expectedExcluded[index])) {
356
+ return fail("Agent message handoff.privacy.excludedFields is not canonical");
357
+ }
358
+ if (privacyRecord.classification !== "private-local") {
359
+ return fail("Agent message handoff must be classified private-local");
360
+ }
361
+ const integrityRecord = object(record.integrity, "Agent message handoff.integrity");
362
+ exactKeys(integrityRecord, ["algorithm", "canonicalSha256"], "Agent message handoff.integrity");
363
+ if (integrityRecord.algorithm !== "sha256")
364
+ return fail("Agent message handoff integrity algorithm must be sha256");
365
+ const context = parseWrenchMessagingContextBindingV1({
366
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
367
+ format: WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT,
368
+ contractId: wrenchRecord.contractId,
369
+ contractHash: wrenchRecord.contractHash,
370
+ routeRef: wrenchRecord.routeRef,
371
+ contextRef: wrenchRecord.contextRef,
372
+ exactDataRevision: wrenchRecord.exactDataRevision,
373
+ latestMessageRevision: wrenchRecord.latestMessageRevision,
374
+ validatedAt: wrenchRecord.validatedAt,
375
+ expiresAt: wrenchRecord.contextExpiresAt
376
+ });
377
+ const handoff = createAgentMessageHandoffV1({
378
+ createdAt: timestamp(record.createdAt, "Agent message handoff.createdAt"),
379
+ expiresAt: timestamp(record.expiresAt, "Agent message handoff.expiresAt"),
380
+ contact: {
381
+ contactId: identifier(contactRecord.contactId, "Agent message handoff.contact.contactId"),
382
+ routeCandidateId: routeCandidateId(contactRecord.routeCandidateId, "Agent message handoff.contact.routeCandidateId"),
383
+ sourceId: identifier(contactRecord.sourceId, "Agent message handoff.contact.sourceId"),
384
+ conversationId: identifier(contactRecord.conversationId, "Agent message handoff.contact.conversationId")
385
+ },
386
+ evidence: {
387
+ corpusRevision: digest(evidenceRecord.corpusRevision, "Agent message handoff.evidence.corpusRevision"),
388
+ sourceRevision: digest(evidenceRecord.sourceRevision, "Agent message handoff.evidence.sourceRevision"),
389
+ profileState: profileState(evidenceRecord.profileState, "Agent message handoff.evidence.profileState"),
390
+ profileEvidenceRevision: evidenceRecord.profileEvidenceRevision === null ? null : digest(evidenceRecord.profileEvidenceRevision, "Agent message handoff.evidence.profileEvidenceRevision")
391
+ },
392
+ wrenchContext: context,
393
+ draft: {
394
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
395
+ format: AGENT_MESSAGE_DRAFT_V1_FORMAT,
396
+ bubbles: bubbles(turnRecord.bubbles, "Agent message handoff.turn.bubbles")
397
+ }
398
+ });
399
+ const suppliedRouteSha = digest(wrenchRecord.routeRefSha256, "Agent message handoff.wrench.routeRefSha256");
400
+ const suppliedContextSha = digest(wrenchRecord.contextRefSha256, "Agent message handoff.wrench.contextRefSha256");
401
+ const suppliedCanonicalSha = digest(integrityRecord.canonicalSha256, "Agent message handoff.integrity.canonicalSha256");
402
+ if (suppliedRouteSha !== handoff.wrench.routeRefSha256 || suppliedContextSha !== handoff.wrench.contextRefSha256 || suppliedCanonicalSha !== handoff.integrity.canonicalSha256 || record.handoffId !== handoff.handoffId)
403
+ return fail("Agent message handoff integrity does not match its canonical content");
404
+ return handoff;
405
+ }
406
+ function wrenchMessagingTurnDigestV1(value) {
407
+ const handoff = parseAgentMessageHandoffV1(value);
408
+ return sha256(canonicalJson({
409
+ schemaVersion: 1,
410
+ format: "wrench.messaging-turn",
411
+ clientIntentSha256: handoff.integrity.canonicalSha256,
412
+ routeRef: handoff.wrench.routeRef,
413
+ contextRef: handoff.wrench.contextRef,
414
+ parts: handoff.turn.bubbles.map((bubble2) => ({
415
+ partId: bubble2.id,
416
+ text: bubble2.text,
417
+ replyRef: bubble2.replyToRef
418
+ }))
419
+ }));
420
+ }
421
+ function parseWrenchMessagingReceiptBindingV1(value) {
422
+ const record = object(value, "Wrench messaging receipt binding");
423
+ exactKeys(record, [
424
+ "schemaVersion",
425
+ "format",
426
+ "contractId",
427
+ "contractHash",
428
+ "clientIntentSha256",
429
+ "routeRefSha256",
430
+ "contextRefSha256",
431
+ "turnDigest",
432
+ "previewDigest",
433
+ "runId",
434
+ "state",
435
+ "partCount",
436
+ "provenPartCount",
437
+ "receiptSha256",
438
+ "recordedAt"
439
+ ], "Wrench messaging receipt binding");
440
+ if (record.schemaVersion !== AGENTIC_MESSAGING_V1_SCHEMA_VERSION || record.format !== WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT)
441
+ return fail("Wrench messaging receipt binding has the wrong schemaVersion or format");
442
+ if (record.contractId !== WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID || record.contractHash !== WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH)
443
+ return fail("Wrench messaging receipt binding has an unsupported contract identity");
444
+ if (record.state !== "submitted" && record.state !== "failed" && record.state !== "partial" && record.state !== "indeterminate")
445
+ return fail("Wrench messaging receipt binding has an invalid state");
446
+ if (!Number.isSafeInteger(record.partCount) || record.partCount < 1 || record.partCount > 8) {
447
+ return fail("Wrench messaging receipt binding.partCount must be from 1 through 8");
448
+ }
449
+ if (!Number.isSafeInteger(record.provenPartCount) || record.provenPartCount < 0 || record.provenPartCount > record.partCount)
450
+ return fail("Wrench messaging receipt binding.provenPartCount is out of range");
451
+ const partCount = record.partCount;
452
+ const provenPartCount = record.provenPartCount;
453
+ if (record.state === "submitted" && provenPartCount !== partCount || record.state === "failed" && provenPartCount !== 0 || record.state === "partial" && (provenPartCount < 1 || provenPartCount >= partCount) || record.state === "indeterminate" && provenPartCount >= partCount)
454
+ return fail("Wrench messaging receipt binding state does not match its proven prefix");
455
+ const parsed = Object.freeze({
456
+ schemaVersion: AGENTIC_MESSAGING_V1_SCHEMA_VERSION,
457
+ format: WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT,
458
+ contractId: WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID,
459
+ contractHash: WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH,
460
+ clientIntentSha256: digest(record.clientIntentSha256, "Wrench messaging receipt binding.clientIntentSha256"),
461
+ routeRefSha256: digest(record.routeRefSha256, "Wrench messaging receipt binding.routeRefSha256"),
462
+ contextRefSha256: digest(record.contextRefSha256, "Wrench messaging receipt binding.contextRefSha256"),
463
+ turnDigest: digest(record.turnDigest, "Wrench messaging receipt binding.turnDigest"),
464
+ previewDigest: digest(record.previewDigest, "Wrench messaging receipt binding.previewDigest"),
465
+ runId: identifier(record.runId, "Wrench messaging receipt binding.runId", 256),
466
+ state: record.state,
467
+ partCount,
468
+ provenPartCount,
469
+ receiptSha256: digest(record.receiptSha256, "Wrench messaging receipt binding.receiptSha256"),
470
+ recordedAt: timestamp(record.recordedAt, "Wrench messaging receipt binding.recordedAt")
471
+ });
472
+ const { receiptSha256, ...receiptCore } = parsed;
473
+ if (sha256(canonicalJson(receiptCore)) !== receiptSha256) {
474
+ return fail("Wrench messaging receipt binding receiptSha256 does not match its canonical content");
475
+ }
476
+ return parsed;
477
+ }
478
+ function agentMessageRouteCandidateId(sourceId, conversationId) {
479
+ return `route_${sha256(canonicalJson({
480
+ conversationId: identifier(conversationId, "Source-conversation route.conversationId"),
481
+ sourceId: identifier(sourceId, "Source-conversation route.sourceId")
482
+ }))}`;
483
+ }
484
+
485
+ export { AGENTIC_MESSAGING_V1_SCHEMA_VERSION, AGENT_MESSAGE_DRAFT_V1_FORMAT, AGENT_MESSAGE_HANDOFF_REQUEST_V1_FORMAT, AGENT_MESSAGE_HANDOFF_V1_FORMAT, AGENT_MESSAGE_AUDIT_V1_FORMAT, WRENCH_MESSAGING_CONTEXT_BINDING_V1_FORMAT, WRENCH_MESSAGING_RECEIPT_BINDING_V1_FORMAT, WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_ID, WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_HASH, WRENCH_MESSAGING_CONTEXT_BINDING_V1_CONTRACT_DESCRIPTOR, WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_ID, WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_HASH, WRENCH_MESSAGING_RECEIPT_BINDING_V1_CONTRACT_DESCRIPTOR, AGENTIC_MESSAGING_V1_LIMITS, AgenticMessagingV1ContractError, parseWrenchMessagingContextBindingV1, parseAgentMessageDraftV1, parseAgentMessageHandoffRequestV1, createAgentMessageHandoffV1, parseAgentMessageHandoffV1, wrenchMessagingTurnDigestV1, parseWrenchMessagingReceiptBindingV1, agentMessageRouteCandidateId };
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ // src/message-bundle-v2-identity.ts
3
+ var MESSAGE_BUNDLE_V2_SCHEMA_IDENTITY = 2;
4
+
5
+ export { MESSAGE_BUNDLE_V2_SCHEMA_IDENTITY };
@@ -0,0 +1,5 @@
1
+ // @bun
2
+ // src/message-bundle-v1-identity.ts
3
+ var MESSAGE_BUNDLE_V1_SCHEMA_IDENTITY = 1;
4
+
5
+ export { MESSAGE_BUNDLE_V1_SCHEMA_IDENTITY };