@openacp/cli 0.2.15 → 0.2.17

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.
@@ -0,0 +1,260 @@
1
+ import {
2
+ createChildLogger
3
+ } from "./chunk-ZATQZUJT.js";
4
+
5
+ // src/core/config.ts
6
+ import { z } from "zod";
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ import * as os from "os";
10
+ var log = createChildLogger({ module: "config" });
11
+ var BaseChannelSchema = z.object({
12
+ enabled: z.boolean().default(false),
13
+ adapter: z.string().optional()
14
+ // package name for plugin adapters
15
+ }).passthrough();
16
+ var PLUGINS_DIR = path.join(os.homedir(), ".openacp", "plugins");
17
+ var AgentSchema = z.object({
18
+ command: z.string(),
19
+ args: z.array(z.string()).default([]),
20
+ workingDirectory: z.string().optional(),
21
+ env: z.record(z.string(), z.string()).default({})
22
+ });
23
+ var LoggingSchema = z.object({
24
+ level: z.enum(["silent", "debug", "info", "warn", "error", "fatal"]).default("info"),
25
+ logDir: z.string().default("~/.openacp/logs"),
26
+ maxFileSize: z.union([z.string(), z.number()]).default("10m"),
27
+ maxFiles: z.number().default(7),
28
+ sessionLogRetentionDays: z.number().default(30)
29
+ }).default({});
30
+ var TunnelAuthSchema = z.object({
31
+ enabled: z.boolean().default(false),
32
+ token: z.string().optional()
33
+ }).default({});
34
+ var TunnelSchema = z.object({
35
+ enabled: z.boolean().default(false),
36
+ port: z.number().default(3100),
37
+ provider: z.enum(["cloudflare", "ngrok", "bore"]).default("cloudflare"),
38
+ options: z.record(z.string(), z.unknown()).default({}),
39
+ storeTtlMinutes: z.number().default(60),
40
+ auth: TunnelAuthSchema
41
+ }).default({});
42
+ var ConfigSchema = z.object({
43
+ channels: z.record(z.string(), BaseChannelSchema),
44
+ agents: z.record(z.string(), AgentSchema),
45
+ defaultAgent: z.string(),
46
+ workspace: z.object({
47
+ baseDir: z.string().default("~/openacp-workspace")
48
+ }).default({}),
49
+ security: z.object({
50
+ allowedUserIds: z.array(z.string()).default([]),
51
+ maxConcurrentSessions: z.number().default(5),
52
+ sessionTimeoutMinutes: z.number().default(60)
53
+ }).default({}),
54
+ logging: LoggingSchema,
55
+ tunnel: TunnelSchema
56
+ });
57
+ function expandHome(p) {
58
+ if (p.startsWith("~")) {
59
+ return path.join(os.homedir(), p.slice(1));
60
+ }
61
+ return p;
62
+ }
63
+ var DEFAULT_CONFIG = {
64
+ channels: {
65
+ telegram: {
66
+ enabled: false,
67
+ botToken: "YOUR_BOT_TOKEN_HERE",
68
+ chatId: 0,
69
+ notificationTopicId: null,
70
+ assistantTopicId: null
71
+ }
72
+ },
73
+ agents: {
74
+ claude: { command: "claude-agent-acp", args: [], env: {} },
75
+ codex: { command: "codex", args: ["--acp"], env: {} }
76
+ },
77
+ defaultAgent: "claude",
78
+ workspace: { baseDir: "~/openacp-workspace" },
79
+ security: { allowedUserIds: [], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }
80
+ };
81
+ var ConfigManager = class {
82
+ config;
83
+ configPath;
84
+ constructor() {
85
+ this.configPath = process.env.OPENACP_CONFIG_PATH || expandHome("~/.openacp/config.json");
86
+ }
87
+ async load() {
88
+ const dir = path.dirname(this.configPath);
89
+ fs.mkdirSync(dir, { recursive: true });
90
+ if (!fs.existsSync(this.configPath)) {
91
+ fs.writeFileSync(this.configPath, JSON.stringify(DEFAULT_CONFIG, null, 2));
92
+ log.info({ configPath: this.configPath }, "Config created");
93
+ log.info("Please edit it with your Telegram bot token and chat ID, then restart.");
94
+ process.exit(1);
95
+ }
96
+ const raw = JSON.parse(fs.readFileSync(this.configPath, "utf-8"));
97
+ this.applyEnvOverrides(raw);
98
+ const result = ConfigSchema.safeParse(raw);
99
+ if (!result.success) {
100
+ log.error("Config validation failed");
101
+ for (const issue of result.error.issues) {
102
+ log.error({ path: issue.path.join("."), message: issue.message }, "Validation error");
103
+ }
104
+ process.exit(1);
105
+ }
106
+ this.config = result.data;
107
+ }
108
+ get() {
109
+ return this.config;
110
+ }
111
+ async save(updates) {
112
+ const raw = JSON.parse(fs.readFileSync(this.configPath, "utf-8"));
113
+ this.deepMerge(raw, updates);
114
+ fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2));
115
+ const result = ConfigSchema.safeParse(raw);
116
+ if (result.success) {
117
+ this.config = result.data;
118
+ }
119
+ }
120
+ resolveWorkspace(input) {
121
+ if (!input) {
122
+ const resolved2 = expandHome(this.config.workspace.baseDir);
123
+ fs.mkdirSync(resolved2, { recursive: true });
124
+ return resolved2;
125
+ }
126
+ if (input.startsWith("/") || input.startsWith("~")) {
127
+ const resolved2 = expandHome(input);
128
+ fs.mkdirSync(resolved2, { recursive: true });
129
+ return resolved2;
130
+ }
131
+ const name = input.toLowerCase();
132
+ const resolved = path.join(expandHome(this.config.workspace.baseDir), name);
133
+ fs.mkdirSync(resolved, { recursive: true });
134
+ return resolved;
135
+ }
136
+ async exists() {
137
+ return fs.existsSync(this.configPath);
138
+ }
139
+ getConfigPath() {
140
+ return this.configPath;
141
+ }
142
+ async writeNew(config) {
143
+ const dir = path.dirname(this.configPath);
144
+ fs.mkdirSync(dir, { recursive: true });
145
+ fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2));
146
+ }
147
+ applyEnvOverrides(raw) {
148
+ const overrides = [
149
+ ["OPENACP_TELEGRAM_BOT_TOKEN", ["channels", "telegram", "botToken"]],
150
+ ["OPENACP_TELEGRAM_CHAT_ID", ["channels", "telegram", "chatId"]],
151
+ ["OPENACP_DEFAULT_AGENT", ["defaultAgent"]]
152
+ ];
153
+ for (const [envVar, configPath] of overrides) {
154
+ const value = process.env[envVar];
155
+ if (value !== void 0) {
156
+ let target = raw;
157
+ for (let i = 0; i < configPath.length - 1; i++) {
158
+ if (!target[configPath[i]]) target[configPath[i]] = {};
159
+ target = target[configPath[i]];
160
+ }
161
+ const key = configPath[configPath.length - 1];
162
+ target[key] = key === "chatId" ? Number(value) : value;
163
+ }
164
+ }
165
+ if (process.env.OPENACP_LOG_LEVEL) {
166
+ raw.logging = raw.logging || {};
167
+ raw.logging.level = process.env.OPENACP_LOG_LEVEL;
168
+ }
169
+ if (process.env.OPENACP_LOG_DIR) {
170
+ raw.logging = raw.logging || {};
171
+ raw.logging.logDir = process.env.OPENACP_LOG_DIR;
172
+ }
173
+ if (process.env.OPENACP_DEBUG && !process.env.OPENACP_LOG_LEVEL) {
174
+ raw.logging = raw.logging || {};
175
+ raw.logging.level = "debug";
176
+ }
177
+ if (process.env.OPENACP_TUNNEL_ENABLED) {
178
+ raw.tunnel = raw.tunnel || {};
179
+ raw.tunnel.enabled = process.env.OPENACP_TUNNEL_ENABLED === "true";
180
+ }
181
+ if (process.env.OPENACP_TUNNEL_PORT) {
182
+ raw.tunnel = raw.tunnel || {};
183
+ raw.tunnel.port = Number(process.env.OPENACP_TUNNEL_PORT);
184
+ }
185
+ if (process.env.OPENACP_TUNNEL_PROVIDER) {
186
+ raw.tunnel = raw.tunnel || {};
187
+ raw.tunnel.provider = process.env.OPENACP_TUNNEL_PROVIDER;
188
+ }
189
+ }
190
+ deepMerge(target, source) {
191
+ for (const key of Object.keys(source)) {
192
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
193
+ if (!target[key]) target[key] = {};
194
+ this.deepMerge(target[key], source[key]);
195
+ } else {
196
+ target[key] = source[key];
197
+ }
198
+ }
199
+ }
200
+ };
201
+
202
+ // src/core/plugin-manager.ts
203
+ import { execSync } from "child_process";
204
+ import * as fs2 from "fs";
205
+ import * as path2 from "path";
206
+ import { createRequire } from "module";
207
+ var log2 = createChildLogger({ module: "plugin-manager" });
208
+ function ensurePluginsDir() {
209
+ fs2.mkdirSync(PLUGINS_DIR, { recursive: true });
210
+ const pkgPath = path2.join(PLUGINS_DIR, "package.json");
211
+ if (!fs2.existsSync(pkgPath)) {
212
+ fs2.writeFileSync(pkgPath, JSON.stringify({ name: "openacp-plugins", private: true, dependencies: {} }, null, 2));
213
+ }
214
+ }
215
+ function installPlugin(packageName) {
216
+ ensurePluginsDir();
217
+ log2.info({ packageName }, "Installing plugin");
218
+ execSync(`npm install ${packageName} --prefix "${PLUGINS_DIR}"`, { stdio: "inherit" });
219
+ log2.info({ packageName }, "Plugin installed successfully");
220
+ }
221
+ function uninstallPlugin(packageName) {
222
+ ensurePluginsDir();
223
+ log2.info({ packageName }, "Uninstalling plugin");
224
+ execSync(`npm uninstall ${packageName} --prefix "${PLUGINS_DIR}"`, { stdio: "inherit" });
225
+ log2.info({ packageName }, "Plugin uninstalled");
226
+ }
227
+ function listPlugins() {
228
+ const pkgPath = path2.join(PLUGINS_DIR, "package.json");
229
+ if (!fs2.existsSync(pkgPath)) return {};
230
+ const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
231
+ return pkg.dependencies || {};
232
+ }
233
+ async function loadAdapterFactory(packageName) {
234
+ try {
235
+ const require2 = createRequire(path2.join(PLUGINS_DIR, "package.json"));
236
+ const resolved = require2.resolve(packageName);
237
+ const mod = await import(resolved);
238
+ const factory = mod.adapterFactory || mod.default;
239
+ if (!factory || typeof factory.createAdapter !== "function") {
240
+ log2.error({ packageName }, "Plugin does not export a valid AdapterFactory (needs .createAdapter())");
241
+ return null;
242
+ }
243
+ return factory;
244
+ } catch (err) {
245
+ log2.error({ packageName, err }, "Failed to load plugin");
246
+ log2.error({ packageName }, "Run: npx openacp install <packageName>");
247
+ return null;
248
+ }
249
+ }
250
+
251
+ export {
252
+ PLUGINS_DIR,
253
+ expandHome,
254
+ ConfigManager,
255
+ installPlugin,
256
+ uninstallPlugin,
257
+ listPlugins,
258
+ loadAdapterFactory
259
+ };
260
+ //# sourceMappingURL=chunk-QY32F5S7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/config.ts","../../src/core/plugin-manager.ts"],"sourcesContent":["import { z } from 'zod'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport * as os from 'node:os'\nimport { createChildLogger } from './log.js'\nconst log = createChildLogger({ module: 'config' })\n\nconst BaseChannelSchema = z.object({\n enabled: z.boolean().default(false),\n adapter: z.string().optional(), // package name for plugin adapters\n}).passthrough()\n\nexport const PLUGINS_DIR = path.join(os.homedir(), '.openacp', 'plugins')\n\nconst AgentSchema = z.object({\n command: z.string(),\n args: z.array(z.string()).default([]),\n workingDirectory: z.string().optional(),\n env: z.record(z.string(), z.string()).default({}),\n})\n\nconst LoggingSchema = z.object({\n level: z.enum(['silent', 'debug', 'info', 'warn', 'error', 'fatal']).default('info'),\n logDir: z.string().default('~/.openacp/logs'),\n maxFileSize: z.union([z.string(), z.number()]).default('10m'),\n maxFiles: z.number().default(7),\n sessionLogRetentionDays: z.number().default(30),\n}).default({})\n\nexport type LoggingConfig = z.infer<typeof LoggingSchema>\n\nconst TunnelAuthSchema = z.object({\n enabled: z.boolean().default(false),\n token: z.string().optional(),\n}).default({})\n\nconst TunnelSchema = z.object({\n enabled: z.boolean().default(false),\n port: z.number().default(3100),\n provider: z.enum(['cloudflare', 'ngrok', 'bore']).default('cloudflare'),\n options: z.record(z.string(), z.unknown()).default({}),\n storeTtlMinutes: z.number().default(60),\n auth: TunnelAuthSchema,\n}).default({})\n\nexport type TunnelConfig = z.infer<typeof TunnelSchema>\n\nexport const ConfigSchema = z.object({\n channels: z.record(z.string(), BaseChannelSchema),\n agents: z.record(z.string(), AgentSchema),\n defaultAgent: z.string(),\n workspace: z.object({\n baseDir: z.string().default('~/openacp-workspace'),\n }).default({}),\n security: z.object({\n allowedUserIds: z.array(z.string()).default([]),\n maxConcurrentSessions: z.number().default(5),\n sessionTimeoutMinutes: z.number().default(60),\n }).default({}),\n logging: LoggingSchema,\n tunnel: TunnelSchema,\n})\n\nexport type Config = z.infer<typeof ConfigSchema>\n\nexport function expandHome(p: string): string {\n if (p.startsWith('~')) {\n return path.join(os.homedir(), p.slice(1))\n }\n return p\n}\n\nconst DEFAULT_CONFIG = {\n channels: {\n telegram: {\n enabled: false,\n botToken: \"YOUR_BOT_TOKEN_HERE\",\n chatId: 0,\n notificationTopicId: null,\n assistantTopicId: null\n }\n },\n agents: {\n claude: { command: \"claude-agent-acp\", args: [], env: {} },\n codex: { command: \"codex\", args: [\"--acp\"], env: {} }\n },\n defaultAgent: \"claude\",\n workspace: { baseDir: \"~/openacp-workspace\" },\n security: { allowedUserIds: [], maxConcurrentSessions: 5, sessionTimeoutMinutes: 60 }\n}\n\nexport class ConfigManager {\n private config!: Config\n private configPath: string\n\n constructor() {\n this.configPath = process.env.OPENACP_CONFIG_PATH || expandHome('~/.openacp/config.json')\n }\n\n async load(): Promise<void> {\n // 1. Ensure directory exists\n const dir = path.dirname(this.configPath)\n fs.mkdirSync(dir, { recursive: true })\n\n // 2. If config file doesn't exist, create default\n if (!fs.existsSync(this.configPath)) {\n fs.writeFileSync(this.configPath, JSON.stringify(DEFAULT_CONFIG, null, 2))\n log.info({ configPath: this.configPath }, 'Config created')\n log.info('Please edit it with your Telegram bot token and chat ID, then restart.')\n process.exit(1)\n }\n\n // 3. Read and parse\n const raw = JSON.parse(fs.readFileSync(this.configPath, 'utf-8'))\n\n // 4. Apply env var overrides\n this.applyEnvOverrides(raw)\n\n // 5. Validate with Zod\n const result = ConfigSchema.safeParse(raw)\n if (!result.success) {\n log.error('Config validation failed')\n for (const issue of result.error.issues) {\n log.error({ path: issue.path.join('.'), message: issue.message }, 'Validation error')\n }\n process.exit(1)\n }\n this.config = result.data\n }\n\n get(): Config {\n return this.config\n }\n\n async save(updates: Record<string, unknown>): Promise<void> {\n // Read current file, merge updates, write back\n const raw = JSON.parse(fs.readFileSync(this.configPath, 'utf-8'))\n this.deepMerge(raw, updates)\n fs.writeFileSync(this.configPath, JSON.stringify(raw, null, 2))\n // Re-validate and update in-memory config\n const result = ConfigSchema.safeParse(raw)\n if (result.success) {\n this.config = result.data\n }\n }\n\n resolveWorkspace(input?: string): string {\n if (!input) {\n const resolved = expandHome(this.config.workspace.baseDir)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n if (input.startsWith('/') || input.startsWith('~')) {\n const resolved = expandHome(input)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n // Named workspace → lowercase, under baseDir\n const name = input.toLowerCase()\n const resolved = path.join(expandHome(this.config.workspace.baseDir), name)\n fs.mkdirSync(resolved, { recursive: true })\n return resolved\n }\n\n async exists(): Promise<boolean> {\n return fs.existsSync(this.configPath)\n }\n\n getConfigPath(): string {\n return this.configPath\n }\n\n async writeNew(config: Config): Promise<void> {\n const dir = path.dirname(this.configPath)\n fs.mkdirSync(dir, { recursive: true })\n fs.writeFileSync(this.configPath, JSON.stringify(config, null, 2))\n }\n\n private applyEnvOverrides(raw: Record<string, unknown>): void {\n const overrides: [string, string[]][] = [\n ['OPENACP_TELEGRAM_BOT_TOKEN', ['channels', 'telegram', 'botToken']],\n ['OPENACP_TELEGRAM_CHAT_ID', ['channels', 'telegram', 'chatId']],\n ['OPENACP_DEFAULT_AGENT', ['defaultAgent']],\n ]\n for (const [envVar, configPath] of overrides) {\n const value = process.env[envVar]\n if (value !== undefined) {\n let target = raw as Record<string, any>\n for (let i = 0; i < configPath.length - 1; i++) {\n if (!target[configPath[i]]) target[configPath[i]] = {}\n target = target[configPath[i]]\n }\n const key = configPath[configPath.length - 1]\n // Convert chatId to number\n target[key] = key === 'chatId' ? Number(value) : value\n }\n }\n\n // Logging env var overrides\n if (process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {}\n ;(raw.logging as Record<string, unknown>).level = process.env.OPENACP_LOG_LEVEL\n }\n if (process.env.OPENACP_LOG_DIR) {\n raw.logging = raw.logging || {}\n ;(raw.logging as Record<string, unknown>).logDir = process.env.OPENACP_LOG_DIR\n }\n if (process.env.OPENACP_DEBUG && !process.env.OPENACP_LOG_LEVEL) {\n raw.logging = raw.logging || {}\n ;(raw.logging as Record<string, unknown>).level = 'debug'\n }\n\n // Tunnel env var overrides\n if (process.env.OPENACP_TUNNEL_ENABLED) {\n raw.tunnel = raw.tunnel || {}\n ;(raw.tunnel as Record<string, unknown>).enabled = process.env.OPENACP_TUNNEL_ENABLED === 'true'\n }\n if (process.env.OPENACP_TUNNEL_PORT) {\n raw.tunnel = raw.tunnel || {}\n ;(raw.tunnel as Record<string, unknown>).port = Number(process.env.OPENACP_TUNNEL_PORT)\n }\n if (process.env.OPENACP_TUNNEL_PROVIDER) {\n raw.tunnel = raw.tunnel || {}\n ;(raw.tunnel as Record<string, unknown>).provider = process.env.OPENACP_TUNNEL_PROVIDER\n }\n }\n\n private deepMerge(target: Record<string, any>, source: Record<string, any>): void {\n for (const key of Object.keys(source)) {\n if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {\n if (!target[key]) target[key] = {}\n this.deepMerge(target[key], source[key])\n } else {\n target[key] = source[key]\n }\n }\n }\n}\n","import { execSync } from 'node:child_process'\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\nimport { createRequire } from 'node:module'\nimport { PLUGINS_DIR } from './config.js'\nimport { createChildLogger } from './log.js'\nconst log = createChildLogger({ module: 'plugin-manager' })\nimport type { ChannelAdapter } from './channel.js'\n\nexport interface AdapterFactory {\n name: string\n createAdapter(core: any, config: any): ChannelAdapter\n}\n\nfunction ensurePluginsDir(): void {\n fs.mkdirSync(PLUGINS_DIR, { recursive: true })\n const pkgPath = path.join(PLUGINS_DIR, 'package.json')\n if (!fs.existsSync(pkgPath)) {\n fs.writeFileSync(pkgPath, JSON.stringify({ name: 'openacp-plugins', private: true, dependencies: {} }, null, 2))\n }\n}\n\nexport function installPlugin(packageName: string): void {\n ensurePluginsDir()\n log.info({ packageName }, 'Installing plugin')\n execSync(`npm install ${packageName} --prefix \"${PLUGINS_DIR}\"`, { stdio: 'inherit' })\n log.info({ packageName }, 'Plugin installed successfully')\n}\n\nexport function uninstallPlugin(packageName: string): void {\n ensurePluginsDir()\n log.info({ packageName }, 'Uninstalling plugin')\n execSync(`npm uninstall ${packageName} --prefix \"${PLUGINS_DIR}\"`, { stdio: 'inherit' })\n log.info({ packageName }, 'Plugin uninstalled')\n}\n\nexport function listPlugins(): Record<string, string> {\n const pkgPath = path.join(PLUGINS_DIR, 'package.json')\n if (!fs.existsSync(pkgPath)) return {}\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))\n return pkg.dependencies || {}\n}\n\nexport async function loadAdapterFactory(packageName: string): Promise<AdapterFactory | null> {\n try {\n const require = createRequire(path.join(PLUGINS_DIR, 'package.json'))\n const resolved = require.resolve(packageName)\n const mod = await import(resolved)\n\n // Plugin must export `adapterFactory` or default export conforming to AdapterFactory\n const factory: AdapterFactory | undefined = mod.adapterFactory || mod.default\n if (!factory || typeof factory.createAdapter !== 'function') {\n log.error({ packageName }, 'Plugin does not export a valid AdapterFactory (needs .createAdapter())')\n return null\n }\n return factory\n } catch (err) {\n log.error({ packageName, err }, 'Failed to load plugin')\n log.error({ packageName }, 'Run: npx openacp install <packageName>')\n return null\n }\n}\n"],"mappings":"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","names":["resolved","fs","path","log","require"]}
@@ -0,0 +1,193 @@
1
+ // src/core/log.ts
2
+ import pino from "pino";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import os from "os";
6
+ var rootLogger = pino({
7
+ level: "debug",
8
+ transport: { target: "pino-pretty", options: { colorize: true, translateTime: "SYS:standard" } }
9
+ });
10
+ var initialized = false;
11
+ var logDir;
12
+ function expandHome(p) {
13
+ return p.startsWith("~") ? path.join(os.homedir(), p.slice(1)) : p;
14
+ }
15
+ function wrapVariadic(logger) {
16
+ return {
17
+ info: (...args) => {
18
+ if (args.length === 0) return;
19
+ if (typeof args[0] === "object" && args[0] !== null && !(args[0] instanceof Error)) {
20
+ logger.info(args[0], args.slice(1).join(" "));
21
+ } else {
22
+ logger.info(args.map(String).join(" "));
23
+ }
24
+ },
25
+ warn: (...args) => {
26
+ if (args.length === 0) return;
27
+ if (typeof args[0] === "object" && args[0] !== null && !(args[0] instanceof Error)) {
28
+ logger.warn(args[0], args.slice(1).join(" "));
29
+ } else {
30
+ logger.warn(args.map(String).join(" "));
31
+ }
32
+ },
33
+ error: (...args) => {
34
+ if (args.length === 0) return;
35
+ if (typeof args[0] === "object" && args[0] !== null && !(args[0] instanceof Error)) {
36
+ logger.error(args[0], args.slice(1).join(" "));
37
+ } else {
38
+ logger.error(args.map(String).join(" "));
39
+ }
40
+ },
41
+ debug: (...args) => {
42
+ if (args.length === 0) return;
43
+ if (typeof args[0] === "object" && args[0] !== null && !(args[0] instanceof Error)) {
44
+ logger.debug(args[0], args.slice(1).join(" "));
45
+ } else {
46
+ logger.debug(args.map(String).join(" "));
47
+ }
48
+ },
49
+ fatal: (...args) => {
50
+ if (args.length === 0) return;
51
+ if (typeof args[0] === "object" && args[0] !== null && !(args[0] instanceof Error)) {
52
+ logger.fatal(args[0], args.slice(1).join(" "));
53
+ } else {
54
+ logger.fatal(args.map(String).join(" "));
55
+ }
56
+ },
57
+ child: (bindings) => logger.child(bindings)
58
+ };
59
+ }
60
+ var log = wrapVariadic(rootLogger);
61
+ function initLogger(config) {
62
+ if (initialized) return rootLogger;
63
+ const resolvedLogDir = expandHome(config.logDir);
64
+ logDir = resolvedLogDir;
65
+ try {
66
+ fs.mkdirSync(resolvedLogDir, { recursive: true });
67
+ fs.mkdirSync(path.join(resolvedLogDir, "sessions"), { recursive: true });
68
+ } catch (err) {
69
+ console.error(`[WARN] Failed to create log directory ${resolvedLogDir}, falling back to console-only:`, err);
70
+ return rootLogger;
71
+ }
72
+ const transports = pino.transport({
73
+ targets: [
74
+ {
75
+ target: "pino-pretty",
76
+ options: { colorize: true, translateTime: "SYS:standard" },
77
+ level: config.level
78
+ },
79
+ {
80
+ target: "pino-roll",
81
+ options: {
82
+ file: path.join(resolvedLogDir, "openacp.log"),
83
+ size: config.maxFileSize,
84
+ limit: { count: config.maxFiles }
85
+ },
86
+ level: config.level
87
+ }
88
+ ]
89
+ });
90
+ rootLogger = pino({ level: config.level }, transports);
91
+ initialized = true;
92
+ Object.assign(log, wrapVariadic(rootLogger));
93
+ return rootLogger;
94
+ }
95
+ function createChildLogger(context) {
96
+ return new Proxy({}, {
97
+ get(_target, prop, receiver) {
98
+ const child = rootLogger.child(context);
99
+ const value = Reflect.get(child, prop, receiver);
100
+ return typeof value === "function" ? value.bind(child) : value;
101
+ }
102
+ });
103
+ }
104
+ function createSessionLogger(sessionId, parentLogger) {
105
+ const sessionLogDir = logDir ? path.join(logDir, "sessions") : void 0;
106
+ if (!sessionLogDir) {
107
+ return parentLogger.child({ sessionId });
108
+ }
109
+ try {
110
+ const sessionLogPath = path.join(sessionLogDir, `${sessionId}.log`);
111
+ const dest = pino.destination(sessionLogPath);
112
+ const sessionFileLogger = pino({ level: parentLogger.level }, dest).child({ sessionId });
113
+ const combinedChild = parentLogger.child({ sessionId });
114
+ const originalInfo = combinedChild.info.bind(combinedChild);
115
+ const originalWarn = combinedChild.warn.bind(combinedChild);
116
+ const originalError = combinedChild.error.bind(combinedChild);
117
+ const originalDebug = combinedChild.debug.bind(combinedChild);
118
+ const originalFatal = combinedChild.fatal.bind(combinedChild);
119
+ combinedChild.info = ((objOrMsg, ...rest) => {
120
+ sessionFileLogger.info(objOrMsg, ...rest);
121
+ return originalInfo(objOrMsg, ...rest);
122
+ });
123
+ combinedChild.warn = ((objOrMsg, ...rest) => {
124
+ sessionFileLogger.warn(objOrMsg, ...rest);
125
+ return originalWarn(objOrMsg, ...rest);
126
+ });
127
+ combinedChild.error = ((objOrMsg, ...rest) => {
128
+ sessionFileLogger.error(objOrMsg, ...rest);
129
+ return originalError(objOrMsg, ...rest);
130
+ });
131
+ combinedChild.debug = ((objOrMsg, ...rest) => {
132
+ sessionFileLogger.debug(objOrMsg, ...rest);
133
+ return originalDebug(objOrMsg, ...rest);
134
+ });
135
+ combinedChild.fatal = ((objOrMsg, ...rest) => {
136
+ sessionFileLogger.fatal(objOrMsg, ...rest);
137
+ return originalFatal(objOrMsg, ...rest);
138
+ });
139
+ combinedChild.__sessionDest = dest;
140
+ return combinedChild;
141
+ } catch (err) {
142
+ parentLogger.warn({ sessionId, err }, "Failed to create session log file, using combined log only");
143
+ return parentLogger.child({ sessionId });
144
+ }
145
+ }
146
+ async function shutdownLogger() {
147
+ if (!initialized) return;
148
+ return new Promise((resolve) => {
149
+ const timeout = setTimeout(() => {
150
+ resolve();
151
+ }, 5e3);
152
+ rootLogger.flush();
153
+ setTimeout(() => {
154
+ clearTimeout(timeout);
155
+ rootLogger = pino({ level: "debug" });
156
+ Object.assign(log, wrapVariadic(rootLogger));
157
+ logDir = void 0;
158
+ initialized = false;
159
+ resolve();
160
+ }, 500);
161
+ });
162
+ }
163
+ async function cleanupOldSessionLogs(retentionDays) {
164
+ if (!logDir) return;
165
+ const sessionsDir = path.join(logDir, "sessions");
166
+ try {
167
+ const files = await fs.promises.readdir(sessionsDir);
168
+ const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
169
+ for (const file of files) {
170
+ try {
171
+ const filePath = path.join(sessionsDir, file);
172
+ const stat = await fs.promises.stat(filePath);
173
+ if (stat.mtimeMs < cutoff) {
174
+ await fs.promises.unlink(filePath);
175
+ rootLogger.debug({ file }, "Deleted old session log");
176
+ }
177
+ } catch (err) {
178
+ rootLogger.warn({ file, err }, "Failed to delete old session log");
179
+ }
180
+ }
181
+ } catch {
182
+ }
183
+ }
184
+
185
+ export {
186
+ log,
187
+ initLogger,
188
+ createChildLogger,
189
+ createSessionLogger,
190
+ shutdownLogger,
191
+ cleanupOldSessionLogs
192
+ };
193
+ //# sourceMappingURL=chunk-ZATQZUJT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/log.ts"],"sourcesContent":["import pino from 'pino'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { LoggingConfig } from './config.js'\n\nexport type Logger = pino.Logger\n\n// --- Default console-only logger (pre-init) ---\nlet rootLogger: pino.Logger = pino({\n level: 'debug',\n transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard' } },\n})\nlet initialized = false\nlet logDir: string | undefined\n\nfunction expandHome(p: string): string {\n return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p\n}\n\n// --- Variadic wrapper for backward compatibility ---\nfunction wrapVariadic(logger: pino.Logger) {\n return {\n info: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.info(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.info(args.map(String).join(' '))\n }\n },\n warn: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.warn(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.warn(args.map(String).join(' '))\n }\n },\n error: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.error(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.error(args.map(String).join(' '))\n }\n },\n debug: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.debug(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.debug(args.map(String).join(' '))\n }\n },\n fatal: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.fatal(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.fatal(args.map(String).join(' '))\n }\n },\n child: (bindings: pino.Bindings) => logger.child(bindings),\n }\n}\n\nexport const log = wrapVariadic(rootLogger)\n\n// --- Public API ---\n\nexport function initLogger(config: LoggingConfig): Logger {\n if (initialized) return rootLogger\n\n const resolvedLogDir = expandHome(config.logDir)\n logDir = resolvedLogDir\n\n try {\n fs.mkdirSync(resolvedLogDir, { recursive: true })\n fs.mkdirSync(path.join(resolvedLogDir, 'sessions'), { recursive: true })\n } catch (err) {\n console.error(`[WARN] Failed to create log directory ${resolvedLogDir}, falling back to console-only:`, err)\n return rootLogger\n }\n\n const transports = pino.transport({\n targets: [\n {\n target: 'pino-pretty',\n options: { colorize: true, translateTime: 'SYS:standard' },\n level: config.level,\n },\n {\n target: 'pino-roll',\n options: {\n file: path.join(resolvedLogDir, 'openacp.log'),\n size: config.maxFileSize,\n limit: { count: config.maxFiles },\n },\n level: config.level,\n },\n ],\n })\n\n rootLogger = pino({ level: config.level }, transports)\n initialized = true\n\n // Update the default log wrapper to use the new root logger\n Object.assign(log, wrapVariadic(rootLogger))\n\n return rootLogger\n}\n\nexport function createChildLogger(context: { module: string; [key: string]: unknown }): Logger {\n // Return a proxy that always delegates to the current rootLogger.\n // This ensures child loggers created at module-level (before initLogger)\n // pick up the initialized logger with pino-pretty transport.\n return new Proxy({} as Logger, {\n get(_target, prop, receiver) {\n const child = rootLogger.child(context)\n const value = Reflect.get(child, prop, receiver)\n return typeof value === 'function' ? value.bind(child) : value\n },\n })\n}\n\nexport function createSessionLogger(sessionId: string, parentLogger: Logger): Logger {\n const sessionLogDir = logDir ? path.join(logDir, 'sessions') : undefined\n if (!sessionLogDir) {\n return parentLogger.child({ sessionId })\n }\n\n try {\n const sessionLogPath = path.join(sessionLogDir, `${sessionId}.log`)\n const dest = pino.destination(sessionLogPath)\n const sessionFileLogger = pino({ level: parentLogger.level }, dest).child({ sessionId })\n\n // Create a logger that writes to both parent (combined) and session file\n const combinedChild = parentLogger.child({ sessionId })\n const originalInfo = combinedChild.info.bind(combinedChild)\n const originalWarn = combinedChild.warn.bind(combinedChild)\n const originalError = combinedChild.error.bind(combinedChild)\n const originalDebug = combinedChild.debug.bind(combinedChild)\n const originalFatal = combinedChild.fatal.bind(combinedChild)\n\n // Proxy log methods to write to both destinations\n combinedChild.info = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.info(objOrMsg, ...rest)\n return originalInfo(objOrMsg, ...rest)\n }) as any\n combinedChild.warn = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.warn(objOrMsg, ...rest)\n return originalWarn(objOrMsg, ...rest)\n }) as any\n combinedChild.error = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.error(objOrMsg, ...rest)\n return originalError(objOrMsg, ...rest)\n }) as any\n combinedChild.debug = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.debug(objOrMsg, ...rest)\n return originalDebug(objOrMsg, ...rest)\n }) as any\n combinedChild.fatal = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.fatal(objOrMsg, ...rest)\n return originalFatal(objOrMsg, ...rest)\n }) as any\n\n // Store dest for cleanup\n ;(combinedChild as any).__sessionDest = dest\n\n return combinedChild\n } catch (err) {\n // Graceful degradation: session file failed, just use combined log\n parentLogger.warn({ sessionId, err }, 'Failed to create session log file, using combined log only')\n return parentLogger.child({ sessionId })\n }\n}\n\nexport async function shutdownLogger(): Promise<void> {\n if (!initialized) return\n\n return new Promise<void>((resolve) => {\n const timeout = setTimeout(() => {\n resolve()\n }, 5000)\n\n rootLogger.flush()\n // Give transports time to flush\n setTimeout(() => {\n clearTimeout(timeout)\n // Reset to console-only logger so tests can re-init\n rootLogger = pino({ level: 'debug' })\n Object.assign(log, wrapVariadic(rootLogger))\n logDir = undefined\n initialized = false\n resolve()\n }, 500)\n })\n}\n\nexport async function cleanupOldSessionLogs(retentionDays: number): Promise<void> {\n if (!logDir) return\n\n const sessionsDir = path.join(logDir, 'sessions')\n try {\n const files = await fs.promises.readdir(sessionsDir)\n const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n\n for (const file of files) {\n try {\n const filePath = path.join(sessionsDir, file)\n const stat = await fs.promises.stat(filePath)\n if (stat.mtimeMs < cutoff) {\n await fs.promises.unlink(filePath)\n rootLogger.debug({ file }, 'Deleted old session log')\n }\n } catch (err) {\n rootLogger.warn({ file, err }, 'Failed to delete old session log')\n }\n }\n } catch {\n // Sessions directory doesn't exist — no-op\n }\n}\n"],"mappings":"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","names":[]}
package/dist/cli.js CHANGED
@@ -3,7 +3,8 @@ import {
3
3
  installPlugin,
4
4
  listPlugins,
5
5
  uninstallPlugin
6
- } from "./chunk-HTUZOMIT.js";
6
+ } from "./chunk-QY32F5S7.js";
7
+ import "./chunk-ZATQZUJT.js";
7
8
 
8
9
  // src/cli.ts
9
10
  var args = process.argv.slice(2);
@@ -81,7 +82,7 @@ async function main() {
81
82
  printHelp();
82
83
  process.exit(1);
83
84
  }
84
- const { startServer } = await import("./main-PB2TMO3M.js");
85
+ const { startServer } = await import("./main-OAVE4LUW.js");
85
86
  await startServer();
86
87
  }
87
88
  main().catch((err) => {
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { installPlugin, uninstallPlugin, listPlugins } from './core/plugin-manager.js'\n\nconst args = process.argv.slice(2)\nconst command = args[0]\n\nfunction printHelp(): void {\n console.log(`\nOpenACP - Self-hosted bridge for AI coding agents\n\nUsage:\n openacp Start the server\n openacp install <package> Install a plugin adapter\n openacp uninstall <package> Uninstall a plugin adapter\n openacp plugins List installed plugins\n openacp --version Show version\n openacp --help Show this help\n\nInstall:\n npm install -g @openacp/cli\n\nExamples:\n openacp\n openacp install @openacp/adapter-discord\n openacp uninstall @openacp/adapter-discord\n`)\n}\n\nasync function main() {\n if (command === '--help' || command === '-h') {\n printHelp()\n return\n }\n\n if (command === '--version' || command === '-v') {\n // In published build: read version from own package.json via createRequire\n // In dev: fallback to 'dev'\n try {\n const { createRequire } = await import('node:module')\n const require = createRequire(import.meta.url)\n const pkg = require('../package.json')\n console.log(`openacp v${pkg.version}`)\n } catch {\n console.log('openacp v0.0.0-dev')\n }\n return\n }\n\n if (command === 'install') {\n const pkg = args[1]\n if (!pkg) {\n console.error('Usage: openacp install <package>')\n process.exit(1)\n }\n installPlugin(pkg)\n return\n }\n\n if (command === 'uninstall') {\n const pkg = args[1]\n if (!pkg) {\n console.error('Usage: openacp uninstall <package>')\n process.exit(1)\n }\n uninstallPlugin(pkg)\n return\n }\n\n if (command === 'plugins') {\n const plugins = listPlugins()\n const entries = Object.entries(plugins)\n if (entries.length === 0) {\n console.log('No plugins installed.')\n } else {\n console.log('Installed plugins:')\n for (const [name, version] of entries) {\n console.log(` ${name}@${version}`)\n }\n }\n return\n }\n\n // Default: start server\n if (command && !command.startsWith('-')) {\n console.error(`Unknown command: ${command}`)\n printHelp()\n process.exit(1)\n }\n\n // Import and run server start\n const { startServer } = await import('./main.js')\n await startServer()\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;AAIA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AAEtB,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAkBb;AACD;AAEA,eAAe,OAAO;AACpB,MAAI,YAAY,YAAY,YAAY,MAAM;AAC5C,cAAU;AACV;AAAA,EACF;AAEA,MAAI,YAAY,eAAe,YAAY,MAAM;AAG/C,QAAI;AACF,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,QAAa;AACpD,YAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,YAAM,MAAMA,SAAQ,iBAAiB;AACrC,cAAQ,IAAI,YAAY,IAAI,OAAO,EAAE;AAAA,IACvC,QAAQ;AACN,cAAQ,IAAI,oBAAoB;AAAA,IAClC;AACA;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,kCAAkC;AAChD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,kBAAc,GAAG;AACjB;AAAA,EACF;AAEA,MAAI,YAAY,aAAa;AAC3B,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,oBAAgB,GAAG;AACnB;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,UAAM,UAAU,YAAY;AAC5B,UAAM,UAAU,OAAO,QAAQ,OAAO;AACtC,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAI,uBAAuB;AAAA,IACrC,OAAO;AACL,cAAQ,IAAI,oBAAoB;AAChC,iBAAW,CAAC,MAAM,OAAO,KAAK,SAAS;AACrC,gBAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,EAAE;AAAA,MACpC;AAAA,IACF;AACA;AAAA,EACF;AAGA,MAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;AACvC,YAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,cAAU;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,oBAAW;AAChD,QAAM,YAAY;AACpB;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["require"]}
1
+ {"version":3,"sources":["../../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { installPlugin, uninstallPlugin, listPlugins } from './core/plugin-manager.js'\n\nconst args = process.argv.slice(2)\nconst command = args[0]\n\nfunction printHelp(): void {\n console.log(`\nOpenACP - Self-hosted bridge for AI coding agents\n\nUsage:\n openacp Start the server\n openacp install <package> Install a plugin adapter\n openacp uninstall <package> Uninstall a plugin adapter\n openacp plugins List installed plugins\n openacp --version Show version\n openacp --help Show this help\n\nInstall:\n npm install -g @openacp/cli\n\nExamples:\n openacp\n openacp install @openacp/adapter-discord\n openacp uninstall @openacp/adapter-discord\n`)\n}\n\nasync function main() {\n if (command === '--help' || command === '-h') {\n printHelp()\n return\n }\n\n if (command === '--version' || command === '-v') {\n // In published build: read version from own package.json via createRequire\n // In dev: fallback to 'dev'\n try {\n const { createRequire } = await import('node:module')\n const require = createRequire(import.meta.url)\n const pkg = require('../package.json')\n console.log(`openacp v${pkg.version}`)\n } catch {\n console.log('openacp v0.0.0-dev')\n }\n return\n }\n\n if (command === 'install') {\n const pkg = args[1]\n if (!pkg) {\n console.error('Usage: openacp install <package>')\n process.exit(1)\n }\n installPlugin(pkg)\n return\n }\n\n if (command === 'uninstall') {\n const pkg = args[1]\n if (!pkg) {\n console.error('Usage: openacp uninstall <package>')\n process.exit(1)\n }\n uninstallPlugin(pkg)\n return\n }\n\n if (command === 'plugins') {\n const plugins = listPlugins()\n const entries = Object.entries(plugins)\n if (entries.length === 0) {\n console.log('No plugins installed.')\n } else {\n console.log('Installed plugins:')\n for (const [name, version] of entries) {\n console.log(` ${name}@${version}`)\n }\n }\n return\n }\n\n // Default: start server\n if (command && !command.startsWith('-')) {\n console.error(`Unknown command: ${command}`)\n printHelp()\n process.exit(1)\n }\n\n // Import and run server start\n const { startServer } = await import('./main.js')\n await startServer()\n}\n\nmain().catch((err) => {\n console.error('Fatal:', err)\n process.exit(1)\n})\n"],"mappings":";;;;;;;;;AAIA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,UAAU,KAAK,CAAC;AAEtB,SAAS,YAAkB;AACzB,UAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAkBb;AACD;AAEA,eAAe,OAAO;AACpB,MAAI,YAAY,YAAY,YAAY,MAAM;AAC5C,cAAU;AACV;AAAA,EACF;AAEA,MAAI,YAAY,eAAe,YAAY,MAAM;AAG/C,QAAI;AACF,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,QAAa;AACpD,YAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,YAAM,MAAMA,SAAQ,iBAAiB;AACrC,cAAQ,IAAI,YAAY,IAAI,OAAO,EAAE;AAAA,IACvC,QAAQ;AACN,cAAQ,IAAI,oBAAoB;AAAA,IAClC;AACA;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,kCAAkC;AAChD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,kBAAc,GAAG;AACjB;AAAA,EACF;AAEA,MAAI,YAAY,aAAa;AAC3B,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,CAAC,KAAK;AACR,cAAQ,MAAM,oCAAoC;AAClD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,oBAAgB,GAAG;AACnB;AAAA,EACF;AAEA,MAAI,YAAY,WAAW;AACzB,UAAM,UAAU,YAAY;AAC5B,UAAM,UAAU,OAAO,QAAQ,OAAO;AACtC,QAAI,QAAQ,WAAW,GAAG;AACxB,cAAQ,IAAI,uBAAuB;AAAA,IACrC,OAAO;AACL,cAAQ,IAAI,oBAAoB;AAChC,iBAAW,CAAC,MAAM,OAAO,KAAK,SAAS;AACrC,gBAAQ,IAAI,KAAK,IAAI,IAAI,OAAO,EAAE;AAAA,MACpC;AAAA,IACF;AACA;AAAA,EACF;AAGA,MAAI,WAAW,CAAC,QAAQ,WAAW,GAAG,GAAG;AACvC,YAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,cAAU;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB;AAGA,QAAM,EAAE,YAAY,IAAI,MAAM,OAAO,oBAAW;AAChD,QAAM,YAAY;AACpB;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM,UAAU,GAAG;AAC3B,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["require"]}