@agenticprimitives/fabric 0.0.0-alpha.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/CLAUDE.md +67 -0
- package/LICENSE +21 -0
- package/README.md +21 -0
- package/dist/case-machine.d.ts +76 -0
- package/dist/case-machine.d.ts.map +1 -0
- package/dist/case-machine.js +83 -0
- package/dist/case-machine.js.map +1 -0
- package/dist/client/index.d.ts +114 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +76 -0
- package/dist/client/index.js.map +1 -0
- package/dist/cloudflare/authority-verdict-cache.d.ts +27 -0
- package/dist/cloudflare/authority-verdict-cache.d.ts.map +1 -0
- package/dist/cloudflare/authority-verdict-cache.js +66 -0
- package/dist/cloudflare/authority-verdict-cache.js.map +1 -0
- package/dist/cloudflare/channel-store.d.ts +61 -0
- package/dist/cloudflare/channel-store.d.ts.map +1 -0
- package/dist/cloudflare/channel-store.js +124 -0
- package/dist/cloudflare/channel-store.js.map +1 -0
- package/dist/cloudflare/exchange-store.d.ts +16 -0
- package/dist/cloudflare/exchange-store.d.ts.map +1 -0
- package/dist/cloudflare/exchange-store.js +45 -0
- package/dist/cloudflare/exchange-store.js.map +1 -0
- package/dist/cloudflare/gateway-tools.d.ts +28 -0
- package/dist/cloudflare/gateway-tools.d.ts.map +1 -0
- package/dist/cloudflare/gateway-tools.js +45 -0
- package/dist/cloudflare/gateway-tools.js.map +1 -0
- package/dist/cloudflare/index.d.ts +13 -0
- package/dist/cloudflare/index.d.ts.map +1 -0
- package/dist/cloudflare/index.js +20 -0
- package/dist/cloudflare/index.js.map +1 -0
- package/dist/cloudflare/orchestration-runtime.d.ts +28 -0
- package/dist/cloudflare/orchestration-runtime.d.ts.map +1 -0
- package/dist/cloudflare/orchestration-runtime.js +35 -0
- package/dist/cloudflare/orchestration-runtime.js.map +1 -0
- package/dist/cloudflare/outbox-store.d.ts +24 -0
- package/dist/cloudflare/outbox-store.d.ts.map +1 -0
- package/dist/cloudflare/outbox-store.js +42 -0
- package/dist/cloudflare/outbox-store.js.map +1 -0
- package/dist/cloudflare/principal-gateway-do.d.ts +234 -0
- package/dist/cloudflare/principal-gateway-do.d.ts.map +1 -0
- package/dist/cloudflare/principal-gateway-do.js +369 -0
- package/dist/cloudflare/principal-gateway-do.js.map +1 -0
- package/dist/cloudflare/provenance-store.d.ts +9 -0
- package/dist/cloudflare/provenance-store.d.ts.map +1 -0
- package/dist/cloudflare/provenance-store.js +36 -0
- package/dist/cloudflare/provenance-store.js.map +1 -0
- package/dist/cloudflare/receipt-signer.d.ts +26 -0
- package/dist/cloudflare/receipt-signer.d.ts.map +1 -0
- package/dist/cloudflare/receipt-signer.js +69 -0
- package/dist/cloudflare/receipt-signer.js.map +1 -0
- package/dist/cloudflare/request-id-ledger.d.ts +13 -0
- package/dist/cloudflare/request-id-ledger.d.ts.map +1 -0
- package/dist/cloudflare/request-id-ledger.js +38 -0
- package/dist/cloudflare/request-id-ledger.js.map +1 -0
- package/dist/cloudflare/sql-vault.d.ts +10 -0
- package/dist/cloudflare/sql-vault.d.ts.map +1 -0
- package/dist/cloudflare/sql-vault.js +98 -0
- package/dist/cloudflare/sql-vault.js.map +1 -0
- package/dist/communicative-act.d.ts +47 -0
- package/dist/communicative-act.d.ts.map +1 -0
- package/dist/communicative-act.js +36 -0
- package/dist/communicative-act.js.map +1 -0
- package/dist/delivery-envelope.d.ts +38 -0
- package/dist/delivery-envelope.d.ts.map +1 -0
- package/dist/delivery-envelope.js +43 -0
- package/dist/delivery-envelope.js.map +1 -0
- package/dist/exchange-record.d.ts +131 -0
- package/dist/exchange-record.d.ts.map +1 -0
- package/dist/exchange-record.js +25 -0
- package/dist/exchange-record.js.map +1 -0
- package/dist/exchange-reducer.d.ts +25 -0
- package/dist/exchange-reducer.d.ts.map +1 -0
- package/dist/exchange-reducer.js +108 -0
- package/dist/exchange-reducer.js.map +1 -0
- package/dist/exchange-state.d.ts +56 -0
- package/dist/exchange-state.d.ts.map +1 -0
- package/dist/exchange-state.js +81 -0
- package/dist/exchange-state.js.map +1 -0
- package/dist/gateway-surface.d.ts +24 -0
- package/dist/gateway-surface.d.ts.map +1 -0
- package/dist/gateway-surface.js +33 -0
- package/dist/gateway-surface.js.map +1 -0
- package/dist/inbox-doc.d.ts +32 -0
- package/dist/inbox-doc.d.ts.map +1 -0
- package/dist/inbox-doc.js +57 -0
- package/dist/inbox-doc.js.map +1 -0
- package/dist/inbox-projection.d.ts +15 -0
- package/dist/inbox-projection.d.ts.map +1 -0
- package/dist/inbox-projection.js +28 -0
- package/dist/inbox-projection.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/interactions/audited.d.ts +12 -0
- package/dist/interactions/audited.d.ts.map +1 -0
- package/dist/interactions/audited.js +67 -0
- package/dist/interactions/audited.js.map +1 -0
- package/dist/interactions/builders.d.ts +24 -0
- package/dist/interactions/builders.d.ts.map +1 -0
- package/dist/interactions/builders.js +48 -0
- package/dist/interactions/builders.js.map +1 -0
- package/dist/interactions/cards.d.ts +32 -0
- package/dist/interactions/cards.d.ts.map +1 -0
- package/dist/interactions/cards.js +20 -0
- package/dist/interactions/cards.js.map +1 -0
- package/dist/interactions/index.d.ts +15 -0
- package/dist/interactions/index.d.ts.map +1 -0
- package/dist/interactions/index.js +23 -0
- package/dist/interactions/index.js.map +1 -0
- package/dist/interactions/machine.d.ts +19 -0
- package/dist/interactions/machine.d.ts.map +1 -0
- package/dist/interactions/machine.js +31 -0
- package/dist/interactions/machine.js.map +1 -0
- package/dist/interactions/mandates.d.ts +64 -0
- package/dist/interactions/mandates.d.ts.map +1 -0
- package/dist/interactions/mandates.js +62 -0
- package/dist/interactions/mandates.js.map +1 -0
- package/dist/interactions/relationship.d.ts +29 -0
- package/dist/interactions/relationship.d.ts.map +1 -0
- package/dist/interactions/relationship.js +31 -0
- package/dist/interactions/relationship.js.map +1 -0
- package/dist/interactions/risk.d.ts +39 -0
- package/dist/interactions/risk.d.ts.map +1 -0
- package/dist/interactions/risk.js +49 -0
- package/dist/interactions/risk.js.map +1 -0
- package/dist/interactions/runs.d.ts +26 -0
- package/dist/interactions/runs.d.ts.map +1 -0
- package/dist/interactions/runs.js +80 -0
- package/dist/interactions/runs.js.map +1 -0
- package/dist/interactions/store.d.ts +20 -0
- package/dist/interactions/store.d.ts.map +1 -0
- package/dist/interactions/store.js +68 -0
- package/dist/interactions/store.js.map +1 -0
- package/dist/interactions/tickets.d.ts +68 -0
- package/dist/interactions/tickets.d.ts.map +1 -0
- package/dist/interactions/tickets.js +49 -0
- package/dist/interactions/tickets.js.map +1 -0
- package/dist/interactions/types.d.ts +160 -0
- package/dist/interactions/types.d.ts.map +1 -0
- package/dist/interactions/types.js +7 -0
- package/dist/interactions/types.js.map +1 -0
- package/dist/messaging/board.d.ts +54 -0
- package/dist/messaging/board.d.ts.map +1 -0
- package/dist/messaging/board.js +90 -0
- package/dist/messaging/board.js.map +1 -0
- package/dist/messaging/conversation.d.ts +35 -0
- package/dist/messaging/conversation.d.ts.map +1 -0
- package/dist/messaging/conversation.js +72 -0
- package/dist/messaging/conversation.js.map +1 -0
- package/dist/messaging/delivery.d.ts +19 -0
- package/dist/messaging/delivery.d.ts.map +1 -0
- package/dist/messaging/delivery.js +56 -0
- package/dist/messaging/delivery.js.map +1 -0
- package/dist/messaging/directory.d.ts +32 -0
- package/dist/messaging/directory.d.ts.map +1 -0
- package/dist/messaging/directory.js +35 -0
- package/dist/messaging/directory.js.map +1 -0
- package/dist/messaging/envelope.d.ts +14 -0
- package/dist/messaging/envelope.d.ts.map +1 -0
- package/dist/messaging/envelope.js +71 -0
- package/dist/messaging/envelope.js.map +1 -0
- package/dist/messaging/hash.d.ts +19 -0
- package/dist/messaging/hash.d.ts.map +1 -0
- package/dist/messaging/hash.js +36 -0
- package/dist/messaging/hash.js.map +1 -0
- package/dist/messaging/index.d.ts +16 -0
- package/dist/messaging/index.d.ts.map +1 -0
- package/dist/messaging/index.js +29 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/messaging/projector.d.ts +58 -0
- package/dist/messaging/projector.d.ts.map +1 -0
- package/dist/messaging/projector.js +103 -0
- package/dist/messaging/projector.js.map +1 -0
- package/dist/messaging/receipts.d.ts +5 -0
- package/dist/messaging/receipts.d.ts.map +1 -0
- package/dist/messaging/receipts.js +19 -0
- package/dist/messaging/receipts.js.map +1 -0
- package/dist/messaging/rules.d.ts +84 -0
- package/dist/messaging/rules.d.ts.map +1 -0
- package/dist/messaging/rules.js +109 -0
- package/dist/messaging/rules.js.map +1 -0
- package/dist/messaging/store.d.ts +24 -0
- package/dist/messaging/store.d.ts.map +1 -0
- package/dist/messaging/store.js +120 -0
- package/dist/messaging/store.js.map +1 -0
- package/dist/messaging/types.d.ts +166 -0
- package/dist/messaging/types.d.ts.map +1 -0
- package/dist/messaging/types.js +7 -0
- package/dist/messaging/types.js.map +1 -0
- package/dist/messaging/vault-store.d.ts +37 -0
- package/dist/messaging/vault-store.d.ts.map +1 -0
- package/dist/messaging/vault-store.js +62 -0
- package/dist/messaging/vault-store.js.map +1 -0
- package/dist/record-catalog.d.ts +22 -0
- package/dist/record-catalog.d.ts.map +1 -0
- package/dist/record-catalog.js +35 -0
- package/dist/record-catalog.js.map +1 -0
- package/package.json +82 -0
- package/spec.md +15 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ConversationId, MessageEnvelopeV1, MessageId, ThreadId } from './types.js';
|
|
2
|
+
export declare function generateMessageId(): MessageId;
|
|
3
|
+
export declare function generateConversationId(): ConversationId;
|
|
4
|
+
export declare function generateThreadId(): ThreadId;
|
|
5
|
+
export type EnvelopeValidationError = 'bad_version' | 'bad_id' | 'bad_conversation_id' | 'missing_from' | 'empty_recipients' | 'bad_created_at' | 'bad_expires_at' | 'expired_before_created' | 'bad_body_hash' | 'missing_body_content_type' | 'bad_attachment_hash' | 'too_many_context_refs' | 'bad_context_ref';
|
|
6
|
+
/** Envelope context refs are bounded so refs stay metadata, not payload. */
|
|
7
|
+
export declare const MAX_CONTEXT_REFS = 8;
|
|
8
|
+
/**
|
|
9
|
+
* Structural validation only — signature verification, sender authority, and
|
|
10
|
+
* recipient admission policy are the recipient runtime's job (spec 309 §4.4).
|
|
11
|
+
* Returns an empty array iff the envelope is structurally admissible.
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateMessageEnvelope(env: MessageEnvelopeV1): EnvelopeValidationError[];
|
|
14
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAUzF,wBAAgB,iBAAiB,IAAI,SAAS,CAE7C;AAED,wBAAgB,sBAAsB,IAAI,cAAc,CAEvD;AAED,wBAAgB,gBAAgB,IAAI,QAAQ,CAE3C;AAED,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,QAAQ,GACR,qBAAqB,GACrB,cAAc,GACd,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,wBAAwB,GACxB,eAAe,GACf,2BAA2B,GAC3B,qBAAqB,GACrB,uBAAuB,GACvB,iBAAiB,CAAC;AAEtB,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAQlC;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,iBAAiB,GAAG,uBAAuB,EAAE,CA+BzF"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Envelope construction + structural validation (fail-closed, spec 309 §8).
|
|
2
|
+
function randomSuffix() {
|
|
3
|
+
const bytes = new Uint8Array(16);
|
|
4
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
5
|
+
return Array.from(bytes)
|
|
6
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
7
|
+
.join('');
|
|
8
|
+
}
|
|
9
|
+
export function generateMessageId() {
|
|
10
|
+
return `msg_${randomSuffix()}`;
|
|
11
|
+
}
|
|
12
|
+
export function generateConversationId() {
|
|
13
|
+
return `conv_${randomSuffix()}`;
|
|
14
|
+
}
|
|
15
|
+
export function generateThreadId() {
|
|
16
|
+
return `thr_${randomSuffix()}`;
|
|
17
|
+
}
|
|
18
|
+
/** Envelope context refs are bounded so refs stay metadata, not payload. */
|
|
19
|
+
export const MAX_CONTEXT_REFS = 8;
|
|
20
|
+
const HEX32_RE = /^0x[0-9a-f]{64}$/;
|
|
21
|
+
function isIsoDate(s) {
|
|
22
|
+
return !Number.isNaN(Date.parse(s));
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Structural validation only — signature verification, sender authority, and
|
|
26
|
+
* recipient admission policy are the recipient runtime's job (spec 309 §4.4).
|
|
27
|
+
* Returns an empty array iff the envelope is structurally admissible.
|
|
28
|
+
*/
|
|
29
|
+
export function validateMessageEnvelope(env) {
|
|
30
|
+
const errors = [];
|
|
31
|
+
if (env.version !== 'ap.message.v1')
|
|
32
|
+
errors.push('bad_version');
|
|
33
|
+
if (!env.id?.startsWith('msg_'))
|
|
34
|
+
errors.push('bad_id');
|
|
35
|
+
if (!env.conversationId?.startsWith('conv_'))
|
|
36
|
+
errors.push('bad_conversation_id');
|
|
37
|
+
if (!env.from)
|
|
38
|
+
errors.push('missing_from');
|
|
39
|
+
if (!Array.isArray(env.to) || env.to.length === 0)
|
|
40
|
+
errors.push('empty_recipients');
|
|
41
|
+
if (!env.createdAt || !isIsoDate(env.createdAt))
|
|
42
|
+
errors.push('bad_created_at');
|
|
43
|
+
if (env.expiresAt !== undefined) {
|
|
44
|
+
if (!isIsoDate(env.expiresAt))
|
|
45
|
+
errors.push('bad_expires_at');
|
|
46
|
+
else if (isIsoDate(env.createdAt) && Date.parse(env.expiresAt) <= Date.parse(env.createdAt))
|
|
47
|
+
errors.push('expired_before_created');
|
|
48
|
+
}
|
|
49
|
+
if (!HEX32_RE.test(env.bodyHash ?? ''))
|
|
50
|
+
errors.push('bad_body_hash');
|
|
51
|
+
if (!env.bodyContentType)
|
|
52
|
+
errors.push('missing_body_content_type');
|
|
53
|
+
for (const att of env.attachments ?? []) {
|
|
54
|
+
if (!HEX32_RE.test(att.hash ?? '')) {
|
|
55
|
+
errors.push('bad_attachment_hash');
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (env.contextRefs !== undefined) {
|
|
60
|
+
if (env.contextRefs.length > MAX_CONTEXT_REFS)
|
|
61
|
+
errors.push('too_many_context_refs');
|
|
62
|
+
for (const ref of env.contextRefs) {
|
|
63
|
+
if (!ref.kind?.trim() || !ref.id?.trim() || (ref.hash !== undefined && !HEX32_RE.test(ref.hash))) {
|
|
64
|
+
errors.push('bad_context_ref');
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return errors;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/messaging/envelope.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAI5E,SAAS,YAAY;IACnB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACjC,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;SACrB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,YAAY,EAAE,EAAE,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,sBAAsB;IACpC,OAAO,QAAQ,YAAY,EAAE,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,YAAY,EAAE,EAAE,CAAC;AACjC,CAAC;AAiBD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAElC,MAAM,QAAQ,GAAG,kBAAkB,CAAC;AAEpC,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAsB;IAC5D,MAAM,MAAM,GAA8B,EAAE,CAAC;IAC7C,IAAI,GAAG,CAAC,OAAO,KAAK,eAAe;QAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAChE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,MAAM,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvD,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,OAAO,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACjF,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACnF,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC/E,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;aACxD,IAAI,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;YACzF,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACrE,IAAI,CAAC,GAAG,CAAC,eAAe;QAAE,MAAM,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACnE,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YACnC,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QAClC,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,gBAAgB;YAAE,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACpF,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBACjG,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAC/B,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Hex32, MessageEnvelopeV1 } from './types.js';
|
|
2
|
+
import { canonicalizeJson } from '@agenticprimitives/types';
|
|
3
|
+
/** Deterministic JSON: sorted keys, `undefined` members dropped. Hoisted to `@agenticprimitives/types` as
|
|
4
|
+
* `canonicalizeJson` (spec 316 Open Decision F); kept here as an alias for back-compat. */
|
|
5
|
+
export declare const canonicalizeMessage: typeof canonicalizeJson;
|
|
6
|
+
export declare function sha256Hex32(input: string | Uint8Array): Promise<Hex32>;
|
|
7
|
+
/**
|
|
8
|
+
* Hash of the canonical envelope EXCLUDING `signature` — this is the payload a
|
|
9
|
+
* sender signs and a recipient verifies (spec 309 §8.1). Deterministic across
|
|
10
|
+
* key order and undefined optional fields.
|
|
11
|
+
*/
|
|
12
|
+
export declare function hashMessageEnvelope(envelope: MessageEnvelopeV1): Promise<Hex32>;
|
|
13
|
+
/**
|
|
14
|
+
* Body-hash binding (spec 309 §8.4): the envelope's `bodyHash` MUST equal the
|
|
15
|
+
* digest of the vault-resident body bytes. Recipients enforce this BEFORE
|
|
16
|
+
* admitting a message; a mismatch is a delivery failure, not a warning.
|
|
17
|
+
*/
|
|
18
|
+
export declare function verifyBodyHash(envelope: Pick<MessageEnvelopeV1, 'bodyHash'>, bodyBytes: Uint8Array): Promise<boolean>;
|
|
19
|
+
//# sourceMappingURL=hash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../../src/messaging/hash.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAI5D;4FAC4F;AAC5F,eAAO,MAAM,mBAAmB,yBAAmB,CAAC;AAEpD,wBAAsB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAO5E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,KAAK,CAAC,CAGrF;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,IAAI,CAAC,iBAAiB,EAAE,UAAU,CAAC,EAC7C,SAAS,EAAE,UAAU,GACpB,OAAO,CAAC,OAAO,CAAC,CAElB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Canonical hashing for message envelopes + vault-resident bodies.
|
|
2
|
+
//
|
|
3
|
+
// Same deterministic-JSON convention as verification-receipts / key-authorization
|
|
4
|
+
// (sorted keys, undefined dropped) so cross-package tooling produces identical
|
|
5
|
+
// digests. Web Crypto only — runs in Node, Workers, and browsers.
|
|
6
|
+
import { canonicalizeJson } from '@agenticprimitives/types';
|
|
7
|
+
const enc = new TextEncoder();
|
|
8
|
+
/** Deterministic JSON: sorted keys, `undefined` members dropped. Hoisted to `@agenticprimitives/types` as
|
|
9
|
+
* `canonicalizeJson` (spec 316 Open Decision F); kept here as an alias for back-compat. */
|
|
10
|
+
export const canonicalizeMessage = canonicalizeJson;
|
|
11
|
+
export async function sha256Hex32(input) {
|
|
12
|
+
const bytes = typeof input === 'string' ? enc.encode(input) : input;
|
|
13
|
+
const digest = await globalThis.crypto.subtle.digest('SHA-256', bytes);
|
|
14
|
+
const hex = Array.from(new Uint8Array(digest))
|
|
15
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
16
|
+
.join('');
|
|
17
|
+
return `0x${hex}`;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Hash of the canonical envelope EXCLUDING `signature` — this is the payload a
|
|
21
|
+
* sender signs and a recipient verifies (spec 309 §8.1). Deterministic across
|
|
22
|
+
* key order and undefined optional fields.
|
|
23
|
+
*/
|
|
24
|
+
export async function hashMessageEnvelope(envelope) {
|
|
25
|
+
const { signature: _signature, ...unsigned } = envelope;
|
|
26
|
+
return sha256Hex32(canonicalizeMessage(unsigned));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Body-hash binding (spec 309 §8.4): the envelope's `bodyHash` MUST equal the
|
|
30
|
+
* digest of the vault-resident body bytes. Recipients enforce this BEFORE
|
|
31
|
+
* admitting a message; a mismatch is a delivery failure, not a warning.
|
|
32
|
+
*/
|
|
33
|
+
export async function verifyBodyHash(envelope, bodyBytes) {
|
|
34
|
+
return (await sha256Hex32(bodyBytes)) === envelope.bodyHash;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=hash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../../src/messaging/hash.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,kFAAkF;AAClF,+EAA+E;AAC/E,kEAAkE;AAGlE,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAE9B;4FAC4F;AAC5F,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAA0B;IAC1D,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAA+B,CAAC,CAAC;IACjG,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SAC3C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,KAAK,GAAG,EAAW,CAAC;AAC7B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,QAA2B;IACnE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,QAAQ,EAAE,GAAG,QAAQ,CAAC;IACxD,OAAO,WAAW,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,QAA6C,EAC7C,SAAqB;IAErB,OAAO,CAAC,MAAM,WAAW,CAAC,SAAS,CAAC,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const PACKAGE_NAME = "@agenticprimitives/fabric/messaging";
|
|
2
|
+
export declare const PACKAGE_STATUS: "w5-context";
|
|
3
|
+
export declare const SPEC_REF = "specs/309-messaging-and-interactions.md";
|
|
4
|
+
export { type Hex32, type MessageId, type ConversationId, type ThreadId, type FolderKind, type MessagePriority, type MessageKind, type ContextRefV1, type SignatureProof, type MessageAttachmentRef, type RetentionPolicyRef, type MessageEnvelopeV1, type MessageEventType, type MessageEventV1, type InboxItemV1, type ConversationDescriptorV1, type ConversationProfile, type DiscussionTopicV1, type MessageThreadV1, } from './types.js';
|
|
5
|
+
export { canonicalizeMessage, sha256Hex32, hashMessageEnvelope, verifyBodyHash, } from './hash.js';
|
|
6
|
+
export { generateMessageId, generateConversationId, generateThreadId, type EnvelopeValidationError, validateMessageEnvelope, MAX_CONTEXT_REFS, } from './envelope.js';
|
|
7
|
+
export { type ConversationValidationError, validateConversationDescriptor, type ConversationSummaryV1, summarizeConversations, } from './conversation.js';
|
|
8
|
+
export { applyMessageEvent, type MessageStore, createInMemoryMessageStore, } from './store.js';
|
|
9
|
+
export { type InboxRulePredicateV1, type InboxRuleActionV1, type InboxRuleV1, type NotificationEventV1, type NotificationSink, matchesRulePredicate, matchesContextRef, type RuleApplication, applyInboxRules, } from './rules.js';
|
|
10
|
+
export { type FolderSummaryV1, summarizeFolders, type InboxDeltaCursorV1, type InboxDeltaV1, type DeltaCursorStore, type MessageDeliveryPort, type InboxProjector, type CreateInboxProjectorOpts, createInMemoryInboxProjector, } from './projector.js';
|
|
11
|
+
export { buildDeliveryReceipt, buildReadReceipt } from './receipts.js';
|
|
12
|
+
export { MESSAGE_BODY_RECORD_TYPE, MESSAGE_ATTACHMENT_RECORD_TYPE, messageBodyResource, topicBodyResource, messageAttachmentResource, type PutBodyResult, type MessageBodyStore, createVaultMessageBodyStore, } from './vault-store.js';
|
|
13
|
+
export { type AuditedInboxDelivery, createAuditedInboxDelivery } from './delivery.js';
|
|
14
|
+
export { BOARD_HISTORY_LIMIT, createBoardChannel, canSeeChannel, appendBoardPost, type BoardResult, type ChannelMessageEntryV1, type ChannelV1, } from './board.js';
|
|
15
|
+
export { validateDirectoryListing, isListingCurrent, type DirectoryListingV1, type ListingValidationError, } from './directory.js';
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/messaging/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,YAAY,wCAAwC,CAAC;AAClE,eAAO,MAAM,cAAc,EAAG,YAAqB,CAAC;AACpD,eAAO,MAAM,QAAQ,4CAA4C,CAAC;AAElE,OAAO,EACL,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,cAAc,GACf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EACL,KAAK,2BAA2B,EAChC,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,KAAK,YAAY,EACjB,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,KAAK,eAAe,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,wBAAwB,EAC7B,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EACzB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,KAAK,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAItF,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,GAC5B,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @agenticprimitives/messaging — signed, vault-resident Smart Agent messaging
|
|
2
|
+
// (spec 309). W2 slice: W1's envelope + hash binding + validation + reducer +
|
|
3
|
+
// MessageStore, PLUS the deterministic inbox-rule DSL (projection-only actions),
|
|
4
|
+
// the InboxProjector with folder counters + delta cursors, receipt builders, and
|
|
5
|
+
// the transport/notification/cursor ports.
|
|
6
|
+
//
|
|
7
|
+
// Doctrine (spec 309 §4): a message is NEVER authority — it carries requests,
|
|
8
|
+
// evidence, and credential REFERENCES; delegation / entitlements / VC packages
|
|
9
|
+
// remain the authority layer. Bodies live in the vault; envelopes carry
|
|
10
|
+
// hashes + VaultRefs only. Transport (A2A, direct endpoint, relay) is the
|
|
11
|
+
// caller's choice — this package owns no I/O.
|
|
12
|
+
export const PACKAGE_NAME = '@agenticprimitives/fabric/messaging';
|
|
13
|
+
export const PACKAGE_STATUS = 'w5-context';
|
|
14
|
+
export const SPEC_REF = 'specs/309-messaging-and-interactions.md';
|
|
15
|
+
export { canonicalizeMessage, sha256Hex32, hashMessageEnvelope, verifyBodyHash, } from './hash.js';
|
|
16
|
+
export { generateMessageId, generateConversationId, generateThreadId, validateMessageEnvelope, MAX_CONTEXT_REFS, } from './envelope.js';
|
|
17
|
+
export { validateConversationDescriptor, summarizeConversations, } from './conversation.js';
|
|
18
|
+
export { applyMessageEvent, createInMemoryMessageStore, } from './store.js';
|
|
19
|
+
export { matchesRulePredicate, matchesContextRef, applyInboxRules, } from './rules.js';
|
|
20
|
+
export { summarizeFolders, createInMemoryInboxProjector, } from './projector.js';
|
|
21
|
+
export { buildDeliveryReceipt, buildReadReceipt } from './receipts.js';
|
|
22
|
+
export { MESSAGE_BODY_RECORD_TYPE, MESSAGE_ATTACHMENT_RECORD_TYPE, messageBodyResource, topicBodyResource, messageAttachmentResource, createVaultMessageBodyStore, } from './vault-store.js';
|
|
23
|
+
export { createAuditedInboxDelivery } from './delivery.js';
|
|
24
|
+
// Community channel board (spec 322 W1) — shape + validated pure mutations; gating/audit/residency
|
|
25
|
+
// stay with the execution point.
|
|
26
|
+
export { BOARD_HISTORY_LIMIT, createBoardChannel, canSeeChannel, appendBoardPost, } from './board.js';
|
|
27
|
+
// Directory listing (spec 322 W1; moved from @agenticprimitives/home — a listing is substrate).
|
|
28
|
+
export { validateDirectoryListing, isListingCurrent, } from './directory.js';
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/messaging/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,8EAA8E;AAC9E,iFAAiF;AACjF,iFAAiF;AACjF,2CAA2C;AAC3C,EAAE;AACF,8EAA8E;AAC9E,+EAA+E;AAC/E,wEAAwE;AACxE,0EAA0E;AAC1E,8CAA8C;AAE9C,MAAM,CAAC,MAAM,YAAY,GAAG,qCAAqC,CAAC;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,YAAqB,CAAC;AACpD,MAAM,CAAC,MAAM,QAAQ,GAAG,yCAAyC,CAAC;AAwBlE,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,mBAAmB,EACnB,cAAc,GACf,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAEhB,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,8BAA8B,EAE9B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EAEjB,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAML,oBAAoB,EACpB,iBAAiB,EAEjB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAEL,gBAAgB,EAOhB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,EAGzB,2BAA2B,GAC5B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAA6B,0BAA0B,EAAE,MAAM,eAAe,CAAC;AAEtF,mGAAmG;AACnG,iCAAiC;AACjC,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,aAAa,EACb,eAAe,GAIhB,MAAM,YAAY,CAAC;AAEpB,gGAAgG;AAChG,OAAO,EACL,wBAAwB,EACxB,gBAAgB,GAGjB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { FolderKind, InboxItemV1, MessageEnvelopeV1, MessageEventV1, MessageId } from './types.js';
|
|
2
|
+
import { type MessageStore } from './store.js';
|
|
3
|
+
import { type InboxRuleV1, type RuleApplication } from './rules.js';
|
|
4
|
+
export interface FolderSummaryV1 {
|
|
5
|
+
folder: FolderKind;
|
|
6
|
+
total: number;
|
|
7
|
+
unread: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function summarizeFolders(items: InboxItemV1[]): FolderSummaryV1[];
|
|
10
|
+
/** Opaque sync position for one projection stream (AT-proto-style logical clock). */
|
|
11
|
+
export interface InboxDeltaCursorV1 {
|
|
12
|
+
version: 'ap.inbox.cursor.v1';
|
|
13
|
+
streamId: string;
|
|
14
|
+
revision: number;
|
|
15
|
+
}
|
|
16
|
+
export interface InboxDeltaV1 {
|
|
17
|
+
cursor: InboxDeltaCursorV1;
|
|
18
|
+
/** Items whose projection changed after the given cursor (upserts). */
|
|
19
|
+
changed: InboxItemV1[];
|
|
20
|
+
/** Messages tombstoned after the given cursor — consumers purge local copies. */
|
|
21
|
+
removed: MessageId[];
|
|
22
|
+
}
|
|
23
|
+
/** Port for persisting a consumer's cursor — adapters live in apps/runtimes. */
|
|
24
|
+
export interface DeltaCursorStore {
|
|
25
|
+
get(streamId: string): InboxDeltaCursorV1 | null | Promise<InboxDeltaCursorV1 | null>;
|
|
26
|
+
put(cursor: InboxDeltaCursorV1): void | Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
/** Port a transport adapter (A2A, direct endpoint, relay) implements to move
|
|
29
|
+
* envelopes. Resolves to the delivery event the recipient runtime emitted. */
|
|
30
|
+
export interface MessageDeliveryPort {
|
|
31
|
+
deliver(envelope: MessageEnvelopeV1): Promise<MessageEventV1>;
|
|
32
|
+
}
|
|
33
|
+
export interface InboxProjector {
|
|
34
|
+
putMessage(envelope: MessageEnvelopeV1): void;
|
|
35
|
+
/** Reducer + rules. Rules run only on first admission (admitted/delivered),
|
|
36
|
+
* mirroring Outlook: user actions afterwards are not re-filed. */
|
|
37
|
+
appendEvent(event: MessageEventV1): RuleApplication;
|
|
38
|
+
getInboxItem(id: MessageId): InboxItemV1 | null;
|
|
39
|
+
listInbox(folder?: FolderKind): InboxItemV1[];
|
|
40
|
+
/** THE related-messages read path (spec 312 §8.2): items about a context.
|
|
41
|
+
* `id` omitted ⇒ every item carrying any ref of that kind. */
|
|
42
|
+
listByContext(ref: {
|
|
43
|
+
kind: string;
|
|
44
|
+
id?: string;
|
|
45
|
+
}): InboxItemV1[];
|
|
46
|
+
unreadCount(folder?: FolderKind): number;
|
|
47
|
+
summarize(): FolderSummaryV1[];
|
|
48
|
+
revision(): number;
|
|
49
|
+
/** Pass `null` for initial sync. Fail-closed: a cursor from another stream throws. */
|
|
50
|
+
deltaSince(cursor: InboxDeltaCursorV1 | null): InboxDeltaV1;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateInboxProjectorOpts {
|
|
53
|
+
streamId: string;
|
|
54
|
+
rules?: InboxRuleV1[];
|
|
55
|
+
store?: MessageStore;
|
|
56
|
+
}
|
|
57
|
+
export declare function createInMemoryInboxProjector(opts: CreateInboxProjectorOpts): InboxProjector;
|
|
58
|
+
//# sourceMappingURL=projector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projector.d.ts","sourceRoot":"","sources":["../../src/messaging/projector.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,SAAS,EACV,MAAM,YAAY,CAAC;AACpB,OAAO,EAA8B,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAC3E,OAAO,EAAsC,KAAK,WAAW,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAExG,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,eAAe,EAAE,CASxE;AAED,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,uEAAuE;IACvE,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,iFAAiF;IACjF,OAAO,EAAE,SAAS,EAAE,CAAC;CACtB;AAED,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IACtF,GAAG,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvD;AAED;+EAC+E;AAC/E,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,QAAQ,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC9C;uEACmE;IACnE,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,eAAe,CAAC;IACpD,YAAY,CAAC,EAAE,EAAE,SAAS,GAAG,WAAW,GAAG,IAAI,CAAC;IAChD,SAAS,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,WAAW,EAAE,CAAC;IAC9C;mEAC+D;IAC/D,aAAa,CAAC,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,WAAW,EAAE,CAAC;IACjE,WAAW,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IACzC,SAAS,IAAI,eAAe,EAAE,CAAC;IAC/B,QAAQ,IAAI,MAAM,CAAC;IACnB,sFAAsF;IACtF,UAAU,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,GAAG,YAAY,CAAC;CAC7D;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,wBAAwB,GAAG,cAAc,CA4F3F"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Inbox projector (spec 309 §5): the deterministic pipeline
|
|
2
|
+
// envelope + events → reducer → rules → InboxItemV1, plus folder counters and
|
|
3
|
+
// delta cursors so apps can do Outlook/Graph-style initial + incremental sync.
|
|
4
|
+
import { createInMemoryMessageStore } from './store.js';
|
|
5
|
+
import { applyInboxRules, matchesContextRef } from './rules.js';
|
|
6
|
+
export function summarizeFolders(items) {
|
|
7
|
+
const byFolder = new Map();
|
|
8
|
+
for (const item of items) {
|
|
9
|
+
const s = byFolder.get(item.folder) ?? { folder: item.folder, total: 0, unread: 0 };
|
|
10
|
+
s.total += 1;
|
|
11
|
+
if (item.unread)
|
|
12
|
+
s.unread += 1;
|
|
13
|
+
byFolder.set(item.folder, s);
|
|
14
|
+
}
|
|
15
|
+
return [...byFolder.values()].sort((a, b) => a.folder.localeCompare(b.folder));
|
|
16
|
+
}
|
|
17
|
+
export function createInMemoryInboxProjector(opts) {
|
|
18
|
+
const store = opts.store ?? createInMemoryMessageStore();
|
|
19
|
+
const rules = opts.rules ?? [];
|
|
20
|
+
let revision = 0;
|
|
21
|
+
const itemRevisions = new Map();
|
|
22
|
+
const removedAt = new Map();
|
|
23
|
+
// Rule outcomes overlay the store's reducer output (labels/categories/moves).
|
|
24
|
+
const overlay = new Map();
|
|
25
|
+
function currentItems() {
|
|
26
|
+
return store.listInbox().map((i) => overlay.get(i.messageId) ?? i);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
putMessage(envelope) {
|
|
30
|
+
store.putMessage(envelope);
|
|
31
|
+
},
|
|
32
|
+
appendEvent(event) {
|
|
33
|
+
const envelope = store.getMessage(event.messageId);
|
|
34
|
+
if (!envelope)
|
|
35
|
+
throw new Error(`unknown message ${event.messageId}`);
|
|
36
|
+
const prevOverlay = overlay.get(event.messageId);
|
|
37
|
+
const reduced = store.appendEvent(event);
|
|
38
|
+
revision += 1;
|
|
39
|
+
itemRevisions.set(event.messageId, revision);
|
|
40
|
+
if (event.eventType === 'tombstoned')
|
|
41
|
+
removedAt.set(event.messageId, revision);
|
|
42
|
+
const isAdmission = prevOverlay === undefined &&
|
|
43
|
+
(event.eventType === 'admitted' || event.eventType === 'delivered');
|
|
44
|
+
let application;
|
|
45
|
+
if (isAdmission) {
|
|
46
|
+
application = applyInboxRules(reduced, envelope, rules);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Preserve rule-applied labels/categories/priority across later events;
|
|
50
|
+
// folder + unread always follow the reducer (user actions win).
|
|
51
|
+
const merged = prevOverlay
|
|
52
|
+
? {
|
|
53
|
+
...reduced,
|
|
54
|
+
labels: [...new Set([...reduced.labels, ...prevOverlay.labels])],
|
|
55
|
+
categories: [...prevOverlay.categories],
|
|
56
|
+
priority: prevOverlay.priority,
|
|
57
|
+
}
|
|
58
|
+
: reduced;
|
|
59
|
+
application = { item: merged, notifications: [], suppressed: false, appliedRuleIds: [] };
|
|
60
|
+
}
|
|
61
|
+
overlay.set(event.messageId, application.item);
|
|
62
|
+
return application;
|
|
63
|
+
},
|
|
64
|
+
getInboxItem(id) {
|
|
65
|
+
return overlay.get(id) ?? store.getInboxItem(id);
|
|
66
|
+
},
|
|
67
|
+
listInbox(folder) {
|
|
68
|
+
return currentItems()
|
|
69
|
+
.filter((i) => (folder ? i.folder === folder : true))
|
|
70
|
+
.sort((a, b) => b.lastEventAt.localeCompare(a.lastEventAt));
|
|
71
|
+
},
|
|
72
|
+
listByContext(ref) {
|
|
73
|
+
return currentItems()
|
|
74
|
+
.filter((i) => i.folder !== 'trash' && matchesContextRef(i.contextRefs, ref))
|
|
75
|
+
.sort((a, b) => b.lastEventAt.localeCompare(a.lastEventAt));
|
|
76
|
+
},
|
|
77
|
+
unreadCount(folder) {
|
|
78
|
+
return currentItems().filter((i) => i.unread && (folder ? i.folder === folder : true)).length;
|
|
79
|
+
},
|
|
80
|
+
summarize() {
|
|
81
|
+
return summarizeFolders(currentItems());
|
|
82
|
+
},
|
|
83
|
+
revision() {
|
|
84
|
+
return revision;
|
|
85
|
+
},
|
|
86
|
+
deltaSince(cursor) {
|
|
87
|
+
if (cursor && cursor.streamId !== opts.streamId) {
|
|
88
|
+
throw new Error(`cursor stream ${cursor.streamId} does not match projector stream ${opts.streamId}`);
|
|
89
|
+
}
|
|
90
|
+
const since = cursor?.revision ?? 0;
|
|
91
|
+
const changed = currentItems().filter((i) => (itemRevisions.get(i.messageId) ?? 0) > since && !removedAt.has(i.messageId));
|
|
92
|
+
const removed = [...removedAt.entries()]
|
|
93
|
+
.filter(([, rev]) => rev > since)
|
|
94
|
+
.map(([id]) => id);
|
|
95
|
+
return {
|
|
96
|
+
cursor: { version: 'ap.inbox.cursor.v1', streamId: opts.streamId, revision },
|
|
97
|
+
changed,
|
|
98
|
+
removed,
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=projector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projector.js","sourceRoot":"","sources":["../../src/messaging/projector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CanonicalAgentId } from '@agenticprimitives/types';
|
|
2
|
+
import type { MessageEnvelopeV1, MessageEventV1 } from './types.js';
|
|
3
|
+
export declare function buildDeliveryReceipt(envelope: MessageEnvelopeV1, actor: CanonicalAgentId, at: string): MessageEventV1;
|
|
4
|
+
export declare function buildReadReceipt(envelope: MessageEnvelopeV1, actor: CanonicalAgentId, at: string): MessageEventV1;
|
|
5
|
+
//# sourceMappingURL=receipts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipts.d.ts","sourceRoot":"","sources":["../../src/messaging/receipts.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAkBpE,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,gBAAgB,EACvB,EAAE,EAAE,MAAM,GACT,cAAc,CAEhB;AAED,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,gBAAgB,EACvB,EAAE,EAAE,MAAM,GACT,cAAc,CAEhB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Delivery/read receipt builders (spec 309 §5). A receipt is a MessageEventV1
|
|
2
|
+
// the RECIPIENT emits back to the sender; fail-closed — only an addressed
|
|
3
|
+
// recipient may emit one. Signing the event is the caller's job.
|
|
4
|
+
function isRecipient(envelope, actor) {
|
|
5
|
+
return envelope.to.includes(actor) || (envelope.cc ?? []).includes(actor);
|
|
6
|
+
}
|
|
7
|
+
function buildReceipt(envelope, actor, eventType, at) {
|
|
8
|
+
if (!isRecipient(envelope, actor)) {
|
|
9
|
+
throw new Error(`${actor} is not a recipient of ${envelope.id}; cannot emit ${eventType} receipt`);
|
|
10
|
+
}
|
|
11
|
+
return { version: 'ap.message.event.v1', messageId: envelope.id, actor, eventType, at };
|
|
12
|
+
}
|
|
13
|
+
export function buildDeliveryReceipt(envelope, actor, at) {
|
|
14
|
+
return buildReceipt(envelope, actor, 'delivered', at);
|
|
15
|
+
}
|
|
16
|
+
export function buildReadReceipt(envelope, actor, at) {
|
|
17
|
+
return buildReceipt(envelope, actor, 'read', at);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=receipts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipts.js","sourceRoot":"","sources":["../../src/messaging/receipts.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,iEAAiE;AAKjE,SAAS,WAAW,CAAC,QAA2B,EAAE,KAAuB;IACvE,OAAO,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,YAAY,CACnB,QAA2B,EAC3B,KAAuB,EACvB,SAA+B,EAC/B,EAAU;IAEV,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,0BAA0B,QAAQ,CAAC,EAAE,iBAAiB,SAAS,UAAU,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,QAA2B,EAC3B,KAAuB,EACvB,EAAU;IAEV,OAAO,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAA2B,EAC3B,KAAuB,EACvB,EAAU;IAEV,OAAO,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { CanonicalAgentId } from '@agenticprimitives/types';
|
|
2
|
+
import type { VaultClassification } from '@agenticprimitives/vault';
|
|
3
|
+
import type { ContextRefV1, FolderKind, InboxItemV1, MessageEnvelopeV1, MessageId, MessageKind, MessagePriority } from './types.js';
|
|
4
|
+
/** AND across specified members; any-of within each list. Empty predicate matches all. */
|
|
5
|
+
export interface InboxRulePredicateV1 {
|
|
6
|
+
fromAnyOf?: CanonicalAgentId[];
|
|
7
|
+
kindAnyOf?: MessageKind[];
|
|
8
|
+
/** Case-insensitive substring match, any-of. */
|
|
9
|
+
subjectContainsAnyOf?: string[];
|
|
10
|
+
labelAnyOf?: string[];
|
|
11
|
+
priorityAtLeast?: MessagePriority;
|
|
12
|
+
hasAttachments?: boolean;
|
|
13
|
+
classificationAnyOf?: VaultClassification[];
|
|
14
|
+
hasInteraction?: boolean;
|
|
15
|
+
/** Matches messages ABOUT any of these contexts (spec 312). `id` omitted ⇒
|
|
16
|
+
* any ref of that kind matches ("everything about any org"). */
|
|
17
|
+
contextRefAnyOf?: Pick<ContextRefV1, 'kind' | 'id'>[];
|
|
18
|
+
}
|
|
19
|
+
/** Shared context-match used by rules and `listByContext` — ONE mechanism (ADR-0013). */
|
|
20
|
+
export declare function matchesContextRef(refs: readonly ContextRefV1[], query: {
|
|
21
|
+
kind: string;
|
|
22
|
+
id?: string;
|
|
23
|
+
}): boolean;
|
|
24
|
+
export type InboxRuleActionV1 = {
|
|
25
|
+
type: 'move';
|
|
26
|
+
folder: FolderKind;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'label';
|
|
29
|
+
label: string;
|
|
30
|
+
} | {
|
|
31
|
+
type: 'category';
|
|
32
|
+
category: string;
|
|
33
|
+
} | {
|
|
34
|
+
type: 'mark-read';
|
|
35
|
+
} | {
|
|
36
|
+
type: 'mark-unread';
|
|
37
|
+
} | {
|
|
38
|
+
type: 'set-priority';
|
|
39
|
+
priority: MessagePriority;
|
|
40
|
+
} | {
|
|
41
|
+
type: 'notify';
|
|
42
|
+
channel?: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'suppress-notification';
|
|
45
|
+
};
|
|
46
|
+
export interface InboxRuleV1 {
|
|
47
|
+
version: 'ap.inbox.rule.v1';
|
|
48
|
+
id: string;
|
|
49
|
+
name?: string;
|
|
50
|
+
/** Rules evaluate sorted by (order, id) — same input always yields same output. */
|
|
51
|
+
order: number;
|
|
52
|
+
enabled: boolean;
|
|
53
|
+
when: InboxRulePredicateV1;
|
|
54
|
+
except?: InboxRulePredicateV1;
|
|
55
|
+
actions: InboxRuleActionV1[];
|
|
56
|
+
/** Outlook-style: matching this rule stops evaluation of later rules. */
|
|
57
|
+
stopProcessing?: boolean;
|
|
58
|
+
}
|
|
59
|
+
export interface NotificationEventV1 {
|
|
60
|
+
version: 'ap.message.notification.v1';
|
|
61
|
+
messageId: MessageId;
|
|
62
|
+
ruleId: string;
|
|
63
|
+
channel?: string;
|
|
64
|
+
at: string;
|
|
65
|
+
}
|
|
66
|
+
/** Port for push/email/UI toast fan-out — implementations live in apps/runtimes. */
|
|
67
|
+
export interface NotificationSink {
|
|
68
|
+
notify(event: NotificationEventV1): void | Promise<void>;
|
|
69
|
+
}
|
|
70
|
+
export declare function matchesRulePredicate(predicate: InboxRulePredicateV1, envelope: MessageEnvelopeV1, item: InboxItemV1): boolean;
|
|
71
|
+
export interface RuleApplication {
|
|
72
|
+
item: InboxItemV1;
|
|
73
|
+
/** Empty when suppressed — a matching suppress-notification wins over notify. */
|
|
74
|
+
notifications: NotificationEventV1[];
|
|
75
|
+
suppressed: boolean;
|
|
76
|
+
appliedRuleIds: string[];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Pure, deterministic rule pass over a freshly projected inbox item.
|
|
80
|
+
* Rules run in (order, id) order; disabled rules skip; `except` vetoes `when`;
|
|
81
|
+
* `stopProcessing` halts later rules after the current one's actions apply.
|
|
82
|
+
*/
|
|
83
|
+
export declare function applyInboxRules(item: InboxItemV1, envelope: MessageEnvelopeV1, rules: InboxRuleV1[]): RuleApplication;
|
|
84
|
+
//# sourceMappingURL=rules.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/messaging/rules.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACpE,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,eAAe,EAChB,MAAM,YAAY,CAAC;AAIpB,0FAA0F;AAC1F,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,gDAAgD;IAChD,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;qEACiE;IACjE,eAAe,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;CACvD;AAED,yFAAyF;AACzF,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,YAAY,EAAE,EAC7B,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC,OAAO,CAET;AAED,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,uBAAuB,CAAA;CAAE,CAAC;AAEtC,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mFAAmF;IACnF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,4BAA4B,CAAC;IACtC,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,oFAAoF;AACpF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,oBAAoB,EAC/B,QAAQ,EAAE,iBAAiB,EAC3B,IAAI,EAAE,WAAW,GAChB,OAAO,CAyBT;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,WAAW,CAAC;IAClB,iFAAiF;IACjF,aAAa,EAAE,mBAAmB,EAAE,CAAC;IACrC,UAAU,EAAE,OAAO,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,iBAAiB,EAC3B,KAAK,EAAE,WAAW,EAAE,GACnB,eAAe,CAwDjB"}
|