@better-agent/cli 0.1.0-beta.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ # @better-agent/cli
2
+
3
+ CLI utilities for Better Agent.
4
+
5
+ ## Commands
6
+
7
+ ### `better-agent generate type`
8
+
9
+ Generate a portable client app type from Better Agent config exports.
10
+
11
+ ```bash
12
+ better-agent generate type --config ./better-agent.ts
13
+ ```
14
+
15
+ Useful options:
16
+
17
+ - `--config <path...>`: one or more Better Agent config paths
18
+ - `--cwd <path>`: base directory for resolving relative config paths
19
+ - `--out <path>`: output `.d.ts` path, defaults to `better-agent.types.d.ts`
20
+ - `--name <identifier>`: exported type alias name, defaults to `BAClientApp`
21
+ - `--yes`: skip prompts and overwrite output
@@ -0,0 +1 @@
1
+ export { };
package/dist/index.mjs ADDED
@@ -0,0 +1,1032 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import path from "node:path";
4
+ import { BetterAgentError } from "@better-agent/shared/errors";
5
+ import chalk from "chalk";
6
+ import { existsSync } from "node:fs";
7
+ import { pathToFileURL } from "node:url";
8
+ import { createJiti } from "jiti";
9
+ import ts from "typescript";
10
+ import prompts from "prompts";
11
+ import fs from "node:fs/promises";
12
+ import { createInterface } from "node:readline/promises";
13
+
14
+ //#region src/typegen/discovery.ts
15
+ const isRecord$1 = (value) => value !== null && typeof value === "object";
16
+ const isTypegenAppExport = (value) => {
17
+ if (!isRecord$1(value)) return false;
18
+ if (!isRecord$1(value.config)) return false;
19
+ return typeof value.run === "function" && typeof value.stream === "function" && typeof value.handler === "function";
20
+ };
21
+ const resolveConfigPaths = (config, cwd) => (config ?? []).map((configPath) => path.isAbsolute(configPath) ? configPath : path.resolve(cwd, configPath));
22
+ const existingConfigPaths = (configPaths) => configPaths.filter((configPath) => existsSync(configPath));
23
+ const withMutedConsole = async (work) => {
24
+ const original = {
25
+ log: console.log,
26
+ info: console.info,
27
+ warn: console.warn
28
+ };
29
+ console.log = () => {};
30
+ console.info = () => {};
31
+ console.warn = () => {};
32
+ try {
33
+ return await work();
34
+ } finally {
35
+ console.log = original.log;
36
+ console.info = original.info;
37
+ console.warn = original.warn;
38
+ }
39
+ };
40
+ const collectDiscoveredApps = async (configPaths, cwd, onImportError) => {
41
+ const jiti = createJiti(import.meta.url, { extensions: [".ts", ".js"] });
42
+ const candidates = [];
43
+ let importErrors = 0;
44
+ const collectExportedApp = (app, configFile, exportName) => {
45
+ if (!isTypegenAppExport(app)) return false;
46
+ candidates.push({
47
+ app,
48
+ configFile,
49
+ exportPath: exportName.split("."),
50
+ label: `${path.relative(cwd, configFile)}:${exportName}`
51
+ });
52
+ return true;
53
+ };
54
+ const exportedEntries = (mod) => Object.entries(mod).flatMap(([exportName, value]) => {
55
+ if (exportName !== "default" || !isRecord$1(value)) return [[exportName, value]];
56
+ return [[exportName, value], ...Object.entries(value).map(([nestedName, nestedValue]) => [`default.${nestedName}`, nestedValue])];
57
+ });
58
+ for (const configPath of configPaths) {
59
+ const configFile = path.isAbsolute(configPath) ? configPath : path.resolve(cwd, configPath);
60
+ let mod;
61
+ try {
62
+ mod = await withMutedConsole(() => jiti.import(pathToFileURL(configFile).href));
63
+ } catch (error) {
64
+ onImportError(BetterAgentError.wrap({
65
+ err: error,
66
+ message: `Failed to load config: ${path.relative(cwd, configFile)}`,
67
+ opts: {
68
+ code: "INTERNAL",
69
+ context: {
70
+ command: "generate type",
71
+ configPath: path.relative(cwd, configFile)
72
+ },
73
+ trace: [{ at: "cli.typegen.discovery.collectDiscoveredApps.loadConfig" }],
74
+ stackFrom: collectDiscoveredApps
75
+ }
76
+ }));
77
+ importErrors += 1;
78
+ continue;
79
+ }
80
+ if (!isRecord$1(mod)) continue;
81
+ for (const [exportName, value] of exportedEntries(mod)) collectExportedApp(value, configFile, exportName);
82
+ }
83
+ if (candidates.length > 0) return candidates;
84
+ throw BetterAgentError.fromCode("NOT_FOUND", "No Better Agent app exports found in the provided config(s).", {
85
+ context: {
86
+ command: "generate type",
87
+ configCount: configPaths.length,
88
+ importErrors
89
+ },
90
+ trace: [{ at: "cli.typegen.discovery.collectDiscoveredApps.findApps" }],
91
+ stackFrom: collectDiscoveredApps
92
+ });
93
+ };
94
+
95
+ //#endregion
96
+ //#region src/typegen/normalize.ts
97
+ const isRecord = (value) => value !== null && typeof value === "object";
98
+ const hasNamedAgents = (value) => Array.isArray(value) && value.some((agent) => isRecord(agent) && typeof agent.name === "string" && agent.name.length > 0);
99
+ const normalizeDiscoveredApp = (candidate) => {
100
+ if (!hasNamedAgents(candidate.app.config.agents)) throw BetterAgentError.fromCode("VALIDATION_FAILED", "App has no serializable agents.", {
101
+ trace: [{ at: "cli.typegen.normalize.normalizeDiscoveredApp" }],
102
+ stackFrom: normalizeDiscoveredApp
103
+ });
104
+ return {
105
+ configFile: candidate.configFile,
106
+ exportPath: candidate.exportPath,
107
+ label: candidate.label
108
+ };
109
+ };
110
+
111
+ //#endregion
112
+ //#region src/typegen/render.ts
113
+ const DEFAULT_TYPE_NAME$1 = "BAClientApp";
114
+ const TYPE_FORMAT_FLAGS = ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.UseFullyQualifiedType | ts.TypeFormatFlags.WriteTypeArgumentsOfSignature | ts.TypeFormatFlags.MultilineObjectLiterals | ts.TypeFormatFlags.InTypeAlias;
115
+ var TypegenRenderError = class extends Error {
116
+ path;
117
+ constructor(path, message) {
118
+ super(`${path}: ${message}`);
119
+ this.name = "TypegenRenderError";
120
+ this.path = path;
121
+ }
122
+ };
123
+ const toPropertyName = (value) => /^[$A-Z_a-z][$\w]*$/.test(value) ? value : JSON.stringify(value);
124
+ const loadCompilerOptions = (configFiles) => {
125
+ const configPath = configFiles.map((configFile) => ts.findConfigFile(path.dirname(configFile), ts.sys.fileExists)).find((value) => typeof value === "string");
126
+ if (!configPath) return {
127
+ allowJs: true,
128
+ checkJs: false,
129
+ esModuleInterop: true,
130
+ jsx: ts.JsxEmit.Preserve,
131
+ module: ts.ModuleKind.ESNext,
132
+ moduleResolution: ts.ModuleResolutionKind.Bundler,
133
+ resolveJsonModule: true,
134
+ skipLibCheck: true,
135
+ strict: false,
136
+ target: ts.ScriptTarget.ES2022
137
+ };
138
+ return ts.getParsedCommandLineOfConfigFile(configPath, {}, {
139
+ ...ts.sys,
140
+ onUnRecoverableConfigFileDiagnostic: () => {}
141
+ })?.options ?? {};
142
+ };
143
+ const isLiteralLike = (node) => ts.isStringLiteralLike(node) || ts.isNumericLiteral(node) || node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.FalseKeyword || node.kind === ts.SyntaxKind.NullKeyword;
144
+ const unwrapExpression = (expression) => {
145
+ let current = expression;
146
+ while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isSatisfiesExpression(current) || ts.isTypeAssertionExpression(current)) current = current.expression;
147
+ return current;
148
+ };
149
+ const getExportSymbol = (checker, sourceFile, exportPath) => {
150
+ const moduleSymbol = checker.getSymbolAtLocation(sourceFile);
151
+ if (!moduleSymbol) return void 0;
152
+ let currentSymbol = checker.getExportsOfModule(moduleSymbol).find((symbol) => {
153
+ return symbol.escapedName.toString() === exportPath[0];
154
+ });
155
+ for (const segment of exportPath.slice(1)) {
156
+ if (!currentSymbol) return void 0;
157
+ const declaration = currentSymbol.valueDeclaration ?? currentSymbol.declarations?.[0];
158
+ if (!declaration) return void 0;
159
+ const currentType = checker.getTypeOfSymbolAtLocation(currentSymbol, declaration);
160
+ currentSymbol = checker.getPropertyOfType(currentType, segment);
161
+ }
162
+ return currentSymbol;
163
+ };
164
+ const renderPortableNode = (node, indent = 0) => {
165
+ const spacing = " ".repeat(indent);
166
+ switch (node.kind) {
167
+ case "literal": return node.value === null ? "null" : JSON.stringify(node.value);
168
+ case "keyword": return node.value;
169
+ case "union": return node.members.map((member) => renderPortableNode(member, indent)).join(" | ");
170
+ case "array": return `${node.readonly ? "readonly " : ""}${renderPortableNode(node.element, indent)}[]`;
171
+ case "tuple": return `${node.readonly ? "readonly " : ""}[${node.elements.map((element) => renderPortableNode(element, indent)).join(", ")}]`;
172
+ case "object":
173
+ if (node.properties.length === 0) return "{}";
174
+ return `{\n${node.properties.map((property) => `${spacing} ${toPropertyName(property.name)}${property.optional ? "?" : ""}: ${renderPortableNode(property.value, indent + 4)};`).join("\n")}\n${spacing}}`;
175
+ }
176
+ };
177
+ const renderTypeAlias = (typeName, node, label) => `/** ${label} */\nexport type ${typeName} = ${renderPortableNode(node)};`;
178
+ const formatCallableType = (checker, type) => {
179
+ const rendered = checker.typeToString(type, void 0, TYPE_FORMAT_FLAGS);
180
+ return rendered === "{}" ? "unknown" : rendered;
181
+ };
182
+ const fail = (pathLabel, message) => {
183
+ throw new TypegenRenderError(pathLabel, message);
184
+ };
185
+ const getPropertyAssignment = (objectLiteral, name) => objectLiteral.properties.find((property) => {
186
+ if (!ts.isPropertyAssignment(property) && !ts.isShorthandPropertyAssignment(property) && !ts.isMethodDeclaration(property)) return false;
187
+ return (ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property) ? property.name.getText() : ts.isIdentifier(property.name) || ts.isStringLiteral(property.name) || ts.isNumericLiteral(property.name) ? property.name.text : property.name.getText()) === name;
188
+ });
189
+ const resolvePropertyExpression = (objectLiteral, name) => {
190
+ const property = getPropertyAssignment(objectLiteral, name);
191
+ if (!property) return void 0;
192
+ if (ts.isPropertyAssignment(property)) return property.initializer;
193
+ if (ts.isShorthandPropertyAssignment(property)) return property.name;
194
+ };
195
+ const getSymbolExpression = (checker, expression) => {
196
+ let symbol = ts.isIdentifier(expression) && ts.isShorthandPropertyAssignment(expression.parent) ? checker.getShorthandAssignmentValueSymbol(expression.parent) : checker.getSymbolAtLocation(expression);
197
+ if (!symbol) return void 0;
198
+ while (symbol.flags & ts.SymbolFlags.Alias) {
199
+ const aliased = checker.getAliasedSymbol(symbol);
200
+ if (!aliased || aliased === symbol) break;
201
+ symbol = aliased;
202
+ }
203
+ const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
204
+ if (!declaration) return void 0;
205
+ if (ts.isVariableDeclaration(declaration)) return declaration.initializer ? ts.isAsExpression(declaration.initializer) || ts.isTypeAssertionExpression(declaration.initializer) ? declaration.initializer : declaration.initializer : void 0;
206
+ if (ts.isPropertyAssignment(declaration)) return declaration.initializer;
207
+ if (ts.isShorthandPropertyAssignment(declaration)) return declaration.name;
208
+ if (ts.isExportAssignment(declaration)) return declaration.expression;
209
+ };
210
+ const resolveExpressionReference = (checker, expression, seen = /* @__PURE__ */ new Set()) => {
211
+ let current = unwrapExpression(expression);
212
+ while (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {
213
+ if (seen.has(current)) return current;
214
+ seen.add(current);
215
+ const resolved = getSymbolExpression(checker, current);
216
+ if (!resolved) return current;
217
+ current = unwrapExpression(resolved);
218
+ }
219
+ return current;
220
+ };
221
+ const findPropertyInType = (checker, type, name) => {
222
+ const property = checker.getPropertyOfType(type, name);
223
+ if (!property) return void 0;
224
+ const declaration = property.valueDeclaration ?? property.declarations?.[0];
225
+ if (!declaration) return void 0;
226
+ return {
227
+ declaration,
228
+ symbol: property,
229
+ type: checker.getTypeOfSymbolAtLocation(property, declaration)
230
+ };
231
+ };
232
+ const OMIT_MODEL_OPTION_KEYS = new Set([
233
+ "input",
234
+ "tools",
235
+ "toolChoice",
236
+ "structured_output",
237
+ "modalities",
238
+ "instructions",
239
+ "text"
240
+ ]);
241
+ const extractPortableObjectNodeFromProperties = (checker, type, pathLabel, properties, seen = /* @__PURE__ */ new Set()) => {
242
+ const nextSeen = new Set([...seen, type]);
243
+ return {
244
+ kind: "object",
245
+ properties: properties.map((property) => {
246
+ const declaration = property.valueDeclaration ?? property.declarations?.[0];
247
+ if (!declaration) return fail(`${pathLabel}.${property.getName()}`, "missing declaration");
248
+ return {
249
+ name: property.getName(),
250
+ optional: (property.flags & ts.SymbolFlags.Optional) !== 0,
251
+ value: extractPortableNodeFromType(checker, checker.getTypeOfSymbolAtLocation(property, declaration), `${pathLabel}.${property.getName()}`, nextSeen)
252
+ };
253
+ })
254
+ };
255
+ };
256
+ const extractModelOptionsNodeFromType = (checker, modelType, pathLabel) => {
257
+ const options = findPropertyInType(checker, modelType, "options");
258
+ if (options) {
259
+ const optionsProperties = checker.getPropertiesOfType(options.type).filter((property) => !OMIT_MODEL_OPTION_KEYS.has(property.getName()));
260
+ if (optionsProperties.length === 0) return {
261
+ kind: "object",
262
+ properties: []
263
+ };
264
+ return extractPortableObjectNodeFromProperties(checker, options.type, `${pathLabel}.options`, optionsProperties);
265
+ }
266
+ const getOptionsFromMethod = (methodName) => {
267
+ const method = findPropertyInType(checker, modelType, methodName);
268
+ if (!method?.declaration) return void 0;
269
+ const methodType = checker.getTypeOfSymbolAtLocation(method.symbol, method.declaration);
270
+ const callableType = checker.getNonNullableType(methodType);
271
+ const parameter = checker.getSignaturesOfType(callableType, ts.SignatureKind.Call)[0]?.getParameters()[0];
272
+ const parameterDeclaration = parameter?.valueDeclaration ?? parameter?.declarations?.[0];
273
+ if (!parameter || !parameterDeclaration) return void 0;
274
+ const parameterType = checker.getTypeOfSymbolAtLocation(parameter, parameterDeclaration);
275
+ const optionProperties = checker.getPropertiesOfType(parameterType).filter((property) => !OMIT_MODEL_OPTION_KEYS.has(property.getName()));
276
+ if (optionProperties.length === 0) return {
277
+ kind: "object",
278
+ properties: []
279
+ };
280
+ return extractPortableObjectNodeFromProperties(checker, parameterType, `${pathLabel}.options`, optionProperties);
281
+ };
282
+ return getOptionsFromMethod("doGenerate") ?? getOptionsFromMethod("doGenerateStream");
283
+ };
284
+ const dedupeUnionMembers = (members) => {
285
+ const seen = /* @__PURE__ */ new Set();
286
+ const deduped = [];
287
+ for (const member of members) {
288
+ const key = renderPortableNode(member);
289
+ if (seen.has(key)) continue;
290
+ seen.add(key);
291
+ deduped.push(member);
292
+ }
293
+ return deduped;
294
+ };
295
+ const getStandardTypesInputType = (checker, schemaType) => {
296
+ const standard = findPropertyInType(checker, checker.getApparentType(checker.getNonNullableType(schemaType)), "~standard");
297
+ if (!standard) return void 0;
298
+ const types = findPropertyInType(checker, standard.type, "types");
299
+ if (!types) return void 0;
300
+ return findPropertyInType(checker, checker.getApparentType(checker.getNonNullableType(types.type)), "input")?.type;
301
+ };
302
+ const hasStandardSchemaShape = (checker, schemaType) => !!findPropertyInType(checker, checker.getApparentType(checker.getNonNullableType(schemaType)), "~standard");
303
+ const extractPortableNodeFromType = (checker, type, pathLabel, seen = /* @__PURE__ */ new Set()) => {
304
+ if (seen.has(type)) {
305
+ const rendered = formatCallableType(checker, type);
306
+ switch (rendered) {
307
+ case "string":
308
+ case "number":
309
+ case "boolean":
310
+ case "unknown": return {
311
+ kind: "keyword",
312
+ value: rendered
313
+ };
314
+ case "null": return {
315
+ kind: "literal",
316
+ value: null
317
+ };
318
+ case "undefined": return {
319
+ kind: "keyword",
320
+ value: "undefined"
321
+ };
322
+ default: fail(pathLabel, `unsupported recursive type: ${rendered}`);
323
+ }
324
+ }
325
+ if (type.isStringLiteral()) return {
326
+ kind: "literal",
327
+ value: type.value
328
+ };
329
+ if (type.isNumberLiteral()) return {
330
+ kind: "literal",
331
+ value: type.value
332
+ };
333
+ if (type.flags & ts.TypeFlags.BooleanLiteral) return {
334
+ kind: "literal",
335
+ value: checker.typeToString(type) === "true"
336
+ };
337
+ if (type.flags & ts.TypeFlags.Null) return {
338
+ kind: "literal",
339
+ value: null
340
+ };
341
+ if (type.flags & ts.TypeFlags.Undefined) return {
342
+ kind: "keyword",
343
+ value: "undefined"
344
+ };
345
+ if (type.flags & ts.TypeFlags.String) return {
346
+ kind: "keyword",
347
+ value: "string"
348
+ };
349
+ if (type.flags & ts.TypeFlags.Number) return {
350
+ kind: "keyword",
351
+ value: "number"
352
+ };
353
+ if (type.flags & ts.TypeFlags.Boolean) return {
354
+ kind: "keyword",
355
+ value: "boolean"
356
+ };
357
+ if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) return {
358
+ kind: "keyword",
359
+ value: "unknown"
360
+ };
361
+ if (type.isUnion()) return {
362
+ kind: "union",
363
+ members: dedupeUnionMembers(type.types.map((member, index) => extractPortableNodeFromType(checker, member, `${pathLabel}|${index + 1}`, new Set([...seen, type]))))
364
+ };
365
+ if (checker.isTupleType(type)) {
366
+ const typeReference = type;
367
+ return {
368
+ kind: "tuple",
369
+ readonly: true,
370
+ elements: checker.getTypeArguments(typeReference).map((entry, index) => extractPortableNodeFromType(checker, entry, `${pathLabel}[${index}]`, new Set([...seen, type])))
371
+ };
372
+ }
373
+ if (checker.isArrayType(type)) {
374
+ const typeReference = type;
375
+ const [element] = checker.getTypeArguments(typeReference);
376
+ if (!element) return fail(pathLabel, "unsupported array element type");
377
+ return {
378
+ kind: "array",
379
+ readonly: true,
380
+ element: extractPortableNodeFromType(checker, element, `${pathLabel}[]`, new Set([...seen, type]))
381
+ };
382
+ }
383
+ const properties = checker.getPropertiesOfType(type);
384
+ if (properties.length === 0) {
385
+ const rendered = formatCallableType(checker, type);
386
+ if (rendered.includes("[x: string]") || rendered.includes("[x:string]") || rendered === "{}") return {
387
+ kind: "keyword",
388
+ value: "unknown"
389
+ };
390
+ fail(pathLabel, `unsupported type: ${rendered}`);
391
+ }
392
+ const nextSeen = new Set([...seen, type]);
393
+ return {
394
+ kind: "object",
395
+ properties: properties.map((property) => {
396
+ const declaration = property.valueDeclaration ?? property.declarations?.[0];
397
+ if (!declaration) return fail(`${pathLabel}.${property.getName()}`, "missing declaration");
398
+ return {
399
+ name: property.getName(),
400
+ optional: (property.flags & ts.SymbolFlags.Optional) !== 0,
401
+ value: extractPortableNodeFromType(checker, checker.getTypeOfSymbolAtLocation(property, declaration), `${pathLabel}.${property.getName()}`, nextSeen)
402
+ };
403
+ })
404
+ };
405
+ };
406
+ const extractPortableNodeFromTypeNode = (checker, typeNode, pathLabel) => extractPortableNodeFromType(checker, checker.getTypeFromTypeNode(typeNode), pathLabel);
407
+ const extractPortableSchemaNodeFromExpression = (context, expression) => {
408
+ const current = resolveExpressionReference(context.checker, expression);
409
+ const schemaType = context.checker.getTypeAtLocation(current);
410
+ const standardInputType = getStandardTypesInputType(context.checker, schemaType);
411
+ if (standardInputType) return extractPortableNodeFromType(context.checker, standardInputType, `${context.path}.~standard.types.input`);
412
+ if (hasStandardSchemaShape(context.checker, schemaType)) return fail(context.path, "standard schema must expose '~standard.types.input' for portable type generation");
413
+ return extractPortableNodeFromExpression(context, current);
414
+ };
415
+ const extractPortableNodeFromExpression = (context, expression, mode = "strict") => {
416
+ const current = unwrapExpression(expression);
417
+ if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) return extractPortableNodeFromTypeNode(context.checker, expression.type, context.path);
418
+ if (isLiteralLike(current)) {
419
+ if (ts.isStringLiteralLike(current)) return {
420
+ kind: "literal",
421
+ value: current.text
422
+ };
423
+ if (ts.isNumericLiteral(current)) return {
424
+ kind: "literal",
425
+ value: Number(current.text)
426
+ };
427
+ if (current.kind === ts.SyntaxKind.TrueKeyword) return {
428
+ kind: "literal",
429
+ value: true
430
+ };
431
+ if (current.kind === ts.SyntaxKind.FalseKeyword) return {
432
+ kind: "literal",
433
+ value: false
434
+ };
435
+ return {
436
+ kind: "literal",
437
+ value: null
438
+ };
439
+ }
440
+ if (ts.isObjectLiteralExpression(current)) {
441
+ const properties = [];
442
+ for (const property of current.properties) {
443
+ if (ts.isSpreadAssignment(property)) fail(context.path, "spread properties are not supported in portable type generation");
444
+ if (ts.isMethodDeclaration(property)) continue;
445
+ let name;
446
+ let initializer;
447
+ if (ts.isPropertyAssignment(property)) {
448
+ name = ts.isIdentifier(property.name) || ts.isStringLiteral(property.name) || ts.isNumericLiteral(property.name) ? property.name.text : property.name.getText();
449
+ initializer = property.initializer;
450
+ } else if (ts.isShorthandPropertyAssignment(property)) {
451
+ name = property.name.text;
452
+ initializer = property.name;
453
+ } else continue;
454
+ properties.push({
455
+ name,
456
+ value: extractPortableNodeFromExpression({
457
+ checker: context.checker,
458
+ path: `${context.path}.${name}`
459
+ }, initializer, mode)
460
+ });
461
+ }
462
+ return {
463
+ kind: "object",
464
+ properties
465
+ };
466
+ }
467
+ if (ts.isArrayLiteralExpression(current)) return {
468
+ kind: "tuple",
469
+ readonly: true,
470
+ elements: current.elements.map((element, index) => {
471
+ if (ts.isSpreadElement(element)) fail(`${context.path}[${index}]`, "spread elements are not supported");
472
+ return extractPortableNodeFromExpression({
473
+ checker: context.checker,
474
+ path: `${context.path}[${index}]`
475
+ }, element, mode);
476
+ })
477
+ };
478
+ if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {
479
+ const resolved = getSymbolExpression(context.checker, current);
480
+ if (resolved) return extractPortableNodeFromExpression(context, resolved, mode);
481
+ }
482
+ if (ts.isCallExpression(current)) {
483
+ const firstArg = current.arguments[0];
484
+ if (firstArg && ts.isObjectLiteralExpression(unwrapExpression(firstArg))) return extractPortableNodeFromExpression(context, firstArg, mode);
485
+ if (mode === "type-fallback") return extractPortableNodeFromType(context.checker, context.checker.getTypeAtLocation(current), context.path);
486
+ }
487
+ if (mode === "type-fallback") return extractPortableNodeFromType(context.checker, context.checker.getTypeAtLocation(current), context.path);
488
+ return fail(context.path, `unsupported expression: ${current.getText()}`);
489
+ };
490
+ const extractOutputSchemaNode = (checker, expression, pathLabel) => {
491
+ const current = resolveExpressionReference(checker, expression);
492
+ if (!ts.isObjectLiteralExpression(current)) return fail(pathLabel, "outputSchema must resolve to an object literal");
493
+ const schemaExpression = resolvePropertyExpression(current, "schema");
494
+ if (!schemaExpression) return fail(pathLabel, "outputSchema is missing 'schema'");
495
+ const properties = [{
496
+ name: "schema",
497
+ value: extractPortableSchemaNodeFromExpression({
498
+ checker,
499
+ path: `${pathLabel}.schema`
500
+ }, schemaExpression)
501
+ }];
502
+ const nameExpression = resolvePropertyExpression(current, "name");
503
+ if (nameExpression) properties.push({
504
+ name: "name",
505
+ value: extractPortableNodeFromExpression({
506
+ checker,
507
+ path: `${pathLabel}.name`
508
+ }, nameExpression, "type-fallback")
509
+ });
510
+ const strictExpression = resolvePropertyExpression(current, "strict");
511
+ if (strictExpression) properties.push({
512
+ name: "strict",
513
+ value: extractPortableNodeFromExpression({
514
+ checker,
515
+ path: `${pathLabel}.strict`
516
+ }, strictExpression, "type-fallback")
517
+ });
518
+ return {
519
+ kind: "object",
520
+ properties
521
+ };
522
+ };
523
+ const extractAppConfigObject = (checker, declaration, label) => {
524
+ const fromExpression = (expression) => {
525
+ const current = unwrapExpression(expression);
526
+ if (ts.isObjectLiteralExpression(current)) {
527
+ const configExpr = resolvePropertyExpression(current, "config");
528
+ if (!configExpr) return void 0;
529
+ const configCurrent = unwrapExpression(configExpr);
530
+ return ts.isObjectLiteralExpression(configCurrent) ? configCurrent : void 0;
531
+ }
532
+ if (ts.isCallExpression(current)) {
533
+ const firstArg = current.arguments[0];
534
+ if (!firstArg) return void 0;
535
+ const configCurrent = unwrapExpression(firstArg);
536
+ return ts.isObjectLiteralExpression(configCurrent) ? configCurrent : void 0;
537
+ }
538
+ if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {
539
+ const resolved = getSymbolExpression(checker, current);
540
+ return resolved ? fromExpression(resolved) : void 0;
541
+ }
542
+ };
543
+ const expression = ts.isVariableDeclaration(declaration) && declaration.initializer ? declaration.initializer : ts.isExportAssignment(declaration) ? declaration.expression : void 0;
544
+ const configObject = expression ? fromExpression(expression) : void 0;
545
+ if (!configObject) return fail(label, "unable to locate a portable app config object");
546
+ return configObject;
547
+ };
548
+ const extractRequiredObjectProperty = (objectLiteral, name, checker, pathLabel) => {
549
+ const expression = resolvePropertyExpression(objectLiteral, name);
550
+ if (!expression) return fail(pathLabel, `missing required property '${name}'`);
551
+ return {
552
+ checker,
553
+ expression: unwrapExpression(expression),
554
+ path: `${pathLabel}.${name}`
555
+ };
556
+ };
557
+ const extractOptionalObjectProperty = (objectLiteral, name, checker, pathLabel) => {
558
+ const expression = resolvePropertyExpression(objectLiteral, name);
559
+ return expression ? {
560
+ checker,
561
+ expression: unwrapExpression(expression),
562
+ path: `${pathLabel}.${name}`
563
+ } : void 0;
564
+ };
565
+ const extractClientToolNode = (checker, expression, pathLabel) => {
566
+ const current = unwrapExpression(expression);
567
+ if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {
568
+ const resolved = getSymbolExpression(checker, current);
569
+ return resolved ? extractClientToolNode(checker, resolved, pathLabel) : void 0;
570
+ }
571
+ if (ts.isObjectLiteralExpression(current)) {
572
+ const kindExpression = resolvePropertyExpression(current, "kind");
573
+ const kindNode = kindExpression ? extractPortableNodeFromExpression({
574
+ checker,
575
+ path: `${pathLabel}.kind`
576
+ }, kindExpression, "type-fallback") : void 0;
577
+ if (!kindNode || kindNode.kind !== "literal" || typeof kindNode.value !== "string" || kindNode.value !== "client") return;
578
+ const nameExpression = resolvePropertyExpression(current, "name");
579
+ const schemaExpression = resolvePropertyExpression(current, "schema");
580
+ if (!nameExpression || !schemaExpression) return fail(pathLabel, "client tool is missing 'name' or 'schema'");
581
+ return {
582
+ kind: "object",
583
+ properties: [
584
+ {
585
+ name: "kind",
586
+ value: {
587
+ kind: "literal",
588
+ value: "client"
589
+ }
590
+ },
591
+ {
592
+ name: "name",
593
+ value: extractPortableNodeFromExpression({
594
+ checker,
595
+ path: `${pathLabel}.name`
596
+ }, nameExpression, "type-fallback")
597
+ },
598
+ {
599
+ name: "schema",
600
+ value: extractPortableSchemaNodeFromExpression({
601
+ checker,
602
+ path: `${pathLabel}.schema`
603
+ }, schemaExpression)
604
+ }
605
+ ]
606
+ };
607
+ }
608
+ if (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {
609
+ if (current.expression.name.text === "client") {
610
+ const baseCall = resolveExpressionReference(checker, current.expression.expression);
611
+ if (ts.isCallExpression(baseCall)) {
612
+ const configArg = baseCall.arguments[0];
613
+ const configObject = configArg && ts.isObjectLiteralExpression(unwrapExpression(configArg)) ? unwrapExpression(configArg) : void 0;
614
+ if (configObject) {
615
+ const nameExpression = resolvePropertyExpression(configObject, "name");
616
+ const schemaExpression = resolvePropertyExpression(configObject, "schema");
617
+ if (!nameExpression || !schemaExpression) return fail(pathLabel, "defineTool(...).client() is missing 'name' or 'schema'");
618
+ return {
619
+ kind: "object",
620
+ properties: [
621
+ {
622
+ name: "kind",
623
+ value: {
624
+ kind: "literal",
625
+ value: "client"
626
+ }
627
+ },
628
+ {
629
+ name: "name",
630
+ value: extractPortableNodeFromExpression({
631
+ checker,
632
+ path: `${pathLabel}.name`
633
+ }, nameExpression, "type-fallback")
634
+ },
635
+ {
636
+ name: "schema",
637
+ value: extractPortableSchemaNodeFromExpression({
638
+ checker,
639
+ path: `${pathLabel}.schema`
640
+ }, schemaExpression)
641
+ }
642
+ ]
643
+ };
644
+ }
645
+ }
646
+ }
647
+ }
648
+ const toolType = checker.getTypeAtLocation(current);
649
+ const kindProperty = findPropertyInType(checker, toolType, "kind");
650
+ if (!kindProperty) return void 0;
651
+ const kindNode = extractPortableNodeFromType(checker, kindProperty.type, `${pathLabel}.kind`);
652
+ if (kindNode.kind !== "literal" || typeof kindNode.value !== "string" || kindNode.value !== "client") return;
653
+ const nameProperty = findPropertyInType(checker, toolType, "name");
654
+ const schemaProperty = findPropertyInType(checker, toolType, "schema");
655
+ if (!nameProperty || !schemaProperty) return fail(pathLabel, "client tool type is missing 'name' or 'schema'");
656
+ return {
657
+ kind: "object",
658
+ properties: [
659
+ {
660
+ name: "kind",
661
+ value: {
662
+ kind: "literal",
663
+ value: "client"
664
+ }
665
+ },
666
+ {
667
+ name: "name",
668
+ value: extractPortableNodeFromType(checker, nameProperty.type, `${pathLabel}.name`)
669
+ },
670
+ {
671
+ name: "schema",
672
+ value: extractPortableNodeFromType(checker, schemaProperty.type, `${pathLabel}.schema`)
673
+ }
674
+ ]
675
+ };
676
+ };
677
+ const extractToolsNode = (checker, expression, pathLabel) => {
678
+ const current = resolveExpressionReference(checker, expression);
679
+ if (!ts.isArrayLiteralExpression(current)) return fail(pathLabel, "tools must be declared as an array literal");
680
+ return {
681
+ kind: "tuple",
682
+ readonly: true,
683
+ elements: current.elements.flatMap((element, index) => {
684
+ if (ts.isSpreadElement(element)) return fail(`${pathLabel}[${index}]`, "spread tools are not supported");
685
+ const toolNode = extractClientToolNode(checker, element, `${pathLabel}[${index}]`);
686
+ return toolNode ? [toolNode] : [];
687
+ })
688
+ };
689
+ };
690
+ const extractAgentNode = (checker, expression, pathLabel) => {
691
+ const current = unwrapExpression(expression);
692
+ const resolved = ts.isIdentifier(current) || ts.isPropertyAccessExpression(current) ? getSymbolExpression(checker, current) : current;
693
+ const target = resolved ? unwrapExpression(resolved) : current;
694
+ const agentObject = ts.isCallExpression(target) ? target.arguments[0] : ts.isObjectLiteralExpression(target) ? target : void 0;
695
+ if (!agentObject || !ts.isObjectLiteralExpression(unwrapExpression(agentObject))) return fail(pathLabel, "agents must resolve to object literals or defineAgent(...) calls");
696
+ const objectLiteral = unwrapExpression(agentObject);
697
+ const nameSource = extractRequiredObjectProperty(objectLiteral, "name", checker, pathLabel);
698
+ const modelSource = extractRequiredObjectProperty(objectLiteral, "model", checker, pathLabel);
699
+ const contextSchemaSource = extractOptionalObjectProperty(objectLiteral, "contextSchema", checker, pathLabel);
700
+ const outputSchemaSource = extractOptionalObjectProperty(objectLiteral, "outputSchema", checker, pathLabel);
701
+ const toolsSource = extractOptionalObjectProperty(objectLiteral, "tools", checker, pathLabel);
702
+ const modelNode = (() => {
703
+ const modelProperties = [];
704
+ const currentModel = unwrapExpression(modelSource.expression);
705
+ if (ts.isObjectLiteralExpression(currentModel)) {
706
+ const providerIdExpr = resolvePropertyExpression(currentModel, "providerId");
707
+ if (providerIdExpr) modelProperties.push({
708
+ name: "providerId",
709
+ value: extractPortableNodeFromExpression({
710
+ checker,
711
+ path: `${pathLabel}.model.providerId`
712
+ }, providerIdExpr, "type-fallback")
713
+ });
714
+ const modelIdExpr = resolvePropertyExpression(currentModel, "modelId");
715
+ if (modelIdExpr) modelProperties.push({
716
+ name: "modelId",
717
+ value: extractPortableNodeFromExpression({
718
+ checker,
719
+ path: `${pathLabel}.model.modelId`
720
+ }, modelIdExpr, "type-fallback")
721
+ });
722
+ const optionsExpr = resolvePropertyExpression(currentModel, "options");
723
+ if (optionsExpr) {
724
+ const rawOptions = extractPortableNodeFromExpression({
725
+ checker,
726
+ path: `${pathLabel}.model.options`
727
+ }, optionsExpr, "type-fallback");
728
+ const filteredOptions = rawOptions.kind === "object" ? {
729
+ ...rawOptions,
730
+ properties: rawOptions.properties.filter((p) => !OMIT_MODEL_OPTION_KEYS.has(p.name))
731
+ } : rawOptions;
732
+ modelProperties.push({
733
+ name: "options",
734
+ value: filteredOptions
735
+ });
736
+ } else {
737
+ const optionsNode = extractModelOptionsNodeFromType(checker, checker.getTypeAtLocation(currentModel), `${pathLabel}.model`);
738
+ if (optionsNode) modelProperties.push({
739
+ name: "options",
740
+ value: optionsNode
741
+ });
742
+ }
743
+ const capsExpr = resolvePropertyExpression(currentModel, "caps");
744
+ if (!capsExpr) return fail(`${pathLabel}.model`, "model is missing 'caps'");
745
+ modelProperties.push({
746
+ name: "caps",
747
+ value: extractPortableNodeFromExpression({
748
+ checker,
749
+ path: `${pathLabel}.model.caps`
750
+ }, capsExpr, "type-fallback")
751
+ });
752
+ return {
753
+ kind: "object",
754
+ properties: modelProperties
755
+ };
756
+ }
757
+ const modelType = checker.getTypeAtLocation(currentModel);
758
+ const providerId = findPropertyInType(checker, modelType, "providerId");
759
+ if (providerId) modelProperties.push({
760
+ name: "providerId",
761
+ value: extractPortableNodeFromType(checker, providerId.type, `${pathLabel}.model.providerId`)
762
+ });
763
+ const modelId = findPropertyInType(checker, modelType, "modelId");
764
+ if (modelId) modelProperties.push({
765
+ name: "modelId",
766
+ value: extractPortableNodeFromType(checker, modelId.type, `${pathLabel}.model.modelId`)
767
+ });
768
+ const optionsNode = extractModelOptionsNodeFromType(checker, modelType, `${pathLabel}.model`);
769
+ if (optionsNode) modelProperties.push({
770
+ name: "options",
771
+ value: optionsNode
772
+ });
773
+ const caps = findPropertyInType(checker, modelType, "caps");
774
+ if (!caps) return fail(`${pathLabel}.model`, "model type is missing 'caps'");
775
+ modelProperties.push({
776
+ name: "caps",
777
+ value: extractPortableNodeFromType(checker, caps.type, `${pathLabel}.model.caps`)
778
+ });
779
+ return {
780
+ kind: "object",
781
+ properties: modelProperties
782
+ };
783
+ })();
784
+ const properties = [{
785
+ name: "name",
786
+ value: extractPortableNodeFromExpression({
787
+ checker,
788
+ path: `${pathLabel}.name`
789
+ }, nameSource.expression)
790
+ }, {
791
+ name: "model",
792
+ value: modelNode
793
+ }];
794
+ if (contextSchemaSource) properties.push({
795
+ name: "contextSchema",
796
+ value: extractPortableSchemaNodeFromExpression({
797
+ checker,
798
+ path: contextSchemaSource.path
799
+ }, contextSchemaSource.expression)
800
+ });
801
+ if (outputSchemaSource) properties.push({
802
+ name: "outputSchema",
803
+ value: extractOutputSchemaNode(checker, outputSchemaSource.expression, outputSchemaSource.path)
804
+ });
805
+ if (toolsSource) properties.push({
806
+ name: "tools",
807
+ value: extractToolsNode(checker, toolsSource.expression, toolsSource.path)
808
+ });
809
+ return {
810
+ kind: "object",
811
+ properties
812
+ };
813
+ };
814
+ const extractAgentsNode = (checker, expression, pathLabel) => {
815
+ const current = resolveExpressionReference(checker, expression);
816
+ if (!ts.isArrayLiteralExpression(current)) return fail(pathLabel, "agents must be declared as an array literal");
817
+ return {
818
+ kind: "tuple",
819
+ readonly: true,
820
+ elements: current.elements.map((element, index) => {
821
+ if (ts.isSpreadElement(element)) return fail(`${pathLabel}[${index}]`, "spread agents are not supported");
822
+ return extractAgentNode(checker, element, `${pathLabel}[${index}]`);
823
+ })
824
+ };
825
+ };
826
+ const extractAppToolsNode = (checker, expression, pathLabel) => extractToolsNode(checker, expression, pathLabel);
827
+ const extractPortableAppNode = (checker, declaration, label) => {
828
+ const configObject = extractAppConfigObject(checker, declaration, label);
829
+ const agentsSource = extractRequiredObjectProperty(configObject, "agents", checker, `${label}.config`);
830
+ const toolsSource = extractOptionalObjectProperty(configObject, "tools", checker, `${label}.config`);
831
+ const configProperties = [{
832
+ name: "agents",
833
+ value: extractAgentsNode(checker, agentsSource.expression, agentsSource.path)
834
+ }];
835
+ if (toolsSource) configProperties.push({
836
+ name: "tools",
837
+ value: extractAppToolsNode(checker, toolsSource.expression, toolsSource.path)
838
+ });
839
+ return {
840
+ kind: "object",
841
+ properties: [{
842
+ name: "config",
843
+ value: {
844
+ kind: "object",
845
+ properties: configProperties
846
+ }
847
+ }]
848
+ };
849
+ };
850
+ const toTypeIdentifier = (raw) => {
851
+ const cleaned = raw.replace(/[^A-Za-z0-9_$]/g, "_");
852
+ if (!cleaned) return DEFAULT_TYPE_NAME$1;
853
+ return /^[0-9]/.test(cleaned) ? `_${cleaned}` : cleaned;
854
+ };
855
+ const createUniqueTypeNames = (baseName, labels) => {
856
+ const used = /* @__PURE__ */ new Set();
857
+ return labels.map((label, index) => {
858
+ const preferred = toTypeIdentifier(labels.length === 1 ? baseName : `${baseName}_${label.replace(/[:/\\.]/g, "_")}`);
859
+ if (!used.has(preferred)) {
860
+ used.add(preferred);
861
+ return preferred;
862
+ }
863
+ let suffix = index + 1;
864
+ let candidate = `${preferred}_${suffix}`;
865
+ while (used.has(candidate)) {
866
+ suffix += 1;
867
+ candidate = `${preferred}_${suffix}`;
868
+ }
869
+ used.add(candidate);
870
+ return candidate;
871
+ });
872
+ };
873
+ const renderTypegenOutput = (apps, baseName) => {
874
+ const program = ts.createProgram([...new Set(apps.map((app) => app.configFile))], loadCompilerOptions(apps.map((app) => app.configFile)));
875
+ const checker = program.getTypeChecker();
876
+ const typeNames = createUniqueTypeNames(baseName, apps.map((app) => app.label));
877
+ return apps.map((app, index) => {
878
+ const sourceFile = program.getSourceFile(app.configFile);
879
+ if (!sourceFile) throw new Error(`Unable to load TypeScript source for ${app.configFile}`);
880
+ const exportSymbol = getExportSymbol(checker, sourceFile, app.exportPath);
881
+ if (!exportSymbol) throw new Error(`Unable to resolve export ${app.exportPath.join(".")} in ${app.configFile}`);
882
+ const declaration = exportSymbol.valueDeclaration ?? exportSymbol.declarations?.[0];
883
+ if (!declaration) throw new Error(`Unable to resolve declaration for ${app.label}`);
884
+ return renderTypeAlias(typeNames[index] ?? baseName, extractPortableAppNode(checker, declaration, app.label), app.label);
885
+ }).join("\n\n");
886
+ };
887
+
888
+ //#endregion
889
+ //#region src/typegen/selection.ts
890
+ const selectDiscoveredApps = async (apps, yes = false) => {
891
+ if (apps.length <= 1 || yes) return apps;
892
+ const response = await prompts({
893
+ type: "multiselect",
894
+ name: "selected",
895
+ message: "Select app export(s) to generate type(s) for (space to toggle, enter to confirm)",
896
+ instructions: "",
897
+ choices: apps.map((app) => ({
898
+ title: app.label,
899
+ value: app.label,
900
+ selected: true
901
+ }))
902
+ });
903
+ const selectedLabels = new Set(response.selected ?? []);
904
+ return apps.filter((app) => selectedLabels.has(app.label));
905
+ };
906
+
907
+ //#endregion
908
+ //#region src/typegen/write.ts
909
+ const isTestRuntime = () => process.env.NODE_ENV === "test" || process.env.BUN_TEST === "1" || process.env.VITEST === "true" || process.env.JEST_WORKER_ID !== void 0;
910
+ const createTypegenLogger = () => ({ info(message) {
911
+ if (isTestRuntime()) return;
912
+ console.log(message);
913
+ } });
914
+ const confirmOverwrite = async (message) => {
915
+ if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
916
+ const rl = createInterface({
917
+ input: process.stdin,
918
+ output: process.stdout
919
+ });
920
+ try {
921
+ const normalized = (await rl.question(`${message} (y/N) `)).trim().toLowerCase();
922
+ return normalized === "y" || normalized === "yes";
923
+ } finally {
924
+ rl.close();
925
+ }
926
+ };
927
+ const writeGeneratedTypes = async (params) => {
928
+ const exists = existsSync(params.outputPath);
929
+ if ((exists ? await fs.readFile(params.outputPath, "utf-8") : "").trim() === params.body.trim()) {
930
+ params.logger.info(chalk.dim(`Types already up to date: ${path.relative(params.cwd, params.outputPath)}`));
931
+ return 0;
932
+ }
933
+ if (exists && !params.yes) {
934
+ if (!await confirmOverwrite(`Overwrite ${path.relative(params.cwd, params.outputPath)}?`)) {
935
+ params.logger.info(chalk.dim("Type generation aborted."));
936
+ return 0;
937
+ }
938
+ }
939
+ await fs.mkdir(path.dirname(params.outputPath), { recursive: true });
940
+ await fs.writeFile(params.outputPath, params.body);
941
+ params.logger.info(chalk.green(`Types generated: ${path.relative(params.cwd, params.outputPath)}`));
942
+ return 0;
943
+ };
944
+
945
+ //#endregion
946
+ //#region src/typegen/command.ts
947
+ const COMMAND = "generate type";
948
+ const DEFAULT_OUTPUT = "better-agent.types.d.ts";
949
+ const DEFAULT_TYPE_NAME = "BAClientApp";
950
+ const writeError = (message) => process.stderr.write(`${message}\n`);
951
+ const writeBetterAgentError = (error) => {
952
+ writeError(chalk.red(`[${error.code}] ${error.message}`));
953
+ if (process.env.BA_DEBUG === "1") writeError(chalk.dim(JSON.stringify(error.toDebugJSON(), null, 2)));
954
+ };
955
+ const resolveTypegenRequest = (opts) => {
956
+ const cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd();
957
+ const configPaths = resolveConfigPaths(opts.config, cwd);
958
+ if (configPaths.length === 0) throw BetterAgentError.fromCode("BAD_REQUEST", "No config paths provided.", {
959
+ context: { command: COMMAND },
960
+ trace: [{ at: "cli.typegen.command.generateTypes.validateInput" }],
961
+ stackFrom: generateTypes
962
+ });
963
+ const existingPaths = existingConfigPaths(configPaths);
964
+ if (existingPaths.length === 0) throw BetterAgentError.fromCode("NOT_FOUND", "None of the provided config paths exist.", {
965
+ context: {
966
+ command: COMMAND,
967
+ configPaths: configPaths.map((configPath) => path.relative(cwd, configPath))
968
+ },
969
+ trace: [{ at: "cli.typegen.command.generateTypes.validatePaths" }],
970
+ stackFrom: generateTypes
971
+ });
972
+ return {
973
+ cwd,
974
+ existingPaths,
975
+ outputPath: path.resolve(cwd, opts.out ?? DEFAULT_OUTPUT),
976
+ typeName: toTypeIdentifier(opts.name ?? DEFAULT_TYPE_NAME),
977
+ yes: opts.yes ?? false
978
+ };
979
+ };
980
+ const generateTypes = async (opts) => {
981
+ const logger = createTypegenLogger();
982
+ try {
983
+ const request = resolveTypegenRequest(opts);
984
+ const selectedApps = await selectDiscoveredApps(await collectDiscoveredApps(request.existingPaths, request.cwd, writeBetterAgentError), request.yes);
985
+ if (selectedApps.length === 0) {
986
+ logger.info(chalk.dim("No app exports selected. Type generation aborted."));
987
+ return 0;
988
+ }
989
+ return await writeGeneratedTypes({
990
+ body: renderTypegenOutput(selectedApps.map(normalizeDiscoveredApp), request.typeName),
991
+ cwd: request.cwd,
992
+ outputPath: request.outputPath,
993
+ yes: request.yes,
994
+ logger
995
+ });
996
+ } catch (error) {
997
+ const wrapped = error instanceof BetterAgentError ? error : error instanceof TypegenRenderError ? BetterAgentError.fromCode("VALIDATION_FAILED", error.message, {
998
+ context: {
999
+ command: COMMAND,
1000
+ path: error.path
1001
+ },
1002
+ trace: [{ at: "cli.typegen.command.generateTypes.renderPortableType" }],
1003
+ stackFrom: generateTypes
1004
+ }) : BetterAgentError.wrap({
1005
+ err: error,
1006
+ message: "Type generate command failed",
1007
+ opts: {
1008
+ code: "INTERNAL",
1009
+ context: { command: COMMAND },
1010
+ trace: [{ at: "cli.typegen.command.generateTypes" }],
1011
+ stackFrom: generateTypes
1012
+ }
1013
+ });
1014
+ writeBetterAgentError(wrapped);
1015
+ if (wrapped.code === "BAD_REQUEST") writeError(chalk.dim("Example: better-agent generate type --config ./better-agent.ts"));
1016
+ return 1;
1017
+ }
1018
+ };
1019
+
1020
+ //#endregion
1021
+ //#region src/index.ts
1022
+ const cli = new Command();
1023
+ cli.name("better-agent").description("Better Agent CLI").version("0.0.1");
1024
+ cli.command("generate").description("Generate Better Agent type").command("type").description("Generate a portable client app type from Better Agent config exports").option("--config <path...>", "One or more Better Agent config paths (e.g. --config ./agents.ts ./libs/better-agent.ts)").option("--cwd <path>", "Base directory for resolving relative config paths", process.cwd()).option("--out <path>", "Generated .d.ts file path", "better-agent.types.d.ts").option("--name <identifier>", "Exported type alias name", "BAClientApp").option("--yes", "Skip prompts and overwrite output", false).action(async (opts) => {
1025
+ const code = await generateTypes(opts);
1026
+ process.exit(code);
1027
+ });
1028
+ cli.parse();
1029
+
1030
+ //#endregion
1031
+ export { };
1032
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["isRecord","DEFAULT_TYPE_NAME"],"sources":["../src/typegen/discovery.ts","../src/typegen/normalize.ts","../src/typegen/render.ts","../src/typegen/selection.ts","../src/typegen/write.ts","../src/typegen/command.ts","../src/index.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { BetterAgentError } from \"@better-agent/shared/errors\";\nimport { createJiti } from \"jiti\";\nimport type { DiscoveredApp, TypegenAppExport } from \"./types\";\n\nconst isRecord = (value: unknown): value is Record<PropertyKey, unknown> =>\n value !== null && typeof value === \"object\";\n\nconst isTypegenAppExport = (value: unknown): value is TypegenAppExport => {\n if (!isRecord(value)) return false;\n if (!isRecord(value.config)) return false;\n return (\n typeof value.run === \"function\" &&\n typeof value.stream === \"function\" &&\n typeof value.handler === \"function\"\n );\n};\n\nexport const resolveConfigPaths = (config: string[] | undefined, cwd: string) =>\n (config ?? []).map((configPath) =>\n path.isAbsolute(configPath) ? configPath : path.resolve(cwd, configPath),\n );\n\nexport const existingConfigPaths = (configPaths: string[]) =>\n configPaths.filter((configPath) => existsSync(configPath));\n\nconst withMutedConsole = async <T>(work: () => Promise<T>): Promise<T> => {\n const original = { log: console.log, info: console.info, warn: console.warn };\n console.log = () => {};\n console.info = () => {};\n console.warn = () => {};\n try {\n return await work();\n } finally {\n console.log = original.log;\n console.info = original.info;\n console.warn = original.warn;\n }\n};\n\nexport const collectDiscoveredApps = async (\n configPaths: string[],\n cwd: string,\n onImportError: (error: BetterAgentError) => void,\n): Promise<DiscoveredApp[]> => {\n const jiti = createJiti(import.meta.url, { extensions: [\".ts\", \".js\"] });\n const candidates: DiscoveredApp[] = [];\n let importErrors = 0;\n\n const collectExportedApp = (app: unknown, configFile: string, exportName: string) => {\n if (!isTypegenAppExport(app)) return false;\n candidates.push({\n app,\n configFile,\n exportPath: exportName.split(\".\"),\n label: `${path.relative(cwd, configFile)}:${exportName}`,\n });\n return true;\n };\n\n const exportedEntries = (mod: Record<string, unknown>) =>\n Object.entries(mod).flatMap(([exportName, value]) => {\n if (exportName !== \"default\" || !isRecord(value)) {\n return [[exportName, value] as const];\n }\n\n return [\n [exportName, value] as const,\n ...Object.entries(value).map(\n ([nestedName, nestedValue]) => [`default.${nestedName}`, nestedValue] as const,\n ),\n ];\n });\n\n for (const configPath of configPaths) {\n const configFile = path.isAbsolute(configPath) ? configPath : path.resolve(cwd, configPath);\n let mod: unknown;\n try {\n mod = await withMutedConsole(() => jiti.import(pathToFileURL(configFile).href));\n } catch (error) {\n onImportError(\n BetterAgentError.wrap({\n err: error,\n message: `Failed to load config: ${path.relative(cwd, configFile)}`,\n opts: {\n code: \"INTERNAL\",\n context: {\n command: \"generate type\",\n configPath: path.relative(cwd, configFile),\n },\n trace: [{ at: \"cli.typegen.discovery.collectDiscoveredApps.loadConfig\" }],\n stackFrom: collectDiscoveredApps,\n },\n }),\n );\n importErrors += 1;\n continue;\n }\n\n if (!isRecord(mod)) continue;\n for (const [exportName, value] of exportedEntries(mod)) {\n collectExportedApp(value, configFile, exportName);\n }\n }\n\n if (candidates.length > 0) return candidates;\n\n throw BetterAgentError.fromCode(\n \"NOT_FOUND\",\n \"No Better Agent app exports found in the provided config(s).\",\n {\n context: {\n command: \"generate type\",\n configCount: configPaths.length,\n importErrors,\n },\n trace: [{ at: \"cli.typegen.discovery.collectDiscoveredApps.findApps\" }],\n stackFrom: collectDiscoveredApps,\n },\n );\n};\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type { DiscoveredApp, TypegenAppReference } from \"./types\";\n\nconst isRecord = (value: unknown): value is Record<PropertyKey, unknown> =>\n value !== null && typeof value === \"object\";\n\nconst hasNamedAgents = (value: unknown) =>\n Array.isArray(value) &&\n value.some(\n (agent) => isRecord(agent) && typeof agent.name === \"string\" && agent.name.length > 0,\n );\n\nexport const normalizeDiscoveredApp = (candidate: DiscoveredApp): TypegenAppReference => {\n if (!hasNamedAgents(candidate.app.config.agents)) {\n throw BetterAgentError.fromCode(\"VALIDATION_FAILED\", \"App has no serializable agents.\", {\n trace: [{ at: \"cli.typegen.normalize.normalizeDiscoveredApp\" }],\n stackFrom: normalizeDiscoveredApp,\n });\n }\n\n return {\n configFile: candidate.configFile,\n exportPath: candidate.exportPath,\n label: candidate.label,\n };\n};\n","import path from \"node:path\";\nimport ts from \"typescript\";\nimport type { TypegenAppReference } from \"./types\";\n\nconst DEFAULT_TYPE_NAME = \"BAClientApp\";\nconst TYPE_FORMAT_FLAGS =\n ts.TypeFormatFlags.NoTruncation |\n ts.TypeFormatFlags.UseFullyQualifiedType |\n ts.TypeFormatFlags.WriteTypeArgumentsOfSignature |\n ts.TypeFormatFlags.MultilineObjectLiterals |\n ts.TypeFormatFlags.InTypeAlias;\n\ntype PortableNode =\n | { kind: \"literal\"; value: string | number | boolean | null }\n | { kind: \"keyword\"; value: \"string\" | \"number\" | \"boolean\" | \"unknown\" | \"null\" | \"undefined\" }\n | { kind: \"union\"; members: PortableNode[] }\n | { kind: \"object\"; properties: PortableProperty[] }\n | { kind: \"array\"; element: PortableNode; readonly: boolean }\n | { kind: \"tuple\"; elements: PortableNode[]; readonly: boolean };\n\ntype PortableProperty = {\n name: string;\n optional?: boolean;\n value: PortableNode;\n};\n\ntype ExtractContext = {\n checker: ts.TypeChecker;\n path: string;\n};\n\nexport class TypegenRenderError extends Error {\n path: string;\n\n constructor(path: string, message: string) {\n super(`${path}: ${message}`);\n this.name = \"TypegenRenderError\";\n this.path = path;\n }\n}\n\nconst toPropertyName = (value: string) =>\n /^[$A-Z_a-z][$\\w]*$/.test(value) ? value : JSON.stringify(value);\n\nconst loadCompilerOptions = (configFiles: string[]) => {\n const configPath = configFiles\n .map((configFile) => ts.findConfigFile(path.dirname(configFile), ts.sys.fileExists))\n .find((value): value is string => typeof value === \"string\");\n\n if (!configPath) {\n return {\n allowJs: true,\n checkJs: false,\n esModuleInterop: true,\n jsx: ts.JsxEmit.Preserve,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n resolveJsonModule: true,\n skipLibCheck: true,\n strict: false,\n target: ts.ScriptTarget.ES2022,\n } satisfies ts.CompilerOptions;\n }\n\n const parsed = ts.getParsedCommandLineOfConfigFile(\n configPath,\n {},\n {\n ...ts.sys,\n onUnRecoverableConfigFileDiagnostic: () => {},\n },\n );\n\n return parsed?.options ?? {};\n};\n\nconst isLiteralLike = (node: ts.Expression) =>\n ts.isStringLiteralLike(node) ||\n ts.isNumericLiteral(node) ||\n node.kind === ts.SyntaxKind.TrueKeyword ||\n node.kind === ts.SyntaxKind.FalseKeyword ||\n node.kind === ts.SyntaxKind.NullKeyword;\n\nconst unwrapExpression = (expression: ts.Expression): ts.Expression => {\n let current = expression;\n while (\n ts.isParenthesizedExpression(current) ||\n ts.isAsExpression(current) ||\n ts.isSatisfiesExpression(current) ||\n ts.isTypeAssertionExpression(current)\n ) {\n current = current.expression;\n }\n return current;\n};\n\nconst getExportSymbol = (\n checker: ts.TypeChecker,\n sourceFile: ts.SourceFile,\n exportPath: string[],\n): ts.Symbol | undefined => {\n const moduleSymbol = checker.getSymbolAtLocation(sourceFile);\n if (!moduleSymbol) return undefined;\n\n let currentSymbol = checker.getExportsOfModule(moduleSymbol).find((symbol) => {\n const name = symbol.escapedName.toString();\n return name === exportPath[0];\n });\n\n for (const segment of exportPath.slice(1)) {\n if (!currentSymbol) return undefined;\n const declaration = currentSymbol.valueDeclaration ?? currentSymbol.declarations?.[0];\n if (!declaration) return undefined;\n const currentType = checker.getTypeOfSymbolAtLocation(currentSymbol, declaration);\n currentSymbol = checker.getPropertyOfType(currentType, segment);\n }\n\n return currentSymbol;\n};\n\nconst renderPortableNode = (node: PortableNode, indent = 0): string => {\n const spacing = \" \".repeat(indent);\n\n switch (node.kind) {\n case \"literal\":\n return node.value === null ? \"null\" : JSON.stringify(node.value);\n case \"keyword\":\n return node.value;\n case \"union\":\n return node.members.map((member) => renderPortableNode(member, indent)).join(\" | \");\n case \"array\":\n return `${node.readonly ? \"readonly \" : \"\"}${renderPortableNode(node.element, indent)}[]`;\n case \"tuple\":\n return `${node.readonly ? \"readonly \" : \"\"}[${node.elements\n .map((element) => renderPortableNode(element, indent))\n .join(\", \")}]`;\n case \"object\":\n if (node.properties.length === 0) return \"{}\";\n return `{\\n${node.properties\n .map(\n (property) =>\n `${spacing} ${toPropertyName(property.name)}${property.optional ? \"?\" : \"\"}: ${renderPortableNode(property.value, indent + 4)};`,\n )\n .join(\"\\n\")}\\n${spacing}}`;\n }\n};\n\nconst renderTypeAlias = (typeName: string, node: PortableNode, label: string) =>\n `/** ${label} */\\nexport type ${typeName} = ${renderPortableNode(node)};`;\n\nconst formatCallableType = (checker: ts.TypeChecker, type: ts.Type) => {\n const rendered = checker.typeToString(type, undefined, TYPE_FORMAT_FLAGS);\n return rendered === \"{}\" ? \"unknown\" : rendered;\n};\n\nconst fail = (pathLabel: string, message: string): never => {\n throw new TypegenRenderError(pathLabel, message);\n};\n\nconst getPropertyAssignment = (objectLiteral: ts.ObjectLiteralExpression, name: string) =>\n objectLiteral.properties.find((property) => {\n if (\n !ts.isPropertyAssignment(property) &&\n !ts.isShorthandPropertyAssignment(property) &&\n !ts.isMethodDeclaration(property)\n ) {\n return false;\n }\n\n const propertyName =\n ts.isShorthandPropertyAssignment(property) || ts.isMethodDeclaration(property)\n ? property.name.getText()\n : ts.isIdentifier(property.name) ||\n ts.isStringLiteral(property.name) ||\n ts.isNumericLiteral(property.name)\n ? property.name.text\n : property.name.getText();\n\n return propertyName === name;\n });\n\nconst resolvePropertyExpression = (\n objectLiteral: ts.ObjectLiteralExpression,\n name: string,\n): ts.Expression | undefined => {\n const property = getPropertyAssignment(objectLiteral, name);\n if (!property) return undefined;\n if (ts.isPropertyAssignment(property)) return property.initializer;\n if (ts.isShorthandPropertyAssignment(property)) return property.name;\n return undefined;\n};\n\nconst getSymbolExpression = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n): ts.Expression | undefined => {\n let symbol =\n ts.isIdentifier(expression) && ts.isShorthandPropertyAssignment(expression.parent)\n ? checker.getShorthandAssignmentValueSymbol(expression.parent)\n : checker.getSymbolAtLocation(expression);\n if (!symbol) return undefined;\n\n // Imported/re-exported values are often alias symbols, resolve them to the underlying value symbol.\n while (symbol.flags & ts.SymbolFlags.Alias) {\n const aliased = checker.getAliasedSymbol(symbol);\n if (!aliased || aliased === symbol) break;\n symbol = aliased;\n }\n\n const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];\n if (!declaration) return undefined;\n\n if (ts.isVariableDeclaration(declaration)) {\n return declaration.initializer\n ? ts.isAsExpression(declaration.initializer) ||\n ts.isTypeAssertionExpression(declaration.initializer)\n ? declaration.initializer\n : declaration.initializer\n : undefined;\n }\n if (ts.isPropertyAssignment(declaration)) return declaration.initializer;\n if (ts.isShorthandPropertyAssignment(declaration)) return declaration.name;\n if (ts.isExportAssignment(declaration)) return declaration.expression;\n return undefined;\n};\n\nconst resolveExpressionReference = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n seen = new Set<ts.Node>(),\n): ts.Expression => {\n let current = unwrapExpression(expression);\n\n while (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {\n if (seen.has(current)) return current;\n seen.add(current);\n\n const resolved = getSymbolExpression(checker, current);\n if (!resolved) return current;\n current = unwrapExpression(resolved);\n }\n\n return current;\n};\n\nconst findPropertyInType = (\n checker: ts.TypeChecker,\n type: ts.Type,\n name: string,\n): { declaration: ts.Declaration | undefined; symbol: ts.Symbol; type: ts.Type } | undefined => {\n const property = checker.getPropertyOfType(type, name);\n if (!property) return undefined;\n const declaration = property.valueDeclaration ?? property.declarations?.[0];\n if (!declaration) return undefined;\n return {\n declaration,\n symbol: property,\n type: checker.getTypeOfSymbolAtLocation(property, declaration),\n };\n};\n\nconst OMIT_MODEL_OPTION_KEYS = new Set([\n \"input\",\n \"tools\",\n \"toolChoice\",\n \"structured_output\",\n \"modalities\",\n \"instructions\",\n \"text\",\n]);\n\nconst extractPortableObjectNodeFromProperties = (\n checker: ts.TypeChecker,\n type: ts.Type,\n pathLabel: string,\n properties: ts.Symbol[],\n seen = new Set<ts.Type>(),\n): PortableNode => {\n const nextSeen = new Set([...seen, type]);\n return {\n kind: \"object\",\n properties: properties.map((property) => {\n const declaration = property.valueDeclaration ?? property.declarations?.[0];\n if (!declaration)\n return fail(`${pathLabel}.${property.getName()}`, \"missing declaration\");\n return {\n name: property.getName(),\n optional: (property.flags & ts.SymbolFlags.Optional) !== 0,\n value: extractPortableNodeFromType(\n checker,\n checker.getTypeOfSymbolAtLocation(property, declaration),\n `${pathLabel}.${property.getName()}`,\n nextSeen,\n ),\n };\n }),\n };\n};\n\nconst extractModelOptionsNodeFromType = (\n checker: ts.TypeChecker,\n modelType: ts.Type,\n pathLabel: string,\n): PortableNode | undefined => {\n const options = findPropertyInType(checker, modelType, \"options\");\n if (options) {\n const optionsProperties = checker\n .getPropertiesOfType(options.type)\n .filter((property) => !OMIT_MODEL_OPTION_KEYS.has(property.getName()));\n if (optionsProperties.length === 0) {\n return { kind: \"object\", properties: [] } satisfies PortableNode;\n }\n return extractPortableObjectNodeFromProperties(\n checker,\n options.type,\n `${pathLabel}.options`,\n optionsProperties,\n );\n }\n\n const getOptionsFromMethod = (methodName: \"doGenerate\" | \"doGenerateStream\") => {\n const method = findPropertyInType(checker, modelType, methodName);\n if (!method?.declaration) return undefined;\n\n const methodType = checker.getTypeOfSymbolAtLocation(method.symbol, method.declaration);\n const callableType = checker.getNonNullableType(methodType);\n const signature = checker.getSignaturesOfType(callableType, ts.SignatureKind.Call)[0];\n const parameter = signature?.getParameters()[0];\n const parameterDeclaration = parameter?.valueDeclaration ?? parameter?.declarations?.[0];\n if (!parameter || !parameterDeclaration) return undefined;\n\n const parameterType = checker.getTypeOfSymbolAtLocation(parameter, parameterDeclaration);\n const optionProperties = checker\n .getPropertiesOfType(parameterType)\n .filter((property) => !OMIT_MODEL_OPTION_KEYS.has(property.getName()));\n\n if (optionProperties.length === 0) {\n return { kind: \"object\", properties: [] } satisfies PortableNode;\n }\n\n return extractPortableObjectNodeFromProperties(\n checker,\n parameterType,\n `${pathLabel}.options`,\n optionProperties,\n );\n };\n\n return getOptionsFromMethod(\"doGenerate\") ?? getOptionsFromMethod(\"doGenerateStream\");\n};\n\nconst dedupeUnionMembers = (members: PortableNode[]) => {\n const seen = new Set<string>();\n const deduped: PortableNode[] = [];\n for (const member of members) {\n const key = renderPortableNode(member);\n if (seen.has(key)) continue;\n seen.add(key);\n deduped.push(member);\n }\n return deduped;\n};\n\nconst getStandardTypesInputType = (\n checker: ts.TypeChecker,\n schemaType: ts.Type,\n): ts.Type | undefined => {\n const apparentType = checker.getApparentType(checker.getNonNullableType(schemaType));\n const standard = findPropertyInType(checker, apparentType, \"~standard\");\n if (!standard) return undefined;\n\n const types = findPropertyInType(checker, standard.type, \"types\");\n if (!types) return undefined;\n\n const typesType = checker.getApparentType(checker.getNonNullableType(types.type));\n return findPropertyInType(checker, typesType, \"input\")?.type;\n};\n\nconst hasStandardSchemaShape = (checker: ts.TypeChecker, schemaType: ts.Type): boolean =>\n !!findPropertyInType(\n checker,\n checker.getApparentType(checker.getNonNullableType(schemaType)),\n \"~standard\",\n );\n\nconst extractPortableNodeFromType = (\n checker: ts.TypeChecker,\n type: ts.Type,\n pathLabel: string,\n seen = new Set<ts.Type>(),\n): PortableNode => {\n if (seen.has(type)) {\n const rendered = formatCallableType(checker, type);\n switch (rendered) {\n case \"string\":\n case \"number\":\n case \"boolean\":\n case \"unknown\":\n return { kind: \"keyword\", value: rendered };\n case \"null\":\n return { kind: \"literal\", value: null };\n case \"undefined\":\n return { kind: \"keyword\", value: \"undefined\" };\n default:\n fail(pathLabel, `unsupported recursive type: ${rendered}`);\n }\n }\n\n if (type.isStringLiteral()) return { kind: \"literal\", value: type.value };\n if (type.isNumberLiteral()) return { kind: \"literal\", value: type.value };\n if (type.flags & ts.TypeFlags.BooleanLiteral) {\n return {\n kind: \"literal\",\n value: checker.typeToString(type) === \"true\",\n };\n }\n if (type.flags & ts.TypeFlags.Null) return { kind: \"literal\", value: null };\n if (type.flags & ts.TypeFlags.Undefined) return { kind: \"keyword\", value: \"undefined\" };\n if (type.flags & ts.TypeFlags.String) return { kind: \"keyword\", value: \"string\" };\n if (type.flags & ts.TypeFlags.Number) return { kind: \"keyword\", value: \"number\" };\n if (type.flags & ts.TypeFlags.Boolean) return { kind: \"keyword\", value: \"boolean\" };\n if (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) {\n return { kind: \"keyword\", value: \"unknown\" };\n }\n\n if (type.isUnion()) {\n return {\n kind: \"union\",\n members: dedupeUnionMembers(\n type.types.map((member, index) =>\n extractPortableNodeFromType(\n checker,\n member,\n `${pathLabel}|${index + 1}`,\n new Set([...seen, type]),\n ),\n ),\n ),\n };\n }\n\n if (checker.isTupleType(type)) {\n const typeReference = type as ts.TypeReference;\n return {\n kind: \"tuple\",\n readonly: true,\n elements: checker\n .getTypeArguments(typeReference)\n .map((entry, index) =>\n extractPortableNodeFromType(\n checker,\n entry,\n `${pathLabel}[${index}]`,\n new Set([...seen, type]),\n ),\n ),\n };\n }\n\n if (checker.isArrayType(type)) {\n const typeReference = type as ts.TypeReference;\n const [element] = checker.getTypeArguments(typeReference);\n if (!element) return fail(pathLabel, \"unsupported array element type\");\n return {\n kind: \"array\",\n readonly: true,\n element: extractPortableNodeFromType(\n checker,\n element,\n `${pathLabel}[]`,\n new Set([...seen, type]),\n ),\n };\n }\n\n const properties = checker.getPropertiesOfType(type);\n if (properties.length === 0) {\n const rendered = formatCallableType(checker, type);\n if (\n rendered.includes(\"[x: string]\") ||\n rendered.includes(\"[x:string]\") ||\n rendered === \"{}\"\n ) {\n return { kind: \"keyword\", value: \"unknown\" };\n }\n fail(pathLabel, `unsupported type: ${rendered}`);\n }\n\n const nextSeen = new Set([...seen, type]);\n return {\n kind: \"object\",\n properties: properties.map((property) => {\n const declaration = property.valueDeclaration ?? property.declarations?.[0];\n if (!declaration)\n return fail(`${pathLabel}.${property.getName()}`, \"missing declaration\");\n return {\n name: property.getName(),\n optional: (property.flags & ts.SymbolFlags.Optional) !== 0,\n value: extractPortableNodeFromType(\n checker,\n checker.getTypeOfSymbolAtLocation(property, declaration),\n `${pathLabel}.${property.getName()}`,\n nextSeen,\n ),\n };\n }),\n };\n};\n\nconst extractPortableNodeFromTypeNode = (\n checker: ts.TypeChecker,\n typeNode: ts.TypeNode,\n pathLabel: string,\n) => extractPortableNodeFromType(checker, checker.getTypeFromTypeNode(typeNode), pathLabel);\n\nconst extractPortableSchemaNodeFromExpression = (\n context: ExtractContext,\n expression: ts.Expression,\n): PortableNode => {\n const current = resolveExpressionReference(context.checker, expression);\n const schemaType = context.checker.getTypeAtLocation(current);\n const standardInputType = getStandardTypesInputType(context.checker, schemaType);\n\n if (standardInputType) {\n return extractPortableNodeFromType(\n context.checker,\n standardInputType,\n `${context.path}.~standard.types.input`,\n );\n }\n\n if (hasStandardSchemaShape(context.checker, schemaType)) {\n return fail(\n context.path,\n \"standard schema must expose '~standard.types.input' for portable type generation\",\n );\n }\n\n return extractPortableNodeFromExpression(context, current);\n};\n\nconst extractPortableNodeFromExpression = (\n context: ExtractContext,\n expression: ts.Expression,\n mode: \"strict\" | \"type-fallback\" = \"strict\",\n): PortableNode => {\n const current = unwrapExpression(expression);\n\n if (ts.isAsExpression(expression) || ts.isTypeAssertionExpression(expression)) {\n return extractPortableNodeFromTypeNode(context.checker, expression.type, context.path);\n }\n\n if (isLiteralLike(current)) {\n if (ts.isStringLiteralLike(current)) return { kind: \"literal\", value: current.text };\n if (ts.isNumericLiteral(current)) return { kind: \"literal\", value: Number(current.text) };\n if (current.kind === ts.SyntaxKind.TrueKeyword) return { kind: \"literal\", value: true };\n if (current.kind === ts.SyntaxKind.FalseKeyword) return { kind: \"literal\", value: false };\n return { kind: \"literal\", value: null };\n }\n\n if (ts.isObjectLiteralExpression(current)) {\n const properties: PortableProperty[] = [];\n\n for (const property of current.properties) {\n if (ts.isSpreadAssignment(property)) {\n fail(\n context.path,\n \"spread properties are not supported in portable type generation\",\n );\n }\n if (ts.isMethodDeclaration(property)) continue;\n\n let name: string;\n let initializer: ts.Expression;\n\n if (ts.isPropertyAssignment(property)) {\n name =\n ts.isIdentifier(property.name) ||\n ts.isStringLiteral(property.name) ||\n ts.isNumericLiteral(property.name)\n ? property.name.text\n : property.name.getText();\n initializer = property.initializer;\n } else if (ts.isShorthandPropertyAssignment(property)) {\n name = property.name.text;\n initializer = property.name;\n } else {\n continue;\n }\n\n properties.push({\n name,\n value: extractPortableNodeFromExpression(\n { checker: context.checker, path: `${context.path}.${name}` },\n initializer,\n mode,\n ),\n });\n }\n\n return { kind: \"object\", properties };\n }\n\n if (ts.isArrayLiteralExpression(current)) {\n return {\n kind: \"tuple\",\n readonly: true,\n elements: current.elements.map((element, index) => {\n if (ts.isSpreadElement(element)) {\n fail(`${context.path}[${index}]`, \"spread elements are not supported\");\n }\n return extractPortableNodeFromExpression(\n { checker: context.checker, path: `${context.path}[${index}]` },\n element,\n mode,\n );\n }),\n };\n }\n\n if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {\n const resolved = getSymbolExpression(context.checker, current);\n if (resolved) {\n return extractPortableNodeFromExpression(context, resolved, mode);\n }\n }\n\n if (ts.isCallExpression(current)) {\n const firstArg = current.arguments[0];\n if (firstArg && ts.isObjectLiteralExpression(unwrapExpression(firstArg))) {\n return extractPortableNodeFromExpression(context, firstArg, mode);\n }\n\n if (mode === \"type-fallback\") {\n return extractPortableNodeFromType(\n context.checker,\n context.checker.getTypeAtLocation(current),\n context.path,\n );\n }\n }\n\n if (mode === \"type-fallback\") {\n return extractPortableNodeFromType(\n context.checker,\n context.checker.getTypeAtLocation(current),\n context.path,\n );\n }\n\n return fail(context.path, `unsupported expression: ${current.getText()}`);\n};\n\nconst extractOutputSchemaNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode => {\n const current = resolveExpressionReference(checker, expression);\n if (!ts.isObjectLiteralExpression(current)) {\n return fail(pathLabel, \"outputSchema must resolve to an object literal\");\n }\n\n const schemaExpression = resolvePropertyExpression(current, \"schema\");\n if (!schemaExpression) {\n return fail(pathLabel, \"outputSchema is missing 'schema'\");\n }\n\n const properties: PortableProperty[] = [\n {\n name: \"schema\",\n value: extractPortableSchemaNodeFromExpression(\n { checker, path: `${pathLabel}.schema` },\n schemaExpression,\n ),\n },\n ];\n\n const nameExpression = resolvePropertyExpression(current, \"name\");\n if (nameExpression) {\n properties.push({\n name: \"name\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.name` },\n nameExpression,\n \"type-fallback\",\n ),\n });\n }\n\n const strictExpression = resolvePropertyExpression(current, \"strict\");\n if (strictExpression) {\n properties.push({\n name: \"strict\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.strict` },\n strictExpression,\n \"type-fallback\",\n ),\n });\n }\n\n return {\n kind: \"object\",\n properties,\n };\n};\n\nconst extractAppConfigObject = (\n checker: ts.TypeChecker,\n declaration: ts.Declaration,\n label: string,\n): ts.ObjectLiteralExpression => {\n const fromExpression = (expression: ts.Expression): ts.ObjectLiteralExpression | undefined => {\n const current = unwrapExpression(expression);\n\n if (ts.isObjectLiteralExpression(current)) {\n const configExpr = resolvePropertyExpression(current, \"config\");\n if (!configExpr) return undefined;\n const configCurrent = unwrapExpression(configExpr);\n return ts.isObjectLiteralExpression(configCurrent) ? configCurrent : undefined;\n }\n\n if (ts.isCallExpression(current)) {\n const firstArg = current.arguments[0];\n if (!firstArg) return undefined;\n const configCurrent = unwrapExpression(firstArg);\n return ts.isObjectLiteralExpression(configCurrent) ? configCurrent : undefined;\n }\n\n if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {\n const resolved = getSymbolExpression(checker, current);\n return resolved ? fromExpression(resolved) : undefined;\n }\n\n return undefined;\n };\n\n const expression =\n ts.isVariableDeclaration(declaration) && declaration.initializer\n ? declaration.initializer\n : ts.isExportAssignment(declaration)\n ? declaration.expression\n : undefined;\n\n const configObject = expression ? fromExpression(expression) : undefined;\n if (!configObject) {\n return fail(label, \"unable to locate a portable app config object\");\n }\n return configObject;\n};\n\nconst extractRequiredObjectProperty = (\n objectLiteral: ts.ObjectLiteralExpression,\n name: string,\n checker: ts.TypeChecker,\n pathLabel: string,\n) => {\n const expression = resolvePropertyExpression(objectLiteral, name);\n if (!expression) return fail(pathLabel, `missing required property '${name}'`);\n return { checker, expression: unwrapExpression(expression), path: `${pathLabel}.${name}` };\n};\n\nconst extractOptionalObjectProperty = (\n objectLiteral: ts.ObjectLiteralExpression,\n name: string,\n checker: ts.TypeChecker,\n pathLabel: string,\n) => {\n const expression = resolvePropertyExpression(objectLiteral, name);\n return expression\n ? { checker, expression: unwrapExpression(expression), path: `${pathLabel}.${name}` }\n : undefined;\n};\n\nconst extractClientToolNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode | undefined => {\n const current = unwrapExpression(expression);\n\n if (ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)) {\n const resolved = getSymbolExpression(checker, current);\n return resolved ? extractClientToolNode(checker, resolved, pathLabel) : undefined;\n }\n\n if (ts.isObjectLiteralExpression(current)) {\n const kindExpression = resolvePropertyExpression(current, \"kind\");\n const kindNode = kindExpression\n ? extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.kind` },\n kindExpression,\n \"type-fallback\",\n )\n : undefined;\n\n if (\n !kindNode ||\n kindNode.kind !== \"literal\" ||\n typeof kindNode.value !== \"string\" ||\n kindNode.value !== \"client\"\n ) {\n return undefined;\n }\n\n const nameExpression = resolvePropertyExpression(current, \"name\");\n const schemaExpression = resolvePropertyExpression(current, \"schema\");\n if (!nameExpression || !schemaExpression) {\n return fail(pathLabel, \"client tool is missing 'name' or 'schema'\");\n }\n\n return {\n kind: \"object\",\n properties: [\n {\n name: \"kind\",\n value: { kind: \"literal\", value: \"client\" },\n },\n {\n name: \"name\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.name` },\n nameExpression,\n \"type-fallback\",\n ),\n },\n {\n name: \"schema\",\n value: extractPortableSchemaNodeFromExpression(\n { checker, path: `${pathLabel}.schema` },\n schemaExpression,\n ),\n },\n ],\n };\n }\n\n if (ts.isCallExpression(current) && ts.isPropertyAccessExpression(current.expression)) {\n const methodName = current.expression.name.text;\n if (methodName === \"client\") {\n const baseCall = resolveExpressionReference(checker, current.expression.expression);\n if (ts.isCallExpression(baseCall)) {\n const configArg = baseCall.arguments[0];\n const configObject =\n configArg && ts.isObjectLiteralExpression(unwrapExpression(configArg))\n ? (unwrapExpression(configArg) as ts.ObjectLiteralExpression)\n : undefined;\n\n if (configObject) {\n const nameExpression = resolvePropertyExpression(configObject, \"name\");\n const schemaExpression = resolvePropertyExpression(configObject, \"schema\");\n if (!nameExpression || !schemaExpression) {\n return fail(\n pathLabel,\n \"defineTool(...).client() is missing 'name' or 'schema'\",\n );\n }\n\n return {\n kind: \"object\",\n properties: [\n { name: \"kind\", value: { kind: \"literal\", value: \"client\" } },\n {\n name: \"name\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.name` },\n nameExpression,\n \"type-fallback\",\n ),\n },\n {\n name: \"schema\",\n value: extractPortableSchemaNodeFromExpression(\n { checker, path: `${pathLabel}.schema` },\n schemaExpression,\n ),\n },\n ],\n };\n }\n }\n }\n }\n\n const toolType = checker.getTypeAtLocation(current);\n const kindProperty = findPropertyInType(checker, toolType, \"kind\");\n if (!kindProperty) return undefined;\n\n const kindNode = extractPortableNodeFromType(checker, kindProperty.type, `${pathLabel}.kind`);\n if (\n kindNode.kind !== \"literal\" ||\n typeof kindNode.value !== \"string\" ||\n kindNode.value !== \"client\"\n ) {\n return undefined;\n }\n\n const nameProperty = findPropertyInType(checker, toolType, \"name\");\n const schemaProperty = findPropertyInType(checker, toolType, \"schema\");\n if (!nameProperty || !schemaProperty) {\n return fail(pathLabel, \"client tool type is missing 'name' or 'schema'\");\n }\n\n return {\n kind: \"object\",\n properties: [\n { name: \"kind\", value: { kind: \"literal\", value: \"client\" } },\n {\n name: \"name\",\n value: extractPortableNodeFromType(checker, nameProperty.type, `${pathLabel}.name`),\n },\n {\n name: \"schema\",\n value: extractPortableNodeFromType(\n checker,\n schemaProperty.type,\n `${pathLabel}.schema`,\n ),\n },\n ],\n };\n};\n\nconst extractToolsNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode => {\n const current = resolveExpressionReference(checker, expression);\n if (!ts.isArrayLiteralExpression(current)) {\n return fail(pathLabel, \"tools must be declared as an array literal\");\n }\n\n const clientTools = current.elements.flatMap((element, index) => {\n if (ts.isSpreadElement(element)) {\n return fail(`${pathLabel}[${index}]`, \"spread tools are not supported\");\n }\n\n const toolNode = extractClientToolNode(checker, element, `${pathLabel}[${index}]`);\n return toolNode ? [toolNode] : [];\n });\n\n return {\n kind: \"tuple\",\n readonly: true,\n elements: clientTools,\n };\n};\n\nconst extractAgentNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode => {\n const current = unwrapExpression(expression);\n const resolved =\n ts.isIdentifier(current) || ts.isPropertyAccessExpression(current)\n ? getSymbolExpression(checker, current)\n : current;\n const target = resolved ? unwrapExpression(resolved) : current;\n\n const agentObject = ts.isCallExpression(target)\n ? target.arguments[0]\n : ts.isObjectLiteralExpression(target)\n ? target\n : undefined;\n\n if (!agentObject || !ts.isObjectLiteralExpression(unwrapExpression(agentObject))) {\n return fail(pathLabel, \"agents must resolve to object literals or defineAgent(...) calls\");\n }\n\n const objectLiteral = unwrapExpression(agentObject) as ts.ObjectLiteralExpression;\n const nameSource = extractRequiredObjectProperty(objectLiteral, \"name\", checker, pathLabel);\n const modelSource = extractRequiredObjectProperty(objectLiteral, \"model\", checker, pathLabel);\n const contextSchemaSource = extractOptionalObjectProperty(\n objectLiteral,\n \"contextSchema\",\n checker,\n pathLabel,\n );\n const outputSchemaSource = extractOptionalObjectProperty(\n objectLiteral,\n \"outputSchema\",\n checker,\n pathLabel,\n );\n const toolsSource = extractOptionalObjectProperty(objectLiteral, \"tools\", checker, pathLabel);\n\n const modelNode = (() => {\n const modelProperties: PortableProperty[] = [];\n const currentModel = unwrapExpression(modelSource.expression);\n if (ts.isObjectLiteralExpression(currentModel)) {\n const providerIdExpr = resolvePropertyExpression(currentModel, \"providerId\");\n if (providerIdExpr) {\n modelProperties.push({\n name: \"providerId\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.model.providerId` },\n providerIdExpr,\n \"type-fallback\",\n ),\n });\n }\n\n const modelIdExpr = resolvePropertyExpression(currentModel, \"modelId\");\n if (modelIdExpr) {\n modelProperties.push({\n name: \"modelId\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.model.modelId` },\n modelIdExpr,\n \"type-fallback\",\n ),\n });\n }\n\n const optionsExpr = resolvePropertyExpression(currentModel, \"options\");\n if (optionsExpr) {\n const rawOptions = extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.model.options` },\n optionsExpr,\n \"type-fallback\",\n );\n // Filter out keys that are managed and have agnostic equivalents.\n const filteredOptions =\n rawOptions.kind === \"object\"\n ? {\n ...rawOptions,\n properties: rawOptions.properties.filter(\n (p) => !OMIT_MODEL_OPTION_KEYS.has(p.name),\n ),\n }\n : rawOptions;\n modelProperties.push({\n name: \"options\",\n value: filteredOptions,\n });\n } else {\n const optionsNode = extractModelOptionsNodeFromType(\n checker,\n checker.getTypeAtLocation(currentModel),\n `${pathLabel}.model`,\n );\n if (optionsNode) {\n modelProperties.push({\n name: \"options\",\n value: optionsNode,\n });\n }\n }\n\n const capsExpr = resolvePropertyExpression(currentModel, \"caps\");\n if (!capsExpr) return fail(`${pathLabel}.model`, \"model is missing 'caps'\");\n modelProperties.push({\n name: \"caps\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.model.caps` },\n capsExpr,\n \"type-fallback\",\n ),\n });\n\n return {\n kind: \"object\",\n properties: modelProperties,\n } satisfies PortableNode;\n }\n\n const modelType = checker.getTypeAtLocation(currentModel);\n const providerId = findPropertyInType(checker, modelType, \"providerId\");\n if (providerId) {\n modelProperties.push({\n name: \"providerId\",\n value: extractPortableNodeFromType(\n checker,\n providerId.type,\n `${pathLabel}.model.providerId`,\n ),\n });\n }\n\n const modelId = findPropertyInType(checker, modelType, \"modelId\");\n if (modelId) {\n modelProperties.push({\n name: \"modelId\",\n value: extractPortableNodeFromType(\n checker,\n modelId.type,\n `${pathLabel}.model.modelId`,\n ),\n });\n }\n\n const optionsNode = extractModelOptionsNodeFromType(\n checker,\n modelType,\n `${pathLabel}.model`,\n );\n if (optionsNode) {\n modelProperties.push({\n name: \"options\",\n value: optionsNode,\n });\n }\n\n const caps = findPropertyInType(checker, modelType, \"caps\");\n if (!caps) return fail(`${pathLabel}.model`, \"model type is missing 'caps'\");\n modelProperties.push({\n name: \"caps\",\n value: extractPortableNodeFromType(checker, caps.type, `${pathLabel}.model.caps`),\n });\n\n return {\n kind: \"object\",\n properties: modelProperties,\n } satisfies PortableNode;\n })();\n\n const properties: PortableProperty[] = [\n {\n name: \"name\",\n value: extractPortableNodeFromExpression(\n { checker, path: `${pathLabel}.name` },\n nameSource.expression,\n ),\n },\n { name: \"model\", value: modelNode },\n ];\n\n if (contextSchemaSource) {\n properties.push({\n name: \"contextSchema\",\n value: extractPortableSchemaNodeFromExpression(\n { checker, path: contextSchemaSource.path },\n contextSchemaSource.expression,\n ),\n });\n }\n\n if (outputSchemaSource) {\n properties.push({\n name: \"outputSchema\",\n value: extractOutputSchemaNode(\n checker,\n outputSchemaSource.expression,\n outputSchemaSource.path,\n ),\n });\n }\n\n if (toolsSource) {\n properties.push({\n name: \"tools\",\n value: extractToolsNode(checker, toolsSource.expression, toolsSource.path),\n });\n }\n\n return { kind: \"object\", properties };\n};\n\nconst extractAgentsNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode => {\n const current = resolveExpressionReference(checker, expression);\n if (!ts.isArrayLiteralExpression(current)) {\n return fail(pathLabel, \"agents must be declared as an array literal\");\n }\n\n return {\n kind: \"tuple\",\n readonly: true,\n elements: current.elements.map((element: ts.Expression, index: number) => {\n if (ts.isSpreadElement(element)) {\n return fail(`${pathLabel}[${index}]`, \"spread agents are not supported\");\n }\n return extractAgentNode(checker, element, `${pathLabel}[${index}]`);\n }),\n };\n};\n\nconst extractAppToolsNode = (\n checker: ts.TypeChecker,\n expression: ts.Expression,\n pathLabel: string,\n): PortableNode => extractToolsNode(checker, expression, pathLabel);\n\nconst extractPortableAppNode = (\n checker: ts.TypeChecker,\n declaration: ts.Declaration,\n label: string,\n): PortableNode => {\n const configObject = extractAppConfigObject(checker, declaration, label);\n const agentsSource = extractRequiredObjectProperty(\n configObject,\n \"agents\",\n checker,\n `${label}.config`,\n );\n const toolsSource = extractOptionalObjectProperty(\n configObject,\n \"tools\",\n checker,\n `${label}.config`,\n );\n\n const configProperties: PortableProperty[] = [\n {\n name: \"agents\",\n value: extractAgentsNode(checker, agentsSource.expression, agentsSource.path),\n },\n ];\n\n if (toolsSource) {\n configProperties.push({\n name: \"tools\",\n value: extractAppToolsNode(checker, toolsSource.expression, toolsSource.path),\n });\n }\n\n return {\n kind: \"object\",\n properties: [\n {\n name: \"config\",\n value: {\n kind: \"object\",\n properties: configProperties,\n },\n },\n ],\n };\n};\n\nexport const toTypeIdentifier = (raw: string) => {\n const cleaned = raw.replace(/[^A-Za-z0-9_$]/g, \"_\");\n if (!cleaned) return DEFAULT_TYPE_NAME;\n return /^[0-9]/.test(cleaned) ? `_${cleaned}` : cleaned;\n};\n\nconst createUniqueTypeNames = (baseName: string, labels: string[]) => {\n const used = new Set<string>();\n return labels.map((label, index) => {\n const preferred = toTypeIdentifier(\n labels.length === 1 ? baseName : `${baseName}_${label.replace(/[:/\\\\.]/g, \"_\")}`,\n );\n if (!used.has(preferred)) {\n used.add(preferred);\n return preferred;\n }\n let suffix = index + 1;\n let candidate = `${preferred}_${suffix}`;\n while (used.has(candidate)) {\n suffix += 1;\n candidate = `${preferred}_${suffix}`;\n }\n used.add(candidate);\n return candidate;\n });\n};\n\nexport const renderTypegenOutput = (apps: TypegenAppReference[], baseName: string): string => {\n const program = ts.createProgram(\n [...new Set(apps.map((app) => app.configFile))],\n loadCompilerOptions(apps.map((app) => app.configFile)),\n );\n const checker = program.getTypeChecker();\n\n const typeNames = createUniqueTypeNames(\n baseName,\n apps.map((app) => app.label),\n );\n\n const sections = apps.map((app, index) => {\n const sourceFile = program.getSourceFile(app.configFile);\n if (!sourceFile) {\n throw new Error(`Unable to load TypeScript source for ${app.configFile}`);\n }\n\n const exportSymbol = getExportSymbol(checker, sourceFile, app.exportPath);\n if (!exportSymbol) {\n throw new Error(\n `Unable to resolve export ${app.exportPath.join(\".\")} in ${app.configFile}`,\n );\n }\n\n const declaration = exportSymbol.valueDeclaration ?? exportSymbol.declarations?.[0];\n if (!declaration) {\n throw new Error(`Unable to resolve declaration for ${app.label}`);\n }\n\n const typeName = typeNames[index] ?? baseName;\n const appNode = extractPortableAppNode(checker, declaration, app.label);\n return renderTypeAlias(typeName, appNode, app.label);\n });\n\n return sections.join(\"\\n\\n\");\n};\n","import prompts from \"prompts\";\nimport type { DiscoveredApp } from \"./types\";\n\nexport const selectDiscoveredApps = async (apps: DiscoveredApp[], yes = false) => {\n if (apps.length <= 1 || yes) return apps;\n\n const response = await prompts({\n type: \"multiselect\",\n name: \"selected\",\n message: \"Select app export(s) to generate type(s) for (space to toggle, enter to confirm)\",\n instructions: \"\",\n choices: apps.map((app) => ({\n title: app.label,\n value: app.label,\n selected: true,\n })),\n });\n\n const selectedLabels = new Set<string>(response.selected ?? []);\n return apps.filter((app) => selectedLabels.has(app.label));\n};\n","import { existsSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\n\nconst isTestRuntime = () =>\n process.env.NODE_ENV === \"test\" ||\n process.env.BUN_TEST === \"1\" ||\n process.env.VITEST === \"true\" ||\n process.env.JEST_WORKER_ID !== undefined;\n\nexport const createTypegenLogger = () => ({\n info(message: string) {\n if (isTestRuntime()) return;\n console.log(message);\n },\n});\n\nconst confirmOverwrite = async (message: string) => {\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n return false;\n }\n\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n\n try {\n const answer = await rl.question(`${message} (y/N) `);\n const normalized = answer.trim().toLowerCase();\n return normalized === \"y\" || normalized === \"yes\";\n } finally {\n rl.close();\n }\n};\n\nexport const writeGeneratedTypes = async (params: {\n body: string;\n cwd: string;\n outputPath: string;\n yes: boolean;\n logger: ReturnType<typeof createTypegenLogger>;\n}) => {\n const exists = existsSync(params.outputPath);\n const current = exists ? await fs.readFile(params.outputPath, \"utf-8\") : \"\";\n\n if (current.trim() === params.body.trim()) {\n params.logger.info(\n chalk.dim(`Types already up to date: ${path.relative(params.cwd, params.outputPath)}`),\n );\n return 0;\n }\n\n if (exists && !params.yes) {\n const confirmed = await confirmOverwrite(\n `Overwrite ${path.relative(params.cwd, params.outputPath)}?`,\n );\n if (!confirmed) {\n params.logger.info(chalk.dim(\"Type generation aborted.\"));\n return 0;\n }\n }\n\n await fs.mkdir(path.dirname(params.outputPath), { recursive: true });\n await fs.writeFile(params.outputPath, params.body);\n params.logger.info(\n chalk.green(`Types generated: ${path.relative(params.cwd, params.outputPath)}`),\n );\n return 0;\n};\n","import path from \"node:path\";\nimport { BetterAgentError } from \"@better-agent/shared/errors\";\nimport chalk from \"chalk\";\nimport { collectDiscoveredApps, existingConfigPaths, resolveConfigPaths } from \"./discovery\";\nimport { normalizeDiscoveredApp } from \"./normalize\";\nimport { TypegenRenderError, renderTypegenOutput, toTypeIdentifier } from \"./render\";\nimport { selectDiscoveredApps } from \"./selection\";\nimport type { GenerateTypeOptions } from \"./types\";\nimport { createTypegenLogger, writeGeneratedTypes } from \"./write\";\n\nconst COMMAND = \"generate type\";\nconst DEFAULT_OUTPUT = \"better-agent.types.d.ts\";\nconst DEFAULT_TYPE_NAME = \"BAClientApp\";\n\nconst writeError = (message: string) => process.stderr.write(`${message}\\n`);\n\nconst writeBetterAgentError = (error: BetterAgentError) => {\n writeError(chalk.red(`[${error.code}] ${error.message}`));\n if (process.env.BA_DEBUG === \"1\") {\n writeError(chalk.dim(JSON.stringify(error.toDebugJSON(), null, 2)));\n }\n};\n\nconst resolveTypegenRequest = (opts: GenerateTypeOptions) => {\n const cwd = opts.cwd ? path.resolve(opts.cwd) : process.cwd();\n const configPaths = resolveConfigPaths(opts.config, cwd);\n\n // Validate the CLI input before loading any config files.\n if (configPaths.length === 0) {\n throw BetterAgentError.fromCode(\"BAD_REQUEST\", \"No config paths provided.\", {\n context: { command: COMMAND },\n trace: [{ at: \"cli.typegen.command.generateTypes.validateInput\" }],\n stackFrom: generateTypes,\n });\n }\n\n const existingPaths = existingConfigPaths(configPaths);\n if (existingPaths.length === 0) {\n throw BetterAgentError.fromCode(\"NOT_FOUND\", \"None of the provided config paths exist.\", {\n context: {\n command: COMMAND,\n configPaths: configPaths.map((configPath) => path.relative(cwd, configPath)),\n },\n trace: [{ at: \"cli.typegen.command.generateTypes.validatePaths\" }],\n stackFrom: generateTypes,\n });\n }\n\n return {\n cwd,\n existingPaths,\n outputPath: path.resolve(cwd, opts.out ?? DEFAULT_OUTPUT),\n typeName: toTypeIdentifier(opts.name ?? DEFAULT_TYPE_NAME),\n yes: opts.yes ?? false,\n };\n};\n\nexport const generateTypes = async (opts: GenerateTypeOptions): Promise<number> => {\n const logger = createTypegenLogger();\n\n try {\n const request = resolveTypegenRequest(opts);\n\n // Discover app exports, narrow them to the selected apps, then render and write the output.\n const discoveredApps = await collectDiscoveredApps(\n request.existingPaths,\n request.cwd,\n writeBetterAgentError,\n );\n const selectedApps = await selectDiscoveredApps(discoveredApps, request.yes);\n if (selectedApps.length === 0) {\n logger.info(chalk.dim(\"No app exports selected. Type generation aborted.\"));\n return 0;\n }\n\n const normalizedApps = selectedApps.map(normalizeDiscoveredApp);\n const body = renderTypegenOutput(normalizedApps, request.typeName);\n return await writeGeneratedTypes({\n body,\n cwd: request.cwd,\n outputPath: request.outputPath,\n yes: request.yes,\n logger,\n });\n } catch (error) {\n const wrapped =\n error instanceof BetterAgentError\n ? error\n : error instanceof TypegenRenderError\n ? BetterAgentError.fromCode(\"VALIDATION_FAILED\", error.message, {\n context: { command: COMMAND, path: error.path },\n trace: [{ at: \"cli.typegen.command.generateTypes.renderPortableType\" }],\n stackFrom: generateTypes,\n })\n : BetterAgentError.wrap({\n err: error,\n message: \"Type generate command failed\",\n opts: {\n code: \"INTERNAL\",\n context: { command: COMMAND },\n trace: [{ at: \"cli.typegen.command.generateTypes\" }],\n stackFrom: generateTypes,\n },\n });\n\n writeBetterAgentError(wrapped);\n if (wrapped.code === \"BAD_REQUEST\") {\n writeError(chalk.dim(\"Example: better-agent generate type --config ./better-agent.ts\"));\n }\n return 1;\n }\n};\n","#!/usr/bin/env node\nimport { Command } from \"commander\";\nimport { generateTypes } from \"./typegen/command\";\n\nconst cli = new Command();\n\ncli.name(\"better-agent\").description(\"Better Agent CLI\").version(\"0.0.1\");\n\nconst generateCommand = cli.command(\"generate\").description(\"Generate Better Agent type\");\n\ngenerateCommand\n .command(\"type\")\n .description(\"Generate a portable client app type from Better Agent config exports\")\n .option(\n \"--config <path...>\",\n \"One or more Better Agent config paths (e.g. --config ./agents.ts ./libs/better-agent.ts)\",\n )\n .option(\"--cwd <path>\", \"Base directory for resolving relative config paths\", process.cwd())\n .option(\"--out <path>\", \"Generated .d.ts file path\", \"better-agent.types.d.ts\")\n .option(\"--name <identifier>\", \"Exported type alias name\", \"BAClientApp\")\n .option(\"--yes\", \"Skip prompts and overwrite output\", false)\n .action(async (opts) => {\n const code = await generateTypes(opts);\n process.exit(code);\n });\n\ncli.parse();\n"],"mappings":";;;;;;;;;;;;;;AAOA,MAAMA,cAAY,UACd,UAAU,QAAQ,OAAO,UAAU;AAEvC,MAAM,sBAAsB,UAA8C;AACtE,KAAI,CAACA,WAAS,MAAM,CAAE,QAAO;AAC7B,KAAI,CAACA,WAAS,MAAM,OAAO,CAAE,QAAO;AACpC,QACI,OAAO,MAAM,QAAQ,cACrB,OAAO,MAAM,WAAW,cACxB,OAAO,MAAM,YAAY;;AAIjC,MAAa,sBAAsB,QAA8B,SAC5D,UAAU,EAAE,EAAE,KAAK,eAChB,KAAK,WAAW,WAAW,GAAG,aAAa,KAAK,QAAQ,KAAK,WAAW,CAC3E;AAEL,MAAa,uBAAuB,gBAChC,YAAY,QAAQ,eAAe,WAAW,WAAW,CAAC;AAE9D,MAAM,mBAAmB,OAAU,SAAuC;CACtE,MAAM,WAAW;EAAE,KAAK,QAAQ;EAAK,MAAM,QAAQ;EAAM,MAAM,QAAQ;EAAM;AAC7E,SAAQ,YAAY;AACpB,SAAQ,aAAa;AACrB,SAAQ,aAAa;AACrB,KAAI;AACA,SAAO,MAAM,MAAM;WACb;AACN,UAAQ,MAAM,SAAS;AACvB,UAAQ,OAAO,SAAS;AACxB,UAAQ,OAAO,SAAS;;;AAIhC,MAAa,wBAAwB,OACjC,aACA,KACA,kBAC2B;CAC3B,MAAM,OAAO,WAAW,OAAO,KAAK,KAAK,EAAE,YAAY,CAAC,OAAO,MAAM,EAAE,CAAC;CACxE,MAAM,aAA8B,EAAE;CACtC,IAAI,eAAe;CAEnB,MAAM,sBAAsB,KAAc,YAAoB,eAAuB;AACjF,MAAI,CAAC,mBAAmB,IAAI,CAAE,QAAO;AACrC,aAAW,KAAK;GACZ;GACA;GACA,YAAY,WAAW,MAAM,IAAI;GACjC,OAAO,GAAG,KAAK,SAAS,KAAK,WAAW,CAAC,GAAG;GAC/C,CAAC;AACF,SAAO;;CAGX,MAAM,mBAAmB,QACrB,OAAO,QAAQ,IAAI,CAAC,SAAS,CAAC,YAAY,WAAW;AACjD,MAAI,eAAe,aAAa,CAACA,WAAS,MAAM,CAC5C,QAAO,CAAC,CAAC,YAAY,MAAM,CAAU;AAGzC,SAAO,CACH,CAAC,YAAY,MAAM,EACnB,GAAG,OAAO,QAAQ,MAAM,CAAC,KACpB,CAAC,YAAY,iBAAiB,CAAC,WAAW,cAAc,YAAY,CACxE,CACJ;GACH;AAEN,MAAK,MAAM,cAAc,aAAa;EAClC,MAAM,aAAa,KAAK,WAAW,WAAW,GAAG,aAAa,KAAK,QAAQ,KAAK,WAAW;EAC3F,IAAI;AACJ,MAAI;AACA,SAAM,MAAM,uBAAuB,KAAK,OAAO,cAAc,WAAW,CAAC,KAAK,CAAC;WAC1E,OAAO;AACZ,iBACI,iBAAiB,KAAK;IAClB,KAAK;IACL,SAAS,0BAA0B,KAAK,SAAS,KAAK,WAAW;IACjE,MAAM;KACF,MAAM;KACN,SAAS;MACL,SAAS;MACT,YAAY,KAAK,SAAS,KAAK,WAAW;MAC7C;KACD,OAAO,CAAC,EAAE,IAAI,0DAA0D,CAAC;KACzE,WAAW;KACd;IACJ,CAAC,CACL;AACD,mBAAgB;AAChB;;AAGJ,MAAI,CAACA,WAAS,IAAI,CAAE;AACpB,OAAK,MAAM,CAAC,YAAY,UAAU,gBAAgB,IAAI,CAClD,oBAAmB,OAAO,YAAY,WAAW;;AAIzD,KAAI,WAAW,SAAS,EAAG,QAAO;AAElC,OAAM,iBAAiB,SACnB,aACA,gEACA;EACI,SAAS;GACL,SAAS;GACT,aAAa,YAAY;GACzB;GACH;EACD,OAAO,CAAC,EAAE,IAAI,wDAAwD,CAAC;EACvE,WAAW;EACd,CACJ;;;;;ACtHL,MAAM,YAAY,UACd,UAAU,QAAQ,OAAO,UAAU;AAEvC,MAAM,kBAAkB,UACpB,MAAM,QAAQ,MAAM,IACpB,MAAM,MACD,UAAU,SAAS,MAAM,IAAI,OAAO,MAAM,SAAS,YAAY,MAAM,KAAK,SAAS,EACvF;AAEL,MAAa,0BAA0B,cAAkD;AACrF,KAAI,CAAC,eAAe,UAAU,IAAI,OAAO,OAAO,CAC5C,OAAM,iBAAiB,SAAS,qBAAqB,mCAAmC;EACpF,OAAO,CAAC,EAAE,IAAI,gDAAgD,CAAC;EAC/D,WAAW;EACd,CAAC;AAGN,QAAO;EACH,YAAY,UAAU;EACtB,YAAY,UAAU;EACtB,OAAO,UAAU;EACpB;;;;;ACpBL,MAAMC,sBAAoB;AAC1B,MAAM,oBACF,GAAG,gBAAgB,eACnB,GAAG,gBAAgB,wBACnB,GAAG,gBAAgB,gCACnB,GAAG,gBAAgB,0BACnB,GAAG,gBAAgB;AAqBvB,IAAa,qBAAb,cAAwC,MAAM;CAC1C;CAEA,YAAY,MAAc,SAAiB;AACvC,QAAM,GAAG,KAAK,IAAI,UAAU;AAC5B,OAAK,OAAO;AACZ,OAAK,OAAO;;;AAIpB,MAAM,kBAAkB,UACpB,qBAAqB,KAAK,MAAM,GAAG,QAAQ,KAAK,UAAU,MAAM;AAEpE,MAAM,uBAAuB,gBAA0B;CACnD,MAAM,aAAa,YACd,KAAK,eAAe,GAAG,eAAe,KAAK,QAAQ,WAAW,EAAE,GAAG,IAAI,WAAW,CAAC,CACnF,MAAM,UAA2B,OAAO,UAAU,SAAS;AAEhE,KAAI,CAAC,WACD,QAAO;EACH,SAAS;EACT,SAAS;EACT,iBAAiB;EACjB,KAAK,GAAG,QAAQ;EAChB,QAAQ,GAAG,WAAW;EACtB,kBAAkB,GAAG,qBAAqB;EAC1C,mBAAmB;EACnB,cAAc;EACd,QAAQ;EACR,QAAQ,GAAG,aAAa;EAC3B;AAYL,QATe,GAAG,iCACd,YACA,EAAE,EACF;EACI,GAAG,GAAG;EACN,2CAA2C;EAC9C,CACJ,EAEc,WAAW,EAAE;;AAGhC,MAAM,iBAAiB,SACnB,GAAG,oBAAoB,KAAK,IAC5B,GAAG,iBAAiB,KAAK,IACzB,KAAK,SAAS,GAAG,WAAW,eAC5B,KAAK,SAAS,GAAG,WAAW,gBAC5B,KAAK,SAAS,GAAG,WAAW;AAEhC,MAAM,oBAAoB,eAA6C;CACnE,IAAI,UAAU;AACd,QACI,GAAG,0BAA0B,QAAQ,IACrC,GAAG,eAAe,QAAQ,IAC1B,GAAG,sBAAsB,QAAQ,IACjC,GAAG,0BAA0B,QAAQ,CAErC,WAAU,QAAQ;AAEtB,QAAO;;AAGX,MAAM,mBACF,SACA,YACA,eACwB;CACxB,MAAM,eAAe,QAAQ,oBAAoB,WAAW;AAC5D,KAAI,CAAC,aAAc,QAAO;CAE1B,IAAI,gBAAgB,QAAQ,mBAAmB,aAAa,CAAC,MAAM,WAAW;AAE1E,SADa,OAAO,YAAY,UAAU,KAC1B,WAAW;GAC7B;AAEF,MAAK,MAAM,WAAW,WAAW,MAAM,EAAE,EAAE;AACvC,MAAI,CAAC,cAAe,QAAO;EAC3B,MAAM,cAAc,cAAc,oBAAoB,cAAc,eAAe;AACnF,MAAI,CAAC,YAAa,QAAO;EACzB,MAAM,cAAc,QAAQ,0BAA0B,eAAe,YAAY;AACjF,kBAAgB,QAAQ,kBAAkB,aAAa,QAAQ;;AAGnE,QAAO;;AAGX,MAAM,sBAAsB,MAAoB,SAAS,MAAc;CACnE,MAAM,UAAU,IAAI,OAAO,OAAO;AAElC,SAAQ,KAAK,MAAb;EACI,KAAK,UACD,QAAO,KAAK,UAAU,OAAO,SAAS,KAAK,UAAU,KAAK,MAAM;EACpE,KAAK,UACD,QAAO,KAAK;EAChB,KAAK,QACD,QAAO,KAAK,QAAQ,KAAK,WAAW,mBAAmB,QAAQ,OAAO,CAAC,CAAC,KAAK,MAAM;EACvF,KAAK,QACD,QAAO,GAAG,KAAK,WAAW,cAAc,KAAK,mBAAmB,KAAK,SAAS,OAAO,CAAC;EAC1F,KAAK,QACD,QAAO,GAAG,KAAK,WAAW,cAAc,GAAG,GAAG,KAAK,SAC9C,KAAK,YAAY,mBAAmB,SAAS,OAAO,CAAC,CACrD,KAAK,KAAK,CAAC;EACpB,KAAK;AACD,OAAI,KAAK,WAAW,WAAW,EAAG,QAAO;AACzC,UAAO,MAAM,KAAK,WACb,KACI,aACG,GAAG,QAAQ,MAAM,eAAe,SAAS,KAAK,GAAG,SAAS,WAAW,MAAM,GAAG,IAAI,mBAAmB,SAAS,OAAO,SAAS,EAAE,CAAC,GACxI,CACA,KAAK,KAAK,CAAC,IAAI,QAAQ;;;AAIxC,MAAM,mBAAmB,UAAkB,MAAoB,UAC3D,OAAO,MAAM,mBAAmB,SAAS,KAAK,mBAAmB,KAAK,CAAC;AAE3E,MAAM,sBAAsB,SAAyB,SAAkB;CACnE,MAAM,WAAW,QAAQ,aAAa,MAAM,QAAW,kBAAkB;AACzE,QAAO,aAAa,OAAO,YAAY;;AAG3C,MAAM,QAAQ,WAAmB,YAA2B;AACxD,OAAM,IAAI,mBAAmB,WAAW,QAAQ;;AAGpD,MAAM,yBAAyB,eAA2C,SACtE,cAAc,WAAW,MAAM,aAAa;AACxC,KACI,CAAC,GAAG,qBAAqB,SAAS,IAClC,CAAC,GAAG,8BAA8B,SAAS,IAC3C,CAAC,GAAG,oBAAoB,SAAS,CAEjC,QAAO;AAYX,SARI,GAAG,8BAA8B,SAAS,IAAI,GAAG,oBAAoB,SAAS,GACxE,SAAS,KAAK,SAAS,GACvB,GAAG,aAAa,SAAS,KAAK,IAC5B,GAAG,gBAAgB,SAAS,KAAK,IACjC,GAAG,iBAAiB,SAAS,KAAK,GAClC,SAAS,KAAK,OACd,SAAS,KAAK,SAAS,MAEX;EAC1B;AAEN,MAAM,6BACF,eACA,SAC4B;CAC5B,MAAM,WAAW,sBAAsB,eAAe,KAAK;AAC3D,KAAI,CAAC,SAAU,QAAO;AACtB,KAAI,GAAG,qBAAqB,SAAS,CAAE,QAAO,SAAS;AACvD,KAAI,GAAG,8BAA8B,SAAS,CAAE,QAAO,SAAS;;AAIpE,MAAM,uBACF,SACA,eAC4B;CAC5B,IAAI,SACA,GAAG,aAAa,WAAW,IAAI,GAAG,8BAA8B,WAAW,OAAO,GAC5E,QAAQ,kCAAkC,WAAW,OAAO,GAC5D,QAAQ,oBAAoB,WAAW;AACjD,KAAI,CAAC,OAAQ,QAAO;AAGpB,QAAO,OAAO,QAAQ,GAAG,YAAY,OAAO;EACxC,MAAM,UAAU,QAAQ,iBAAiB,OAAO;AAChD,MAAI,CAAC,WAAW,YAAY,OAAQ;AACpC,WAAS;;CAGb,MAAM,cAAc,QAAQ,oBAAoB,QAAQ,eAAe;AACvE,KAAI,CAAC,YAAa,QAAO;AAEzB,KAAI,GAAG,sBAAsB,YAAY,CACrC,QAAO,YAAY,cACb,GAAG,eAAe,YAAY,YAAY,IAC1C,GAAG,0BAA0B,YAAY,YAAY,GACjD,YAAY,cACZ,YAAY,cAChB;AAEV,KAAI,GAAG,qBAAqB,YAAY,CAAE,QAAO,YAAY;AAC7D,KAAI,GAAG,8BAA8B,YAAY,CAAE,QAAO,YAAY;AACtE,KAAI,GAAG,mBAAmB,YAAY,CAAE,QAAO,YAAY;;AAI/D,MAAM,8BACF,SACA,YACA,uBAAO,IAAI,KAAc,KACT;CAChB,IAAI,UAAU,iBAAiB,WAAW;AAE1C,QAAO,GAAG,aAAa,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,EAAE;AACvE,MAAI,KAAK,IAAI,QAAQ,CAAE,QAAO;AAC9B,OAAK,IAAI,QAAQ;EAEjB,MAAM,WAAW,oBAAoB,SAAS,QAAQ;AACtD,MAAI,CAAC,SAAU,QAAO;AACtB,YAAU,iBAAiB,SAAS;;AAGxC,QAAO;;AAGX,MAAM,sBACF,SACA,MACA,SAC4F;CAC5F,MAAM,WAAW,QAAQ,kBAAkB,MAAM,KAAK;AACtD,KAAI,CAAC,SAAU,QAAO;CACtB,MAAM,cAAc,SAAS,oBAAoB,SAAS,eAAe;AACzE,KAAI,CAAC,YAAa,QAAO;AACzB,QAAO;EACH;EACA,QAAQ;EACR,MAAM,QAAQ,0BAA0B,UAAU,YAAY;EACjE;;AAGL,MAAM,yBAAyB,IAAI,IAAI;CACnC;CACA;CACA;CACA;CACA;CACA;CACA;CACH,CAAC;AAEF,MAAM,2CACF,SACA,MACA,WACA,YACA,uBAAO,IAAI,KAAc,KACV;CACf,MAAM,WAAW,IAAI,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC;AACzC,QAAO;EACH,MAAM;EACN,YAAY,WAAW,KAAK,aAAa;GACrC,MAAM,cAAc,SAAS,oBAAoB,SAAS,eAAe;AACzE,OAAI,CAAC,YACD,QAAO,KAAK,GAAG,UAAU,GAAG,SAAS,SAAS,IAAI,sBAAsB;AAC5E,UAAO;IACH,MAAM,SAAS,SAAS;IACxB,WAAW,SAAS,QAAQ,GAAG,YAAY,cAAc;IACzD,OAAO,4BACH,SACA,QAAQ,0BAA0B,UAAU,YAAY,EACxD,GAAG,UAAU,GAAG,SAAS,SAAS,IAClC,SACH;IACJ;IACH;EACL;;AAGL,MAAM,mCACF,SACA,WACA,cAC2B;CAC3B,MAAM,UAAU,mBAAmB,SAAS,WAAW,UAAU;AACjE,KAAI,SAAS;EACT,MAAM,oBAAoB,QACrB,oBAAoB,QAAQ,KAAK,CACjC,QAAQ,aAAa,CAAC,uBAAuB,IAAI,SAAS,SAAS,CAAC,CAAC;AAC1E,MAAI,kBAAkB,WAAW,EAC7B,QAAO;GAAE,MAAM;GAAU,YAAY,EAAE;GAAE;AAE7C,SAAO,wCACH,SACA,QAAQ,MACR,GAAG,UAAU,WACb,kBACH;;CAGL,MAAM,wBAAwB,eAAkD;EAC5E,MAAM,SAAS,mBAAmB,SAAS,WAAW,WAAW;AACjE,MAAI,CAAC,QAAQ,YAAa,QAAO;EAEjC,MAAM,aAAa,QAAQ,0BAA0B,OAAO,QAAQ,OAAO,YAAY;EACvF,MAAM,eAAe,QAAQ,mBAAmB,WAAW;EAE3D,MAAM,YADY,QAAQ,oBAAoB,cAAc,GAAG,cAAc,KAAK,CAAC,IACtD,eAAe,CAAC;EAC7C,MAAM,uBAAuB,WAAW,oBAAoB,WAAW,eAAe;AACtF,MAAI,CAAC,aAAa,CAAC,qBAAsB,QAAO;EAEhD,MAAM,gBAAgB,QAAQ,0BAA0B,WAAW,qBAAqB;EACxF,MAAM,mBAAmB,QACpB,oBAAoB,cAAc,CAClC,QAAQ,aAAa,CAAC,uBAAuB,IAAI,SAAS,SAAS,CAAC,CAAC;AAE1E,MAAI,iBAAiB,WAAW,EAC5B,QAAO;GAAE,MAAM;GAAU,YAAY,EAAE;GAAE;AAG7C,SAAO,wCACH,SACA,eACA,GAAG,UAAU,WACb,iBACH;;AAGL,QAAO,qBAAqB,aAAa,IAAI,qBAAqB,mBAAmB;;AAGzF,MAAM,sBAAsB,YAA4B;CACpD,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,UAA0B,EAAE;AAClC,MAAK,MAAM,UAAU,SAAS;EAC1B,MAAM,MAAM,mBAAmB,OAAO;AACtC,MAAI,KAAK,IAAI,IAAI,CAAE;AACnB,OAAK,IAAI,IAAI;AACb,UAAQ,KAAK,OAAO;;AAExB,QAAO;;AAGX,MAAM,6BACF,SACA,eACsB;CAEtB,MAAM,WAAW,mBAAmB,SADf,QAAQ,gBAAgB,QAAQ,mBAAmB,WAAW,CAAC,EACzB,YAAY;AACvE,KAAI,CAAC,SAAU,QAAO;CAEtB,MAAM,QAAQ,mBAAmB,SAAS,SAAS,MAAM,QAAQ;AACjE,KAAI,CAAC,MAAO,QAAO;AAGnB,QAAO,mBAAmB,SADR,QAAQ,gBAAgB,QAAQ,mBAAmB,MAAM,KAAK,CAAC,EACnC,QAAQ,EAAE;;AAG5D,MAAM,0BAA0B,SAAyB,eACrD,CAAC,CAAC,mBACE,SACA,QAAQ,gBAAgB,QAAQ,mBAAmB,WAAW,CAAC,EAC/D,YACH;AAEL,MAAM,+BACF,SACA,MACA,WACA,uBAAO,IAAI,KAAc,KACV;AACf,KAAI,KAAK,IAAI,KAAK,EAAE;EAChB,MAAM,WAAW,mBAAmB,SAAS,KAAK;AAClD,UAAQ,UAAR;GACI,KAAK;GACL,KAAK;GACL,KAAK;GACL,KAAK,UACD,QAAO;IAAE,MAAM;IAAW,OAAO;IAAU;GAC/C,KAAK,OACD,QAAO;IAAE,MAAM;IAAW,OAAO;IAAM;GAC3C,KAAK,YACD,QAAO;IAAE,MAAM;IAAW,OAAO;IAAa;GAClD,QACI,MAAK,WAAW,+BAA+B,WAAW;;;AAItE,KAAI,KAAK,iBAAiB,CAAE,QAAO;EAAE,MAAM;EAAW,OAAO,KAAK;EAAO;AACzE,KAAI,KAAK,iBAAiB,CAAE,QAAO;EAAE,MAAM;EAAW,OAAO,KAAK;EAAO;AACzE,KAAI,KAAK,QAAQ,GAAG,UAAU,eAC1B,QAAO;EACH,MAAM;EACN,OAAO,QAAQ,aAAa,KAAK,KAAK;EACzC;AAEL,KAAI,KAAK,QAAQ,GAAG,UAAU,KAAM,QAAO;EAAE,MAAM;EAAW,OAAO;EAAM;AAC3E,KAAI,KAAK,QAAQ,GAAG,UAAU,UAAW,QAAO;EAAE,MAAM;EAAW,OAAO;EAAa;AACvF,KAAI,KAAK,QAAQ,GAAG,UAAU,OAAQ,QAAO;EAAE,MAAM;EAAW,OAAO;EAAU;AACjF,KAAI,KAAK,QAAQ,GAAG,UAAU,OAAQ,QAAO;EAAE,MAAM;EAAW,OAAO;EAAU;AACjF,KAAI,KAAK,QAAQ,GAAG,UAAU,QAAS,QAAO;EAAE,MAAM;EAAW,OAAO;EAAW;AACnF,KAAI,KAAK,SAAS,GAAG,UAAU,MAAM,GAAG,UAAU,SAC9C,QAAO;EAAE,MAAM;EAAW,OAAO;EAAW;AAGhD,KAAI,KAAK,SAAS,CACd,QAAO;EACH,MAAM;EACN,SAAS,mBACL,KAAK,MAAM,KAAK,QAAQ,UACpB,4BACI,SACA,QACA,GAAG,UAAU,GAAG,QAAQ,KACxB,IAAI,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,CAC3B,CACJ,CACJ;EACJ;AAGL,KAAI,QAAQ,YAAY,KAAK,EAAE;EAC3B,MAAM,gBAAgB;AACtB,SAAO;GACH,MAAM;GACN,UAAU;GACV,UAAU,QACL,iBAAiB,cAAc,CAC/B,KAAK,OAAO,UACT,4BACI,SACA,OACA,GAAG,UAAU,GAAG,MAAM,IACtB,IAAI,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,CAC3B,CACJ;GACR;;AAGL,KAAI,QAAQ,YAAY,KAAK,EAAE;EAC3B,MAAM,gBAAgB;EACtB,MAAM,CAAC,WAAW,QAAQ,iBAAiB,cAAc;AACzD,MAAI,CAAC,QAAS,QAAO,KAAK,WAAW,iCAAiC;AACtE,SAAO;GACH,MAAM;GACN,UAAU;GACV,SAAS,4BACL,SACA,SACA,GAAG,UAAU,KACb,IAAI,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC,CAC3B;GACJ;;CAGL,MAAM,aAAa,QAAQ,oBAAoB,KAAK;AACpD,KAAI,WAAW,WAAW,GAAG;EACzB,MAAM,WAAW,mBAAmB,SAAS,KAAK;AAClD,MACI,SAAS,SAAS,cAAc,IAChC,SAAS,SAAS,aAAa,IAC/B,aAAa,KAEb,QAAO;GAAE,MAAM;GAAW,OAAO;GAAW;AAEhD,OAAK,WAAW,qBAAqB,WAAW;;CAGpD,MAAM,WAAW,IAAI,IAAI,CAAC,GAAG,MAAM,KAAK,CAAC;AACzC,QAAO;EACH,MAAM;EACN,YAAY,WAAW,KAAK,aAAa;GACrC,MAAM,cAAc,SAAS,oBAAoB,SAAS,eAAe;AACzE,OAAI,CAAC,YACD,QAAO,KAAK,GAAG,UAAU,GAAG,SAAS,SAAS,IAAI,sBAAsB;AAC5E,UAAO;IACH,MAAM,SAAS,SAAS;IACxB,WAAW,SAAS,QAAQ,GAAG,YAAY,cAAc;IACzD,OAAO,4BACH,SACA,QAAQ,0BAA0B,UAAU,YAAY,EACxD,GAAG,UAAU,GAAG,SAAS,SAAS,IAClC,SACH;IACJ;IACH;EACL;;AAGL,MAAM,mCACF,SACA,UACA,cACC,4BAA4B,SAAS,QAAQ,oBAAoB,SAAS,EAAE,UAAU;AAE3F,MAAM,2CACF,SACA,eACe;CACf,MAAM,UAAU,2BAA2B,QAAQ,SAAS,WAAW;CACvE,MAAM,aAAa,QAAQ,QAAQ,kBAAkB,QAAQ;CAC7D,MAAM,oBAAoB,0BAA0B,QAAQ,SAAS,WAAW;AAEhF,KAAI,kBACA,QAAO,4BACH,QAAQ,SACR,mBACA,GAAG,QAAQ,KAAK,wBACnB;AAGL,KAAI,uBAAuB,QAAQ,SAAS,WAAW,CACnD,QAAO,KACH,QAAQ,MACR,mFACH;AAGL,QAAO,kCAAkC,SAAS,QAAQ;;AAG9D,MAAM,qCACF,SACA,YACA,OAAmC,aACpB;CACf,MAAM,UAAU,iBAAiB,WAAW;AAE5C,KAAI,GAAG,eAAe,WAAW,IAAI,GAAG,0BAA0B,WAAW,CACzE,QAAO,gCAAgC,QAAQ,SAAS,WAAW,MAAM,QAAQ,KAAK;AAG1F,KAAI,cAAc,QAAQ,EAAE;AACxB,MAAI,GAAG,oBAAoB,QAAQ,CAAE,QAAO;GAAE,MAAM;GAAW,OAAO,QAAQ;GAAM;AACpF,MAAI,GAAG,iBAAiB,QAAQ,CAAE,QAAO;GAAE,MAAM;GAAW,OAAO,OAAO,QAAQ,KAAK;GAAE;AACzF,MAAI,QAAQ,SAAS,GAAG,WAAW,YAAa,QAAO;GAAE,MAAM;GAAW,OAAO;GAAM;AACvF,MAAI,QAAQ,SAAS,GAAG,WAAW,aAAc,QAAO;GAAE,MAAM;GAAW,OAAO;GAAO;AACzF,SAAO;GAAE,MAAM;GAAW,OAAO;GAAM;;AAG3C,KAAI,GAAG,0BAA0B,QAAQ,EAAE;EACvC,MAAM,aAAiC,EAAE;AAEzC,OAAK,MAAM,YAAY,QAAQ,YAAY;AACvC,OAAI,GAAG,mBAAmB,SAAS,CAC/B,MACI,QAAQ,MACR,kEACH;AAEL,OAAI,GAAG,oBAAoB,SAAS,CAAE;GAEtC,IAAI;GACJ,IAAI;AAEJ,OAAI,GAAG,qBAAqB,SAAS,EAAE;AACnC,WACI,GAAG,aAAa,SAAS,KAAK,IAC9B,GAAG,gBAAgB,SAAS,KAAK,IACjC,GAAG,iBAAiB,SAAS,KAAK,GAC5B,SAAS,KAAK,OACd,SAAS,KAAK,SAAS;AACjC,kBAAc,SAAS;cAChB,GAAG,8BAA8B,SAAS,EAAE;AACnD,WAAO,SAAS,KAAK;AACrB,kBAAc,SAAS;SAEvB;AAGJ,cAAW,KAAK;IACZ;IACA,OAAO,kCACH;KAAE,SAAS,QAAQ;KAAS,MAAM,GAAG,QAAQ,KAAK,GAAG;KAAQ,EAC7D,aACA,KACH;IACJ,CAAC;;AAGN,SAAO;GAAE,MAAM;GAAU;GAAY;;AAGzC,KAAI,GAAG,yBAAyB,QAAQ,CACpC,QAAO;EACH,MAAM;EACN,UAAU;EACV,UAAU,QAAQ,SAAS,KAAK,SAAS,UAAU;AAC/C,OAAI,GAAG,gBAAgB,QAAQ,CAC3B,MAAK,GAAG,QAAQ,KAAK,GAAG,MAAM,IAAI,oCAAoC;AAE1E,UAAO,kCACH;IAAE,SAAS,QAAQ;IAAS,MAAM,GAAG,QAAQ,KAAK,GAAG,MAAM;IAAI,EAC/D,SACA,KACH;IACH;EACL;AAGL,KAAI,GAAG,aAAa,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,EAAE;EACpE,MAAM,WAAW,oBAAoB,QAAQ,SAAS,QAAQ;AAC9D,MAAI,SACA,QAAO,kCAAkC,SAAS,UAAU,KAAK;;AAIzE,KAAI,GAAG,iBAAiB,QAAQ,EAAE;EAC9B,MAAM,WAAW,QAAQ,UAAU;AACnC,MAAI,YAAY,GAAG,0BAA0B,iBAAiB,SAAS,CAAC,CACpE,QAAO,kCAAkC,SAAS,UAAU,KAAK;AAGrE,MAAI,SAAS,gBACT,QAAO,4BACH,QAAQ,SACR,QAAQ,QAAQ,kBAAkB,QAAQ,EAC1C,QAAQ,KACX;;AAIT,KAAI,SAAS,gBACT,QAAO,4BACH,QAAQ,SACR,QAAQ,QAAQ,kBAAkB,QAAQ,EAC1C,QAAQ,KACX;AAGL,QAAO,KAAK,QAAQ,MAAM,2BAA2B,QAAQ,SAAS,GAAG;;AAG7E,MAAM,2BACF,SACA,YACA,cACe;CACf,MAAM,UAAU,2BAA2B,SAAS,WAAW;AAC/D,KAAI,CAAC,GAAG,0BAA0B,QAAQ,CACtC,QAAO,KAAK,WAAW,iDAAiD;CAG5E,MAAM,mBAAmB,0BAA0B,SAAS,SAAS;AACrE,KAAI,CAAC,iBACD,QAAO,KAAK,WAAW,mCAAmC;CAG9D,MAAM,aAAiC,CACnC;EACI,MAAM;EACN,OAAO,wCACH;GAAE;GAAS,MAAM,GAAG,UAAU;GAAU,EACxC,iBACH;EACJ,CACJ;CAED,MAAM,iBAAiB,0BAA0B,SAAS,OAAO;AACjE,KAAI,eACA,YAAW,KAAK;EACZ,MAAM;EACN,OAAO,kCACH;GAAE;GAAS,MAAM,GAAG,UAAU;GAAQ,EACtC,gBACA,gBACH;EACJ,CAAC;CAGN,MAAM,mBAAmB,0BAA0B,SAAS,SAAS;AACrE,KAAI,iBACA,YAAW,KAAK;EACZ,MAAM;EACN,OAAO,kCACH;GAAE;GAAS,MAAM,GAAG,UAAU;GAAU,EACxC,kBACA,gBACH;EACJ,CAAC;AAGN,QAAO;EACH,MAAM;EACN;EACH;;AAGL,MAAM,0BACF,SACA,aACA,UAC6B;CAC7B,MAAM,kBAAkB,eAAsE;EAC1F,MAAM,UAAU,iBAAiB,WAAW;AAE5C,MAAI,GAAG,0BAA0B,QAAQ,EAAE;GACvC,MAAM,aAAa,0BAA0B,SAAS,SAAS;AAC/D,OAAI,CAAC,WAAY,QAAO;GACxB,MAAM,gBAAgB,iBAAiB,WAAW;AAClD,UAAO,GAAG,0BAA0B,cAAc,GAAG,gBAAgB;;AAGzE,MAAI,GAAG,iBAAiB,QAAQ,EAAE;GAC9B,MAAM,WAAW,QAAQ,UAAU;AACnC,OAAI,CAAC,SAAU,QAAO;GACtB,MAAM,gBAAgB,iBAAiB,SAAS;AAChD,UAAO,GAAG,0BAA0B,cAAc,GAAG,gBAAgB;;AAGzE,MAAI,GAAG,aAAa,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,EAAE;GACpE,MAAM,WAAW,oBAAoB,SAAS,QAAQ;AACtD,UAAO,WAAW,eAAe,SAAS,GAAG;;;CAMrD,MAAM,aACF,GAAG,sBAAsB,YAAY,IAAI,YAAY,cAC/C,YAAY,cACZ,GAAG,mBAAmB,YAAY,GAChC,YAAY,aACZ;CAEZ,MAAM,eAAe,aAAa,eAAe,WAAW,GAAG;AAC/D,KAAI,CAAC,aACD,QAAO,KAAK,OAAO,gDAAgD;AAEvE,QAAO;;AAGX,MAAM,iCACF,eACA,MACA,SACA,cACC;CACD,MAAM,aAAa,0BAA0B,eAAe,KAAK;AACjE,KAAI,CAAC,WAAY,QAAO,KAAK,WAAW,8BAA8B,KAAK,GAAG;AAC9E,QAAO;EAAE;EAAS,YAAY,iBAAiB,WAAW;EAAE,MAAM,GAAG,UAAU,GAAG;EAAQ;;AAG9F,MAAM,iCACF,eACA,MACA,SACA,cACC;CACD,MAAM,aAAa,0BAA0B,eAAe,KAAK;AACjE,QAAO,aACD;EAAE;EAAS,YAAY,iBAAiB,WAAW;EAAE,MAAM,GAAG,UAAU,GAAG;EAAQ,GACnF;;AAGV,MAAM,yBACF,SACA,YACA,cAC2B;CAC3B,MAAM,UAAU,iBAAiB,WAAW;AAE5C,KAAI,GAAG,aAAa,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,EAAE;EACpE,MAAM,WAAW,oBAAoB,SAAS,QAAQ;AACtD,SAAO,WAAW,sBAAsB,SAAS,UAAU,UAAU,GAAG;;AAG5E,KAAI,GAAG,0BAA0B,QAAQ,EAAE;EACvC,MAAM,iBAAiB,0BAA0B,SAAS,OAAO;EACjE,MAAM,WAAW,iBACX,kCACI;GAAE;GAAS,MAAM,GAAG,UAAU;GAAQ,EACtC,gBACA,gBACH,GACD;AAEN,MACI,CAAC,YACD,SAAS,SAAS,aAClB,OAAO,SAAS,UAAU,YAC1B,SAAS,UAAU,SAEnB;EAGJ,MAAM,iBAAiB,0BAA0B,SAAS,OAAO;EACjE,MAAM,mBAAmB,0BAA0B,SAAS,SAAS;AACrE,MAAI,CAAC,kBAAkB,CAAC,iBACpB,QAAO,KAAK,WAAW,4CAA4C;AAGvE,SAAO;GACH,MAAM;GACN,YAAY;IACR;KACI,MAAM;KACN,OAAO;MAAE,MAAM;MAAW,OAAO;MAAU;KAC9C;IACD;KACI,MAAM;KACN,OAAO,kCACH;MAAE;MAAS,MAAM,GAAG,UAAU;MAAQ,EACtC,gBACA,gBACH;KACJ;IACD;KACI,MAAM;KACN,OAAO,wCACH;MAAE;MAAS,MAAM,GAAG,UAAU;MAAU,EACxC,iBACH;KACJ;IACJ;GACJ;;AAGL,KAAI,GAAG,iBAAiB,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,WAAW,EAEjF;MADmB,QAAQ,WAAW,KAAK,SACxB,UAAU;GACzB,MAAM,WAAW,2BAA2B,SAAS,QAAQ,WAAW,WAAW;AACnF,OAAI,GAAG,iBAAiB,SAAS,EAAE;IAC/B,MAAM,YAAY,SAAS,UAAU;IACrC,MAAM,eACF,aAAa,GAAG,0BAA0B,iBAAiB,UAAU,CAAC,GAC/D,iBAAiB,UAAU,GAC5B;AAEV,QAAI,cAAc;KACd,MAAM,iBAAiB,0BAA0B,cAAc,OAAO;KACtE,MAAM,mBAAmB,0BAA0B,cAAc,SAAS;AAC1E,SAAI,CAAC,kBAAkB,CAAC,iBACpB,QAAO,KACH,WACA,yDACH;AAGL,YAAO;MACH,MAAM;MACN,YAAY;OACR;QAAE,MAAM;QAAQ,OAAO;SAAE,MAAM;SAAW,OAAO;SAAU;QAAE;OAC7D;QACI,MAAM;QACN,OAAO,kCACH;SAAE;SAAS,MAAM,GAAG,UAAU;SAAQ,EACtC,gBACA,gBACH;QACJ;OACD;QACI,MAAM;QACN,OAAO,wCACH;SAAE;SAAS,MAAM,GAAG,UAAU;SAAU,EACxC,iBACH;QACJ;OACJ;MACJ;;;;;CAMjB,MAAM,WAAW,QAAQ,kBAAkB,QAAQ;CACnD,MAAM,eAAe,mBAAmB,SAAS,UAAU,OAAO;AAClE,KAAI,CAAC,aAAc,QAAO;CAE1B,MAAM,WAAW,4BAA4B,SAAS,aAAa,MAAM,GAAG,UAAU,OAAO;AAC7F,KACI,SAAS,SAAS,aAClB,OAAO,SAAS,UAAU,YAC1B,SAAS,UAAU,SAEnB;CAGJ,MAAM,eAAe,mBAAmB,SAAS,UAAU,OAAO;CAClE,MAAM,iBAAiB,mBAAmB,SAAS,UAAU,SAAS;AACtE,KAAI,CAAC,gBAAgB,CAAC,eAClB,QAAO,KAAK,WAAW,iDAAiD;AAG5E,QAAO;EACH,MAAM;EACN,YAAY;GACR;IAAE,MAAM;IAAQ,OAAO;KAAE,MAAM;KAAW,OAAO;KAAU;IAAE;GAC7D;IACI,MAAM;IACN,OAAO,4BAA4B,SAAS,aAAa,MAAM,GAAG,UAAU,OAAO;IACtF;GACD;IACI,MAAM;IACN,OAAO,4BACH,SACA,eAAe,MACf,GAAG,UAAU,SAChB;IACJ;GACJ;EACJ;;AAGL,MAAM,oBACF,SACA,YACA,cACe;CACf,MAAM,UAAU,2BAA2B,SAAS,WAAW;AAC/D,KAAI,CAAC,GAAG,yBAAyB,QAAQ,CACrC,QAAO,KAAK,WAAW,6CAA6C;AAYxE,QAAO;EACH,MAAM;EACN,UAAU;EACV,UAZgB,QAAQ,SAAS,SAAS,SAAS,UAAU;AAC7D,OAAI,GAAG,gBAAgB,QAAQ,CAC3B,QAAO,KAAK,GAAG,UAAU,GAAG,MAAM,IAAI,iCAAiC;GAG3E,MAAM,WAAW,sBAAsB,SAAS,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG;AAClF,UAAO,WAAW,CAAC,SAAS,GAAG,EAAE;IACnC;EAMD;;AAGL,MAAM,oBACF,SACA,YACA,cACe;CACf,MAAM,UAAU,iBAAiB,WAAW;CAC5C,MAAM,WACF,GAAG,aAAa,QAAQ,IAAI,GAAG,2BAA2B,QAAQ,GAC5D,oBAAoB,SAAS,QAAQ,GACrC;CACV,MAAM,SAAS,WAAW,iBAAiB,SAAS,GAAG;CAEvD,MAAM,cAAc,GAAG,iBAAiB,OAAO,GACzC,OAAO,UAAU,KACjB,GAAG,0BAA0B,OAAO,GAClC,SACA;AAER,KAAI,CAAC,eAAe,CAAC,GAAG,0BAA0B,iBAAiB,YAAY,CAAC,CAC5E,QAAO,KAAK,WAAW,mEAAmE;CAG9F,MAAM,gBAAgB,iBAAiB,YAAY;CACnD,MAAM,aAAa,8BAA8B,eAAe,QAAQ,SAAS,UAAU;CAC3F,MAAM,cAAc,8BAA8B,eAAe,SAAS,SAAS,UAAU;CAC7F,MAAM,sBAAsB,8BACxB,eACA,iBACA,SACA,UACH;CACD,MAAM,qBAAqB,8BACvB,eACA,gBACA,SACA,UACH;CACD,MAAM,cAAc,8BAA8B,eAAe,SAAS,SAAS,UAAU;CAE7F,MAAM,mBAAmB;EACrB,MAAM,kBAAsC,EAAE;EAC9C,MAAM,eAAe,iBAAiB,YAAY,WAAW;AAC7D,MAAI,GAAG,0BAA0B,aAAa,EAAE;GAC5C,MAAM,iBAAiB,0BAA0B,cAAc,aAAa;AAC5E,OAAI,eACA,iBAAgB,KAAK;IACjB,MAAM;IACN,OAAO,kCACH;KAAE;KAAS,MAAM,GAAG,UAAU;KAAoB,EAClD,gBACA,gBACH;IACJ,CAAC;GAGN,MAAM,cAAc,0BAA0B,cAAc,UAAU;AACtE,OAAI,YACA,iBAAgB,KAAK;IACjB,MAAM;IACN,OAAO,kCACH;KAAE;KAAS,MAAM,GAAG,UAAU;KAAiB,EAC/C,aACA,gBACH;IACJ,CAAC;GAGN,MAAM,cAAc,0BAA0B,cAAc,UAAU;AACtE,OAAI,aAAa;IACb,MAAM,aAAa,kCACf;KAAE;KAAS,MAAM,GAAG,UAAU;KAAiB,EAC/C,aACA,gBACH;IAED,MAAM,kBACF,WAAW,SAAS,WACd;KACI,GAAG;KACH,YAAY,WAAW,WAAW,QAC7B,MAAM,CAAC,uBAAuB,IAAI,EAAE,KAAK,CAC7C;KACJ,GACD;AACV,oBAAgB,KAAK;KACjB,MAAM;KACN,OAAO;KACV,CAAC;UACC;IACH,MAAM,cAAc,gCAChB,SACA,QAAQ,kBAAkB,aAAa,EACvC,GAAG,UAAU,QAChB;AACD,QAAI,YACA,iBAAgB,KAAK;KACjB,MAAM;KACN,OAAO;KACV,CAAC;;GAIV,MAAM,WAAW,0BAA0B,cAAc,OAAO;AAChE,OAAI,CAAC,SAAU,QAAO,KAAK,GAAG,UAAU,SAAS,0BAA0B;AAC3E,mBAAgB,KAAK;IACjB,MAAM;IACN,OAAO,kCACH;KAAE;KAAS,MAAM,GAAG,UAAU;KAAc,EAC5C,UACA,gBACH;IACJ,CAAC;AAEF,UAAO;IACH,MAAM;IACN,YAAY;IACf;;EAGL,MAAM,YAAY,QAAQ,kBAAkB,aAAa;EACzD,MAAM,aAAa,mBAAmB,SAAS,WAAW,aAAa;AACvE,MAAI,WACA,iBAAgB,KAAK;GACjB,MAAM;GACN,OAAO,4BACH,SACA,WAAW,MACX,GAAG,UAAU,mBAChB;GACJ,CAAC;EAGN,MAAM,UAAU,mBAAmB,SAAS,WAAW,UAAU;AACjE,MAAI,QACA,iBAAgB,KAAK;GACjB,MAAM;GACN,OAAO,4BACH,SACA,QAAQ,MACR,GAAG,UAAU,gBAChB;GACJ,CAAC;EAGN,MAAM,cAAc,gCAChB,SACA,WACA,GAAG,UAAU,QAChB;AACD,MAAI,YACA,iBAAgB,KAAK;GACjB,MAAM;GACN,OAAO;GACV,CAAC;EAGN,MAAM,OAAO,mBAAmB,SAAS,WAAW,OAAO;AAC3D,MAAI,CAAC,KAAM,QAAO,KAAK,GAAG,UAAU,SAAS,+BAA+B;AAC5E,kBAAgB,KAAK;GACjB,MAAM;GACN,OAAO,4BAA4B,SAAS,KAAK,MAAM,GAAG,UAAU,aAAa;GACpF,CAAC;AAEF,SAAO;GACH,MAAM;GACN,YAAY;GACf;KACD;CAEJ,MAAM,aAAiC,CACnC;EACI,MAAM;EACN,OAAO,kCACH;GAAE;GAAS,MAAM,GAAG,UAAU;GAAQ,EACtC,WAAW,WACd;EACJ,EACD;EAAE,MAAM;EAAS,OAAO;EAAW,CACtC;AAED,KAAI,oBACA,YAAW,KAAK;EACZ,MAAM;EACN,OAAO,wCACH;GAAE;GAAS,MAAM,oBAAoB;GAAM,EAC3C,oBAAoB,WACvB;EACJ,CAAC;AAGN,KAAI,mBACA,YAAW,KAAK;EACZ,MAAM;EACN,OAAO,wBACH,SACA,mBAAmB,YACnB,mBAAmB,KACtB;EACJ,CAAC;AAGN,KAAI,YACA,YAAW,KAAK;EACZ,MAAM;EACN,OAAO,iBAAiB,SAAS,YAAY,YAAY,YAAY,KAAK;EAC7E,CAAC;AAGN,QAAO;EAAE,MAAM;EAAU;EAAY;;AAGzC,MAAM,qBACF,SACA,YACA,cACe;CACf,MAAM,UAAU,2BAA2B,SAAS,WAAW;AAC/D,KAAI,CAAC,GAAG,yBAAyB,QAAQ,CACrC,QAAO,KAAK,WAAW,8CAA8C;AAGzE,QAAO;EACH,MAAM;EACN,UAAU;EACV,UAAU,QAAQ,SAAS,KAAK,SAAwB,UAAkB;AACtE,OAAI,GAAG,gBAAgB,QAAQ,CAC3B,QAAO,KAAK,GAAG,UAAU,GAAG,MAAM,IAAI,kCAAkC;AAE5E,UAAO,iBAAiB,SAAS,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG;IACrE;EACL;;AAGL,MAAM,uBACF,SACA,YACA,cACe,iBAAiB,SAAS,YAAY,UAAU;AAEnE,MAAM,0BACF,SACA,aACA,UACe;CACf,MAAM,eAAe,uBAAuB,SAAS,aAAa,MAAM;CACxE,MAAM,eAAe,8BACjB,cACA,UACA,SACA,GAAG,MAAM,SACZ;CACD,MAAM,cAAc,8BAChB,cACA,SACA,SACA,GAAG,MAAM,SACZ;CAED,MAAM,mBAAuC,CACzC;EACI,MAAM;EACN,OAAO,kBAAkB,SAAS,aAAa,YAAY,aAAa,KAAK;EAChF,CACJ;AAED,KAAI,YACA,kBAAiB,KAAK;EAClB,MAAM;EACN,OAAO,oBAAoB,SAAS,YAAY,YAAY,YAAY,KAAK;EAChF,CAAC;AAGN,QAAO;EACH,MAAM;EACN,YAAY,CACR;GACI,MAAM;GACN,OAAO;IACH,MAAM;IACN,YAAY;IACf;GACJ,CACJ;EACJ;;AAGL,MAAa,oBAAoB,QAAgB;CAC7C,MAAM,UAAU,IAAI,QAAQ,mBAAmB,IAAI;AACnD,KAAI,CAAC,QAAS,QAAOA;AACrB,QAAO,SAAS,KAAK,QAAQ,GAAG,IAAI,YAAY;;AAGpD,MAAM,yBAAyB,UAAkB,WAAqB;CAClE,MAAM,uBAAO,IAAI,KAAa;AAC9B,QAAO,OAAO,KAAK,OAAO,UAAU;EAChC,MAAM,YAAY,iBACd,OAAO,WAAW,IAAI,WAAW,GAAG,SAAS,GAAG,MAAM,QAAQ,YAAY,IAAI,GACjF;AACD,MAAI,CAAC,KAAK,IAAI,UAAU,EAAE;AACtB,QAAK,IAAI,UAAU;AACnB,UAAO;;EAEX,IAAI,SAAS,QAAQ;EACrB,IAAI,YAAY,GAAG,UAAU,GAAG;AAChC,SAAO,KAAK,IAAI,UAAU,EAAE;AACxB,aAAU;AACV,eAAY,GAAG,UAAU,GAAG;;AAEhC,OAAK,IAAI,UAAU;AACnB,SAAO;GACT;;AAGN,MAAa,uBAAuB,MAA6B,aAA6B;CAC1F,MAAM,UAAU,GAAG,cACf,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,CAAC,EAC/C,oBAAoB,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,CACzD;CACD,MAAM,UAAU,QAAQ,gBAAgB;CAExC,MAAM,YAAY,sBACd,UACA,KAAK,KAAK,QAAQ,IAAI,MAAM,CAC/B;AAyBD,QAvBiB,KAAK,KAAK,KAAK,UAAU;EACtC,MAAM,aAAa,QAAQ,cAAc,IAAI,WAAW;AACxD,MAAI,CAAC,WACD,OAAM,IAAI,MAAM,wCAAwC,IAAI,aAAa;EAG7E,MAAM,eAAe,gBAAgB,SAAS,YAAY,IAAI,WAAW;AACzE,MAAI,CAAC,aACD,OAAM,IAAI,MACN,4BAA4B,IAAI,WAAW,KAAK,IAAI,CAAC,MAAM,IAAI,aAClE;EAGL,MAAM,cAAc,aAAa,oBAAoB,aAAa,eAAe;AACjF,MAAI,CAAC,YACD,OAAM,IAAI,MAAM,qCAAqC,IAAI,QAAQ;AAKrE,SAAO,gBAFU,UAAU,UAAU,UACrB,uBAAuB,SAAS,aAAa,IAAI,MAAM,EAC7B,IAAI,MAAM;GACtD,CAEc,KAAK,OAAO;;;;;AC/wChC,MAAa,uBAAuB,OAAO,MAAuB,MAAM,UAAU;AAC9E,KAAI,KAAK,UAAU,KAAK,IAAK,QAAO;CAEpC,MAAM,WAAW,MAAM,QAAQ;EAC3B,MAAM;EACN,MAAM;EACN,SAAS;EACT,cAAc;EACd,SAAS,KAAK,KAAK,SAAS;GACxB,OAAO,IAAI;GACX,OAAO,IAAI;GACX,UAAU;GACb,EAAE;EACN,CAAC;CAEF,MAAM,iBAAiB,IAAI,IAAY,SAAS,YAAY,EAAE,CAAC;AAC/D,QAAO,KAAK,QAAQ,QAAQ,eAAe,IAAI,IAAI,MAAM,CAAC;;;;;ACb9D,MAAM,sBACF,QAAQ,IAAI,aAAa,UACzB,QAAQ,IAAI,aAAa,OACzB,QAAQ,IAAI,WAAW,UACvB,QAAQ,IAAI,mBAAmB;AAEnC,MAAa,6BAA6B,EACtC,KAAK,SAAiB;AAClB,KAAI,eAAe,CAAE;AACrB,SAAQ,IAAI,QAAQ;GAE3B;AAED,MAAM,mBAAmB,OAAO,YAAoB;AAChD,KAAI,CAAC,QAAQ,MAAM,SAAS,CAAC,QAAQ,OAAO,MACxC,QAAO;CAGX,MAAM,KAAK,gBAAgB;EACvB,OAAO,QAAQ;EACf,QAAQ,QAAQ;EACnB,CAAC;AAEF,KAAI;EAEA,MAAM,cADS,MAAM,GAAG,SAAS,GAAG,QAAQ,SAAS,EAC3B,MAAM,CAAC,aAAa;AAC9C,SAAO,eAAe,OAAO,eAAe;WACtC;AACN,KAAG,OAAO;;;AAIlB,MAAa,sBAAsB,OAAO,WAMpC;CACF,MAAM,SAAS,WAAW,OAAO,WAAW;AAG5C,MAFgB,SAAS,MAAM,GAAG,SAAS,OAAO,YAAY,QAAQ,GAAG,IAE7D,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE;AACvC,SAAO,OAAO,KACV,MAAM,IAAI,6BAA6B,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,GAAG,CACzF;AACD,SAAO;;AAGX,KAAI,UAAU,CAAC,OAAO,KAIlB;MAAI,CAHc,MAAM,iBACpB,aAAa,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,CAAC,GAC7D,EACe;AACZ,UAAO,OAAO,KAAK,MAAM,IAAI,2BAA2B,CAAC;AACzD,UAAO;;;AAIf,OAAM,GAAG,MAAM,KAAK,QAAQ,OAAO,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;AACpE,OAAM,GAAG,UAAU,OAAO,YAAY,OAAO,KAAK;AAClD,QAAO,OAAO,KACV,MAAM,MAAM,oBAAoB,KAAK,SAAS,OAAO,KAAK,OAAO,WAAW,GAAG,CAClF;AACD,QAAO;;;;;AC5DX,MAAM,UAAU;AAChB,MAAM,iBAAiB;AACvB,MAAM,oBAAoB;AAE1B,MAAM,cAAc,YAAoB,QAAQ,OAAO,MAAM,GAAG,QAAQ,IAAI;AAE5E,MAAM,yBAAyB,UAA4B;AACvD,YAAW,MAAM,IAAI,IAAI,MAAM,KAAK,IAAI,MAAM,UAAU,CAAC;AACzD,KAAI,QAAQ,IAAI,aAAa,IACzB,YAAW,MAAM,IAAI,KAAK,UAAU,MAAM,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;;AAI3E,MAAM,yBAAyB,SAA8B;CACzD,MAAM,MAAM,KAAK,MAAM,KAAK,QAAQ,KAAK,IAAI,GAAG,QAAQ,KAAK;CAC7D,MAAM,cAAc,mBAAmB,KAAK,QAAQ,IAAI;AAGxD,KAAI,YAAY,WAAW,EACvB,OAAM,iBAAiB,SAAS,eAAe,6BAA6B;EACxE,SAAS,EAAE,SAAS,SAAS;EAC7B,OAAO,CAAC,EAAE,IAAI,mDAAmD,CAAC;EAClE,WAAW;EACd,CAAC;CAGN,MAAM,gBAAgB,oBAAoB,YAAY;AACtD,KAAI,cAAc,WAAW,EACzB,OAAM,iBAAiB,SAAS,aAAa,4CAA4C;EACrF,SAAS;GACL,SAAS;GACT,aAAa,YAAY,KAAK,eAAe,KAAK,SAAS,KAAK,WAAW,CAAC;GAC/E;EACD,OAAO,CAAC,EAAE,IAAI,mDAAmD,CAAC;EAClE,WAAW;EACd,CAAC;AAGN,QAAO;EACH;EACA;EACA,YAAY,KAAK,QAAQ,KAAK,KAAK,OAAO,eAAe;EACzD,UAAU,iBAAiB,KAAK,QAAQ,kBAAkB;EAC1D,KAAK,KAAK,OAAO;EACpB;;AAGL,MAAa,gBAAgB,OAAO,SAA+C;CAC/E,MAAM,SAAS,qBAAqB;AAEpC,KAAI;EACA,MAAM,UAAU,sBAAsB,KAAK;EAQ3C,MAAM,eAAe,MAAM,qBALJ,MAAM,sBACzB,QAAQ,eACR,QAAQ,KACR,sBACH,EAC+D,QAAQ,IAAI;AAC5E,MAAI,aAAa,WAAW,GAAG;AAC3B,UAAO,KAAK,MAAM,IAAI,oDAAoD,CAAC;AAC3E,UAAO;;AAKX,SAAO,MAAM,oBAAoB;GAC7B,MAFS,oBADU,aAAa,IAAI,uBAAuB,EACd,QAAQ,SAAS;GAG9D,KAAK,QAAQ;GACb,YAAY,QAAQ;GACpB,KAAK,QAAQ;GACb;GACH,CAAC;UACG,OAAO;EACZ,MAAM,UACF,iBAAiB,mBACX,QACA,iBAAiB,qBACf,iBAAiB,SAAS,qBAAqB,MAAM,SAAS;GAC1D,SAAS;IAAE,SAAS;IAAS,MAAM,MAAM;IAAM;GAC/C,OAAO,CAAC,EAAE,IAAI,wDAAwD,CAAC;GACvE,WAAW;GACd,CAAC,GACF,iBAAiB,KAAK;GAClB,KAAK;GACL,SAAS;GACT,MAAM;IACF,MAAM;IACN,SAAS,EAAE,SAAS,SAAS;IAC7B,OAAO,CAAC,EAAE,IAAI,qCAAqC,CAAC;IACpD,WAAW;IACd;GACJ,CAAC;AAEd,wBAAsB,QAAQ;AAC9B,MAAI,QAAQ,SAAS,cACjB,YAAW,MAAM,IAAI,iEAAiE,CAAC;AAE3F,SAAO;;;;;;ACzGf,MAAM,MAAM,IAAI,SAAS;AAEzB,IAAI,KAAK,eAAe,CAAC,YAAY,mBAAmB,CAAC,QAAQ,QAAQ;AAEjD,IAAI,QAAQ,WAAW,CAAC,YAAY,6BAA6B,CAGpF,QAAQ,OAAO,CACf,YAAY,uEAAuE,CACnF,OACG,sBACA,2FACH,CACA,OAAO,gBAAgB,sDAAsD,QAAQ,KAAK,CAAC,CAC3F,OAAO,gBAAgB,6BAA6B,0BAA0B,CAC9E,OAAO,uBAAuB,4BAA4B,cAAc,CACxE,OAAO,SAAS,qCAAqC,MAAM,CAC3D,OAAO,OAAO,SAAS;CACpB,MAAM,OAAO,MAAM,cAAc,KAAK;AACtC,SAAQ,KAAK,KAAK;EACpB;AAEN,IAAI,OAAO"}
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@better-agent/cli",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Better Agent CLI",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/better-agent/better-agent.git",
9
+ "directory": "packages/cli"
10
+ },
11
+ "homepage": "https://github.com/better-agent/better-agent/tree/main/packages/cli",
12
+ "bugs": {
13
+ "url": "https://github.com/better-agent/better-agent/issues"
14
+ },
15
+ "type": "module",
16
+ "types": "./dist/index.d.mts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.mts",
20
+ "import": "./dist/index.mjs",
21
+ "default": "./dist/index.mjs"
22
+ }
23
+ },
24
+ "bin": {
25
+ "better-agent": "./dist/index.mjs"
26
+ },
27
+ "scripts": {
28
+ "build": "bunx tsdown",
29
+ "dev": "bunx tsdown --watch --no-clean",
30
+ "lint:package": "bunx publint run --strict",
31
+ "lint:types": "npm_config_cache=../../.npm-cache bunx attw --profile esm-only --pack .",
32
+ "lint": "bunx biome check .",
33
+ "typecheck": "bunx tsc -p tsconfig.json --noEmit",
34
+ "format": "bunx biome format --write .",
35
+ "clean": "bunx rimraf dist"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public",
39
+ "executableFiles": ["./dist/index.mjs"]
40
+ },
41
+ "dependencies": {
42
+ "@better-agent/shared": "0.1.0-canary.2",
43
+ "@better-agent/core": "0.1.0-canary.2",
44
+ "chalk": "^5.6.2",
45
+ "commander": "^14.0.3",
46
+ "jiti": "^2.6.1",
47
+ "prompts": "^2.4.2",
48
+ "typescript": "^5.6.3"
49
+ },
50
+ "devDependencies": {
51
+ "@types/bun": "^1.2.18",
52
+ "@types/node": "^22.15.30",
53
+ "@types/prompts": "^2.4.9"
54
+ },
55
+ "files": ["dist"]
56
+ }