task-o-matic 0.0.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.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +552 -0
  3. package/dist/cli/bin.d.ts +3 -0
  4. package/dist/cli/bin.d.ts.map +1 -0
  5. package/dist/cli/bin.js +8 -0
  6. package/dist/cli/display/common.d.ts +5 -0
  7. package/dist/cli/display/common.d.ts.map +1 -0
  8. package/dist/cli/display/common.js +44 -0
  9. package/dist/cli/display/plan.d.ts +11 -0
  10. package/dist/cli/display/plan.d.ts.map +1 -0
  11. package/dist/cli/display/plan.js +42 -0
  12. package/dist/cli/display/progress.d.ts +11 -0
  13. package/dist/cli/display/progress.d.ts.map +1 -0
  14. package/dist/cli/display/progress.js +47 -0
  15. package/dist/cli/display/task.d.ts +18 -0
  16. package/dist/cli/display/task.d.ts.map +1 -0
  17. package/dist/cli/display/task.js +250 -0
  18. package/dist/commands/config.d.ts +3 -0
  19. package/dist/commands/config.d.ts.map +1 -0
  20. package/dist/commands/config.js +61 -0
  21. package/dist/commands/init.d.ts +4 -0
  22. package/dist/commands/init.d.ts.map +1 -0
  23. package/dist/commands/init.js +197 -0
  24. package/dist/commands/prd.d.ts +4 -0
  25. package/dist/commands/prd.d.ts.map +1 -0
  26. package/dist/commands/prd.js +131 -0
  27. package/dist/commands/prompt.d.ts +3 -0
  28. package/dist/commands/prompt.d.ts.map +1 -0
  29. package/dist/commands/prompt.js +192 -0
  30. package/dist/commands/tasks.d.ts +3 -0
  31. package/dist/commands/tasks.d.ts.map +1 -0
  32. package/dist/commands/tasks.js +599 -0
  33. package/dist/index.d.ts +18 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +67 -0
  36. package/dist/lib/ai-service/ai-operations.d.ts +31 -0
  37. package/dist/lib/ai-service/ai-operations.d.ts.map +1 -0
  38. package/dist/lib/ai-service/ai-operations.js +648 -0
  39. package/dist/lib/ai-service/json-parser.d.ts +9 -0
  40. package/dist/lib/ai-service/json-parser.d.ts.map +1 -0
  41. package/dist/lib/ai-service/json-parser.js +37 -0
  42. package/dist/lib/ai-service/mcp-client.d.ts +9 -0
  43. package/dist/lib/ai-service/mcp-client.d.ts.map +1 -0
  44. package/dist/lib/ai-service/mcp-client.js +48 -0
  45. package/dist/lib/ai-service/model-provider.d.ts +8 -0
  46. package/dist/lib/ai-service/model-provider.d.ts.map +1 -0
  47. package/dist/lib/ai-service/model-provider.js +71 -0
  48. package/dist/lib/ai-service/research-tools.d.ts +4 -0
  49. package/dist/lib/ai-service/research-tools.d.ts.map +1 -0
  50. package/dist/lib/ai-service/research-tools.js +8 -0
  51. package/dist/lib/ai-service/retry-handler.d.ts +8 -0
  52. package/dist/lib/ai-service/retry-handler.d.ts.map +1 -0
  53. package/dist/lib/ai-service/retry-handler.js +62 -0
  54. package/dist/lib/better-t-stack-cli.d.ts +35 -0
  55. package/dist/lib/better-t-stack-cli.d.ts.map +1 -0
  56. package/dist/lib/better-t-stack-cli.js +118 -0
  57. package/dist/lib/config.d.ts +24 -0
  58. package/dist/lib/config.d.ts.map +1 -0
  59. package/dist/lib/config.js +160 -0
  60. package/dist/lib/context-builder.d.ts +53 -0
  61. package/dist/lib/context-builder.d.ts.map +1 -0
  62. package/dist/lib/context-builder.js +294 -0
  63. package/dist/lib/executors/executor-factory.d.ts +5 -0
  64. package/dist/lib/executors/executor-factory.d.ts.map +1 -0
  65. package/dist/lib/executors/executor-factory.js +21 -0
  66. package/dist/lib/executors/opencode-executor.d.ts +6 -0
  67. package/dist/lib/executors/opencode-executor.d.ts.map +1 -0
  68. package/dist/lib/executors/opencode-executor.js +46 -0
  69. package/dist/lib/index.d.ts +89 -0
  70. package/dist/lib/index.d.ts.map +1 -0
  71. package/dist/lib/index.js +134 -0
  72. package/dist/lib/prompt-builder.d.ts +50 -0
  73. package/dist/lib/prompt-builder.d.ts.map +1 -0
  74. package/dist/lib/prompt-builder.js +171 -0
  75. package/dist/lib/prompt-registry.d.ts +22 -0
  76. package/dist/lib/prompt-registry.d.ts.map +1 -0
  77. package/dist/lib/prompt-registry.js +201 -0
  78. package/dist/lib/storage.d.ts +60 -0
  79. package/dist/lib/storage.d.ts.map +1 -0
  80. package/dist/lib/storage.js +768 -0
  81. package/dist/lib/task-execution.d.ts +3 -0
  82. package/dist/lib/task-execution.d.ts.map +1 -0
  83. package/dist/lib/task-execution.js +130 -0
  84. package/dist/lib/validation.d.ts +4 -0
  85. package/dist/lib/validation.d.ts.map +1 -0
  86. package/dist/lib/validation.js +52 -0
  87. package/dist/mcp/prompts.d.ts +3 -0
  88. package/dist/mcp/prompts.d.ts.map +1 -0
  89. package/dist/mcp/prompts.js +7 -0
  90. package/dist/mcp/resources.d.ts +3 -0
  91. package/dist/mcp/resources.d.ts.map +1 -0
  92. package/dist/mcp/resources.js +7 -0
  93. package/dist/mcp/server.d.ts +3 -0
  94. package/dist/mcp/server.d.ts.map +1 -0
  95. package/dist/mcp/server.js +25 -0
  96. package/dist/mcp/tools.d.ts +3 -0
  97. package/dist/mcp/tools.d.ts.map +1 -0
  98. package/dist/mcp/tools.js +99 -0
  99. package/dist/prompts/documentation-detection.d.ts +2 -0
  100. package/dist/prompts/documentation-detection.d.ts.map +1 -0
  101. package/dist/prompts/documentation-detection.js +24 -0
  102. package/dist/prompts/index.d.ts +7 -0
  103. package/dist/prompts/index.d.ts.map +1 -0
  104. package/dist/prompts/index.js +22 -0
  105. package/dist/prompts/prd-parsing.d.ts +3 -0
  106. package/dist/prompts/prd-parsing.d.ts.map +1 -0
  107. package/dist/prompts/prd-parsing.js +172 -0
  108. package/dist/prompts/prd-rework.d.ts +3 -0
  109. package/dist/prompts/prd-rework.d.ts.map +1 -0
  110. package/dist/prompts/prd-rework.js +81 -0
  111. package/dist/prompts/task-breakdown.d.ts +3 -0
  112. package/dist/prompts/task-breakdown.d.ts.map +1 -0
  113. package/dist/prompts/task-breakdown.js +151 -0
  114. package/dist/prompts/task-enhancement.d.ts +3 -0
  115. package/dist/prompts/task-enhancement.d.ts.map +1 -0
  116. package/dist/prompts/task-enhancement.js +140 -0
  117. package/dist/prompts/task-planning.d.ts +3 -0
  118. package/dist/prompts/task-planning.d.ts.map +1 -0
  119. package/dist/prompts/task-planning.js +66 -0
  120. package/dist/services/prd.d.ts +32 -0
  121. package/dist/services/prd.d.ts.map +1 -0
  122. package/dist/services/prd.js +191 -0
  123. package/dist/services/tasks.d.ts +67 -0
  124. package/dist/services/tasks.d.ts.map +1 -0
  125. package/dist/services/tasks.js +596 -0
  126. package/dist/test/commands.test.d.ts +2 -0
  127. package/dist/test/commands.test.d.ts.map +1 -0
  128. package/dist/test/commands.test.js +74 -0
  129. package/dist/test/storage.test.d.ts +2 -0
  130. package/dist/test/storage.test.d.ts.map +1 -0
  131. package/dist/test/storage.test.js +207 -0
  132. package/dist/types/callbacks.d.ts +27 -0
  133. package/dist/types/callbacks.d.ts.map +1 -0
  134. package/dist/types/callbacks.js +2 -0
  135. package/dist/types/index.d.ts +252 -0
  136. package/dist/types/index.d.ts.map +1 -0
  137. package/dist/types/index.js +2 -0
  138. package/dist/types/mcp.d.ts +3 -0
  139. package/dist/types/mcp.d.ts.map +1 -0
  140. package/dist/types/mcp.js +3 -0
  141. package/dist/types/options.d.ts +94 -0
  142. package/dist/types/options.d.ts.map +1 -0
  143. package/dist/types/options.js +2 -0
  144. package/dist/types/results.d.ts +90 -0
  145. package/dist/types/results.d.ts.map +1 -0
  146. package/dist/types/results.js +2 -0
  147. package/dist/utils/ai-config-builder.d.ts +14 -0
  148. package/dist/utils/ai-config-builder.d.ts.map +1 -0
  149. package/dist/utils/ai-config-builder.js +22 -0
  150. package/dist/utils/ai-service-factory.d.ts +10 -0
  151. package/dist/utils/ai-service-factory.d.ts.map +1 -0
  152. package/dist/utils/ai-service-factory.js +52 -0
  153. package/dist/utils/stack-formatter.d.ts +11 -0
  154. package/dist/utils/stack-formatter.d.ts.map +1 -0
  155. package/dist/utils/stack-formatter.js +30 -0
  156. package/dist/utils/streaming-options.d.ts +10 -0
  157. package/dist/utils/streaming-options.d.ts.map +1 -0
  158. package/dist/utils/streaming-options.js +53 -0
  159. package/package.json +82 -0
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JSONParser = void 0;
4
+ class JSONParser {
5
+ /**
6
+ * Parses JSON from AI text response with improved error handling
7
+ * @deprecated Use generateObject instead for structured output
8
+ */
9
+ parseJSONFromResponse(text) {
10
+ try {
11
+ // Try to extract JSON from the response (handle various formats)
12
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
13
+ if (!jsonMatch) {
14
+ return {
15
+ success: false,
16
+ error: "Could not extract JSON from AI response",
17
+ rawText: text,
18
+ };
19
+ }
20
+ const jsonStr = jsonMatch[0];
21
+ const parsed = JSON.parse(jsonStr);
22
+ return {
23
+ success: true,
24
+ data: parsed,
25
+ rawText: text,
26
+ };
27
+ }
28
+ catch (error) {
29
+ return {
30
+ success: false,
31
+ error: error instanceof Error ? error.message : String(error),
32
+ rawText: text,
33
+ };
34
+ }
35
+ }
36
+ }
37
+ exports.JSONParser = JSONParser;
@@ -0,0 +1,9 @@
1
+ import { ToolSet } from "ai";
2
+ export declare class Context7Client {
3
+ private mcpClient;
4
+ initializeMCPClient(): Promise<any>;
5
+ getMCPTools(): Promise<ToolSet>;
6
+ closeMCPConnection(): Promise<void>;
7
+ saveContext7Documentation(library: string, query: string, content: string): Promise<string>;
8
+ }
9
+ //# sourceMappingURL=mcp-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/mcp-client.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAQ,MAAM,IAAI,CAAC;AAEnC,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAa;IAExB,mBAAmB;IAoBnB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAW/B,kBAAkB;IAOlB,yBAAyB,CAC7B,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,MAAM,CAAC;CAInB"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Context7Client = void 0;
4
+ const mcp_1 = require("@ai-sdk/mcp");
5
+ const ai_service_factory_1 = require("../../utils/ai-service-factory");
6
+ class Context7Client {
7
+ mcpClient = null;
8
+ async initializeMCPClient() {
9
+ if (this.mcpClient)
10
+ return this.mcpClient;
11
+ try {
12
+ // Connect to Context7 MCP server using HTTP transport
13
+ this.mcpClient = await (0, mcp_1.experimental_createMCPClient)({
14
+ transport: {
15
+ type: "http",
16
+ url: "https://mcp.context7.com/mcp",
17
+ headers: {
18
+ CONTEXT7_API_KEY: process.env.CONTEXT7_API_KEY || "",
19
+ },
20
+ },
21
+ });
22
+ return this.mcpClient;
23
+ }
24
+ catch (error) {
25
+ throw error;
26
+ }
27
+ }
28
+ async getMCPTools() {
29
+ const client = await this.initializeMCPClient();
30
+ if (!client) {
31
+ throw new Error("Failed to initialize MCP client");
32
+ }
33
+ // Return original tools without wrapping - tool wrapping doesn't work with MCP tools
34
+ // Context7 result saving will be handled in ai-operations.ts by processing toolResults
35
+ return await client.tools();
36
+ }
37
+ async closeMCPConnection() {
38
+ if (this.mcpClient) {
39
+ await this.mcpClient.close();
40
+ this.mcpClient = null;
41
+ }
42
+ }
43
+ async saveContext7Documentation(library, query, content) {
44
+ const storage = (0, ai_service_factory_1.getStorage)();
45
+ return await storage.saveContext7Documentation(library, query, content);
46
+ }
47
+ }
48
+ exports.Context7Client = Context7Client;
@@ -0,0 +1,8 @@
1
+ import type { LanguageModelV2 } from "@ai-sdk/provider";
2
+ import { AIConfig } from "../../types";
3
+ export declare class ModelProvider {
4
+ getAIConfig(): AIConfig;
5
+ private getEnvConfig;
6
+ getModel(aiConfig: AIConfig): LanguageModelV2;
7
+ }
8
+ //# sourceMappingURL=model-provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-provider.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/model-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,qBAAa,aAAa;IACjB,WAAW,IAAI,QAAQ;IAY9B,OAAO,CAAC,YAAY;IAsBpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,eAAe;CA+B9C"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModelProvider = void 0;
4
+ const openai_1 = require("@ai-sdk/openai");
5
+ const anthropic_1 = require("@ai-sdk/anthropic");
6
+ const openai_compatible_1 = require("@ai-sdk/openai-compatible");
7
+ const ai_sdk_provider_1 = require("@openrouter/ai-sdk-provider");
8
+ const config_1 = require("../config");
9
+ class ModelProvider {
10
+ getAIConfig() {
11
+ const config = config_1.configManager.getAIConfig();
12
+ const envConfig = this.getEnvConfig(config.provider);
13
+ // Override with environment variables if available
14
+ return {
15
+ ...config,
16
+ apiKey: config.apiKey || envConfig.apiKey,
17
+ baseURL: config.baseURL || envConfig.baseURL,
18
+ };
19
+ }
20
+ getEnvConfig(provider) {
21
+ const envConfigMap = {
22
+ openai: {
23
+ apiKey: process.env.OPENAI_API_KEY,
24
+ },
25
+ anthropic: {
26
+ apiKey: process.env.ANTHROPIC_API_KEY,
27
+ },
28
+ openrouter: {
29
+ apiKey: process.env.OPENROUTER_API_KEY,
30
+ baseURL: "https://openrouter.ai/api/v1",
31
+ },
32
+ custom: {
33
+ apiKey: process.env.CUSTOM_API_KEY,
34
+ baseURL: process.env.CUSTOM_API_URL,
35
+ },
36
+ };
37
+ return envConfigMap[provider] || {};
38
+ }
39
+ getModel(aiConfig) {
40
+ const { provider, model, apiKey, baseURL } = aiConfig;
41
+ switch (provider) {
42
+ case "openai":
43
+ if (!apiKey)
44
+ throw new Error("OpenAI API key is required");
45
+ return (0, openai_1.openai)(model);
46
+ case "anthropic":
47
+ if (!apiKey)
48
+ throw new Error("Anthropic API key is required");
49
+ return (0, anthropic_1.anthropic)(model);
50
+ case "openrouter":
51
+ if (!apiKey)
52
+ throw new Error("OpenRouter API key is required");
53
+ const openRouterProvider = (0, ai_sdk_provider_1.createOpenRouter)({ apiKey });
54
+ return openRouterProvider(model);
55
+ case "custom":
56
+ if (!apiKey)
57
+ throw new Error("Custom API key is required");
58
+ if (!baseURL)
59
+ throw new Error("Custom provider requires baseURL");
60
+ const customProvider = (0, openai_compatible_1.createOpenAICompatible)({
61
+ name: "custom",
62
+ apiKey,
63
+ baseURL,
64
+ });
65
+ return customProvider(model);
66
+ default:
67
+ throw new Error(`Unsupported provider: ${provider}`);
68
+ }
69
+ }
70
+ }
71
+ exports.ModelProvider = ModelProvider;
@@ -0,0 +1,4 @@
1
+ export declare class ResearchTools {
2
+ private storage;
3
+ }
4
+ //# sourceMappingURL=research-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research-tools.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/research-tools.ts"],"names":[],"mappings":"AAIA,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAsB;CAwMtC"}
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResearchTools = void 0;
4
+ const storage_1 = require("../storage");
5
+ class ResearchTools {
6
+ storage = new storage_1.LocalStorage();
7
+ }
8
+ exports.ResearchTools = ResearchTools;
@@ -0,0 +1,8 @@
1
+ import { RetryConfig } from "../../types";
2
+ export declare class RetryHandler {
3
+ private getRetryConfig;
4
+ private shouldRetryError;
5
+ private delay;
6
+ executeWithRetry<T>(operation: () => Promise<T>, retryConfig?: Partial<RetryConfig>, operationName?: string): Promise<T>;
7
+ }
8
+ //# sourceMappingURL=retry-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-handler.d.ts","sourceRoot":"","sources":["../../../src/lib/ai-service/retry-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,qBAAa,YAAY;IACvB,OAAO,CAAC,cAAc;IAmBtB,OAAO,CAAC,gBAAgB;YAaV,KAAK;IAIb,gBAAgB,CAAC,CAAC,EACtB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,WAAW,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,EAClC,aAAa,GAAE,MAAuB,GACrC,OAAO,CAAC,CAAC,CAAC;CA6Cd"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RetryHandler = void 0;
4
+ class RetryHandler {
5
+ getRetryConfig() {
6
+ return {
7
+ maxAttempts: parseInt(process.env.AI_MAX_RETRY_ATTEMPTS || "3", 10),
8
+ baseDelay: parseInt(process.env.AI_RETRY_BASE_DELAY || "1000", 10),
9
+ maxDelay: parseInt(process.env.AI_RETRY_MAX_DELAY || "10000", 10),
10
+ backoffFactor: parseFloat(process.env.AI_RETRY_BACKOFF_FACTOR || "2"),
11
+ retryableErrors: [
12
+ "ECONNRESET",
13
+ "ENOTFOUND",
14
+ "ECONNREFUSED",
15
+ "ETIMEDOUT",
16
+ "NETWORK_ERROR",
17
+ "RATE_LIMIT",
18
+ "TEMPORARY_FAILURE",
19
+ "INTERNAL_ERROR",
20
+ ],
21
+ };
22
+ }
23
+ shouldRetryError(error, retryableErrors) {
24
+ if (!error)
25
+ return false;
26
+ const errorMessage = error instanceof Error ? error.message : String(error);
27
+ const errorName = error instanceof Error ? error.name : "";
28
+ return retryableErrors.some((retryableError) => errorMessage.toUpperCase().includes(retryableError) ||
29
+ errorName.toUpperCase().includes(retryableError));
30
+ }
31
+ async delay(ms) {
32
+ return new Promise((resolve) => setTimeout(resolve, ms));
33
+ }
34
+ async executeWithRetry(operation, retryConfig, operationName = "AI operation") {
35
+ const finalRetryConfig = { ...this.getRetryConfig(), ...retryConfig };
36
+ const { maxAttempts = 3, baseDelay = 1000, maxDelay = 10000, backoffFactor = 2, retryableErrors = [], } = finalRetryConfig;
37
+ let lastError;
38
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
39
+ try {
40
+ return await operation();
41
+ }
42
+ catch (error) {
43
+ lastError = error;
44
+ // Don't retry on the last attempt
45
+ if (attempt === maxAttempts) {
46
+ break;
47
+ }
48
+ // Check if error is retryable
49
+ if (!this.shouldRetryError(error, retryableErrors)) {
50
+ break;
51
+ }
52
+ // Calculate delay with exponential backoff
53
+ const delayMs = Math.min(baseDelay * Math.pow(backoffFactor, attempt - 1), maxDelay);
54
+ console.warn(`${operationName} failed (attempt ${attempt}/${maxAttempts}), retrying in ${delayMs}ms:`, error);
55
+ await this.delay(delayMs);
56
+ }
57
+ }
58
+ // Throw the original error - NO rebuilding bullshit
59
+ throw lastError;
60
+ }
61
+ }
62
+ exports.RetryHandler = RetryHandler;
@@ -0,0 +1,35 @@
1
+ import { BTSConfig } from "../types";
2
+ export declare class BetterTStackService {
3
+ createProject(name: string, config: BTSConfig, workingDirectory?: string): Promise<{
4
+ success: boolean;
5
+ projectPath: string;
6
+ message: string;
7
+ }>;
8
+ private convertToAPIConfig;
9
+ private saveBTSConfig;
10
+ }
11
+ export interface InitOptions {
12
+ projectName?: string;
13
+ name?: string;
14
+ frontend: string;
15
+ backend: string;
16
+ database: string;
17
+ noAuth?: boolean;
18
+ addons?: string[];
19
+ runtime?: string;
20
+ api?: string;
21
+ payments?: string;
22
+ orm?: string;
23
+ dbSetup?: string;
24
+ packageManager?: string;
25
+ noGit?: boolean;
26
+ webDeploy?: string;
27
+ serverDeploy?: string;
28
+ noInstall?: boolean;
29
+ examples?: string[];
30
+ }
31
+ export declare function runBetterTStackCLI(options: InitOptions, workingDirectory?: string): Promise<{
32
+ success: boolean;
33
+ message: string;
34
+ }>;
35
+ //# sourceMappingURL=better-t-stack-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"better-t-stack-cli.d.ts","sourceRoot":"","sources":["../../src/lib/better-t-stack-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKrC,qBAAa,mBAAmB;IACxB,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,EACjB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC;QACT,OAAO,EAAE,OAAO,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IAmDF,OAAO,CAAC,kBAAkB;YAsBZ,aAAa;CAqB5B;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,WAAW,EACpB,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAkChD"}
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BetterTStackService = void 0;
4
+ exports.runBetterTStackCLI = runBetterTStackCLI;
5
+ const config_1 = require("./config");
6
+ const fs_1 = require("fs");
7
+ const path_1 = require("path");
8
+ class BetterTStackService {
9
+ async createProject(name, config, workingDirectory) {
10
+ try {
11
+ console.log(`🚀 Bootstrapping Better-T-Stack project: ${name}`);
12
+ // Change to working directory if provided
13
+ const originalCwd = process.cwd();
14
+ if (workingDirectory) {
15
+ process.chdir(workingDirectory);
16
+ console.log(`🔥 Changed working directory to: ${workingDirectory}`);
17
+ }
18
+ // Convert our config to Better-T-Stack API format
19
+ const apiConfig = this.convertToAPIConfig(config);
20
+ console.log(`🔥 Calling Better-T-Stack programmatic API...`);
21
+ // Use dynamic import with eval to bypass TypeScript module resolution
22
+ // this is magically fucking terrible
23
+ const btsModule = await eval(`import("create-better-t-stack")`);
24
+ const result = await btsModule.init(name, apiConfig);
25
+ // Restore original directory
26
+ if (workingDirectory) {
27
+ process.chdir(originalCwd);
28
+ }
29
+ if (result.success) {
30
+ // Save configuration
31
+ await this.saveBTSConfig(name, config);
32
+ return {
33
+ success: true,
34
+ projectPath: result.relativePath,
35
+ message: `Better-T-Stack project ${name} created successfully at ${result.projectDirectory}`,
36
+ };
37
+ }
38
+ else {
39
+ return {
40
+ success: false,
41
+ projectPath: "",
42
+ message: `Better-T-Stack bootstrap failed: ${result.error}`,
43
+ };
44
+ }
45
+ }
46
+ catch (error) {
47
+ return {
48
+ success: false,
49
+ projectPath: "",
50
+ message: `Better-T-Stack initialization failed: ${error instanceof Error ? error.message : "Unknown error"}`,
51
+ };
52
+ }
53
+ }
54
+ convertToAPIConfig(config) {
55
+ return {
56
+ // Don't use 'yes' flag when providing explicit configuration
57
+ frontend: [config.frontend],
58
+ backend: config.backend,
59
+ runtime: config.runtime,
60
+ api: config.api,
61
+ auth: config.auth,
62
+ database: config.database,
63
+ orm: config.orm,
64
+ dbSetup: config.dbSetup,
65
+ packageManager: config.packageManager,
66
+ webDeploy: config.webDeploy,
67
+ serverDeploy: config.serverDeploy,
68
+ git: config.git,
69
+ install: config.install,
70
+ addons: config.addons,
71
+ examples: config.examples,
72
+ disableAnalytics: true,
73
+ };
74
+ }
75
+ async saveBTSConfig(name, config) {
76
+ const taskOMaticDir = config_1.configManager.getTaskOMaticDir();
77
+ const configData = JSON.stringify({
78
+ ...config,
79
+ projectName: config.projectName || name,
80
+ createdAt: new Date().toISOString(),
81
+ }, null, 2);
82
+ // Save with project-specific name for tracking multiple projects
83
+ const namedConfigPath = (0, path_1.join)(taskOMaticDir, `${name}-bts-config.json`);
84
+ (0, fs_1.writeFileSync)(namedConfigPath, configData);
85
+ // Also save as canonical stack.json for easy discovery by context-builder
86
+ const stackConfigPath = (0, path_1.join)(taskOMaticDir, "stack.json");
87
+ (0, fs_1.writeFileSync)(stackConfigPath, configData);
88
+ }
89
+ }
90
+ exports.BetterTStackService = BetterTStackService;
91
+ async function runBetterTStackCLI(options, workingDirectory) {
92
+ const btsService = new BetterTStackService();
93
+ const backend = options.backend;
94
+ const isConvex = backend === "convex";
95
+ const btsConfig = {
96
+ projectName: options.name || options.projectName || "default-project",
97
+ frontend: options.frontend || "next",
98
+ backend: backend || "convex",
99
+ database: isConvex
100
+ ? "none"
101
+ : options.database || "sqlite",
102
+ auth: options.noAuth ? "none" : "better-auth",
103
+ addons: options.addons || ["turborepo"],
104
+ runtime: isConvex ? "none" : options.runtime || "node",
105
+ api: options.api || "none",
106
+ payments: options.payments || "none",
107
+ orm: isConvex ? "none" : options.orm || "drizzle",
108
+ dbSetup: isConvex ? "none" : options.dbSetup || "none",
109
+ packageManager: options.packageManager || "npm",
110
+ git: !options.noGit,
111
+ webDeploy: options.webDeploy || "none",
112
+ serverDeploy: options.serverDeploy || "none",
113
+ install: !options.noInstall,
114
+ examples: options.examples || [],
115
+ };
116
+ const result = await btsService.createProject(options.projectName || options.name || "", btsConfig, workingDirectory);
117
+ return { success: result.success, message: result.message };
118
+ }
@@ -0,0 +1,24 @@
1
+ import { AIConfig } from "../types";
2
+ export interface Config {
3
+ ai: AIConfig;
4
+ workingDirectory?: string;
5
+ }
6
+ export declare class ConfigManager {
7
+ private config;
8
+ private customWorkingDir;
9
+ constructor(workingDirectory?: string);
10
+ setWorkingDirectory(dir: string): void;
11
+ getWorkingDirectory(): string;
12
+ ensureTaskOMaticDir(): void;
13
+ private loadEnvConfig;
14
+ load(): Config;
15
+ save(): void;
16
+ getConfig(): Config;
17
+ getAIConfig(): AIConfig;
18
+ setAIConfig(aiConfig: Partial<AIConfig>): void;
19
+ setConfig(config: Config): void;
20
+ getTaskOMaticDir(): string;
21
+ getConfigFilePath(): string;
22
+ }
23
+ export declare const configManager: ConfigManager;
24
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAA6C,MAAM,UAAU,CAAC;AAE/E,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,QAAQ,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAyCD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,gBAAgB,CAAuB;gBAEnC,gBAAgB,CAAC,EAAE,MAAM;IAOrC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAMtC,mBAAmB,IAAI,MAAM;IAI7B,mBAAmB,IAAI,IAAI;IAO3B,OAAO,CAAC,aAAa;IAcrB,IAAI,IAAI,MAAM;IA2Cd,IAAI,IAAI,IAAI;IAaZ,SAAS,IAAI,MAAM;IAOnB,WAAW,IAAI,QAAQ;IAIvB,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,GAAG,IAAI;IAQ9C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,gBAAgB,IAAI,MAAM;IAIxB,iBAAiB,IAAI,MAAM;CAM5B;AAID,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configManager = exports.ConfigManager = void 0;
4
+ const fs_1 = require("fs");
5
+ const process_1 = require("process");
6
+ const path_1 = require("path");
7
+ const dotenv_1 = require("dotenv");
8
+ // Provider-specific sensible defaults for 2025
9
+ const PROVIDER_DEFAULTS = {
10
+ openrouter: {
11
+ model: "z-ai/glm-4.6",
12
+ maxTokens: 32768,
13
+ temperature: 0.5,
14
+ },
15
+ anthropic: {
16
+ model: "claude-sonnet-4.5",
17
+ maxTokens: 32768,
18
+ temperature: 0.5,
19
+ },
20
+ openai: {
21
+ model: "gpt-5",
22
+ maxTokens: 32768,
23
+ temperature: 0.5,
24
+ },
25
+ custom: {
26
+ model: "llama-3.3-70b",
27
+ maxTokens: 32768,
28
+ temperature: 0.5,
29
+ },
30
+ };
31
+ function getApiKeyFromEnv(provider) {
32
+ switch (provider) {
33
+ case "openrouter":
34
+ return process.env.OPENROUTER_API_KEY;
35
+ case "anthropic":
36
+ return process.env.ANTHROPIC_API_KEY;
37
+ case "openai":
38
+ return process.env.OPENAI_API_KEY;
39
+ case "custom":
40
+ return process.env.CUSTOM_API_KEY;
41
+ default:
42
+ return undefined;
43
+ }
44
+ }
45
+ class ConfigManager {
46
+ config = null;
47
+ customWorkingDir = null;
48
+ constructor(workingDirectory) {
49
+ if (workingDirectory) {
50
+ this.setWorkingDirectory(workingDirectory);
51
+ }
52
+ this.load();
53
+ }
54
+ setWorkingDirectory(dir) {
55
+ this.customWorkingDir = (0, path_1.resolve)(dir);
56
+ // Reload config when directory changes
57
+ this.load();
58
+ }
59
+ getWorkingDirectory() {
60
+ return this.customWorkingDir || (0, process_1.cwd)();
61
+ }
62
+ ensureTaskOMaticDir() {
63
+ const taskOMaticDir = this.getTaskOMaticDir();
64
+ if (!(0, fs_1.existsSync)(taskOMaticDir)) {
65
+ (0, fs_1.mkdirSync)(taskOMaticDir, { recursive: true });
66
+ }
67
+ }
68
+ loadEnvConfig() {
69
+ const env = process.env;
70
+ const provider = env.AI_PROVIDER?.toLowerCase() || "openrouter";
71
+ const defaults = PROVIDER_DEFAULTS[provider] || PROVIDER_DEFAULTS.openrouter;
72
+ return {
73
+ provider,
74
+ model: env.AI_MODEL || defaults.model,
75
+ maxTokens: env.AI_MAX_TOKENS ? parseInt(env.AI_MAX_TOKENS) : defaults.maxTokens,
76
+ temperature: env.AI_TEMPERATURE ? parseFloat(env.AI_TEMPERATURE) : defaults.temperature,
77
+ apiKey: getApiKeyFromEnv(provider),
78
+ };
79
+ }
80
+ load() {
81
+ const workingDir = this.getWorkingDirectory();
82
+ const envPath = (0, path_1.join)(workingDir, '.env');
83
+ if ((0, fs_1.existsSync)(envPath)) {
84
+ (0, dotenv_1.config)({ path: envPath });
85
+ }
86
+ const envConfig = this.loadEnvConfig();
87
+ const defaultConfig = {
88
+ ai: {
89
+ provider: "openrouter",
90
+ model: "z-ai/glm-4.6",
91
+ maxTokens: 32768,
92
+ temperature: 0.5,
93
+ ...envConfig,
94
+ },
95
+ };
96
+ const configFilePath = this.getConfigFilePath();
97
+ if ((0, fs_1.existsSync)(configFilePath)) {
98
+ try {
99
+ const configData = (0, fs_1.readFileSync)(configFilePath, "utf-8");
100
+ const fileConfig = JSON.parse(configData);
101
+ this.config = {
102
+ ...defaultConfig,
103
+ ...fileConfig,
104
+ ai: { ...defaultConfig.ai, ...fileConfig.ai, ...envConfig }
105
+ };
106
+ if (this.config && this.config.workingDirectory) {
107
+ this.customWorkingDir = this.config.workingDirectory;
108
+ }
109
+ }
110
+ catch (error) {
111
+ console.warn("Failed to read config file, using defaults:", error);
112
+ this.config = defaultConfig;
113
+ }
114
+ }
115
+ else {
116
+ this.config = defaultConfig;
117
+ }
118
+ return this.config;
119
+ }
120
+ save() {
121
+ if (!this.config) {
122
+ throw new Error("Config not loaded, cannot save.");
123
+ }
124
+ this.ensureTaskOMaticDir();
125
+ try {
126
+ const configFilePath = this.getConfigFilePath();
127
+ (0, fs_1.writeFileSync)(configFilePath, JSON.stringify(this.config, null, 2));
128
+ }
129
+ catch (error) {
130
+ console.error("Failed to save config:", error);
131
+ }
132
+ }
133
+ getConfig() {
134
+ if (!this.config) {
135
+ return this.load();
136
+ }
137
+ return this.config;
138
+ }
139
+ getAIConfig() {
140
+ return this.getConfig().ai;
141
+ }
142
+ setAIConfig(aiConfig) {
143
+ if (!this.config) {
144
+ this.load();
145
+ }
146
+ this.config.ai = { ...this.config.ai, ...aiConfig };
147
+ this.save();
148
+ }
149
+ setConfig(config) {
150
+ this.config = config;
151
+ }
152
+ getTaskOMaticDir() {
153
+ return (0, path_1.join)(this.getWorkingDirectory(), ".task-o-matic");
154
+ }
155
+ getConfigFilePath() {
156
+ return (0, path_1.join)(this.getTaskOMaticDir(), "config.json");
157
+ }
158
+ }
159
+ exports.ConfigManager = ConfigManager;
160
+ exports.configManager = new ConfigManager();