@moltzap/client 2026.528.0 → 2026.717.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.
- package/dist/agent-client.d.ts +2 -65
- package/dist/agent-client.d.ts.map +1 -1
- package/dist/agent-client.js +1 -286
- package/dist/agent-client.js.map +1 -1
- package/dist/app-client.d.ts +3 -0
- package/dist/app-client.d.ts.map +1 -0
- package/dist/app-client.js +2 -0
- package/dist/app-client.js.map +1 -0
- package/dist/auth.d.ts +6 -15
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +12 -16
- package/dist/auth.js.map +1 -1
- package/dist/channel-base/format-cross-conv.d.ts +10 -15
- package/dist/channel-base/format-cross-conv.d.ts.map +1 -1
- package/dist/channel-base/format-cross-conv.js +10 -15
- package/dist/channel-base/format-cross-conv.js.map +1 -1
- package/dist/channel-base/format-group-block.d.ts +8 -10
- package/dist/channel-base/format-group-block.d.ts.map +1 -1
- package/dist/channel-base/format-group-block.js +8 -10
- package/dist/channel-base/format-group-block.js.map +1 -1
- package/dist/channel-base/index.d.ts +3 -62
- package/dist/channel-base/index.d.ts.map +1 -1
- package/dist/channel-base/index.js +2 -65
- package/dist/channel-base/index.js.map +1 -1
- package/dist/channel-base/lease-guard.d.ts +0 -2
- package/dist/channel-base/lease-guard.d.ts.map +1 -1
- package/dist/channel-base/lease-guard.js +0 -2
- package/dist/channel-base/lease-guard.js.map +1 -1
- package/dist/channel-base/lease-store.d.ts +2 -3
- package/dist/channel-base/lease-store.d.ts.map +1 -1
- package/dist/channel-base/lease-store.js +2 -3
- package/dist/channel-base/lease-store.js.map +1 -1
- package/dist/channel-base/lease.d.ts +25 -31
- package/dist/channel-base/lease.d.ts.map +1 -1
- package/dist/channel-base/lease.js +29 -45
- package/dist/channel-base/lease.js.map +1 -1
- package/dist/channel-core-enrichment.d.ts +1 -1
- package/dist/channel-core-enrichment.d.ts.map +1 -1
- package/dist/channel-core-test-support.d.ts +17 -11
- package/dist/channel-core-test-support.d.ts.map +1 -1
- package/dist/channel-core-test-support.js +5 -6
- package/dist/channel-core-test-support.js.map +1 -1
- package/dist/channel-core.d.ts +24 -29
- package/dist/channel-core.d.ts.map +1 -1
- package/dist/channel-core.js +18 -42
- package/dist/channel-core.js.map +1 -1
- package/dist/cli/commands/agents.d.ts +3 -6
- package/dist/cli/commands/agents.d.ts.map +1 -1
- package/dist/cli/commands/agents.js +14 -50
- package/dist/cli/commands/agents.js.map +1 -1
- package/dist/cli/commands/contacts.d.ts +5 -6
- package/dist/cli/commands/contacts.d.ts.map +1 -1
- package/dist/cli/commands/contacts.js +15 -43
- package/dist/cli/commands/contacts.js.map +1 -1
- package/dist/cli/commands/conversations.d.ts +8 -18
- package/dist/cli/commands/conversations.d.ts.map +1 -1
- package/dist/cli/commands/conversations.js +14 -65
- package/dist/cli/commands/conversations.js.map +1 -1
- package/dist/cli/commands/messages.d.ts +13 -35
- package/dist/cli/commands/messages.d.ts.map +1 -1
- package/dist/cli/commands/messages.js +21 -46
- package/dist/cli/commands/messages.js.map +1 -1
- package/dist/cli/commands/register.d.ts +10 -12
- package/dist/cli/commands/register.d.ts.map +1 -1
- package/dist/cli/commands/register.js +47 -133
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/send.d.ts +23 -36
- package/dist/cli/commands/send.d.ts.map +1 -1
- package/dist/cli/commands/send.js +25 -72
- package/dist/cli/commands/send.js.map +1 -1
- package/dist/cli/commands/start.d.ts +10 -124
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +28 -510
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.d.ts +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +8 -9
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/test-transport.d.ts +12 -5
- package/dist/cli/commands/test-transport.d.ts.map +1 -1
- package/dist/cli/commands/test-transport.js +15 -15
- package/dist/cli/commands/test-transport.js.map +1 -1
- package/dist/cli/index.js +13 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +4 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +9 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/socket-client.d.ts +7 -14
- package/dist/cli/socket-client.d.ts.map +1 -1
- package/dist/cli/socket-client.js +15 -38
- package/dist/cli/socket-client.js.map +1 -1
- package/dist/cli/transport.d.ts +53 -116
- package/dist/cli/transport.d.ts.map +1 -1
- package/dist/cli/transport.js +45 -295
- package/dist/cli/transport.js.map +1 -1
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test-utils.d.ts +13 -0
- package/dist/config.test-utils.d.ts.map +1 -0
- package/dist/config.test-utils.js +46 -0
- package/dist/config.test-utils.js.map +1 -0
- package/dist/index.d.ts +3 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -12
- package/dist/index.js.map +1 -1
- package/dist/local-daemon-rpc.d.ts +259 -8
- package/dist/local-daemon-rpc.d.ts.map +1 -1
- package/dist/local-daemon-rpc.js +189 -12
- package/dist/local-daemon-rpc.js.map +1 -1
- package/dist/{runtime/local-history.d.ts → local-history.d.ts} +16 -21
- package/dist/local-history.d.ts.map +1 -0
- package/dist/{runtime/local-history.js → local-history.js} +16 -21
- package/dist/local-history.js.map +1 -0
- package/dist/local-paths.d.ts +0 -2
- package/dist/local-paths.d.ts.map +1 -1
- package/dist/local-paths.js +0 -4
- package/dist/local-paths.js.map +1 -1
- package/dist/local-socket-server.d.ts +22 -0
- package/dist/local-socket-server.d.ts.map +1 -0
- package/dist/{runtime/local-socket-server.js → local-socket-server.js} +4 -9
- package/dist/local-socket-server.js.map +1 -0
- package/dist/message-rendering.d.ts +3 -0
- package/dist/message-rendering.d.ts.map +1 -0
- package/dist/message-rendering.js +7 -0
- package/dist/message-rendering.js.map +1 -0
- package/dist/notification/__tests__/{snapshot-semantics.types-check.d.ts → subscribe-signatures.types-check.d.ts} +1 -1
- package/dist/notification/__tests__/subscribe-signatures.types-check.d.ts.map +1 -0
- package/dist/notification/__tests__/subscribe-signatures.types-check.js +55 -0
- package/dist/notification/__tests__/subscribe-signatures.types-check.js.map +1 -0
- package/dist/notification/errors.d.ts +18 -6
- package/dist/notification/errors.d.ts.map +1 -1
- package/dist/notification/errors.js +13 -15
- package/dist/notification/errors.js.map +1 -1
- package/dist/notification/index.d.ts +5 -0
- package/dist/notification/index.d.ts.map +1 -0
- package/dist/notification/index.js +5 -0
- package/dist/notification/index.js.map +1 -0
- package/dist/notification/stream.d.ts +33 -49
- package/dist/notification/stream.d.ts.map +1 -1
- package/dist/notification/stream.js +33 -76
- package/dist/notification/stream.js.map +1 -1
- package/dist/pagination.d.ts +20 -10
- package/dist/pagination.d.ts.map +1 -1
- package/dist/pagination.js +8 -9
- package/dist/pagination.js.map +1 -1
- package/dist/profile.d.ts +92 -0
- package/dist/profile.d.ts.map +1 -0
- package/dist/profile.js +149 -0
- package/dist/profile.js.map +1 -0
- package/dist/refs.d.ts.map +1 -0
- package/dist/refs.js.map +1 -0
- package/dist/service-archive-purge.d.ts +2 -1
- package/dist/service-archive-purge.d.ts.map +1 -1
- package/dist/service-archive-purge.js.map +1 -1
- package/dist/{runtime/service-helpers.d.ts → service-helpers.d.ts} +5 -11
- package/dist/service-helpers.d.ts.map +1 -0
- package/dist/{runtime/service-helpers.js → service-helpers.js} +2 -9
- package/dist/service-helpers.js.map +1 -0
- package/dist/service-local-daemon.d.ts +22 -0
- package/dist/service-local-daemon.d.ts.map +1 -0
- package/dist/service-local-daemon.js +185 -0
- package/dist/service-local-daemon.js.map +1 -0
- package/dist/service.d.ts +65 -57
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +205 -156
- package/dist/service.js.map +1 -1
- package/dist/test-utils/channel-service-fixture.d.ts +3 -2
- package/dist/test-utils/channel-service-fixture.d.ts.map +1 -1
- package/dist/test-utils/channel-service-fixture.js.map +1 -1
- package/dist/test-utils/fake-service.d.ts +26 -18
- package/dist/test-utils/fake-service.d.ts.map +1 -1
- package/dist/test-utils/fake-service.js +28 -42
- package/dist/test-utils/fake-service.js.map +1 -1
- package/dist/test-utils/ids.d.ts +3 -1
- package/dist/test-utils/ids.d.ts.map +1 -1
- package/dist/test-utils/ids.js.map +1 -1
- package/dist/test-utils/index.d.ts +9 -2
- package/dist/test-utils/index.d.ts.map +1 -1
- package/dist/test-utils/index.js +8 -1
- package/dist/test-utils/index.js.map +1 -1
- package/dist/test-utils/standalone-provisioning.d.ts +17 -0
- package/dist/test-utils/standalone-provisioning.d.ts.map +1 -0
- package/dist/test-utils/standalone-provisioning.js +14 -0
- package/dist/test-utils/standalone-provisioning.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +39 -17
- package/dist/auth.test.d.ts +0 -2
- package/dist/auth.test.d.ts.map +0 -1
- package/dist/auth.test.js +0 -121
- package/dist/auth.test.js.map +0 -1
- package/dist/channel-core-context.test.d.ts +0 -2
- package/dist/channel-core-context.test.d.ts.map +0 -1
- package/dist/channel-core-context.test.js +0 -342
- package/dist/channel-core-context.test.js.map +0 -1
- package/dist/channel-core-dispatch.test.d.ts +0 -2
- package/dist/channel-core-dispatch.test.d.ts.map +0 -1
- package/dist/channel-core-dispatch.test.js +0 -557
- package/dist/channel-core-dispatch.test.js.map +0 -1
- package/dist/channel-core.test.d.ts +0 -2
- package/dist/channel-core.test.d.ts.map +0 -1
- package/dist/channel-core.test.js +0 -232
- package/dist/channel-core.test.js.map +0 -1
- package/dist/cli/__tests__/cli-multi-agent.int.test.d.ts +0 -2
- package/dist/cli/__tests__/cli-multi-agent.int.test.d.ts.map +0 -1
- package/dist/cli/__tests__/cli-multi-agent.int.test.js +0 -132
- package/dist/cli/__tests__/cli-multi-agent.int.test.js.map +0 -1
- package/dist/cli/commands/invite.d.ts +0 -7
- package/dist/cli/commands/invite.d.ts.map +0 -1
- package/dist/cli/commands/invite.js +0 -11
- package/dist/cli/commands/invite.js.map +0 -1
- package/dist/cli/commands/messages.test.d.ts +0 -2
- package/dist/cli/commands/messages.test.d.ts.map +0 -1
- package/dist/cli/commands/messages.test.js +0 -99
- package/dist/cli/commands/messages.test.js.map +0 -1
- package/dist/cli/commands/ping.d.ts +0 -7
- package/dist/cli/commands/ping.d.ts.map +0 -1
- package/dist/cli/commands/ping.js +0 -37
- package/dist/cli/commands/ping.js.map +0 -1
- package/dist/cli/commands/presence.d.ts +0 -11
- package/dist/cli/commands/presence.d.ts.map +0 -1
- package/dist/cli/commands/presence.js +0 -33
- package/dist/cli/commands/presence.js.map +0 -1
- package/dist/cli/commands/register.test.d.ts +0 -2
- package/dist/cli/commands/register.test.d.ts.map +0 -1
- package/dist/cli/commands/register.test.js +0 -91
- package/dist/cli/commands/register.test.js.map +0 -1
- package/dist/cli/commands/send.test.d.ts +0 -2
- package/dist/cli/commands/send.test.d.ts.map +0 -1
- package/dist/cli/commands/send.test.js +0 -59
- package/dist/cli/commands/send.test.js.map +0 -1
- package/dist/cli/commands/start.test.d.ts +0 -2
- package/dist/cli/commands/start.test.d.ts.map +0 -1
- package/dist/cli/commands/start.test.js +0 -624
- package/dist/cli/commands/start.test.js.map +0 -1
- package/dist/cli/commands/whoami.d.ts +0 -8
- package/dist/cli/commands/whoami.d.ts.map +0 -1
- package/dist/cli/commands/whoami.js +0 -28
- package/dist/cli/commands/whoami.js.map +0 -1
- package/dist/cli/config.d.ts +0 -66
- package/dist/cli/config.d.ts.map +0 -1
- package/dist/cli/config.js +0 -148
- package/dist/cli/config.js.map +0 -1
- package/dist/cli/config.test.d.ts +0 -2
- package/dist/cli/config.test.d.ts.map +0 -1
- package/dist/cli/config.test.js +0 -89
- package/dist/cli/config.test.js.map +0 -1
- package/dist/cli/http-client.d.ts +0 -17
- package/dist/cli/http-client.d.ts.map +0 -1
- package/dist/cli/http-client.js +0 -38
- package/dist/cli/http-client.js.map +0 -1
- package/dist/cli/profile.d.ts +0 -126
- package/dist/cli/profile.d.ts.map +0 -1
- package/dist/cli/profile.js +0 -231
- package/dist/cli/profile.js.map +0 -1
- package/dist/cli/profile.test.d.ts +0 -2
- package/dist/cli/profile.test.d.ts.map +0 -1
- package/dist/cli/profile.test.js +0 -369
- package/dist/cli/profile.test.js.map +0 -1
- package/dist/cli/transport.test.d.ts +0 -2
- package/dist/cli/transport.test.d.ts.map +0 -1
- package/dist/cli/transport.test.js +0 -312
- package/dist/cli/transport.test.js.map +0 -1
- package/dist/notification/__tests__/filter-equivalence.test.d.ts +0 -2
- package/dist/notification/__tests__/filter-equivalence.test.d.ts.map +0 -1
- package/dist/notification/__tests__/filter-equivalence.test.js +0 -123
- package/dist/notification/__tests__/filter-equivalence.test.js.map +0 -1
- package/dist/notification/__tests__/snapshot-semantics.test.d.ts +0 -2
- package/dist/notification/__tests__/snapshot-semantics.test.d.ts.map +0 -1
- package/dist/notification/__tests__/snapshot-semantics.test.js +0 -261
- package/dist/notification/__tests__/snapshot-semantics.test.js.map +0 -1
- package/dist/notification/__tests__/snapshot-semantics.types-check.d.ts.map +0 -1
- package/dist/notification/__tests__/snapshot-semantics.types-check.js +0 -62
- package/dist/notification/__tests__/snapshot-semantics.types-check.js.map +0 -1
- package/dist/pagination.test.d.ts +0 -2
- package/dist/pagination.test.d.ts.map +0 -1
- package/dist/pagination.test.js +0 -72
- package/dist/pagination.test.js.map +0 -1
- package/dist/runtime/close-info.d.ts +0 -84
- package/dist/runtime/close-info.d.ts.map +0 -1
- package/dist/runtime/close-info.js +0 -102
- package/dist/runtime/close-info.js.map +0 -1
- package/dist/runtime/close-info.test.d.ts +0 -2
- package/dist/runtime/close-info.test.d.ts.map +0 -1
- package/dist/runtime/close-info.test.js +0 -109
- package/dist/runtime/close-info.test.js.map +0 -1
- package/dist/runtime/errors.d.ts +0 -11
- package/dist/runtime/errors.d.ts.map +0 -1
- package/dist/runtime/errors.js +0 -41
- package/dist/runtime/errors.js.map +0 -1
- package/dist/runtime/errors.test.d.ts +0 -2
- package/dist/runtime/errors.test.d.ts.map +0 -1
- package/dist/runtime/errors.test.js +0 -79
- package/dist/runtime/errors.test.js.map +0 -1
- package/dist/runtime/frame.d.ts +0 -8
- package/dist/runtime/frame.d.ts.map +0 -1
- package/dist/runtime/frame.js +0 -12
- package/dist/runtime/frame.js.map +0 -1
- package/dist/runtime/frame.test.d.ts +0 -2
- package/dist/runtime/frame.test.d.ts.map +0 -1
- package/dist/runtime/frame.test.js +0 -59
- package/dist/runtime/frame.test.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -10
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -9
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/local-history.d.ts.map +0 -1
- package/dist/runtime/local-history.js.map +0 -1
- package/dist/runtime/local-service-commands.d.ts +0 -26
- package/dist/runtime/local-service-commands.d.ts.map +0 -1
- package/dist/runtime/local-service-commands.js +0 -29
- package/dist/runtime/local-service-commands.js.map +0 -1
- package/dist/runtime/local-socket-server.d.ts +0 -20
- package/dist/runtime/local-socket-server.d.ts.map +0 -1
- package/dist/runtime/local-socket-server.js.map +0 -1
- package/dist/runtime/refs.d.ts.map +0 -1
- package/dist/runtime/refs.js.map +0 -1
- package/dist/runtime/runtime.test.d.ts +0 -2
- package/dist/runtime/runtime.test.d.ts.map +0 -1
- package/dist/runtime/runtime.test.js +0 -37
- package/dist/runtime/runtime.test.js.map +0 -1
- package/dist/runtime/service-helpers.d.ts.map +0 -1
- package/dist/runtime/service-helpers.js.map +0 -1
- package/dist/runtime/service-teardown.d.ts +0 -5
- package/dist/runtime/service-teardown.d.ts.map +0 -1
- package/dist/runtime/service-teardown.js +0 -36
- package/dist/runtime/service-teardown.js.map +0 -1
- package/dist/runtime/service-teardown.test.d.ts +0 -2
- package/dist/runtime/service-teardown.test.d.ts.map +0 -1
- package/dist/runtime/service-teardown.test.js +0 -80
- package/dist/runtime/service-teardown.test.js.map +0 -1
- package/dist/runtime/subscribers.d.ts +0 -152
- package/dist/runtime/subscribers.d.ts.map +0 -1
- package/dist/runtime/subscribers.js +0 -222
- package/dist/runtime/subscribers.js.map +0 -1
- package/dist/service-socket-path.test.d.ts +0 -2
- package/dist/service-socket-path.test.d.ts.map +0 -1
- package/dist/service-socket-path.test.js +0 -87
- package/dist/service-socket-path.test.js.map +0 -1
- package/dist/service.test.d.ts +0 -2
- package/dist/service.test.d.ts.map +0 -1
- package/dist/service.test.js +0 -796
- package/dist/service.test.js.map +0 -1
- package/dist/test/index.d.ts +0 -47
- package/dist/test/index.d.ts.map +0 -1
- package/dist/test/index.js +0 -39
- package/dist/test/index.js.map +0 -1
- package/dist/test-utils/conformance-adapter.d.ts +0 -40
- package/dist/test-utils/conformance-adapter.d.ts.map +0 -1
- package/dist/test-utils/conformance-adapter.js +0 -250
- package/dist/test-utils/conformance-adapter.js.map +0 -1
- package/dist/tm-client-test-support.d.ts +0 -184
- package/dist/tm-client-test-support.d.ts.map +0 -1
- package/dist/tm-client-test-support.js +0 -466
- package/dist/tm-client-test-support.js.map +0 -1
- package/dist/tm-client.d.ts +0 -269
- package/dist/tm-client.d.ts.map +0 -1
- package/dist/tm-client.js +0 -518
- package/dist/tm-client.js.map +0 -1
- package/dist/tm-client.test.d.ts +0 -2
- package/dist/tm-client.test.d.ts.map +0 -1
- package/dist/tm-client.test.js +0 -490
- package/dist/tm-client.test.js.map +0 -1
- /package/dist/{runtime/refs.d.ts → refs.d.ts} +0 -0
- /package/dist/{runtime/refs.js → refs.js} +0 -0
package/dist/service.js
CHANGED
|
@@ -1,24 +1,34 @@
|
|
|
1
|
-
/* eslint-disable jsdoc/text-escaping -- mermaid sequenceDiagram blocks need literal `<br>` (HTML5) for renderer compatibility; the escape would render as literal text. */
|
|
2
1
|
import { FileSystem, Path } from "@effect/platform";
|
|
3
2
|
import { NodeContext } from "@effect/platform-node";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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";
|
|
11
|
+
import { Config, ConfigProvider, Effect, Exit, HashMap, Option, Ref, Schema, Scope, Stream, } from "effect";
|
|
6
12
|
import { MoltZapAgentClient } from "./agent-client.js";
|
|
7
|
-
import {
|
|
8
|
-
import { getOr, snapshot } from "./
|
|
9
|
-
import { LocalServiceCommands } from "./runtime/local-service-commands.js";
|
|
13
|
+
import { loadServiceConfig, } from "./config.js";
|
|
14
|
+
import { getOr, snapshot } from "./refs.js";
|
|
10
15
|
import { getMoltZapAgentServiceSocketPath, getMoltZapServiceSocketPath, } from "./local-paths.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
16
|
+
import {} from "./local-daemon-rpc.js";
|
|
17
|
+
import { makeLocalDaemonHandlers } from "./service-local-daemon.js";
|
|
18
|
+
import { startLocalSocketServer, stopLocalSocketServer, } from "./local-socket-server.js";
|
|
19
|
+
import { buildContextEntries, makeContextCandidate, newMessagesForConversation, notificationTraceRecord, } from "./service-helpers.js";
|
|
20
|
+
import { renderPart } from "./message-rendering.js";
|
|
21
|
+
import { formatHistoryMessage, lastReadIdsForSession, } from "./local-history.js";
|
|
15
22
|
import { purgeAgentCacheEntries, purgeLastNotified, purgeLastRead, } from "./service-archive-purge.js";
|
|
16
23
|
const CROSS_CONTEXT_TEXT_LIMIT = 120;
|
|
17
24
|
const DEFAULT_MAX_CONTEXT_CONVERSATIONS = 5;
|
|
18
25
|
const DEFAULT_MAX_MESSAGES_PER_CONVERSATION = 3;
|
|
19
26
|
const HISTORY_LOOKUP_CONCURRENCY = 2;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
27
|
+
const AGENT_LOOKUP_PAGE_SIZE = 100;
|
|
28
|
+
const AGENT_LOOKUP_MAX_PAGES = 20;
|
|
29
|
+
const REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE = 50;
|
|
30
|
+
const REUSABLE_CONVERSATION_LOOKUP_MAX_PAGES = 20;
|
|
31
|
+
const decodeAgentId = Schema.decodeUnknownOption(AgentIdSchema);
|
|
22
32
|
const ClientEventLogDir = Config.option(Config.string("MOLTZAP_CLIENT_EVENT_LOG_DIR"));
|
|
23
33
|
const getClientEventLogDir = () => Option.getOrUndefined(Effect.runSync(ClientEventLogDir.pipe(Effect.withConfigProvider(ConfigProvider.fromEnv()))));
|
|
24
34
|
function appendClientEventTrace(record) {
|
|
@@ -33,6 +43,10 @@ function appendClientEventTrace(record) {
|
|
|
33
43
|
yield* Effect.zipRight(fileSystem.makeDirectory(dir, { recursive: true }), fileSystem.writeFileString(path.join(dir, `client-events-${safeAgentId}.jsonl`), JSON.stringify(record) + "\n", { flag: "a" }));
|
|
34
44
|
}).pipe(Effect.withSpan("appendClientEventTrace"), Effect.provide(NodeContext.layer), Effect.catchAll((err) => Effect.logWarning("moltzap client event trace write failed", err)));
|
|
35
45
|
}
|
|
46
|
+
const agentNotFound = (agentName) => new AgentNotFoundError({
|
|
47
|
+
message: `Agent not found: ${agentName}`,
|
|
48
|
+
data: { agentName },
|
|
49
|
+
});
|
|
36
50
|
/** Escape `<`, `>`, `&` so sender content can't escape a `<system-reminder>` block. */
|
|
37
51
|
export function sanitizeForSystemReminder(s) {
|
|
38
52
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -42,7 +56,7 @@ export function sanitizeForSystemReminder(s) {
|
|
|
42
56
|
* that inline context into prompt text (nanoclaw) and `MoltZapService.getContext`
|
|
43
57
|
* share this formatter so sanitization and line shape stay in one place.
|
|
44
58
|
*/
|
|
45
|
-
|
|
59
|
+
function formatCrossConversationBlock(entries, opts) {
|
|
46
60
|
if (entries.length === 0)
|
|
47
61
|
return null;
|
|
48
62
|
const lines = entries.map((e) => {
|
|
@@ -91,19 +105,16 @@ function fanout(handlers, arg) {
|
|
|
91
105
|
* API contract: **every fallible method returns `Effect`.** No `*Async`
|
|
92
106
|
* Promise siblings — async/await consumers run the Effect at the edge
|
|
93
107
|
* with `Effect.runPromise`. Keep this class Effect-only so downstream
|
|
94
|
-
* callers compose failures and cancellation explicitly.
|
|
95
|
-
* vendored the legacy `@moltzap/app-sdk` Promise-shaped wrapper out
|
|
96
|
-
* to arena; consumers wanting Promise wrappers maintain their own.)
|
|
108
|
+
* callers compose failures and cancellation explicitly.
|
|
97
109
|
*/
|
|
98
110
|
export class MoltZapService {
|
|
99
111
|
opts;
|
|
100
112
|
client = null;
|
|
101
113
|
_connected = false;
|
|
102
114
|
/**
|
|
103
|
-
* Service-owned scope
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* service.
|
|
115
|
+
* Service-owned scope. Opened in `connect()`, owns the
|
|
116
|
+
* `subscribeAll → Stream.runForEach` fan-out fiber. Closed in `close()` so
|
|
117
|
+
* the fiber terminates with the service.
|
|
107
118
|
*
|
|
108
119
|
* Held off the public `connect()` signature so callers do not need to
|
|
109
120
|
* thread a `Scope` requirement.
|
|
@@ -134,42 +145,29 @@ export class MoltZapService {
|
|
|
134
145
|
conversationArchived: [],
|
|
135
146
|
conversationUnarchived: [],
|
|
136
147
|
dispatchRelease: [],
|
|
137
|
-
|
|
138
|
-
|
|
148
|
+
dispatchLeaseConsumed: [],
|
|
149
|
+
dispatchLeaseExpired: [],
|
|
139
150
|
};
|
|
140
|
-
notificationDispatchers = new Map([
|
|
141
|
-
[
|
|
142
|
-
MessageReceivedNotificationDefinition,
|
|
143
|
-
(notification) => this.handleMessageReceivedNotification(notification.params),
|
|
144
|
-
],
|
|
145
|
-
[
|
|
146
|
-
TaskConversationCreatedNotificationDefinition,
|
|
147
|
-
(notification) => this.handleConversationCreatedNotification(notification.params),
|
|
148
|
-
],
|
|
149
|
-
[
|
|
150
|
-
TaskConversationArchivedNotificationDefinition,
|
|
151
|
-
(notification) => this.handleConversationArchivedNotification(notification.params),
|
|
152
|
-
],
|
|
153
|
-
[
|
|
154
|
-
TaskConversationUnarchivedNotificationDefinition,
|
|
155
|
-
(notification) => this.handleConversationUnarchivedNotification(notification.params),
|
|
156
|
-
],
|
|
157
|
-
[
|
|
158
|
-
DispatchRelease,
|
|
159
|
-
(notification) => fanout(this.handlers.dispatchRelease, notification.params),
|
|
160
|
-
],
|
|
161
|
-
[
|
|
162
|
-
DispatchesConsumed,
|
|
163
|
-
(notification) => fanout(this.handlers.dispatchesConsumed, notification.params),
|
|
164
|
-
],
|
|
165
|
-
[
|
|
166
|
-
DispatchesExpired,
|
|
167
|
-
(notification) => fanout(this.handlers.dispatchesExpired, notification.params),
|
|
168
|
-
],
|
|
169
|
-
]);
|
|
170
151
|
_ownAgentId;
|
|
171
152
|
constructor(opts) {
|
|
172
153
|
this.opts = opts;
|
|
154
|
+
// The empty HelloOk carries no identity; `ownAgentId` is the client's
|
|
155
|
+
// registered/stored id, available before the handshake.
|
|
156
|
+
this._ownAgentId = opts.agentId;
|
|
157
|
+
}
|
|
158
|
+
static fromConfig(config) {
|
|
159
|
+
return new MoltZapService(config);
|
|
160
|
+
}
|
|
161
|
+
static make(profileName) {
|
|
162
|
+
return loadServiceConfig(profileName).pipe(Effect.map(MoltZapService.fromConfig));
|
|
163
|
+
}
|
|
164
|
+
static startDaemon(profileName) {
|
|
165
|
+
return Effect.gen(function* () {
|
|
166
|
+
const service = yield* MoltZapService.make(profileName);
|
|
167
|
+
yield* service.connect();
|
|
168
|
+
yield* service.startSocketServer();
|
|
169
|
+
return service;
|
|
170
|
+
}).pipe(Effect.withSpan("MoltZapService.startDaemon"));
|
|
173
171
|
}
|
|
174
172
|
get connected() {
|
|
175
173
|
return this._connected;
|
|
@@ -183,9 +181,9 @@ export class MoltZapService {
|
|
|
183
181
|
const client = new MoltZapAgentClient({
|
|
184
182
|
serverUrl: this.opts.serverUrl,
|
|
185
183
|
agentKey: this.opts.agentKey,
|
|
186
|
-
//
|
|
187
|
-
//
|
|
188
|
-
//
|
|
184
|
+
// The body doesn't branch on close metadata today; the signature is
|
|
185
|
+
// kept explicit so a future disconnect-handler chain can plumb
|
|
186
|
+
// code/reason through.
|
|
189
187
|
onDisconnect: () => {
|
|
190
188
|
this._connected = false;
|
|
191
189
|
fanout(this.handlers.disconnect, undefined);
|
|
@@ -196,11 +194,10 @@ export class MoltZapService {
|
|
|
196
194
|
},
|
|
197
195
|
});
|
|
198
196
|
this.client = client;
|
|
199
|
-
//
|
|
200
|
-
// is
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
// pre-handshake (pre-connect legality, preserved invariant).
|
|
197
|
+
// `subscribeAll().pipe(Stream.runForEach, …)` is forked into a
|
|
198
|
+
// service-owned scope. The Stream is materialized BEFORE `connect()` so
|
|
199
|
+
// subscriptions are registered with the registry pre-handshake (a
|
|
200
|
+
// pre-connect-legal operation).
|
|
204
201
|
//
|
|
205
202
|
// Stream errors of type `NotConnectedError` are surfaced on the
|
|
206
203
|
// fiber's failure channel only when the client transitions to
|
|
@@ -213,7 +210,6 @@ export class MoltZapService {
|
|
|
213
210
|
yield* Effect.forkIn(fanoutEffect, serviceScope);
|
|
214
211
|
const helloOk = yield* client.connect();
|
|
215
212
|
this._connected = true;
|
|
216
|
-
this._ownAgentId = helloOk.agentId;
|
|
217
213
|
return helloOk;
|
|
218
214
|
});
|
|
219
215
|
}
|
|
@@ -226,22 +222,15 @@ export class MoltZapService {
|
|
|
226
222
|
close() {
|
|
227
223
|
this._connected = false;
|
|
228
224
|
Effect.runFork(this.stopSocketServer());
|
|
229
|
-
// Spec #596 / Spec B §"4.2 service.ts": close the service-owned scope
|
|
230
|
-
// BEFORE the client. Closing the scope interrupts the
|
|
231
|
-
// `subscribeAll().pipe(Stream.runForEach, …)` fiber; the client's
|
|
232
|
-
// `close()` then closes the registry which fires `onClose` on every
|
|
233
|
-
// live subscription's Stream — but since our consumer fiber has
|
|
234
|
-
// already been interrupted, the typed-error delivery is to a
|
|
235
|
-
// terminated consumer (no-op, idempotent).
|
|
236
|
-
// Order: close the service-scope FIRST (interrupting the
|
|
237
|
-
// `subscribeAll → runForEach` fiber), THEN close the ws-client.
|
|
238
|
-
// zipRight chains the two Effects sequentially inside a single
|
|
239
|
-
// fork so the ordering is honoured deterministically.
|
|
240
225
|
const scopeToClose = this.serviceScope;
|
|
241
226
|
const clientToClose = this.client;
|
|
242
227
|
this.serviceScope = null;
|
|
243
228
|
this.client = null;
|
|
244
|
-
|
|
229
|
+
const closeScope = scopeToClose === null
|
|
230
|
+
? Effect.void
|
|
231
|
+
: Scope.close(scopeToClose, Exit.void);
|
|
232
|
+
const closeClient = clientToClose === null ? Effect.void : clientToClose.close();
|
|
233
|
+
Effect.runFork(closeScope.pipe(Effect.zipRight(closeClient)));
|
|
245
234
|
Effect.runSync(Effect.all([
|
|
246
235
|
Ref.set(this.conversationsRef, HashMap.empty()),
|
|
247
236
|
Ref.set(this.messagesRef, HashMap.empty()),
|
|
@@ -287,7 +276,7 @@ export class MoltZapService {
|
|
|
287
276
|
const running = yield* startLocalSocketServer({
|
|
288
277
|
socketPath: this.socketPath,
|
|
289
278
|
defaultSocketPath: MoltZapService.SOCKET_PATH,
|
|
290
|
-
|
|
279
|
+
handlers: this.localDaemonHandlers(),
|
|
291
280
|
});
|
|
292
281
|
this.socketServerScope = running.socketScope;
|
|
293
282
|
this.activeSocketPath = running.socketPath;
|
|
@@ -308,36 +297,18 @@ export class MoltZapService {
|
|
|
308
297
|
defaultSocketPath: MoltZapService.SOCKET_PATH,
|
|
309
298
|
}).pipe(Effect.withSpan("MoltZapService.stopSocketServer"));
|
|
310
299
|
}
|
|
311
|
-
|
|
312
|
-
return
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
agentId: this.ownAgentId,
|
|
319
|
-
connected: this._connected,
|
|
320
|
-
conversations: this.getConversations().length,
|
|
321
|
-
});
|
|
322
|
-
case LocalServiceCommands.History:
|
|
323
|
-
return this.handleHistoryRequest(params);
|
|
324
|
-
default: {
|
|
325
|
-
const definition = serverRpcMethods.find((d) => d.name === method);
|
|
326
|
-
if (definition === undefined ||
|
|
327
|
-
!definition.validateParams(params)) {
|
|
328
|
-
return Effect.fail(new ServiceInputError({
|
|
329
|
-
message: `unknown or invalid RPC method: ${method}`,
|
|
330
|
-
}));
|
|
331
|
-
}
|
|
332
|
-
return this.sendRpc(definition, params);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
300
|
+
localDaemonHandlers() {
|
|
301
|
+
return makeLocalDaemonHandlers({
|
|
302
|
+
ownAgentId: this._ownAgentId,
|
|
303
|
+
connected: this._connected,
|
|
304
|
+
conversationCount: () => this.getConversations().length,
|
|
305
|
+
call: this.call.bind(this),
|
|
306
|
+
handleHistoryRequest: (request) => this.handleHistoryRequest(request),
|
|
335
307
|
});
|
|
336
308
|
}
|
|
337
|
-
handleHistoryRequest(
|
|
309
|
+
handleHistoryRequest(request) {
|
|
338
310
|
return Effect.gen(this, function* () {
|
|
339
|
-
const
|
|
340
|
-
const result = yield* this.sendRpc(MessagesList, {
|
|
311
|
+
const result = yield* this.call(MessagesList.name, {
|
|
341
312
|
taskId: request.taskId,
|
|
342
313
|
conversationId: request.conversationId,
|
|
343
314
|
limit: request.limit,
|
|
@@ -380,19 +351,13 @@ export class MoltZapService {
|
|
|
380
351
|
].filter((id) => !HashMap.has(knownNames, id));
|
|
381
352
|
if (unknownAgentIds.length === 0)
|
|
382
353
|
return;
|
|
383
|
-
yield* this.
|
|
384
|
-
let next = names;
|
|
385
|
-
for (const agent of result.agents) {
|
|
386
|
-
next = HashMap.set(next, agent.id, agent.name);
|
|
387
|
-
}
|
|
388
|
-
return next;
|
|
389
|
-
})), Effect.asVoid, Effect.catchAll(() => Effect.void));
|
|
354
|
+
yield* this.cacheVisibleAgentNamesForIds(new Set(unknownAgentIds)).pipe(Effect.asVoid, Effect.catchAll(() => Effect.void));
|
|
390
355
|
});
|
|
391
356
|
}
|
|
392
357
|
fetchHistoryConversationMeta(convId) {
|
|
393
|
-
//
|
|
394
|
-
//
|
|
395
|
-
return this.
|
|
358
|
+
// The client filters `ConversationList` output for the matching
|
|
359
|
+
// conversation id (there is no per-conversation get RPC).
|
|
360
|
+
return this.call(ConversationList.name, {}).pipe(Effect.map((result) => {
|
|
396
361
|
const hit = result.items.find((item) => item.conversation.id === convId);
|
|
397
362
|
return hit?.conversation;
|
|
398
363
|
}), Effect.catchAll(() => Effect.succeed(undefined)));
|
|
@@ -441,17 +406,16 @@ export class MoltZapService {
|
|
|
441
406
|
*/
|
|
442
407
|
resolveAgentName(agentId) {
|
|
443
408
|
return Effect.gen(this, function* () {
|
|
409
|
+
const decodedAgentId = Option.getOrUndefined(decodeAgentId(agentId));
|
|
410
|
+
if (decodedAgentId === undefined)
|
|
411
|
+
return agentId;
|
|
444
412
|
const cached = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
|
|
445
413
|
if (cached !== undefined)
|
|
446
414
|
return cached;
|
|
447
|
-
return yield* this.
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (!agent)
|
|
452
|
-
return Effect.succeed(agentId);
|
|
453
|
-
return Ref.update(this.agentNamesRef, (names) => HashMap.set(names, agentId, agent.name)).pipe(Effect.as(agent.name));
|
|
454
|
-
}), Effect.catchAll((err) => Effect.logWarning("agents/lookup failed; falling back to agentId").pipe(Effect.annotateLogs({ agentId, err: String(err) }), Effect.as(agentId))));
|
|
415
|
+
return yield* this.cacheVisibleAgentNamesForIds(new Set([decodedAgentId])).pipe(Effect.map(() => {
|
|
416
|
+
const resolved = Option.getOrUndefined(HashMap.get(snapshot(this.agentNamesRef), agentId));
|
|
417
|
+
return resolved ?? agentId;
|
|
418
|
+
}), Effect.catchAll((err) => Effect.logWarning("agent/identity/agents/list failed; falling back to agentId").pipe(Effect.annotateLogs({ agentId, err: String(err) }), Effect.as(agentId))));
|
|
455
419
|
});
|
|
456
420
|
}
|
|
457
421
|
// --- Messaging ---
|
|
@@ -470,8 +434,8 @@ export class MoltZapService {
|
|
|
470
434
|
* svc-->>caller: fail(RpcServerError ConversationArchived)
|
|
471
435
|
* else
|
|
472
436
|
* svc->>ws: sendRpc(MessagesSend, params)
|
|
473
|
-
* Note over ws: stateRef None → fail NotConnectedError
|
|
474
|
-
* ws->>server: {jsonrpc, method
|
|
437
|
+
* Note over ws: stateRef None → fail NotConnectedError; otherwise allocate request id, encode frame
|
|
438
|
+
* ws->>server: {jsonrpc, method agent/message/send, id, params}
|
|
475
439
|
* Note over ws: Deferred raced against 30s timeout
|
|
476
440
|
* server-->>ws: {result, id} or {error, id}
|
|
477
441
|
* Note over ws: reader fiber decodes, resolves the Deferred
|
|
@@ -482,17 +446,14 @@ export class MoltZapService {
|
|
|
482
446
|
*
|
|
483
447
|
* `opts.dispatchLeaseId` (when set) is forwarded verbatim in the
|
|
484
448
|
* params frame. The server marks the lease consumed, blocking the
|
|
485
|
-
*
|
|
449
|
+
* app authorization timeout sweep. `MoltZapChannelCore.sendReply` forwards
|
|
486
450
|
* `leaseIdInFlight` automatically when the caller omits it.
|
|
487
451
|
*/
|
|
488
452
|
send(taskId, conversationId, text, opts) {
|
|
489
453
|
if (this.isConversationArchived(conversationId)) {
|
|
490
|
-
return Effect.fail(new
|
|
491
|
-
code: ConversationArchivedError.code,
|
|
492
|
-
message: "Conversation is archived",
|
|
493
|
-
}));
|
|
454
|
+
return Effect.fail(new ConversationArchivedError({ message: "Conversation is archived" }));
|
|
494
455
|
}
|
|
495
|
-
return Effect.asVoid(this.
|
|
456
|
+
return Effect.asVoid(this.call(MessagesSend.name, {
|
|
496
457
|
taskId,
|
|
497
458
|
conversationId,
|
|
498
459
|
parts: [{ type: "text", text }],
|
|
@@ -503,34 +464,23 @@ export class MoltZapService {
|
|
|
503
464
|
}));
|
|
504
465
|
}
|
|
505
466
|
/**
|
|
506
|
-
* Issue `dispatch/request`. The server returns the ack
|
|
467
|
+
* Issue `agent/dispatch/request`. The server returns the ack
|
|
507
468
|
* `{leaseId, dispatchId}` immediately; the recipient observes the
|
|
508
469
|
* verdict asynchronously via the `dispatchRelease` event.
|
|
509
470
|
*/
|
|
510
471
|
requestDispatch(params) {
|
|
511
|
-
return this.
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* Issue `dispatches/get`. Moderator-only — calls from non-moderator
|
|
515
|
-
* connections fail with a typed wire error. The server enforces the
|
|
516
|
-
* binding tuple recorded at lease-mint time.
|
|
517
|
-
*/
|
|
518
|
-
dispatchesGet(params) {
|
|
519
|
-
return this.sendRpc(DispatchesGet, params);
|
|
472
|
+
return this.call(DispatchRequest.name, params);
|
|
520
473
|
}
|
|
521
474
|
sendToAgent(agentName, text, opts) {
|
|
522
475
|
return Effect.gen(this, function* () {
|
|
523
476
|
const cache = yield* Ref.get(this.agentConversationCacheRef);
|
|
524
477
|
let entry = Option.getOrUndefined(HashMap.get(cache, agentName));
|
|
525
478
|
if (entry === undefined) {
|
|
526
|
-
const
|
|
527
|
-
names: [agentName],
|
|
528
|
-
});
|
|
529
|
-
const agent = lookupResult.agents[0];
|
|
479
|
+
const agent = yield* this.findVisibleAgentByName(agentName);
|
|
530
480
|
if (!agent) {
|
|
531
|
-
return yield* Effect.fail(
|
|
481
|
+
return yield* Effect.fail(agentNotFound(agentName));
|
|
532
482
|
}
|
|
533
|
-
const createResult = yield* this.
|
|
483
|
+
const createResult = yield* this.call(TaskRequest.name, {
|
|
534
484
|
appId: DEFAULT_APP_ID,
|
|
535
485
|
invitedAgentIds: [agent.id],
|
|
536
486
|
initialConversation: { participants: [agent.id] },
|
|
@@ -552,13 +502,13 @@ export class MoltZapService {
|
|
|
552
502
|
resolveReusableConversationId(taskId, agentName) {
|
|
553
503
|
return Effect.gen(this, function* () {
|
|
554
504
|
let cursor = undefined;
|
|
555
|
-
for (let page = 0; page <
|
|
505
|
+
for (let page = 0; page < REUSABLE_CONVERSATION_LOOKUP_MAX_PAGES; page++) {
|
|
556
506
|
const params = {
|
|
557
|
-
limit:
|
|
507
|
+
limit: REUSABLE_CONVERSATION_LOOKUP_PAGE_SIZE,
|
|
558
508
|
};
|
|
559
509
|
if (cursor !== undefined)
|
|
560
510
|
params.cursor = cursor;
|
|
561
|
-
const result = yield* this.
|
|
511
|
+
const result = yield* this.call(ConversationList.name, params);
|
|
562
512
|
const hit = result.items.find((item) => item.taskId === taskId &&
|
|
563
513
|
item.conversation.archivedAt === undefined);
|
|
564
514
|
if (hit !== undefined)
|
|
@@ -567,7 +517,54 @@ export class MoltZapService {
|
|
|
567
517
|
break;
|
|
568
518
|
cursor = result.nextCursor;
|
|
569
519
|
}
|
|
570
|
-
return yield* Effect.fail(
|
|
520
|
+
return yield* Effect.fail(agentNotFound(agentName));
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
cacheAgentNames(agents) {
|
|
524
|
+
if (agents.length === 0)
|
|
525
|
+
return Effect.void;
|
|
526
|
+
return Ref.update(this.agentNamesRef, (names) => {
|
|
527
|
+
let next = names;
|
|
528
|
+
for (const agent of agents) {
|
|
529
|
+
next = HashMap.set(next, agent.id, agent.name);
|
|
530
|
+
}
|
|
531
|
+
return next;
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
agentListParams(cursor) {
|
|
535
|
+
return cursor === undefined
|
|
536
|
+
? { limit: AGENT_LOOKUP_PAGE_SIZE }
|
|
537
|
+
: { limit: AGENT_LOOKUP_PAGE_SIZE, cursor };
|
|
538
|
+
}
|
|
539
|
+
cacheVisibleAgentNamesForIds(agentIds) {
|
|
540
|
+
return Effect.gen(this, function* () {
|
|
541
|
+
const missing = new Set(agentIds);
|
|
542
|
+
let cursor = undefined;
|
|
543
|
+
for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
|
|
544
|
+
const params = this.agentListParams(cursor);
|
|
545
|
+
const result = yield* this.call(AgentsList.name, params);
|
|
546
|
+
yield* this.cacheAgentNames(result.agents);
|
|
547
|
+
for (const agent of result.agents)
|
|
548
|
+
missing.delete(agent.id);
|
|
549
|
+
if (missing.size === 0 || result.nextCursor === undefined)
|
|
550
|
+
return;
|
|
551
|
+
cursor = result.nextCursor;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
findVisibleAgentByName(agentName) {
|
|
556
|
+
return Effect.gen(this, function* () {
|
|
557
|
+
let cursor = undefined;
|
|
558
|
+
for (let page = 0; page < AGENT_LOOKUP_MAX_PAGES; page++) {
|
|
559
|
+
const params = this.agentListParams(cursor);
|
|
560
|
+
const result = yield* this.call(AgentsList.name, params);
|
|
561
|
+
yield* this.cacheAgentNames(result.agents);
|
|
562
|
+
const hit = result.agents.find((agent) => agent.name === agentName);
|
|
563
|
+
if (hit !== undefined || result.nextCursor === undefined)
|
|
564
|
+
return hit;
|
|
565
|
+
cursor = result.nextCursor;
|
|
566
|
+
}
|
|
567
|
+
return undefined;
|
|
571
568
|
});
|
|
572
569
|
}
|
|
573
570
|
// --- Cross-Conversation Context ---
|
|
@@ -672,12 +669,27 @@ export class MoltZapService {
|
|
|
672
669
|
this.handlers[notification].push(handler);
|
|
673
670
|
}
|
|
674
671
|
// --- RPC passthrough ---
|
|
675
|
-
|
|
672
|
+
/**
|
|
673
|
+
* Outbound RPC, typed per method — delegates to the agent client's typed
|
|
674
|
+
* `call`. `call("agent/identity/agents/list", payload)` recovers the result and that
|
|
675
|
+
* method's tagged-error union; an app-only method does not typecheck.
|
|
676
|
+
*/
|
|
677
|
+
call(tag, payload, opts) {
|
|
678
|
+
return Effect.suspend(() => {
|
|
679
|
+
const client = this.client;
|
|
680
|
+
if (!client) {
|
|
681
|
+
return Effect.fail(new NotConnectedError({ message: "Not connected" }));
|
|
682
|
+
}
|
|
683
|
+
return client.call(tag, payload, opts);
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
callDefinition(definition, payload, opts) {
|
|
676
687
|
return Effect.suspend(() => {
|
|
677
|
-
|
|
688
|
+
const client = this.client;
|
|
689
|
+
if (!client) {
|
|
678
690
|
return Effect.fail(new NotConnectedError({ message: "Not connected" }));
|
|
679
691
|
}
|
|
680
|
-
return
|
|
692
|
+
return client.callDefinition(definition, payload, opts);
|
|
681
693
|
});
|
|
682
694
|
}
|
|
683
695
|
// --- Internals ---
|
|
@@ -690,11 +702,46 @@ export class MoltZapService {
|
|
|
690
702
|
Effect.runFork(appendClientEventTrace(notificationTraceRecord(notification, this._ownAgentId)));
|
|
691
703
|
}
|
|
692
704
|
dispatchTypedNotification(notification) {
|
|
693
|
-
|
|
694
|
-
if (dispatch === undefined) {
|
|
705
|
+
if (this.dispatchMessageNotification(notification))
|
|
695
706
|
return;
|
|
707
|
+
if (this.dispatchConversationNotification(notification))
|
|
708
|
+
return;
|
|
709
|
+
this.dispatchAppNotification(notification);
|
|
710
|
+
}
|
|
711
|
+
dispatchMessageNotification(notification) {
|
|
712
|
+
if (isNotificationDeliveryFor(notification, MessageReceivedNotificationDefinition)) {
|
|
713
|
+
this.handleMessageReceivedNotification(notification.params);
|
|
714
|
+
return true;
|
|
715
|
+
}
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
dispatchConversationNotification(notification) {
|
|
719
|
+
if (isNotificationDeliveryFor(notification, ConversationCreatedNotificationDefinition)) {
|
|
720
|
+
this.handleConversationCreatedNotification(notification.params);
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
if (isNotificationDeliveryFor(notification, ConversationArchivedNotificationDefinition)) {
|
|
724
|
+
this.handleConversationArchivedNotification(notification.params);
|
|
725
|
+
return true;
|
|
726
|
+
}
|
|
727
|
+
if (isNotificationDeliveryFor(notification, ConversationUnarchivedNotificationDefinition)) {
|
|
728
|
+
this.handleConversationUnarchivedNotification(notification.params);
|
|
729
|
+
return true;
|
|
730
|
+
}
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
dispatchAppNotification(notification) {
|
|
734
|
+
if (isNotificationDeliveryFor(notification, DispatchRelease)) {
|
|
735
|
+
fanout(this.handlers.dispatchRelease, notification.params);
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (isNotificationDeliveryFor(notification, DispatchLeaseConsumed)) {
|
|
739
|
+
fanout(this.handlers.dispatchLeaseConsumed, notification.params);
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
if (isNotificationDeliveryFor(notification, DispatchLeaseExpired)) {
|
|
743
|
+
fanout(this.handlers.dispatchLeaseExpired, notification.params);
|
|
696
744
|
}
|
|
697
|
-
dispatch(notification);
|
|
698
745
|
}
|
|
699
746
|
/**
|
|
700
747
|
* Record `messageId` in the per-conversation dedup window. Returns
|
|
@@ -702,10 +749,10 @@ export class MoltZapService {
|
|
|
702
749
|
* a duplicate within the window (caller drops). On a new id, evicts
|
|
703
750
|
* the oldest entry if the window is full.
|
|
704
751
|
*
|
|
705
|
-
* Bound to the live `
|
|
752
|
+
* Bound to the live `agent/message/received` notification path: a single
|
|
706
753
|
* server-side broadcast that surfaces the same id twice (network
|
|
707
754
|
* replay, dual subscription) is suppressed to one
|
|
708
|
-
* `on("message", ...)` event. `
|
|
755
|
+
* `on("message", ...)` event. `agent/message/list` returns raw history
|
|
709
756
|
* unfiltered; consumers that combine both feeds dedup themselves.
|
|
710
757
|
*/
|
|
711
758
|
recordMessageIdIfNew(convId, msgId) {
|
|
@@ -719,7 +766,9 @@ export class MoltZapService {
|
|
|
719
766
|
}
|
|
720
767
|
if (dedupSet.size >= DEDUP_WINDOW_PER_CONV) {
|
|
721
768
|
// size >= 1 guaranteed by the guard above; next().value is defined.
|
|
722
|
-
dedupSet.
|
|
769
|
+
const oldest = dedupSet.keys().next();
|
|
770
|
+
if (!oldest.done)
|
|
771
|
+
dedupSet.delete(oldest.value);
|
|
723
772
|
}
|
|
724
773
|
dedupSet.add(msgId);
|
|
725
774
|
return true;
|