@specmarket/cli 0.0.4 → 0.0.5
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 +1 -1
- package/dist/{chunk-MS2DYACY.js → chunk-DLEMNRTH.js} +19 -2
- package/dist/chunk-DLEMNRTH.js.map +1 -0
- package/dist/{config-R5KWZSJP.js → config-OAU6SJLC.js} +2 -2
- package/dist/index.js +980 -181
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/comment.test.ts +211 -0
- package/src/commands/comment.ts +176 -0
- package/src/commands/fork.test.ts +163 -0
- package/src/commands/info.test.ts +192 -0
- package/src/commands/info.ts +66 -2
- package/src/commands/init.test.ts +106 -0
- package/src/commands/init.ts +12 -10
- package/src/commands/issues.test.ts +377 -0
- package/src/commands/issues.ts +443 -0
- package/src/commands/login.test.ts +99 -0
- package/src/commands/logout.test.ts +54 -0
- package/src/commands/publish.test.ts +146 -0
- package/src/commands/report.test.ts +181 -0
- package/src/commands/run.test.ts +213 -0
- package/src/commands/run.ts +10 -2
- package/src/commands/search.test.ts +147 -0
- package/src/commands/validate.test.ts +129 -2
- package/src/commands/validate.ts +333 -192
- package/src/commands/whoami.test.ts +106 -0
- package/src/index.ts +6 -0
- package/src/lib/convex-client.ts +6 -2
- package/src/lib/format-detection.test.ts +223 -0
- package/src/lib/format-detection.ts +172 -0
- package/src/lib/ralph-loop.ts +49 -20
- package/src/lib/telemetry.ts +2 -1
- package/dist/chunk-MS2DYACY.js.map +0 -1
- /package/dist/{config-R5KWZSJP.js.map → config-OAU6SJLC.js.map} +0 -0
package/src/lib/ralph-loop.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { mkdir, writeFile, readFile, access } from 'fs/promises';
|
|
|
3
3
|
import { join, resolve } from 'path';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
5
|
import { randomUUID } from 'crypto';
|
|
6
|
-
import {
|
|
6
|
+
import { exec } from 'child_process';
|
|
7
7
|
import { promisify } from 'util';
|
|
8
8
|
import type { RunReport, LoopIteration, SuccessCriterionResult } from '@specmarket/shared';
|
|
9
9
|
import {
|
|
@@ -17,6 +17,24 @@ import createDebug from 'debug';
|
|
|
17
17
|
const debug = createDebug('specmarket:runner');
|
|
18
18
|
const execAsync = promisify(exec);
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Pre-flight check: Verifies that Claude CLI is installed before attempting to run a spec.
|
|
22
|
+
* Throws an error with installation instructions if claude is not found.
|
|
23
|
+
*/
|
|
24
|
+
export async function checkClaudeCliInstalled(): Promise<void> {
|
|
25
|
+
try {
|
|
26
|
+
// Use 'which claude' to check if claude is in PATH
|
|
27
|
+
await execAsync('which claude');
|
|
28
|
+
} catch {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Claude CLI is not installed or not in your PATH.\n\n` +
|
|
31
|
+
`Installation instructions:\n` +
|
|
32
|
+
` npm install -g @anthropic-ai/claude-code\n\n` +
|
|
33
|
+
`Or visit: https://www.anthropic.com/claude-code\n`
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
20
38
|
export interface RunOptions {
|
|
21
39
|
maxLoops?: number;
|
|
22
40
|
maxBudgetUsd?: number;
|
|
@@ -39,10 +57,10 @@ export interface RunResult {
|
|
|
39
57
|
* 1. Creates a sandboxed working directory under ~/.specmarket/runs/<run-id>/
|
|
40
58
|
* 2. Copies spec files into the working directory
|
|
41
59
|
* 3. Initializes git for diff tracking
|
|
42
|
-
* 4. Executes: `cat PROMPT.md | claude
|
|
60
|
+
* 4. Executes: `cat PROMPT.md | claude --print` in a loop
|
|
43
61
|
* 5. After each loop: captures tokens, duration, git diff
|
|
44
62
|
* 6. Checks for completion conditions:
|
|
45
|
-
* - SUCCESS:
|
|
63
|
+
* - SUCCESS: TASKS.md empty + tests pass + all SUCCESS_CRITERIA.md criteria met
|
|
46
64
|
* - STALL: 3 consecutive loops with no git diff
|
|
47
65
|
* - FAILURE: 10 consecutive loops with same failing output
|
|
48
66
|
* - BUDGET: total tokens > 2x estimated_tokens
|
|
@@ -131,7 +149,7 @@ export async function runSpec(
|
|
|
131
149
|
|
|
132
150
|
const iterStart = Date.now();
|
|
133
151
|
|
|
134
|
-
// Execute: cat PROMPT.md | claude
|
|
152
|
+
// Execute: cat PROMPT.md | claude --print
|
|
135
153
|
const result = await executeClaudeLoop(runDir, opts.model);
|
|
136
154
|
|
|
137
155
|
const iterDuration = Date.now() - iterStart;
|
|
@@ -295,9 +313,9 @@ async function executeClaudeLoop(dir: string, model?: string): Promise<ExecuteRe
|
|
|
295
313
|
args.push('--model', model);
|
|
296
314
|
}
|
|
297
315
|
|
|
298
|
-
// Execute: cat PROMPT.md | claude
|
|
316
|
+
// Execute: cat PROMPT.md | claude --print --output-format json
|
|
299
317
|
// Using --output-format json gives us structured output with token usage metadata.
|
|
300
|
-
const proc = spawn('sh', ['-c', `cat PROMPT.md | claude
|
|
318
|
+
const proc = spawn('sh', ['-c', `cat PROMPT.md | claude ${args.join(' ')}`], {
|
|
301
319
|
cwd: dir,
|
|
302
320
|
stdio: ['inherit', 'pipe', 'pipe'],
|
|
303
321
|
});
|
|
@@ -318,7 +336,7 @@ async function executeClaudeLoop(dir: string, model?: string): Promise<ExecuteRe
|
|
|
318
336
|
});
|
|
319
337
|
|
|
320
338
|
proc.on('error', (err) => {
|
|
321
|
-
debug('claude
|
|
339
|
+
debug('claude spawn error: %O', err);
|
|
322
340
|
resolve({ stdout: '', exitCode: 1 });
|
|
323
341
|
});
|
|
324
342
|
});
|
|
@@ -328,7 +346,7 @@ async function executeClaudeLoop(dir: string, model?: string): Promise<ExecuteRe
|
|
|
328
346
|
* Extracts token count from Claude Code's output.
|
|
329
347
|
*
|
|
330
348
|
* Strategy (in priority order):
|
|
331
|
-
* 1. Parse JSON output format (claude
|
|
349
|
+
* 1. Parse JSON output format (claude --output-format json) which contains
|
|
332
350
|
* structured metadata including token counts in the response.
|
|
333
351
|
* 2. Match known text patterns from Claude Code's output (total_tokens, etc.)
|
|
334
352
|
* 3. Estimate from output length as a last-resort heuristic (~4 chars per token).
|
|
@@ -338,7 +356,7 @@ async function executeClaudeLoop(dir: string, model?: string): Promise<ExecuteRe
|
|
|
338
356
|
function parseTokensFromOutput(output: string): number {
|
|
339
357
|
if (!output || output.trim().length === 0) return 0;
|
|
340
358
|
|
|
341
|
-
// Strategy 1: Parse JSON output format from claude
|
|
359
|
+
// Strategy 1: Parse JSON output format from claude --output-format json
|
|
342
360
|
// Claude Code JSON output may contain token usage info in the response metadata.
|
|
343
361
|
try {
|
|
344
362
|
// The output might be a single JSON object or newline-delimited JSON
|
|
@@ -429,7 +447,7 @@ interface CompletionCheck {
|
|
|
429
447
|
}
|
|
430
448
|
|
|
431
449
|
async function checkCompletion(dir: string): Promise<CompletionCheck> {
|
|
432
|
-
// Check 1:
|
|
450
|
+
// Check 1: TASKS.md should be empty or have only checked items
|
|
433
451
|
const fixPlanEmpty = await isFixPlanEmpty(dir);
|
|
434
452
|
if (!fixPlanEmpty) {
|
|
435
453
|
return {
|
|
@@ -459,37 +477,48 @@ async function checkCompletion(dir: string): Promise<CompletionCheck> {
|
|
|
459
477
|
|
|
460
478
|
async function isFixPlanEmpty(dir: string): Promise<boolean> {
|
|
461
479
|
try {
|
|
462
|
-
const content = await readFile(join(dir, '
|
|
480
|
+
const content = await readFile(join(dir, 'TASKS.md'), 'utf-8');
|
|
463
481
|
// Consider empty if: no unchecked items (- [ ] lines)
|
|
464
482
|
const hasUncheckedItems = /^- \[ \]/m.test(content);
|
|
465
483
|
return !hasUncheckedItems;
|
|
466
484
|
} catch {
|
|
467
|
-
// No
|
|
485
|
+
// No TASKS.md = considered empty
|
|
468
486
|
return true;
|
|
469
487
|
}
|
|
470
488
|
}
|
|
471
489
|
|
|
472
490
|
async function runTests(dir: string): Promise<boolean> {
|
|
473
|
-
// Try to detect and run tests
|
|
491
|
+
// Try to detect and run tests using known test runner config files.
|
|
492
|
+
// Exit code is the primary failure signal; output regex is a fallback.
|
|
474
493
|
const testRunners = [
|
|
475
|
-
{ file: 'package.json', cmd: 'npm test -- --run 2>&1
|
|
476
|
-
{ file: 'vitest.config.ts', cmd: 'npx vitest run 2>&1
|
|
477
|
-
{ file: 'pytest.ini', cmd: 'python -m pytest --tb=no -q 2>&1
|
|
478
|
-
{ file: 'Makefile', cmd: 'make test 2>&1
|
|
494
|
+
{ file: 'package.json', cmd: 'npm test -- --run 2>&1' },
|
|
495
|
+
{ file: 'vitest.config.ts', cmd: 'npx vitest run 2>&1' },
|
|
496
|
+
{ file: 'pytest.ini', cmd: 'python -m pytest --tb=no -q 2>&1' },
|
|
497
|
+
{ file: 'Makefile', cmd: 'make test 2>&1' },
|
|
479
498
|
];
|
|
480
499
|
|
|
481
500
|
for (const runner of testRunners) {
|
|
482
501
|
try {
|
|
483
502
|
await access(join(dir, runner.file));
|
|
503
|
+
} catch {
|
|
504
|
+
continue; // Config file doesn't exist — try next runner
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
try {
|
|
484
508
|
const { stdout, stderr } = await execAsync(runner.cmd, {
|
|
485
509
|
cwd: dir,
|
|
486
510
|
timeout: 120000,
|
|
487
511
|
});
|
|
512
|
+
// Exit code 0 — check output as secondary signal
|
|
488
513
|
const combined = stdout + stderr;
|
|
489
|
-
|
|
490
|
-
const hasFailed = /\d+ failed|\d+ error|FAILED|ERROR/i.test(combined);
|
|
514
|
+
const hasFailed = /\d+ failed|\d+ error/i.test(combined);
|
|
491
515
|
return !hasFailed;
|
|
492
|
-
} catch {
|
|
516
|
+
} catch (err: unknown) {
|
|
517
|
+
// Non-zero exit code means tests failed
|
|
518
|
+
if (err && typeof err === 'object' && 'code' in err && typeof err.code === 'number') {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
// Timeout or other execution error — skip to next runner
|
|
493
522
|
continue;
|
|
494
523
|
}
|
|
495
524
|
}
|
package/src/lib/telemetry.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RunReport } from '@specmarket/shared';
|
|
2
|
+
import type { Id } from '@specmarket/convex/dataModel';
|
|
2
3
|
import { loadCredentials } from './auth.js';
|
|
3
4
|
import { loadConfig } from './config.js';
|
|
4
5
|
import { getConvexClient } from './convex-client.js';
|
|
@@ -52,7 +53,7 @@ export async function submitTelemetry(
|
|
|
52
53
|
const client = await getConvexClient(creds.token);
|
|
53
54
|
|
|
54
55
|
await client.mutation(api.runs.submit, {
|
|
55
|
-
specId: report.specId as
|
|
56
|
+
specId: report.specId as Id<'specs'>,
|
|
56
57
|
specVersion: report.specVersion,
|
|
57
58
|
model: report.model,
|
|
58
59
|
runner: report.runner,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/config.ts","../../shared/src/validators.ts","../../shared/src/constants.ts"],"sourcesContent":["import { readFile, writeFile, mkdir } from 'fs/promises';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport type { CliConfig } from '@specmarket/shared';\nimport { CONFIG_PATHS } from '@specmarket/shared';\nimport createDebug from 'debug';\n\nconst debug = createDebug('specmarket:cli');\n\nfunction getConfigDir(): string {\n return join(homedir(), CONFIG_PATHS.DIR);\n}\n\nfunction getConfigPath(): string {\n return join(homedir(), CONFIG_PATHS.CONFIG);\n}\n\n/**\n * Ensures the ~/.specmarket directory exists.\n */\nasync function ensureConfigDir(): Promise<void> {\n await mkdir(getConfigDir(), { recursive: true });\n}\n\n/**\n * Loads CLI configuration from ~/.specmarket/config.json.\n * Returns default config if the file doesn't exist.\n */\nexport async function loadConfig(): Promise<CliConfig> {\n try {\n const raw = await readFile(getConfigPath(), 'utf-8');\n return JSON.parse(raw) as CliConfig;\n } catch {\n debug('No config file found, using defaults');\n return {};\n }\n}\n\n/**\n * Saves CLI configuration to ~/.specmarket/config.json.\n */\nexport async function saveConfig(config: CliConfig): Promise<void> {\n await ensureConfigDir();\n await writeFile(getConfigPath(), JSON.stringify(config, null, 2), 'utf-8');\n debug('Config saved to %s', getConfigPath());\n}\n\n/**\n * Gets a specific config value by key.\n */\nexport async function getConfigValue<K extends keyof CliConfig>(\n key: K\n): Promise<CliConfig[K]> {\n const config = await loadConfig();\n return config[key];\n}\n\n/**\n * Sets a specific config value and persists.\n */\nexport async function setConfigValue<K extends keyof CliConfig>(\n key: K,\n value: CliConfig[K]\n): Promise<void> {\n const config = await loadConfig();\n config[key] = value;\n await saveConfig(config);\n}\n","import { z } from 'zod';\n\nexport const outputTypeSchema = z.enum([\n 'web-app',\n 'cli-tool',\n 'api-service',\n 'library',\n 'mobile-app',\n]);\n\nexport const primaryStackSchema = z.enum([\n 'nextjs-typescript',\n 'astro-typescript',\n 'python-fastapi',\n 'go',\n 'rust',\n 'other',\n]);\n\nexport const serviceCategorySchema = z.enum([\n 'database',\n 'auth',\n 'storage',\n 'cdn',\n 'dns',\n 'email',\n 'sms',\n 'payments',\n 'search',\n 'analytics',\n 'monitoring',\n 'queue',\n 'cache',\n 'compute',\n 'pdf',\n 'ai',\n 'other',\n]);\n\n/** Provider schema (camelCase) — for Convex DB */\nexport const providerSchema = z.object({\n name: z.string().min(1),\n freeTier: z.boolean(),\n paidStartsUsd: z.number().min(0).optional(),\n notes: z.string().optional(),\n});\n\n/** Provider schema (snake_case) — for spec.yaml parsing */\nexport const providerSchemaYaml = z.object({\n name: z.string().min(1),\n free_tier: z.boolean(),\n paid_starts_usd: z.number().min(0).optional(),\n notes: z.string().optional(),\n});\n\n// snake_case for spec.yaml parsing\nexport const serviceSchemaYaml = z.object({\n category: serviceCategorySchema,\n name: z.string().min(1),\n purpose: z.string().min(1),\n required: z.boolean(),\n user_provided: z.boolean().optional(),\n providers: z.array(providerSchemaYaml).min(1),\n default_provider: z.string().optional(),\n setup_notes: z.string().optional(),\n});\n\n// camelCase for Convex DB\nexport const serviceSchema = z.object({\n category: serviceCategorySchema,\n name: z.string().min(1),\n purpose: z.string().min(1),\n required: z.boolean(),\n userProvided: z.boolean().optional(),\n providers: z.array(providerSchema).min(1),\n defaultProvider: z.string().optional(),\n setupNotes: z.string().optional(),\n});\n\n// snake_case for spec.yaml parsing\nexport const infrastructureSchemaYaml = z.object({\n monthly_cost: z.object({\n free_tier_usd: z.number().min(0),\n production_usd: z.number().min(0),\n }),\n services: z.array(serviceSchemaYaml).default([]),\n user_provided: z.array(z.string()).default([]),\n setup_time_minutes: z.number().min(0).optional(),\n deployment_targets: z\n .array(\n z.object({\n name: z.string().min(1),\n notes: z.string().optional(),\n })\n )\n .optional(),\n});\n\n// camelCase for Convex DB\nexport const infrastructureSchema = z.object({\n monthlyCost: z.object({\n freeTierUsd: z.number().min(0),\n productionUsd: z.number().min(0),\n }),\n services: z.array(serviceSchema).default([]),\n userProvided: z.array(z.string()).default([]),\n setupTimeMinutes: z.number().min(0).optional(),\n deploymentTargets: z\n .array(\n z.object({\n name: z.string().min(1),\n notes: z.string().optional(),\n })\n )\n .optional(),\n});\n\n// Full spec.yaml schema (snake_case as written by users)\nexport const specYamlSchema = z.object({\n name: z\n .string()\n .min(1)\n .regex(/^[a-z0-9-]+$/, 'name must be lowercase alphanumeric with hyphens'),\n display_name: z.string().min(1),\n description: z.string().min(10),\n replaces_saas: z.string().optional(),\n replaces_pricing: z.string().optional(),\n output_type: outputTypeSchema,\n primary_stack: primaryStackSchema,\n version: z\n .string()\n .regex(\n /^\\d+\\.\\d+\\.\\d+$/,\n 'version must be semver (e.g. 1.0.0)'\n ),\n runner: z.literal('claude-code'),\n min_model: z.string().min(1),\n estimated_tokens: z.number().int().positive(),\n estimated_cost_usd: z.number().positive(),\n estimated_time_minutes: z.number().positive(),\n tags: z.array(z.string()).default([]),\n infrastructure: infrastructureSchemaYaml.optional(),\n // Fork metadata (added by CLI when forking)\n forked_from_id: z.string().optional(),\n forked_from_version: z.string().optional(),\n});\n\nexport const runStatusSchema = z.enum([\n 'success',\n 'failure',\n 'stall',\n 'budget_exceeded',\n 'user_cancelled',\n]);\n\nexport const specStatusSchema = z.enum([\n 'published',\n 'draft',\n 'flagged',\n 'removed',\n]);\n\nexport const userRoleSchema = z.enum(['user', 'creator', 'admin']);\n\nexport const bountyFundingTypeSchema = z.enum([\n 'company',\n 'crowdfund',\n 'mixed',\n]);\n\nexport const bountyStatusSchema = z.enum([\n 'open',\n 'claimed',\n 'awarded',\n 'expired',\n 'cancelled',\n]);\n\nexport const bountySubmissionStatusSchema = z.enum([\n 'submitted',\n 'accepted',\n 'rejected',\n]);\n\nexport const successCriterionResultSchema = z.object({\n criterion: z.string().min(1),\n passed: z.boolean(),\n details: z.string().optional(),\n});\n\n/** Transform spec.yaml (snake_case infra) to Convex-friendly camelCase */\nexport function transformInfrastructure(\n yaml: z.infer<typeof infrastructureSchemaYaml>\n): z.infer<typeof infrastructureSchema> {\n return {\n monthlyCost: {\n freeTierUsd: yaml.monthly_cost.free_tier_usd,\n productionUsd: yaml.monthly_cost.production_usd,\n },\n services: yaml.services.map((s) => ({\n category: s.category,\n name: s.name,\n purpose: s.purpose,\n required: s.required,\n userProvided: s.user_provided,\n providers: s.providers.map((p) => ({\n name: p.name,\n freeTier: p.free_tier,\n paidStartsUsd: p.paid_starts_usd,\n notes: p.notes,\n })),\n defaultProvider: s.default_provider,\n setupNotes: s.setup_notes,\n })),\n userProvided: yaml.user_provided,\n setupTimeMinutes: yaml.setup_time_minutes,\n deploymentTargets: yaml.deployment_targets,\n };\n}\n","/** CLI exit codes */\nexport const EXIT_CODES = {\n /** Success */\n SUCCESS: 0,\n /** Validation error (bad spec, invalid args) */\n VALIDATION_ERROR: 1,\n /** Runtime error (loop failed, crash) */\n RUNTIME_ERROR: 2,\n /** Budget exceeded */\n BUDGET_EXCEEDED: 3,\n /** Network error (Convex unreachable, upload failed) */\n NETWORK_ERROR: 4,\n /** Auth error (not logged in, token expired) */\n AUTH_ERROR: 5,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n\n/** Default file paths (relative to $HOME) */\nexport const CONFIG_PATHS = {\n /** Directory for all SpecMarket CLI state */\n DIR: '.specmarket',\n /** Auth credentials file */\n CREDENTIALS: '.specmarket/credentials.json',\n /** CLI config file */\n CONFIG: '.specmarket/config.json',\n /** Run artifacts directory */\n RUNS_DIR: '.specmarket/runs',\n} as const;\n\n/** Default run behavior */\nexport const RUN_DEFAULTS = {\n /** Maximum loop iterations before forced stop */\n MAX_LOOPS: 50,\n /** Budget multiplier: stop if cost > estimated * this */\n BUDGET_MULTIPLIER: 2,\n /** Loops with no git diff before declaring stall */\n STALL_THRESHOLD: 3,\n /** Loops with the same failing test before declaring failure */\n FAILURE_THRESHOLD: 10,\n} as const;\n\n/** Rate limits (client-side awareness, enforced server-side too) */\nexport const RATE_LIMITS = {\n /** Max telemetry submissions per hour */\n RUNS_PER_HOUR: 10,\n /** Max spec publishes per day */\n PUBLISHES_PER_DAY: 5,\n /** Max ratings per day */\n RATINGS_PER_DAY: 20,\n} as const;\n\n/** Credential expiry */\nexport const TOKEN_EXPIRY_MS = 30 * 24 * 60 * 60 * 1000; // 30 days\n\n/** Runner identifier */\nexport const RUNNER_ID = 'claude-code' as const;\n\n/** Default Convex deployment URL (overridable via config or env) */\nexport const DEFAULT_CONVEX_URL =\n process.env['CONVEX_URL'] ?? 'https://clever-bird-665.convex.cloud';\n\n/** Required files in a valid spec directory */\nexport const REQUIRED_SPEC_FILES = [\n 'spec.yaml',\n 'PROMPT.md',\n 'SPEC.md',\n 'SUCCESS_CRITERIA.md',\n] as const;\n\n/** Required files in stdlib/ directory */\nexport const REQUIRED_STDLIB_FILES = ['STACK.md'] as const;\n\n/** Debug log namespaces */\nexport const DEBUG_NAMESPACES = {\n CLI: 'specmarket:cli',\n CONVEX: 'specmarket:convex',\n RUNNER: 'specmarket:runner',\n AUTH: 'specmarket:auth',\n TELEMETRY: 'specmarket:telemetry',\n} as const;\n"],"mappings":";;;AAAA,SAAS,UAAU,WAAW,aAAa;AAC3C,SAAS,YAAY;AACrB,SAAS,eAAe;;;ACFxB,SAAS,SAAS;AAEX,IAAM,mBAAmB,EAAE,KAAK;EACrC;EACA;EACA;EACA;EACA;CACD;AAEM,IAAM,qBAAqB,EAAE,KAAK;EACvC;EACA;EACA;EACA;EACA;EACA;CACD;AAEM,IAAM,wBAAwB,EAAE,KAAK;EAC1C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACD;AAGM,IAAM,iBAAiB,EAAE,OAAO;EACrC,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;EACtB,UAAU,EAAE,QAAO;EACnB,eAAe,EAAE,OAAM,EAAG,IAAI,CAAC,EAAE,SAAQ;EACzC,OAAO,EAAE,OAAM,EAAG,SAAQ;CAC3B;AAGM,IAAM,qBAAqB,EAAE,OAAO;EACzC,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;EACtB,WAAW,EAAE,QAAO;EACpB,iBAAiB,EAAE,OAAM,EAAG,IAAI,CAAC,EAAE,SAAQ;EAC3C,OAAO,EAAE,OAAM,EAAG,SAAQ;CAC3B;AAGM,IAAM,oBAAoB,EAAE,OAAO;EACxC,UAAU;EACV,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;EACtB,SAAS,EAAE,OAAM,EAAG,IAAI,CAAC;EACzB,UAAU,EAAE,QAAO;EACnB,eAAe,EAAE,QAAO,EAAG,SAAQ;EACnC,WAAW,EAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC;EAC5C,kBAAkB,EAAE,OAAM,EAAG,SAAQ;EACrC,aAAa,EAAE,OAAM,EAAG,SAAQ;CACjC;AAGM,IAAM,gBAAgB,EAAE,OAAO;EACpC,UAAU;EACV,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;EACtB,SAAS,EAAE,OAAM,EAAG,IAAI,CAAC;EACzB,UAAU,EAAE,QAAO;EACnB,cAAc,EAAE,QAAO,EAAG,SAAQ;EAClC,WAAW,EAAE,MAAM,cAAc,EAAE,IAAI,CAAC;EACxC,iBAAiB,EAAE,OAAM,EAAG,SAAQ;EACpC,YAAY,EAAE,OAAM,EAAG,SAAQ;CAChC;AAGM,IAAM,2BAA2B,EAAE,OAAO;EAC/C,cAAc,EAAE,OAAO;IACrB,eAAe,EAAE,OAAM,EAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,OAAM,EAAG,IAAI,CAAC;GACjC;EACD,UAAU,EAAE,MAAM,iBAAiB,EAAE,QAAQ,CAAA,CAAE;EAC/C,eAAe,EAAE,MAAM,EAAE,OAAM,CAAE,EAAE,QAAQ,CAAA,CAAE;EAC7C,oBAAoB,EAAE,OAAM,EAAG,IAAI,CAAC,EAAE,SAAQ;EAC9C,oBAAoB,EACjB,MACC,EAAE,OAAO;IACP,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAM,EAAG,SAAQ;GAC3B,CAAC,EAEH,SAAQ;CACZ;AAGM,IAAM,uBAAuB,EAAE,OAAO;EAC3C,aAAa,EAAE,OAAO;IACpB,aAAa,EAAE,OAAM,EAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAM,EAAG,IAAI,CAAC;GAChC;EACD,UAAU,EAAE,MAAM,aAAa,EAAE,QAAQ,CAAA,CAAE;EAC3C,cAAc,EAAE,MAAM,EAAE,OAAM,CAAE,EAAE,QAAQ,CAAA,CAAE;EAC5C,kBAAkB,EAAE,OAAM,EAAG,IAAI,CAAC,EAAE,SAAQ;EAC5C,mBAAmB,EAChB,MACC,EAAE,OAAO;IACP,MAAM,EAAE,OAAM,EAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAM,EAAG,SAAQ;GAC3B,CAAC,EAEH,SAAQ;CACZ;AAGM,IAAM,iBAAiB,EAAE,OAAO;EACrC,MAAM,EACH,OAAM,EACN,IAAI,CAAC,EACL,MAAM,gBAAgB,kDAAkD;EAC3E,cAAc,EAAE,OAAM,EAAG,IAAI,CAAC;EAC9B,aAAa,EAAE,OAAM,EAAG,IAAI,EAAE;EAC9B,eAAe,EAAE,OAAM,EAAG,SAAQ;EAClC,kBAAkB,EAAE,OAAM,EAAG,SAAQ;EACrC,aAAa;EACb,eAAe;EACf,SAAS,EACN,OAAM,EACN,MACC,mBACA,qCAAqC;EAEzC,QAAQ,EAAE,QAAQ,aAAa;EAC/B,WAAW,EAAE,OAAM,EAAG,IAAI,CAAC;EAC3B,kBAAkB,EAAE,OAAM,EAAG,IAAG,EAAG,SAAQ;EAC3C,oBAAoB,EAAE,OAAM,EAAG,SAAQ;EACvC,wBAAwB,EAAE,OAAM,EAAG,SAAQ;EAC3C,MAAM,EAAE,MAAM,EAAE,OAAM,CAAE,EAAE,QAAQ,CAAA,CAAE;EACpC,gBAAgB,yBAAyB,SAAQ;;EAEjD,gBAAgB,EAAE,OAAM,EAAG,SAAQ;EACnC,qBAAqB,EAAE,OAAM,EAAG,SAAQ;CACzC;AAEM,IAAM,kBAAkB,EAAE,KAAK;EACpC;EACA;EACA;EACA;EACA;CACD;AAEM,IAAM,mBAAmB,EAAE,KAAK;EACrC;EACA;EACA;EACA;CACD;AAEM,IAAM,iBAAiB,EAAE,KAAK,CAAC,QAAQ,WAAW,OAAO,CAAC;AAE1D,IAAM,0BAA0B,EAAE,KAAK;EAC5C;EACA;EACA;CACD;AAEM,IAAM,qBAAqB,EAAE,KAAK;EACvC;EACA;EACA;EACA;EACA;CACD;AAEM,IAAM,+BAA+B,EAAE,KAAK;EACjD;EACA;EACA;CACD;AAEM,IAAM,+BAA+B,EAAE,OAAO;EACnD,WAAW,EAAE,OAAM,EAAG,IAAI,CAAC;EAC3B,QAAQ,EAAE,QAAO;EACjB,SAAS,EAAE,OAAM,EAAG,SAAQ;CAC7B;AAGK,SAAU,wBACd,MAA8C;AAE9C,SAAO;IACL,aAAa;MACX,aAAa,KAAK,aAAa;MAC/B,eAAe,KAAK,aAAa;;IAEnC,UAAU,KAAK,SAAS,IAAI,CAAC,OAAO;MAClC,UAAU,EAAE;MACZ,MAAM,EAAE;MACR,SAAS,EAAE;MACX,UAAU,EAAE;MACZ,cAAc,EAAE;MAChB,WAAW,EAAE,UAAU,IAAI,CAAC,OAAO;QACjC,MAAM,EAAE;QACR,UAAU,EAAE;QACZ,eAAe,EAAE;QACjB,OAAO,EAAE;QACT;MACF,iBAAiB,EAAE;MACnB,YAAY,EAAE;MACd;IACF,cAAc,KAAK;IACnB,kBAAkB,KAAK;IACvB,mBAAmB,KAAK;;AAE5B;;;ACzNO,IAAM,aAAa;;EAExB,SAAS;;EAET,kBAAkB;;EAElB,eAAe;;EAEf,iBAAiB;;EAEjB,eAAe;;EAEf,YAAY;;AAMP,IAAM,eAAe;;EAE1B,KAAK;;EAEL,aAAa;;EAEb,QAAQ;;EAER,UAAU;;AAIL,IAAM,eAAe;;EAE1B,WAAW;;EAEX,mBAAmB;;EAEnB,iBAAiB;;EAEjB,mBAAmB;;AAcd,IAAM,kBAAkB,KAAK,KAAK,KAAK,KAAK;AAM5C,IAAM,qBACX,QAAQ,IAAI,YAAY,KAAK;AAGxB,IAAM,sBAAsB;EACjC;EACA;EACA;EACA;;AAIK,IAAM,wBAAwB,CAAC,UAAU;;;AFlEhD,OAAO,iBAAiB;AAExB,IAAM,QAAQ,YAAY,gBAAgB;AAE1C,SAAS,eAAuB;AAC9B,SAAO,KAAK,QAAQ,GAAG,aAAa,GAAG;AACzC;AAEA,SAAS,gBAAwB;AAC/B,SAAO,KAAK,QAAQ,GAAG,aAAa,MAAM;AAC5C;AAKA,eAAe,kBAAiC;AAC9C,QAAM,MAAM,aAAa,GAAG,EAAE,WAAW,KAAK,CAAC;AACjD;AAMA,eAAsB,aAAiC;AACrD,MAAI;AACF,UAAM,MAAM,MAAM,SAAS,cAAc,GAAG,OAAO;AACnD,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,UAAM,sCAAsC;AAC5C,WAAO,CAAC;AAAA,EACV;AACF;AAKA,eAAsB,WAAW,QAAkC;AACjE,QAAM,gBAAgB;AACtB,QAAM,UAAU,cAAc,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,GAAG,OAAO;AACzE,QAAM,sBAAsB,cAAc,CAAC;AAC7C;AAKA,eAAsB,eACpB,KACuB;AACvB,QAAM,SAAS,MAAM,WAAW;AAChC,SAAO,OAAO,GAAG;AACnB;AAKA,eAAsB,eACpB,KACA,OACe;AACf,QAAM,SAAS,MAAM,WAAW;AAChC,SAAO,GAAG,IAAI;AACd,QAAM,WAAW,MAAM;AACzB;","names":[]}
|
|
File without changes
|