remote-pi 0.1.2 → 0.2.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/README.md +195 -36
- package/dist/bin/supervisord.d.ts +2 -0
- package/dist/bin/supervisord.js +44 -0
- package/dist/bin/supervisord.js.map +1 -0
- package/dist/config.d.ts +49 -5
- package/dist/config.js +73 -9
- package/dist/config.js.map +1 -1
- package/dist/daemon/client.d.ts +20 -0
- package/dist/daemon/client.js +128 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +100 -0
- package/dist/daemon/control_protocol.js +63 -0
- package/dist/daemon/control_protocol.js.map +1 -0
- package/dist/daemon/id.d.ts +18 -0
- package/dist/daemon/id.js +30 -0
- package/dist/daemon/id.js.map +1 -0
- package/dist/daemon/install.d.ts +132 -0
- package/dist/daemon/install.js +312 -0
- package/dist/daemon/install.js.map +1 -0
- package/dist/daemon/registry.d.ts +47 -0
- package/dist/daemon/registry.js +123 -0
- package/dist/daemon/registry.js.map +1 -0
- package/dist/daemon/rpc_child.d.ts +76 -0
- package/dist/daemon/rpc_child.js +130 -0
- package/dist/daemon/rpc_child.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +38 -0
- package/dist/daemon/supervisor.js +301 -0
- package/dist/daemon/supervisor.js.map +1 -0
- package/dist/index.d.ts +62 -8
- package/dist/index.js +1232 -304
- package/dist/index.js.map +1 -1
- package/dist/mesh/canonical.d.ts +30 -0
- package/dist/mesh/canonical.js +61 -0
- package/dist/mesh/canonical.js.map +1 -0
- package/dist/mesh/client.d.ts +31 -0
- package/dist/mesh/client.js +56 -0
- package/dist/mesh/client.js.map +1 -0
- package/dist/mesh/encoding.d.ts +36 -0
- package/dist/mesh/encoding.js +53 -0
- package/dist/mesh/encoding.js.map +1 -0
- package/dist/mesh/self_revoke.d.ts +111 -0
- package/dist/mesh/self_revoke.js +182 -0
- package/dist/mesh/self_revoke.js.map +1 -0
- package/dist/mesh/siblings.d.ts +62 -0
- package/dist/mesh/siblings.js +95 -0
- package/dist/mesh/siblings.js.map +1 -0
- package/dist/mesh/types.d.ts +34 -0
- package/dist/mesh/types.js +11 -0
- package/dist/mesh/types.js.map +1 -0
- package/dist/mesh/verify.d.ts +17 -0
- package/dist/mesh/verify.js +77 -0
- package/dist/mesh/verify.js.map +1 -0
- package/dist/pairing/qr.d.ts +16 -5
- package/dist/pairing/qr.js +27 -8
- package/dist/pairing/qr.js.map +1 -1
- package/dist/pairing/storage.d.ts +41 -0
- package/dist/pairing/storage.js +158 -21
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +23 -0
- package/dist/session/broker.d.ts +74 -0
- package/dist/session/broker.js +142 -4
- package/dist/session/broker.js.map +1 -1
- package/dist/session/broker_remote.d.ts +110 -0
- package/dist/session/broker_remote.js +397 -0
- package/dist/session/broker_remote.js.map +1 -0
- package/dist/session/cwd_lock.d.ts +28 -0
- package/dist/session/cwd_lock.js +89 -0
- package/dist/session/cwd_lock.js.map +1 -0
- package/dist/session/global_config.d.ts +9 -0
- package/dist/session/global_config.js +9 -0
- package/dist/session/global_config.js.map +1 -1
- package/dist/session/leader_election.d.ts +16 -0
- package/dist/session/leader_election.js +22 -0
- package/dist/session/leader_election.js.map +1 -1
- package/dist/session/local_config.d.ts +12 -5
- package/dist/session/local_config.js +24 -3
- package/dist/session/local_config.js.map +1 -1
- package/dist/session/peer.d.ts +28 -1
- package/dist/session/peer.js +69 -2
- package/dist/session/peer.js.map +1 -1
- package/dist/session/peer_inventory.d.ts +13 -0
- package/dist/session/peer_inventory.js +48 -0
- package/dist/session/peer_inventory.js.map +1 -0
- package/dist/session/setup_wizard.d.ts +32 -8
- package/dist/session/setup_wizard.js +45 -33
- package/dist/session/setup_wizard.js.map +1 -1
- package/dist/session/tools.d.ts +15 -7
- package/dist/session/tools.js +145 -31
- package/dist/session/tools.js.map +1 -1
- package/dist/transport/pi_forward_client.d.ts +29 -0
- package/dist/transport/pi_forward_client.js +62 -0
- package/dist/transport/pi_forward_client.js.map +1 -0
- package/dist/ui/footer.js +8 -6
- package/dist/ui/footer.js.map +1 -1
- package/docs/daemon.md +289 -0
- package/package.json +10 -3
- package/service-templates/launchd.plist.template +35 -0
- package/service-templates/systemd.service.template +19 -0
- package/skills/agent-network/SKILL.md +273 -294
package/dist/session/tools.js
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
1
|
import { Type } from "typebox";
|
|
2
2
|
const NOT_IN_SESSION = "Not in a session. Run /remote-pi join first";
|
|
3
|
-
const
|
|
3
|
+
const ACK_TIMEOUT_MS = 5_000;
|
|
4
|
+
const LEGACY_REQUEST_TIMEOUT_MS = 30_000;
|
|
5
|
+
const LIST_PEERS_TIMEOUT_MS = 2_000;
|
|
4
6
|
/**
|
|
5
|
-
* Registers
|
|
6
|
-
*
|
|
7
|
-
* - `agent_send` — fire-and-forget delivery
|
|
8
|
-
* - `agent_request` — request/reply with `re` correlation + timeout
|
|
7
|
+
* Registers the native tools the Pi LLM uses to talk to other agents in the
|
|
8
|
+
* same UDS session (plano 19 transport + plan/25 Wave 0 ACK protocol):
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* - `agent_send` — unified delivery with broker-level ACK. Returns
|
|
11
|
+
* a status so the LLM can decide whether to retry.
|
|
12
|
+
* For unicast targets the broker auto-replies with
|
|
13
|
+
* `received | busy | denied`. For broadcast/multicast
|
|
14
|
+
* the tool is fire-and-forget (status `sent`).
|
|
15
|
+
* - `agent_request` — **deprecated**. Still works (send + block on reply
|
|
16
|
+
* via `re` correlation) but the LLM should migrate
|
|
17
|
+
* to the event-driven send+inbox pattern. Each call
|
|
18
|
+
* emits a one-shot warning to stderr.
|
|
19
|
+
*
|
|
20
|
+
* Reply pattern (new world): when you receive a message you want to answer,
|
|
21
|
+
* send back another envelope with `re=<original-id>`. The original sender
|
|
22
|
+
* sees that reply in its inbox during a future turn.
|
|
13
23
|
*
|
|
14
24
|
* `getSessionPeer` is a getter (not a captured value) so changes to the
|
|
15
25
|
* underlying `_sessionPeer` module variable are observed live.
|
|
16
26
|
*/
|
|
17
27
|
export function registerAgentTools(pi, getSessionPeer) {
|
|
18
28
|
const SendParams = Type.Object({
|
|
19
|
-
to: Type.String({
|
|
29
|
+
to: Type.String({
|
|
30
|
+
description: "Recipient agent name (e.g. 'backend'), 'broadcast', or array of names. " +
|
|
31
|
+
"Broadcast/multicast are fire-and-forget; unicast returns an ACK status.",
|
|
32
|
+
}),
|
|
20
33
|
body: Type.Unknown({ description: "Free-form JSON payload. String or object — your choice." }),
|
|
21
34
|
re: Type.Optional(Type.String({
|
|
22
|
-
description: "
|
|
23
|
-
"
|
|
24
|
-
"without it, the sender's pending request times out. Skip for unsolicited sends.",
|
|
35
|
+
description: "Set this to the `id` of an incoming message when you are REPLYING to it. " +
|
|
36
|
+
"The peer correlates your answer with their original send via this field.",
|
|
25
37
|
})),
|
|
26
38
|
});
|
|
27
39
|
const RequestParams = Type.Object({
|
|
@@ -34,54 +46,141 @@ export function registerAgentTools(pi, getSessionPeer) {
|
|
|
34
46
|
pi.registerTool({
|
|
35
47
|
name: "agent_send",
|
|
36
48
|
label: "Agent Send",
|
|
37
|
-
description: "Send a message to another Pi agent in the current local session
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
49
|
+
description: "Send a message to another Pi agent in the current local session and " +
|
|
50
|
+
"wait for the broker's delivery ACK. Returns one of: `received` (peer " +
|
|
51
|
+
"was idle, will process in its next turn), `busy` (peer mid-turn, " +
|
|
52
|
+
"message dropped — you own the retry), `denied` (peer refused), " +
|
|
53
|
+
"`timeout` (no ACK in 5s — treat as transport error), `sent` " +
|
|
54
|
+
"(broadcast/multicast — no ACK semantics). Use `re` to mark this " +
|
|
55
|
+
"message as a reply to an incoming envelope's `id`.",
|
|
56
|
+
promptSnippet: "agent_send({to, body, re?}): unicast → returns {status: received|busy|denied|timeout}. Broadcast/multicast → fire-and-forget ({status:'sent'}).",
|
|
43
57
|
parameters: SendParams,
|
|
44
58
|
execute: async (_toolCallId, params) => {
|
|
45
59
|
const peer = getSessionPeer();
|
|
46
60
|
if (!peer) {
|
|
61
|
+
const details = { status: "refused", ok: false, error: NOT_IN_SESSION };
|
|
47
62
|
return {
|
|
48
63
|
content: [{ type: "text", text: NOT_IN_SESSION }],
|
|
49
|
-
details
|
|
64
|
+
details,
|
|
50
65
|
};
|
|
51
66
|
}
|
|
52
67
|
const { to, body, re } = params;
|
|
53
68
|
if (to === peer.name()) {
|
|
54
69
|
const msg = `Refused: cannot agent_send to yourself ("${to}"). Just do the work directly.`;
|
|
70
|
+
const details = { status: "refused", ok: false, error: msg };
|
|
55
71
|
return {
|
|
56
72
|
content: [{ type: "text", text: msg }],
|
|
57
|
-
details
|
|
73
|
+
details,
|
|
58
74
|
};
|
|
59
75
|
}
|
|
76
|
+
const isUnicast = to !== "broadcast";
|
|
77
|
+
// Broadcast: fire-and-forget. Broker doesn't ACK multi-target sends.
|
|
78
|
+
if (!isUnicast) {
|
|
79
|
+
try {
|
|
80
|
+
await peer.send(to, body, re ?? null);
|
|
81
|
+
const details = { status: "sent", ok: true };
|
|
82
|
+
return {
|
|
83
|
+
content: [{ type: "text", text: `Broadcast sent.` }],
|
|
84
|
+
details,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
89
|
+
const details = { status: "timeout", ok: false, error: msg };
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: "text", text: `Broadcast failed: ${msg}` }],
|
|
92
|
+
details,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Unicast: wait for broker ACK.
|
|
60
97
|
try {
|
|
61
|
-
await peer.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
98
|
+
const ack = await peer.sendWithAck(to, body, re ?? null, ACK_TIMEOUT_MS);
|
|
99
|
+
const ok = ack.status === "received";
|
|
100
|
+
const details = {
|
|
101
|
+
status: ack.status,
|
|
102
|
+
ok,
|
|
103
|
+
target: ack.target,
|
|
65
104
|
};
|
|
105
|
+
const text = _formatAck(to, ack.status, re);
|
|
106
|
+
return { content: [{ type: "text", text }], details };
|
|
66
107
|
}
|
|
67
108
|
catch (err) {
|
|
68
109
|
const msg = err instanceof Error ? err.message : String(err);
|
|
110
|
+
const details = { status: "timeout", ok: false, error: msg };
|
|
69
111
|
return {
|
|
70
112
|
content: [{ type: "text", text: `Failed to send: ${msg}` }],
|
|
71
|
-
details
|
|
113
|
+
details,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
const ListPeersParams = Type.Object({});
|
|
119
|
+
pi.registerTool({
|
|
120
|
+
name: "list_peers",
|
|
121
|
+
label: "List Peers",
|
|
122
|
+
description: "Returns the current peer inventory in this session — local names " +
|
|
123
|
+
"(no prefix) plus cross-PC peers prefixed `<pc_label>:<peer>`. Use " +
|
|
124
|
+
"BEFORE `agent_send` whenever you're unsure who's available, or " +
|
|
125
|
+
"after a `peer_joined` / `peer_left` notification to refresh your " +
|
|
126
|
+
"mental model. Resolves in milliseconds — this is a metadata query " +
|
|
127
|
+
"to the broker, not a turn of another agent.",
|
|
128
|
+
promptSnippet: "list_peers(): returns {peers: string[]} — locals + `<pc>:<peer>` remotes. Cheap; call freely before agent_send.",
|
|
129
|
+
parameters: ListPeersParams,
|
|
130
|
+
execute: async (_toolCallId) => {
|
|
131
|
+
const peer = getSessionPeer();
|
|
132
|
+
if (!peer) {
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: "text", text: NOT_IN_SESSION }],
|
|
135
|
+
details: { peers: [] },
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
// Internal use of the request/reply primitive is fine — broker
|
|
140
|
+
// replies are synthesised in-process (`_handleBrokerMessage`)
|
|
141
|
+
// without going through `_route`, so they bypass the ACK and
|
|
142
|
+
// busy-gate machinery entirely.
|
|
143
|
+
const reply = await peer.request("broker", { type: "list_peers" }, LIST_PEERS_TIMEOUT_MS);
|
|
144
|
+
const body = reply.body;
|
|
145
|
+
const peers = Array.isArray(body?.peers)
|
|
146
|
+
? body.peers.filter((p) => typeof p === "string")
|
|
147
|
+
: [];
|
|
148
|
+
// Drop self from the list — the caller is the only one who can't
|
|
149
|
+
// address itself anyway, so listing it is noise.
|
|
150
|
+
const selfName = peer.name();
|
|
151
|
+
const filtered = peers.filter((p) => p !== selfName);
|
|
152
|
+
const text = filtered.length === 0 ? "(no peers)" : filtered.join("\n");
|
|
153
|
+
return {
|
|
154
|
+
content: [{ type: "text", text }],
|
|
155
|
+
details: { peers: filtered },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: "text", text: `list_peers failed: ${msg}` }],
|
|
162
|
+
details: { peers: [] },
|
|
72
163
|
};
|
|
73
164
|
}
|
|
74
165
|
},
|
|
75
166
|
});
|
|
167
|
+
let _requestDeprecationWarned = false;
|
|
76
168
|
pi.registerTool({
|
|
77
169
|
name: "agent_request",
|
|
78
|
-
label: "Agent Request",
|
|
79
|
-
description: "
|
|
80
|
-
"
|
|
81
|
-
"
|
|
82
|
-
|
|
170
|
+
label: "Agent Request (deprecated)",
|
|
171
|
+
description: "DEPRECATED — prefer `agent_send` + observing your inbox for the " +
|
|
172
|
+
"reply (correlated by `re=<your-send-id>`). This tool still works: " +
|
|
173
|
+
"it sends a message and synchronously blocks until the peer replies " +
|
|
174
|
+
"or the timeout fires. Default 30s. Will be removed in a future " +
|
|
175
|
+
"release; migrate to the event-driven pattern in the agent-network skill.",
|
|
176
|
+
promptSnippet: "agent_request({to, body, timeout_ms?}): DEPRECATED synchronous request/reply (blocks current turn). Prefer agent_send + inbox observation.",
|
|
83
177
|
parameters: RequestParams,
|
|
84
178
|
execute: async (_toolCallId, params) => {
|
|
179
|
+
if (!_requestDeprecationWarned) {
|
|
180
|
+
_requestDeprecationWarned = true;
|
|
181
|
+
console.error("[remote-pi] agent_request is deprecated — migrate to agent_send + " +
|
|
182
|
+
"observe inbox by `re`. See the agent-network skill for the new pattern.");
|
|
183
|
+
}
|
|
85
184
|
const peer = getSessionPeer();
|
|
86
185
|
if (!peer) {
|
|
87
186
|
return {
|
|
@@ -99,7 +198,7 @@ export function registerAgentTools(pi, getSessionPeer) {
|
|
|
99
198
|
}
|
|
100
199
|
const timeout = typeof timeout_ms === "number" && timeout_ms > 0
|
|
101
200
|
? timeout_ms
|
|
102
|
-
:
|
|
201
|
+
: LEGACY_REQUEST_TIMEOUT_MS;
|
|
103
202
|
try {
|
|
104
203
|
const reply = await peer.request(to, body, timeout);
|
|
105
204
|
const text = typeof reply.body === "string"
|
|
@@ -120,4 +219,19 @@ export function registerAgentTools(pi, getSessionPeer) {
|
|
|
120
219
|
},
|
|
121
220
|
});
|
|
122
221
|
}
|
|
222
|
+
function _formatAck(to, status, re) {
|
|
223
|
+
const reSuffix = re ? ` (re=${re})` : "";
|
|
224
|
+
switch (status) {
|
|
225
|
+
case "received":
|
|
226
|
+
return `Delivered to "${to}"${reSuffix} — peer was idle and will process in its next turn.`;
|
|
227
|
+
case "busy":
|
|
228
|
+
return `"${to}" is busy${reSuffix} — message dropped. Retry with backoff or abandon (see agent-network skill).`;
|
|
229
|
+
case "denied":
|
|
230
|
+
return `"${to}" denied the message${reSuffix}. Do not retry; report to user.`;
|
|
231
|
+
case "timeout":
|
|
232
|
+
return `No ACK from "${to}" within ${ACK_TIMEOUT_MS}ms${reSuffix} — transport error. Investigate or retry later.`;
|
|
233
|
+
default:
|
|
234
|
+
return `Sent to "${to}"${reSuffix} — status: ${status}.`;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
123
237
|
//# sourceMappingURL=tools.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/session/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,MAAM,cAAc,GAAG,6CAA6C,CAAC;AACrE,MAAM,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/session/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,MAAM,cAAc,GAAG,6CAA6C,CAAC;AACrE,MAAM,cAAc,GAAG,KAAK,CAAC;AAC7B,MAAM,yBAAyB,GAAG,MAAM,CAAC;AACzC,MAAM,qBAAqB,GAAG,KAAK,CAAC;AAuBpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,kBAAkB,CAChC,EAAgB,EAChB,cAAwC;IAExC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;QAC7B,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC;YACd,WAAW,EACT,yEAAyE;gBACzE,yEAAyE;SAC5E,CAAC;QACF,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;QAC9F,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YAC5B,WAAW,EACT,2EAA2E;gBAC3E,0EAA0E;SAC7E,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC;QAChC,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC;QAChG,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;QACtE,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;YACpC,WAAW,EAAE,kEAAkE;SAChF,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,EAAE,CAAC,YAAY,CAAiC;QAC9C,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,sEAAsE;YACtE,uEAAuE;YACvE,mEAAmE;YACnE,iEAAiE;YACjE,8DAA8D;YAC9D,kEAAkE;YAClE,oDAAoD;QACtD,aAAa,EACX,iJAAiJ;QACnJ,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,OAAO,GAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;gBACrF,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;oBACjD,OAAO;iBACR,CAAC;YACJ,CAAC;YACD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAmB,CAAC;YAC7C,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,4CAA4C,EAAE,gCAAgC,CAAC;gBAC3F,MAAM,OAAO,GAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;gBAC1E,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;oBACtC,OAAO;iBACR,CAAC;YACJ,CAAC;YAED,MAAM,SAAS,GAAG,EAAE,KAAK,WAAW,CAAC;YAErC,qEAAqE;YACrE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,CAAC,CAAC;oBACtC,MAAM,OAAO,GAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;oBAC1D,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;wBACpD,OAAO;qBACR,CAAC;gBACJ,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;oBAC7D,MAAM,OAAO,GAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;oBAC1E,OAAO;wBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,GAAG,EAAE,EAAE,CAAC;wBAC7D,OAAO;qBACR,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,cAAc,CAAC,CAAC;gBACzE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,KAAK,UAAU,CAAC;gBACrC,MAAM,OAAO,GAAgB;oBAC3B,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,EAAE;oBACF,MAAM,EAAE,GAAG,CAAC,MAAM;iBACnB,CAAC;gBACF,MAAM,IAAI,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;gBAC5C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;YACxD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,MAAM,OAAO,GAAgB,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;gBAC1E,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,EAAE,EAAE,CAAC;oBAC3D,OAAO;iBACR,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAExC,EAAE,CAAC,YAAY,CAA8C;QAC3D,IAAI,EAAE,YAAY;QAClB,KAAK,EAAE,YAAY;QACnB,WAAW,EACT,mEAAmE;YACnE,oEAAoE;YACpE,iEAAiE;YACjE,mEAAmE;YACnE,oEAAoE;YACpE,6CAA6C;QAC/C,aAAa,EACX,iHAAiH;QACnH,UAAU,EAAE,eAAe;QAC3B,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE;YAC7B,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;oBACjD,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;iBACvB,CAAC;YACJ,CAAC;YACD,IAAI,CAAC;gBACH,+DAA+D;gBAC/D,8DAA8D;gBAC9D,6DAA6D;gBAC7D,gCAAgC;gBAChC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAC9B,QAAQ,EACR,EAAE,IAAI,EAAE,YAAY,EAAE,EACtB,qBAAqB,CACtB,CAAC;gBACF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAkC,CAAC;gBACtD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC;oBACtC,CAAC,CAAE,IAAK,CAAC,KAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;oBAC9E,CAAC,CAAC,EAAE,CAAC;gBACP,iEAAiE;gBACjE,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC;gBACrD,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACxE,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjC,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE;iBAC7B,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,GAAG,EAAE,EAAE,CAAC;oBAC9D,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;iBACvB,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;IAEH,IAAI,yBAAyB,GAAG,KAAK,CAAC;IAEtC,EAAE,CAAC,YAAY,CAAgC;QAC7C,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,4BAA4B;QACnC,WAAW,EACT,kEAAkE;YAClE,oEAAoE;YACpE,qEAAqE;YACrE,iEAAiE;YACjE,0EAA0E;QAC5E,aAAa,EACX,4IAA4I;QAC9I,UAAU,EAAE,aAAa;QACzB,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,yBAAyB,EAAE,CAAC;gBAC/B,yBAAyB,GAAG,IAAI,CAAC;gBACjC,OAAO,CAAC,KAAK,CACX,oEAAoE;oBACpE,yEAAyE,CAC1E,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;oBACjD,OAAO,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE;iBACnC,CAAC;YACJ,CAAC;YACD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,MAAsB,CAAC;YACxD,IAAI,EAAE,KAAK,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACvB,MAAM,GAAG,GAAG,+CAA+C,EAAE,gCAAgC,CAAC;gBAC9F,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;oBACtC,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;iBACxB,CAAC;YACJ,CAAC;YACD,MAAM,OAAO,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,GAAG,CAAC;gBAC9D,CAAC,CAAC,UAAU;gBACZ,CAAC,CAAC,yBAAyB,CAAC;YAC9B,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;oBACzC,CAAC,CAAC,KAAK,CAAC,IAAI;oBACZ,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC/B,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;oBACjC,OAAO,EAAE,KAAK,CAAC,IAAI;iBACpB,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,GAAG,EAAE,EAAE,CAAC;oBAC3D,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;iBACxB,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,EAAU,EAAE,MAAkB,EAAE,EAA6B;IAC/E,MAAM,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACzC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,UAAU;YACb,OAAO,iBAAiB,EAAE,IAAI,QAAQ,qDAAqD,CAAC;QAC9F,KAAK,MAAM;YACT,OAAO,IAAI,EAAE,YAAY,QAAQ,8EAA8E,CAAC;QAClH,KAAK,QAAQ;YACX,OAAO,IAAI,EAAE,uBAAuB,QAAQ,iCAAiC,CAAC;QAChF,KAAK,SAAS;YACZ,OAAO,gBAAgB,EAAE,YAAY,cAAc,KAAK,QAAQ,iDAAiD,CAAC;QACpH;YACE,OAAO,YAAY,EAAE,IAAI,QAAQ,cAAc,MAAM,GAAG,CAAC;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
import type { RelayClient } from "./relay_client.js";
|
|
3
|
+
import type { Envelope } from "../session/envelope.js";
|
|
4
|
+
/** Outbound API + inbound listener for Pi↔Pi envelope forwarding via relay. */
|
|
5
|
+
export interface PiForwardClientEvents {
|
|
6
|
+
/**
|
|
7
|
+
* Emitted whenever the relay delivers a `pi_envelope_in` frame addressed
|
|
8
|
+
* to this Pi. `fromPc` is the verified Pi-pubkey of the sender (relay
|
|
9
|
+
* authoritative — defense against spoofed `envelope.from`).
|
|
10
|
+
*/
|
|
11
|
+
envelope: [env: Envelope, fromPc: string];
|
|
12
|
+
}
|
|
13
|
+
export declare class PiForwardClient extends EventEmitter {
|
|
14
|
+
private readonly relay;
|
|
15
|
+
private readonly onRelayMessage;
|
|
16
|
+
private detached;
|
|
17
|
+
constructor(relay: RelayClient);
|
|
18
|
+
/**
|
|
19
|
+
* Pack `env` in a `pi_envelope` frame addressed to `toPc` and send via
|
|
20
|
+
* the relay WS. Best-effort: if the relay is not connected, the call is
|
|
21
|
+
* silently dropped. The caller (broker_remote) handles the timeout via
|
|
22
|
+
* its outstanding-ACK map — a missing ACK from the destination wrapper
|
|
23
|
+
* surfaces as `status: "timeout"` upstream regardless.
|
|
24
|
+
*/
|
|
25
|
+
sendEnvelopeToPi(toPc: string, env: Envelope): void;
|
|
26
|
+
/** Stop listening to the relay. Call from `_goIdle` / shutdown. */
|
|
27
|
+
detach(): void;
|
|
28
|
+
private _handleLine;
|
|
29
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
export class PiForwardClient extends EventEmitter {
|
|
3
|
+
relay;
|
|
4
|
+
onRelayMessage;
|
|
5
|
+
detached = false;
|
|
6
|
+
constructor(relay) {
|
|
7
|
+
super();
|
|
8
|
+
this.relay = relay;
|
|
9
|
+
this.onRelayMessage = (line) => this._handleLine(line);
|
|
10
|
+
this.relay.on("message", this.onRelayMessage);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pack `env` in a `pi_envelope` frame addressed to `toPc` and send via
|
|
14
|
+
* the relay WS. Best-effort: if the relay is not connected, the call is
|
|
15
|
+
* silently dropped. The caller (broker_remote) handles the timeout via
|
|
16
|
+
* its outstanding-ACK map — a missing ACK from the destination wrapper
|
|
17
|
+
* surfaces as `status: "timeout"` upstream regardless.
|
|
18
|
+
*/
|
|
19
|
+
sendEnvelopeToPi(toPc, env) {
|
|
20
|
+
if (this.detached)
|
|
21
|
+
return;
|
|
22
|
+
const frame = { type: "pi_envelope", to_pc: toPc, envelope: env };
|
|
23
|
+
try {
|
|
24
|
+
this.relay.send(JSON.stringify(frame));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// relay not connected; broker_remote's pending logic will time out
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Stop listening to the relay. Call from `_goIdle` / shutdown. */
|
|
31
|
+
detach() {
|
|
32
|
+
if (this.detached)
|
|
33
|
+
return;
|
|
34
|
+
this.detached = true;
|
|
35
|
+
this.relay.off("message", this.onRelayMessage);
|
|
36
|
+
}
|
|
37
|
+
_handleLine(line) {
|
|
38
|
+
// The relay multiplexes several frame types over the same WS; we only
|
|
39
|
+
// care about `pi_envelope_in`. Other frames (outer-encrypted owner
|
|
40
|
+
// envelopes, control replies) are silently ignored.
|
|
41
|
+
let parsed;
|
|
42
|
+
try {
|
|
43
|
+
parsed = JSON.parse(line);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!parsed || typeof parsed !== "object")
|
|
49
|
+
return;
|
|
50
|
+
const o = parsed;
|
|
51
|
+
if (o.type !== "pi_envelope_in")
|
|
52
|
+
return;
|
|
53
|
+
if (typeof o.from_pc !== "string" || !o.envelope || typeof o.envelope !== "object")
|
|
54
|
+
return;
|
|
55
|
+
// Cheap shape check — full envelope parse happens downstream in broker_remote.
|
|
56
|
+
const env = o.envelope;
|
|
57
|
+
if (typeof env.from !== "string" || typeof env.id !== "string")
|
|
58
|
+
return;
|
|
59
|
+
this.emit("envelope", env, o.from_pc);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=pi_forward_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi_forward_client.js","sourceRoot":"","sources":["../../src/transport/pi_forward_client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA2C3C,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAIlB;IAHZ,cAAc,CAAyB;IAChD,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAA6B,KAAkB;QAC7C,KAAK,EAAE,CAAC;QADmB,UAAK,GAAL,KAAK,CAAa;QAE7C,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,IAAY,EAAE,GAAa;QAC1C,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,MAAM,KAAK,GAAoB,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;QACnF,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,MAAM;QACJ,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;IACjD,CAAC;IAEO,WAAW,CAAC,IAAY;QAC9B,sEAAsE;QACtE,mEAAmE;QACnE,oDAAoD;QACpD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO;QAClD,MAAM,CAAC,GAAG,MAAoC,CAAC;QAC/C,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB;YAAE,OAAO;QACxC,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAAE,OAAO;QAE3F,+EAA+E;QAC/E,MAAM,GAAG,GAAG,CAAC,CAAC,QAAoB,CAAC;QACnC,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO;QACvE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;CACF"}
|
package/dist/ui/footer.js
CHANGED
|
@@ -21,12 +21,14 @@ export function updateFooter(ctx, state) {
|
|
|
21
21
|
else {
|
|
22
22
|
ctx.ui.setStatus(K_PEER, undefined);
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
// Terminal title — two parts only: `<agent-name> · <On|Off>`.
|
|
25
|
+
// Pre-2026-05-24 the title carried three segments (`name · local · relay`),
|
|
26
|
+
// but `local` was always the same string (single fixed UDS session) and
|
|
27
|
+
// `relay` repeated information the relay slot already shows. Collapsed
|
|
28
|
+
// to "name + relay state in plain English" — same info, clearer at a
|
|
29
|
+
// glance: terminal tabs read like `backend · On` / `backend · Off`.
|
|
29
30
|
const prefix = state.agentName?.trim() || "Pi";
|
|
30
|
-
|
|
31
|
+
const relayState = state.relayOn ? "On" : "Off";
|
|
32
|
+
ctx.ui.setTitle(`${prefix} · ${relayState}`);
|
|
31
33
|
}
|
|
32
34
|
//# sourceMappingURL=footer.js.map
|
package/dist/ui/footer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../src/ui/footer.ts"],"names":[],"mappings":"AAiCA,MAAM,SAAS,GAAG,mBAAmB,CAAC;AACtC,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAClC,MAAM,MAAM,GAAG,uBAAuB,CAAC;AAEvC,MAAM,UAAU,YAAY,CAAC,GAAkB,EAAE,KAAkB;IACjE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,KAAK,CAAC,OAAO,KAAK,KAAK,GAAG,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,GAAG,CAAC,EAAE,CAAC,SAAS,CACd,OAAO,EACP,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,8BAA8B,CAChE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"footer.js","sourceRoot":"","sources":["../../src/ui/footer.ts"],"names":[],"mappings":"AAiCA,MAAM,SAAS,GAAG,mBAAmB,CAAC;AACtC,MAAM,OAAO,GAAG,iBAAiB,CAAC;AAClC,MAAM,MAAM,GAAG,uBAAuB,CAAC;AAEvC,MAAM,UAAU,YAAY,CAAC,GAAkB,EAAE,KAAkB;IACjE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,KAAK,CAAC,OAAO,KAAK,KAAK,GAAG,CAAC,CAAC;IAChE,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,GAAG,CAAC,EAAE,CAAC,SAAS,CACd,OAAO,EACP,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,8BAA8B,CAChE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,KAAK,CAAC,YAAY,EAAE,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtC,CAAC;IAED,8DAA8D;IAC9D,4EAA4E;IAC5E,wEAAwE;IACxE,uEAAuE;IACvE,qEAAqE;IACrE,oEAAoE;IACpE,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC;IAC/C,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAChD,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,MAAM,MAAM,UAAU,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|