duocode 0.1.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.
Files changed (220) hide show
  1. package/.env.example +36 -0
  2. package/LICENSE +21 -0
  3. package/README.md +52 -0
  4. package/dist/ast/context.d.ts +16 -0
  5. package/dist/ast/context.js +37 -0
  6. package/dist/ast/context.js.map +1 -0
  7. package/dist/ast/diff.d.ts +27 -0
  8. package/dist/ast/diff.js +44 -0
  9. package/dist/ast/diff.js.map +1 -0
  10. package/dist/ast/locks.d.ts +47 -0
  11. package/dist/ast/locks.js +88 -0
  12. package/dist/ast/locks.js.map +1 -0
  13. package/dist/ast/merge.d.ts +22 -0
  14. package/dist/ast/merge.js +120 -0
  15. package/dist/ast/merge.js.map +1 -0
  16. package/dist/ast/ownership.d.ts +31 -0
  17. package/dist/ast/ownership.js +111 -0
  18. package/dist/ast/ownership.js.map +1 -0
  19. package/dist/ast/parser.d.ts +44 -0
  20. package/dist/ast/parser.js +134 -0
  21. package/dist/ast/parser.js.map +1 -0
  22. package/dist/cli.d.ts +2 -0
  23. package/dist/cli.js +423 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/commands/doctor.d.ts +5 -0
  26. package/dist/commands/doctor.js +63 -0
  27. package/dist/commands/doctor.js.map +1 -0
  28. package/dist/commands/duo.d.ts +9 -0
  29. package/dist/commands/duo.js +285 -0
  30. package/dist/commands/duo.js.map +1 -0
  31. package/dist/commands/github.d.ts +2 -0
  32. package/dist/commands/github.js +85 -0
  33. package/dist/commands/github.js.map +1 -0
  34. package/dist/commands/init.d.ts +2 -0
  35. package/dist/commands/init.js +33 -0
  36. package/dist/commands/init.js.map +1 -0
  37. package/dist/commands/negotiation.d.ts +2 -0
  38. package/dist/commands/negotiation.js +160 -0
  39. package/dist/commands/negotiation.js.map +1 -0
  40. package/dist/commands/repl_commands.d.ts +26 -0
  41. package/dist/commands/repl_commands.js +226 -0
  42. package/dist/commands/repl_commands.js.map +1 -0
  43. package/dist/commands/shell.d.ts +1 -0
  44. package/dist/commands/shell.js +110 -0
  45. package/dist/commands/shell.js.map +1 -0
  46. package/dist/commands/start.d.ts +2 -0
  47. package/dist/commands/start.js +231 -0
  48. package/dist/commands/start.js.map +1 -0
  49. package/dist/commands/task.d.ts +2 -0
  50. package/dist/commands/task.js +215 -0
  51. package/dist/commands/task.js.map +1 -0
  52. package/dist/config/loader.d.ts +193 -0
  53. package/dist/config/loader.js +106 -0
  54. package/dist/config/loader.js.map +1 -0
  55. package/dist/context/project_context.d.ts +79 -0
  56. package/dist/context/project_context.js +292 -0
  57. package/dist/context/project_context.js.map +1 -0
  58. package/dist/context/token_budget.d.ts +35 -0
  59. package/dist/context/token_budget.js +81 -0
  60. package/dist/context/token_budget.js.map +1 -0
  61. package/dist/db/queries.d.ts +121 -0
  62. package/dist/db/queries.js +109 -0
  63. package/dist/db/queries.js.map +1 -0
  64. package/dist/db/schema.d.ts +110 -0
  65. package/dist/db/schema.js +346 -0
  66. package/dist/db/schema.js.map +1 -0
  67. package/dist/duo/duo_orchestrator.d.ts +50 -0
  68. package/dist/duo/duo_orchestrator.js +510 -0
  69. package/dist/duo/duo_orchestrator.js.map +1 -0
  70. package/dist/duo/duo_session.d.ts +47 -0
  71. package/dist/duo/duo_session.js +127 -0
  72. package/dist/duo/duo_session.js.map +1 -0
  73. package/dist/duo/duo_types.d.ts +168 -0
  74. package/dist/duo/duo_types.js +53 -0
  75. package/dist/duo/duo_types.js.map +1 -0
  76. package/dist/duo/session_store.d.ts +71 -0
  77. package/dist/duo/session_store.js +177 -0
  78. package/dist/duo/session_store.js.map +1 -0
  79. package/dist/git/worktree.d.ts +21 -0
  80. package/dist/git/worktree.js +86 -0
  81. package/dist/git/worktree.js.map +1 -0
  82. package/dist/github/cache.d.ts +23 -0
  83. package/dist/github/cache.js +67 -0
  84. package/dist/github/cache.js.map +1 -0
  85. package/dist/github/issues.d.ts +17 -0
  86. package/dist/github/issues.js +93 -0
  87. package/dist/github/issues.js.map +1 -0
  88. package/dist/github/mcp_client.d.ts +57 -0
  89. package/dist/github/mcp_client.js +214 -0
  90. package/dist/github/mcp_client.js.map +1 -0
  91. package/dist/github/sync.d.ts +11 -0
  92. package/dist/github/sync.js +65 -0
  93. package/dist/github/sync.js.map +1 -0
  94. package/dist/github/webhook.d.ts +25 -0
  95. package/dist/github/webhook.js +197 -0
  96. package/dist/github/webhook.js.map +1 -0
  97. package/dist/negotiation/index.d.ts +1 -0
  98. package/dist/negotiation/index.js +2 -0
  99. package/dist/negotiation/index.js.map +1 -0
  100. package/dist/negotiation/protocol.d.ts +62 -0
  101. package/dist/negotiation/protocol.js +188 -0
  102. package/dist/negotiation/protocol.js.map +1 -0
  103. package/dist/orchestrator/complexity_scorer.d.ts +2 -0
  104. package/dist/orchestrator/complexity_scorer.js +79 -0
  105. package/dist/orchestrator/complexity_scorer.js.map +1 -0
  106. package/dist/orchestrator/dependency_graph.d.ts +7 -0
  107. package/dist/orchestrator/dependency_graph.js +73 -0
  108. package/dist/orchestrator/dependency_graph.js.map +1 -0
  109. package/dist/orchestrator/intent_parser.d.ts +11 -0
  110. package/dist/orchestrator/intent_parser.js +116 -0
  111. package/dist/orchestrator/intent_parser.js.map +1 -0
  112. package/dist/orchestrator/task_runner.d.ts +56 -0
  113. package/dist/orchestrator/task_runner.js +181 -0
  114. package/dist/orchestrator/task_runner.js.map +1 -0
  115. package/dist/orchestrator/types.d.ts +44 -0
  116. package/dist/orchestrator/types.js +21 -0
  117. package/dist/orchestrator/types.js.map +1 -0
  118. package/dist/providers/anthropic.d.ts +12 -0
  119. package/dist/providers/anthropic.js +258 -0
  120. package/dist/providers/anthropic.js.map +1 -0
  121. package/dist/providers/auction.d.ts +42 -0
  122. package/dist/providers/auction.js +190 -0
  123. package/dist/providers/auction.js.map +1 -0
  124. package/dist/providers/base.d.ts +103 -0
  125. package/dist/providers/base.js +2 -0
  126. package/dist/providers/base.js.map +1 -0
  127. package/dist/providers/cost_tracker.d.ts +45 -0
  128. package/dist/providers/cost_tracker.js +111 -0
  129. package/dist/providers/cost_tracker.js.map +1 -0
  130. package/dist/providers/duo_pair_router.d.ts +11 -0
  131. package/dist/providers/duo_pair_router.js +67 -0
  132. package/dist/providers/duo_pair_router.js.map +1 -0
  133. package/dist/providers/factory.d.ts +7 -0
  134. package/dist/providers/factory.js +130 -0
  135. package/dist/providers/factory.js.map +1 -0
  136. package/dist/providers/grading_rubric.d.ts +37 -0
  137. package/dist/providers/grading_rubric.js +238 -0
  138. package/dist/providers/grading_rubric.js.map +1 -0
  139. package/dist/providers/openai.d.ts +12 -0
  140. package/dist/providers/openai.js +229 -0
  141. package/dist/providers/openai.js.map +1 -0
  142. package/dist/providers/openrouter.d.ts +14 -0
  143. package/dist/providers/openrouter.js +178 -0
  144. package/dist/providers/openrouter.js.map +1 -0
  145. package/dist/providers/performance_tracker.d.ts +21 -0
  146. package/dist/providers/performance_tracker.js +63 -0
  147. package/dist/providers/performance_tracker.js.map +1 -0
  148. package/dist/providers/registry_loader.d.ts +6 -0
  149. package/dist/providers/registry_loader.js +54 -0
  150. package/dist/providers/registry_loader.js.map +1 -0
  151. package/dist/providers/retry.d.ts +66 -0
  152. package/dist/providers/retry.js +203 -0
  153. package/dist/providers/retry.js.map +1 -0
  154. package/dist/providers/role_scorer.d.ts +16 -0
  155. package/dist/providers/role_scorer.js +16 -0
  156. package/dist/providers/role_scorer.js.map +1 -0
  157. package/dist/providers/router.d.ts +84 -0
  158. package/dist/providers/router.js +542 -0
  159. package/dist/providers/router.js.map +1 -0
  160. package/dist/security/credentials.d.ts +6 -0
  161. package/dist/security/credentials.js +16 -0
  162. package/dist/security/credentials.js.map +1 -0
  163. package/dist/setup/browser.d.ts +1 -0
  164. package/dist/setup/browser.js +12 -0
  165. package/dist/setup/browser.js.map +1 -0
  166. package/dist/setup/global_config.d.ts +14 -0
  167. package/dist/setup/global_config.js +54 -0
  168. package/dist/setup/global_config.js.map +1 -0
  169. package/dist/setup/wizard.d.ts +2 -0
  170. package/dist/setup/wizard.js +206 -0
  171. package/dist/setup/wizard.js.map +1 -0
  172. package/dist/tools/agent_loop.d.ts +38 -0
  173. package/dist/tools/agent_loop.js +72 -0
  174. package/dist/tools/agent_loop.js.map +1 -0
  175. package/dist/tools/approval.d.ts +64 -0
  176. package/dist/tools/approval.js +172 -0
  177. package/dist/tools/approval.js.map +1 -0
  178. package/dist/tools/checkpoint.d.ts +65 -0
  179. package/dist/tools/checkpoint.js +342 -0
  180. package/dist/tools/checkpoint.js.map +1 -0
  181. package/dist/tools/definitions.d.ts +13 -0
  182. package/dist/tools/definitions.js +103 -0
  183. package/dist/tools/definitions.js.map +1 -0
  184. package/dist/tools/diff_display.d.ts +46 -0
  185. package/dist/tools/diff_display.js +298 -0
  186. package/dist/tools/diff_display.js.map +1 -0
  187. package/dist/tools/executor.d.ts +12 -0
  188. package/dist/tools/executor.js +340 -0
  189. package/dist/tools/executor.js.map +1 -0
  190. package/dist/tools/permissions.d.ts +17 -0
  191. package/dist/tools/permissions.js +139 -0
  192. package/dist/tools/permissions.js.map +1 -0
  193. package/dist/tools/tool_types.d.ts +48 -0
  194. package/dist/tools/tool_types.js +7 -0
  195. package/dist/tools/tool_types.js.map +1 -0
  196. package/dist/ui/banner.d.ts +4 -0
  197. package/dist/ui/banner.js +104 -0
  198. package/dist/ui/banner.js.map +1 -0
  199. package/dist/ui/callbacks.d.ts +30 -0
  200. package/dist/ui/callbacks.js +132 -0
  201. package/dist/ui/callbacks.js.map +1 -0
  202. package/dist/ui/colors.d.ts +14 -0
  203. package/dist/ui/colors.js +28 -0
  204. package/dist/ui/colors.js.map +1 -0
  205. package/dist/ui/dashboard.d.ts +51 -0
  206. package/dist/ui/dashboard.js +181 -0
  207. package/dist/ui/dashboard.js.map +1 -0
  208. package/dist/ui/leaderboard.d.ts +16 -0
  209. package/dist/ui/leaderboard.js +43 -0
  210. package/dist/ui/leaderboard.js.map +1 -0
  211. package/dist/ui/logger.d.ts +28 -0
  212. package/dist/ui/logger.js +117 -0
  213. package/dist/ui/logger.js.map +1 -0
  214. package/dist/ui/progress.d.ts +16 -0
  215. package/dist/ui/progress.js +62 -0
  216. package/dist/ui/progress.js.map +1 -0
  217. package/dist/ui/tokenizer.d.ts +5 -0
  218. package/dist/ui/tokenizer.js +54 -0
  219. package/dist/ui/tokenizer.js.map +1 -0
  220. package/package.json +63 -0
@@ -0,0 +1,111 @@
1
+ import { createHash } from "node:crypto";
2
+ import { textForNode } from "./parser.js";
3
+ function isOwnershipNode(language, node) {
4
+ switch (language) {
5
+ case "typescript":
6
+ return [
7
+ "function_declaration",
8
+ "method_definition",
9
+ "class_declaration",
10
+ "interface_declaration",
11
+ "type_alias_declaration",
12
+ "enum_declaration",
13
+ ].includes(node.type);
14
+ case "python":
15
+ return ["function_definition", "class_definition"].includes(node.type);
16
+ case "go":
17
+ return ["function_declaration", "method_declaration", "type_declaration"].includes(node.type);
18
+ default:
19
+ return false;
20
+ }
21
+ }
22
+ function normalizeIdentifier(text) {
23
+ return text.replace(/["'`]/g, "").trim();
24
+ }
25
+ function resolveNodeName(language, node, source) {
26
+ const fieldCandidates = [
27
+ "name",
28
+ "identifier",
29
+ "declarator",
30
+ "type",
31
+ ];
32
+ for (const field of fieldCandidates) {
33
+ const named = node.childForFieldName(field);
34
+ if (named) {
35
+ return normalizeIdentifier(textForNode(named, source));
36
+ }
37
+ }
38
+ for (const child of node.namedChildren) {
39
+ if (child.type === "identifier" || child.type === "type_identifier") {
40
+ return normalizeIdentifier(textForNode(child, source));
41
+ }
42
+ }
43
+ // Tree-sitter grammars vary by language and statement form. Fall back to
44
+ // a stable anonymous name to keep ownership units serializable.
45
+ return `${language}:${node.type}@${node.startPosition.row + 1}:${node.startPosition.column + 1}`;
46
+ }
47
+ function createUnitHash(language, path, text) {
48
+ return createHash("sha256")
49
+ .update(language)
50
+ .update("\n")
51
+ .update(path)
52
+ .update("\n")
53
+ .update(text)
54
+ .digest("hex");
55
+ }
56
+ export function extractOwnershipUnits(parseResult, filePath) {
57
+ const { language, tree, source } = parseResult;
58
+ const units = [];
59
+ function visit(node, parentPath) {
60
+ let nextParentPath = parentPath;
61
+ if (isOwnershipNode(language, node)) {
62
+ const name = resolveNodeName(language, node, source);
63
+ const nodeSegment = `${node.type}:${name}`;
64
+ const nodePath = parentPath ? `${parentPath}/${nodeSegment}` : nodeSegment;
65
+ const text = textForNode(node, source);
66
+ const unit = {
67
+ id: createHash("sha1").update(nodePath).digest("hex"),
68
+ language,
69
+ filePath,
70
+ nodeType: node.type,
71
+ name,
72
+ path: nodePath,
73
+ parentPath,
74
+ range: {
75
+ startIndex: node.startIndex,
76
+ endIndex: node.endIndex,
77
+ startLine: node.startPosition.row + 1,
78
+ startColumn: node.startPosition.column + 1,
79
+ endLine: node.endPosition.row + 1,
80
+ endColumn: node.endPosition.column + 1,
81
+ },
82
+ hash: createUnitHash(language, nodePath, text),
83
+ text,
84
+ };
85
+ units.push(unit);
86
+ nextParentPath = nodePath;
87
+ }
88
+ for (const child of node.namedChildren) {
89
+ visit(child, nextParentPath);
90
+ }
91
+ }
92
+ visit(tree.rootNode, null);
93
+ return units.sort((a, b) => a.path.localeCompare(b.path));
94
+ }
95
+ export function createOwnershipSnapshot(parseResult, filePath) {
96
+ return {
97
+ language: parseResult.language,
98
+ filePath,
99
+ units: extractOwnershipUnits(parseResult, filePath),
100
+ };
101
+ }
102
+ export function serializeOwnershipSnapshot(snapshot) {
103
+ return JSON.stringify(snapshot, null, 2);
104
+ }
105
+ export function deserializeOwnershipSnapshot(serialized) {
106
+ return JSON.parse(serialized);
107
+ }
108
+ export function ownershipMapByPath(snapshot) {
109
+ return new Map(snapshot.units.map((unit) => [unit.path, unit]));
110
+ }
111
+ //# sourceMappingURL=ownership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ownership.js","sourceRoot":"","sources":["../../src/ast/ownership.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export type SupportedLanguage = "typescript" | "python" | "go";
2
+ export interface AstNode {
3
+ type: string;
4
+ startIndex: number;
5
+ endIndex: number;
6
+ startPosition: {
7
+ row: number;
8
+ column: number;
9
+ };
10
+ endPosition: {
11
+ row: number;
12
+ column: number;
13
+ };
14
+ children: AstNode[];
15
+ namedChildren: AstNode[];
16
+ text?: string;
17
+ childForFieldName(name: string): AstNode | null;
18
+ }
19
+ export interface AstTree {
20
+ rootNode: AstNode;
21
+ }
22
+ export interface AstParseResult {
23
+ language: SupportedLanguage;
24
+ source: string;
25
+ tree: AstTree;
26
+ }
27
+ /**
28
+ * Whether tree-sitter is available. Must be called after `ensureTreeSitter()`.
29
+ */
30
+ export declare function isAstAvailable(): boolean;
31
+ /**
32
+ * Attempt to load tree-sitter. Safe to call multiple times.
33
+ * Returns true if tree-sitter is available.
34
+ */
35
+ export declare function ensureTreeSitter(): Promise<boolean>;
36
+ export declare class MultiLanguageAstParser {
37
+ private readonly ts;
38
+ private readonly parser;
39
+ constructor();
40
+ parseSource(language: SupportedLanguage, source: string): AstParseResult;
41
+ parseFile(filePath: string, language?: SupportedLanguage): AstParseResult;
42
+ parseMaybeFile(filePath: string): AstParseResult | null;
43
+ }
44
+ export declare function textForNode(node: AstNode, source: string): string;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * AST parsing with tree-sitter.
3
+ * tree-sitter is an optional dependency — this module gracefully degrades
4
+ * when it is not installed (e.g., on platforms without prebuilt binaries).
5
+ */
6
+ import fs from "node:fs";
7
+ import path from "node:path";
8
+ import { createRequire } from "node:module";
9
+ let _loaded = null;
10
+ let _loadAttempted = false;
11
+ const esmRequire = createRequire(import.meta.url);
12
+ /** Synchronous load using createRequire (CJS native addons in ESM). */
13
+ function tryLoadSync() {
14
+ try {
15
+ const ParserMod = esmRequire("tree-sitter");
16
+ const tsMod = esmRequire("tree-sitter-typescript");
17
+ const pyMod = esmRequire("tree-sitter-python");
18
+ const goMod = esmRequire("tree-sitter-go");
19
+ return {
20
+ Parser: ParserMod.default ?? ParserMod,
21
+ typescript: (tsMod.default ?? tsMod).typescript ?? (tsMod.default ?? tsMod),
22
+ python: pyMod.default ?? pyMod,
23
+ go: goMod.default ?? goMod,
24
+ };
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ async function loadTreeSitter() {
31
+ if (_loadAttempted)
32
+ return _loaded;
33
+ _loadAttempted = true;
34
+ try {
35
+ const parserMod = await import("tree-sitter");
36
+ const tsMod = await import("tree-sitter-typescript");
37
+ const pyMod = await import("tree-sitter-python");
38
+ const goMod = await import("tree-sitter-go");
39
+ _loaded = {
40
+ Parser: parserMod.default,
41
+ typescript: tsMod.default.typescript,
42
+ python: pyMod.default,
43
+ go: goMod.default,
44
+ };
45
+ }
46
+ catch {
47
+ _loaded = null;
48
+ }
49
+ return _loaded;
50
+ }
51
+ /**
52
+ * Whether tree-sitter is available. Must be called after `ensureTreeSitter()`.
53
+ */
54
+ export function isAstAvailable() {
55
+ return _loaded !== null;
56
+ }
57
+ /**
58
+ * Attempt to load tree-sitter. Safe to call multiple times.
59
+ * Returns true if tree-sitter is available.
60
+ */
61
+ export async function ensureTreeSitter() {
62
+ const ts = await loadTreeSitter();
63
+ return ts !== null;
64
+ }
65
+ // ── Helpers ───────────────────────────────────────────────────────
66
+ function languageFromExtension(filePath) {
67
+ const ext = path.extname(filePath).toLowerCase();
68
+ if (ext === ".ts" || ext === ".tsx") {
69
+ return "typescript";
70
+ }
71
+ if (ext === ".py") {
72
+ return "python";
73
+ }
74
+ if (ext === ".go") {
75
+ return "go";
76
+ }
77
+ return null;
78
+ }
79
+ function grammarFor(ts, language) {
80
+ switch (language) {
81
+ case "typescript":
82
+ return ts.typescript;
83
+ case "python":
84
+ return ts.python;
85
+ case "go":
86
+ return ts.go;
87
+ default: {
88
+ const neverLanguage = language;
89
+ throw new Error(`Unsupported language: ${String(neverLanguage)}`);
90
+ }
91
+ }
92
+ }
93
+ // ── MultiLanguageAstParser ────────────────────────────────────────
94
+ export class MultiLanguageAstParser {
95
+ ts;
96
+ parser;
97
+ constructor() {
98
+ // Auto-attempt sync load if not already loaded
99
+ if (!_loaded && !_loadAttempted) {
100
+ _loaded = tryLoadSync();
101
+ _loadAttempted = true;
102
+ }
103
+ if (!_loaded) {
104
+ throw new Error("tree-sitter is not available. Install optional dependencies:\n" +
105
+ " npm install tree-sitter tree-sitter-typescript tree-sitter-python tree-sitter-go");
106
+ }
107
+ this.ts = _loaded;
108
+ this.parser = new _loaded.Parser();
109
+ }
110
+ parseSource(language, source) {
111
+ this.parser.setLanguage(grammarFor(this.ts, language));
112
+ const tree = this.parser.parse(source);
113
+ return { language, source, tree };
114
+ }
115
+ parseFile(filePath, language) {
116
+ const detected = language ?? languageFromExtension(filePath);
117
+ if (!detected) {
118
+ throw new Error(`Unable to detect language for ${filePath}`);
119
+ }
120
+ const source = fs.readFileSync(filePath, "utf8");
121
+ return this.parseSource(detected, source);
122
+ }
123
+ parseMaybeFile(filePath) {
124
+ const detected = languageFromExtension(filePath);
125
+ if (!detected) {
126
+ return null;
127
+ }
128
+ return this.parseFile(filePath, detected);
129
+ }
130
+ }
131
+ export function textForNode(node, source) {
132
+ return source.slice(node.startIndex, node.endIndex);
133
+ }
134
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/ast/parser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsC5C,IAAI,OAAO,GAA0B,IAAI,CAAC;AAC1C,IAAI,cAAc,GAAG,KAAK,CAAC;AAE3B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAElD,uEAAuE;AACvE,SAAS,WAAW;IAClB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,UAAU,CAAC,wBAAwB,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,UAAU,CAAC,oBAAoB,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;QAE3C,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,OAAO,IAAI,SAAS;YACtC,UAAU,EAAE,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC;YAC3E,MAAM,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK;YAC9B,EAAE,EAAE,KAAK,CAAC,OAAO,IAAI,KAAK;SAC3B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,IAAI,cAAc;QAAE,OAAO,OAAO,CAAC;IACnC,cAAc,GAAG,IAAI,CAAC;IAEtB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAE7C,OAAO,GAAG;YACR,MAAM,EAAE,SAAS,CAAC,OAAO;YACzB,UAAU,EAAG,KAAoE,CAAC,OAAO,CAAC,UAAU;YACpG,MAAM,EAAG,KAAoD,CAAC,OAAO;YACrE,EAAE,EAAG,KAAoD,CAAC,OAAO;SAClE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,KAAK,IAAI,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,EAAE,GAAG,MAAM,cAAc,EAAE,CAAC;IAClC,OAAO,EAAE,KAAK,IAAI,CAAC;AACrB,CAAC;AAED,qEAAqE;AAErE,SAAS,qBAAqB,CAAC,QAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAEjD,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACpC,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,EAAkB,EAAE,QAA2B;IACjE,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,YAAY;YACf,OAAO,EAAE,CAAC,UAAU,CAAC;QACvB,KAAK,QAAQ;YACX,OAAO,EAAE,CAAC,MAAM,CAAC;QACnB,KAAK,IAAI;YACP,OAAO,EAAE,CAAC,EAAE,CAAC;QACf,OAAO,CAAC,CAAC,CAAC;YACR,MAAM,aAAa,GAAU,QAAQ,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,yBAAyB,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC;AAED,qEAAqE;AAErE,MAAM,OAAO,sBAAsB;IAChB,EAAE,CAAiB;IACnB,MAAM,CAAiF;IAExG;QACE,+CAA+C;QAC/C,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;YAChC,OAAO,GAAG,WAAW,EAAE,CAAC;YACxB,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,gEAAgE;gBAChE,oFAAoF,CACrF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,OAAO,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IACrC,CAAC;IAED,WAAW,CAAC,QAA2B,EAAE,MAAc;QACrD,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAEvD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,SAAS,CAAC,QAAgB,EAAE,QAA4B;QACtD,MAAM,QAAQ,GAAG,QAAQ,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,iCAAiC,QAAQ,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc,CAAC,QAAgB;QAC7B,MAAM,QAAQ,GAAG,qBAAqB,CAAC,QAAQ,CAAC,CAAC;QACjD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,IAAa,EAAE,MAAc;IACvD,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACtD,CAAC"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};