frely-cli 0.23.9 → 0.23.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +49 -20
  2. package/README.zh-CN.md +47 -19
  3. package/dist/agent/local/approvals.d.ts +24 -0
  4. package/dist/agent/local/approvals.js +79 -0
  5. package/dist/agent/local/approvals.js.map +1 -0
  6. package/dist/agent/local/command.d.ts +10 -0
  7. package/dist/agent/local/command.js +292 -0
  8. package/dist/agent/local/command.js.map +1 -0
  9. package/dist/agent/local/confine.d.ts +20 -0
  10. package/dist/agent/local/confine.js +52 -0
  11. package/dist/agent/local/confine.js.map +1 -0
  12. package/dist/agent/local/manifest.d.ts +17 -0
  13. package/dist/agent/local/manifest.js +55 -0
  14. package/dist/agent/local/manifest.js.map +1 -0
  15. package/dist/agent/local/model-proxy.d.ts +18 -0
  16. package/dist/agent/local/model-proxy.js +111 -0
  17. package/dist/agent/local/model-proxy.js.map +1 -0
  18. package/dist/agent/local/source.d.ts +28 -0
  19. package/dist/agent/local/source.js +64 -0
  20. package/dist/agent/local/source.js.map +1 -0
  21. package/dist/agent/local/store.d.ts +45 -0
  22. package/dist/agent/local/store.js +78 -0
  23. package/dist/agent/local/store.js.map +1 -0
  24. package/dist/agent/local/supervisor.d.ts +9 -0
  25. package/dist/agent/local/supervisor.js +62 -0
  26. package/dist/agent/local/supervisor.js.map +1 -0
  27. package/dist/agent-help.d.ts +118 -10
  28. package/dist/agent-help.js +25 -6
  29. package/dist/agent-help.js.map +1 -1
  30. package/dist/index.js +35 -5
  31. package/dist/index.js.map +1 -1
  32. package/dist/provider/control.d.ts +10 -0
  33. package/dist/provider/control.js +19 -0
  34. package/dist/provider/control.js.map +1 -1
  35. package/dist/provider/share.js +4 -1
  36. package/dist/provider/share.js.map +1 -1
  37. package/dist/runtime/sandbox.d.ts +20 -0
  38. package/dist/runtime/sandbox.js +39 -1
  39. package/dist/runtime/sandbox.js.map +1 -1
  40. package/dist/share/allowance.d.ts +8 -0
  41. package/dist/share/allowance.js +22 -0
  42. package/dist/share/allowance.js.map +1 -0
  43. package/dist/share/control.d.ts +2 -0
  44. package/dist/share/control.js +14 -10
  45. package/dist/share/control.js.map +1 -1
  46. package/dist/share/service-config.d.ts +39 -0
  47. package/dist/share/service-config.js +85 -0
  48. package/dist/share/service-config.js.map +1 -0
  49. package/dist/share/service-control.d.ts +15 -0
  50. package/dist/share/service-control.js +31 -0
  51. package/dist/share/service-control.js.map +1 -0
  52. package/dist/share/service-run.d.ts +55 -0
  53. package/dist/share/service-run.js +285 -0
  54. package/dist/share/service-run.js.map +1 -0
  55. package/dist/share/service-state.d.ts +16 -0
  56. package/dist/share/service-state.js +66 -0
  57. package/dist/share/service-state.js.map +1 -0
  58. package/dist/skill/access.d.ts +2 -2
  59. package/dist/skill/access.js +4 -2
  60. package/dist/skill/access.js.map +1 -1
  61. package/dist/skill/cloud-item.d.ts +2 -2
  62. package/dist/skill/cloud-item.js.map +1 -1
  63. package/dist/skill/entry.d.ts +1 -1
  64. package/dist/skill/entry.js +1 -1
  65. package/dist/skill/remote-mcp.d.ts +3 -0
  66. package/dist/skill/remote-mcp.js +7 -1
  67. package/dist/skill/remote-mcp.js.map +1 -1
  68. package/dist/skill/router.d.ts +6 -2
  69. package/dist/skill/router.js +4 -4
  70. package/dist/skill/router.js.map +1 -1
  71. package/dist/uninstall.d.ts +4 -0
  72. package/dist/uninstall.js +14 -0
  73. package/dist/uninstall.js.map +1 -1
  74. package/package.json +3 -2
@@ -0,0 +1,292 @@
1
+ import { spawn } from "node:child_process";
2
+ import { closeSync, openSync } from "node:fs";
3
+ import { mkdir, readFile, rm, stat } from "node:fs/promises";
4
+ import { fileURLToPath } from "node:url";
5
+ import { inspectAuth, normalizeRelayUrl, requireLogin } from "../../auth.js";
6
+ import { cliLaunchArguments } from "../../cli-launch.js";
7
+ import { credentialStore } from "../../credential-store.js";
8
+ import { ControllerError, EXIT } from "../../controller/session.js";
9
+ import { restrictSandboxNetwork, sandboxUnavailableReason, shutdownSandbox } from "../../runtime/sandbox.js";
10
+ import { approveSites } from "./approvals.js";
11
+ import { API_KEY_SERVICE, agentEnv, gatewayOrigin, readApiKey, spawnConfined } from "./confine.js";
12
+ import { parseManifest } from "./manifest.js";
13
+ import { download, githubUrl, parseSource, resolveRegisteredRepo } from "./source.js";
14
+ import { SLUG, agentsRoot, approvedHosts, assertSlug, insideAgentsRoot, isRunning, listRecords, logPath, readRecord, removeRecordFiles, stateDir, workspaceOf, writeRecord, } from "./store.js";
15
+ import { superviseAgent } from "./supervisor.js";
16
+ export const LOCAL_USAGE = `Usage:
17
+ frely agent local add <username/name | https://github.com/owner/repo> [--name <folder-name>]
18
+ frely agent local start <name> [--foreground]
19
+ frely agent local stop <name>
20
+ frely agent local logs <name> [--lines <n>] [--follow]
21
+ frely agent local list [--json]
22
+ frely agent local remove <name>
23
+ frely agent local key --api-key-stdin | --clear
24
+ `;
25
+ const fail = (message, code = EXIT.cli) => { throw new ControllerError(message, code); };
26
+ const flag = (args, name) => args.includes(name);
27
+ function value(args, name) {
28
+ const index = args.indexOf(name);
29
+ if (index < 0)
30
+ return undefined;
31
+ const next = args[index + 1];
32
+ if (!next || next.startsWith("--"))
33
+ return fail(`${name} needs a value.`);
34
+ return next;
35
+ }
36
+ const positional = (args) => args.filter((arg, index) => !arg.startsWith("--") && !(index > 0 && ["--name", "--lines"].includes(args[index - 1])));
37
+ /** Runs `frely agent local ...`; returns the exit code. */
38
+ export async function runAgentLocal(args, io, deps = {}) {
39
+ try {
40
+ const [action, ...rest] = args;
41
+ switch (action) {
42
+ case "add": return await add(rest, io, deps);
43
+ case "start": return await start(rest, io, deps);
44
+ case "stop": return await stop(rest, io);
45
+ case "logs": return await logs(rest, io);
46
+ case "list": return await list(rest, io);
47
+ case "remove": return await remove(rest, io);
48
+ case "key": return await key(rest, io);
49
+ case "supervise": return await superviseAgent(rest[0] ?? "");
50
+ default:
51
+ io.out(LOCAL_USAGE);
52
+ return action === undefined ? EXIT.ok : EXIT.cli;
53
+ }
54
+ }
55
+ catch (error) {
56
+ if (error instanceof ControllerError) {
57
+ io.err(error.message + "\n");
58
+ return error.exitCode;
59
+ }
60
+ io.err((error instanceof Error ? error.message : String(error)) + "\n");
61
+ return EXIT.cli;
62
+ }
63
+ }
64
+ function slugFor(source, requested, manifestName) {
65
+ const raw = requested ?? (source.kind === "frely" ? source.name : source.repo);
66
+ const slug = raw.toLowerCase().replace(/[^a-z0-9-]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 63);
67
+ if (!SLUG.test(slug))
68
+ return fail(`Could not make a folder name from ${JSON.stringify(manifestName ?? raw)}. Pass --name <letters-digits-dashes>.`);
69
+ return slug;
70
+ }
71
+ async function add(args, io, deps) {
72
+ const [target] = positional(args);
73
+ if (!target)
74
+ return fail(LOCAL_USAGE);
75
+ const source = parseSource(target);
76
+ const requested = value(args, "--name");
77
+ if (requested !== undefined)
78
+ assertSlug(requested);
79
+ const relayUrl = normalizeRelayUrl((await inspectAuth().catch(() => null))?.relayUrl);
80
+ const unavailable = sandboxUnavailableReason();
81
+ if (unavailable)
82
+ return fail(`Agents run on this computer only inside the Frely sandbox, and it cannot run here (${unavailable}). On Linux install bubblewrap, socat and ripgrep; Windows is not supported.`, EXIT.tool);
83
+ // Resume an Agent whose setup was interrupted (for example by an approval link) instead of downloading it again.
84
+ const existing = (await listRecords()).find((item) => !item.setupDone && item.source === target && (requested === undefined || item.slug === requested));
85
+ let record;
86
+ if (existing) {
87
+ record = existing;
88
+ }
89
+ else {
90
+ const registered = source.kind === "frely" ? await resolveRegisteredRepo(source.user, source.name, relayUrl) : undefined;
91
+ const repoUrl = registered?.repoUrl ?? githubUrl(source);
92
+ const slug = slugFor(source, requested, registered?.name);
93
+ if (await readRecord(slug))
94
+ return fail(`${slug} is already on this computer. Remove it first with frely agent local remove ${slug}, or pick another --name.`);
95
+ const workspace = workspaceOf(slug);
96
+ if (await stat(workspace).then(() => true, () => false))
97
+ return fail(`${workspace} already exists. Pick another --name or move that folder away.`);
98
+ io.err(`Downloading ${repoUrl}${registered?.commit ? ` at ${registered.commit.slice(0, 8)}` : ""}…\n`);
99
+ const commit = await download(repoUrl, workspace, registered?.commit).catch(async (error) => { await rm(workspace, { recursive: true, force: true }); throw error; });
100
+ let manifest;
101
+ try {
102
+ manifest = parseManifest(await readFile(`${workspace}/frely.yaml`, "utf8").catch(() => fail("The repository has no frely.yaml, so it cannot run through Frely.")));
103
+ }
104
+ catch (error) {
105
+ await rm(workspace, { recursive: true, force: true });
106
+ throw error;
107
+ }
108
+ record = { version: 1, slug, source: target, repoUrl, commit, name: manifest.name ?? registered?.name ?? slug, workspace, setup: manifest.setup, run: manifest.run, network: [...manifest.network],
109
+ addedAt: new Date().toISOString(), setupDone: false, approvals: {}, pid: undefined, startedAt: undefined };
110
+ await writeRecord(record);
111
+ }
112
+ io.out(`${record.name} (${record.repoUrl} at ${record.commit.slice(0, 8)})\n runs: ${record.run}\n${record.setup ? ` setup: ${record.setup}\n` : ""} folder: ${record.workspace}\n`);
113
+ io.out(` can reach: Frely's API${record.network.length ? `, and after your approval ${record.network.join(", ")}` : " only"}\n`);
114
+ record = await withApprovals(record, io, deps);
115
+ if (record.setup && !record.setupDone) {
116
+ io.err(`Running setup inside the sandbox: ${record.setup}\n`);
117
+ const code = await runSetup(record, relayUrl, io);
118
+ if (code !== 0)
119
+ return fail(`Setup failed (exit ${code}). Fix it or remove the Agent with frely agent local remove ${record.slug}, then run add again.`, EXIT.tool);
120
+ }
121
+ await writeRecord({ ...record, setupDone: true });
122
+ io.out(`Added. Start it with: frely agent local start ${record.slug}\n`);
123
+ return EXIT.ok;
124
+ }
125
+ async function withApprovals(record, io, deps) {
126
+ // When the owner has not answered yet this throws and keeps the download, so the same command carries on from here.
127
+ const gained = await approveSites(record, io, deps);
128
+ if (Object.keys(gained).length === 0)
129
+ return record;
130
+ const next = { ...record, approvals: { ...record.approvals, ...gained } };
131
+ await writeRecord(next);
132
+ return next;
133
+ }
134
+ async function runSetup(record, relayUrl, io) {
135
+ restrictSandboxNetwork({ allowedDomains: [new URL(gatewayOrigin(relayUrl)).hostname, ...approvedHosts(record)] });
136
+ await mkdir(`${record.workspace}/.cache`, { recursive: true });
137
+ try {
138
+ const { child, violations } = await spawnConfined(record.setup, record.workspace, agentEnv(record.workspace, { model: false }));
139
+ child.stdout?.on("data", (data) => io.err(data.toString("utf8")));
140
+ child.stderr?.on("data", (data) => io.err(data.toString("utf8")));
141
+ const code = await new Promise((done) => { child.once("error", () => done(1)); child.once("close", (exit) => done(exit ?? 1)); });
142
+ const blocked = violations();
143
+ if (code !== 0 && blocked.length > 0)
144
+ io.err(`The sandbox blocked:\n${[...new Set(blocked)].slice(0, 10).join("\n")}\nIf a site is missing, the Agent's author needs to list it under local.network in frely.yaml.\n`);
145
+ return code;
146
+ }
147
+ finally {
148
+ await shutdownSandbox();
149
+ }
150
+ }
151
+ async function start(args, io, deps) {
152
+ const [slug] = positional(args);
153
+ if (!slug)
154
+ return fail("Usage: frely agent local start <name> [--foreground]");
155
+ assertSlug(slug);
156
+ let record = await readRecord(slug) ?? fail(`No local Agent named ${slug}. See frely agent local list.`);
157
+ if (!record.setupDone)
158
+ return fail(`${slug} was not set up yet. Run frely agent local add again to finish.`);
159
+ if (isRunning(record))
160
+ return fail(`${slug} is already running (process ${record.pid}). Stop it first to apply new approvals.`);
161
+ record = await withApprovals(record, io, deps);
162
+ await preflight(record);
163
+ if (flag(args, "--foreground"))
164
+ return superviseAgent(slug);
165
+ await mkdir(stateDir(), { recursive: true, mode: 0o700 });
166
+ let supervisor;
167
+ const log = openSync(logPath(slug), "a", 0o600);
168
+ try {
169
+ const launch = cliLaunchArguments(fileURLToPath(new URL("../../index.js", import.meta.url)), ["agent", "local", "supervise", slug]);
170
+ const child = spawn(launch[0], launch.slice(1), { detached: true, stdio: ["ignore", log, log], env: process.env, windowsHide: true });
171
+ child.unref();
172
+ supervisor = child.pid;
173
+ }
174
+ finally {
175
+ closeSync(log);
176
+ }
177
+ // The supervisor records its own process id once the Agent is up; wait briefly so a failed start is reported here.
178
+ for (let waited = 0; waited < 15_000; waited += 250) {
179
+ await new Promise((done) => setTimeout(done, 250));
180
+ const current = await readRecord(slug);
181
+ if (current && isRunning(current)) {
182
+ io.out(`${slug} is running. Logs: frely agent local logs ${slug}\n`);
183
+ return EXIT.ok;
184
+ }
185
+ if (supervisor === undefined || !isRunning({ pid: supervisor })) {
186
+ const tail = (await readFile(logPath(slug), "utf8").catch(() => "")).trim().split("\n").slice(-6).join("\n");
187
+ return fail(`${slug} did not start:\n${tail}`, EXIT.tool);
188
+ }
189
+ }
190
+ return fail(`${slug} did not report that it started. See frely agent local logs ${slug}.`, EXIT.tool);
191
+ }
192
+ /** The two things a start needs besides the download: a login and a key for the model calls. Said now, not in a log file. */
193
+ async function preflight(record) {
194
+ const login = await requireLogin().catch(() => fail("Frely login is required. Run `frely login`."));
195
+ if (!await readApiKey(gatewayOrigin(login.config.relayUrl))) {
196
+ fail(`${record.slug} needs a Frely API key for its model calls. Create one at ${login.config.relayUrl}/user/keys, then run: frely agent local key --api-key-stdin`);
197
+ }
198
+ }
199
+ async function stop(args, io) {
200
+ const [slug] = positional(args);
201
+ if (!slug)
202
+ return fail("Usage: frely agent local stop <name>");
203
+ assertSlug(slug);
204
+ const record = await readRecord(slug) ?? fail(`No local Agent named ${slug}.`);
205
+ if (!isRunning(record)) {
206
+ io.out(`${slug} is not running.\n`);
207
+ return EXIT.ok;
208
+ }
209
+ process.kill(record.pid, "SIGTERM");
210
+ for (let waited = 0; waited < 8000 && isRunning(record); waited += 200)
211
+ await new Promise((done) => setTimeout(done, 200));
212
+ if (isRunning(record)) {
213
+ try {
214
+ process.kill(record.pid, "SIGKILL");
215
+ }
216
+ catch { /* already gone */ }
217
+ }
218
+ await writeRecord({ ...record, pid: undefined, startedAt: undefined });
219
+ io.out(`${slug} stopped.\n`);
220
+ return EXIT.ok;
221
+ }
222
+ async function logs(args, io) {
223
+ const [slug] = positional(args);
224
+ if (!slug)
225
+ return fail("Usage: frely agent local logs <name> [--lines <n>] [--follow]");
226
+ assertSlug(slug);
227
+ if (!await readRecord(slug))
228
+ return fail(`No local Agent named ${slug}.`);
229
+ const lines = Number(value(args, "--lines") ?? 100);
230
+ if (!Number.isInteger(lines) || lines < 1 || lines > 10_000)
231
+ return fail("--lines must be 1 to 10000.");
232
+ const text = await readFile(logPath(slug), "utf8").catch(() => "");
233
+ const all = text.split("\n");
234
+ io.out(all.slice(-lines - 1).join("\n"));
235
+ if (!flag(args, "--follow"))
236
+ return EXIT.ok;
237
+ let offset = Buffer.byteLength(text);
238
+ for (;;) {
239
+ await new Promise((done) => setTimeout(done, 1000));
240
+ const size = (await stat(logPath(slug)).catch(() => undefined))?.size ?? 0;
241
+ if (size > offset) {
242
+ const handle = await readFile(logPath(slug));
243
+ io.out(handle.subarray(offset).toString("utf8"));
244
+ offset = size;
245
+ }
246
+ }
247
+ }
248
+ async function list(args, io) {
249
+ const records = await listRecords();
250
+ if (flag(args, "--json")) {
251
+ io.out(JSON.stringify(records.map((r) => ({ name: r.slug, title: r.name, source: r.source, commit: r.commit, workspace: r.workspace, running: isRunning(r), setupDone: r.setupDone, sites: r.network, approved: approvedHosts(r) })), null, 2) + "\n");
252
+ return EXIT.ok;
253
+ }
254
+ if (records.length === 0) {
255
+ io.out(`No local Agents. Add one with frely agent local add <username/name>. They live under ${agentsRoot()}.\n`);
256
+ return EXIT.ok;
257
+ }
258
+ io.out(records.map((r) => `${r.slug}\t${isRunning(r) ? "running" : r.setupDone ? "stopped" : "not set up"}\t${r.source}\t${r.commit.slice(0, 8)}`).join("\n") + "\n");
259
+ return EXIT.ok;
260
+ }
261
+ async function remove(args, io) {
262
+ const [slug] = positional(args);
263
+ if (!slug)
264
+ return fail("Usage: frely agent local remove <name>");
265
+ assertSlug(slug);
266
+ const record = await readRecord(slug) ?? fail(`No local Agent named ${slug}.`);
267
+ if (isRunning(record))
268
+ await stop([slug], io);
269
+ if (!insideAgentsRoot(record.workspace))
270
+ return fail(`Refusing to delete ${record.workspace}: it is not inside ${agentsRoot()}.`);
271
+ await rm(record.workspace, { recursive: true, force: true });
272
+ await removeRecordFiles(slug);
273
+ io.out(`${slug} removed, with its folder ${record.workspace}.\n`);
274
+ return EXIT.ok;
275
+ }
276
+ async function key(args, io) {
277
+ const origin = gatewayOrigin((await requireLogin().catch(() => fail("Frely login is required. Run `frely login`."))).config.relayUrl);
278
+ if (flag(args, "--clear")) {
279
+ await credentialStore.deletePassword(API_KEY_SERVICE, origin);
280
+ io.out("The saved API key was removed.\n");
281
+ return EXIT.ok;
282
+ }
283
+ if (!flag(args, "--api-key-stdin"))
284
+ return fail("Usage: frely agent local key --api-key-stdin | --clear");
285
+ const secret = await io.readSecret();
286
+ if (Buffer.byteLength(secret, "utf8") < 8 || Buffer.byteLength(secret, "utf8") > 8192 || /[\x00-\x20\x7f]/u.test(secret))
287
+ return fail("The API key is invalid.");
288
+ await credentialStore.setPassword(API_KEY_SERVICE, origin, secret);
289
+ io.out("The API key was saved in this computer's secure storage. Local Agents use it for their model calls.\n");
290
+ return EXIT.ok;
291
+ }
292
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../../src/agent/local/command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ import { type CredentialStore } from "../../credential-store.js";
3
+ export declare const API_KEY_SERVICE = "frely-cli-local-agent-key-v1";
4
+ /** Where the Agent's model calls go: the public gateway for frely.cloud, the relay itself elsewhere (development). */
5
+ export declare function gatewayOrigin(relayUrl: string, env?: NodeJS.ProcessEnv): string;
6
+ /** The key for the Agent's model calls: FRELY_API_KEY when set, else the one saved with `frely agent local key`. */
7
+ export declare function readApiKey(origin: string, env?: NodeJS.ProcessEnv, store?: CredentialStore): Promise<string | undefined>;
8
+ /**
9
+ * The environment of the Agent's program. Not the caller's environment: a key or token exported in the shell must not reach code
10
+ * from a repository. Package managers get caches inside the Agent's folder, the only place besides the temp folder they may write.
11
+ */
12
+ export declare function agentEnv(workspace: string, hosts: {
13
+ model: boolean;
14
+ }, base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
15
+ export interface Confined {
16
+ child: ChildProcess;
17
+ violations(): string[];
18
+ }
19
+ /** Starts `command` inside the sandbox, in the Agent's own folder. Refused, never run bare, when this computer cannot sandbox it. */
20
+ export declare function spawnConfined(command: string, workspace: string, env: NodeJS.ProcessEnv): Promise<Confined>;
@@ -0,0 +1,52 @@
1
+ import { spawn } from "node:child_process";
2
+ import { join } from "node:path";
3
+ import { credentialStore as secureCredentialStore } from "../../credential-store.js";
4
+ import { sandboxCommandDetailed, sandboxViolationLines } from "../../runtime/sandbox.js";
5
+ import { MODEL_HOST } from "./model-proxy.js";
6
+ export const API_KEY_SERVICE = "frely-cli-local-agent-key-v1";
7
+ /** Where the Agent's model calls go: the public gateway for frely.cloud, the relay itself elsewhere (development). */
8
+ export function gatewayOrigin(relayUrl, env = process.env) {
9
+ const override = env.FRELY_GATEWAY_URL?.trim();
10
+ const url = new URL(override || relayUrl);
11
+ if (url.protocol !== "https:" && !(url.protocol === "http:" && ["127.0.0.1", "localhost", "::1"].includes(url.hostname)))
12
+ throw new Error("The Frely gateway must use HTTPS outside loopback development.");
13
+ if (!override && url.hostname === "frely.cloud")
14
+ return "https://api.frely.cloud";
15
+ return url.origin;
16
+ }
17
+ /** The key for the Agent's model calls: FRELY_API_KEY when set, else the one saved with `frely agent local key`. */
18
+ export async function readApiKey(origin, env = process.env, store = secureCredentialStore) {
19
+ const fromEnv = env.FRELY_API_KEY?.trim();
20
+ if (fromEnv)
21
+ return fromEnv;
22
+ return (await store.getPassword(API_KEY_SERVICE, origin).catch(() => null)) ?? undefined;
23
+ }
24
+ const PASS_THROUGH = ["PATH", "HOME", "USER", "LOGNAME", "SHELL", "LANG", "LC_ALL", "TERM", "TZ", "TMPDIR", "SystemRoot"];
25
+ /**
26
+ * The environment of the Agent's program. Not the caller's environment: a key or token exported in the shell must not reach code
27
+ * from a repository. Package managers get caches inside the Agent's folder, the only place besides the temp folder they may write.
28
+ */
29
+ export function agentEnv(workspace, hosts, base = process.env) {
30
+ const env = {};
31
+ for (const name of PASS_THROUGH)
32
+ if (base[name] !== undefined)
33
+ env[name] = base[name];
34
+ const cache = join(workspace, ".cache");
35
+ Object.assign(env, { XDG_CACHE_HOME: cache, UV_CACHE_DIR: join(cache, "uv"), PIP_CACHE_DIR: join(cache, "pip"), npm_config_cache: join(cache, "npm"), BUN_INSTALL_CACHE_DIR: join(cache, "bun") });
36
+ if (hosts.model) {
37
+ const base = `http://${MODEL_HOST}`;
38
+ Object.assign(env, {
39
+ FRELY_MODEL_BASE_URL: `${base}/v1`,
40
+ OPENAI_BASE_URL: `${base}/v1`, OPENAI_API_BASE: `${base}/v1`, OPENAI_API_KEY: "frely-local-placeholder",
41
+ ANTHROPIC_BASE_URL: base, ANTHROPIC_API_KEY: "frely-local-placeholder",
42
+ });
43
+ }
44
+ return env;
45
+ }
46
+ /** Starts `command` inside the sandbox, in the Agent's own folder. Refused, never run bare, when this computer cannot sandbox it. */
47
+ export async function spawnConfined(command, workspace, env) {
48
+ const wrapped = await sandboxCommandDetailed(command, workspace);
49
+ const child = spawn(wrapped.command, { cwd: workspace, env, shell: true, stdio: ["ignore", "pipe", "pipe"], detached: process.platform !== "win32", windowsHide: true });
50
+ return { child, violations: () => sandboxViolationLines(wrapped.commandId) };
51
+ }
52
+ //# sourceMappingURL=confine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confine.js","sourceRoot":"","sources":["../../../src/agent/local/confine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /** What `frely.yaml` says about running the repository on this computer (the `local:` section). */
2
+ export interface LocalManifest {
3
+ /** Display name; the repository name when the file has none. */
4
+ name: string | undefined;
5
+ /** Runs once after the download, inside the sandbox. */
6
+ setup: string | undefined;
7
+ /** Starts the Agent, inside the sandbox. */
8
+ run: string;
9
+ /** Extra sites the Agent needs beyond Frely's API. Each one needs the owner's approval. */
10
+ network: readonly string[];
11
+ }
12
+ export declare class ManifestError extends Error {
13
+ constructor(message: string);
14
+ }
15
+ export declare function isApprovableHost(value: unknown): value is string;
16
+ /** Reads the `local:` section of a repository's `frely.yaml`. Throws ManifestError with a sentence the person can act on. */
17
+ export declare function parseManifest(text: string): LocalManifest;
@@ -0,0 +1,55 @@
1
+ import { parse } from "yaml";
2
+ export class ManifestError extends Error {
3
+ constructor(message) { super(message); this.name = "ManifestError"; }
4
+ }
5
+ const MAX_MANIFEST_BYTES = 64 * 1024;
6
+ const MAX_COMMAND_CHARS = 500;
7
+ const MAX_NETWORK_HOSTS = 20;
8
+ /** A plain lower-case DNS name with at least one dot. No wildcards, ports, IP literals or `localhost`. */
9
+ const HOST = /^(?=.{4,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]{0,61}[a-z0-9]$/u;
10
+ export function isApprovableHost(value) {
11
+ return typeof value === "string" && HOST.test(value) && !/^\d+(?:\.\d+)+$/u.test(value) && !value.endsWith(".localhost") && !value.endsWith(".local");
12
+ }
13
+ const asObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : undefined;
14
+ function command(value, field, required) {
15
+ if (value === undefined || value === null) {
16
+ if (required)
17
+ throw new ManifestError(`frely.yaml: local.${field} is required.`);
18
+ return undefined;
19
+ }
20
+ if (typeof value !== "string" || value.trim() === "" || value.length > MAX_COMMAND_CHARS || /[\0\r\n]/u.test(value)) {
21
+ throw new ManifestError(`frely.yaml: local.${field} must be one line of at most ${MAX_COMMAND_CHARS} characters.`);
22
+ }
23
+ return value.trim();
24
+ }
25
+ /** Reads the `local:` section of a repository's `frely.yaml`. Throws ManifestError with a sentence the person can act on. */
26
+ export function parseManifest(text) {
27
+ if (Buffer.byteLength(text, "utf8") > MAX_MANIFEST_BYTES)
28
+ throw new ManifestError("frely.yaml is larger than 64 KiB.");
29
+ let document;
30
+ try {
31
+ document = parse(text, { maxAliasCount: 0 });
32
+ }
33
+ catch (error) {
34
+ throw new ManifestError(`frely.yaml is not valid YAML: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`);
35
+ }
36
+ const root = asObject(document);
37
+ if (!root)
38
+ throw new ManifestError("frely.yaml must be a mapping.");
39
+ const local = asObject(root.local);
40
+ if (!local)
41
+ throw new ManifestError("frely.yaml has no local: section, so this repository cannot run on this computer. It needs local.run (and optionally local.setup).");
42
+ const name = root.name === undefined ? undefined : typeof root.name === "string" && root.name.trim() !== "" && root.name.length <= 100 && !/[\0\r\n]/u.test(root.name) ? root.name.trim() : (() => { throw new ManifestError("frely.yaml: name must be a short single line."); })();
43
+ const hosts = local.network ?? [];
44
+ if (!Array.isArray(hosts) || hosts.length > MAX_NETWORK_HOSTS)
45
+ throw new ManifestError(`frely.yaml: local.network must be a list of at most ${MAX_NETWORK_HOSTS} site names.`);
46
+ const network = [];
47
+ for (const host of hosts) {
48
+ if (!isApprovableHost(host))
49
+ throw new ManifestError(`frely.yaml: local.network entry ${JSON.stringify(host)} is not an exact site name such as pypi.org (no wildcards, ports or addresses).`);
50
+ if (!network.includes(host))
51
+ network.push(host);
52
+ }
53
+ return { name, setup: command(local.setup, "setup", false), run: command(local.run, "run", true), network };
54
+ }
55
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../src/agent/local/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The name the Agent's program uses for model access, as plain http:// (`OPENAI_BASE_URL=http://frely-model.local/v1`).
3
+ * The sandbox's own proxy hands every request for this name to the Unix socket below, so the request reaches this file and nothing else.
4
+ * The program therefore never holds a Frely credential: it sends a placeholder key, and the real one is added here, outside the sandbox.
5
+ */
6
+ export declare const MODEL_HOST = "frely-model.local";
7
+ export interface ModelProxyOptions {
8
+ socketPath: string;
9
+ /** The gateway origin, for example https://api.frely.cloud. */
10
+ upstream: string;
11
+ /** The `Authorization` header value for one upstream call. Read per call so a renewed credential is used. */
12
+ authorization(): Promise<string>;
13
+ fetchFn?: typeof fetch;
14
+ }
15
+ export interface ModelProxy {
16
+ close(): Promise<void>;
17
+ }
18
+ export declare function startModelProxy(options: ModelProxyOptions): Promise<ModelProxy>;
@@ -0,0 +1,111 @@
1
+ import { createServer } from "node:http";
2
+ import { chmod, mkdir, rm } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { Readable } from "node:stream";
5
+ /**
6
+ * The name the Agent's program uses for model access, as plain http:// (`OPENAI_BASE_URL=http://frely-model.local/v1`).
7
+ * The sandbox's own proxy hands every request for this name to the Unix socket below, so the request reaches this file and nothing else.
8
+ * The program therefore never holds a Frely credential: it sends a placeholder key, and the real one is added here, outside the sandbox.
9
+ */
10
+ export const MODEL_HOST = "frely-model.local";
11
+ const MAX_BODY_BYTES = 16 * 1024 * 1024;
12
+ /** Only the model calls: nothing about the account, keys or billing. */
13
+ const ROUTES = new Map([
14
+ ["POST /v1/chat/completions", "POST"], ["POST /v1/responses", "POST"], ["POST /v1/embeddings", "POST"],
15
+ ["POST /v1/messages", "POST"], ["POST /v1/messages/count_tokens", "POST"], ["GET /v1/models", "GET"],
16
+ ]);
17
+ /** Request headers passed on. Everything else, above all anything that authenticates, is dropped. */
18
+ const FORWARD_REQUEST = ["content-type", "accept", "anthropic-version", "anthropic-beta", "openai-beta"];
19
+ const FORWARD_RESPONSE = ["content-type", "cache-control", "retry-after", "x-request-id"];
20
+ function reply(response, status, message) {
21
+ if (response.headersSent) {
22
+ response.destroy();
23
+ return;
24
+ }
25
+ response.writeHead(status, { "content-type": "application/json" });
26
+ response.end(JSON.stringify({ error: { message, type: "frely_local_proxy" } }));
27
+ }
28
+ /** The body, or undefined when it is over the limit. An oversize body is still read to its end (not kept) so the sender gets the refusal instead of a broken pipe. */
29
+ async function readBody(request) {
30
+ const chunks = [];
31
+ let size = 0;
32
+ for await (const chunk of request) {
33
+ size += chunk.length;
34
+ if (size > 4 * MAX_BODY_BYTES) {
35
+ request.destroy();
36
+ break;
37
+ }
38
+ if (size <= MAX_BODY_BYTES)
39
+ chunks.push(chunk);
40
+ }
41
+ return size > MAX_BODY_BYTES ? undefined : Buffer.concat(chunks);
42
+ }
43
+ export async function startModelProxy(options) {
44
+ const fetchFn = options.fetchFn ?? fetch;
45
+ const upstream = new URL(options.upstream);
46
+ const handle = async (request, response) => {
47
+ // The sandbox proxy sends an absolute URL; anything else did not come through it.
48
+ let url;
49
+ try {
50
+ url = new URL(request.url ?? "");
51
+ }
52
+ catch {
53
+ return reply(response, 404, "Unknown host.");
54
+ }
55
+ if (url.protocol !== "http:" || url.hostname !== MODEL_HOST)
56
+ return reply(response, 404, "Unknown host.");
57
+ const method = ROUTES.get(`${request.method} ${url.pathname}`);
58
+ if (!method)
59
+ return reply(response, 404, "This path is not available to a local Agent. It can call the model endpoints only.");
60
+ const body = method === "POST" ? await readBody(request) : undefined;
61
+ if (method === "POST" && body === undefined)
62
+ return reply(response, 413, "The request is larger than 16 MiB.");
63
+ const headers = new Headers();
64
+ for (const name of FORWARD_REQUEST) {
65
+ const value = request.headers[name];
66
+ if (typeof value === "string")
67
+ headers.set(name, value);
68
+ }
69
+ try {
70
+ headers.set("authorization", await options.authorization());
71
+ }
72
+ catch (error) {
73
+ return reply(response, 401, error instanceof Error ? error.message : "No Frely credential.");
74
+ }
75
+ const abort = new AbortController();
76
+ response.once("close", () => abort.abort());
77
+ let result;
78
+ try {
79
+ result = await fetchFn(new URL(url.pathname + url.search, upstream), { method, headers, ...(body ? { body: new Uint8Array(body) } : {}), redirect: "error", signal: abort.signal });
80
+ }
81
+ catch {
82
+ return reply(response, 502, "Frely could not be reached.");
83
+ }
84
+ const out = {};
85
+ for (const name of FORWARD_RESPONSE) {
86
+ const value = result.headers.get(name);
87
+ if (value !== null)
88
+ out[name] = value;
89
+ }
90
+ response.writeHead(result.status, out);
91
+ if (!result.body) {
92
+ response.end();
93
+ return;
94
+ }
95
+ const stream = Readable.fromWeb(result.body);
96
+ stream.once("error", () => response.destroy());
97
+ stream.pipe(response);
98
+ };
99
+ const server = createServer((request, response) => { handle(request, response).catch(() => reply(response, 500, "The local model proxy failed.")); });
100
+ await mkdir(dirname(options.socketPath), { recursive: true, mode: 0o700 });
101
+ await rm(options.socketPath, { force: true });
102
+ await new Promise((done, fail) => { server.once("error", fail); server.listen(options.socketPath, done); });
103
+ await chmod(options.socketPath, 0o600).catch(() => undefined);
104
+ return {
105
+ close: async () => {
106
+ await new Promise((done) => { server.close(() => done()); server.closeAllConnections(); });
107
+ await rm(options.socketPath, { force: true });
108
+ },
109
+ };
110
+ }
111
+ //# sourceMappingURL=model-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-proxy.js","sourceRoot":"","sources":["../../../src/agent/local/model-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAE9C,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AACxC,wEAAwE;AACxE,MAAM,MAAM,GAAgC,IAAI,GAAG,CAAC;IAClD,CAAC,2BAA2B,EAAE,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACtG,CAAC,mBAAmB,EAAE,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,CAAC;CACrG,CAAC,CAAC;AACH,qGAAqG;AACrG,MAAM,eAAe,GAAG,CAAC,cAAc,EAAE,QAAQ,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,aAAa,CAAU,CAAC;AAClH,MAAM,gBAAgB,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,CAAU,CAAC;AAanG,SAAS,KAAK,CAAC,QAAwB,EAAE,MAAc,EAAE,OAAe;IACtE,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAAC,OAAO;IAAC,CAAC;IACzD,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IACnE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,sKAAsK;AACtK,KAAK,UAAU,QAAQ,CAAC,OAAwB;IAC9C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAClC,IAAI,IAAK,KAAgB,CAAC,MAAM,CAAC;QACjC,IAAI,IAAI,GAAG,CAAC,GAAG,cAAc,EAAE,CAAC;YAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAAC,MAAM;QAAC,CAAC;QAC5D,IAAI,IAAI,IAAI,cAAc;YAAE,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC,CAAC;IAC3D,CAAC;IACD,OAAO,IAAI,GAAG,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACnE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA0B;IAC9D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,KAAK,EAAE,OAAwB,EAAE,QAAwB,EAAiB,EAAE;QACzF,kFAAkF;QAClF,IAAI,GAAQ,CAAC;QACb,IAAI,CAAC;YAAC,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC;QAAC,CAAC;QACjG,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC;QAC1G,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,oFAAoF,CAAC,CAAC;QAC/H,MAAM,IAAI,GAAG,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,IAAI,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,oCAAoC,CAAC,CAAC;QAC/G,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAAC,CAAC;QACrI,IAAI,CAAC;YAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QAAC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAAC,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC;QAAC,CAAC;QACpL,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;QACpC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAC5C,IAAI,MAAgB,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACtL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,6BAA6B,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;YAAC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAAC,IAAI,KAAK,KAAK,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAAC,CAAC;QACvH,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;YAAC,OAAO;QAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,IAAa,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACxB,CAAC,CAAC;IACF,MAAM,MAAM,GAAW,YAAY,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,+BAA+B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9J,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClH,MAAM,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9D,OAAO;QACL,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,IAAI,OAAO,CAAO,CAAC,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YACjG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC"}