claude-devloop 1.0.0
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 +340 -0
- package/dist/cli.d.ts +4 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +90 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +9 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +80 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/continue.d.ts +11 -0
- package/dist/commands/continue.d.ts.map +1 -0
- package/dist/commands/continue.js +167 -0
- package/dist/commands/continue.js.map +1 -0
- package/dist/commands/feature.d.ts +7 -0
- package/dist/commands/feature.d.ts.map +1 -0
- package/dist/commands/feature.js +123 -0
- package/dist/commands/feature.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +401 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/run.d.ts +12 -0
- package/dist/commands/run.d.ts.map +1 -0
- package/dist/commands/run.js +82 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/shared.d.ts +22 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +32 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +305 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/workspace.d.ts +2 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +19 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/constants.d.ts +21 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +21 -0
- package/dist/constants.js.map +1 -0
- package/dist/core/claude.d.ts +20 -0
- package/dist/core/claude.d.ts.map +1 -0
- package/dist/core/claude.js +401 -0
- package/dist/core/claude.js.map +1 -0
- package/dist/core/commit-format.d.ts +22 -0
- package/dist/core/commit-format.d.ts.map +1 -0
- package/dist/core/commit-format.js +148 -0
- package/dist/core/commit-format.js.map +1 -0
- package/dist/core/config.d.ts +30 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +130 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/feature-session.d.ts +8 -0
- package/dist/core/feature-session.d.ts.map +1 -0
- package/dist/core/feature-session.js +58 -0
- package/dist/core/feature-session.js.map +1 -0
- package/dist/core/git.d.ts +81 -0
- package/dist/core/git.d.ts.map +1 -0
- package/dist/core/git.js +475 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/loop.d.ts +3 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +469 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/session.d.ts +7 -0
- package/dist/core/session.d.ts.map +1 -0
- package/dist/core/session.js +57 -0
- package/dist/core/session.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/progress.d.ts +7 -0
- package/dist/parser/progress.d.ts.map +1 -0
- package/dist/parser/progress.js +132 -0
- package/dist/parser/progress.js.map +1 -0
- package/dist/parser/requirements.d.ts +6 -0
- package/dist/parser/requirements.d.ts.map +1 -0
- package/dist/parser/requirements.js +126 -0
- package/dist/parser/requirements.js.map +1 -0
- package/dist/types/feature.d.ts +15 -0
- package/dist/types/feature.d.ts.map +1 -0
- package/dist/types/feature.js +2 -0
- package/dist/types/feature.js.map +1 -0
- package/dist/types/index.d.ts +78 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
const CONFIG_DIR = path.join(os.homedir(), '.devloop');
|
|
5
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
6
|
+
const DEFAULT_CONFIG = {
|
|
7
|
+
defaultWorkspace: null,
|
|
8
|
+
maxIterations: 10
|
|
9
|
+
};
|
|
10
|
+
export async function ensureConfigDir() {
|
|
11
|
+
try {
|
|
12
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// Directory already exists
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export async function readGlobalConfig() {
|
|
19
|
+
try {
|
|
20
|
+
const content = await fs.readFile(CONFIG_FILE, 'utf-8');
|
|
21
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(content) };
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return DEFAULT_CONFIG;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export async function writeGlobalConfig(config) {
|
|
28
|
+
await ensureConfigDir();
|
|
29
|
+
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
30
|
+
}
|
|
31
|
+
export async function getDefaultWorkspace() {
|
|
32
|
+
const config = await readGlobalConfig();
|
|
33
|
+
return config.defaultWorkspace;
|
|
34
|
+
}
|
|
35
|
+
export async function setDefaultWorkspace(workspacePath) {
|
|
36
|
+
const config = await readGlobalConfig();
|
|
37
|
+
config.defaultWorkspace = path.resolve(workspacePath);
|
|
38
|
+
await writeGlobalConfig(config);
|
|
39
|
+
}
|
|
40
|
+
export async function resolveWorkspace(cliWorkspace) {
|
|
41
|
+
// Priority: CLI flag > config default > current directory
|
|
42
|
+
if (cliWorkspace) {
|
|
43
|
+
return path.resolve(cliWorkspace);
|
|
44
|
+
}
|
|
45
|
+
const defaultWorkspace = await getDefaultWorkspace();
|
|
46
|
+
if (defaultWorkspace) {
|
|
47
|
+
return defaultWorkspace;
|
|
48
|
+
}
|
|
49
|
+
return process.cwd();
|
|
50
|
+
}
|
|
51
|
+
export function getRequirementsPath(workspace) {
|
|
52
|
+
return path.join(workspace, 'requirements.md');
|
|
53
|
+
}
|
|
54
|
+
export function getProgressPath(workspace) {
|
|
55
|
+
return path.join(workspace, 'progress.md');
|
|
56
|
+
}
|
|
57
|
+
export function getSessionPath(workspace) {
|
|
58
|
+
return path.join(workspace, '.devloop', 'session.json');
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Validates a feature name to ensure it's a safe filename
|
|
62
|
+
* @throws Error if feature name is invalid
|
|
63
|
+
*/
|
|
64
|
+
export function validateFeatureName(feature) {
|
|
65
|
+
// Must be alphanumeric with hyphens or underscores
|
|
66
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(feature)) {
|
|
67
|
+
throw new Error(`Invalid feature name: "${feature}"\n` +
|
|
68
|
+
'Feature names must be alphanumeric with hyphens or underscores only.\n' +
|
|
69
|
+
'Example: my-feature or my_feature');
|
|
70
|
+
}
|
|
71
|
+
// Prevent path traversal
|
|
72
|
+
if (feature.includes('..') || feature.includes('/') || feature.includes('\\')) {
|
|
73
|
+
throw new Error(`Invalid feature name: "${feature}" (path traversal not allowed)`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Resolves feature input to normalized paths
|
|
78
|
+
* Handles both short form (auth) and explicit paths (requirements/auth.md)
|
|
79
|
+
*/
|
|
80
|
+
export function resolveFeaturePath(workspace, featureInput) {
|
|
81
|
+
let featureName;
|
|
82
|
+
// Handle explicit path format (requirements/auth.md)
|
|
83
|
+
if (featureInput.includes('/') || featureInput.includes('\\')) {
|
|
84
|
+
const normalized = featureInput.replace(/\\/g, '/');
|
|
85
|
+
const match = normalized.match(/^requirements\/([^/]+)\.md$/);
|
|
86
|
+
if (!match) {
|
|
87
|
+
throw new Error(`Invalid feature path: "${featureInput}"\n` +
|
|
88
|
+
'Feature paths must be in format: requirements/<name>.md\n' +
|
|
89
|
+
'Or use short form: <name>');
|
|
90
|
+
}
|
|
91
|
+
featureName = match[1];
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Remove .md extension if provided
|
|
95
|
+
featureName = featureInput.replace(/\.md$/, '');
|
|
96
|
+
}
|
|
97
|
+
validateFeatureName(featureName);
|
|
98
|
+
return {
|
|
99
|
+
featureName,
|
|
100
|
+
requirementsPath: getFeatureRequirementsPath(workspace, featureName),
|
|
101
|
+
progressPath: getFeatureProgressPath(workspace, featureName)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export function getFeatureRequirementsPath(workspace, feature) {
|
|
105
|
+
return path.join(workspace, 'requirements', `${feature}.md`);
|
|
106
|
+
}
|
|
107
|
+
export function getFeatureProgressPath(workspace, feature) {
|
|
108
|
+
return path.join(workspace, 'progress', `${feature}.md`);
|
|
109
|
+
}
|
|
110
|
+
export function getWorkspaceConfigPath(workspace) {
|
|
111
|
+
return path.join(workspace, '.devloop', 'config.json');
|
|
112
|
+
}
|
|
113
|
+
export async function readWorkspaceConfig(workspace) {
|
|
114
|
+
try {
|
|
115
|
+
const configPath = getWorkspaceConfigPath(workspace);
|
|
116
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
117
|
+
return JSON.parse(content);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export async function writeWorkspaceConfig(workspace, config) {
|
|
124
|
+
const configPath = getWorkspaceConfigPath(workspace);
|
|
125
|
+
const devloopDir = path.dirname(configPath);
|
|
126
|
+
// Ensure .devloop directory exists
|
|
127
|
+
await fs.mkdir(devloopDir, { recursive: true });
|
|
128
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FeatureSession } from '../types/feature.js';
|
|
2
|
+
import { SessionPhase } from '../types/index.js';
|
|
3
|
+
export declare function readFeatureSession(workspace: string, feature: string): Promise<FeatureSession | null>;
|
|
4
|
+
export declare function writeFeatureSession(workspace: string, session: FeatureSession): Promise<void>;
|
|
5
|
+
export declare function createFeatureSession(workspace: string, feature: string, phase: SessionPhase): Promise<FeatureSession>;
|
|
6
|
+
export declare function updateFeatureSessionIteration(workspace: string, feature: string, iteration: number): Promise<void>;
|
|
7
|
+
export declare function listFeatures(workspace: string): Promise<string[]>;
|
|
8
|
+
//# sourceMappingURL=feature-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-session.d.ts","sourceRoot":"","sources":["../../src/core/feature-session.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOjD,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAQ3G;AAED,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAQnG;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,cAAc,CAAC,CAazB;AAED,wBAAsB,6BAA6B,CACjD,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYvE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { getFeatureRequirementsPath, getFeatureProgressPath } from './config.js';
|
|
4
|
+
function getFeatureSessionPath(workspace, feature) {
|
|
5
|
+
return path.join(workspace, '.devloop', 'features', `${feature}.json`);
|
|
6
|
+
}
|
|
7
|
+
export async function readFeatureSession(workspace, feature) {
|
|
8
|
+
try {
|
|
9
|
+
const sessionPath = getFeatureSessionPath(workspace, feature);
|
|
10
|
+
const content = await fs.readFile(sessionPath, 'utf-8');
|
|
11
|
+
return JSON.parse(content);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export async function writeFeatureSession(workspace, session) {
|
|
18
|
+
const sessionPath = getFeatureSessionPath(workspace, session.feature);
|
|
19
|
+
const sessionDir = path.dirname(sessionPath);
|
|
20
|
+
// Ensure .devloop/features directory exists
|
|
21
|
+
await fs.mkdir(sessionDir, { recursive: true });
|
|
22
|
+
await fs.writeFile(sessionPath, JSON.stringify(session, null, 2), 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
export async function createFeatureSession(workspace, feature, phase) {
|
|
25
|
+
const session = {
|
|
26
|
+
feature,
|
|
27
|
+
phase,
|
|
28
|
+
sessionId: null,
|
|
29
|
+
lastIteration: 0,
|
|
30
|
+
startedAt: new Date().toISOString(),
|
|
31
|
+
requirementsPath: getFeatureRequirementsPath(workspace, feature),
|
|
32
|
+
progressPath: getFeatureProgressPath(workspace, feature)
|
|
33
|
+
};
|
|
34
|
+
await writeFeatureSession(workspace, session);
|
|
35
|
+
return session;
|
|
36
|
+
}
|
|
37
|
+
export async function updateFeatureSessionIteration(workspace, feature, iteration) {
|
|
38
|
+
const session = await readFeatureSession(workspace, feature);
|
|
39
|
+
if (!session) {
|
|
40
|
+
throw new Error(`Feature session not found: ${feature}`);
|
|
41
|
+
}
|
|
42
|
+
session.lastIteration = iteration;
|
|
43
|
+
await writeFeatureSession(workspace, session);
|
|
44
|
+
}
|
|
45
|
+
export async function listFeatures(workspace) {
|
|
46
|
+
const requirementsDir = path.join(workspace, 'requirements');
|
|
47
|
+
try {
|
|
48
|
+
const files = await fs.readdir(requirementsDir);
|
|
49
|
+
return files
|
|
50
|
+
.filter(file => file.endsWith('.md'))
|
|
51
|
+
.map(file => file.replace(/\.md$/, ''))
|
|
52
|
+
.sort();
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=feature-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-session.js","sourceRoot":"","sources":["../../src/core/feature-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a DevLoop internal commit message using the configured format
|
|
3
|
+
* @param action - What DevLoop is doing (e.g., "Initialize workspace", "Start run")
|
|
4
|
+
*/
|
|
5
|
+
export declare function formatDevloopCommit(format: string | undefined, action: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Get the DevLoop commit message for an action, using workspace config if available
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDevloopCommitMessage(workspace: string, action: string): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Save a DevLoop commit format to workspace config, extracting {action} placeholder if possible
|
|
12
|
+
*/
|
|
13
|
+
export declare function saveDevloopCommitFormat(workspace: string, userMessage: string, defaultAction: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Check if git is available on the system
|
|
16
|
+
*/
|
|
17
|
+
export declare function isGitAvailable(): Promise<boolean>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if the workspace is inside a git repository
|
|
20
|
+
* Uses git rev-parse to properly detect repos (handles nested dirs, submodules, etc.)
|
|
21
|
+
*/
|
|
22
|
+
export declare function isGitRepo(workspace: string): Promise<boolean>;
|
|
23
|
+
/**
|
|
24
|
+
* Get the root directory of the git repository containing the workspace
|
|
25
|
+
*/
|
|
26
|
+
export declare function getGitRoot(workspace: string): Promise<string | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Initialize a new git repository in the workspace
|
|
29
|
+
*/
|
|
30
|
+
export declare function initGitRepo(workspace: string): Promise<boolean>;
|
|
31
|
+
/**
|
|
32
|
+
* Ensure .gitignore exists with sensible defaults.
|
|
33
|
+
* If .gitignore doesn't exist, creates one.
|
|
34
|
+
* If it exists but is missing critical patterns, appends them.
|
|
35
|
+
* Creates .gitignore at the git root, not necessarily the workspace.
|
|
36
|
+
*/
|
|
37
|
+
export declare function ensureGitignore(workspace: string, verbose?: boolean): Promise<boolean>;
|
|
38
|
+
/**
|
|
39
|
+
* Stage all changes and commit with the given message
|
|
40
|
+
* Returns true if commit was made, false if nothing to commit or error
|
|
41
|
+
*/
|
|
42
|
+
export declare function gitCommit(workspace: string, message: string, verbose?: boolean): Promise<{
|
|
43
|
+
committed: boolean;
|
|
44
|
+
error?: string;
|
|
45
|
+
isHookFailure?: boolean;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Ensure the workspace has a git repository.
|
|
49
|
+
* If git is available and no repo exists, initialize one and commit initial files.
|
|
50
|
+
* Returns info about what was done.
|
|
51
|
+
*/
|
|
52
|
+
export declare function ensureGitRepo(workspace: string, verbose?: boolean): Promise<{
|
|
53
|
+
gitAvailable: boolean;
|
|
54
|
+
wasInitialized: boolean;
|
|
55
|
+
initialCommit: boolean;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Check if there are uncommitted changes in the workspace
|
|
59
|
+
* Returns the list of changed files if any
|
|
60
|
+
*/
|
|
61
|
+
export declare function getUncommittedChanges(workspace: string, ignorePaths?: string[]): Promise<{
|
|
62
|
+
hasChanges: boolean;
|
|
63
|
+
files: string[];
|
|
64
|
+
}>;
|
|
65
|
+
/**
|
|
66
|
+
* Get a diff summary of uncommitted changes
|
|
67
|
+
*/
|
|
68
|
+
export declare function getUncommittedDiff(workspace: string): Promise<string | null>;
|
|
69
|
+
/**
|
|
70
|
+
* Commit uncommitted changes from a previous interrupted session
|
|
71
|
+
* This preserves the partial work in git history before starting fresh
|
|
72
|
+
*/
|
|
73
|
+
export declare function commitInterruptedWork(workspace: string, taskId?: string, taskTitle?: string, verbose?: boolean): Promise<boolean>;
|
|
74
|
+
/**
|
|
75
|
+
* Commit changes after an iteration
|
|
76
|
+
*/
|
|
77
|
+
export declare function commitIteration(workspace: string, iteration: number, taskId: string | null, taskTitle: string | null, success: boolean, verbose?: boolean, featureName?: string): Promise<{
|
|
78
|
+
committed: boolean;
|
|
79
|
+
hookFailure?: boolean;
|
|
80
|
+
}>;
|
|
81
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/core/git.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAKtF;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhG;AAED;;GAEG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsB1H;AAqCD;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAGvD;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGnE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAM1E;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGrE;AAgDD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAoDnG;AAmCD;;;GAGG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAoDtK;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC;IACxF,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC,CAuDD;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAAE,UAAU,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiCxI;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuBlF;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CACzC,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,OAAe,GACvB,OAAO,CAAC,OAAO,CAAC,CAkClB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,IAAI,EACrB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,OAAe,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAmCxD"}
|