@moltzap/client 2026.726.0 → 2026.730.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 (200) hide show
  1. package/dist/agent-client.d.ts +2 -0
  2. package/dist/agent-client.d.ts.map +1 -1
  3. package/dist/agent-client.js +1 -0
  4. package/dist/agent-client.js.map +1 -1
  5. package/dist/app-client.d.ts +2 -0
  6. package/dist/app-client.d.ts.map +1 -1
  7. package/dist/app-client.js +1 -0
  8. package/dist/app-client.js.map +1 -1
  9. package/dist/auth.d.ts +7 -2
  10. package/dist/auth.d.ts.map +1 -1
  11. package/dist/auth.js +10 -5
  12. package/dist/auth.js.map +1 -1
  13. package/dist/channel-base/format-cross-conv.d.ts +8 -3
  14. package/dist/channel-base/format-cross-conv.d.ts.map +1 -1
  15. package/dist/channel-base/format-cross-conv.js +10 -9
  16. package/dist/channel-base/format-cross-conv.js.map +1 -1
  17. package/dist/channel-base/format-group-block.d.ts +9 -2
  18. package/dist/channel-base/format-group-block.d.ts.map +1 -1
  19. package/dist/channel-base/format-group-block.js +12 -7
  20. package/dist/channel-base/format-group-block.js.map +1 -1
  21. package/dist/channel-base/index.d.ts +8 -0
  22. package/dist/channel-base/index.d.ts.map +1 -1
  23. package/dist/channel-base/index.js +8 -0
  24. package/dist/channel-base/index.js.map +1 -1
  25. package/dist/channel-base/lease-guard.d.ts +6 -3
  26. package/dist/channel-base/lease-guard.d.ts.map +1 -1
  27. package/dist/channel-base/lease-guard.js +10 -4
  28. package/dist/channel-base/lease-guard.js.map +1 -1
  29. package/dist/channel-base/lease-store.d.ts +29 -10
  30. package/dist/channel-base/lease-store.d.ts.map +1 -1
  31. package/dist/channel-base/lease-store.js +33 -13
  32. package/dist/channel-base/lease-store.js.map +1 -1
  33. package/dist/channel-base/lease.d.ts +9 -1
  34. package/dist/channel-base/lease.d.ts.map +1 -1
  35. package/dist/channel-base/lease.js +16 -4
  36. package/dist/channel-base/lease.js.map +1 -1
  37. package/dist/channel-core-enrichment.d.ts +9 -2
  38. package/dist/channel-core-enrichment.d.ts.map +1 -1
  39. package/dist/channel-core-enrichment.js +17 -5
  40. package/dist/channel-core-enrichment.js.map +1 -1
  41. package/dist/channel-core-test-support.d.ts +46 -0
  42. package/dist/channel-core-test-support.d.ts.map +1 -1
  43. package/dist/channel-core-test-support.js +67 -13
  44. package/dist/channel-core-test-support.js.map +1 -1
  45. package/dist/channel-core.d.ts +37 -22
  46. package/dist/channel-core.d.ts.map +1 -1
  47. package/dist/channel-core.js +45 -38
  48. package/dist/channel-core.js.map +1 -1
  49. package/dist/cli/adapters.d.ts +4 -1
  50. package/dist/cli/adapters.d.ts.map +1 -1
  51. package/dist/cli/adapters.js +11 -4
  52. package/dist/cli/adapters.js.map +1 -1
  53. package/dist/cli/commands/agents.js +3 -3
  54. package/dist/cli/commands/contacts.d.ts +3 -3
  55. package/dist/cli/commands/contacts.d.ts.map +1 -1
  56. package/dist/cli/commands/contacts.js +13 -9
  57. package/dist/cli/commands/contacts.js.map +1 -1
  58. package/dist/cli/commands/conversations.d.ts +3 -2
  59. package/dist/cli/commands/conversations.d.ts.map +1 -1
  60. package/dist/cli/commands/conversations.js +7 -6
  61. package/dist/cli/commands/conversations.js.map +1 -1
  62. package/dist/cli/commands/messages.d.ts +6 -2
  63. package/dist/cli/commands/messages.d.ts.map +1 -1
  64. package/dist/cli/commands/messages.js +8 -5
  65. package/dist/cli/commands/messages.js.map +1 -1
  66. package/dist/cli/commands/register.d.ts +1 -1
  67. package/dist/cli/commands/register.js +4 -4
  68. package/dist/cli/commands/send.d.ts +7 -6
  69. package/dist/cli/commands/send.d.ts.map +1 -1
  70. package/dist/cli/commands/send.js +7 -6
  71. package/dist/cli/commands/send.js.map +1 -1
  72. package/dist/cli/commands/start.d.ts +15 -7
  73. package/dist/cli/commands/start.d.ts.map +1 -1
  74. package/dist/cli/commands/start.js +12 -5
  75. package/dist/cli/commands/start.js.map +1 -1
  76. package/dist/cli/commands/status.js +2 -2
  77. package/dist/cli/commands/test-transport.d.ts +9 -1
  78. package/dist/cli/commands/test-transport.d.ts.map +1 -1
  79. package/dist/cli/commands/test-transport.js +5 -1
  80. package/dist/cli/commands/test-transport.js.map +1 -1
  81. package/dist/cli/index.js +8 -7
  82. package/dist/cli/index.js.map +1 -1
  83. package/dist/cli/output.d.ts +10 -0
  84. package/dist/cli/output.d.ts.map +1 -1
  85. package/dist/cli/output.js +10 -0
  86. package/dist/cli/output.js.map +1 -1
  87. package/dist/cli/socket-client.d.ts +13 -3
  88. package/dist/cli/socket-client.d.ts.map +1 -1
  89. package/dist/cli/socket-client.js +16 -5
  90. package/dist/cli/socket-client.js.map +1 -1
  91. package/dist/cli/transport.d.ts +16 -3
  92. package/dist/cli/transport.d.ts.map +1 -1
  93. package/dist/cli/transport.js +19 -6
  94. package/dist/cli/transport.js.map +1 -1
  95. package/dist/config.d.ts +15 -6
  96. package/dist/config.d.ts.map +1 -1
  97. package/dist/config.js +15 -5
  98. package/dist/config.js.map +1 -1
  99. package/dist/config.test-utils.d.ts +7 -2
  100. package/dist/config.test-utils.d.ts.map +1 -1
  101. package/dist/config.test-utils.js +8 -1
  102. package/dist/config.test-utils.js.map +1 -1
  103. package/dist/index.d.ts +3 -0
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +2 -0
  106. package/dist/index.js.map +1 -1
  107. package/dist/local-daemon-rpc.d.ts +122 -99
  108. package/dist/local-daemon-rpc.d.ts.map +1 -1
  109. package/dist/local-daemon-rpc.js +128 -108
  110. package/dist/local-daemon-rpc.js.map +1 -1
  111. package/dist/local-history.d.ts +40 -20
  112. package/dist/local-history.d.ts.map +1 -1
  113. package/dist/local-history.js +45 -23
  114. package/dist/local-history.js.map +1 -1
  115. package/dist/local-paths.d.ts +17 -0
  116. package/dist/local-paths.d.ts.map +1 -1
  117. package/dist/local-paths.js +21 -4
  118. package/dist/local-paths.js.map +1 -1
  119. package/dist/local-socket-server.d.ts +13 -2
  120. package/dist/local-socket-server.d.ts.map +1 -1
  121. package/dist/local-socket-server.js +13 -2
  122. package/dist/local-socket-server.js.map +1 -1
  123. package/dist/message-rendering.d.ts +1 -0
  124. package/dist/message-rendering.d.ts.map +1 -1
  125. package/dist/message-rendering.js +1 -0
  126. package/dist/message-rendering.js.map +1 -1
  127. package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts +50 -2
  128. package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts.map +1 -1
  129. package/dist/notification/__tests__/subscribe-signatures.types-check.js +22 -48
  130. package/dist/notification/__tests__/subscribe-signatures.types-check.js.map +1 -1
  131. package/dist/notification/errors.d.ts +4 -2
  132. package/dist/notification/errors.d.ts.map +1 -1
  133. package/dist/notification/errors.js +3 -1
  134. package/dist/notification/errors.js.map +1 -1
  135. package/dist/notification/index.d.ts +1 -0
  136. package/dist/notification/index.d.ts.map +1 -1
  137. package/dist/notification/index.js +1 -0
  138. package/dist/notification/index.js.map +1 -1
  139. package/dist/notification/stream.d.ts +16 -9
  140. package/dist/notification/stream.d.ts.map +1 -1
  141. package/dist/notification/stream.js +5 -38
  142. package/dist/notification/stream.js.map +1 -1
  143. package/dist/pagination.d.ts +13 -16
  144. package/dist/pagination.d.ts.map +1 -1
  145. package/dist/pagination.js +9 -1
  146. package/dist/pagination.js.map +1 -1
  147. package/dist/profile.d.ts +21 -9
  148. package/dist/profile.d.ts.map +1 -1
  149. package/dist/profile.js +30 -16
  150. package/dist/profile.js.map +1 -1
  151. package/dist/refs.d.ts +9 -1
  152. package/dist/refs.d.ts.map +1 -1
  153. package/dist/refs.js +9 -1
  154. package/dist/refs.js.map +1 -1
  155. package/dist/service-archive-purge.d.ts +18 -0
  156. package/dist/service-archive-purge.d.ts.map +1 -1
  157. package/dist/service-archive-purge.js +18 -0
  158. package/dist/service-archive-purge.js.map +1 -1
  159. package/dist/service-event-trace.d.ts +15 -0
  160. package/dist/service-event-trace.d.ts.map +1 -0
  161. package/dist/service-event-trace.js +35 -0
  162. package/dist/service-event-trace.js.map +1 -0
  163. package/dist/service-helpers.d.ts +35 -6
  164. package/dist/service-helpers.d.ts.map +1 -1
  165. package/dist/service-helpers.js +38 -8
  166. package/dist/service-helpers.js.map +1 -1
  167. package/dist/service-local-daemon.d.ts +12 -2
  168. package/dist/service-local-daemon.d.ts.map +1 -1
  169. package/dist/service-local-daemon.js +38 -25
  170. package/dist/service-local-daemon.js.map +1 -1
  171. package/dist/service.d.ts +62 -23
  172. package/dist/service.d.ts.map +1 -1
  173. package/dist/service.js +138 -89
  174. package/dist/service.js.map +1 -1
  175. package/dist/test-utils/channel-service-fixture.d.ts +8 -1
  176. package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
  177. package/dist/test-utils/channel-service-fixture.js +31 -21
  178. package/dist/test-utils/channel-service-fixture.js.map +1 -1
  179. package/dist/test-utils/fake-service.d.ts +20 -7
  180. package/dist/test-utils/fake-service.d.ts.map +1 -1
  181. package/dist/test-utils/fake-service.js +20 -5
  182. package/dist/test-utils/fake-service.js.map +1 -1
  183. package/dist/test-utils/harness.d.ts +8 -4
  184. package/dist/test-utils/harness.d.ts.map +1 -1
  185. package/dist/test-utils/harness.js +3 -0
  186. package/dist/test-utils/harness.js.map +1 -1
  187. package/dist/test-utils/ids.d.ts +25 -0
  188. package/dist/test-utils/ids.d.ts.map +1 -1
  189. package/dist/test-utils/ids.js +27 -1
  190. package/dist/test-utils/ids.js.map +1 -1
  191. package/dist/test-utils/index.d.ts +7 -1
  192. package/dist/test-utils/index.d.ts.map +1 -1
  193. package/dist/test-utils/index.js +7 -1
  194. package/dist/test-utils/index.js.map +1 -1
  195. package/dist/test-utils/standalone-provisioning.d.ts +5 -0
  196. package/dist/test-utils/standalone-provisioning.d.ts.map +1 -1
  197. package/dist/test-utils/standalone-provisioning.js +3 -0
  198. package/dist/test-utils/standalone-provisioning.js.map +1 -1
  199. package/dist/tsconfig.tsbuildinfo +1 -1
  200. package/package.json +6 -6
package/dist/service.js CHANGED
@@ -1,26 +1,22 @@
1
- import { FileSystem, Path } from "@effect/platform";
2
- import { NodeContext } from "@effect/platform-node";
3
- import { AgentId as AgentIdSchema, AgentNotFoundError, AgentsList, } from "@moltzap/protocol/identity";
4
- import { DispatchRequest, DispatchRelease, DispatchLeaseConsumed, DispatchLeaseExpired, } from "@moltzap/protocol/message/dispatch";
5
- import { ConversationCreatedNotificationDefinition, ConversationArchivedNotificationDefinition, ConversationUnarchivedNotificationDefinition, ConversationList, } from "@moltzap/protocol/conversation";
6
- import { DEFAULT_APP_ID, TaskRequest } from "@moltzap/protocol/task";
7
- import { ConversationArchivedError, } from "@moltzap/protocol/conversation";
8
- import { MessageReceivedNotificationDefinition, MessagesList, MessagesSend, } from "@moltzap/protocol/message";
9
- import { NotConnectedError, RpcTimeoutError, isNotificationDeliveryFor, } from "@moltzap/protocol/rpc";
10
- import { AgentCallableGroup } from "@moltzap/protocol/socket/catalog";
1
+ import { agentId as AgentIdSchema, AgentNotFoundError, agentsList, } from "@moltzap/protocol/identity";
2
+ import { dispatchRequest, dispatchRelease, dispatchLeaseConsumed, dispatchLeaseExpired, } from "@moltzap/protocol/message/dispatch";
3
+ import { conversationCreatedNotificationDefinition, conversationArchivedNotificationDefinition, conversationUnarchivedNotificationDefinition, conversationList, ConversationArchivedError, } from "@moltzap/protocol/conversation";
4
+ import { DEFAULT_APP_ID, taskRequest, } from "@moltzap/protocol/task";
5
+ import { messageReceivedNotificationDefinition, messagesList, messagesSend, } from "@moltzap/protocol/message";
6
+ import { NotConnectedError, isNotificationDeliveryFor, } from "@moltzap/protocol/rpc";
11
7
  import { BoundedMap } from "@moltzap/protocol/bounded-map";
12
- import { Config, ConfigProvider, Effect, Exit, HashMap, Option, Ref, Schema, Scope, Stream, } from "effect";
8
+ import { Effect, Exit, HashMap, Option, Ref, Schema, Scope, Stream, } from "effect";
13
9
  import { MoltZapAgentClient } from "./agent-client.js";
14
10
  import { loadServiceConfig, } from "./config.js";
15
11
  import { getOr, snapshot } from "./refs.js";
16
12
  import { getMoltZapAgentServiceSocketPath, getMoltZapServiceSocketPath, } from "./local-paths.js";
17
- import {} from "./local-daemon-rpc.js";
18
13
  import { makeLocalDaemonHandlers } from "./service-local-daemon.js";
19
14
  import { startLocalSocketServer, stopLocalSocketServer, } from "./local-socket-server.js";
20
15
  import { buildContextEntries, makeContextCandidate, newMessagesForConversation, notificationTraceRecord, } from "./service-helpers.js";
21
16
  import { renderPart } from "./message-rendering.js";
22
17
  import { formatHistoryMessage, lastReadIdsForSession, } from "./local-history.js";
23
18
  import { purgeAgentCacheEntries, purgeLastNotified, purgeLastRead, } from "./service-archive-purge.js";
19
+ import { appendClientEventTrace } from "./service-event-trace.js";
24
20
  const CROSS_CONTEXT_TEXT_LIMIT = 120;
25
21
  const DEFAULT_MAX_CONTEXT_CONVERSATIONS = 5;
26
22
  const DEFAULT_MAX_MESSAGES_PER_CONVERSATION = 3;
@@ -30,25 +26,15 @@ const AGENT_LOOKUP_MAX_PAGES = 20;
30
26
  const REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE = 50;
31
27
  const REUSABLE_CONVERSATION_LOOKUP_MAX_PAGES = 20;
32
28
  const decodeAgentId = Schema.decodeUnknownOption(AgentIdSchema);
33
- const ClientEventLogDir = Config.option(Config.string("MOLTZAP_CLIENT_EVENT_LOG_DIR"));
34
- const getClientEventLogDir = () => Option.getOrUndefined(Effect.runSync(ClientEventLogDir.pipe(Effect.withConfigProvider(ConfigProvider.fromEnv()))));
35
- function appendClientEventTrace(record) {
36
- const dir = getClientEventLogDir();
37
- if (!dir)
38
- return Effect.void;
39
- return Effect.gen(function* () {
40
- const fileSystem = yield* FileSystem.FileSystem;
41
- const path = yield* Path.Path;
42
- const agentId = typeof record["agentId"] === "string" ? record["agentId"] : "unknown";
43
- const safeAgentId = /^[A-Za-z0-9_-]+$/.test(agentId) ? agentId : "unknown";
44
- yield* Effect.zipRight(fileSystem.makeDirectory(dir, { recursive: true }), fileSystem.writeFileString(path.join(dir, `client-events-${safeAgentId}.jsonl`), JSON.stringify(record) + "\n", { flag: "a" }));
45
- }).pipe(Effect.withSpan("appendClientEventTrace"), Effect.provide(NodeContext.layer), Effect.catchAll((err) => Effect.logWarning("moltzap client event trace write failed", err)));
46
- }
47
29
  const agentNotFound = (agentName) => new AgentNotFoundError({
48
30
  message: `Agent not found: ${agentName}`,
49
31
  data: { agentName },
50
32
  });
51
- /** Escape `<`, `>`, `&` so sender content can't escape a `<system-reminder>` block. */
33
+ /**
34
+ * Escape `<`, `>`, `&` so sender content can't escape a `<system-reminder>` block.
35
+ * @param s Value supplied to the operation.
36
+ * @returns The sanitize for system reminder result.
37
+ */
52
38
  export function sanitizeForSystemReminder(s) {
53
39
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
54
40
  }
@@ -56,10 +42,15 @@ export function sanitizeForSystemReminder(s) {
56
42
  * Format CrossConversationEntry[] as a `&lt;system-reminder>` block. Adapters
57
43
  * that inline context into prompt text (nanoclaw) and `MoltZapService.getContext`
58
44
  * share this formatter so sanitization and line shape stay in one place.
45
+ * @param entries Value supplied to the operation.
46
+ * @param opts Value supplied to the operation.
47
+ * @param opts.header Value supplied to the operation.
48
+ * @returns The format cross conversation block result.
59
49
  */
60
50
  function formatCrossConversationBlock(entries, opts) {
61
- if (entries.length === 0)
51
+ if (entries.length === 0) {
62
52
  return null;
53
+ }
63
54
  const lines = entries.map((e) => {
64
55
  const safeSender = sanitizeForSystemReminder(e.senderName);
65
56
  const safeText = sanitizeForSystemReminder(e.text.slice(0, CROSS_CONTEXT_TEXT_LIMIT));
@@ -88,6 +79,8 @@ const DEDUP_WINDOW_PER_CONV = 1000;
88
79
  /**
89
80
  * Invoke every handler with `arg`, isolating throws so one bad handler
90
81
  * doesn't abort the remaining fanout.
82
+ * @param handlers Value supplied to the operation.
83
+ * @param arg Value supplied to the operation.
91
84
  */
92
85
  function fanout(handlers, arg) {
93
86
  for (const h of handlers) {
@@ -109,9 +102,8 @@ function fanout(handlers, arg) {
109
102
  * callers compose failures and cancellation explicitly.
110
103
  */
111
104
  export class MoltZapService {
112
- opts;
113
105
  client = null;
114
- _connected = false;
106
+ connectedValue = false;
115
107
  /**
116
108
  * Service-owned scope. Opened in `connect()`, owns the
117
109
  * `subscribeAll → Stream.runForEach` fan-out fiber. Closed in `close()` so
@@ -137,25 +129,25 @@ export class MoltZapService {
137
129
  message: [],
138
130
  rawNotification: [],
139
131
  disconnect: [],
140
- reconnect: [],
141
132
  conversationArchived: [],
142
133
  conversationUnarchived: [],
143
134
  dispatchRelease: [],
144
135
  dispatchLeaseConsumed: [],
145
136
  dispatchLeaseExpired: [],
146
137
  };
147
- _ownAgentId;
138
+ ownAgentIdValue;
139
+ opts;
148
140
  constructor(opts) {
149
141
  this.opts = opts;
150
142
  // The empty HelloOk carries no identity; `ownAgentId` is the client's
151
143
  // registered/stored id, available before the handshake.
152
- this._ownAgentId = opts.agentId;
144
+ this.ownAgentIdValue = opts.agentId;
153
145
  }
154
146
  static fromConfig(config) {
155
147
  return new MoltZapService(config);
156
148
  }
157
149
  static make(profileName) {
158
- return loadServiceConfig(profileName).pipe(Effect.map(MoltZapService.fromConfig));
150
+ return loadServiceConfig(profileName).pipe(Effect.map((config) => MoltZapService.fromConfig(config)));
159
151
  }
160
152
  static startDaemon(profileName) {
161
153
  return Effect.gen(function* () {
@@ -166,12 +158,15 @@ export class MoltZapService {
166
158
  }).pipe(Effect.withSpan("MoltZapService.startDaemon"));
167
159
  }
168
160
  get connected() {
169
- return this._connected;
161
+ return this.connectedValue;
170
162
  }
171
163
  get ownAgentId() {
172
- return this._ownAgentId;
164
+ return this.ownAgentIdValue;
173
165
  }
174
- /** Effect-native: compose via `yield*` or bridge at the edge via `Effect.runPromise`. */
166
+ /**
167
+ * Effect-native: compose via `yield*` or bridge at the edge via `Effect.runPromise`.
168
+ * @returns The client result.
169
+ */
175
170
  connect() {
176
171
  return Effect.gen(this, function* () {
177
172
  const client = new MoltZapAgentClient({
@@ -181,13 +176,9 @@ export class MoltZapService {
181
176
  // kept explicit so a future disconnect-handler chain can plumb
182
177
  // code/reason through.
183
178
  onDisconnect: () => {
184
- this._connected = false;
179
+ this.connectedValue = false;
185
180
  fanout(this.handlers.disconnect, undefined);
186
181
  },
187
- onReconnect: (helloOk) => {
188
- this._connected = true;
189
- fanout(this.handlers.reconnect, helloOk);
190
- },
191
182
  });
192
183
  this.client = client;
193
184
  // `subscribeAll().pipe(Stream.runForEach, …)` is forked into a
@@ -202,10 +193,12 @@ export class MoltZapService {
202
193
  // before the fiber exits.
203
194
  const serviceScope = yield* Scope.make();
204
195
  this.serviceScope = serviceScope;
205
- const fanoutEffect = client.subscribeAll().pipe(Stream.runForEach((notification) => Effect.sync(() => this.handleNotification(notification))), Effect.catchAll((cause) => Effect.logWarning("MoltZapService notification fan-out terminated", cause)), Effect.asVoid);
196
+ const fanoutEffect = client.subscribeAll().pipe(Stream.runForEach((notification) => Effect.sync(() => {
197
+ this.handleNotification(notification);
198
+ })), Effect.catchAll((cause) => Effect.logWarning("MoltZapService notification fan-out terminated", cause)), Effect.asVoid);
206
199
  yield* Effect.forkIn(fanoutEffect, serviceScope);
207
200
  const helloOk = yield* client.connect();
208
- this._connected = true;
201
+ this.connectedValue = true;
209
202
  return helloOk;
210
203
  });
211
204
  }
@@ -216,7 +209,7 @@ export class MoltZapService {
216
209
  * shutdown.
217
210
  */
218
211
  close() {
219
- this._connected = false;
212
+ this.connectedValue = false;
220
213
  Effect.runFork(this.stopSocketServer());
221
214
  const scopeToClose = this.serviceScope;
222
215
  const clientToClose = this.client;
@@ -237,10 +230,9 @@ export class MoltZapService {
237
230
  ]));
238
231
  this.archivedConversationIds.clear();
239
232
  this.seenMessageIds.clear();
240
- // Handlers are preserved across close()/connect() cycles. MoltZapChannelCore
241
- // subscribes once in its constructor; clearing handlers here would silently
242
- // drop inbound/reconnect dispatch on any subsequent reconnect of the same
243
- // service instance.
233
+ // Handlers are preserved across explicit close()/connect() cycles.
234
+ // MoltZapChannelCore subscribes once in its constructor; clearing handlers
235
+ // here would silently drop inbound dispatch after the next connect.
244
236
  }
245
237
  // --- Socket Server ---
246
238
  socketServerScope = null;
@@ -252,11 +244,16 @@ export class MoltZapService {
252
244
  * compromised or malicious server returns an id containing `..` or a
253
245
  * path separator, a naive `path.join(... , agentId)` escapes `~/.moltzap`.
254
246
  * Reject anything that isn't a safe identifier.
247
+ * @param id Value supplied to the operation.
248
+ * @returns The id result.
255
249
  */
256
250
  static safeAgentIdSegment(id) {
257
251
  return /^[A-Za-z0-9_-]+$/.test(id) ? id : "default";
258
252
  }
259
- /** Per-instance socket path based on connected agentId. */
253
+ /**
254
+ * Per-instance socket path based on connected agentId.
255
+ * @returns The id result.
256
+ */
260
257
  get socketPath() {
261
258
  const id = MoltZapService.safeAgentIdSegment(this.ownAgentId ?? "default");
262
259
  return getMoltZapAgentServiceSocketPath(id);
@@ -295,8 +292,8 @@ export class MoltZapService {
295
292
  }
296
293
  localDaemonHandlers() {
297
294
  return makeLocalDaemonHandlers({
298
- ownAgentId: this._ownAgentId,
299
- connected: this._connected,
295
+ ownAgentId: this.ownAgentIdValue,
296
+ connected: this.connectedValue,
300
297
  conversationCount: () => this.getConversations().length,
301
298
  call: this.call.bind(this),
302
299
  handleHistoryRequest: (request) => this.handleHistoryRequest(request),
@@ -304,7 +301,7 @@ export class MoltZapService {
304
301
  }
305
302
  handleHistoryRequest(request) {
306
303
  return Effect.gen(this, function* () {
307
- const result = yield* this.call(MessagesList.name, {
304
+ const result = yield* this.call(messagesList.name, {
308
305
  taskId: request.taskId,
309
306
  conversationId: request.conversationId,
310
307
  limit: request.limit,
@@ -344,15 +341,16 @@ export class MoltZapService {
344
341
  const unknownAgentIds = [
345
342
  ...new Set(messages.map((message) => message.senderId)),
346
343
  ].filter((id) => !HashMap.has(knownNames, id));
347
- if (unknownAgentIds.length === 0)
344
+ if (unknownAgentIds.length === 0) {
348
345
  return;
346
+ }
349
347
  yield* this.cacheVisibleAgentNamesForIds(new Set(unknownAgentIds)).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void));
350
348
  });
351
349
  }
352
350
  fetchHistoryConversationMeta(convId) {
353
351
  // The client filters `ConversationList` output for the matching
354
352
  // conversation id (there is no per-conversation get RPC).
355
- return this.call(ConversationList.name, {}).pipe(Effect.map((result) => {
353
+ return this.call(conversationList.name, {}).pipe(Effect.map((result) => {
356
354
  const hit = result.items.find((item) => item.conversation.id === convId);
357
355
  return hit?.conversation;
358
356
  }), Effect.catchAll(() => Effect.succeed(undefined)));
@@ -364,9 +362,11 @@ export class MoltZapService {
364
362
  const { conversationId, sessionKey } = request;
365
363
  return Ref.update(this.lastReadRef, (outer) => {
366
364
  const perSession = getOr(outer, sessionKey, () => HashMap.empty());
367
- const existing = getOr(perSession, conversationId, () => new Set());
368
- if (messages.every((message) => existing.has(message.id)))
365
+ const existing = getOr(perSession, conversationId, () =>
366
+ /* Safe because the surrounding invariant establishes this asserted shape. */ new Set());
367
+ if (messages.every((message) => existing.has(message.id))) {
369
368
  return outer;
369
+ }
370
370
  const nextSet = new Set(existing);
371
371
  for (const message of messages) {
372
372
  nextSet.add(message.id);
@@ -398,15 +398,19 @@ export class MoltZapService {
398
398
  * when the RPC errors or the server has no record. The error path logs
399
399
  * so ops can see repeated lookup failures; the empty-response path is
400
400
  * silent (a cold agent is an expected transient state).
401
+ * @param agentId Identifier of the agent targeted by the operation.
402
+ * @returns The decoded d agent id.
401
403
  */
402
404
  resolveAgentName(agentId) {
403
405
  return Effect.gen(this, function* () {
404
406
  const decodedAgentId = Option.getOrUndefined(decodeAgentId(agentId));
405
- if (decodedAgentId === undefined)
407
+ if (decodedAgentId === undefined) {
406
408
  return agentId;
409
+ }
407
410
  const cached = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
408
- if (cached !== undefined)
411
+ if (cached !== undefined) {
409
412
  return cached;
413
+ }
410
414
  return yield* this.cacheVisibleAgentNamesForIds(new Set([decodedAgentId])).pipe(Effect.map(() => {
411
415
  const resolved = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
412
416
  return resolved ?? agentId;
@@ -443,12 +447,19 @@ export class MoltZapService {
443
447
  * params frame. The server marks the lease consumed, blocking the
444
448
  * app authorization timeout sweep. `MoltZapChannelCore.sendReply` forwards
445
449
  * `leaseIdInFlight` automatically when the caller omits it.
450
+ * @param taskId Value supplied to the operation.
451
+ * @param conversationId Value supplied to the operation.
452
+ * @param text Text to process.
453
+ * @param opts Value supplied to the operation.
454
+ * @param opts.replyTo Value supplied to the operation.
455
+ * @param opts.dispatchLeaseId Value supplied to the operation.
456
+ * @returns The send result.
446
457
  */
447
458
  send(taskId, conversationId, text, opts) {
448
459
  if (this.isConversationArchived(conversationId)) {
449
460
  return Effect.fail(new ConversationArchivedError({ message: "Conversation is archived" }));
450
461
  }
451
- return Effect.asVoid(this.call(MessagesSend.name, {
462
+ return Effect.asVoid(this.call(messagesSend.name, {
452
463
  taskId,
453
464
  conversationId,
454
465
  parts: [{ type: "text", text }],
@@ -462,9 +473,11 @@ export class MoltZapService {
462
473
  * Issue `agent/dispatch/request`. The server returns the ack
463
474
  * `{leaseId, dispatchId}` immediately; the recipient observes the
464
475
  * verdict asynchronously via the `dispatchRelease` event.
476
+ * @param params Request payload to process.
477
+ * @returns The cache result.
465
478
  */
466
479
  requestDispatch(params) {
467
- return this.call(DispatchRequest.name, params);
480
+ return this.call(dispatchRequest.name, params);
468
481
  }
469
482
  sendToAgent(agentName, text, opts) {
470
483
  return Effect.gen(this, function* () {
@@ -475,7 +488,7 @@ export class MoltZapService {
475
488
  if (!agent) {
476
489
  return yield* Effect.fail(agentNotFound(agentName));
477
490
  }
478
- const createResult = yield* this.call(TaskRequest.name, {
491
+ const createResult = yield* this.call(taskRequest.name, {
479
492
  appId: DEFAULT_APP_ID,
480
493
  invitedAgentIds: [agent.id],
481
494
  initialConversation: { participants: [agent.id] },
@@ -501,23 +514,27 @@ export class MoltZapService {
501
514
  const params = {
502
515
  limit: REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE,
503
516
  };
504
- if (cursor !== undefined)
517
+ if (cursor !== undefined) {
505
518
  params.cursor = cursor;
506
- const result = yield* this.call(ConversationList.name, params);
519
+ }
520
+ const result = yield* this.call(conversationList.name, params);
507
521
  const hit = result.items.find((item) => item.taskId === taskId &&
508
522
  item.conversation.archivedAt === undefined);
509
- if (hit !== undefined)
523
+ if (hit !== undefined) {
510
524
  return hit.conversation.id;
511
- if (result.nextCursor === undefined)
525
+ }
526
+ if (result.nextCursor === undefined) {
512
527
  break;
528
+ }
513
529
  cursor = result.nextCursor;
514
530
  }
515
531
  return yield* Effect.fail(agentNotFound(agentName));
516
532
  });
517
533
  }
518
534
  cacheAgentNames(agents) {
519
- if (agents.length === 0)
535
+ if (agents.length === 0) {
520
536
  return Effect.void;
537
+ }
521
538
  return Ref.update(this.agentNamesRef, (names) => {
522
539
  let next = names;
523
540
  for (const agent of agents) {
@@ -537,12 +554,14 @@ export class MoltZapService {
537
554
  let cursor = undefined;
538
555
  for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
539
556
  const params = this.agentListParams(cursor);
540
- const result = yield* this.call(AgentsList.name, params);
557
+ const result = yield* this.call(agentsList.name, params);
541
558
  yield* this.cacheAgentNames(result.agents);
542
- for (const agent of result.agents)
559
+ for (const agent of result.agents) {
543
560
  missing.delete(agent.id);
544
- if (missing.size === 0 || result.nextCursor === undefined)
561
+ }
562
+ if (missing.size === 0 || result.nextCursor === undefined) {
545
563
  return;
564
+ }
546
565
  cursor = result.nextCursor;
547
566
  }
548
567
  });
@@ -552,11 +571,12 @@ export class MoltZapService {
552
571
  let cursor = undefined;
553
572
  for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
554
573
  const params = this.agentListParams(cursor);
555
- const result = yield* this.call(AgentsList.name, params);
574
+ const result = yield* this.call(agentsList.name, params);
556
575
  yield* this.cacheAgentNames(result.agents);
557
576
  const hit = result.agents.find((agent) => agent.name === agentName);
558
- if (hit !== undefined || result.nextCursor === undefined)
577
+ if (hit !== undefined || result.nextCursor === undefined) {
559
578
  return hit;
579
+ }
560
580
  cursor = result.nextCursor;
561
581
  }
562
582
  return undefined;
@@ -567,12 +587,16 @@ export class MoltZapService {
567
587
  * Generate a system reminder with updates from other conversations.
568
588
  * Each conversation has its own view of what's "new" — markers are tracked
569
589
  * per viewing conversation and advanced after notification.
590
+ * @param currentConvId Value supplied to the operation.
591
+ * @param opts Value supplied to the operation.
592
+ * @returns The context options result.
570
593
  */
571
594
  getContext(currentConvId, opts) {
572
595
  const contextOptions = opts ?? {};
573
596
  const { entries, commit } = this.peekContextEntries(currentConvId, contextOptions);
574
- if (entries.length === 0)
597
+ if (entries.length === 0) {
575
598
  return null;
599
+ }
576
600
  commit();
577
601
  return formatCrossConversationBlock(entries, {
578
602
  header: `Recent updates (you are in conv:${currentConvId}):`,
@@ -583,6 +607,11 @@ export class MoltZapService {
583
607
  * Call `commit()` on the result to mark the returned messages as seen so
584
608
  * subsequent peeks return only what's new. A caller that reads without
585
609
  * committing can re-peek idempotently.
610
+ * @param currentConvId Value supplied to the operation.
611
+ * @param opts Value supplied to the operation.
612
+ * @param opts.maxConversations Value supplied to the operation.
613
+ * @param opts.maxMessagesPerConv Value supplied to the operation.
614
+ * @returns The max convs result.
586
615
  */
587
616
  peekContextEntries(currentConvId, opts) {
588
617
  const maxConvs = opts?.maxConversations ?? DEFAULT_MAX_CONTEXT_CONVERSATIONS;
@@ -592,13 +621,17 @@ export class MoltZapService {
592
621
  const { entries, pendingAdvances } = buildContextEntries(candidates.slice(0, maxConvs), state, maxMsgsPerConv);
593
622
  return {
594
623
  entries,
595
- commit: () => this.advanceLastNotified(currentConvId, pendingAdvances),
624
+ commit: () => {
625
+ this.advanceLastNotified(currentConvId, pendingAdvances);
626
+ },
596
627
  };
597
628
  }
598
629
  /**
599
630
  * Return all new messages from all other conversations as full transcripts,
600
631
  * sorted chronologically. Uses the same lastNotified markers as
601
632
  * peekContextEntries. Call commit() to advance markers.
633
+ * @param currentConvId Value supplied to the operation.
634
+ * @returns The all messages result.
602
635
  */
603
636
  peekFullMessages(currentConvId) {
604
637
  const { messagesMap, conversationsMap, agentNamesMap, viewMarkers } = this.readCrossConvState(currentConvId);
@@ -616,12 +649,17 @@ export class MoltZapService {
616
649
  timestamp: m.createdAt,
617
650
  });
618
651
  }
619
- pendingAdvances.push([convId, newMsgs[newMsgs.length - 1].id]);
652
+ pendingAdvances.push([
653
+ convId,
654
+ /* Safe because the surrounding invariant establishes this asserted shape. */ newMsgs[newMsgs.length - 1].id,
655
+ ]);
620
656
  }
621
657
  allMessages.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
622
658
  return {
623
659
  messages: allMessages,
624
- commit: () => this.advanceLastNotified(currentConvId, pendingAdvances),
660
+ commit: () => {
661
+ this.advanceLastNotified(currentConvId, pendingAdvances);
662
+ },
625
663
  };
626
664
  }
627
665
  readCrossConvState(currentConvId) {
@@ -644,13 +682,15 @@ export class MoltZapService {
644
682
  *iterNewMessagesByConv(messagesMap, viewMarkers, currentConvId) {
645
683
  for (const [convId, msgs] of messagesMap) {
646
684
  const newMsgs = newMessagesForConversation(convId, msgs, viewMarkers, currentConvId);
647
- if (newMsgs.length > 0)
685
+ if (newMsgs.length > 0) {
648
686
  yield [convId, newMsgs];
687
+ }
649
688
  }
650
689
  }
651
690
  advanceLastNotified(currentConvId, pendingAdvances) {
652
- if (pendingAdvances.length === 0)
691
+ if (pendingAdvances.length === 0) {
653
692
  return;
693
+ }
654
694
  Effect.runSync(Ref.update(this.lastNotifiedRef, (outer) => {
655
695
  let markers = getOr(outer, currentConvId, () => HashMap.empty());
656
696
  for (const [convId, msgId] of pendingAdvances) {
@@ -668,6 +708,10 @@ export class MoltZapService {
668
708
  * Outbound RPC, typed per method — delegates to the agent client's typed
669
709
  * `call`. `call("agent/identity/agents/list", payload)` recovers the result and that
670
710
  * method's tagged-error union; an app-only method does not typecheck.
711
+ * @param tag Value supplied to the operation.
712
+ * @param payload Value supplied to the operation.
713
+ * @param opts Value supplied to the operation.
714
+ * @returns The client result.
671
715
  */
672
716
  call(tag, payload, opts) {
673
717
  return Effect.suspend(() => {
@@ -694,47 +738,49 @@ export class MoltZapService {
694
738
  this.dispatchTypedNotification(notification);
695
739
  }
696
740
  recordNotificationTrace(notification) {
697
- Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this._ownAgentId)));
741
+ Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this.ownAgentIdValue)));
698
742
  }
699
743
  dispatchTypedNotification(notification) {
700
- if (this.dispatchMessageNotification(notification))
744
+ if (this.dispatchMessageNotification(notification)) {
701
745
  return;
702
- if (this.dispatchConversationNotification(notification))
746
+ }
747
+ if (this.dispatchConversationNotification(notification)) {
703
748
  return;
749
+ }
704
750
  this.dispatchAppNotification(notification);
705
751
  }
706
752
  dispatchMessageNotification(notification) {
707
- if (isNotificationDeliveryFor(notification, MessageReceivedNotificationDefinition)) {
753
+ if (isNotificationDeliveryFor(notification, messageReceivedNotificationDefinition)) {
708
754
  this.handleMessageReceivedNotification(notification.params);
709
755
  return true;
710
756
  }
711
757
  return false;
712
758
  }
713
759
  dispatchConversationNotification(notification) {
714
- if (isNotificationDeliveryFor(notification, ConversationCreatedNotificationDefinition)) {
760
+ if (isNotificationDeliveryFor(notification, conversationCreatedNotificationDefinition)) {
715
761
  this.handleConversationCreatedNotification(notification.params);
716
762
  return true;
717
763
  }
718
- if (isNotificationDeliveryFor(notification, ConversationArchivedNotificationDefinition)) {
764
+ if (isNotificationDeliveryFor(notification, conversationArchivedNotificationDefinition)) {
719
765
  this.handleConversationArchivedNotification(notification.params);
720
766
  return true;
721
767
  }
722
- if (isNotificationDeliveryFor(notification, ConversationUnarchivedNotificationDefinition)) {
768
+ if (isNotificationDeliveryFor(notification, conversationUnarchivedNotificationDefinition)) {
723
769
  this.handleConversationUnarchivedNotification(notification.params);
724
770
  return true;
725
771
  }
726
772
  return false;
727
773
  }
728
774
  dispatchAppNotification(notification) {
729
- if (isNotificationDeliveryFor(notification, DispatchRelease)) {
775
+ if (isNotificationDeliveryFor(notification, dispatchRelease)) {
730
776
  fanout(this.handlers.dispatchRelease, notification.params);
731
777
  return;
732
778
  }
733
- if (isNotificationDeliveryFor(notification, DispatchLeaseConsumed)) {
779
+ if (isNotificationDeliveryFor(notification, dispatchLeaseConsumed)) {
734
780
  fanout(this.handlers.dispatchLeaseConsumed, notification.params);
735
781
  return;
736
782
  }
737
- if (isNotificationDeliveryFor(notification, DispatchLeaseExpired)) {
783
+ if (isNotificationDeliveryFor(notification, dispatchLeaseExpired)) {
738
784
  fanout(this.handlers.dispatchLeaseExpired, notification.params);
739
785
  }
740
786
  }
@@ -749,6 +795,9 @@ export class MoltZapService {
749
795
  * replay, dual subscription) is suppressed to one
750
796
  * `on("message", ...)` event. `agent/message/list` returns raw history
751
797
  * unfiltered; consumers that combine both feeds dedup themselves.
798
+ * @param convId Value supplied to the operation.
799
+ * @param msgId Value supplied to the operation.
800
+ * @returns The dedup window result.
752
801
  */
753
802
  recordMessageIdIfNew(convId, msgId) {
754
803
  let dedupWindow = this.seenMessageIds.get(convId);
@@ -774,7 +823,7 @@ export class MoltZapService {
774
823
  // Name resolution is driven lazily by channel-core's serialized consumer
775
824
  // via resolveAgentName(), which populates agentNamesRef on first miss and
776
825
  // hits the cache on every subsequent message.
777
- if (msg.senderId !== this._ownAgentId) {
826
+ if (msg.senderId !== this.ownAgentIdValue) {
778
827
  fanout(this.handlers.message, {
779
828
  taskId: notification.taskId,
780
829
  message: msg,