@moltzap/client 2026.518.0 → 2026.519.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.
Files changed (84) hide show
  1. package/dist/channel-base/format-cross-conv.d.ts +43 -0
  2. package/dist/channel-base/format-cross-conv.d.ts.map +1 -0
  3. package/dist/channel-base/format-cross-conv.js +69 -0
  4. package/dist/channel-base/format-cross-conv.js.map +1 -0
  5. package/dist/channel-base/format-group-block.d.ts +43 -0
  6. package/dist/channel-base/format-group-block.d.ts.map +1 -0
  7. package/dist/channel-base/format-group-block.js +59 -0
  8. package/dist/channel-base/format-group-block.js.map +1 -0
  9. package/dist/channel-base/index.d.ts +21 -0
  10. package/dist/channel-base/index.d.ts.map +1 -0
  11. package/dist/channel-base/index.js +24 -0
  12. package/dist/channel-base/index.js.map +1 -0
  13. package/dist/channel-base/lease-guard.d.ts +30 -0
  14. package/dist/channel-base/lease-guard.d.ts.map +1 -0
  15. package/dist/channel-base/lease-guard.js +40 -0
  16. package/dist/channel-base/lease-guard.js.map +1 -0
  17. package/dist/channel-base/lease-store.d.ts +30 -0
  18. package/dist/channel-base/lease-store.d.ts.map +1 -0
  19. package/dist/channel-base/lease-store.js +58 -0
  20. package/dist/channel-base/lease-store.js.map +1 -0
  21. package/dist/channel-base/lease.d.ts +94 -0
  22. package/dist/channel-base/lease.d.ts.map +1 -0
  23. package/dist/channel-base/lease.js +110 -0
  24. package/dist/channel-base/lease.js.map +1 -0
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +4 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/notification/__tests__/filter-equivalence.test.d.ts +2 -0
  30. package/dist/notification/__tests__/filter-equivalence.test.d.ts.map +1 -0
  31. package/dist/notification/__tests__/filter-equivalence.test.js +123 -0
  32. package/dist/notification/__tests__/filter-equivalence.test.js.map +1 -0
  33. package/dist/notification/__tests__/snapshot-semantics.test.d.ts +2 -0
  34. package/dist/notification/__tests__/snapshot-semantics.test.d.ts.map +1 -0
  35. package/dist/notification/__tests__/snapshot-semantics.test.js +261 -0
  36. package/dist/notification/__tests__/snapshot-semantics.test.js.map +1 -0
  37. package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts +3 -0
  38. package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts.map +1 -0
  39. package/dist/notification/__tests__/snapshot-semantics.types-check.js +62 -0
  40. package/dist/notification/__tests__/snapshot-semantics.types-check.js.map +1 -0
  41. package/dist/notification/errors.d.ts +27 -0
  42. package/dist/notification/errors.d.ts.map +1 -0
  43. package/dist/notification/errors.js +24 -0
  44. package/dist/notification/errors.js.map +1 -0
  45. package/dist/notification/stream.d.ts +84 -0
  46. package/dist/notification/stream.d.ts.map +1 -0
  47. package/dist/notification/stream.js +106 -0
  48. package/dist/notification/stream.js.map +1 -0
  49. package/dist/runtime/index.d.ts +3 -4
  50. package/dist/runtime/index.d.ts.map +1 -1
  51. package/dist/runtime/index.js +3 -3
  52. package/dist/runtime/service-teardown.d.ts +5 -0
  53. package/dist/runtime/service-teardown.d.ts.map +1 -0
  54. package/dist/runtime/service-teardown.js +36 -0
  55. package/dist/runtime/service-teardown.js.map +1 -0
  56. package/dist/runtime/service-teardown.test.d.ts +2 -0
  57. package/dist/runtime/service-teardown.test.d.ts.map +1 -0
  58. package/dist/runtime/service-teardown.test.js +80 -0
  59. package/dist/runtime/service-teardown.test.js.map +1 -0
  60. package/dist/runtime/subscribers.d.ts +74 -136
  61. package/dist/runtime/subscribers.d.ts.map +1 -1
  62. package/dist/runtime/subscribers.js +187 -93
  63. package/dist/runtime/subscribers.js.map +1 -1
  64. package/dist/service.d.ts +10 -0
  65. package/dist/service.d.ts.map +1 -1
  66. package/dist/service.js +45 -12
  67. package/dist/service.js.map +1 -1
  68. package/dist/test-utils/conformance-adapter.d.ts +6 -16
  69. package/dist/test-utils/conformance-adapter.d.ts.map +1 -1
  70. package/dist/test-utils/conformance-adapter.js +100 -59
  71. package/dist/test-utils/conformance-adapter.js.map +1 -1
  72. package/dist/ws-client-test-support.d.ts +1 -1
  73. package/dist/ws-client-test-support.d.ts.map +1 -1
  74. package/dist/ws-client-test-support.js +24 -3
  75. package/dist/ws-client-test-support.js.map +1 -1
  76. package/dist/ws-client.d.ts +52 -54
  77. package/dist/ws-client.d.ts.map +1 -1
  78. package/dist/ws-client.js +40 -168
  79. package/dist/ws-client.js.map +1 -1
  80. package/package.json +7 -3
  81. package/dist/runtime/subscribers.test.d.ts +0 -2
  82. package/dist/runtime/subscribers.test.d.ts.map +0 -1
  83. package/dist/runtime/subscribers.test.js +0 -193
  84. package/dist/runtime/subscribers.test.js.map +0 -1
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Channel-base `formatCrossConv` — shared cross-conversation message
3
+ * formatter parameterized by markup variant or per-channel formatter
4
+ * callback.
5
+ *
6
+ * Replaces:
7
+ * - `packages/openclaw-channel/src/format-cross-conv.ts → formatCrossConvOpenClaw`
8
+ * (markup variant: `"json-header"`)
9
+ * - `packages/nanoclaw-channel/src/channels/moltzap.ts → formatCrossConvNanoclaw`
10
+ * (markup variant: `"xml-system-reminder"`)
11
+ *
12
+ * Behavioral parity is locked via the golden-snapshot fixtures captured
13
+ * pre-refactor — see arch sub-issue #605 §3.5 and §4.6.
14
+ */
15
+ import { type CrossConvMessage } from "../service.js";
16
+ export type { CrossConvMessage };
17
+ export type CrossConvMarkup = "json-header" | "xml-system-reminder";
18
+ export type CrossConvFormatter = (messages: readonly CrossConvMessage[], opts: {
19
+ readonly ownAgentId: string;
20
+ }) => string;
21
+ /**
22
+ * Returns the formatted block, or `null` when `messages` is empty.
23
+ *
24
+ * Markup variants:
25
+ * - `"json-header"`: byte-identical to the pre-refactor openclaw output.
26
+ * Header is `"Messages (untrusted metadata):"` followed by a ` ```json `
27
+ * fenced JSON array.
28
+ * - `"xml-system-reminder"`: byte-identical to the pre-refactor nanoclaw
29
+ * output. `<messages>` wrapper around `<message>` entries with
30
+ * `sender`/`conversation`/`time` attributes; sender/conv/time/text all
31
+ * run through `sanitizeForSystemReminder`.
32
+ *
33
+ * Or pass a custom `formatter` callback — channel-base owns the empty-check
34
+ * + ownAgentId disambiguation; the callback owns the markup.
35
+ */
36
+ export declare function formatCrossConv(messages: readonly CrossConvMessage[], opts: {
37
+ readonly ownAgentId: string;
38
+ readonly markup: CrossConvMarkup;
39
+ } | {
40
+ readonly ownAgentId: string;
41
+ readonly formatter: CrossConvFormatter;
42
+ }): string | null;
43
+ //# sourceMappingURL=format-cross-conv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-cross-conv.d.ts","sourceRoot":"","sources":["../../src/channel-base/format-cross-conv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EACL,KAAK,gBAAgB,EAEtB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,qBAAqB,CAAC;AAEpE,MAAM,MAAM,kBAAkB,GAAG,CAC/B,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EACrC,IAAI,EAAE;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,KAClC,MAAM,CAAC;AAmDZ;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EACrC,IAAI,EACA;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACjE;IAAE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,kBAAkB,CAAA;CAAE,GAC1E,MAAM,GAAG,IAAI,CAWf"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Channel-base `formatCrossConv` — shared cross-conversation message
3
+ * formatter parameterized by markup variant or per-channel formatter
4
+ * callback.
5
+ *
6
+ * Replaces:
7
+ * - `packages/openclaw-channel/src/format-cross-conv.ts → formatCrossConvOpenClaw`
8
+ * (markup variant: `"json-header"`)
9
+ * - `packages/nanoclaw-channel/src/channels/moltzap.ts → formatCrossConvNanoclaw`
10
+ * (markup variant: `"xml-system-reminder"`)
11
+ *
12
+ * Behavioral parity is locked via the golden-snapshot fixtures captured
13
+ * pre-refactor — see arch sub-issue #605 §3.5 and §4.6.
14
+ */
15
+ import { sanitizeForSystemReminder, } from "../service.js";
16
+ const CROSS_CONV_HEADER_JSON = "Messages (untrusted metadata):";
17
+ const JSON_INDENT_SPACES = 2;
18
+ function normalizeMessage(message, opts) {
19
+ return {
20
+ conversation: message.conversationName ?? `DM with @${message.senderName}`,
21
+ sender: message.senderId === opts.ownAgentId ? "You" : message.senderName,
22
+ text: message.text,
23
+ timestamp: message.timestamp,
24
+ };
25
+ }
26
+ function formatJsonHeader(messages, opts) {
27
+ const items = messages.map((m) => normalizeMessage(m, opts));
28
+ return `${CROSS_CONV_HEADER_JSON}\n\`\`\`json\n${JSON.stringify(items, null, JSON_INDENT_SPACES)}\n\`\`\``;
29
+ }
30
+ function formatXmlSystemReminder(messages, opts) {
31
+ const lines = messages.map((m) => {
32
+ const item = normalizeMessage(m, opts);
33
+ const sender = sanitizeForSystemReminder(item.sender);
34
+ const conv = sanitizeForSystemReminder(item.conversation);
35
+ const text = sanitizeForSystemReminder(item.text);
36
+ const time = sanitizeForSystemReminder(item.timestamp);
37
+ return `<message sender="${sender}" conversation="${conv}" time="${time}">${text}</message>`;
38
+ });
39
+ return ["<messages>", ...lines, "</messages>"].join("\n");
40
+ }
41
+ /**
42
+ * Returns the formatted block, or `null` when `messages` is empty.
43
+ *
44
+ * Markup variants:
45
+ * - `"json-header"`: byte-identical to the pre-refactor openclaw output.
46
+ * Header is `"Messages (untrusted metadata):"` followed by a ` ```json `
47
+ * fenced JSON array.
48
+ * - `"xml-system-reminder"`: byte-identical to the pre-refactor nanoclaw
49
+ * output. `&lt;messages&gt;` wrapper around `&lt;message&gt;` entries with
50
+ * `sender`/`conversation`/`time` attributes; sender/conv/time/text all
51
+ * run through `sanitizeForSystemReminder`.
52
+ *
53
+ * Or pass a custom `formatter` callback — channel-base owns the empty-check
54
+ * + ownAgentId disambiguation; the callback owns the markup.
55
+ */
56
+ export function formatCrossConv(messages, opts) {
57
+ if (messages.length === 0)
58
+ return null;
59
+ if ("formatter" in opts) {
60
+ return opts.formatter(messages, { ownAgentId: opts.ownAgentId });
61
+ }
62
+ switch (opts.markup) {
63
+ case "json-header":
64
+ return formatJsonHeader(messages, { ownAgentId: opts.ownAgentId });
65
+ case "xml-system-reminder":
66
+ return formatXmlSystemReminder(messages, { ownAgentId: opts.ownAgentId });
67
+ }
68
+ }
69
+ //# sourceMappingURL=format-cross-conv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-cross-conv.js","sourceRoot":"","sources":["../../src/channel-base/format-cross-conv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAEL,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAWvB,MAAM,sBAAsB,GAAG,gCAAgC,CAAC;AAChE,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAS7B,SAAS,gBAAgB,CACvB,OAAyB,EACzB,IAAqC;IAErC,OAAO;QACL,YAAY,EAAE,OAAO,CAAC,gBAAgB,IAAI,YAAY,OAAO,CAAC,UAAU,EAAE;QAC1E,MAAM,EAAE,OAAO,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU;QACzE,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,QAAqC,EACrC,IAAqC;IAErC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IAC7D,OAAO,GAAG,sBAAsB,iBAAiB,IAAI,CAAC,SAAS,CAC7D,KAAK,EACL,IAAI,EACJ,kBAAkB,CACnB,UAAU,CAAC;AACd,CAAC;AAED,SAAS,uBAAuB,CAC9B,QAAqC,EACrC,IAAqC;IAErC,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC/B,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,yBAAyB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACvD,OAAO,oBAAoB,MAAM,mBAAmB,IAAI,WAAW,IAAI,KAAK,IAAI,YAAY,CAAC;IAC/F,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,YAAY,EAAE,GAAG,KAAK,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAC7B,QAAqC,EACrC,IAE2E;IAE3E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,aAAa;YAChB,OAAO,gBAAgB,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;QACrE,KAAK,qBAAqB;YACxB,OAAO,uBAAuB,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Channel-base group-block helpers.
3
+ *
4
+ * Replaces nanoclaw's inline `formatGroupBlock` at
5
+ * `packages/nanoclaw-channel/src/channels/moltzap.ts → formatGroupBlock`. Also
6
+ * extracts the shared type-narrowing predicate (`getGroupFields`) consumed by
7
+ * openclaw (deriving `groupSubject` / `groupMembers` for the OpenClaw context)
8
+ * and nanoclaw (gating the inline group-block render).
9
+ */
10
+ import type { EnrichedConversationMeta } from "../channel-core.js";
11
+ import type { CrossConvMarkup } from "./format-cross-conv.js";
12
+ export interface GroupFields {
13
+ readonly name: string | undefined;
14
+ readonly participants: readonly string[];
15
+ }
16
+ export type GroupFormatter = (fields: GroupFields) => string;
17
+ /**
18
+ * Returns `{ name, participants }` when `meta?.type === "group"`; else `null`.
19
+ * Pure narrowing helper — callers use the non-null return to drive
20
+ * `formatGroupBlock` or per-channel field extraction (openclaw's
21
+ * `groupSubject` + `groupMembers`).
22
+ */
23
+ export declare function getGroupFields(meta: EnrichedConversationMeta | undefined): GroupFields | null;
24
+ /**
25
+ * Returns the formatted group block.
26
+ *
27
+ * Markup variants:
28
+ * - `"xml-system-reminder"`: byte-identical to the pre-refactor nanoclaw
29
+ * output (a `&lt;system-reminder&gt;` block with group name + participants).
30
+ * - `"json-header"`: empty string. Openclaw does not render a group block;
31
+ * it consumes `getGroupFields` directly to derive its OpenClaw-side
32
+ * `groupSubject` / `groupMembers` fields. The empty-string return locks
33
+ * the "openclaw renders no group block" behavior as an explicit,
34
+ * fixtured output (see arch sub-issue #605 §3.5).
35
+ *
36
+ * Or pass a custom `formatter` callback.
37
+ */
38
+ export declare function formatGroupBlock(fields: GroupFields, opts: {
39
+ readonly markup: CrossConvMarkup;
40
+ } | {
41
+ readonly formatter: GroupFormatter;
42
+ }): string;
43
+ //# sourceMappingURL=format-group-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-group-block.d.ts","sourceRoot":"","sources":["../../src/channel-base/format-group-block.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,MAAM,CAAC;AAK7D;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,wBAAwB,GAAG,SAAS,GACzC,WAAW,GAAG,IAAI,CAGpB;AAgBD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EACnB,IAAI,EACA;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAA;CAAE,GACpC;IAAE,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;CAAE,GACzC,MAAM,CAQR"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Channel-base group-block helpers.
3
+ *
4
+ * Replaces nanoclaw's inline `formatGroupBlock` at
5
+ * `packages/nanoclaw-channel/src/channels/moltzap.ts → formatGroupBlock`. Also
6
+ * extracts the shared type-narrowing predicate (`getGroupFields`) consumed by
7
+ * openclaw (deriving `groupSubject` / `groupMembers` for the OpenClaw context)
8
+ * and nanoclaw (gating the inline group-block render).
9
+ */
10
+ import { sanitizeForSystemReminder } from "../service.js";
11
+ const UNNAMED_GROUP_FALLBACK = "(unnamed)";
12
+ const NO_PARTICIPANTS_FALLBACK = "(none listed)";
13
+ /**
14
+ * Returns `{ name, participants }` when `meta?.type === "group"`; else `null`.
15
+ * Pure narrowing helper — callers use the non-null return to drive
16
+ * `formatGroupBlock` or per-channel field extraction (openclaw's
17
+ * `groupSubject` + `groupMembers`).
18
+ */
19
+ export function getGroupFields(meta) {
20
+ if (meta?.type !== "group")
21
+ return null;
22
+ return { name: meta.name, participants: meta.participants };
23
+ }
24
+ function formatXmlSystemReminder(fields) {
25
+ const safeName = sanitizeForSystemReminder(fields.name ?? UNNAMED_GROUP_FALLBACK);
26
+ const safeParticipants = fields.participants.map(sanitizeForSystemReminder);
27
+ return [
28
+ "<system-reminder>",
29
+ "This is a group conversation.",
30
+ `Group name: ${safeName}`,
31
+ `Participants (${fields.participants.length}): ${safeParticipants.join(", ") || NO_PARTICIPANTS_FALLBACK}`,
32
+ "</system-reminder>",
33
+ ].join("\n");
34
+ }
35
+ /**
36
+ * Returns the formatted group block.
37
+ *
38
+ * Markup variants:
39
+ * - `"xml-system-reminder"`: byte-identical to the pre-refactor nanoclaw
40
+ * output (a `&lt;system-reminder&gt;` block with group name + participants).
41
+ * - `"json-header"`: empty string. Openclaw does not render a group block;
42
+ * it consumes `getGroupFields` directly to derive its OpenClaw-side
43
+ * `groupSubject` / `groupMembers` fields. The empty-string return locks
44
+ * the "openclaw renders no group block" behavior as an explicit,
45
+ * fixtured output (see arch sub-issue #605 §3.5).
46
+ *
47
+ * Or pass a custom `formatter` callback.
48
+ */
49
+ export function formatGroupBlock(fields, opts) {
50
+ if ("formatter" in opts)
51
+ return opts.formatter(fields);
52
+ switch (opts.markup) {
53
+ case "xml-system-reminder":
54
+ return formatXmlSystemReminder(fields);
55
+ case "json-header":
56
+ return "";
57
+ }
58
+ }
59
+ //# sourceMappingURL=format-group-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-group-block.js","sourceRoot":"","sources":["../../src/channel-base/format-group-block.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAW1D,MAAM,sBAAsB,GAAG,WAAW,CAAC;AAC3C,MAAM,wBAAwB,GAAG,eAAe,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,IAA0C;IAE1C,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,uBAAuB,CAAC,MAAmB;IAClD,MAAM,QAAQ,GAAG,yBAAyB,CACxC,MAAM,CAAC,IAAI,IAAI,sBAAsB,CACtC,CAAC;IACF,MAAM,gBAAgB,GAAG,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IAC5E,OAAO;QACL,mBAAmB;QACnB,+BAA+B;QAC/B,eAAe,QAAQ,EAAE;QACzB,iBAAiB,MAAM,CAAC,YAAY,CAAC,MAAM,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,wBAAwB,EAAE;QAC1G,oBAAoB;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAmB,EACnB,IAE0C;IAE1C,IAAI,WAAW,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACvD,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,qBAAqB;YACxB,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACzC,KAAK,aAAa;YAChB,OAAO,EAAE,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @file `@moltzap/client/channel-base` — shared scaffolding for channel adapters.
3
+ *
4
+ * Used by `@moltzap/openclaw-channel`, `@moltzap/claude-code-channel`, and
5
+ * `@moltzap/nanoclaw-channel` to canonicalize the lease-lifecycle primitives,
6
+ * the `LeaseAlreadyConsumed` tagged error, and the markup-parameterized
7
+ * cross-conv + group-block formatters. Detail doc:
8
+ * `packages/client/docs/architecture/08-channel-base.md`. Spec: #597.
9
+ * Architect plan: #605.
10
+ *
11
+ * Note: this subpath is opt-in. Direct `@moltzap/client` consumers
12
+ * (server-core, runtimes, test-utils) see no API-surface change.
13
+ */
14
+ export { LeaseAlreadyConsumed, projectLeaseInvalid, catchLeaseInvalid, type LeaseInvalidProjectionError, } from "./lease.js";
15
+ export { LeaseStore } from "./lease-store.js";
16
+ export { LeaseGuard } from "./lease-guard.js";
17
+ export { formatCrossConv, type CrossConvFormatter, type CrossConvMarkup, } from "./format-cross-conv.js";
18
+ export { formatGroupBlock, getGroupFields, type GroupFields, type GroupFormatter, } from "./format-group-block.js";
19
+ export { sanitizeForSystemReminder, type CrossConvMessage, } from "../service.js";
20
+ export { type EnrichedConversationMeta } from "../channel-core.js";
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/channel-base/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,KAAK,2BAA2B,GACjC,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,eAAe,EACf,KAAK,kBAAkB,EACvB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,cAAc,GACpB,MAAM,yBAAyB,CAAC;AAKjC,OAAO,EACL,yBAAyB,EACzB,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @file `@moltzap/client/channel-base` — shared scaffolding for channel adapters.
3
+ *
4
+ * Used by `@moltzap/openclaw-channel`, `@moltzap/claude-code-channel`, and
5
+ * `@moltzap/nanoclaw-channel` to canonicalize the lease-lifecycle primitives,
6
+ * the `LeaseAlreadyConsumed` tagged error, and the markup-parameterized
7
+ * cross-conv + group-block formatters. Detail doc:
8
+ * `packages/client/docs/architecture/08-channel-base.md`. Spec: #597.
9
+ * Architect plan: #605.
10
+ *
11
+ * Note: this subpath is opt-in. Direct `@moltzap/client` consumers
12
+ * (server-core, runtimes, test-utils) see no API-surface change.
13
+ */
14
+ export { LeaseAlreadyConsumed, projectLeaseInvalid, catchLeaseInvalid, } from "./lease.js";
15
+ export { LeaseStore } from "./lease-store.js";
16
+ export { LeaseGuard } from "./lease-guard.js";
17
+ export { formatCrossConv, } from "./format-cross-conv.js";
18
+ export { formatGroupBlock, getGroupFields, } from "./format-group-block.js";
19
+ // Re-exports for ergonomics on the subpath (these are part of the public
20
+ // `@moltzap/client` barrel already; channel-base callers shouldn't need to
21
+ // import from two paths to use the formatters).
22
+ export { sanitizeForSystemReminder, } from "../service.js";
23
+ export {} from "../channel-core.js";
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/channel-base/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,GAElB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,eAAe,GAGhB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,gBAAgB,EAChB,cAAc,GAGf,MAAM,yBAAyB,CAAC;AAEjC,yEAAyE;AACzE,2EAA2E;AAC3E,gDAAgD;AAChD,OAAO,EACL,yBAAyB,GAE1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiC,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Channel-base `LeaseGuard` — per-dispatch single-shot client-side dup-reply
3
+ * detection.
4
+ *
5
+ * Replaces openclaw's `consumedLeaseAt: number | null` closure in
6
+ * `packages/openclaw-channel/src/openclaw-entry.ts → createLeaseConsumingDeliver`.
7
+ * One `LeaseGuard` instance per inbound message (created inside the deliver
8
+ * wrapper); `consume()` returns true exactly once, false on every subsequent
9
+ * call.
10
+ *
11
+ * Backed by a private `number | null` field that records
12
+ * `Clock.currentTimeMillis` on the first consume.
13
+ */
14
+ import { Effect, Option } from "effect";
15
+ export declare class LeaseGuard {
16
+ #private;
17
+ /**
18
+ * Returns `true` on first call (transitions internal state from
19
+ * "not-consumed" to "consumed-at-now"); returns `false` on every later
20
+ * call. Reads `Clock.currentTimeMillis` inside the Effect on first call.
21
+ */
22
+ consume(): Effect.Effect<boolean, never, never>;
23
+ /**
24
+ * `Option.none` before the first `consume`; `Option.some(epochMs)` after,
25
+ * where `epochMs` is the value Clock returned at the first-consume moment.
26
+ * Idempotent on second-and-later reads.
27
+ */
28
+ get consumedAt(): Effect.Effect<Option.Option<number>, never, never>;
29
+ }
30
+ //# sourceMappingURL=lease-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-guard.d.ts","sourceRoot":"","sources":["../../src/channel-base/lease-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAS,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE/C,qBAAa,UAAU;;IAGrB;;;;OAIG;IACH,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC;IAS/C;;;;OAIG;IACH,IAAI,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAInE;CACF"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Channel-base `LeaseGuard` — per-dispatch single-shot client-side dup-reply
3
+ * detection.
4
+ *
5
+ * Replaces openclaw's `consumedLeaseAt: number | null` closure in
6
+ * `packages/openclaw-channel/src/openclaw-entry.ts → createLeaseConsumingDeliver`.
7
+ * One `LeaseGuard` instance per inbound message (created inside the deliver
8
+ * wrapper); `consume()` returns true exactly once, false on every subsequent
9
+ * call.
10
+ *
11
+ * Backed by a private `number | null` field that records
12
+ * `Clock.currentTimeMillis` on the first consume.
13
+ */
14
+ import { Clock, Effect, Option } from "effect";
15
+ export class LeaseGuard {
16
+ #consumedAt = null;
17
+ /**
18
+ * Returns `true` on first call (transitions internal state from
19
+ * "not-consumed" to "consumed-at-now"); returns `false` on every later
20
+ * call. Reads `Clock.currentTimeMillis` inside the Effect on first call.
21
+ */
22
+ consume() {
23
+ return Effect.gen(this, function* () {
24
+ if (this.#consumedAt !== null)
25
+ return false;
26
+ const ts = yield* Clock.currentTimeMillis;
27
+ this.#consumedAt = ts;
28
+ return true;
29
+ });
30
+ }
31
+ /**
32
+ * `Option.none` before the first `consume`; `Option.some(epochMs)` after,
33
+ * where `epochMs` is the value Clock returned at the first-consume moment.
34
+ * Idempotent on second-and-later reads.
35
+ */
36
+ get consumedAt() {
37
+ return Effect.sync(() => this.#consumedAt === null ? Option.none() : Option.some(this.#consumedAt));
38
+ }
39
+ }
40
+ //# sourceMappingURL=lease-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-guard.js","sourceRoot":"","sources":["../../src/channel-base/lease-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE/C,MAAM,OAAO,UAAU;IACrB,WAAW,GAAkB,IAAI,CAAC;IAElC;;;;OAIG;IACH,OAAO;QACL,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC;YAC/B,IAAI,IAAI,CAAC,WAAW,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YAC5C,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC1C,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,IAAI,UAAU;QACZ,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CACtB,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAC1E,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Channel-base `LeaseStore` — generic per-key payload tracker.
3
+ *
4
+ * Nanoclaw uses a string-keyed, string-valued store (keyed by JID, payload
5
+ * is the dispatchLeaseId string). The deliberate "keep stale entry to trigger
6
+ * server CONSUMED rejection on retry" semantic is preserved via `peek`
7
+ * (read-only) — see arch sub-issue #605 §3.3 and §6.3.
8
+ *
9
+ * The class wraps a private `Map`; Effect wrappers are for caller-side
10
+ * composition. Single-threaded by construction — one instance lives per
11
+ * channel runtime, accessed from the host event loop.
12
+ */
13
+ import { Effect, Option } from "effect";
14
+ export declare class LeaseStore<HostKey, T> {
15
+ #private;
16
+ /** Overwrite-on-newer-inbound. Last-write-wins per spec table. */
17
+ remember(key: HostKey, payload: T): Effect.Effect<void, never, never>;
18
+ /**
19
+ * Read-only lookup. Does NOT delete. Nanoclaw uses this for the
20
+ * stale-entry-on-retry semantic at `MoltZapChannel.sendMessage`.
21
+ */
22
+ peek(key: HostKey): Effect.Effect<Option.Option<T>, never, never>;
23
+ /** Read-and-delete. `Option.none` if absent (no throw). */
24
+ consume(key: HostKey): Effect.Effect<Option.Option<T>, never, never>;
25
+ /** Clears one key (when provided) or the whole store. */
26
+ clear(key?: HostKey): Effect.Effect<void, never, never>;
27
+ /** Entry count. */
28
+ get size(): Effect.Effect<number, never, never>;
29
+ }
30
+ //# sourceMappingURL=lease-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-store.d.ts","sourceRoot":"","sources":["../../src/channel-base/lease-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,qBAAa,UAAU,CAAC,OAAO,EAAE,CAAC;;IAGhC,kEAAkE;IAClE,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;IAMrE;;;OAGG;IACH,IAAI,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;IAOjE,2DAA2D;IAC3D,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;IASpE,yDAAyD;IACzD,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC;IAUvD,mBAAmB;IACnB,IAAI,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAE9C;CACF"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Channel-base `LeaseStore` — generic per-key payload tracker.
3
+ *
4
+ * Nanoclaw uses a string-keyed, string-valued store (keyed by JID, payload
5
+ * is the dispatchLeaseId string). The deliberate "keep stale entry to trigger
6
+ * server CONSUMED rejection on retry" semantic is preserved via `peek`
7
+ * (read-only) — see arch sub-issue #605 §3.3 and §6.3.
8
+ *
9
+ * The class wraps a private `Map`; Effect wrappers are for caller-side
10
+ * composition. Single-threaded by construction — one instance lives per
11
+ * channel runtime, accessed from the host event loop.
12
+ */
13
+ import { Effect, Option } from "effect";
14
+ export class LeaseStore {
15
+ #entries = new Map();
16
+ /** Overwrite-on-newer-inbound. Last-write-wins per spec table. */
17
+ remember(key, payload) {
18
+ return Effect.sync(() => {
19
+ this.#entries.set(key, payload);
20
+ });
21
+ }
22
+ /**
23
+ * Read-only lookup. Does NOT delete. Nanoclaw uses this for the
24
+ * stale-entry-on-retry semantic at `MoltZapChannel.sendMessage`.
25
+ */
26
+ peek(key) {
27
+ return Effect.sync(() => {
28
+ const existing = this.#entries.get(key);
29
+ return existing === undefined ? Option.none() : Option.some(existing);
30
+ });
31
+ }
32
+ /** Read-and-delete. `Option.none` if absent (no throw). */
33
+ consume(key) {
34
+ return Effect.sync(() => {
35
+ const existing = this.#entries.get(key);
36
+ if (existing === undefined)
37
+ return Option.none();
38
+ this.#entries.delete(key);
39
+ return Option.some(existing);
40
+ });
41
+ }
42
+ /** Clears one key (when provided) or the whole store. */
43
+ clear(key) {
44
+ return Effect.sync(() => {
45
+ if (key === undefined) {
46
+ this.#entries.clear();
47
+ }
48
+ else {
49
+ this.#entries.delete(key);
50
+ }
51
+ });
52
+ }
53
+ /** Entry count. */
54
+ get size() {
55
+ return Effect.sync(() => this.#entries.size);
56
+ }
57
+ }
58
+ //# sourceMappingURL=lease-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease-store.js","sourceRoot":"","sources":["../../src/channel-base/lease-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAExC,MAAM,OAAO,UAAU;IACZ,QAAQ,GAAG,IAAI,GAAG,EAAc,CAAC;IAE1C,kEAAkE;IAClE,QAAQ,CAAC,GAAY,EAAE,OAAU;QAC/B,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,GAAY;QACf,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC;IAED,2DAA2D;IAC3D,OAAO,CAAC,GAAY;QAClB,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,QAAQ,KAAK,SAAS;gBAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;YACjD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,OAAO,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,yDAAyD;IACzD,KAAK,CAAC,GAAa;QACjB,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;YACtB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;gBACtB,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mBAAmB;IACnB,IAAI,IAAI;QACN,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;CACF"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Channel-base lease primitives.
3
+ *
4
+ * Public surface for spec C (#597):
5
+ * - `LeaseAlreadyConsumed`: canonical tagged error class. One definition site
6
+ * across all three channels (claude-code, openclaw, nanoclaw).
7
+ * - `projectLeaseInvalid`: predicate that narrows a `RpcServerError` to
8
+ * `LeaseAlreadyConsumed` when the server's wire-error payload matches the
9
+ * single-use-lease shape.
10
+ * - `catchLeaseInvalid`: Effect-pipe convenience that runs the projection
11
+ * inside `Effect.catchTag("RpcServerError", ...)` with
12
+ * `Clock.currentTimeMillis` threaded into the projector as `consumedAt`.
13
+ */
14
+ import { Effect } from "effect";
15
+ import { RpcServerError } from "@moltzap/protocol";
16
+ declare const LeaseAlreadyConsumed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
17
+ readonly _tag: "LeaseAlreadyConsumed";
18
+ } & Readonly<A>;
19
+ /**
20
+ * The dispatch lease was already consumed (server returned the typed
21
+ * single-use-lease failure on a second `messages/send` for the same lease).
22
+ *
23
+ * Construction is **only** via `projectLeaseInvalid` (or `catchLeaseInvalid`).
24
+ * The original `RpcServerError` is preserved on `cause` so hosts can inspect
25
+ * the wire payload without re-fetching.
26
+ *
27
+ * See arch sub-issue #605 §3.1 for the shape rationale (cause field is the
28
+ * verbatim wire error; consumedAt is `Clock.currentTimeMillis` at projection
29
+ * time; message is derived from cause.message).
30
+ */
31
+ export declare class LeaseAlreadyConsumed extends LeaseAlreadyConsumed_base<{
32
+ readonly leaseId: string;
33
+ readonly consumedAt: number;
34
+ readonly cause: RpcServerError;
35
+ readonly message: string;
36
+ }> {
37
+ }
38
+ /**
39
+ * Named alias for the error channel produced by `catchLeaseInvalid` over an
40
+ * effect with residual error `E`. Equivalent to
41
+ * `LeaseAlreadyConsumed | RpcServerError | E`, but referencable from external
42
+ * consumers (per arch sub-issue #605 §5.1 named-error-union commitment).
43
+ */
44
+ export type LeaseInvalidProjectionError<E> = LeaseAlreadyConsumed | RpcServerError | E;
45
+ /**
46
+ * Project an `RpcServerError` to `LeaseAlreadyConsumed` if it matches the
47
+ * lease-invalid wire shape; otherwise return the original error unchanged.
48
+ *
49
+ * Predicate (architect-corrected per arch sub-issue #605 §3.2):
50
+ * `err.data.reason === "LeaseInvalid"` OR
51
+ * `err.data._tag === "LeaseAlreadyConsumed"` (forward-compat for a future
52
+ * server that emits the canonical tag in data).
53
+ *
54
+ * The wire code (-32001 / generic Forbidden) is intentionally NOT part of
55
+ * the predicate because the code is too generic to discriminate on alone.
56
+ *
57
+ * `ctx.leaseId` (optional) is the lease the caller just sent. Caller-supplied
58
+ * because the server's `ForbiddenError.data` shape does NOT carry leaseId.
59
+ * Falls back to `"(unknown)"` when omitted (matches the pre-refactor
60
+ * claude-code behavior).
61
+ *
62
+ * `ctx.consumedAt` (required) is the epoch ms to stamp on the resulting
63
+ * `LeaseAlreadyConsumed.consumedAt`. Required because `LeaseAlreadyConsumed`
64
+ * requires it and this function is synchronous (no Clock access). Callers
65
+ * either pass `Date.now()` directly or use `catchLeaseInvalid` which reads
66
+ * `Clock.currentTimeMillis` inside the Effect.
67
+ */
68
+ export declare function projectLeaseInvalid(err: RpcServerError, ctx: {
69
+ readonly leaseId?: string;
70
+ readonly consumedAt: number;
71
+ }): LeaseAlreadyConsumed | RpcServerError;
72
+ /**
73
+ * Effect-pipe convenience: catches `RpcServerError` and runs
74
+ * `projectLeaseInvalid` on each instance. Reads `Clock.currentTimeMillis`
75
+ * inside the catch and passes the result to `projectLeaseInvalid` as
76
+ * `consumedAt`. Matching errors are surfaced as the typed
77
+ * `LeaseAlreadyConsumed` on the failure channel; non-matching errors are
78
+ * re-raised unchanged so downstream `mapError`s see the original
79
+ * `RpcServerError`.
80
+ *
81
+ * Use at every channel's outbound `core.sendReply(...)` boundary:
82
+ *
83
+ * ```ts
84
+ * core.sendReply(conv, text, { dispatchLeaseId: leaseId }).pipe(
85
+ * catchLeaseInvalid({ leaseId }),
86
+ * // ... per-channel surfacing
87
+ * )
88
+ * ```
89
+ */
90
+ export declare function catchLeaseInvalid<A, E2, R>(ctx?: {
91
+ readonly leaseId?: string;
92
+ }): (eff: Effect.Effect<A, RpcServerError | E2, R>) => Effect.Effect<A, LeaseInvalidProjectionError<E2>, R>;
93
+ export {};
94
+ //# sourceMappingURL=lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../src/channel-base/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;;;;AAEnD;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,SAAQ,0BAExC;IACA,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;CAAG;AAEL;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,CAAC,CAAC,IACrC,oBAAoB,GACpB,cAAc,GACd,CAAC,CAAC;AAcN;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAC9D,oBAAoB,GAAG,cAAc,CAQvC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,GAAG,CACF,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,cAAc,GAAG,EAAE,EAAE,CAAC,CAAC,KAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,2BAA2B,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAyBxD"}