@cotal-ai/cli 0.137.0 → 0.138.1
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/chat/chat-view.d.ts +1 -1
- package/dist/chat/chat-view.d.ts.map +1 -1
- package/dist/chat/controller.d.ts +1 -1
- package/dist/chat/controller.d.ts.map +1 -1
- package/dist/chat/frontend.d.ts +1 -1
- package/dist/chat/frontend.d.ts.map +1 -1
- package/dist/chat/picker.d.ts +1 -1
- package/dist/chat/picker.d.ts.map +1 -1
- package/dist/chat/plain.d.ts +1 -1
- package/dist/chat/plain.d.ts.map +1 -1
- package/dist/chat/stdio-io.d.ts +1 -1
- package/dist/chat/stdio-io.d.ts.map +1 -1
- package/dist/chat/stdio.d.ts +1 -1
- package/dist/chat/stdio.d.ts.map +1 -1
- package/dist/chat/view.d.ts +1 -1
- package/dist/chat/view.d.ts.map +1 -1
- package/dist/commands/agents.d.ts +7 -149
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +15 -723
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/channels.js +1 -1
- package/dist/commands/channels.js.map +1 -1
- package/dist/commands/chat.d.ts +1 -24
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +3 -15
- package/dist/commands/chat.js.map +1 -1
- package/dist/console/app.js +1 -1
- package/dist/console/app.js.map +1 -1
- package/package.json +5 -6
- package/dist/chat/engine.d.ts +0 -111
- package/dist/chat/engine.d.ts.map +0 -1
- package/dist/chat/engine.js +0 -225
- package/dist/chat/engine.js.map +0 -1
- package/dist/chat/native-session.d.ts +0 -120
- package/dist/chat/native-session.d.ts.map +0 -1
- package/dist/chat/native-session.js +0 -487
- package/dist/chat/native-session.js.map +0 -1
- package/dist/chat/open-session.d.ts +0 -9
- package/dist/chat/open-session.d.ts.map +0 -1
- package/dist/chat/open-session.js +0 -120
- package/dist/chat/open-session.js.map +0 -1
- package/dist/chat/session.d.ts +0 -230
- package/dist/chat/session.d.ts.map +0 -1
- package/dist/chat/session.js +0 -2
- package/dist/chat/session.js.map +0 -1
- package/dist/chat/static-session.d.ts +0 -62
- package/dist/chat/static-session.d.ts.map +0 -1
- package/dist/chat/static-session.js +0 -236
- package/dist/chat/static-session.js.map +0 -1
- package/dist/chat/user-session.d.ts +0 -22
- package/dist/chat/user-session.d.ts.map +0 -1
- package/dist/chat/user-session.js +0 -180
- package/dist/chat/user-session.js.map +0 -1
- package/dist/lib/attach-client.d.ts +0 -112
- package/dist/lib/attach-client.d.ts.map +0 -1
- package/dist/lib/attach-client.js +0 -528
- package/dist/lib/attach-client.js.map +0 -1
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The static-mode chat admission adapter. On a static-auth mesh the local manager admits the
|
|
3
|
-
* session (`chat-session-open`): it draws the `chat_` alias and a fresh nkey identity and mints the
|
|
4
|
-
* session's own leaf. This adapter runs one real `CotalEndpoint` under that leaf and ends the
|
|
5
|
-
* session with `chat-session-retire` at the same manager instance that admitted it, on close or at
|
|
6
|
-
* the leaf's expiry. `cotal chat` opens it for a static-auth target.
|
|
7
|
-
*
|
|
8
|
-
* The leaf never crosses the wire in the clear. The adapter sends a one-time curve key as
|
|
9
|
-
* `sealTo`, and the manager seals the leaf to it, bound to the space, the admitting instance and
|
|
10
|
-
* every reply field; a generic invoke, an agent tool or a browser sees only that ciphertext. The
|
|
11
|
-
* adapter opens it once, checks every bound field, keeps the leaf in memory, and never writes it to
|
|
12
|
-
* a file, a receipt, a log or any output record. Its retire path never sees it.
|
|
13
|
-
*
|
|
14
|
-
* The caller resolves the mesh once, into `target`. Every manager call mints its one-shot
|
|
15
|
-
* instrument from a copy of that target's server, TLS requirement and trust material, so a later
|
|
16
|
-
* `cotal use` or registry change cannot move the retirement to another mesh.
|
|
17
|
-
*/
|
|
18
|
-
import { CotalEndpoint, DEV_OWNER, EP_UNANSWERED, SealRecipient, assertLifecycleToken, assertValidChannel, idFromCreds, isCurvePublicKey, principalKey, resolveReadAcl, } from "@cotal-ai/core";
|
|
19
|
-
import { CommandFailure, isConnectRefusal, mintControlInstrument, preflightOrThrow } from "@cotal-ai/workspace";
|
|
20
|
-
import { NativeChatSession } from "./native-session.js";
|
|
21
|
-
import { askManager, managerFailure, refuseWithoutLiveManager } from "@cotal-ai/workspace/control";
|
|
22
|
-
import { cliControl } from "../lib/control.js";
|
|
23
|
-
/** The leaf's whole life. The manager caps `ttl` here and never renews it. */
|
|
24
|
-
export const STATIC_CHAT_TTL_SEC = 900;
|
|
25
|
-
/** How long `chat-session-retire` may take to answer. The manager answers once its static terminal
|
|
26
|
-
* settles, and that terminal waits up to 15 seconds for the delivery daemon's verified eviction so
|
|
27
|
-
* a daemon that is reconnecting can still finish it. The window outlives that wait and the
|
|
28
|
-
* footprint cleanup after a late eviction; a reply that still does not come is reported unknown. */
|
|
29
|
-
const STATIC_CHAT_RETIRE_TIMEOUT_MS = 30_000;
|
|
30
|
-
/** Every key the manager seals and no other, sorted and joined for one comparison. */
|
|
31
|
-
const SEALED_KEYS = ["v", "space", "managerInstanceId", "alias", "actor", "lifecycleUid", "expiresAt", "sealTo", "creds"].sort().join();
|
|
32
|
-
/** Open and check one `chat-session-open` reply. The outer reply must have its contract shape;
|
|
33
|
-
* the sealed payload must open with `recipient`, which it uses up, must carry exactly the sealed
|
|
34
|
-
* keys, and must bind the expected space and responding instance, this recipient's own key and
|
|
35
|
-
* the outer alias, actor, uid and expiry; and its credential must be the identity it names.
|
|
36
|
-
* Undefined when any part does not hold; the caller never uses a reply that fails here. */
|
|
37
|
-
export function readAdmission(data, recipient, expected) {
|
|
38
|
-
const sealTo = recipient.publicKey;
|
|
39
|
-
// A reply refused before the open still uses the key up, so it never opens a later one.
|
|
40
|
-
const refuse = () => {
|
|
41
|
-
recipient.clear();
|
|
42
|
-
return undefined;
|
|
43
|
-
};
|
|
44
|
-
if (typeof data !== "object" || data === null)
|
|
45
|
-
return refuse();
|
|
46
|
-
const d = data;
|
|
47
|
-
if (typeof d.alias !== "string" || !/^chat_[a-z2-7]{26}$/.test(d.alias))
|
|
48
|
-
return refuse();
|
|
49
|
-
if (typeof d.actor !== "string" || typeof d.lifecycleUid !== "string" || typeof d.sealed !== "string")
|
|
50
|
-
return refuse();
|
|
51
|
-
if (typeof d.sealer !== "string" || !isCurvePublicKey(d.sealer))
|
|
52
|
-
return refuse();
|
|
53
|
-
if (typeof d.expiresAt !== "number" || !Number.isSafeInteger(d.expiresAt))
|
|
54
|
-
return refuse();
|
|
55
|
-
if ("creds" in d)
|
|
56
|
-
return refuse();
|
|
57
|
-
const opened = recipient.openJson(d.sealed, d.sealer);
|
|
58
|
-
if (typeof opened !== "object" || opened === null)
|
|
59
|
-
return undefined;
|
|
60
|
-
const p = opened;
|
|
61
|
-
if (Object.keys(p).sort().join() !== SEALED_KEYS)
|
|
62
|
-
return undefined;
|
|
63
|
-
if (p.v !== 1 || p.space !== expected.space || p.managerInstanceId !== expected.managerInstanceId || p.sealTo !== sealTo)
|
|
64
|
-
return undefined;
|
|
65
|
-
if (p.alias !== d.alias || p.actor !== d.actor || p.lifecycleUid !== d.lifecycleUid || p.expiresAt !== d.expiresAt)
|
|
66
|
-
return undefined;
|
|
67
|
-
if (typeof p.creds !== "string")
|
|
68
|
-
return undefined;
|
|
69
|
-
try {
|
|
70
|
-
assertLifecycleToken(d.lifecycleUid);
|
|
71
|
-
principalKey(DEV_OWNER, d.actor);
|
|
72
|
-
if (idFromCreds(p.creds) !== d.actor)
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
return { alias: d.alias, actor: d.actor, lifecycleUid: d.lifecycleUid, creds: p.creds, expiresAt: d.expiresAt };
|
|
79
|
-
}
|
|
80
|
-
/** The close report for a `chat-session-retire` reply. The adapter asks only after its own
|
|
81
|
-
* endpoint stopped, so `connectionClosed` is that observed stop, and `NativeChatSession`
|
|
82
|
-
* downgrades it when the stop failed. The retirement outcome is reported apart from it and never
|
|
83
|
-
* changes it. A static mesh has no broker-side revocation, so no outcome here ends the leaf at
|
|
84
|
-
* the broker: a copy of it still authenticates until `validUntil`. */
|
|
85
|
-
export function retireReport(reply, managerInstanceId, validUntil) {
|
|
86
|
-
const base = { connectionClosed: "confirmed", credentialValidUntil: validUntil };
|
|
87
|
-
const valid = `The broker accepts the session's credential until ${new Date(validUntil).toISOString()}; a static mesh cannot revoke it sooner.`;
|
|
88
|
-
if (!reply.ok) {
|
|
89
|
-
const failure = managerFailure(reply, "chat-session-retire", null);
|
|
90
|
-
return failure.outcome === "refused"
|
|
91
|
-
? { ...base, retirement: "requested", message: `Manager ${managerInstanceId} refused the retirement; the session is not retired: ${reply.error ?? failure.message}. ${valid}` }
|
|
92
|
-
: { ...base, retirement: "unknown", message: `${failure.message}. The session may still be admitted at manager ${managerInstanceId}. ${valid}` };
|
|
93
|
-
}
|
|
94
|
-
const data = reply.data;
|
|
95
|
-
if (data?.outcome === "retired")
|
|
96
|
-
return { ...base, retirement: "retired", message: `Static session retired at manager ${managerInstanceId}: its slot is retired, its credential row is marked revoked, and its principal had no broker connection left when it retired. ${valid}` };
|
|
97
|
-
if (data?.outcome === "alreadyRetired")
|
|
98
|
-
return { ...base, retirement: "retired", message: `Static session was already retired at manager ${managerInstanceId}. ${valid}` };
|
|
99
|
-
if (data?.outcome === "failed")
|
|
100
|
-
return { ...base, retirement: "requested", message: `Manager ${managerInstanceId} did not finish the retirement: ${typeof data.reason === "string" ? data.reason : "retirement pending"}. ${valid}` };
|
|
101
|
-
return { ...base, retirement: "unknown", message: `Manager ${managerInstanceId} answered the retirement without a recognized outcome. ${valid}` };
|
|
102
|
-
}
|
|
103
|
-
/** Ask the pinned mesh's manager `op` under a fresh one-shot instrument minted from the pinned
|
|
104
|
-
* trust material. When the mint or the dial throws, nothing reached the manager, and a read-only
|
|
105
|
-
* preflight of the same target classifies the cause as `connectOrThrow` does; it prunes nothing.
|
|
106
|
-
* With `purpose`, an unpinned call on a space whose registry lists no live manager is refused
|
|
107
|
-
* before `op` is sent, as the run verbs refuse it, rather than after it has waited out its deadline.
|
|
108
|
-
* `timeoutMs` is the reply window for `op` itself; absent, it is `askManager`'s default. */
|
|
109
|
-
async function askPinned(mesh, op, args, instanceId, purpose, timeoutMs) {
|
|
110
|
-
try {
|
|
111
|
-
const auth = { ...await mintControlInstrument(mesh, "privileged", instanceId), tls: mesh.tlsRequired };
|
|
112
|
-
if (purpose !== undefined && instanceId === undefined)
|
|
113
|
-
await refuseWithoutLiveManager(mesh.space, mesh.server, auth, { space: mesh.space }, purpose);
|
|
114
|
-
return await askManager(cliControl, mesh.space, mesh.server, op, args, auth, "owner", timeoutMs, instanceId !== undefined ? { instanceId } : undefined);
|
|
115
|
-
}
|
|
116
|
-
catch (e) {
|
|
117
|
-
if (e instanceof CommandFailure)
|
|
118
|
-
throw e;
|
|
119
|
-
await preflightOrThrow(mesh, undefined, true);
|
|
120
|
-
throw e;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
/** Open one static chat session on `target`, which the caller resolved once. The three lists are
|
|
124
|
-
* a spawn's, under its rules: `subscribe` the initial channels, `allowSubscribe` the read ceiling
|
|
125
|
-
* (empty means `subscribe`), `allowPublish` the post list (empty means none). `instanceId`
|
|
126
|
-
* (`--on`) chooses the admitting manager; retirement always goes to the instance that answered
|
|
127
|
-
* the open. */
|
|
128
|
-
export async function openStaticChatSession(target, options) {
|
|
129
|
-
if (target.mode !== "auth" || !target.auth)
|
|
130
|
-
throw new CommandFailure("refused", "UNSUPPORTED", "the static chat adapter requires a recorded static-auth target with its trust material; no other admission was attempted", { target: { space: target.space } });
|
|
131
|
-
const subscribe = [...(options.subscribe ?? [])];
|
|
132
|
-
const allowPublish = [...(options.allowPublish ?? [])];
|
|
133
|
-
let allowSubscribe;
|
|
134
|
-
try {
|
|
135
|
-
if (!options.label || options.label.length > 128)
|
|
136
|
-
throw new Error("the label must be 1 to 128 characters");
|
|
137
|
-
for (const channel of [...subscribe, ...(options.allowSubscribe ?? []), ...allowPublish])
|
|
138
|
-
assertValidChannel(channel);
|
|
139
|
-
allowSubscribe = resolveReadAcl(subscribe, [...(options.allowSubscribe ?? [])]);
|
|
140
|
-
}
|
|
141
|
-
catch (e) {
|
|
142
|
-
throw new CommandFailure("refused", "USAGE_INVALID", `chat could not be opened: ${e.message}`);
|
|
143
|
-
}
|
|
144
|
-
const mesh = Object.freeze({ ...target, auth: target.auth });
|
|
145
|
-
// The one-time key the leaf is sealed to. Its private half stays in this object and is cleared
|
|
146
|
-
// once the reply is opened or the open fails.
|
|
147
|
-
const recipient = new SealRecipient();
|
|
148
|
-
let reply;
|
|
149
|
-
try {
|
|
150
|
-
reply = await askPinned(mesh, "chatSessionOpen", {
|
|
151
|
-
subscribe, allowSubscribe: [...(options.allowSubscribe ?? [])], allowPublish, label: options.label, ttl: STATIC_CHAT_TTL_SEC, sealTo: recipient.publicKey,
|
|
152
|
-
}, options.instanceId, "admit a chat session");
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
recipient.clear();
|
|
156
|
-
if (e instanceof CommandFailure)
|
|
157
|
-
throw e;
|
|
158
|
-
if (isConnectRefusal(e))
|
|
159
|
-
throw e.failure();
|
|
160
|
-
throw new CommandFailure("refused", "DEPENDENCY_UNAVAILABLE", `the control instrument could not be minted or connected, so chat-session-open was not sent: ${e.message}`, { target: { space: mesh.space } });
|
|
161
|
-
}
|
|
162
|
-
if (!reply.ok) {
|
|
163
|
-
recipient.clear();
|
|
164
|
-
// A describe that drew no answer means chat-session-open was never sent, so this is a refusal,
|
|
165
|
-
// as the run verbs give it, and not an unknown outcome.
|
|
166
|
-
if (reply.details?.some((detail) => detail.kind === EP_UNANSWERED && detail.command === "describe"))
|
|
167
|
-
throw new CommandFailure("refused", "TARGET_UNAVAILABLE", `chat-session-open was not sent: ${reply.error}`, {
|
|
168
|
-
target: { space: mesh.space },
|
|
169
|
-
native: { code: reply.code },
|
|
170
|
-
remedy: "cotal status shows whether this space's manager answers; a stack manager that runs but does not answer is named there with its pid and the way to end it",
|
|
171
|
-
});
|
|
172
|
-
throw managerFailure(reply, "chat-session-open", { space: mesh.space });
|
|
173
|
-
}
|
|
174
|
-
const managerInstanceId = reply.managerInstanceId;
|
|
175
|
-
const admission = managerInstanceId === undefined ? undefined : readAdmission(reply.data, recipient, { space: mesh.space, managerInstanceId });
|
|
176
|
-
if (admission === undefined || managerInstanceId === undefined) {
|
|
177
|
-
recipient.clear();
|
|
178
|
-
throw new CommandFailure("unknown", "OPERATION_UNKNOWN", "the manager answered chat-session-open with a reply this CLI could not open or verify; the session was not used and could not be retired from here", {
|
|
179
|
-
target: { space: mesh.space },
|
|
180
|
-
native: { outcome: "unknown", detail: { managerInstanceId: managerInstanceId ?? null } },
|
|
181
|
-
remedy: "list the manager's slots with `cotal ps --slots`; the admitting manager retires an unretired chat_ slot at its expiry, at its stop, or at its next start",
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
// The retire path never sees the credential bytes.
|
|
185
|
-
const { creds, ...slot } = admission;
|
|
186
|
-
const identity = {
|
|
187
|
-
mode: "static", space: mesh.space, principal: principalKey(DEV_OWNER, slot.actor).key, lifecycleUid: slot.lifecycleUid, label: options.label,
|
|
188
|
-
allowSubscribe, allowPublish, expiresAt: slot.expiresAt,
|
|
189
|
-
};
|
|
190
|
-
const retire = async () => {
|
|
191
|
-
let answer;
|
|
192
|
-
try {
|
|
193
|
-
answer = await askPinned(mesh, "chatSessionRetire", { alias: slot.alias, actor: slot.actor, lifecycleUid: slot.lifecycleUid }, managerInstanceId, undefined, STATIC_CHAT_RETIRE_TIMEOUT_MS);
|
|
194
|
-
}
|
|
195
|
-
catch (e) {
|
|
196
|
-
const cause = isConnectRefusal(e) ? e.failure().message : e.message;
|
|
197
|
-
return { retirement: "unknown", connectionClosed: "confirmed", credentialValidUntil: slot.expiresAt, message: `The retire request was not sent to manager ${managerInstanceId}: ${cause}. That manager retires the session at its expiry or its stop if it is still running.` };
|
|
198
|
-
}
|
|
199
|
-
return retireReport(answer, managerInstanceId, slot.expiresAt);
|
|
200
|
-
};
|
|
201
|
-
const endpoint = new CotalEndpoint({
|
|
202
|
-
space: mesh.space,
|
|
203
|
-
servers: mesh.server,
|
|
204
|
-
tls: mesh.tlsRequired,
|
|
205
|
-
creds,
|
|
206
|
-
card: { owner: DEV_OWNER, actor: slot.actor, name: options.label, kind: "endpoint", meta: { sessionKind: "chat" } },
|
|
207
|
-
lifecycleUid: slot.lifecycleUid,
|
|
208
|
-
// A copy: the endpoint edits its list on /leave and /join, and the read grant may be this array.
|
|
209
|
-
channels: [...subscribe],
|
|
210
|
-
});
|
|
211
|
-
// The participant listeners are installed here, before the endpoint starts.
|
|
212
|
-
const session = new NativeChatSession({ endpoint, identity, retire, reopen: options.reopen });
|
|
213
|
-
if (slot.expiresAt <= Date.now()) {
|
|
214
|
-
const close = await session.close();
|
|
215
|
-
throw new CommandFailure("failed", "OPERATION_FAILED", "the admitted session had already expired when its reply arrived, so it was closed without connecting", {
|
|
216
|
-
target: { space: mesh.space, principal: identity.principal, lifecycleUid: slot.lifecycleUid },
|
|
217
|
-
native: { detail: { close } },
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
try {
|
|
221
|
-
await endpoint.start();
|
|
222
|
-
// The leaf is never renewed, so the session ends at its expiry. Closing is memoized, so an
|
|
223
|
-
// earlier close by the front end makes this a no-op.
|
|
224
|
-
setTimeout(() => void session.close(), Math.max(0, slot.expiresAt - Date.now())).unref();
|
|
225
|
-
return session;
|
|
226
|
-
}
|
|
227
|
-
catch {
|
|
228
|
-
const close = await session.close();
|
|
229
|
-
throw new CommandFailure("unknown", "OPERATION_UNKNOWN", "the static chat opening did not finish; no automatic retry was made", {
|
|
230
|
-
target: { space: mesh.space, principal: identity.principal, lifecycleUid: slot.lifecycleUid },
|
|
231
|
-
native: { outcome: "unknown", detail: { close } },
|
|
232
|
-
remedy: "the close report in the error cause says whether the session was retired; the admitting manager retires an unretired chat_ slot at its expiry, at its stop, or at its next start",
|
|
233
|
-
});
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
//# sourceMappingURL=static-session.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-session.js","sourceRoot":"","sources":["../../src/chat/static-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { type MeshTarget } from "@cotal-ai/workspace";
|
|
2
|
-
import { NativeChatSession } from "./native-session.js";
|
|
3
|
-
/**
|
|
4
|
-
* User mode: each opening is its own principal `<owner>.chat_<…>` at a fresh lifecycle UID, which the
|
|
5
|
-
* space's auth service draws and admits under the signed-in human's own `cli` grant, confined to the
|
|
6
|
-
* given read and post lists and to `ttlSec`. No `cli`, managed or other borrowed identity connects.
|
|
7
|
-
*
|
|
8
|
-
* The holder secret lives in this process's memory only: admission receives its SHA-256, and each
|
|
9
|
-
* bearer exchange and the retirement present the secret itself. No bearer, sentinel or holder secret
|
|
10
|
-
* is returned, printed or written. Mode, server, TLS and space come from the one resolved target,
|
|
11
|
-
* and the open names that target's IdP and exchange position so the provider cannot follow a
|
|
12
|
-
* re-registered entry; the session's later requests reuse the route its open resolved.
|
|
13
|
-
*/
|
|
14
|
-
export declare function openUserChatSession(target: MeshTarget, options: {
|
|
15
|
-
readonly label: string;
|
|
16
|
-
readonly channels: readonly string[];
|
|
17
|
-
readonly read: readonly string[];
|
|
18
|
-
readonly post: readonly string[];
|
|
19
|
-
readonly ttlSec: number;
|
|
20
|
-
readonly reopen: (channel: string) => string;
|
|
21
|
-
}): Promise<NativeChatSession>;
|
|
22
|
-
//# sourceMappingURL=user-session.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-session.d.ts","sourceRoot":"","sources":["../../src/chat/user-session.ts"],"names":[],"mappings":"AAUA,OAAO,EAA0D,KAAK,UAAU,EAAoB,MAAM,qBAAqB,CAAC;AAChI,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AA8CxD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE;IACrE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9C,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA0H7B"}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
-
import { CotalEndpoint, EpEnvelopeError, channelInAllow, isConcreteChannel, registry, } from "@cotal-ai/core";
|
|
3
|
-
import { CommandFailure, userAuthStateDir, workspaceSecretStore } from "@cotal-ai/workspace";
|
|
4
|
-
import { NativeChatSession } from "./native-session.js";
|
|
5
|
-
/** Native refusal codes the auth service answers before any effect. */
|
|
6
|
-
const REFUSED = {
|
|
7
|
-
"bad-request": "USAGE_INVALID",
|
|
8
|
-
"unauthenticated": "AUTH_REQUIRED",
|
|
9
|
-
"permission-denied": "PERMISSION_DENIED",
|
|
10
|
-
"not-found": "TARGET_NOT_FOUND",
|
|
11
|
-
"failed-precondition": "LIFECYCLE_BLOCKED",
|
|
12
|
-
"unimplemented": "UNSUPPORTED",
|
|
13
|
-
"unavailable": "TARGET_UNAVAILABLE",
|
|
14
|
-
"conflict": "CONFLICT",
|
|
15
|
-
"resource-exhausted": "TARGET_UNAVAILABLE",
|
|
16
|
-
};
|
|
17
|
-
/** A provider failure as the command's outcome, by the effect outcome the service stated: a
|
|
18
|
-
* `not-executed` refusal keeps its code, an `executed` one failed after writing, and anything else
|
|
19
|
-
* is unknown and never retried here. A plain provider error was raised before the request left this
|
|
20
|
-
* machine (sign-in, discovery, transport setup). */
|
|
21
|
-
function providerFailure(e, target) {
|
|
22
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
23
|
-
if (e instanceof EpEnvelopeError) {
|
|
24
|
-
const native = { code: e.code, outcome: e.outcome ?? "unknown" };
|
|
25
|
-
if (e.outcome === "not-executed")
|
|
26
|
-
return new CommandFailure("refused", REFUSED[e.code] ?? "DEPENDENCY_UNAVAILABLE", message, { target, native });
|
|
27
|
-
if (e.outcome === "executed")
|
|
28
|
-
return new CommandFailure("failed", "OPERATION_FAILED", message, { target, native });
|
|
29
|
-
return new CommandFailure("unknown", "OPERATION_UNKNOWN", message, {
|
|
30
|
-
target,
|
|
31
|
-
native,
|
|
32
|
-
remedy: "no automatic retry was made; an admission that landed without an answer is reclaimed by the auth service's sweep",
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
const credential = e?.code;
|
|
36
|
-
return new CommandFailure("refused", credential === "signed-out" ? "AUTH_REQUIRED" : credential === "refused" ? "PERMISSION_DENIED" : "DEPENDENCY_UNAVAILABLE", message, { target });
|
|
37
|
-
}
|
|
38
|
-
/** The principal a minted bearer names, read without verification (the broker verifies). */
|
|
39
|
-
function bearerPrincipal(bearer) {
|
|
40
|
-
const payload = JSON.parse(Buffer.from(bearer.split(".")[1] ?? "", "base64url").toString("utf8"));
|
|
41
|
-
if (typeof payload.sub !== "string" || typeof payload.act?.actor !== "string" || typeof payload.act.lifecycleUid !== "string")
|
|
42
|
-
throw new Error("the chat bearer does not name a principal and lifecycle");
|
|
43
|
-
return { owner: payload.sub, actor: payload.act.actor, lifecycleUid: payload.act.lifecycleUid };
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* User mode: each opening is its own principal `<owner>.chat_<…>` at a fresh lifecycle UID, which the
|
|
47
|
-
* space's auth service draws and admits under the signed-in human's own `cli` grant, confined to the
|
|
48
|
-
* given read and post lists and to `ttlSec`. No `cli`, managed or other borrowed identity connects.
|
|
49
|
-
*
|
|
50
|
-
* The holder secret lives in this process's memory only: admission receives its SHA-256, and each
|
|
51
|
-
* bearer exchange and the retirement present the secret itself. No bearer, sentinel or holder secret
|
|
52
|
-
* is returned, printed or written. Mode, server, TLS and space come from the one resolved target,
|
|
53
|
-
* and the open names that target's IdP and exchange position so the provider cannot follow a
|
|
54
|
-
* re-registered entry; the session's later requests reuse the route its open resolved.
|
|
55
|
-
*/
|
|
56
|
-
export async function openUserChatSession(target, options) {
|
|
57
|
-
const space = target.space;
|
|
58
|
-
if (target.mode !== "user" || target.userAuth === undefined)
|
|
59
|
-
throw new CommandFailure("refused", "UNSUPPORTED", "the user-mode chat adapter requires a recorded user-auth target; no other authentication was attempted", { target: { space } });
|
|
60
|
-
if (!options.label || options.label.length > 128 || options.channels.some((channel) => !isConcreteChannel(channel)))
|
|
61
|
-
throw new CommandFailure("refused", "USAGE_INVALID", "chat requires a label of 1 to 128 characters and concrete initial channels");
|
|
62
|
-
if (options.channels.some((channel) => !channelInAllow([...options.read], channel)))
|
|
63
|
-
throw new CommandFailure("refused", "USAGE_INVALID", "every initial channel must sit within the session's read list");
|
|
64
|
-
if (!Number.isSafeInteger(options.ttlSec) || options.ttlSec <= 0)
|
|
65
|
-
throw new CommandFailure("refused", "USAGE_INVALID", "a chat session lifetime is a positive whole number of seconds");
|
|
66
|
-
const userAuth = target.userAuth;
|
|
67
|
-
const providerName = userAuth.provider;
|
|
68
|
-
let provider;
|
|
69
|
-
try {
|
|
70
|
-
provider = registry.resolve("auth-provider", providerName);
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
throw new CommandFailure("refused", "UNSUPPORTED", `space "${space}" uses the "${providerName}" auth provider, which this build does not register`, { target: { space } });
|
|
74
|
-
}
|
|
75
|
-
const openChat = provider.openChatSession?.bind(provider);
|
|
76
|
-
const bearerFor = provider.chatSessionBearer?.bind(provider);
|
|
77
|
-
const retireChat = provider.retireChatSession?.bind(provider);
|
|
78
|
-
if (!openChat || !bearerFor || !retireChat)
|
|
79
|
-
throw new CommandFailure("refused", "UNSUPPORTED", `the "${providerName}" auth provider cannot serve user-mode chat; no other identity or auth mode was tried`, { target: { space } });
|
|
80
|
-
const auth = { store: workspaceSecretStore(target.root), dir: userAuthStateDir(target.root, space), space };
|
|
81
|
-
const holderProof = randomBytes(32).toString("base64url");
|
|
82
|
-
const holderHash = createHash("sha256").update(holderProof, "utf8").digest("hex");
|
|
83
|
-
let opened;
|
|
84
|
-
try {
|
|
85
|
-
// The provider refuses before sending anything when its own resolution is not this target's.
|
|
86
|
-
const exchangeUrl = userAuth.remote === true ? userAuth.endpoints?.url : undefined;
|
|
87
|
-
const expect = { idpUrl: userAuth.idp.url, ...(exchangeUrl !== undefined ? { exchangeUrl } : {}) };
|
|
88
|
-
opened = await openChat({ ...auth, holderHash, label: options.label, read: [...options.read], post: [...options.post], ttlSec: options.ttlSec, expect });
|
|
89
|
-
}
|
|
90
|
-
catch (e) {
|
|
91
|
-
throw providerFailure(e, { space });
|
|
92
|
-
}
|
|
93
|
-
const { actor, lifecycleUid } = opened;
|
|
94
|
-
const expiresAtMs = opened.expiresAt * 1000;
|
|
95
|
-
// The last bearer this process received: it stays broker-valid until its expiry unless the
|
|
96
|
-
// retirement's eviction completes.
|
|
97
|
-
let credentialValidUntil = 0;
|
|
98
|
-
let expiry;
|
|
99
|
-
const validUntil = () => (credentialValidUntil > 0 ? { credentialValidUntil } : {});
|
|
100
|
-
const retire = async () => {
|
|
101
|
-
clearTimeout(expiry);
|
|
102
|
-
try {
|
|
103
|
-
const r = await retireChat({ ...auth, actor, lifecycleUid, holderProof });
|
|
104
|
-
if (r.outcome === "failed")
|
|
105
|
-
return { retirement: "requested", connectionClosed: "not-confirmed", ...validUntil(), message: `Chat session retirement is pending: ${r.pending ?? "the authority gave no reason"}. Its last bearer stays usable until its expiry unless eviction completes.` };
|
|
106
|
-
const what = r.outcome === "alreadyRetired" ? "was already retired" : r.outcome === "notStarted" ? "had nothing left to retire" : "retired";
|
|
107
|
-
return { retirement: "retired", connectionClosed: "confirmed", message: `Chat session ${what}; its connections were evicted and no bearer can be minted for it.` };
|
|
108
|
-
}
|
|
109
|
-
catch (e) {
|
|
110
|
-
const unknown = !(e instanceof EpEnvelopeError) || (e.outcome !== "not-executed" && e.outcome !== "executed");
|
|
111
|
-
return {
|
|
112
|
-
retirement: unknown ? "unknown" : "requested",
|
|
113
|
-
connectionClosed: "not-confirmed",
|
|
114
|
-
...validUntil(),
|
|
115
|
-
message: `Chat session retirement was not confirmed (${e instanceof Error ? e.message : String(e)}). The auth service retires it at its expiry; its last bearer stays usable until then unless evicted.`,
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
let first;
|
|
120
|
-
let owner;
|
|
121
|
-
try {
|
|
122
|
-
first = await bearerFor({ ...auth, actor, holderProof });
|
|
123
|
-
const principal = bearerPrincipal(first.bearer);
|
|
124
|
-
if (principal.actor !== actor || principal.lifecycleUid !== lifecycleUid)
|
|
125
|
-
throw new Error("the chat bearer names another session than the one admitted");
|
|
126
|
-
owner = principal.owner;
|
|
127
|
-
}
|
|
128
|
-
catch (e) {
|
|
129
|
-
const close = await retire();
|
|
130
|
-
const f = providerFailure(e, { space, actor, lifecycleUid });
|
|
131
|
-
throw new CommandFailure(f.outcome, f.code, f.message, { target: { space, actor, lifecycleUid }, native: { ...(f.native ?? {}), detail: { close } }, ...(f.remedy ? { remedy: f.remedy } : {}) });
|
|
132
|
-
}
|
|
133
|
-
credentialValidUntil = first.exp * 1000;
|
|
134
|
-
let prefetched = first.bearer;
|
|
135
|
-
// Each renewal is a fresh holder-proof exchange; the service re-checks the parent pin and the
|
|
136
|
-
// holder index for every one, and refuses once the session has expired or been retired.
|
|
137
|
-
const bearerSource = async () => {
|
|
138
|
-
if (prefetched !== undefined) {
|
|
139
|
-
const bearer = prefetched;
|
|
140
|
-
prefetched = undefined;
|
|
141
|
-
return bearer;
|
|
142
|
-
}
|
|
143
|
-
const next = await bearerFor({ ...auth, actor, holderProof });
|
|
144
|
-
credentialValidUntil = Math.max(credentialValidUntil, next.exp * 1000);
|
|
145
|
-
return next.bearer;
|
|
146
|
-
};
|
|
147
|
-
const endpoint = new CotalEndpoint({
|
|
148
|
-
space,
|
|
149
|
-
servers: target.server,
|
|
150
|
-
tls: target.tlsRequired,
|
|
151
|
-
card: { owner, actor, name: options.label, kind: "endpoint", meta: { sessionKind: "chat" } },
|
|
152
|
-
lifecycleUid,
|
|
153
|
-
channels: [...options.channels],
|
|
154
|
-
bearer: bearerSource,
|
|
155
|
-
sentinelCreds: first.sentinelCreds,
|
|
156
|
-
});
|
|
157
|
-
const identity = {
|
|
158
|
-
mode: "user", space, principal: `${owner}.${actor}`, lifecycleUid, label: options.label,
|
|
159
|
-
allowSubscribe: [...options.read], allowPublish: [...options.post], expiresAt: expiresAtMs,
|
|
160
|
-
};
|
|
161
|
-
// Register the participant listeners before the endpoint starts; the session owns them until close.
|
|
162
|
-
const session = new NativeChatSession({ endpoint, identity, retire, reopen: options.reopen });
|
|
163
|
-
try {
|
|
164
|
-
await endpoint.start();
|
|
165
|
-
}
|
|
166
|
-
catch (e) {
|
|
167
|
-
const close = await session.close();
|
|
168
|
-
throw new CommandFailure("unknown", "OPERATION_UNKNOWN", `the user-mode chat session was admitted but did not connect (${e instanceof Error ? e.message : String(e)}); no automatic retry was made`, {
|
|
169
|
-
target: { space, principal: identity.principal, lifecycleUid },
|
|
170
|
-
native: { outcome: "unknown", detail: { close } },
|
|
171
|
-
remedy: "open a new session; this one was asked to retire",
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
// The session ends at its admitted expiry: the authority refuses every later bearer, so close
|
|
175
|
-
// here rather than let the connection lapse silently.
|
|
176
|
-
expiry = setTimeout(() => void session.close(), Math.max(0, expiresAtMs - Date.now()));
|
|
177
|
-
expiry.unref?.();
|
|
178
|
-
return session;
|
|
179
|
-
}
|
|
180
|
-
//# sourceMappingURL=user-session.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"user-session.js","sourceRoot":"","sources":["../../src/chat/user-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import type { NatsConnection } from "@nats-io/transport-node";
|
|
2
|
-
import { type SessionGrant } from "@cotal-ai/core";
|
|
3
|
-
/**
|
|
4
|
-
* The detach key — Ctrl-] (0x1d) by default, as in telnet/ssh escape conventions. The `detach-key`
|
|
5
|
-
* preference rebinds it to another control key when Ctrl-] clashes with a keybinding inside the
|
|
6
|
-
* agent's TUI: `COTAL_DETACH_KEY`, then the saved preference (`cotal config set detach-key`). Both
|
|
7
|
-
* accept `ctrl-<char>` or `^<char>` (e.g. `ctrl-b`, `^_`). An unparseable `COTAL_DETACH_KEY` —
|
|
8
|
-
* including a set-but-empty or whitespace-only one — throws (named), never silently falling back;
|
|
9
|
-
* the caller turns that into a loud exit. A saved value was validated when it was written.
|
|
10
|
-
*/
|
|
11
|
-
export declare function detachKey(): {
|
|
12
|
-
byte: number;
|
|
13
|
-
label: string;
|
|
14
|
-
overridden: boolean;
|
|
15
|
-
from: string;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Whether a whole chunk `d` is exactly one press of the detach key `byte`, in any of three
|
|
19
|
-
* encodings: the legacy single control byte; the kitty keyboard protocol's `CSI <codepoint> ;
|
|
20
|
-
* <mods> u`; or xterm `modifyOtherKeys`'s `CSI 27 ; <mods> ; <codepoint> ~`. `<codepoint>` is the
|
|
21
|
-
* decimal codepoint kitty/xterm report for the unshifted key: `byte | 0x40` for the control
|
|
22
|
-
* punctuation (`@ [ \ ] ^ _`) and `byte | 0x60` for a letter (kitty reports the lowercase key even
|
|
23
|
-
* though Ctrl was held). `<mods>` is 1 + the modifier bitmask and must carry the Ctrl bit
|
|
24
|
-
* (`(mods - 1) & 4`), so plain Ctrl (5) and Ctrl+Shift (6) match but a modifier field without Ctrl
|
|
25
|
-
* does not, and a field of 0, which neither protocol emits, is not a press either (the test needs
|
|
26
|
-
* that floor: `(0 - 1) & 4` is 4 in ToInt32 arithmetic, so 0 would otherwise read as Ctrl). The match is on the WHOLE chunk:
|
|
27
|
-
* a sequence with company (a paste, a second keystroke, a trailing byte) is not a press, which is
|
|
28
|
-
* the same paste-safety property the one-byte test already had. This assumes one press arrives in
|
|
29
|
-
* one read, as measured on a pty (issue #598); a sequence split across two reads is not buffered
|
|
30
|
-
* and is not recognised. A kitty `CSI u` with an alternate-key `<codepoint>:<shifted>:<base>` triple
|
|
31
|
-
* is accepted by matching only the leading codepoint before an optional `:...` group; no other
|
|
32
|
-
* kitty event type (release, repeat) is recognised.
|
|
33
|
-
*/
|
|
34
|
-
export declare function isDetachPress(d: Buffer, byte: number): boolean;
|
|
35
|
-
/**
|
|
36
|
-
* A transport-agnostic terminal session. {@link attachClient} drives the terminal through this
|
|
37
|
-
* interface, so the SAME raw-mode / alt-screen / detach handling serves the mesh §13.6 session
|
|
38
|
-
* ({@link meshSessionTransport}). (The legacy loopback `ws://.../attach/` transport was removed with
|
|
39
|
-
* the P2 item 6 no-127.0.0.1 sweep.)
|
|
40
|
-
*/
|
|
41
|
-
export interface TerminalTransport {
|
|
42
|
-
/** Fires once the transport is connected and ready to carry the terminal. */
|
|
43
|
-
onReady(cb: () => void): void;
|
|
44
|
-
/** Remote → local: terminal output bytes. The transport awaits an async consumer before returning
|
|
45
|
-
* credit, so a slow local stdout applies real backpressure instead of acknowledging unread bytes. */
|
|
46
|
-
onData(cb: (bytes: Buffer) => void | Promise<void>): void;
|
|
47
|
-
/** The session ended: `err` on a transport error (rejects), else a clean detach/close (resolves),
|
|
48
|
-
* with the peer's distinct end `reason` when it sent one. */
|
|
49
|
-
onEnd(cb: (err?: Error, reason?: string) => void): void;
|
|
50
|
-
/** Local → remote: keystroke bytes. */
|
|
51
|
-
send(bytes: Buffer): void;
|
|
52
|
-
/** Local → remote: terminal resize. */
|
|
53
|
-
resize(cols: number, rows: number): void;
|
|
54
|
-
/** Detach: signal the remote and stop locally. */
|
|
55
|
-
close(): void;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* The operator's terminal, held ACROSS attach attempts. A reconnect re-establishes the SESSION,
|
|
59
|
-
* not the terminal: restoring raw mode and leaving the child's alternate screen between attempts
|
|
60
|
-
* would flash the shell's screen back and then repaint over it, which is exactly the garble the
|
|
61
|
-
* reconnect is supposed to spare the operator. So the two facts that outlive one session — the
|
|
62
|
-
* mode the terminal was in before we touched it, and whether the child has us in its alternate
|
|
63
|
-
* screen — live here, and the undo runs exactly once, when the attach really ends.
|
|
64
|
-
*
|
|
65
|
-
* `attachClient` creates its own when no hold is passed, which is the one-shot behaviour: enter on
|
|
66
|
-
* ready, undo on end.
|
|
67
|
-
*/
|
|
68
|
-
export interface TerminalHold {
|
|
69
|
-
/** Raw mode on, remembering what we found. Idempotent across reconnects. */
|
|
70
|
-
enterRaw(): void;
|
|
71
|
-
/** Is the child in its alternate screen right now? Carried across reconnects so the final undo
|
|
72
|
-
* leaves that buffer exactly when the child put us there. */
|
|
73
|
-
altScreen: boolean;
|
|
74
|
-
/** Undo every mode we changed, leave the alternate screen if the child put us there, and give
|
|
75
|
-
* the terminal back the raw mode it had. Idempotent. */
|
|
76
|
-
restore(): void;
|
|
77
|
-
}
|
|
78
|
-
export declare function holdTerminal(): TerminalHold;
|
|
79
|
-
/**
|
|
80
|
-
* Why a session ended, as {@link attachClient} resolves it. The reason is the peer's distinct `end`
|
|
81
|
-
* reason, the transport's own (`detached`, `peer-closed`, `connection-closed`), or the broken
|
|
82
|
-
* rail's protocol-fault name. `error` is set when the end was a fault rather than a clean close;
|
|
83
|
-
* it is DATA here rather than a rejection, because a caller that reconnects has to read the reason
|
|
84
|
-
* to decide, and an exception carries it only as prose.
|
|
85
|
-
*/
|
|
86
|
-
export interface AttachOutcome {
|
|
87
|
-
readonly reason: string;
|
|
88
|
-
readonly error?: Error;
|
|
89
|
-
/** Did any seat output actually reach the terminal? The manager replays its backlog snapshot on
|
|
90
|
-
* every open, so a session that carried nothing never got that far — which is how a caller that
|
|
91
|
-
* reconnects tells a session that worked from one that died on the way up. */
|
|
92
|
-
readonly carried: boolean;
|
|
93
|
-
}
|
|
94
|
-
/** Did the session end because the LINK broke (so re-establishing is the honest response)? */
|
|
95
|
-
export declare function isTransportEnd(reason: string): boolean;
|
|
96
|
-
/**
|
|
97
|
-
* Drive a manager's attach session from the terminal: raw-mode stdin streams to the remote PTY,
|
|
98
|
-
* PTY output streams to stdout, and SIGWINCH-style resizes are forwarded. The detach key (Ctrl-]
|
|
99
|
-
* by default, {@link detachKey}) detaches without killing the agent. Transport-agnostic over the
|
|
100
|
-
* mesh §13.6 session.
|
|
101
|
-
*/
|
|
102
|
-
export declare function attachClient(transport: TerminalTransport, hold?: TerminalHold, takeStdin?: () => boolean): Promise<AttachOutcome>;
|
|
103
|
-
/**
|
|
104
|
-
* The mesh §13.6 SESSION transport: the item-6 replacement for the loopback WebSocket. Given a
|
|
105
|
-
* connection scoped to the session's eps rails and the redeemed grant, it opens the caller rail,
|
|
106
|
-
* asks the serving side to replay the reconstructed backlog (the `ready` handshake — PR #158 over
|
|
107
|
-
* the mesh), and speaks the core terminal-session frame codec. A `drop` frame is surfaced INLINE
|
|
108
|
-
* (never a silent loss); a peer `end`/close or a protocol fault ends the session with the distinct
|
|
109
|
-
* reason. No `127.0.0.1`, no bearer URL — the grant is holder-bound.
|
|
110
|
-
*/
|
|
111
|
-
export declare function meshSessionTransport(nc: NatsConnection, grant: SessionGrant): TerminalTransport;
|
|
112
|
-
//# sourceMappingURL=attach-client.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attach-client.d.ts","sourceRoot":"","sources":["../../src/lib/attach-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAgF,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIjI;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAW9F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAmB9D;AA4DD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC9B;0GACsG;IACtG,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D;kEAC8D;IAC9D,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACxD,uCAAuC;IACvC,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,uCAAuC;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,kDAAkD;IAClD,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,4EAA4E;IAC5E,QAAQ,IAAI,IAAI,CAAC;IACjB;kEAC8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB;6DACyD;IACzD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,wBAAgB,YAAY,IAAI,YAAY,CAoB3C;AA6BD;;;;;;GAMG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB;;mFAE+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAqBD,8FAA8F;AAC9F,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,iBAAiB,EAAE,IAAI,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,EAAE,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,CAiNjI;AAGD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,YAAY,GAAG,iBAAiB,CA6E/F"}
|