prismalens 0.0.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.
Files changed (64) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +5 -0
  3. package/README.md +312 -0
  4. package/dist/bin/prismalens.d.ts +3 -0
  5. package/dist/bin/prismalens.d.ts.map +1 -0
  6. package/dist/bin/prismalens.js +32 -0
  7. package/dist/bin/prismalens.js.map +1 -0
  8. package/dist/src/cli/doctor.d.ts +3 -0
  9. package/dist/src/cli/doctor.d.ts.map +1 -0
  10. package/dist/src/cli/doctor.js +156 -0
  11. package/dist/src/cli/doctor.js.map +1 -0
  12. package/dist/src/cli/init.d.ts +3 -0
  13. package/dist/src/cli/init.d.ts.map +1 -0
  14. package/dist/src/cli/init.js +85 -0
  15. package/dist/src/cli/init.js.map +1 -0
  16. package/dist/src/cli/investigate.d.ts +101 -0
  17. package/dist/src/cli/investigate.d.ts.map +1 -0
  18. package/dist/src/cli/investigate.js +452 -0
  19. package/dist/src/cli/investigate.js.map +1 -0
  20. package/dist/src/cli/serve.d.ts +3 -0
  21. package/dist/src/cli/serve.d.ts.map +1 -0
  22. package/dist/src/cli/serve.js +26 -0
  23. package/dist/src/cli/serve.js.map +1 -0
  24. package/dist/src/config/loader.d.ts +22 -0
  25. package/dist/src/config/loader.d.ts.map +1 -0
  26. package/dist/src/config/loader.js +155 -0
  27. package/dist/src/config/loader.js.map +1 -0
  28. package/dist/src/config/schema.d.ts +336 -0
  29. package/dist/src/config/schema.d.ts.map +1 -0
  30. package/dist/src/config/schema.js +160 -0
  31. package/dist/src/config/schema.js.map +1 -0
  32. package/dist/src/core/detect-repo.d.ts +4 -0
  33. package/dist/src/core/detect-repo.d.ts.map +1 -0
  34. package/dist/src/core/detect-repo.js +28 -0
  35. package/dist/src/core/detect-repo.js.map +1 -0
  36. package/dist/src/core/file-session-store.d.ts +10 -0
  37. package/dist/src/core/file-session-store.d.ts.map +1 -0
  38. package/dist/src/core/file-session-store.js +34 -0
  39. package/dist/src/core/file-session-store.js.map +1 -0
  40. package/dist/src/core/parse-stdin.d.ts +2 -0
  41. package/dist/src/core/parse-stdin.d.ts.map +1 -0
  42. package/dist/src/core/parse-stdin.js +30 -0
  43. package/dist/src/core/parse-stdin.js.map +1 -0
  44. package/dist/src/core/run-investigation.d.ts +42 -0
  45. package/dist/src/core/run-investigation.d.ts.map +1 -0
  46. package/dist/src/core/run-investigation.js +144 -0
  47. package/dist/src/core/run-investigation.js.map +1 -0
  48. package/dist/src/core/session.d.ts +42 -0
  49. package/dist/src/core/session.d.ts.map +1 -0
  50. package/dist/src/core/session.js +168 -0
  51. package/dist/src/core/session.js.map +1 -0
  52. package/dist/src/jsonrpc/server.d.ts +15 -0
  53. package/dist/src/jsonrpc/server.d.ts.map +1 -0
  54. package/dist/src/jsonrpc/server.js +244 -0
  55. package/dist/src/jsonrpc/server.js.map +1 -0
  56. package/dist/src/jsonrpc/types.d.ts +12 -0
  57. package/dist/src/jsonrpc/types.d.ts.map +1 -0
  58. package/dist/src/jsonrpc/types.js +4 -0
  59. package/dist/src/jsonrpc/types.js.map +1 -0
  60. package/dist/src/version.d.ts +8 -0
  61. package/dist/src/version.d.ts.map +1 -0
  62. package/dist/src/version.js +27 -0
  63. package/dist/src/version.js.map +1 -0
  64. package/package.json +61 -0
@@ -0,0 +1,156 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Sumit Patel
3
+ /**
4
+ * `prismalens doctor` — preflight checklist for the two-tier engine (ADR-0008/0010).
5
+ *
6
+ * Salvaged in spirit from the retired pl orchestrator's doctor, but pared down to the
7
+ * checks that actually gate a run:
8
+ * - HARD: the configured harness binary is on PATH
9
+ * (deepagents -> "deepagents", claude-code -> "claude", codex -> "codex")
10
+ * - HARD: an LLM credential is present
11
+ * (any provider credential env var from LLM_PROVIDERS, or, for claude-code,
12
+ * a signed-in ~/.claude/.credentials.json)
13
+ * - SOFT: workspace.base_dir is writable
14
+ *
15
+ * Prints pass/fail per check; exits non-zero iff a HARD check fails. No tinyexec /
16
+ * check-tool helper here — availability is a dependency-free PATH scan.
17
+ */
18
+ import { accessSync, existsSync, constants as fsConstants } from "node:fs";
19
+ import { access, mkdir } from "node:fs/promises";
20
+ import { homedir } from "node:os";
21
+ import { delimiter, join } from "node:path";
22
+ import { HARNESS_BINARY } from "@prismalens/config/harness";
23
+ import { LLM_CREDENTIAL_ENV_VARS } from "@prismalens/config/llm";
24
+ import { defineCommand } from "citty";
25
+ import consola from "consola";
26
+ import { loadConfig } from "../config/loader.js";
27
+ import { PlConfigSchema } from "../config/schema.js";
28
+ import { resolveBaseDir } from "../core/session.js";
29
+ /** Is `bin` an executable somewhere on PATH? Synchronous, dependency-free. */
30
+ function isOnPath(bin) {
31
+ const pathEnv = process.env.PATH ?? "";
32
+ const exts = process.platform === "win32"
33
+ ? (process.env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";")
34
+ : [""];
35
+ for (const dir of pathEnv.split(delimiter)) {
36
+ if (dir.length === 0)
37
+ continue;
38
+ for (const ext of exts) {
39
+ try {
40
+ accessSync(join(dir, bin + ext), fsConstants.X_OK);
41
+ return true;
42
+ }
43
+ catch {
44
+ // not in this dir / not executable — keep looking
45
+ }
46
+ }
47
+ }
48
+ return false;
49
+ }
50
+ function checkHarness(harness) {
51
+ const binary = HARNESS_BINARY[harness];
52
+ const pass = isOnPath(binary);
53
+ return {
54
+ name: "Harness binary",
55
+ pass,
56
+ detail: pass
57
+ ? `${binary} found on PATH (harness: ${harness})`
58
+ : `${binary} not found on PATH — install the "${harness}" harness`,
59
+ hard: true,
60
+ };
61
+ }
62
+ function checkCredential(harness) {
63
+ const envVar = LLM_CREDENTIAL_ENV_VARS.find((name) => (process.env[name]?.length ?? 0) > 0);
64
+ const credentialsFile = join(homedir(), ".claude", ".credentials.json");
65
+ const hasClaudeLogin = harness === "claude-code" && existsSync(credentialsFile);
66
+ if (envVar) {
67
+ return {
68
+ name: "LLM credential",
69
+ pass: true,
70
+ detail: `${envVar} is set`,
71
+ hard: true,
72
+ };
73
+ }
74
+ if (hasClaudeLogin) {
75
+ return {
76
+ name: "LLM credential",
77
+ pass: true,
78
+ detail: "~/.claude/.credentials.json present (Claude Code login)",
79
+ hard: true,
80
+ };
81
+ }
82
+ const hint = harness === "claude-code"
83
+ ? "set ANTHROPIC_API_KEY or sign in with `claude` (creates ~/.claude/.credentials.json)"
84
+ : `set one of ${LLM_CREDENTIAL_ENV_VARS.join(", ")}`;
85
+ return {
86
+ name: "LLM credential",
87
+ pass: false,
88
+ detail: `no LLM credential found — ${hint}`,
89
+ hard: true,
90
+ };
91
+ }
92
+ async function checkWorkspace(config) {
93
+ const baseDir = resolveBaseDir(config.workspace.base_dir);
94
+ try {
95
+ await mkdir(baseDir, { recursive: true });
96
+ await access(baseDir, fsConstants.W_OK);
97
+ return {
98
+ name: "Workspace",
99
+ pass: true,
100
+ detail: `${baseDir} is writable`,
101
+ hard: false,
102
+ };
103
+ }
104
+ catch {
105
+ return {
106
+ name: "Workspace",
107
+ pass: false,
108
+ detail: `${baseDir} is not writable — runs cannot persist here`,
109
+ hard: false,
110
+ };
111
+ }
112
+ }
113
+ export default defineCommand({
114
+ meta: {
115
+ name: "doctor",
116
+ description: "Preflight check the investigation environment",
117
+ },
118
+ async run() {
119
+ // loadConfig applies schema defaults, so this succeeds even with no config
120
+ // file. It only throws on an invalid file / unset ${VAR}; fall back to the
121
+ // built-in defaults so doctor can still report what it can.
122
+ let config;
123
+ try {
124
+ config = await loadConfig();
125
+ }
126
+ catch (err) {
127
+ const detail = err instanceof Error ? err.message : String(err);
128
+ consola.warn(`Could not load config (${detail}); using built-in defaults.`);
129
+ config = PlConfigSchema.parse({});
130
+ }
131
+ const harness = config.agent.default;
132
+ const checks = [
133
+ checkHarness(harness),
134
+ checkCredential(harness),
135
+ await checkWorkspace(config),
136
+ ];
137
+ consola.log("");
138
+ for (const check of checks) {
139
+ const line = `${check.name}: ${check.detail}`;
140
+ if (check.pass)
141
+ consola.success(line);
142
+ else if (check.hard)
143
+ consola.error(line);
144
+ else
145
+ consola.warn(line);
146
+ }
147
+ consola.log("");
148
+ const hardFailures = checks.filter((c) => c.hard && !c.pass);
149
+ if (hardFailures.length > 0) {
150
+ consola.error(`${hardFailures.length} required check(s) failed — fix the above before investigating.`);
151
+ process.exit(1);
152
+ }
153
+ consola.success("All required checks passed.");
154
+ },
155
+ });
156
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ declare const _default: import("citty").CommandDef<import("citty").ArgsDef>;
2
+ export default _default;
3
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":";AAyEA,wBAyBG"}
@@ -0,0 +1,85 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright 2026 Sumit Patel
3
+ /**
4
+ * `prismalens init` — scaffold a prismalens.config.yaml in the cwd.
5
+ *
6
+ * Behaviour (intentionally non-interactive, unlike the retired pl orchestrator's
7
+ * wizard): if a prismalens.config.yaml already exists, print a notice and do
8
+ * nothing; otherwise write a commented default. Values are sourced from the Zod
9
+ * schema's defaults so the scaffold can't drift from what the engine actually uses.
10
+ */
11
+ import { existsSync } from "node:fs";
12
+ import { writeFile } from "node:fs/promises";
13
+ import { resolve } from "node:path";
14
+ import { INVESTIGATION_DEFAULTS } from "@prismalens/config/investigation";
15
+ import { defineCommand } from "citty";
16
+ import consola from "consola";
17
+ import { AgentConfigSchema, PlConfigSchema, } from "../config/schema.js";
18
+ const CONFIG_FILENAME = "prismalens.config.yaml";
19
+ /** Render a commented default config, sourcing live values from schema defaults. */
20
+ function renderDefaultConfig(d) {
21
+ const harnessOptions = AgentConfigSchema.shape.default
22
+ .removeDefault()
23
+ .options.join(" | ");
24
+ return `# prismalens.config.yaml — investigation engine configuration (ADR-0008/0010).
25
+ # Generated by \`prismalens init\`. Unset values fall back to built-in defaults;
26
+ # \`prismalens doctor\` checks the bits that gate a run.
27
+
28
+ # Repository under investigation (owner/name). Auto-detected from the git remote
29
+ # when omitted.
30
+ # repo: owner/name
31
+
32
+ # Tier-2 harness backend the supervisor rents (ADR-0008).
33
+ agent:
34
+ # Which agent harness to rent: ${harnessOptions}
35
+ default: ${d.agent.default}
36
+ # BARE model id, e.g. "gpt-oss:120b" — the harness applies its own provider prefix.
37
+ # Omit to let the chosen harness pick its own default.
38
+ # model: gpt-oss:120b
39
+
40
+ # Read-only telemetry + app endpoints the harness may query. Point these at your
41
+ # stack; defaults assume a local dev setup.
42
+ telemetry:
43
+ prometheusUrl: ${INVESTIGATION_DEFAULTS.telemetry.prometheusUrl}
44
+ alertmanagerUrl: ${INVESTIGATION_DEFAULTS.telemetry.alertmanagerUrl}
45
+ apiUrl: ${INVESTIGATION_DEFAULTS.telemetry.apiUrl}
46
+
47
+ # Read-only log-query system the harness may curl (Loki, Elasticsearch, …).
48
+ # logs:
49
+ # kind: loki
50
+ # url: http://localhost:3100
51
+
52
+ # Service catalog (ADR-0015). The alert's \`service\` label (else \`namespace\`/\`job\`)
53
+ # selects an entry; \`--service <name>\` overrides. The matched service's repo/tier/
54
+ # deps ride into the investigation context so a single-alert run isn't context-free.
55
+ # services:
56
+ # checkout:
57
+ # tier: tier-1
58
+ # repo: acme/checkout
59
+ # depends_on: [payments, inventory]
60
+
61
+ # Where runs, events, and reports are stored.
62
+ workspace:
63
+ base_dir: ${d.workspace.base_dir}
64
+ `;
65
+ }
66
+ export default defineCommand({
67
+ meta: {
68
+ name: "init",
69
+ description: `Scaffold a ${CONFIG_FILENAME} in the current directory`,
70
+ },
71
+ async run() {
72
+ const configPath = resolve(process.cwd(), CONFIG_FILENAME);
73
+ if (existsSync(configPath)) {
74
+ consola.info(`${CONFIG_FILENAME} already exists at ${configPath} — leaving it untouched.`);
75
+ return;
76
+ }
77
+ // PlConfigSchema.parse({}) yields the fully-defaulted config; the scaffold
78
+ // renders those exact values so it never drifts from the schema.
79
+ const defaults = PlConfigSchema.parse({});
80
+ await writeFile(configPath, renderDefaultConfig(defaults), "utf-8");
81
+ consola.success(`Created ${configPath}`);
82
+ consola.info("Edit it for your stack, then run `prismalens doctor` to verify your environment.");
83
+ },
84
+ });
85
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/init.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,6BAA6B;AAE7B;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,EACN,iBAAiB,EAEjB,cAAc,GACd,MAAM,qBAAqB,CAAC;AAE7B,MAAM,eAAe,GAAG,wBAAwB,CAAC;AAEjD,oFAAoF;AACpF,SAAS,mBAAmB,CAAC,CAAW;IACvC,MAAM,cAAc,GAAG,iBAAiB,CAAC,KAAK,CAAC,OAAO;SACpD,aAAa,EAAE;SACf,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,OAAO;;;;;;;;;;mCAU2B,cAAc;aACpC,CAAC,CAAC,KAAK,CAAC,OAAO;;;;;;;;mBAQT,sBAAsB,CAAC,SAAS,CAAC,aAAa;qBAC5C,sBAAsB,CAAC,SAAS,CAAC,eAAe;YACzD,sBAAsB,CAAC,SAAS,CAAC,MAAM;;;;;;;;;;;;;;;;;;cAkBrC,CAAC,CAAC,SAAS,CAAC,QAAQ;CACjC,CAAC;AACF,CAAC;AAED,eAAe,aAAa,CAAC;IAC5B,IAAI,EAAE;QACL,IAAI,EAAE,MAAM;QACZ,WAAW,EAAE,cAAc,eAAe,2BAA2B;KACrE;IACD,KAAK,CAAC,GAAG;QACR,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,eAAe,CAAC,CAAC;QAE3D,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CACX,GAAG,eAAe,sBAAsB,UAAU,0BAA0B,CAC5E,CAAC;YACF,OAAO;QACR,CAAC;QAED,2EAA2E;QAC3E,iEAAiE;QACjE,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,SAAS,CAAC,UAAU,EAAE,mBAAmB,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC;QAEpE,OAAO,CAAC,OAAO,CAAC,WAAW,UAAU,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,IAAI,CACX,kFAAkF,CAClF,CAAC;IACH,CAAC;CACD,CAAC,CAAC"}
@@ -0,0 +1,101 @@
1
+ import { type HarnessId } from "@prismalens/config/harness";
2
+ import { type SandboxMode, type SandboxSelection } from "@prismalens/engine";
3
+ import type { PlConfig } from "../config/schema.js";
4
+ declare const _default: import("citty").CommandDef<{
5
+ readonly repo: {
6
+ readonly type: "string";
7
+ readonly description: "Path to the repository the harness investigates (its cwd). Defaults to the current directory.";
8
+ };
9
+ readonly query: {
10
+ readonly type: "string";
11
+ readonly alias: "q";
12
+ readonly description: "Investigate a synthesized alert from this one-line description (alternative to piping a FiringAlert JSON on stdin).";
13
+ };
14
+ readonly config: {
15
+ readonly type: "string";
16
+ readonly description: "Path to a prismalens.config.yaml (skips the upward config search).";
17
+ };
18
+ readonly model: {
19
+ readonly type: "string";
20
+ readonly description: "Override agent.model — a bare model id, e.g. gpt-oss:120b.";
21
+ };
22
+ readonly harness: {
23
+ readonly type: "enum";
24
+ readonly options: ["deepagents", "claude-code", "codex"];
25
+ readonly description: "Tier-2 harness backend. Defaults to agent.default in config.";
26
+ };
27
+ readonly mode: {
28
+ readonly type: "enum";
29
+ readonly options: ["read-only", "supervised", "auto", "dangerous"];
30
+ readonly description: "Permission posture the harness runs under (ADR-0017). Defaults to agent.permissions.mode in config (read-only).";
31
+ };
32
+ readonly dangerouslySkipPermissions: {
33
+ readonly type: "boolean";
34
+ readonly default: false;
35
+ readonly description: "Alias for --mode dangerous.";
36
+ };
37
+ readonly sandbox: {
38
+ readonly type: "enum";
39
+ readonly options: ["auto", "process", "srt", "e2b"];
40
+ readonly description: "Isolation boundary the harness runs in (ADR-0020): process (cooperative floor), srt (enforced), or auto. Defaults to agent.sandbox in config (auto — srt when its egress bridge is healthy, else the process floor).";
41
+ };
42
+ readonly service: {
43
+ readonly type: "string";
44
+ readonly description: "Select the service context by name from `services` in config (overrides the alert's service label).";
45
+ };
46
+ readonly json: {
47
+ readonly type: "boolean";
48
+ readonly default: false;
49
+ readonly description: "Print the InvestigationReport as JSON to stdout (suppresses the human renderer).";
50
+ };
51
+ readonly output: {
52
+ readonly type: "string";
53
+ readonly description: "Write the InvestigationReport JSON to this file.";
54
+ };
55
+ readonly quiet: {
56
+ readonly type: "boolean";
57
+ readonly default: false;
58
+ readonly description: "Suppress progress + the human renderer (errors still go to stderr).";
59
+ };
60
+ }>;
61
+ export default _default;
62
+ /**
63
+ * The egress allowlist for an enforced sandbox (ADR-0020: allowlist, not closed) — the
64
+ * hostnames of every surface the harness will ACTUALLY contact: its own LLM endpoint
65
+ * (BYO-key baseURL, env override included) PLUS the read-only telemetry + log surfaces.
66
+ * The LLM + telemetry hosts carry the SAME `INVESTIGATION_DEFAULTS` fallback the request
67
+ * assembly applies (`run-investigation`), because an unset config field still resolves to
68
+ * a default the harness queries — omitting it hard-denied the model call and default
69
+ * telemetry, so every branch failed with no report. Mirrors the worker's
70
+ * `deriveWorkerAllowedHosts`. Non-URL values are skipped (no egress hole from a malformed
71
+ * endpoint); the `process` floor ignores this.
72
+ */
73
+ export declare function collectAllowedDomains(config: PlConfig): string[];
74
+ /**
75
+ * Resolve the isolation boundary for a run (ADR-0020/0017) — the single sandbox-resolution
76
+ * path shared by the `investigate` command and the JSON-RPC `serve` handler, so both honour
77
+ * `agent.sandbox` (and `--sandbox`) with identical semantics. Guards first: a mode that
78
+ * DEMANDS enforcement (`srt`/`e2b`) on a non-ACP (in-process) harness THROWS — the caller
79
+ * maps it to its own channel (CLI stderr+exit, or a JSON-RPC error), never a silent floor.
80
+ * Then resolves a boundary ONLY for an ACP harness; an in-process harness returns a null
81
+ * selection (it runs on the cooperative floor, claiming nothing — nothing dishonest). The
82
+ * returned `selection` is CALLER-OWNED — destroy it after the run. `degradeReason` is the
83
+ * honest note when `auto` fell short of srt (present only on a degrade).
84
+ */
85
+ export declare function resolveRunSandbox(harness: HarnessId, mode: SandboxMode, config: PlConfig): Promise<{
86
+ selection: SandboxSelection | null;
87
+ degradeReason: string | null;
88
+ }>;
89
+ /**
90
+ * The sandbox guard (ADR-0020/0017), mirrored in the worker's `harnessTakesSandbox`: only
91
+ * ACP-transport harnesses are spawned as a child the engine can place inside a boundary.
92
+ * Returns whether this harness `takesSandbox` and whether the request is `blocked` — the
93
+ * fail-fast case where a mode that DEMANDS an enforced boundary (`srt`/`e2b`) was asked of a
94
+ * non-ACP harness. `auto`/`process` are never blocked: they run WITHOUT a sandbox on an
95
+ * in-process harness, claiming nothing, so nothing is dishonest.
96
+ */
97
+ export declare function resolveSandboxGuard(harness: HarnessId, mode: SandboxMode): {
98
+ takesSandbox: boolean;
99
+ blocked: boolean;
100
+ };
101
+ //# sourceMappingURL=investigate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"investigate.d.ts","sourceRoot":"","sources":["../../../src/cli/investigate.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAS9E,OAAO,EAIN,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUpD,wBA+PG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,EAAE,CA0BhE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,iBAAiB,CACtC,OAAO,EAAE,SAAS,EAClB,IAAI,EAAE,WAAW,EACjB,MAAM,EAAE,QAAQ,GACd,OAAO,CAAC;IACV,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,CAAC,CAoBD;AA2BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAClC,OAAO,EAAE,SAAS,EAClB,IAAI,EAAE,WAAW,GACf;IAAE,YAAY,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAI7C"}