@moltzap/client 2026.729.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 -19
  46. package/dist/channel-core.d.ts.map +1 -1
  47. package/dist/channel-core.js +45 -30
  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 +9 -3
  96. package/dist/config.d.ts.map +1 -1
  97. package/dist/config.js +8 -3
  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 +116 -93
  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 +2 -0
  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 +11 -4
  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 -22
  172. package/dist/service.d.ts.map +1 -1
  173. package/dist/service.js +135 -80
  174. package/dist/service.js.map +1 -1
  175. package/dist/test-utils/channel-service-fixture.d.ts +8 -0
  176. package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
  177. package/dist/test-utils/channel-service-fixture.js +31 -13
  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 +18 -4
  182. package/dist/test-utils/fake-service.js.map +1 -1
  183. package/dist/test-utils/harness.d.ts +5 -1
  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
@@ -143,18 +135,19 @@ export class MoltZapService {
143
135
  dispatchLeaseConsumed: [],
144
136
  dispatchLeaseExpired: [],
145
137
  };
146
- _ownAgentId;
138
+ ownAgentIdValue;
139
+ opts;
147
140
  constructor(opts) {
148
141
  this.opts = opts;
149
142
  // The empty HelloOk carries no identity; `ownAgentId` is the client's
150
143
  // registered/stored id, available before the handshake.
151
- this._ownAgentId = opts.agentId;
144
+ this.ownAgentIdValue = opts.agentId;
152
145
  }
153
146
  static fromConfig(config) {
154
147
  return new MoltZapService(config);
155
148
  }
156
149
  static make(profileName) {
157
- return loadServiceConfig(profileName).pipe(Effect.map(MoltZapService.fromConfig));
150
+ return loadServiceConfig(profileName).pipe(Effect.map((config) => MoltZapService.fromConfig(config)));
158
151
  }
159
152
  static startDaemon(profileName) {
160
153
  return Effect.gen(function* () {
@@ -165,12 +158,15 @@ export class MoltZapService {
165
158
  }).pipe(Effect.withSpan("MoltZapService.startDaemon"));
166
159
  }
167
160
  get connected() {
168
- return this._connected;
161
+ return this.connectedValue;
169
162
  }
170
163
  get ownAgentId() {
171
- return this._ownAgentId;
164
+ return this.ownAgentIdValue;
172
165
  }
173
- /** 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
+ */
174
170
  connect() {
175
171
  return Effect.gen(this, function* () {
176
172
  const client = new MoltZapAgentClient({
@@ -180,7 +176,7 @@ export class MoltZapService {
180
176
  // kept explicit so a future disconnect-handler chain can plumb
181
177
  // code/reason through.
182
178
  onDisconnect: () => {
183
- this._connected = false;
179
+ this.connectedValue = false;
184
180
  fanout(this.handlers.disconnect, undefined);
185
181
  },
186
182
  });
@@ -197,10 +193,12 @@ export class MoltZapService {
197
193
  // before the fiber exits.
198
194
  const serviceScope = yield* Scope.make();
199
195
  this.serviceScope = serviceScope;
200
- 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);
201
199
  yield* Effect.forkIn(fanoutEffect, serviceScope);
202
200
  const helloOk = yield* client.connect();
203
- this._connected = true;
201
+ this.connectedValue = true;
204
202
  return helloOk;
205
203
  });
206
204
  }
@@ -211,7 +209,7 @@ export class MoltZapService {
211
209
  * shutdown.
212
210
  */
213
211
  close() {
214
- this._connected = false;
212
+ this.connectedValue = false;
215
213
  Effect.runFork(this.stopSocketServer());
216
214
  const scopeToClose = this.serviceScope;
217
215
  const clientToClose = this.client;
@@ -246,11 +244,16 @@ export class MoltZapService {
246
244
  * compromised or malicious server returns an id containing `..` or a
247
245
  * path separator, a naive `path.join(... , agentId)` escapes `~/.moltzap`.
248
246
  * Reject anything that isn't a safe identifier.
247
+ * @param id Value supplied to the operation.
248
+ * @returns The id result.
249
249
  */
250
250
  static safeAgentIdSegment(id) {
251
251
  return /^[A-Za-z0-9_-]+$/.test(id) ? id : "default";
252
252
  }
253
- /** Per-instance socket path based on connected agentId. */
253
+ /**
254
+ * Per-instance socket path based on connected agentId.
255
+ * @returns The id result.
256
+ */
254
257
  get socketPath() {
255
258
  const id = MoltZapService.safeAgentIdSegment(this.ownAgentId ?? "default");
256
259
  return getMoltZapAgentServiceSocketPath(id);
@@ -289,8 +292,8 @@ export class MoltZapService {
289
292
  }
290
293
  localDaemonHandlers() {
291
294
  return makeLocalDaemonHandlers({
292
- ownAgentId: this._ownAgentId,
293
- connected: this._connected,
295
+ ownAgentId: this.ownAgentIdValue,
296
+ connected: this.connectedValue,
294
297
  conversationCount: () => this.getConversations().length,
295
298
  call: this.call.bind(this),
296
299
  handleHistoryRequest: (request) => this.handleHistoryRequest(request),
@@ -298,7 +301,7 @@ export class MoltZapService {
298
301
  }
299
302
  handleHistoryRequest(request) {
300
303
  return Effect.gen(this, function* () {
301
- const result = yield* this.call(MessagesList.name, {
304
+ const result = yield* this.call(messagesList.name, {
302
305
  taskId: request.taskId,
303
306
  conversationId: request.conversationId,
304
307
  limit: request.limit,
@@ -338,15 +341,16 @@ export class MoltZapService {
338
341
  const unknownAgentIds = [
339
342
  ...new Set(messages.map((message) => message.senderId)),
340
343
  ].filter((id) => !HashMap.has(knownNames, id));
341
- if (unknownAgentIds.length === 0)
344
+ if (unknownAgentIds.length === 0) {
342
345
  return;
346
+ }
343
347
  yield* this.cacheVisibleAgentNamesForIds(new Set(unknownAgentIds)).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void));
344
348
  });
345
349
  }
346
350
  fetchHistoryConversationMeta(convId) {
347
351
  // The client filters `ConversationList` output for the matching
348
352
  // conversation id (there is no per-conversation get RPC).
349
- return this.call(ConversationList.name, {}).pipe(Effect.map((result) => {
353
+ return this.call(conversationList.name, {}).pipe(Effect.map((result) => {
350
354
  const hit = result.items.find((item) => item.conversation.id === convId);
351
355
  return hit?.conversation;
352
356
  }), Effect.catchAll(() => Effect.succeed(undefined)));
@@ -358,9 +362,11 @@ export class MoltZapService {
358
362
  const { conversationId, sessionKey } = request;
359
363
  return Ref.update(this.lastReadRef, (outer) => {
360
364
  const perSession = getOr(outer, sessionKey, () => HashMap.empty());
361
- const existing = getOr(perSession, conversationId, () => new Set());
362
- 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))) {
363
368
  return outer;
369
+ }
364
370
  const nextSet = new Set(existing);
365
371
  for (const message of messages) {
366
372
  nextSet.add(message.id);
@@ -392,15 +398,19 @@ export class MoltZapService {
392
398
  * when the RPC errors or the server has no record. The error path logs
393
399
  * so ops can see repeated lookup failures; the empty-response path is
394
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.
395
403
  */
396
404
  resolveAgentName(agentId) {
397
405
  return Effect.gen(this, function* () {
398
406
  const decodedAgentId = Option.getOrUndefined(decodeAgentId(agentId));
399
- if (decodedAgentId === undefined)
407
+ if (decodedAgentId === undefined) {
400
408
  return agentId;
409
+ }
401
410
  const cached = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
402
- if (cached !== undefined)
411
+ if (cached !== undefined) {
403
412
  return cached;
413
+ }
404
414
  return yield* this.cacheVisibleAgentNamesForIds(new Set([decodedAgentId])).pipe(Effect.map(() => {
405
415
  const resolved = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
406
416
  return resolved ?? agentId;
@@ -437,12 +447,19 @@ export class MoltZapService {
437
447
  * params frame. The server marks the lease consumed, blocking the
438
448
  * app authorization timeout sweep. `MoltZapChannelCore.sendReply` forwards
439
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.
440
457
  */
441
458
  send(taskId, conversationId, text, opts) {
442
459
  if (this.isConversationArchived(conversationId)) {
443
460
  return Effect.fail(new ConversationArchivedError({ message: "Conversation is archived" }));
444
461
  }
445
- return Effect.asVoid(this.call(MessagesSend.name, {
462
+ return Effect.asVoid(this.call(messagesSend.name, {
446
463
  taskId,
447
464
  conversationId,
448
465
  parts: [{ type: "text", text }],
@@ -456,9 +473,11 @@ export class MoltZapService {
456
473
  * Issue `agent/dispatch/request`. The server returns the ack
457
474
  * `{leaseId, dispatchId}` immediately; the recipient observes the
458
475
  * verdict asynchronously via the `dispatchRelease` event.
476
+ * @param params Request payload to process.
477
+ * @returns The cache result.
459
478
  */
460
479
  requestDispatch(params) {
461
- return this.call(DispatchRequest.name, params);
480
+ return this.call(dispatchRequest.name, params);
462
481
  }
463
482
  sendToAgent(agentName, text, opts) {
464
483
  return Effect.gen(this, function* () {
@@ -469,7 +488,7 @@ export class MoltZapService {
469
488
  if (!agent) {
470
489
  return yield* Effect.fail(agentNotFound(agentName));
471
490
  }
472
- const createResult = yield* this.call(TaskRequest.name, {
491
+ const createResult = yield* this.call(taskRequest.name, {
473
492
  appId: DEFAULT_APP_ID,
474
493
  invitedAgentIds: [agent.id],
475
494
  initialConversation: { participants: [agent.id] },
@@ -495,23 +514,27 @@ export class MoltZapService {
495
514
  const params = {
496
515
  limit: REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE,
497
516
  };
498
- if (cursor !== undefined)
517
+ if (cursor !== undefined) {
499
518
  params.cursor = cursor;
500
- const result = yield* this.call(ConversationList.name, params);
519
+ }
520
+ const result = yield* this.call(conversationList.name, params);
501
521
  const hit = result.items.find((item) => item.taskId === taskId &&
502
522
  item.conversation.archivedAt === undefined);
503
- if (hit !== undefined)
523
+ if (hit !== undefined) {
504
524
  return hit.conversation.id;
505
- if (result.nextCursor === undefined)
525
+ }
526
+ if (result.nextCursor === undefined) {
506
527
  break;
528
+ }
507
529
  cursor = result.nextCursor;
508
530
  }
509
531
  return yield* Effect.fail(agentNotFound(agentName));
510
532
  });
511
533
  }
512
534
  cacheAgentNames(agents) {
513
- if (agents.length === 0)
535
+ if (agents.length === 0) {
514
536
  return Effect.void;
537
+ }
515
538
  return Ref.update(this.agentNamesRef, (names) => {
516
539
  let next = names;
517
540
  for (const agent of agents) {
@@ -531,12 +554,14 @@ export class MoltZapService {
531
554
  let cursor = undefined;
532
555
  for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
533
556
  const params = this.agentListParams(cursor);
534
- const result = yield* this.call(AgentsList.name, params);
557
+ const result = yield* this.call(agentsList.name, params);
535
558
  yield* this.cacheAgentNames(result.agents);
536
- for (const agent of result.agents)
559
+ for (const agent of result.agents) {
537
560
  missing.delete(agent.id);
538
- if (missing.size === 0 || result.nextCursor === undefined)
561
+ }
562
+ if (missing.size === 0 || result.nextCursor === undefined) {
539
563
  return;
564
+ }
540
565
  cursor = result.nextCursor;
541
566
  }
542
567
  });
@@ -546,11 +571,12 @@ export class MoltZapService {
546
571
  let cursor = undefined;
547
572
  for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
548
573
  const params = this.agentListParams(cursor);
549
- const result = yield* this.call(AgentsList.name, params);
574
+ const result = yield* this.call(agentsList.name, params);
550
575
  yield* this.cacheAgentNames(result.agents);
551
576
  const hit = result.agents.find((agent) => agent.name === agentName);
552
- if (hit !== undefined || result.nextCursor === undefined)
577
+ if (hit !== undefined || result.nextCursor === undefined) {
553
578
  return hit;
579
+ }
554
580
  cursor = result.nextCursor;
555
581
  }
556
582
  return undefined;
@@ -561,12 +587,16 @@ export class MoltZapService {
561
587
  * Generate a system reminder with updates from other conversations.
562
588
  * Each conversation has its own view of what's "new" — markers are tracked
563
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.
564
593
  */
565
594
  getContext(currentConvId, opts) {
566
595
  const contextOptions = opts ?? {};
567
596
  const { entries, commit } = this.peekContextEntries(currentConvId, contextOptions);
568
- if (entries.length === 0)
597
+ if (entries.length === 0) {
569
598
  return null;
599
+ }
570
600
  commit();
571
601
  return formatCrossConversationBlock(entries, {
572
602
  header: `Recent updates (you are in conv:${currentConvId}):`,
@@ -577,6 +607,11 @@ export class MoltZapService {
577
607
  * Call `commit()` on the result to mark the returned messages as seen so
578
608
  * subsequent peeks return only what's new. A caller that reads without
579
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.
580
615
  */
581
616
  peekContextEntries(currentConvId, opts) {
582
617
  const maxConvs = opts?.maxConversations ?? DEFAULT_MAX_CONTEXT_CONVERSATIONS;
@@ -586,13 +621,17 @@ export class MoltZapService {
586
621
  const { entries, pendingAdvances } = buildContextEntries(candidates.slice(0, maxConvs), state, maxMsgsPerConv);
587
622
  return {
588
623
  entries,
589
- commit: () => this.advanceLastNotified(currentConvId, pendingAdvances),
624
+ commit: () => {
625
+ this.advanceLastNotified(currentConvId, pendingAdvances);
626
+ },
590
627
  };
591
628
  }
592
629
  /**
593
630
  * Return all new messages from all other conversations as full transcripts,
594
631
  * sorted chronologically. Uses the same lastNotified markers as
595
632
  * peekContextEntries. Call commit() to advance markers.
633
+ * @param currentConvId Value supplied to the operation.
634
+ * @returns The all messages result.
596
635
  */
597
636
  peekFullMessages(currentConvId) {
598
637
  const { messagesMap, conversationsMap, agentNamesMap, viewMarkers } = this.readCrossConvState(currentConvId);
@@ -610,12 +649,17 @@ export class MoltZapService {
610
649
  timestamp: m.createdAt,
611
650
  });
612
651
  }
613
- 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
+ ]);
614
656
  }
615
657
  allMessages.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
616
658
  return {
617
659
  messages: allMessages,
618
- commit: () => this.advanceLastNotified(currentConvId, pendingAdvances),
660
+ commit: () => {
661
+ this.advanceLastNotified(currentConvId, pendingAdvances);
662
+ },
619
663
  };
620
664
  }
621
665
  readCrossConvState(currentConvId) {
@@ -638,13 +682,15 @@ export class MoltZapService {
638
682
  *iterNewMessagesByConv(messagesMap, viewMarkers, currentConvId) {
639
683
  for (const [convId, msgs] of messagesMap) {
640
684
  const newMsgs = newMessagesForConversation(convId, msgs, viewMarkers, currentConvId);
641
- if (newMsgs.length > 0)
685
+ if (newMsgs.length > 0) {
642
686
  yield [convId, newMsgs];
687
+ }
643
688
  }
644
689
  }
645
690
  advanceLastNotified(currentConvId, pendingAdvances) {
646
- if (pendingAdvances.length === 0)
691
+ if (pendingAdvances.length === 0) {
647
692
  return;
693
+ }
648
694
  Effect.runSync(Ref.update(this.lastNotifiedRef, (outer) => {
649
695
  let markers = getOr(outer, currentConvId, () => HashMap.empty());
650
696
  for (const [convId, msgId] of pendingAdvances) {
@@ -662,6 +708,10 @@ export class MoltZapService {
662
708
  * Outbound RPC, typed per method — delegates to the agent client's typed
663
709
  * `call`. `call("agent/identity/agents/list", payload)` recovers the result and that
664
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.
665
715
  */
666
716
  call(tag, payload, opts) {
667
717
  return Effect.suspend(() => {
@@ -688,47 +738,49 @@ export class MoltZapService {
688
738
  this.dispatchTypedNotification(notification);
689
739
  }
690
740
  recordNotificationTrace(notification) {
691
- Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this._ownAgentId)));
741
+ Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this.ownAgentIdValue)));
692
742
  }
693
743
  dispatchTypedNotification(notification) {
694
- if (this.dispatchMessageNotification(notification))
744
+ if (this.dispatchMessageNotification(notification)) {
695
745
  return;
696
- if (this.dispatchConversationNotification(notification))
746
+ }
747
+ if (this.dispatchConversationNotification(notification)) {
697
748
  return;
749
+ }
698
750
  this.dispatchAppNotification(notification);
699
751
  }
700
752
  dispatchMessageNotification(notification) {
701
- if (isNotificationDeliveryFor(notification, MessageReceivedNotificationDefinition)) {
753
+ if (isNotificationDeliveryFor(notification, messageReceivedNotificationDefinition)) {
702
754
  this.handleMessageReceivedNotification(notification.params);
703
755
  return true;
704
756
  }
705
757
  return false;
706
758
  }
707
759
  dispatchConversationNotification(notification) {
708
- if (isNotificationDeliveryFor(notification, ConversationCreatedNotificationDefinition)) {
760
+ if (isNotificationDeliveryFor(notification, conversationCreatedNotificationDefinition)) {
709
761
  this.handleConversationCreatedNotification(notification.params);
710
762
  return true;
711
763
  }
712
- if (isNotificationDeliveryFor(notification, ConversationArchivedNotificationDefinition)) {
764
+ if (isNotificationDeliveryFor(notification, conversationArchivedNotificationDefinition)) {
713
765
  this.handleConversationArchivedNotification(notification.params);
714
766
  return true;
715
767
  }
716
- if (isNotificationDeliveryFor(notification, ConversationUnarchivedNotificationDefinition)) {
768
+ if (isNotificationDeliveryFor(notification, conversationUnarchivedNotificationDefinition)) {
717
769
  this.handleConversationUnarchivedNotification(notification.params);
718
770
  return true;
719
771
  }
720
772
  return false;
721
773
  }
722
774
  dispatchAppNotification(notification) {
723
- if (isNotificationDeliveryFor(notification, DispatchRelease)) {
775
+ if (isNotificationDeliveryFor(notification, dispatchRelease)) {
724
776
  fanout(this.handlers.dispatchRelease, notification.params);
725
777
  return;
726
778
  }
727
- if (isNotificationDeliveryFor(notification, DispatchLeaseConsumed)) {
779
+ if (isNotificationDeliveryFor(notification, dispatchLeaseConsumed)) {
728
780
  fanout(this.handlers.dispatchLeaseConsumed, notification.params);
729
781
  return;
730
782
  }
731
- if (isNotificationDeliveryFor(notification, DispatchLeaseExpired)) {
783
+ if (isNotificationDeliveryFor(notification, dispatchLeaseExpired)) {
732
784
  fanout(this.handlers.dispatchLeaseExpired, notification.params);
733
785
  }
734
786
  }
@@ -743,6 +795,9 @@ export class MoltZapService {
743
795
  * replay, dual subscription) is suppressed to one
744
796
  * `on("message", ...)` event. `agent/message/list` returns raw history
745
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.
746
801
  */
747
802
  recordMessageIdIfNew(convId, msgId) {
748
803
  let dedupWindow = this.seenMessageIds.get(convId);
@@ -768,7 +823,7 @@ export class MoltZapService {
768
823
  // Name resolution is driven lazily by channel-core's serialized consumer
769
824
  // via resolveAgentName(), which populates agentNamesRef on first miss and
770
825
  // hits the cache on every subsequent message.
771
- if (msg.senderId !== this._ownAgentId) {
826
+ if (msg.senderId !== this.ownAgentIdValue) {
772
827
  fanout(this.handlers.message, {
773
828
  taskId: notification.taskId,
774
829
  message: msg,