pi-forge 1.1.6 → 1.2.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/README.md +23 -13
- package/bin/pi-forge.mjs +34 -5
- package/dist/client/assets/{CodeMirrorEditor-C_ITRoQa.js → CodeMirrorEditor-D_P6wobf.js} +2 -2
- package/dist/client/assets/{CodeMirrorEditor-C_ITRoQa.js.map → CodeMirrorEditor-D_P6wobf.js.map} +1 -1
- package/dist/client/assets/index-BDOppLth.css +1 -0
- package/dist/client/assets/{index-B67tDt4n.js → index-Bv9XfcDK.js} +71 -71
- package/dist/client/assets/index-Bv9XfcDK.js.map +1 -0
- package/dist/client/index.html +14 -3
- package/dist/client/manifest.webmanifest +1 -1
- package/dist/client/sw.js +1 -1
- package/dist/client/sw.js.map +1 -1
- package/dist/server/cli.js +512 -0
- package/dist/server/cli.js.map +1 -0
- package/dist/server/config.js +29 -14
- package/dist/server/config.js.map +1 -1
- package/dist/server/git-hunk-stager.js +137 -0
- package/dist/server/git-hunk-stager.js.map +1 -0
- package/dist/server/index.js +4 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/export.js +66 -0
- package/dist/server/routes/export.js.map +1 -0
- package/dist/server/routes/git.js +61 -0
- package/dist/server/routes/git.js.map +1 -1
- package/dist/server/routes/search.js +108 -0
- package/dist/server/routes/search.js.map +1 -0
- package/dist/server/session-exporter.js +490 -0
- package/dist/server/session-exporter.js.map +1 -0
- package/dist/server/session-searcher.js +490 -0
- package/dist/server/session-searcher.js.map +1 -0
- package/package.json +2 -2
- package/dist/client/assets/index-B67tDt4n.js.map +0 -1
- package/dist/client/assets/index-BB-19PiX.css +0 -1
package/dist/client/index.html
CHANGED
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
|
-
|
|
5
|
+
<!-- `interactive-widget=resizes-content`: when the on-screen
|
|
6
|
+
keyboard appears on iOS / Android, shrink the visual viewport
|
|
7
|
+
(i.e. take the keyboard's space out of the layout) instead of
|
|
8
|
+
the default `resizes-visual` which leaves layout untouched and
|
|
9
|
+
lets the keyboard overlay the page. The chat input lives at
|
|
10
|
+
the bottom of a flex column, so this lets it ride above the
|
|
11
|
+
keyboard automatically — no JS / visualViewport handling
|
|
12
|
+
needed. Safe on desktop (no keyboard, no effect). -->
|
|
13
|
+
<meta
|
|
14
|
+
name="viewport"
|
|
15
|
+
content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content"
|
|
16
|
+
/>
|
|
6
17
|
<meta name="theme-color" content="#0a0a0a" />
|
|
7
18
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
8
19
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
|
|
@@ -15,8 +26,8 @@
|
|
|
15
26
|
<link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192.png" />
|
|
16
27
|
<link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512.png" />
|
|
17
28
|
<title>pi-forge</title>
|
|
18
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
29
|
+
<script type="module" crossorigin src="/assets/index-Bv9XfcDK.js"></script>
|
|
30
|
+
<link rel="stylesheet" crossorigin href="/assets/index-BDOppLth.css">
|
|
20
31
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
21
32
|
<body class="bg-neutral-950 text-neutral-100 antialiased">
|
|
22
33
|
<div id="root"></div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"pi-forge","short_name":"pi-forge","description":"
|
|
1
|
+
{"name":"pi-forge","short_name":"pi-forge","description":"Self-hosted browser workbench for the pi coding agent — chat with the agent against your code, browse files, run a terminal, review diffs, all from one tab.","start_url":"/","display":"standalone","background_color":"#0a0a0a","theme_color":"#0a0a0a","lang":"en","scope":"/","orientation":"any","categories":["productivity","developer"],"icons":[{"src":"/icons/icon-192.png","sizes":"192x192","type":"image/png","purpose":"any"},{"src":"/icons/icon-512.png","sizes":"512x512","type":"image/png","purpose":"any"},{"src":"/icons/icon-maskable-512.png","sizes":"512x512","type":"image/png","purpose":"maskable"},{"src":"/icons/icon.svg","sizes":"any","type":"image/svg+xml","purpose":"any"}]}
|
package/dist/client/sw.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(i[c])return;let r={};const
|
|
1
|
+
if(!self.define){let e,i={};const n=(n,s)=>(n=new URL(n+".js",s).href,i[n]||new Promise(i=>{if("document"in self){const e=document.createElement("script");e.src=n,e.onload=i,document.head.appendChild(e)}else e=n,importScripts(n),i()}).then(()=>{let e=i[n];if(!e)throw new Error(`Module ${n} didn’t register its module`);return e}));self.define=(s,o)=>{const c=e||("document"in self?document.currentScript.src:"")||location.href;if(i[c])return;let r={};const f=e=>n(e,c),l={module:{uri:c},exports:r,require:f};i[c]=Promise.all(s.map(e=>l[e]||f(e))).then(e=>(o(...e),r))}}define(["./workbox-6d7155ed"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"},{url:"index.html",revision:"8edd7bc3602276fa52b938ad23fb9e06"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"assets/workbox-window.prod.es5-Cch4wiA5.js",revision:null},{url:"assets/index-Bv9XfcDK.js",revision:null},{url:"assets/index-BDOppLth.css",revision:null},{url:"assets/CodeMirrorEditor-D_P6wobf.js",revision:null},{url:"offline.html",revision:"e4f087b40040ff045a6fd572b5fed726"},{url:"icons/icon-192.png",revision:"54082a8d4e49f4e5c2ad5646b7fb7551"},{url:"icons/icon-512.png",revision:"c1b37dbf870c852577dbb4733f45c9c2"},{url:"icons/icon-maskable-512.png",revision:"734c73b2ee3cc3856c67bed196e7557f"},{url:"icons/icon.svg",revision:"549b462207e763a57c9dfbae214afc31"},{url:"manifest.webmanifest",revision:"aef9cb4935c3fba2754da10580256c9e"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api\//]})),e.registerRoute(({url:e})=>e.pathname.startsWith("/api/v1/"),new e.NetworkOnly,"GET"),e.registerRoute(({request:e})=>"navigate"===e.mode,new e.NetworkFirst({cacheName:"pi-navigation",networkTimeoutSeconds:3,plugins:[new e.PrecacheFallbackPlugin({fallbackURL:"/offline.html"})]}),"GET")});
|
|
2
2
|
//# sourceMappingURL=sw.js.map
|
|
3
3
|
//# sourceMappingURL=sw.js.map
|
package/dist/client/sw.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sw.js","sources":["../../../../../../../tmp/
|
|
1
|
+
{"version":3,"file":"sw.js","sources":["../../../../../../../tmp/72b15f0b3b13d01613fd783496f58823/sw.js"],"sourcesContent":["import {registerRoute as workbox_routing_registerRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/registerRoute.mjs';\nimport {NetworkOnly as workbox_strategies_NetworkOnly} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkOnly.mjs';\nimport {PrecacheFallbackPlugin as workbox_precaching_PrecacheFallbackPlugin} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/PrecacheFallbackPlugin.mjs';\nimport {NetworkFirst as workbox_strategies_NetworkFirst} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-strategies/NetworkFirst.mjs';\nimport {clientsClaim as workbox_core_clientsClaim} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-core/clientsClaim.mjs';\nimport {precacheAndRoute as workbox_precaching_precacheAndRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/precacheAndRoute.mjs';\nimport {cleanupOutdatedCaches as workbox_precaching_cleanupOutdatedCaches} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/cleanupOutdatedCaches.mjs';\nimport {NavigationRoute as workbox_routing_NavigationRoute} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-routing/NavigationRoute.mjs';\nimport {createHandlerBoundToURL as workbox_precaching_createHandlerBoundToURL} from '/home/runner/work/pi-forge/pi-forge/node_modules/workbox-precaching/createHandlerBoundToURL.mjs';/**\n * Welcome to your Workbox-powered service worker!\n *\n * You'll need to register this file in your web app.\n * See https://goo.gl/nhQhGp\n *\n * The rest of the code is auto-generated. Please don't update this file\n * directly; instead, make changes to your Workbox build configuration\n * and re-run your build process.\n * See https://goo.gl/2aRDsh\n */\n\n\n\n\nself.skipWaiting();\nworkbox_core_clientsClaim();\n/**\n * The precacheAndRoute() method efficiently caches and responds to\n * requests for URLs in the manifest.\n * See https://goo.gl/S9QRab\n */\nworkbox_precaching_precacheAndRoute([\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n },\n {\n \"url\": \"index.html\",\n \"revision\": \"8edd7bc3602276fa52b938ad23fb9e06\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"assets/workbox-window.prod.es5-Cch4wiA5.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-Bv9XfcDK.js\",\n \"revision\": null\n },\n {\n \"url\": \"assets/index-BDOppLth.css\",\n \"revision\": null\n },\n {\n \"url\": \"assets/CodeMirrorEditor-D_P6wobf.js\",\n \"revision\": null\n },\n {\n \"url\": \"offline.html\",\n \"revision\": \"e4f087b40040ff045a6fd572b5fed726\"\n },\n {\n \"url\": \"icons/icon-192.png\",\n \"revision\": \"54082a8d4e49f4e5c2ad5646b7fb7551\"\n },\n {\n \"url\": \"icons/icon-512.png\",\n \"revision\": \"c1b37dbf870c852577dbb4733f45c9c2\"\n },\n {\n \"url\": \"icons/icon-maskable-512.png\",\n \"revision\": \"734c73b2ee3cc3856c67bed196e7557f\"\n },\n {\n \"url\": \"icons/icon.svg\",\n \"revision\": \"549b462207e763a57c9dfbae214afc31\"\n },\n {\n \"url\": \"manifest.webmanifest\",\n \"revision\": \"aef9cb4935c3fba2754da10580256c9e\"\n }\n], {});\nworkbox_precaching_cleanupOutdatedCaches();workbox_routing_registerRoute(new workbox_routing_NavigationRoute(workbox_precaching_createHandlerBoundToURL(\"/index.html\"), {\n denylist: [/^\\/api\\//],}));\nworkbox_routing_registerRoute(({ url }) => url.pathname.startsWith(\"/api/v1/\"), new workbox_strategies_NetworkOnly(), 'GET');\nworkbox_routing_registerRoute(({ request }) => request.mode === \"navigate\", new workbox_strategies_NetworkFirst({ \"cacheName\":\"pi-navigation\",\"networkTimeoutSeconds\":3, plugins: [new workbox_precaching_PrecacheFallbackPlugin({ fallbackURL: '/offline.html' })] }), 'GET');\n\n\n"],"names":["self","skipWaiting","workbox_core_clientsClaim","workbox_precaching_precacheAndRoute","url","revision","workbox_precaching_cleanupOutdatedCaches","workbox_routing_registerRoute","workbox_routing_NavigationRoute","workbox_precaching_createHandlerBoundToURL","denylist","pathname","startsWith","workbox_strategies_NetworkOnly","request","mode","workbox_strategies_NetworkFirst","cacheName","networkTimeoutSeconds","plugins","workbox_precaching_PrecacheFallbackPlugin","fallbackURL"],"mappings":"inBAuBAA,KAAKC,cACLC,EAAAA,eAMAC,EAAAA,iBAAoC,CAClC,CACEC,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,oCAEd,CACED,IAAO,aACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,6CACPC,SAAY,MAEd,CACED,IAAO,2BACPC,SAAY,MAEd,CACED,IAAO,4BACPC,SAAY,MAEd,CACED,IAAO,sCACPC,SAAY,MAEd,CACED,IAAO,eACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,qBACPC,SAAY,oCAEd,CACED,IAAO,8BACPC,SAAY,oCAEd,CACED,IAAO,iBACPC,SAAY,oCAEd,CACED,IAAO,uBACPC,SAAY,qCAEb,CAAA,GACHC,EAAAA,wBAA2CC,EAAAA,cAA8B,IAAIC,EAAAA,gBAAgCC,0BAA2C,eAAgB,CACpKC,SAAU,CAAC,eACfH,EAAAA,cAA8B,EAAGH,SAAUA,EAAIO,SAASC,WAAW,YAAa,IAAIC,EAAAA,YAAkC,OACtHN,EAAAA,cAA8B,EAAGO,aAA+B,aAAjBA,EAAQC,KAAqB,IAAIC,EAAAA,aAAgC,CAAEC,UAAY,gBAAgBC,sBAAwB,EAAGC,QAAS,CAAC,IAAIC,yBAA0C,CAAEC,YAAa,qBAAwB"}
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-forge CLI argument parser.
|
|
3
|
+
*
|
|
4
|
+
* Pure module — does NOT import from `./config.js` or any other server
|
|
5
|
+
* module so it can run in the bin shim BEFORE the server module loads.
|
|
6
|
+
* Config reads `process.env` at import time, so flag → env writes must
|
|
7
|
+
* happen before that import.
|
|
8
|
+
*
|
|
9
|
+
* Single source of truth: the `FLAGS` table below drives:
|
|
10
|
+
* 1. argument parsing (via Node's built-in `node:util` parseArgs)
|
|
11
|
+
* 2. process.env mutation (each flag maps to its env-var equivalent)
|
|
12
|
+
* 3. `--help` rendering
|
|
13
|
+
*
|
|
14
|
+
* Adding a new env var → add one row here. Don't fork the table.
|
|
15
|
+
*
|
|
16
|
+
* Conventions:
|
|
17
|
+
* - Flag names: kebab-case, long-form only (no single-char shortcuts).
|
|
18
|
+
* - Boolean flags: `--foo true|false|on|off|1|0|yes|no`. Bare `--foo`
|
|
19
|
+
* is treated as `--foo=true`. `--no-foo` is treated as `--foo=false`.
|
|
20
|
+
* - Path flags: passed through verbatim (config.ts resolves them).
|
|
21
|
+
* - Sensitive flags (auth secrets): support `@<path>` syntax so the
|
|
22
|
+
* value can come from a file instead of argv (avoids shell history
|
|
23
|
+
* / `ps` exposure). Same convention `curl` and `gh` use.
|
|
24
|
+
* - Flag values always WIN over env. `pi-forge --port 4000` overrides
|
|
25
|
+
* `PORT=3000` in the environment. Env is a fallback — if the flag
|
|
26
|
+
* is absent, the existing env value persists, and config.ts handles
|
|
27
|
+
* the default.
|
|
28
|
+
*/
|
|
29
|
+
import { readFileSync } from "node:fs";
|
|
30
|
+
import { parseArgs } from "node:util";
|
|
31
|
+
const FLAGS = [
|
|
32
|
+
// network
|
|
33
|
+
{
|
|
34
|
+
name: "port",
|
|
35
|
+
env: "PORT",
|
|
36
|
+
type: "number",
|
|
37
|
+
group: "network",
|
|
38
|
+
desc: "HTTP listen port",
|
|
39
|
+
defaultText: "3000",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: "host",
|
|
43
|
+
env: "HOST",
|
|
44
|
+
type: "string",
|
|
45
|
+
group: "network",
|
|
46
|
+
desc: "Bind address (loopback by default; set 0.0.0.0 to expose to the network)",
|
|
47
|
+
defaultText: "127.0.0.1",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "cors-origin",
|
|
51
|
+
env: "CORS_ORIGIN",
|
|
52
|
+
type: "string",
|
|
53
|
+
group: "network",
|
|
54
|
+
desc: "CORS allow-origin (production only; dev is wide-open)",
|
|
55
|
+
defaultText: "(unset)",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "trust-proxy",
|
|
59
|
+
env: "TRUST_PROXY",
|
|
60
|
+
type: "boolean",
|
|
61
|
+
group: "network",
|
|
62
|
+
desc: "Trust X-Forwarded-* headers (set when behind a reverse proxy)",
|
|
63
|
+
defaultText: "false",
|
|
64
|
+
},
|
|
65
|
+
// paths
|
|
66
|
+
{
|
|
67
|
+
name: "workspace-path",
|
|
68
|
+
env: "WORKSPACE_PATH",
|
|
69
|
+
type: "string",
|
|
70
|
+
group: "paths",
|
|
71
|
+
desc: "Where project code lives",
|
|
72
|
+
defaultText: "~/.pi-forge/workspace",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "pi-config-dir",
|
|
76
|
+
env: "PI_CONFIG_DIR",
|
|
77
|
+
type: "string",
|
|
78
|
+
group: "paths",
|
|
79
|
+
desc: "Pi SDK config dir (auth/models/settings)",
|
|
80
|
+
defaultText: "~/.pi/agent",
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "forge-data-dir",
|
|
84
|
+
env: "FORGE_DATA_DIR",
|
|
85
|
+
type: "string",
|
|
86
|
+
group: "paths",
|
|
87
|
+
desc: "Forge state dir (projects.json, mcp.json, overrides)",
|
|
88
|
+
defaultText: "~/.pi-forge",
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "session-dir",
|
|
92
|
+
env: "SESSION_DIR",
|
|
93
|
+
type: "string",
|
|
94
|
+
group: "paths",
|
|
95
|
+
desc: "JSONL session storage",
|
|
96
|
+
defaultText: "${workspace-path}/.pi/sessions",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "client-dist-path",
|
|
100
|
+
env: "CLIENT_DIST_PATH",
|
|
101
|
+
type: "string",
|
|
102
|
+
group: "paths",
|
|
103
|
+
desc: "Built client (Vite output) dir",
|
|
104
|
+
defaultText: "(bundled with package)",
|
|
105
|
+
},
|
|
106
|
+
// auth
|
|
107
|
+
{
|
|
108
|
+
name: "ui-password",
|
|
109
|
+
env: "UI_PASSWORD",
|
|
110
|
+
type: "string",
|
|
111
|
+
group: "auth",
|
|
112
|
+
desc: "Browser login password (enables JWT auth). Use @<path> to read from a file.",
|
|
113
|
+
defaultText: "(unset, auth disabled unless --api-key)",
|
|
114
|
+
sensitive: true,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "api-key",
|
|
118
|
+
env: "API_KEY",
|
|
119
|
+
type: "string",
|
|
120
|
+
group: "auth",
|
|
121
|
+
desc: "Static bearer token for programmatic clients. Use @<path> to read from a file.",
|
|
122
|
+
defaultText: "(unset, auth disabled unless --ui-password)",
|
|
123
|
+
sensitive: true,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: "jwt-secret",
|
|
127
|
+
env: "JWT_SECRET",
|
|
128
|
+
type: "string",
|
|
129
|
+
group: "auth",
|
|
130
|
+
desc: "JWT signing secret (auto-generated and persisted if unset). Use @<path>.",
|
|
131
|
+
defaultText: "(auto-generated)",
|
|
132
|
+
sensitive: true,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "jwt-expires-in-seconds",
|
|
136
|
+
env: "JWT_EXPIRES_IN_SECONDS",
|
|
137
|
+
type: "number",
|
|
138
|
+
group: "auth",
|
|
139
|
+
desc: "Browser JWT lifetime in seconds",
|
|
140
|
+
defaultText: "604800 (7d)",
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: "require-password-change",
|
|
144
|
+
env: "REQUIRE_PASSWORD_CHANGE",
|
|
145
|
+
type: "boolean",
|
|
146
|
+
group: "auth",
|
|
147
|
+
desc: "Require user to change password on first login (set when --ui-password is sealed-secret)",
|
|
148
|
+
defaultText: "false",
|
|
149
|
+
},
|
|
150
|
+
// features
|
|
151
|
+
{
|
|
152
|
+
name: "log-level",
|
|
153
|
+
env: "LOG_LEVEL",
|
|
154
|
+
type: "string",
|
|
155
|
+
group: "features",
|
|
156
|
+
desc: "Pino log level: trace|debug|info|warn|error|fatal",
|
|
157
|
+
defaultText: "info",
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "serve-client",
|
|
161
|
+
env: "SERVE_CLIENT",
|
|
162
|
+
type: "boolean",
|
|
163
|
+
group: "features",
|
|
164
|
+
desc: "Serve the built React UI from this server (turn off if running Vite separately)",
|
|
165
|
+
defaultText: "true",
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "minimal-ui",
|
|
169
|
+
env: "MINIMAL_UI",
|
|
170
|
+
type: "boolean",
|
|
171
|
+
group: "features",
|
|
172
|
+
desc: "Hide terminal/git/last-turn/settings panes; locked-down deploys",
|
|
173
|
+
defaultText: "false",
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: "hide-builtin-providers",
|
|
177
|
+
env: "HIDE_BUILTIN_PROVIDERS",
|
|
178
|
+
type: "boolean",
|
|
179
|
+
group: "features",
|
|
180
|
+
desc: "Hide built-in provider entries from the providers list",
|
|
181
|
+
defaultText: "false",
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
name: "expose-docs",
|
|
185
|
+
env: "EXPOSE_DOCS",
|
|
186
|
+
type: "boolean",
|
|
187
|
+
group: "features",
|
|
188
|
+
desc: "Expose /api/docs (Swagger UI + OpenAPI JSON)",
|
|
189
|
+
defaultText: "true",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "agent-secret-hygiene",
|
|
193
|
+
env: "AGENT_SECRET_HYGIENE_RULE",
|
|
194
|
+
type: "boolean",
|
|
195
|
+
group: "features",
|
|
196
|
+
desc: "Append a secret-hygiene rule to the agent's system prompt",
|
|
197
|
+
defaultText: "false",
|
|
198
|
+
},
|
|
199
|
+
// rate limits
|
|
200
|
+
{
|
|
201
|
+
name: "rate-limit-login-max",
|
|
202
|
+
env: "RATE_LIMIT_LOGIN_MAX",
|
|
203
|
+
type: "number",
|
|
204
|
+
group: "rate-limits",
|
|
205
|
+
desc: "Login attempts per window",
|
|
206
|
+
defaultText: "10",
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
name: "rate-limit-login-window-ms",
|
|
210
|
+
env: "RATE_LIMIT_LOGIN_WINDOW_MS",
|
|
211
|
+
type: "number",
|
|
212
|
+
group: "rate-limits",
|
|
213
|
+
desc: "Login rate-limit window (ms)",
|
|
214
|
+
defaultText: "60000",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: "rate-limit-prompt-max",
|
|
218
|
+
env: "RATE_LIMIT_PROMPT_MAX",
|
|
219
|
+
type: "number",
|
|
220
|
+
group: "rate-limits",
|
|
221
|
+
desc: "Prompt/steer/compact/navigate calls per window",
|
|
222
|
+
defaultText: "60",
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
name: "rate-limit-prompt-window-ms",
|
|
226
|
+
env: "RATE_LIMIT_PROMPT_WINDOW_MS",
|
|
227
|
+
type: "number",
|
|
228
|
+
group: "rate-limits",
|
|
229
|
+
desc: "Prompt rate-limit window (ms)",
|
|
230
|
+
defaultText: "60000",
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "rate-limit-upload-max",
|
|
234
|
+
env: "RATE_LIMIT_UPLOAD_MAX",
|
|
235
|
+
type: "number",
|
|
236
|
+
group: "rate-limits",
|
|
237
|
+
desc: "File upload calls per window",
|
|
238
|
+
defaultText: "30",
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
name: "rate-limit-upload-window-ms",
|
|
242
|
+
env: "RATE_LIMIT_UPLOAD_WINDOW_MS",
|
|
243
|
+
type: "number",
|
|
244
|
+
group: "rate-limits",
|
|
245
|
+
desc: "Upload rate-limit window (ms)",
|
|
246
|
+
defaultText: "60000",
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: "rate-limit-search-max",
|
|
250
|
+
env: "RATE_LIMIT_SEARCH_MAX",
|
|
251
|
+
type: "number",
|
|
252
|
+
group: "rate-limits",
|
|
253
|
+
desc: "File search calls per window",
|
|
254
|
+
defaultText: "60",
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
name: "rate-limit-search-window-ms",
|
|
258
|
+
env: "RATE_LIMIT_SEARCH_WINDOW_MS",
|
|
259
|
+
type: "number",
|
|
260
|
+
group: "rate-limits",
|
|
261
|
+
desc: "Search rate-limit window (ms)",
|
|
262
|
+
defaultText: "60000",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
name: "rate-limit-push-max",
|
|
266
|
+
env: "RATE_LIMIT_PUSH_MAX",
|
|
267
|
+
type: "number",
|
|
268
|
+
group: "rate-limits",
|
|
269
|
+
desc: "Git push calls per window",
|
|
270
|
+
defaultText: "10",
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
name: "rate-limit-push-window-ms",
|
|
274
|
+
env: "RATE_LIMIT_PUSH_WINDOW_MS",
|
|
275
|
+
type: "number",
|
|
276
|
+
group: "rate-limits",
|
|
277
|
+
desc: "Push rate-limit window (ms)",
|
|
278
|
+
defaultText: "60000",
|
|
279
|
+
},
|
|
280
|
+
// terminal
|
|
281
|
+
{
|
|
282
|
+
name: "pty-idle-reap-ms",
|
|
283
|
+
env: "PTY_IDLE_REAP_MS",
|
|
284
|
+
type: "number",
|
|
285
|
+
group: "terminal",
|
|
286
|
+
desc: "How long a detached PTY survives before reap (ms; 0 disables reattach)",
|
|
287
|
+
defaultText: "600000 (10m)",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: "terminal-passthrough-env",
|
|
291
|
+
env: "TERMINAL_PASSTHROUGH_ENV",
|
|
292
|
+
type: "list",
|
|
293
|
+
group: "terminal",
|
|
294
|
+
desc: "Extra env vars the integrated terminal inherits (comma- or space-separated)",
|
|
295
|
+
defaultText: "(empty allowlist)",
|
|
296
|
+
},
|
|
297
|
+
];
|
|
298
|
+
const FLAGS_BY_NAME = new Map(FLAGS.map((f) => [f.name, f]));
|
|
299
|
+
const BOOL_TRUE = new Set(["1", "true", "yes", "on"]);
|
|
300
|
+
const BOOL_FALSE = new Set(["0", "false", "no", "off"]);
|
|
301
|
+
/**
|
|
302
|
+
* Pre-process argv to handle `--no-<bool>` (parseArgs doesn't natively).
|
|
303
|
+
*
|
|
304
|
+
* `--no-foo` becomes `--foo=false` (only for declared boolean flags;
|
|
305
|
+
* unknown `--no-X` is left untouched so parseArgs surfaces it as a
|
|
306
|
+
* normal "Unknown option" error).
|
|
307
|
+
*/
|
|
308
|
+
function expandNegatedBooleans(args) {
|
|
309
|
+
const out = [];
|
|
310
|
+
for (const arg of args) {
|
|
311
|
+
if (arg.startsWith("--no-")) {
|
|
312
|
+
const name = arg.slice("--no-".length);
|
|
313
|
+
const def = FLAGS_BY_NAME.get(name);
|
|
314
|
+
if (def && def.type === "boolean") {
|
|
315
|
+
out.push(`--${name}=false`);
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
out.push(arg);
|
|
320
|
+
}
|
|
321
|
+
return out;
|
|
322
|
+
}
|
|
323
|
+
/** Read a sensitive flag's value, dereferencing `@<path>` syntax. */
|
|
324
|
+
function resolveSensitive(value, flagName, errors) {
|
|
325
|
+
if (!value.startsWith("@"))
|
|
326
|
+
return value;
|
|
327
|
+
const path = value.slice(1);
|
|
328
|
+
if (path === "") {
|
|
329
|
+
errors.push(`--${flagName}: @ syntax requires a path (e.g. --${flagName} @/run/secrets/key)`);
|
|
330
|
+
return undefined;
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
return readFileSync(path, "utf8").trim();
|
|
334
|
+
}
|
|
335
|
+
catch (err) {
|
|
336
|
+
errors.push(`--${flagName}: failed to read ${path}: ${err.code ?? err.message}`);
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
export function parseCliArgs(argv) {
|
|
341
|
+
const result = {
|
|
342
|
+
envWrites: [],
|
|
343
|
+
helpRequested: false,
|
|
344
|
+
versionRequested: false,
|
|
345
|
+
errors: [],
|
|
346
|
+
positionals: [],
|
|
347
|
+
};
|
|
348
|
+
const expanded = expandNegatedBooleans(argv);
|
|
349
|
+
const options = {
|
|
350
|
+
help: { type: "boolean", short: "h" },
|
|
351
|
+
version: { type: "boolean", short: "v" },
|
|
352
|
+
};
|
|
353
|
+
for (const f of FLAGS) {
|
|
354
|
+
if (f.type === "boolean") {
|
|
355
|
+
// Accept bare `--foo` (parsed as boolean true) and `--foo=value` (string).
|
|
356
|
+
// parseArgs can't represent both — pick string, treat presence-without-value
|
|
357
|
+
// by inserting "=true" in pre-pass.
|
|
358
|
+
options[f.name] = { type: "string" };
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
options[f.name] = { type: "string" };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
// Second pre-pass: bare `--bool-flag` with no following arg (or a
|
|
365
|
+
// following arg that looks like another flag) → `--bool-flag=true`.
|
|
366
|
+
// Otherwise we leave it alone so parseArgs grabs the next arg as the
|
|
367
|
+
// value, and the bool-coercion step below produces a precise
|
|
368
|
+
// "expected a boolean" error rather than a generic "unexpected
|
|
369
|
+
// positional" complaint.
|
|
370
|
+
const finalArgs = [];
|
|
371
|
+
for (let i = 0; i < expanded.length; i++) {
|
|
372
|
+
const arg = expanded[i];
|
|
373
|
+
if (arg === undefined)
|
|
374
|
+
continue;
|
|
375
|
+
if (arg.startsWith("--") && !arg.includes("=")) {
|
|
376
|
+
const name = arg.slice(2);
|
|
377
|
+
const def = FLAGS_BY_NAME.get(name);
|
|
378
|
+
if (def && def.type === "boolean") {
|
|
379
|
+
const next = expanded[i + 1];
|
|
380
|
+
if (next === undefined || next.startsWith("--") || next.startsWith("-")) {
|
|
381
|
+
finalArgs.push(`--${name}=true`);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
finalArgs.push(arg);
|
|
387
|
+
}
|
|
388
|
+
let parsed;
|
|
389
|
+
try {
|
|
390
|
+
parsed = parseArgs({
|
|
391
|
+
args: finalArgs,
|
|
392
|
+
options,
|
|
393
|
+
allowPositionals: true,
|
|
394
|
+
strict: true,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
catch (err) {
|
|
398
|
+
result.errors.push(err.message);
|
|
399
|
+
return result;
|
|
400
|
+
}
|
|
401
|
+
result.positionals = parsed.positionals;
|
|
402
|
+
if (parsed.values.help === true)
|
|
403
|
+
result.helpRequested = true;
|
|
404
|
+
if (parsed.values.version === true)
|
|
405
|
+
result.versionRequested = true;
|
|
406
|
+
if (parsed.positionals.length > 0) {
|
|
407
|
+
result.errors.push(`Unexpected positional argument(s): ${parsed.positionals.join(", ")}. ` +
|
|
408
|
+
`pi-forge takes flags only — see --help.`);
|
|
409
|
+
}
|
|
410
|
+
for (const f of FLAGS) {
|
|
411
|
+
const raw = parsed.values[f.name];
|
|
412
|
+
if (raw === undefined)
|
|
413
|
+
continue;
|
|
414
|
+
const rawStr = String(raw);
|
|
415
|
+
if (f.type === "boolean") {
|
|
416
|
+
const lc = rawStr.toLowerCase();
|
|
417
|
+
if (BOOL_TRUE.has(lc)) {
|
|
418
|
+
result.envWrites.push({ key: f.env, value: "true" });
|
|
419
|
+
}
|
|
420
|
+
else if (BOOL_FALSE.has(lc)) {
|
|
421
|
+
result.envWrites.push({ key: f.env, value: "false" });
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
result.errors.push(`--${f.name}: expected a boolean (true/false/on/off/1/0/yes/no), got ${JSON.stringify(rawStr)}`);
|
|
425
|
+
}
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
if (f.type === "number") {
|
|
429
|
+
const n = Number.parseInt(rawStr, 10);
|
|
430
|
+
if (!Number.isFinite(n) || n < 0 || String(n) !== rawStr.trim()) {
|
|
431
|
+
result.errors.push(`--${f.name}: expected a non-negative integer, got ${JSON.stringify(rawStr)}`);
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
result.envWrites.push({ key: f.env, value: String(n) });
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
437
|
+
if (f.sensitive) {
|
|
438
|
+
const resolved = resolveSensitive(rawStr, f.name, result.errors);
|
|
439
|
+
if (resolved === undefined)
|
|
440
|
+
continue;
|
|
441
|
+
if (resolved === "") {
|
|
442
|
+
result.errors.push(`--${f.name}: resolved value is empty`);
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
result.envWrites.push({ key: f.env, value: resolved });
|
|
446
|
+
continue;
|
|
447
|
+
}
|
|
448
|
+
// string + list pass through verbatim — config.ts parses lists.
|
|
449
|
+
result.envWrites.push({ key: f.env, value: rawStr });
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Apply parsed env writes. Flag values WIN over any pre-existing env,
|
|
455
|
+
* matching the documented "flag overrides env" rule.
|
|
456
|
+
*/
|
|
457
|
+
export function applyCliEnv(parsed) {
|
|
458
|
+
for (const { key, value } of parsed.envWrites) {
|
|
459
|
+
process.env[key] = value;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
const GROUP_LABELS = {
|
|
463
|
+
network: "Network",
|
|
464
|
+
paths: "Paths",
|
|
465
|
+
auth: "Authentication",
|
|
466
|
+
features: "Features",
|
|
467
|
+
"rate-limits": "Rate limits",
|
|
468
|
+
terminal: "Terminal",
|
|
469
|
+
};
|
|
470
|
+
export function buildHelpText(version) {
|
|
471
|
+
const out = [];
|
|
472
|
+
out.push(`pi-forge ${version}`);
|
|
473
|
+
out.push("");
|
|
474
|
+
out.push("Browser UI for the pi coding agent.");
|
|
475
|
+
out.push("");
|
|
476
|
+
out.push("Usage:");
|
|
477
|
+
out.push(" pi-forge [options]");
|
|
478
|
+
out.push("");
|
|
479
|
+
out.push("Every option below has an equivalent environment variable. Flags win when both are set.");
|
|
480
|
+
out.push("");
|
|
481
|
+
const groups = ["network", "paths", "auth", "features", "rate-limits", "terminal"];
|
|
482
|
+
for (const group of groups) {
|
|
483
|
+
const flags = FLAGS.filter((f) => f.group === group);
|
|
484
|
+
if (flags.length === 0)
|
|
485
|
+
continue;
|
|
486
|
+
out.push(`${GROUP_LABELS[group]}:`);
|
|
487
|
+
const longest = Math.max(...flags.map((f) => f.name.length + (f.type === "boolean" ? 0 : 6)));
|
|
488
|
+
for (const f of flags) {
|
|
489
|
+
const flagCol = f.type === "boolean" ? `--${f.name}` : `--${f.name} <val>`;
|
|
490
|
+
const padded = flagCol.padEnd(longest + 4, " ");
|
|
491
|
+
out.push(` ${padded}${f.desc}`);
|
|
492
|
+
out.push(` ${"".padEnd(longest + 4, " ")}env: ${f.env}; default: ${f.defaultText}`);
|
|
493
|
+
}
|
|
494
|
+
out.push("");
|
|
495
|
+
}
|
|
496
|
+
out.push("Other:");
|
|
497
|
+
out.push(" --help, -h Show this help and exit");
|
|
498
|
+
out.push(" --version, -v Print version and exit");
|
|
499
|
+
out.push("");
|
|
500
|
+
out.push("Boolean flags accept true/false/on/off/1/0/yes/no, or use --no-<flag> for false.");
|
|
501
|
+
out.push("Sensitive flags (--ui-password, --api-key, --jwt-secret) accept @<path> to read from file.");
|
|
502
|
+
out.push("");
|
|
503
|
+
out.push("Examples:");
|
|
504
|
+
out.push(" pi-forge --port 4000 --workspace-path ~/Code");
|
|
505
|
+
out.push(" pi-forge --api-key @/run/secrets/api-key");
|
|
506
|
+
out.push(" pi-forge --no-expose-docs --minimal-ui");
|
|
507
|
+
out.push("");
|
|
508
|
+
return out.join("\n");
|
|
509
|
+
}
|
|
510
|
+
/** Exposed so tests can iterate the same source of truth. */
|
|
511
|
+
export const FLAG_DEFS = FLAGS;
|
|
512
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAetC,MAAM,KAAK,GAAuB;IAChC,UAAU;IACV;QACE,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,MAAM;KACpB;IACD;QACE,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,MAAM;QACX,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,0EAA0E;QAChF,WAAW,EAAE,WAAW;KACzB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,aAAa;QAClB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,uDAAuD;QAC7D,WAAW,EAAE,SAAS;KACvB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,aAAa;QAClB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,+DAA+D;QACrE,WAAW,EAAE,OAAO;KACrB;IACD,QAAQ;IACR;QACE,IAAI,EAAE,gBAAgB;QACtB,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,0BAA0B;QAChC,WAAW,EAAE,uBAAuB;KACrC;IACD;QACE,IAAI,EAAE,eAAe;QACrB,GAAG,EAAE,eAAe;QACpB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,0CAA0C;QAChD,WAAW,EAAE,aAAa;KAC3B;IACD;QACE,IAAI,EAAE,gBAAgB;QACtB,GAAG,EAAE,gBAAgB;QACrB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,sDAAsD;QAC5D,WAAW,EAAE,aAAa;KAC3B;IACD;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,aAAa;QAClB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EAAE,gCAAgC;KAC9C;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,GAAG,EAAE,kBAAkB;QACvB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,OAAO;QACd,IAAI,EAAE,gCAAgC;QACtC,WAAW,EAAE,wBAAwB;KACtC;IACD,OAAO;IACP;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,aAAa;QAClB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,6EAA6E;QACnF,WAAW,EAAE,yCAAyC;QACtD,SAAS,EAAE,IAAI;KAChB;IACD;QACE,IAAI,EAAE,SAAS;QACf,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,gFAAgF;QACtF,WAAW,EAAE,6CAA6C;QAC1D,SAAS,EAAE,IAAI;KAChB;IACD;QACE,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,YAAY;QACjB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,0EAA0E;QAChF,WAAW,EAAE,kBAAkB;QAC/B,SAAS,EAAE,IAAI;KAChB;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,GAAG,EAAE,wBAAwB;QAC7B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,iCAAiC;QACvC,WAAW,EAAE,aAAa;KAC3B;IACD;QACE,IAAI,EAAE,yBAAyB;QAC/B,GAAG,EAAE,yBAAyB;QAC9B,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,MAAM;QACb,IAAI,EAAE,0FAA0F;QAChG,WAAW,EAAE,OAAO;KACrB;IACD,WAAW;IACX;QACE,IAAI,EAAE,WAAW;QACjB,GAAG,EAAE,WAAW;QAChB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,mDAAmD;QACzD,WAAW,EAAE,MAAM;KACpB;IACD;QACE,IAAI,EAAE,cAAc;QACpB,GAAG,EAAE,cAAc;QACnB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,iFAAiF;QACvF,WAAW,EAAE,MAAM;KACpB;IACD;QACE,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,YAAY;QACjB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,iEAAiE;QACvE,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,wBAAwB;QAC9B,GAAG,EAAE,wBAAwB;QAC7B,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,wDAAwD;QAC9D,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,aAAa;QACnB,GAAG,EAAE,aAAa;QAClB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,8CAA8C;QACpD,WAAW,EAAE,MAAM;KACpB;IACD;QACE,IAAI,EAAE,sBAAsB;QAC5B,GAAG,EAAE,2BAA2B;QAChC,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,2DAA2D;QACjE,WAAW,EAAE,OAAO;KACrB;IACD,cAAc;IACd;QACE,IAAI,EAAE,sBAAsB;QAC5B,GAAG,EAAE,sBAAsB;QAC3B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,IAAI;KAClB;IACD;QACE,IAAI,EAAE,4BAA4B;QAClC,GAAG,EAAE,4BAA4B;QACjC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,8BAA8B;QACpC,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,GAAG,EAAE,uBAAuB;QAC5B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,gDAAgD;QACtD,WAAW,EAAE,IAAI;KAClB;IACD;QACE,IAAI,EAAE,6BAA6B;QACnC,GAAG,EAAE,6BAA6B;QAClC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,+BAA+B;QACrC,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,GAAG,EAAE,uBAAuB;QAC5B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,8BAA8B;QACpC,WAAW,EAAE,IAAI;KAClB;IACD;QACE,IAAI,EAAE,6BAA6B;QACnC,GAAG,EAAE,6BAA6B;QAClC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,+BAA+B;QACrC,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,uBAAuB;QAC7B,GAAG,EAAE,uBAAuB;QAC5B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,8BAA8B;QACpC,WAAW,EAAE,IAAI;KAClB;IACD;QACE,IAAI,EAAE,6BAA6B;QACnC,GAAG,EAAE,6BAA6B;QAClC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,+BAA+B;QACrC,WAAW,EAAE,OAAO;KACrB;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,GAAG,EAAE,qBAAqB;QAC1B,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,2BAA2B;QACjC,WAAW,EAAE,IAAI;KAClB;IACD;QACE,IAAI,EAAE,2BAA2B;QACjC,GAAG,EAAE,2BAA2B;QAChC,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,6BAA6B;QACnC,WAAW,EAAE,OAAO;KACrB;IACD,WAAW;IACX;QACE,IAAI,EAAE,kBAAkB;QACxB,GAAG,EAAE,kBAAkB;QACvB,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,wEAAwE;QAC9E,WAAW,EAAE,cAAc;KAC5B;IACD;QACE,IAAI,EAAE,0BAA0B;QAChC,GAAG,EAAE,0BAA0B;QAC/B,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,6EAA6E;QACnF,WAAW,EAAE,mBAAmB;KACjC;CACO,CAAC;AAEX,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AACtD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;AAexD;;;;;;GAMG;AACH,SAAS,qBAAqB,CAAC,IAAc;IAC3C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAClC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC;gBAC5B,SAAS;YACX,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,qEAAqE;AACrE,SAAS,gBAAgB,CAAC,KAAa,EAAE,QAAgB,EAAE,MAAgB;IACzE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,KAAK,QAAQ,sCAAsC,QAAQ,qBAAqB,CAAC,CAAC;QAC9F,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,IAAI,CACT,KAAK,QAAQ,oBAAoB,IAAI,KAAM,GAA6B,CAAC,IAAI,IAAK,GAAa,CAAC,OAAO,EAAE,CAC1G,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,MAAM,GAAgB;QAC1B,SAAS,EAAE,EAAE;QACb,aAAa,EAAE,KAAK;QACpB,gBAAgB,EAAE,KAAK;QACvB,MAAM,EAAE,EAAE;QACV,WAAW,EAAE,EAAE;KAChB,CAAC;IAEF,MAAM,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAU7C,MAAM,OAAO,GAAiC;QAC5C,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;QACrC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE;KACzC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,2EAA2E;YAC3E,6EAA6E;YAC7E,oCAAoC;YACpC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACvC,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACvC,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,oEAAoE;IACpE,qEAAqE;IACrE,6DAA6D;IAC7D,+DAA+D;IAC/D,yBAAyB;IACzB,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxE,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC;oBACjC,SAAS;gBACX,CAAC;YACH,CAAC;QACH,CAAC;QACD,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,MAAuF,CAAC;IAC5F,IAAI,CAAC;QACH,MAAM,GAAG,SAAS,CAAC;YACjB,IAAI,EAAE,SAAS;YACf,OAAO;YACP,gBAAgB,EAAE,IAAI;YACtB,MAAM,EAAE,IAAI;SACb,CAAkB,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,MAAM,CAAC,IAAI,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;IAC7D,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,KAAK,IAAI;QAAE,MAAM,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAEnE,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,sCAAsC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YACrE,yCAAyC,CAC5C,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,GAAG,KAAK,SAAS;YAAE,SAAS;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE3B,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;YAChC,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBACtB,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,IAAI,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,KAAK,CAAC,CAAC,IAAI,4DAA4D,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAChG,CAAC;YACJ,CAAC;YACD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChE,MAAM,CAAC,MAAM,CAAC,IAAI,CAChB,KAAK,CAAC,CAAC,IAAI,0CAA0C,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAC9E,CAAC;gBACF,SAAS;YACX,CAAC;YACD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACxD,SAAS;QACX,CAAC;QAED,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACjE,IAAI,QAAQ,KAAK,SAAS;gBAAE,SAAS;YACrC,IAAI,QAAQ,KAAK,EAAE,EAAE,CAAC;gBACpB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,2BAA2B,CAAC,CAAC;gBAC3D,SAAS;YACX,CAAC;YACD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvD,SAAS;QACX,CAAC;QAED,gEAAgE;QAChE,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAmB;IAC7C,KAAK,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,YAAY,GAA8B;IAC9C,OAAO,EAAE,SAAS;IAClB,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,gBAAgB;IACtB,QAAQ,EAAE,UAAU;IACpB,aAAa,EAAE,aAAa;IAC5B,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,GAAG,CAAC,IAAI,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;IAChC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnB,GAAG,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACjC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CACN,yFAAyF,CAC1F,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEb,MAAM,MAAM,GAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;IAChG,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACjC,GAAG,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAC;YAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YAChD,GAAG,CAAC,IAAI,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACjC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACnB,GAAG,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;IAC1D,GAAG,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;IACzD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;IAC7F,GAAG,CAAC,IAAI,CACN,4FAA4F,CAC7F,CAAC;IACF,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtB,GAAG,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;IAC3D,GAAG,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;IACvD,GAAG,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACrD,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACb,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,MAAM,SAAS,GAAuB,KAAK,CAAC"}
|