agent-comms 8.15.9 → 8.15.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/dist/bridges/user/web/server.d.ts.map +1 -1
- package/dist/bridges/user/web/server.js +44 -24
- package/dist/bridges/user/web/server.js.map +1 -1
- package/dist/bridges/user/web/test/web-assets.unit.test.d.ts +5 -0
- package/dist/bridges/user/web/test/web-assets.unit.test.d.ts.map +1 -0
- package/dist/bridges/user/web/test/web-assets.unit.test.js +90 -0
- package/dist/bridges/user/web/test/web-assets.unit.test.js.map +1 -0
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.d.ts +2 -0
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.d.ts.map +1 -0
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.js +75 -0
- package/dist/bridges/user/web/test/web-server-unbuilt-frontend.integration.test.js.map +1 -0
- package/dist/bridges/user/web/web-assets.d.ts +28 -0
- package/dist/bridges/user/web/web-assets.d.ts.map +1 -0
- package/dist/bridges/user/web/web-assets.js +67 -0
- package/dist/bridges/user/web/web-assets.js.map +1 -0
- package/dist/test/pi-manifest-packed.integration.test.d.ts +2 -0
- package/dist/test/pi-manifest-packed.integration.test.d.ts.map +1 -0
- package/dist/test/pi-manifest-packed.integration.test.js +68 -0
- package/dist/test/pi-manifest-packed.integration.test.js.map +1 -0
- package/package.json +8 -2
- package/src/account-cli.ts +195 -0
- package/src/account-join-cli.ts +191 -0
- package/src/bridges/cc-peer/approval-commands.ts +82 -0
- package/src/bridges/cc-peer/bridge.ts +138 -0
- package/src/bridges/cc-peer/default-front.ts +58 -0
- package/src/bridges/cc-peer/front-controller.ts +160 -0
- package/src/bridges/cc-peer/front-relay.ts +191 -0
- package/src/bridges/cc-peer/front-runtime.ts +167 -0
- package/src/bridges/cc-peer/front.ts +59 -0
- package/src/bridges/cc-peer/reply-aliases.ts +90 -0
- package/src/bridges/cc-peer/run.ts +100 -0
- package/src/bridges/cc-peer/shared-peer.ts +28 -0
- package/src/bridges/claude-code/channel.ts +318 -0
- package/src/bridges/codex/tool.ts +132 -0
- package/src/bridges/mcp/server.ts +137 -0
- package/src/bridges/opencode/plugin.ts +130 -0
- package/src/bridges/pi/extension.ts +330 -0
- package/src/bridges/registry.ts +17 -0
- package/src/bridges/user/cli.ts +87 -0
- package/src/bridges/user/controller.ts +345 -0
- package/src/bridges/user/tui.ts +300 -0
- package/src/bridges/user/web/actions.ts +173 -0
- package/src/bridges/user/web/contract.ts +222 -0
- package/src/bridges/user/web/dist/bundle.js +49 -0
- package/src/bridges/user/web/dist/icons/icon-192x192.svg +9 -0
- package/src/bridges/user/web/dist/icons/icon-512x512.svg +9 -0
- package/src/bridges/user/web/dist/icons/icon-96x96.svg +9 -0
- package/src/bridges/user/web/dist/index.html +21 -0
- package/src/bridges/user/web/dist/manifest.json +26 -0
- package/src/bridges/user/web/dist/mesh-worker.js +64 -0
- package/src/bridges/user/web/dist/sw.js +1 -0
- package/src/bridges/user/web/event-publisher.ts +114 -0
- package/src/bridges/user/web/port-discovery.ts +49 -0
- package/src/bridges/user/web/reads.ts +35 -0
- package/src/bridges/user/web/router.ts +158 -0
- package/src/bridges/user/web/server.ts +782 -0
- package/src/bridges/user/web/vite.config.ts +71 -0
- package/src/bridges/user/web/web-access.ts +404 -0
- package/src/bridges/user/web/web-assets.ts +90 -0
- package/src/bridges/user/web/web-beacon.ts +69 -0
- package/src/bridges/user/web/web-console-static.ts +90 -0
- package/src/cli-main.ts +635 -0
- package/src/cli.ts +13 -0
- package/src/core/account-bundle.ts +264 -0
- package/src/core/account-join.ts +289 -0
- package/src/core/account-ledger-crypto.ts +154 -0
- package/src/core/account-ledger-store.ts +66 -0
- package/src/core/account-ledger.ts +385 -0
- package/src/core/agent-details.ts +216 -0
- package/src/core/agent-list-format.ts +97 -0
- package/src/core/agent-registry.ts +282 -0
- package/src/core/agent-table.ts +58 -0
- package/src/core/atomic-file.ts +46 -0
- package/src/core/bind-retry.ts +38 -0
- package/src/core/bridge-mesh.ts +176 -0
- package/src/core/bridge.ts +718 -0
- package/src/core/capability-ask.ts +162 -0
- package/src/core/capability-bubble-up.ts +237 -0
- package/src/core/comms-store.ts +130 -0
- package/src/core/connection-approval.ts +134 -0
- package/src/core/connection-code-tool.ts +92 -0
- package/src/core/connection-code.ts +296 -0
- package/src/core/coordinator-role.ts +224 -0
- package/src/core/data-directory.ts +32 -0
- package/src/core/data-frame-routing.ts +309 -0
- package/src/core/default-command.ts +12 -0
- package/src/core/delegation-policy.ts +41 -0
- package/src/core/delivery-engine.ts +649 -0
- package/src/core/device-membership-verification.ts +125 -0
- package/src/core/device-membership.ts +130 -0
- package/src/core/directory-admission.ts +155 -0
- package/src/core/discovery-mdns.ts +247 -0
- package/src/core/discovery-tailscale.ts +224 -0
- package/src/core/discovery.ts +303 -0
- package/src/core/display-name.ts +73 -0
- package/src/core/dm-grant-actions.ts +72 -0
- package/src/core/dm-send-delegation.ts +73 -0
- package/src/core/dm-token-verification.ts +76 -0
- package/src/core/election-sessions.ts +135 -0
- package/src/core/error-reporting.ts +85 -0
- package/src/core/first-contact.ts +242 -0
- package/src/core/gateway-trust-actions.ts +184 -0
- package/src/core/gateway-trust.ts +305 -0
- package/src/core/gossip-directory.ts +276 -0
- package/src/core/gossip-extensions.ts +123 -0
- package/src/core/group-proofs.ts +205 -0
- package/src/core/handshake.ts +354 -0
- package/src/core/hub-forwarding.ts +24 -0
- package/src/core/hub-link.ts +176 -0
- package/src/core/hub-session.ts +374 -0
- package/src/core/identity-store.ts +715 -0
- package/src/core/identity.ts +489 -0
- package/src/core/index.ts +65 -0
- package/src/core/issuer-grouping.ts +165 -0
- package/src/core/issuer-identity-file.ts +187 -0
- package/src/core/lan-web-actions.ts +34 -0
- package/src/core/lan-web-uis.ts +55 -0
- package/src/core/ledger-lock.ts +81 -0
- package/src/core/listener-registry.ts +133 -0
- package/src/core/loopback-address.ts +22 -0
- package/src/core/machine-identity.ts +77 -0
- package/src/core/machine-list-groups.ts +53 -0
- package/src/core/mcp-registry-retry.ts +69 -0
- package/src/core/mcp-registry-version.ts +18 -0
- package/src/core/membership-proof.ts +139 -0
- package/src/core/membership-proofs.ts +149 -0
- package/src/core/mesh-graph-trace-tool.ts +81 -0
- package/src/core/mesh-graph.ts +89 -0
- package/src/core/mesh-network-actions.ts +183 -0
- package/src/core/mesh-store-options.ts +23 -0
- package/src/core/mesh-store-shared.ts +134 -0
- package/src/core/mesh-store.ts +1114 -0
- package/src/core/name-claim.ts +145 -0
- package/src/core/naming-actions.ts +90 -0
- package/src/core/naming.ts +138 -0
- package/src/core/nanoid.ts +20 -0
- package/src/core/network-interfaces.ts +24 -0
- package/src/core/package-version.ts +34 -0
- package/src/core/peer-lifecycle.ts +377 -0
- package/src/core/peer-link-error.ts +41 -0
- package/src/core/peer-versions.ts +98 -0
- package/src/core/pending-connection.ts +53 -0
- package/src/core/petnames.ts +121 -0
- package/src/core/pgp-keyserver.ts +32 -0
- package/src/core/pid-lock-file.ts +122 -0
- package/src/core/push-manager.ts +76 -0
- package/src/core/random-id.ts +9 -0
- package/src/core/receiver-set.ts +42 -0
- package/src/core/relay-role.ts +182 -0
- package/src/core/relay-selection.ts +120 -0
- package/src/core/relay-server.ts +198 -0
- package/src/core/relay-uplink.ts +78 -0
- package/src/core/request-timeouts.ts +37 -0
- package/src/core/room-discovery.ts +48 -0
- package/src/core/room-lifecycle.ts +838 -0
- package/src/core/room-lookup.ts +41 -0
- package/src/core/room-messaging.ts +247 -0
- package/src/core/room-notice-log.ts +61 -0
- package/src/core/room-path.ts +84 -0
- package/src/core/room-protocol.ts +893 -0
- package/src/core/room-router.ts +180 -0
- package/src/core/room-token-verification.ts +85 -0
- package/src/core/room-wire-extensions.ts +60 -0
- package/src/core/self-name-claim.ts +67 -0
- package/src/core/send-outcome.ts +69 -0
- package/src/core/shutdown-signals.ts +57 -0
- package/src/core/stale-agent-checker.ts +108 -0
- package/src/core/store.ts +704 -0
- package/src/core/token-text.ts +40 -0
- package/src/core/tool.ts +853 -0
- package/src/core/transport-events.ts +73 -0
- package/src/core/transport-queries.ts +54 -0
- package/src/core/transport.ts +367 -0
- package/src/core/types.ts +550 -0
- package/src/core/user-identity.ts +290 -0
- package/src/core/vapid.ts +81 -0
- package/src/core/version-check.ts +147 -0
- package/src/core/version-report-actions.ts +79 -0
- package/src/core/web-beacon.ts +31 -0
- package/src/core/web-push.ts +322 -0
- package/src/core/wire-mesh-core-version.ts +25 -0
- package/src/core/wire-mesh-identity.ts +36 -0
- package/src/core/wire-mesh-transport-options.ts +82 -0
- package/src/core/wire-mesh-transport.ts +1007 -0
- package/src/core/wire-protocol.ts +153 -0
- package/src/core/ws-dial.ts +191 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain action functions -- one per browser-facing action, extracted from server.ts's executeAction switch so both the legacy /api/action REST dispatcher and the new oRPC router call the same implementation instead of two copies drifting apart.
|
|
3
|
+
*
|
|
4
|
+
* Each function preserves executeAction's exact prior validation behaviour (empty string treated the same as missing) even though the oRPC contract's own Zod schemas already enforce presence and type -- the contract validates shape, these functions still validate the same business rules the REST path has always enforced.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { PushManager } from "../../../core/push-manager.js";
|
|
8
|
+
import type { PushSubscription } from "../../../core/web-push.js";
|
|
9
|
+
import type { ChatController } from "../controller.js";
|
|
10
|
+
import type { ActionResult } from "./contract.js";
|
|
11
|
+
|
|
12
|
+
export async function sendAction(
|
|
13
|
+
controller: ChatController,
|
|
14
|
+
input: Readonly<{ target: string; content: string }>,
|
|
15
|
+
): Promise<ActionResult> {
|
|
16
|
+
if (input.target === "" || input.content === "") {
|
|
17
|
+
return { content: "Missing target or content", isError: true };
|
|
18
|
+
}
|
|
19
|
+
return controller.send(input.target, input.content);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function dmAction(
|
|
23
|
+
controller: ChatController,
|
|
24
|
+
input: Readonly<{ target: string; content: string }>,
|
|
25
|
+
): Promise<ActionResult> {
|
|
26
|
+
if (input.target === "" || input.content === "") {
|
|
27
|
+
return { content: "Missing target or content", isError: true };
|
|
28
|
+
}
|
|
29
|
+
return controller.dm(input.target, input.content);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function joinRoomAction(
|
|
33
|
+
controller: ChatController,
|
|
34
|
+
input: Readonly<{ room: string }>,
|
|
35
|
+
): Promise<ActionResult> {
|
|
36
|
+
if (input.room === "") return { content: "Missing room", isError: true };
|
|
37
|
+
const result = await controller.switchRoom(input.room);
|
|
38
|
+
if (!result.isError) {
|
|
39
|
+
const msgs = await controller.readRoom();
|
|
40
|
+
return { content: `${result.content}\n${msgs.content}`, isError: false };
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function leaveRoomAction(
|
|
46
|
+
controller: ChatController,
|
|
47
|
+
input: Readonly<{ room?: string | undefined }>,
|
|
48
|
+
): Promise<ActionResult> {
|
|
49
|
+
return controller.leaveRoom(input.room);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export async function createRoomAction(
|
|
53
|
+
controller: ChatController,
|
|
54
|
+
input: Readonly<{
|
|
55
|
+
name: string;
|
|
56
|
+
type: "public" | "private" | "secret";
|
|
57
|
+
description?: string | undefined;
|
|
58
|
+
}>,
|
|
59
|
+
): Promise<ActionResult> {
|
|
60
|
+
if (input.name === "") return { content: "Missing name", isError: true };
|
|
61
|
+
return controller.createRoom(input.name, {
|
|
62
|
+
type: input.type,
|
|
63
|
+
description: input.description ?? "",
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function listRoomsAction(
|
|
68
|
+
controller: ChatController,
|
|
69
|
+
): Promise<ActionResult> {
|
|
70
|
+
return controller.listRooms();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function listAgentsAction(
|
|
74
|
+
controller: ChatController,
|
|
75
|
+
): Promise<ActionResult> {
|
|
76
|
+
return controller.listAgents();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export async function readRoomAction(
|
|
80
|
+
controller: ChatController,
|
|
81
|
+
input: Readonly<{ room?: string | undefined }>,
|
|
82
|
+
): Promise<ActionResult> {
|
|
83
|
+
return controller.readRoom({ roomId: input.room });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export async function destroyRoomAction(
|
|
87
|
+
controller: ChatController,
|
|
88
|
+
input: Readonly<{ room: string }>,
|
|
89
|
+
): Promise<ActionResult> {
|
|
90
|
+
if (input.room === "") return { content: "Missing room", isError: true };
|
|
91
|
+
return controller.destroyRoom(input.room);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export async function inviteAction(
|
|
95
|
+
controller: ChatController,
|
|
96
|
+
input: Readonly<{ room: string; agent: string }>,
|
|
97
|
+
): Promise<ActionResult> {
|
|
98
|
+
if (input.room === "" || input.agent === "") {
|
|
99
|
+
return { content: "Missing room or agent", isError: true };
|
|
100
|
+
}
|
|
101
|
+
return controller.invite(input.room, input.agent);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function declineInviteAction(
|
|
105
|
+
controller: ChatController,
|
|
106
|
+
input: Readonly<{ room: string; reason: string }>,
|
|
107
|
+
): Promise<ActionResult> {
|
|
108
|
+
if (input.room === "" || input.reason === "") {
|
|
109
|
+
return { content: "Missing room or reason", isError: true };
|
|
110
|
+
}
|
|
111
|
+
return controller.declineInvite(input.room, input.reason);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function kickAction(
|
|
115
|
+
controller: ChatController,
|
|
116
|
+
input: Readonly<{ room: string; agent: string }>,
|
|
117
|
+
): Promise<ActionResult> {
|
|
118
|
+
if (input.room === "" || input.agent === "") {
|
|
119
|
+
return { content: "Missing room or agent", isError: true };
|
|
120
|
+
}
|
|
121
|
+
return controller.kick(input.room, input.agent);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function renameAgentAction(
|
|
125
|
+
controller: ChatController,
|
|
126
|
+
input: Readonly<{ agent: string; name: string }>,
|
|
127
|
+
): Promise<ActionResult> {
|
|
128
|
+
if (input.agent === "" || input.name === "") {
|
|
129
|
+
return { content: "Missing agent or name", isError: true };
|
|
130
|
+
}
|
|
131
|
+
return controller.renameAgent(input.agent, input.name);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function isPushSubscription(value: unknown): value is PushSubscription {
|
|
135
|
+
if (typeof value !== "object" || value === null) return false;
|
|
136
|
+
if (!("endpoint" in value) || typeof value.endpoint !== "string")
|
|
137
|
+
return false;
|
|
138
|
+
if (!("keys" in value)) return false;
|
|
139
|
+
const keys = value.keys;
|
|
140
|
+
if (typeof keys !== "object" || keys === null) return false;
|
|
141
|
+
if (!("p256dh" in keys) || typeof keys.p256dh !== "string") return false;
|
|
142
|
+
if (!("auth" in keys) || typeof keys.auth !== "string") return false;
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function pushSubscribeAction(
|
|
147
|
+
controller: ChatController,
|
|
148
|
+
pushManager: PushManager | undefined,
|
|
149
|
+
input: Readonly<{ subscription: unknown; agentId?: string | undefined }>,
|
|
150
|
+
): ActionResult {
|
|
151
|
+
if (!pushManager) {
|
|
152
|
+
return { content: "Push notifications unavailable", isError: true };
|
|
153
|
+
}
|
|
154
|
+
if (!isPushSubscription(input.subscription)) {
|
|
155
|
+
return { content: "Invalid push subscription", isError: true };
|
|
156
|
+
}
|
|
157
|
+
const agentId = input.agentId ?? controller.agentId;
|
|
158
|
+
pushManager.addSubscription(agentId, input.subscription);
|
|
159
|
+
return { content: "Push subscription registered", isError: false };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export function pushUnsubscribeAction(
|
|
163
|
+
controller: ChatController,
|
|
164
|
+
pushManager: PushManager | undefined,
|
|
165
|
+
input: Readonly<{ agentId?: string | undefined }>,
|
|
166
|
+
): ActionResult {
|
|
167
|
+
if (!pushManager) {
|
|
168
|
+
return { content: "Push notifications unavailable", isError: true };
|
|
169
|
+
}
|
|
170
|
+
const agentId = input.agentId ?? controller.agentId;
|
|
171
|
+
pushManager.removeSubscription(agentId);
|
|
172
|
+
return { content: "Push subscription removed", isError: false };
|
|
173
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* oRPC contract for the web UI's browser-to-server protocol.
|
|
3
|
+
*
|
|
4
|
+
* One procedure per browser-facing action, plus a single `subscribeEvents` procedure that unifies what the JSON-over-WebSocket protocol split across three separate concepts: the chat socket's `delivery` frames, the mesh socket's `state_sync` method, and its `state_update` method. Entity and delivery-event shapes are imported from core/types.ts rather than re-declared here -- core already carries the single source of truth Zod schema for each (AgentIdentitySchema, RoomSchema, RoomMessageSchema, DmMessageSchema, DeliveryEventSchema), and duplicating them a third time (frontend/types.ts's hand-written interfaces are the second copy) is exactly the kind of drift that let frontend/mesh-worker.ts's local MeshStatePatch keep a "message_read" variant the real server stopped emitting once room.read replaced the old mesh-wide broadcast.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { oc, eventIterator } from "@orpc/contract";
|
|
9
|
+
import {
|
|
10
|
+
AgentIdentitySchema,
|
|
11
|
+
RoomSchema,
|
|
12
|
+
RoomMessageSchema,
|
|
13
|
+
DmMessageSchema,
|
|
14
|
+
DeliveryEventSchema,
|
|
15
|
+
} from "../../../core/types.js";
|
|
16
|
+
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Shared fragments
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
const ActionResultSchema = z.object({
|
|
22
|
+
content: z.string(),
|
|
23
|
+
isError: z.boolean(),
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const RoomTypeSchema = z.union([
|
|
27
|
+
z.literal("public"),
|
|
28
|
+
z.literal("private"),
|
|
29
|
+
z.literal("secret"),
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Mesh graph and path trace -- mirrors core/transport.ts's MeshGraph/MeshTraceResult shape, the same "mirror, don't import" precedent as MeshStatePatchSchema above (core's own interfaces aren't Zod-backed, and don't need to be for their many non-browser callers). MeshTraceResult.outcome is wire-mesh-core's own ManageOutcome, an external union this contract has no reason to model in full -- only the two fields the UI actually reads (result, code) are validated; everything else on the outcome object passes through unchecked.
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
const MeshGraphEdgeSchema = z.object({
|
|
37
|
+
kind: z.union([z.literal("direct"), z.literal("relay")]),
|
|
38
|
+
from: z.string(),
|
|
39
|
+
to: z.string(),
|
|
40
|
+
via: z.string().optional(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const MeshGraphSchema = z.object({
|
|
44
|
+
nodes: z.array(z.string()),
|
|
45
|
+
edges: z.array(MeshGraphEdgeSchema),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
/** One id's names, as display-name.ts's DisplayNameParts: the parts the dashboard formats with formatDisplayName. */
|
|
49
|
+
const DisplayNamePartsSchema = z.object({
|
|
50
|
+
id: z.string(),
|
|
51
|
+
petname: z.string().optional(),
|
|
52
|
+
selfName: z.string().optional(),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const MeshTraceSideSchema = z.object({
|
|
56
|
+
relayed: z.boolean(),
|
|
57
|
+
hubAddress: z.string().optional(),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const MeshTraceResultSchema = z.object({
|
|
61
|
+
rttMs: z.number(),
|
|
62
|
+
local: MeshTraceSideSchema,
|
|
63
|
+
remote: MeshTraceSideSchema.optional(),
|
|
64
|
+
outcome: z
|
|
65
|
+
.object({ result: z.string(), code: z.string().optional() })
|
|
66
|
+
.loose(),
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Mesh state patch -- mirrors core/wire-protocol.ts's MeshStatePatch exactly (7 variants; no "message_read", which room.read/P3.5 already replaced).
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
|
|
73
|
+
const MeshStatePatchSchema = z.discriminatedUnion("type", [
|
|
74
|
+
z.object({ type: z.literal("agent_upsert"), agent: AgentIdentitySchema }),
|
|
75
|
+
z.object({ type: z.literal("agent_offline"), agentId: z.string() }),
|
|
76
|
+
z.object({ type: z.literal("room_upsert"), room: RoomSchema }),
|
|
77
|
+
z.object({ type: z.literal("room_delete"), roomId: z.string() }),
|
|
78
|
+
z.object({
|
|
79
|
+
type: z.literal("message_add"),
|
|
80
|
+
roomId: z.string(),
|
|
81
|
+
message: RoomMessageSchema,
|
|
82
|
+
}),
|
|
83
|
+
z.object({
|
|
84
|
+
type: z.literal("dm_add"),
|
|
85
|
+
key: z.string(),
|
|
86
|
+
message: DmMessageSchema,
|
|
87
|
+
}),
|
|
88
|
+
z.object({
|
|
89
|
+
type: z.literal("delivery"),
|
|
90
|
+
agentId: z.string(),
|
|
91
|
+
event: DeliveryEventSchema,
|
|
92
|
+
}),
|
|
93
|
+
]);
|
|
94
|
+
|
|
95
|
+
const SerialisedStateSchema = z.object({
|
|
96
|
+
agents: z.record(z.string(), AgentIdentitySchema),
|
|
97
|
+
rooms: z.record(z.string(), RoomSchema),
|
|
98
|
+
messages: z.record(z.string(), z.array(RoomMessageSchema)),
|
|
99
|
+
dms: z.record(z.string(), z.array(DmMessageSchema)),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The one stream every tab subscribes to. Unifies state_sync (a full snapshot, sent once on connect or resume-without-lastEventId), state_update (an incremental patch), and the old chat socket's delivery frames -- today three separate wire concepts -- into a single ordered event stream a tab can resume by lastEventId.
|
|
104
|
+
*/
|
|
105
|
+
const MeshEventSchema = z.discriminatedUnion("kind", [
|
|
106
|
+
z.object({ kind: z.literal("state_sync"), state: SerialisedStateSchema }),
|
|
107
|
+
z.object({ kind: z.literal("state_patch"), patch: MeshStatePatchSchema }),
|
|
108
|
+
z.object({ kind: z.literal("delivery"), event: DeliveryEventSchema }),
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Push subscription (PWA)
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
const PushSubscriptionSchema = z.object({
|
|
116
|
+
endpoint: z.string(),
|
|
117
|
+
keys: z.object({ p256dh: z.string(), auth: z.string() }),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// ---------------------------------------------------------------------------
|
|
121
|
+
// Contract
|
|
122
|
+
// ---------------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
export const meshContract = {
|
|
125
|
+
send: oc
|
|
126
|
+
.input(z.object({ target: z.string(), content: z.string() }))
|
|
127
|
+
.output(ActionResultSchema),
|
|
128
|
+
|
|
129
|
+
dm: oc
|
|
130
|
+
.input(z.object({ target: z.string(), content: z.string() }))
|
|
131
|
+
.output(ActionResultSchema),
|
|
132
|
+
|
|
133
|
+
joinRoom: oc.input(z.object({ room: z.string() })).output(ActionResultSchema),
|
|
134
|
+
|
|
135
|
+
leaveRoom: oc
|
|
136
|
+
.input(z.object({ room: z.string().optional() }))
|
|
137
|
+
.output(ActionResultSchema),
|
|
138
|
+
|
|
139
|
+
createRoom: oc
|
|
140
|
+
.input(
|
|
141
|
+
z.object({
|
|
142
|
+
name: z.string(),
|
|
143
|
+
type: RoomTypeSchema,
|
|
144
|
+
description: z.string().optional(),
|
|
145
|
+
}),
|
|
146
|
+
)
|
|
147
|
+
.output(ActionResultSchema),
|
|
148
|
+
|
|
149
|
+
listRooms: oc.input(z.object({})).output(ActionResultSchema),
|
|
150
|
+
|
|
151
|
+
listAgents: oc.input(z.object({})).output(ActionResultSchema),
|
|
152
|
+
|
|
153
|
+
readRoom: oc
|
|
154
|
+
.input(z.object({ room: z.string().optional() }))
|
|
155
|
+
.output(ActionResultSchema),
|
|
156
|
+
|
|
157
|
+
destroyRoom: oc
|
|
158
|
+
.input(z.object({ room: z.string() }))
|
|
159
|
+
.output(ActionResultSchema),
|
|
160
|
+
|
|
161
|
+
invite: oc
|
|
162
|
+
.input(z.object({ room: z.string(), agent: z.string() }))
|
|
163
|
+
.output(ActionResultSchema),
|
|
164
|
+
|
|
165
|
+
declineInvite: oc
|
|
166
|
+
.input(z.object({ room: z.string(), reason: z.string() }))
|
|
167
|
+
.output(ActionResultSchema),
|
|
168
|
+
|
|
169
|
+
kick: oc
|
|
170
|
+
.input(z.object({ room: z.string(), agent: z.string() }))
|
|
171
|
+
.output(ActionResultSchema),
|
|
172
|
+
|
|
173
|
+
renameAgent: oc
|
|
174
|
+
.input(z.object({ agent: z.string(), name: z.string() }))
|
|
175
|
+
.output(ActionResultSchema),
|
|
176
|
+
|
|
177
|
+
pushSubscribe: oc
|
|
178
|
+
.input(
|
|
179
|
+
z.object({
|
|
180
|
+
subscription: PushSubscriptionSchema,
|
|
181
|
+
agentId: z.string().optional(),
|
|
182
|
+
}),
|
|
183
|
+
)
|
|
184
|
+
.output(ActionResultSchema),
|
|
185
|
+
|
|
186
|
+
pushUnsubscribe: oc
|
|
187
|
+
.input(z.object({ agentId: z.string().optional() }))
|
|
188
|
+
.output(ActionResultSchema),
|
|
189
|
+
|
|
190
|
+
subscribeEvents: oc
|
|
191
|
+
.input(z.object({ lastEventId: z.string().optional() }))
|
|
192
|
+
.output(eventIterator(MeshEventSchema)),
|
|
193
|
+
|
|
194
|
+
// -------------------------------------------------------------------------
|
|
195
|
+
// Structured one-shot reads (agent-comms#206) -- genuinely request/response data with no real-time channel of its own, unlike agents/rooms (already fully covered by subscribeEvents' state_sync/state_patch above, so deliberately not duplicated here as a read procedure). Distinct from listRooms/listAgents/readRoom above, which are the legacy CLI-text-command equivalents (ActionResult output, for chat-style /list and /read commands) -- these return real structured JSON, the same shape the REST endpoints they share an implementation with already return.
|
|
196
|
+
// -------------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
getRoomMessages: oc
|
|
199
|
+
.input(z.object({ room: z.string(), since: z.string().optional() }))
|
|
200
|
+
.output(z.array(RoomMessageSchema)),
|
|
201
|
+
|
|
202
|
+
getMeshGraph: oc.input(z.object({})).output(MeshGraphSchema),
|
|
203
|
+
|
|
204
|
+
getDisplayNames: oc
|
|
205
|
+
.input(z.object({}))
|
|
206
|
+
.output(z.array(DisplayNamePartsSchema)),
|
|
207
|
+
|
|
208
|
+
getMeshTrace: oc
|
|
209
|
+
.input(z.object({ target: z.string(), timeoutMs: z.number().optional() }))
|
|
210
|
+
.output(MeshTraceResultSchema),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export type MeshEvent = z.infer<typeof MeshEventSchema>;
|
|
214
|
+
export type MeshStatePatch = z.infer<typeof MeshStatePatchSchema>;
|
|
215
|
+
export type SerialisedState = z.infer<typeof SerialisedStateSchema>;
|
|
216
|
+
export type ActionResult = z.infer<typeof ActionResultSchema>;
|
|
217
|
+
export type MeshGraph = z.infer<typeof MeshGraphSchema>;
|
|
218
|
+
export type DisplayNamePartsWire = z.infer<typeof DisplayNamePartsSchema>;
|
|
219
|
+
export type MeshTraceResult = z.infer<typeof MeshTraceResultSchema>;
|
|
220
|
+
|
|
221
|
+
/** Type-only handle onto the contract's shape for building a typed client (`ContractRouterClient<MeshContract>`) without importing the contract's own runtime value -- browser code that only needs the type (mesh-worker.ts, mesh-client.ts) can `import type` this and never bundle Zod/core's schemas at all, since a type-only import is erased entirely at build time. */
|
|
222
|
+
export type MeshContract = typeof meshContract;
|