@sudocode-ai/integration-speckit 0.1.14
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/dist/id-generator.d.ts +149 -0
- package/dist/id-generator.d.ts.map +1 -0
- package/dist/id-generator.js +197 -0
- package/dist/id-generator.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1017 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/index.d.ts +11 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +16 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/markdown-utils.d.ts +138 -0
- package/dist/parser/markdown-utils.d.ts.map +1 -0
- package/dist/parser/markdown-utils.js +283 -0
- package/dist/parser/markdown-utils.js.map +1 -0
- package/dist/parser/plan-parser.d.ts +97 -0
- package/dist/parser/plan-parser.d.ts.map +1 -0
- package/dist/parser/plan-parser.js +286 -0
- package/dist/parser/plan-parser.js.map +1 -0
- package/dist/parser/spec-parser.d.ts +95 -0
- package/dist/parser/spec-parser.d.ts.map +1 -0
- package/dist/parser/spec-parser.js +250 -0
- package/dist/parser/spec-parser.js.map +1 -0
- package/dist/parser/supporting-docs.d.ts +119 -0
- package/dist/parser/supporting-docs.d.ts.map +1 -0
- package/dist/parser/supporting-docs.js +324 -0
- package/dist/parser/supporting-docs.js.map +1 -0
- package/dist/parser/tasks-parser.d.ts +171 -0
- package/dist/parser/tasks-parser.d.ts.map +1 -0
- package/dist/parser/tasks-parser.js +281 -0
- package/dist/parser/tasks-parser.js.map +1 -0
- package/dist/relationship-mapper.d.ts +165 -0
- package/dist/relationship-mapper.d.ts.map +1 -0
- package/dist/relationship-mapper.js +238 -0
- package/dist/relationship-mapper.js.map +1 -0
- package/dist/watcher.d.ts +137 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +599 -0
- package/dist/watcher.js.map +1 -0
- package/dist/writer/index.d.ts +8 -0
- package/dist/writer/index.d.ts.map +1 -0
- package/dist/writer/index.js +10 -0
- package/dist/writer/index.js.map +1 -0
- package/dist/writer/spec-writer.d.ts +70 -0
- package/dist/writer/spec-writer.d.ts.map +1 -0
- package/dist/writer/spec-writer.js +261 -0
- package/dist/writer/spec-writer.js.map +1 -0
- package/dist/writer/tasks-writer.d.ts +47 -0
- package/dist/writer/tasks-writer.d.ts.map +1 -0
- package/dist/writer/tasks-writer.js +161 -0
- package/dist/writer/tasks-writer.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship Mapping for Spec-Kit Integration
|
|
3
|
+
*
|
|
4
|
+
* Maps spec-kit file hierarchy to sudocode relationships.
|
|
5
|
+
*
|
|
6
|
+
* Spec-kit hierarchy:
|
|
7
|
+
* ```
|
|
8
|
+
* spec.md (root)
|
|
9
|
+
* └── plan.md (implements spec.md)
|
|
10
|
+
* ├── tasks (implement plan.md)
|
|
11
|
+
* ├── research.md (references plan.md)
|
|
12
|
+
* ├── data-model.md (references plan.md)
|
|
13
|
+
* └── contracts/* (references plan.md)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* This creates a clear dependency graph:
|
|
17
|
+
* - plan implements spec (spec defines WHAT, plan defines HOW)
|
|
18
|
+
* - tasks implement plan (tasks are actionable work items from the plan)
|
|
19
|
+
* - supporting docs reference plan (research, data models, contracts support the plan)
|
|
20
|
+
*/
|
|
21
|
+
import { getFeatureSpecId, getFeaturePlanId, generateTaskIssueId, } from "./id-generator.js";
|
|
22
|
+
/**
|
|
23
|
+
* Map all relationships for a spec-kit feature
|
|
24
|
+
*
|
|
25
|
+
* Creates the standard relationship hierarchy:
|
|
26
|
+
* 1. plan implements spec
|
|
27
|
+
* 2. each task implements plan
|
|
28
|
+
* 3. supporting docs reference plan
|
|
29
|
+
*
|
|
30
|
+
* @param featureNumber - Feature number (e.g., "001")
|
|
31
|
+
* @param prefix - Spec ID prefix (default: "sk")
|
|
32
|
+
* @param taskPrefix - Task issue ID prefix (default: "skt")
|
|
33
|
+
* @param tasks - Array of task information from tasks.md
|
|
34
|
+
* @param supportingDocs - Optional array of supporting documents to include
|
|
35
|
+
* @returns Array of relationships to create
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const relationships = mapFeatureRelationships("001", "sk", "skt", [
|
|
39
|
+
* { taskId: "T001" },
|
|
40
|
+
* { taskId: "T002", dependsOn: ["T001"] },
|
|
41
|
+
* ]);
|
|
42
|
+
* // Returns relationships:
|
|
43
|
+
* // - sk-001-plan implements sk-001-spec
|
|
44
|
+
* // - skt-001-T001 implements sk-001-plan
|
|
45
|
+
* // - skt-001-T002 implements sk-001-plan
|
|
46
|
+
* // - skt-001-T002 depends-on skt-001-T001
|
|
47
|
+
*/
|
|
48
|
+
export function mapFeatureRelationships(featureNumber, prefix = "sk", taskPrefix = "skt", tasks = [], supportingDocs = []) {
|
|
49
|
+
const relationships = [];
|
|
50
|
+
const specId = getFeatureSpecId(featureNumber, prefix);
|
|
51
|
+
const planId = getFeaturePlanId(featureNumber, prefix);
|
|
52
|
+
// 1. Plan implements Spec
|
|
53
|
+
relationships.push({
|
|
54
|
+
fromId: planId,
|
|
55
|
+
fromType: "spec",
|
|
56
|
+
toId: specId,
|
|
57
|
+
toType: "spec",
|
|
58
|
+
relationshipType: "implements",
|
|
59
|
+
});
|
|
60
|
+
// 2. Each task implements Plan
|
|
61
|
+
for (const task of tasks) {
|
|
62
|
+
const taskIssueId = generateTaskIssueId(featureNumber, task.taskId, taskPrefix);
|
|
63
|
+
relationships.push({
|
|
64
|
+
fromId: taskIssueId,
|
|
65
|
+
fromType: "issue",
|
|
66
|
+
toId: planId,
|
|
67
|
+
toType: "spec",
|
|
68
|
+
relationshipType: "implements",
|
|
69
|
+
});
|
|
70
|
+
// 3. Task dependencies (depends-on relationships)
|
|
71
|
+
if (task.dependsOn && task.dependsOn.length > 0) {
|
|
72
|
+
for (const depTaskId of task.dependsOn) {
|
|
73
|
+
const depIssueId = generateTaskIssueId(featureNumber, depTaskId, taskPrefix);
|
|
74
|
+
relationships.push({
|
|
75
|
+
fromId: taskIssueId,
|
|
76
|
+
fromType: "issue",
|
|
77
|
+
toId: depIssueId,
|
|
78
|
+
toType: "issue",
|
|
79
|
+
relationshipType: "depends-on",
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 4. Supporting docs reference Plan
|
|
85
|
+
for (const doc of supportingDocs) {
|
|
86
|
+
const docId = `${prefix}-${featureNumber}-${doc.fileType}`;
|
|
87
|
+
relationships.push({
|
|
88
|
+
fromId: docId,
|
|
89
|
+
fromType: doc.entityType,
|
|
90
|
+
toId: planId,
|
|
91
|
+
toType: "spec",
|
|
92
|
+
relationshipType: "references",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return relationships;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Map relationships for task dependencies within a feature
|
|
99
|
+
*
|
|
100
|
+
* @param featureNumber - Feature number (e.g., "001")
|
|
101
|
+
* @param taskPrefix - Task issue ID prefix (default: "skt")
|
|
102
|
+
* @param tasks - Array of tasks with their dependencies
|
|
103
|
+
* @returns Array of depends-on relationships between tasks
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* const deps = mapTaskDependencies("001", "skt", [
|
|
107
|
+
* { taskId: "T001" },
|
|
108
|
+
* { taskId: "T002", dependsOn: ["T001"] },
|
|
109
|
+
* { taskId: "T003", dependsOn: ["T001", "T002"] },
|
|
110
|
+
* ]);
|
|
111
|
+
* // Returns:
|
|
112
|
+
* // - skt-001-T002 depends-on skt-001-T001
|
|
113
|
+
* // - skt-001-T003 depends-on skt-001-T001
|
|
114
|
+
* // - skt-001-T003 depends-on skt-001-T002
|
|
115
|
+
*/
|
|
116
|
+
export function mapTaskDependencies(featureNumber, taskPrefix = "skt", tasks) {
|
|
117
|
+
const relationships = [];
|
|
118
|
+
for (const task of tasks) {
|
|
119
|
+
if (task.dependsOn && task.dependsOn.length > 0) {
|
|
120
|
+
const taskIssueId = generateTaskIssueId(featureNumber, task.taskId, taskPrefix);
|
|
121
|
+
for (const depTaskId of task.dependsOn) {
|
|
122
|
+
const depIssueId = generateTaskIssueId(featureNumber, depTaskId, taskPrefix);
|
|
123
|
+
relationships.push({
|
|
124
|
+
fromId: taskIssueId,
|
|
125
|
+
fromType: "issue",
|
|
126
|
+
toId: depIssueId,
|
|
127
|
+
toType: "issue",
|
|
128
|
+
relationshipType: "depends-on",
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return relationships;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Map relationships for supporting documents in a feature
|
|
137
|
+
*
|
|
138
|
+
* @param featureNumber - Feature number (e.g., "001")
|
|
139
|
+
* @param prefix - Spec ID prefix (default: "sk")
|
|
140
|
+
* @param supportingDocs - Array of supporting document information
|
|
141
|
+
* @returns Array of reference relationships to the plan
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* const refs = mapSupportingDocRelationships("001", "sk", [
|
|
145
|
+
* { fileType: "research", entityType: "spec" },
|
|
146
|
+
* { fileType: "data-model", entityType: "spec" },
|
|
147
|
+
* { fileType: "contract-api-spec", entityType: "spec" },
|
|
148
|
+
* ]);
|
|
149
|
+
* // Returns:
|
|
150
|
+
* // - sk-001-research references sk-001-plan
|
|
151
|
+
* // - sk-001-data-model references sk-001-plan
|
|
152
|
+
* // - sk-001-contract-api-spec references sk-001-plan
|
|
153
|
+
*/
|
|
154
|
+
export function mapSupportingDocRelationships(featureNumber, prefix = "sk", supportingDocs) {
|
|
155
|
+
const planId = getFeaturePlanId(featureNumber, prefix);
|
|
156
|
+
const relationships = [];
|
|
157
|
+
for (const doc of supportingDocs) {
|
|
158
|
+
const docId = `${prefix}-${featureNumber}-${doc.fileType}`;
|
|
159
|
+
relationships.push({
|
|
160
|
+
fromId: docId,
|
|
161
|
+
fromType: doc.entityType,
|
|
162
|
+
toId: planId,
|
|
163
|
+
toType: "spec",
|
|
164
|
+
relationshipType: "references",
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
return relationships;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Map the core spec->plan relationship for a feature
|
|
171
|
+
*
|
|
172
|
+
* @param featureNumber - Feature number (e.g., "001")
|
|
173
|
+
* @param prefix - Spec ID prefix (default: "sk")
|
|
174
|
+
* @returns The implements relationship from plan to spec
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* const rel = mapPlanToSpecRelationship("001");
|
|
178
|
+
* // Returns: sk-001-plan implements sk-001-spec
|
|
179
|
+
*/
|
|
180
|
+
export function mapPlanToSpecRelationship(featureNumber, prefix = "sk") {
|
|
181
|
+
return {
|
|
182
|
+
fromId: getFeaturePlanId(featureNumber, prefix),
|
|
183
|
+
fromType: "spec",
|
|
184
|
+
toId: getFeatureSpecId(featureNumber, prefix),
|
|
185
|
+
toType: "spec",
|
|
186
|
+
relationshipType: "implements",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Map a single task's relationship to its plan
|
|
191
|
+
*
|
|
192
|
+
* @param featureNumber - Feature number (e.g., "001")
|
|
193
|
+
* @param taskId - Task ID (e.g., "T001")
|
|
194
|
+
* @param prefix - Spec ID prefix (default: "sk")
|
|
195
|
+
* @param taskPrefix - Task issue ID prefix (default: "skt")
|
|
196
|
+
* @returns The implements relationship from task to plan
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* const rel = mapTaskToPlanRelationship("001", "T001");
|
|
200
|
+
* // Returns: skt-001-T001 implements sk-001-plan
|
|
201
|
+
*/
|
|
202
|
+
export function mapTaskToPlanRelationship(featureNumber, taskId, prefix = "sk", taskPrefix = "skt") {
|
|
203
|
+
return {
|
|
204
|
+
fromId: generateTaskIssueId(featureNumber, taskId, taskPrefix),
|
|
205
|
+
fromType: "issue",
|
|
206
|
+
toId: getFeaturePlanId(featureNumber, prefix),
|
|
207
|
+
toType: "spec",
|
|
208
|
+
relationshipType: "implements",
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Determine the standard supporting doc types for a feature
|
|
213
|
+
*
|
|
214
|
+
* @returns Array of standard supporting document types
|
|
215
|
+
*/
|
|
216
|
+
export function getStandardSupportingDocTypes() {
|
|
217
|
+
return [
|
|
218
|
+
{ fileType: "research", entityType: "spec" },
|
|
219
|
+
{ fileType: "data-model", entityType: "spec" },
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Create a contract document info for relationship mapping
|
|
224
|
+
*
|
|
225
|
+
* @param contractName - Contract file name without extension (e.g., "api-spec")
|
|
226
|
+
* @returns Supporting doc info for the contract
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* createContractDocInfo("api-spec")
|
|
230
|
+
* // Returns: { fileType: "contract-api-spec", entityType: "spec" }
|
|
231
|
+
*/
|
|
232
|
+
export function createContractDocInfo(contractName) {
|
|
233
|
+
return {
|
|
234
|
+
fileType: `contract-${contractName}`,
|
|
235
|
+
entityType: "spec",
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=relationship-mapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relationship-mapper.js","sourceRoot":"","sources":["../src/relationship-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File watcher for Spec-Kit integration
|
|
3
|
+
*
|
|
4
|
+
* Watches the .specify directory for changes to spec files, plans, tasks,
|
|
5
|
+
* and supporting documents. Detects which entities were created, updated, or deleted.
|
|
6
|
+
*/
|
|
7
|
+
import type { ExternalChange } from "@sudocode-ai/types";
|
|
8
|
+
/**
|
|
9
|
+
* Callback type for change notifications
|
|
10
|
+
*/
|
|
11
|
+
export type ChangeCallback = (changes: ExternalChange[]) => void;
|
|
12
|
+
/**
|
|
13
|
+
* Options for the SpecKitWatcher
|
|
14
|
+
*/
|
|
15
|
+
export interface SpecKitWatcherOptions {
|
|
16
|
+
/** Path to the .specify directory */
|
|
17
|
+
specifyPath: string;
|
|
18
|
+
/** Prefix for spec IDs (default: "sk") */
|
|
19
|
+
specPrefix?: string;
|
|
20
|
+
/** Prefix for task IDs (default: "skt") */
|
|
21
|
+
taskPrefix?: string;
|
|
22
|
+
/** Include supporting docs (default: true) */
|
|
23
|
+
includeSupportingDocs?: boolean;
|
|
24
|
+
/** Include constitution (default: true) */
|
|
25
|
+
includeConstitution?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* SpecKitWatcher monitors the .specify directory for changes
|
|
29
|
+
*
|
|
30
|
+
* Uses content hashing to detect actual changes vs just file touches.
|
|
31
|
+
* This prevents false positives from atomic writes and other file operations.
|
|
32
|
+
*/
|
|
33
|
+
export declare class SpecKitWatcher {
|
|
34
|
+
private watcher;
|
|
35
|
+
private entityHashes;
|
|
36
|
+
private callback;
|
|
37
|
+
private isProcessing;
|
|
38
|
+
private isRelevantFile;
|
|
39
|
+
private readonly specifyPath;
|
|
40
|
+
private readonly specPrefix;
|
|
41
|
+
private readonly taskPrefix;
|
|
42
|
+
private readonly includeSupportingDocs;
|
|
43
|
+
private readonly includeConstitution;
|
|
44
|
+
constructor(options: SpecKitWatcherOptions);
|
|
45
|
+
/**
|
|
46
|
+
* Update the cached hash for a specific entity after we wrote to it.
|
|
47
|
+
* This prevents the watcher from detecting our own writes as changes.
|
|
48
|
+
*/
|
|
49
|
+
updateEntityHash(entityId: string, hash: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Remove an entity from the hash cache (after deletion)
|
|
52
|
+
*/
|
|
53
|
+
removeEntityHash(entityId: string): void;
|
|
54
|
+
/**
|
|
55
|
+
* Start watching for changes
|
|
56
|
+
*
|
|
57
|
+
* @param callback - Function to call when changes are detected
|
|
58
|
+
*/
|
|
59
|
+
start(callback: ChangeCallback): void;
|
|
60
|
+
/**
|
|
61
|
+
* Stop watching for changes
|
|
62
|
+
*/
|
|
63
|
+
stop(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Check if watcher is active
|
|
66
|
+
*/
|
|
67
|
+
isWatching(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Handle file change event
|
|
70
|
+
*
|
|
71
|
+
* Uses content hashing to detect actual changes - no explicit debouncing needed.
|
|
72
|
+
* Chokidar's awaitWriteFinish handles write settling, and hash comparison
|
|
73
|
+
* filters out false positives from atomic writes.
|
|
74
|
+
*/
|
|
75
|
+
private handleFileChange;
|
|
76
|
+
/**
|
|
77
|
+
* Handle file deleted event
|
|
78
|
+
*/
|
|
79
|
+
private handleFileDeleted;
|
|
80
|
+
/**
|
|
81
|
+
* Process changes by comparing current state to cached hashes
|
|
82
|
+
*
|
|
83
|
+
* Uses isProcessing flag to prevent concurrent processing if multiple
|
|
84
|
+
* file events fire rapidly. Content hashing ensures only actual changes
|
|
85
|
+
* are reported.
|
|
86
|
+
*/
|
|
87
|
+
private processChanges;
|
|
88
|
+
/**
|
|
89
|
+
* Capture current state (entity hashes) for comparison
|
|
90
|
+
*/
|
|
91
|
+
captureState(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Detect changes by comparing current state to cached state
|
|
94
|
+
*/
|
|
95
|
+
private detectChanges;
|
|
96
|
+
/**
|
|
97
|
+
* Scan all entities in the .specify directory
|
|
98
|
+
*/
|
|
99
|
+
private scanAllEntities;
|
|
100
|
+
/**
|
|
101
|
+
* Compute a hash for an entity to detect changes
|
|
102
|
+
*/
|
|
103
|
+
private computeEntityHash;
|
|
104
|
+
/**
|
|
105
|
+
* Convert a parsed spec to ExternalEntity
|
|
106
|
+
*/
|
|
107
|
+
private specToExternalEntity;
|
|
108
|
+
/**
|
|
109
|
+
* Convert a parsed plan to ExternalEntity
|
|
110
|
+
*/
|
|
111
|
+
private planToExternalEntity;
|
|
112
|
+
/**
|
|
113
|
+
* Convert a parsed task to ExternalEntity (as issue)
|
|
114
|
+
*/
|
|
115
|
+
private taskToExternalEntity;
|
|
116
|
+
/**
|
|
117
|
+
* Convert a parsed supporting document to ExternalEntity
|
|
118
|
+
*/
|
|
119
|
+
private supportingDocToExternalEntity;
|
|
120
|
+
/**
|
|
121
|
+
* Convert a parsed contract to ExternalEntity
|
|
122
|
+
*/
|
|
123
|
+
private contractToExternalEntity;
|
|
124
|
+
/**
|
|
125
|
+
* Map spec-kit status to sudocode priority
|
|
126
|
+
*/
|
|
127
|
+
private statusToPriority;
|
|
128
|
+
/**
|
|
129
|
+
* Get current cached hashes (for testing/debugging)
|
|
130
|
+
*/
|
|
131
|
+
getEntityHashes(): Map<string, string>;
|
|
132
|
+
/**
|
|
133
|
+
* Force refresh of cached state (useful after external sync)
|
|
134
|
+
*/
|
|
135
|
+
refreshState(): void;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../src/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,oBAAoB,CAAC;AAiBzE;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,2CAA2C;IAC3C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,cAAc,CAAgD;IAEtE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAU;gBAElC,OAAO,EAAE,qBAAqB;IAQ1C;;;OAGG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAOtD;;OAEG;IACH,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAOxC;;;;OAIG;IACH,KAAK,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI;IAwFrC;;OAEG;IACH,IAAI,IAAI,IAAI;IASZ;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;IAgCtB;;OAEG;IACH,YAAY,IAAI,IAAI;IAcpB;;OAEG;IACH,OAAO,CAAC,aAAa;IAuDrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAsKvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAYzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqC5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgD5B;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA0C5B;;OAEG;IACH,OAAO,CAAC,6BAA6B;IA+CrC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IA6ChC;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAwBxB;;OAEG;IACH,eAAe,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;IAItC;;OAEG;IACH,YAAY,IAAI,IAAI;CAGrB"}
|