@krr2020/taskflow-core 0.1.0-beta.4 → 0.1.0-beta.5
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 +1 -1
- package/dist/cli/index.js +41 -3
- package/dist/commands/base.d.ts +41 -0
- package/dist/commands/base.js +141 -0
- package/dist/commands/configure.d.ts +29 -0
- package/dist/commands/configure.js +187 -0
- package/dist/commands/init.js +15 -1
- package/dist/commands/prd/create.d.ts +1 -1
- package/dist/commands/prd/create.js +26 -8
- package/dist/commands/tasks/generate.d.ts +1 -1
- package/dist/commands/tasks/generate.js +81 -55
- package/dist/commands/upgrade.js +35 -2
- package/dist/commands/workflow/check.d.ts +16 -0
- package/dist/commands/workflow/check.js +355 -32
- package/dist/commands/workflow/do.js +157 -62
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -0
- package/dist/lib/config-paths.js +6 -1
- package/dist/lib/file-validator.d.ts +119 -0
- package/dist/lib/file-validator.js +291 -0
- package/dist/lib/log-parser.d.ts +91 -0
- package/dist/lib/log-parser.js +178 -0
- package/dist/lib/retrospective.d.ts +27 -0
- package/dist/lib/retrospective.js +110 -0
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.js +12 -8
- package/dist/llm/base.d.ts +52 -0
- package/dist/llm/base.js +35 -0
- package/dist/llm/factory.d.ts +39 -0
- package/dist/llm/factory.js +102 -0
- package/dist/llm/index.d.ts +7 -0
- package/dist/llm/index.js +7 -0
- package/dist/llm/model-selector.d.ts +71 -0
- package/dist/llm/model-selector.js +139 -0
- package/dist/llm/providers/anthropic.d.ts +31 -0
- package/dist/llm/providers/anthropic.js +116 -0
- package/dist/llm/providers/index.d.ts +6 -0
- package/dist/llm/providers/index.js +6 -0
- package/dist/llm/providers/ollama.d.ts +28 -0
- package/dist/llm/providers/ollama.js +91 -0
- package/dist/llm/providers/openai-compatible.d.ts +30 -0
- package/dist/llm/providers/openai-compatible.js +93 -0
- package/dist/schemas/config.d.ts +82 -0
- package/dist/schemas/config.js +35 -0
- package/package.json +43 -43
- package/dist/lib/package-manager.d.ts +0 -17
- package/dist/lib/package-manager.js +0 -53
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Claude LLM Provider
|
|
3
|
+
* Supports Claude models via Anthropic API
|
|
4
|
+
*/
|
|
5
|
+
import { LLMProvider, LLMProviderType, } from "../base.js";
|
|
6
|
+
export class AnthropicProvider extends LLMProvider {
|
|
7
|
+
config;
|
|
8
|
+
DEFAULT_MAX_TOKENS = 4096;
|
|
9
|
+
constructor(config) {
|
|
10
|
+
super(LLMProviderType.Anthropic, config.model);
|
|
11
|
+
this.config = config;
|
|
12
|
+
this.config.maxTokens = config.maxTokens || this.DEFAULT_MAX_TOKENS;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Generate text using Anthropic Claude API
|
|
16
|
+
*/
|
|
17
|
+
async generate(messages, options) {
|
|
18
|
+
if (!this.isConfigured()) {
|
|
19
|
+
throw new Error("Anthropic provider is not configured properly");
|
|
20
|
+
}
|
|
21
|
+
// Extract system message (Anthropic separates system message)
|
|
22
|
+
let systemMessage = "";
|
|
23
|
+
const apiMessages = [];
|
|
24
|
+
for (const msg of messages) {
|
|
25
|
+
if (msg.role === "system") {
|
|
26
|
+
systemMessage = msg.content;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
apiMessages.push(msg);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const requestBody = {
|
|
33
|
+
model: this.config.model,
|
|
34
|
+
messages: apiMessages,
|
|
35
|
+
max_tokens: options?.maxTokens || this.config.maxTokens,
|
|
36
|
+
stream: false,
|
|
37
|
+
};
|
|
38
|
+
if (systemMessage) {
|
|
39
|
+
requestBody.system = systemMessage;
|
|
40
|
+
}
|
|
41
|
+
if (options?.temperature !== undefined) {
|
|
42
|
+
requestBody.temperature = options.temperature;
|
|
43
|
+
}
|
|
44
|
+
if (options?.topP !== undefined) {
|
|
45
|
+
requestBody.top_p = options.topP;
|
|
46
|
+
}
|
|
47
|
+
if (options?.topK !== undefined) {
|
|
48
|
+
requestBody.top_k = options.topK;
|
|
49
|
+
}
|
|
50
|
+
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: {
|
|
53
|
+
"Content-Type": "application/json",
|
|
54
|
+
"x-api-key": this.config.apiKey,
|
|
55
|
+
"anthropic-version": "2023-06-01",
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify(requestBody),
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const error = await response.text();
|
|
61
|
+
throw new Error(`Anthropic API error: ${response.status} - ${error}`);
|
|
62
|
+
}
|
|
63
|
+
const data = (await response.json());
|
|
64
|
+
const contentItem = data.content[0];
|
|
65
|
+
if (!contentItem) {
|
|
66
|
+
throw new Error("No content returned from Anthropic API");
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
content: contentItem.text,
|
|
70
|
+
model: data.model,
|
|
71
|
+
tokensUsed: (data.usage?.input_tokens ?? 0) + (data.usage?.output_tokens ?? 0),
|
|
72
|
+
finishReason: data.stop_reason,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Check if provider is configured
|
|
77
|
+
*/
|
|
78
|
+
isConfigured() {
|
|
79
|
+
return !!this.config.apiKey;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Create provider from environment variables
|
|
83
|
+
*/
|
|
84
|
+
static fromEnv(config) {
|
|
85
|
+
const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY || "";
|
|
86
|
+
const model = config.model ||
|
|
87
|
+
process.env.ANTHROPIC_MODEL ||
|
|
88
|
+
"claude-3-5-sonnet-20241022";
|
|
89
|
+
const maxTokensValue = config.maxTokens ||
|
|
90
|
+
Number.parseInt(process.env.ANTHROPIC_MAX_TOKENS || "4096", 10);
|
|
91
|
+
if (!apiKey) {
|
|
92
|
+
console.warn("Warning: Anthropic provider missing API key");
|
|
93
|
+
}
|
|
94
|
+
const maxTokens = Number.isNaN(maxTokensValue) ? undefined : maxTokensValue;
|
|
95
|
+
return new AnthropicProvider({
|
|
96
|
+
apiKey: expandEnvVar(apiKey),
|
|
97
|
+
model,
|
|
98
|
+
maxTokens: maxTokens ?? 4096,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Expand environment variable in string (e.g., "${VAR_NAME}" -> actual value)
|
|
104
|
+
*/
|
|
105
|
+
function expandEnvVar(value) {
|
|
106
|
+
if (!value) {
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
const envVarMatch = value.match(/^\$\{([^}]+)\}$/);
|
|
110
|
+
if (envVarMatch?.[1]) {
|
|
111
|
+
const envVar = envVarMatch[1];
|
|
112
|
+
const envValue = process.env[envVar];
|
|
113
|
+
return envValue ?? value;
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider exports
|
|
3
|
+
*/
|
|
4
|
+
export { type AnthropicConfig, AnthropicProvider } from "./anthropic.js";
|
|
5
|
+
export { type OllamaConfig, OllamaProvider } from "./ollama.js";
|
|
6
|
+
export { type OpenAICompatibleConfig, OpenAICompatibleProvider, } from "./openai-compatible.js";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM Provider
|
|
3
|
+
* Supports local LLM models via Ollama API
|
|
4
|
+
*/
|
|
5
|
+
import { type LLMGenerationOptions, type LLMGenerationResult, type LLMMessage, LLMProvider } from "../base.js";
|
|
6
|
+
export interface OllamaConfig {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
model: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class OllamaProvider extends LLMProvider {
|
|
11
|
+
private config;
|
|
12
|
+
constructor(config: OllamaConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Generate text using Ollama API
|
|
15
|
+
*/
|
|
16
|
+
generate(messages: LLMMessage[], options?: LLMGenerationOptions): Promise<LLMGenerationResult>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if provider is configured
|
|
19
|
+
*/
|
|
20
|
+
isConfigured(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Create provider from environment variables
|
|
23
|
+
*/
|
|
24
|
+
static fromEnv(config: {
|
|
25
|
+
baseUrl?: string;
|
|
26
|
+
model?: string;
|
|
27
|
+
}): OllamaProvider;
|
|
28
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama LLM Provider
|
|
3
|
+
* Supports local LLM models via Ollama API
|
|
4
|
+
*/
|
|
5
|
+
import { LLMProvider, LLMProviderType, } from "../base.js";
|
|
6
|
+
export class OllamaProvider extends LLMProvider {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super(LLMProviderType.Ollama, config.model);
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generate text using Ollama API
|
|
14
|
+
*/
|
|
15
|
+
async generate(messages, options) {
|
|
16
|
+
if (!this.isConfigured()) {
|
|
17
|
+
throw new Error("Ollama provider is not configured properly");
|
|
18
|
+
}
|
|
19
|
+
// Convert messages to Ollama format
|
|
20
|
+
const prompt = messages
|
|
21
|
+
.map((msg) => `${msg.role}: ${msg.content}`)
|
|
22
|
+
.join("\n\n");
|
|
23
|
+
const requestBody = {
|
|
24
|
+
model: this.config.model,
|
|
25
|
+
prompt,
|
|
26
|
+
stream: false,
|
|
27
|
+
};
|
|
28
|
+
if (options?.temperature !== undefined) {
|
|
29
|
+
requestBody.temperature = options.temperature;
|
|
30
|
+
}
|
|
31
|
+
if (options?.topP !== undefined) {
|
|
32
|
+
requestBody.top_p = options.topP;
|
|
33
|
+
}
|
|
34
|
+
if (options?.topK !== undefined) {
|
|
35
|
+
requestBody.top_k = options.topK;
|
|
36
|
+
}
|
|
37
|
+
if (options?.maxTokens) {
|
|
38
|
+
requestBody.num_predict = options.maxTokens;
|
|
39
|
+
}
|
|
40
|
+
const response = await fetch(`${this.config.baseUrl}/api/generate`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
headers: {
|
|
43
|
+
"Content-Type": "application/json",
|
|
44
|
+
},
|
|
45
|
+
body: JSON.stringify(requestBody),
|
|
46
|
+
});
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
const error = await response.text();
|
|
49
|
+
throw new Error(`Ollama API error: ${response.status} - ${error}`);
|
|
50
|
+
}
|
|
51
|
+
const data = (await response.json());
|
|
52
|
+
return {
|
|
53
|
+
content: data.response,
|
|
54
|
+
model: data.model,
|
|
55
|
+
tokensUsed: data.eval_count,
|
|
56
|
+
finishReason: data.done ? "stop" : "length",
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if provider is configured
|
|
61
|
+
*/
|
|
62
|
+
isConfigured() {
|
|
63
|
+
return !!(this.config.baseUrl && this.config.model);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create provider from environment variables
|
|
67
|
+
*/
|
|
68
|
+
static fromEnv(config) {
|
|
69
|
+
const baseUrl = config.baseUrl || process.env.OLLAMA_BASE_URL || "http://localhost:11434";
|
|
70
|
+
const model = config.model || process.env.OLLAMA_MODEL || "llama2";
|
|
71
|
+
return new OllamaProvider({
|
|
72
|
+
baseUrl: expandEnvVar(baseUrl),
|
|
73
|
+
model: expandEnvVar(model),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Expand environment variable in string (e.g., "${VAR_NAME}" -> actual value)
|
|
79
|
+
*/
|
|
80
|
+
function expandEnvVar(value) {
|
|
81
|
+
if (!value) {
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
const envVarMatch = value.match(/^\$\{([^}]+)\}$/);
|
|
85
|
+
if (envVarMatch?.[1]) {
|
|
86
|
+
const envVar = envVarMatch[1];
|
|
87
|
+
const envValue = process.env[envVar];
|
|
88
|
+
return envValue ?? value;
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible LLM Provider
|
|
3
|
+
* Supports: OpenAI, Azure OpenAI, Together AI, Groq, DeepSeek, and any OpenAI-compatible API
|
|
4
|
+
*/
|
|
5
|
+
import { type LLMGenerationOptions, type LLMGenerationResult, type LLMMessage, LLMProvider } from "../base.js";
|
|
6
|
+
export interface OpenAICompatibleConfig {
|
|
7
|
+
baseUrl: string;
|
|
8
|
+
apiKey: string;
|
|
9
|
+
model: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class OpenAICompatibleProvider extends LLMProvider {
|
|
12
|
+
private config;
|
|
13
|
+
constructor(config: OpenAICompatibleConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Generate text using OpenAI-compatible API
|
|
16
|
+
*/
|
|
17
|
+
generate(messages: LLMMessage[], options?: LLMGenerationOptions): Promise<LLMGenerationResult>;
|
|
18
|
+
/**
|
|
19
|
+
* Check if provider is configured
|
|
20
|
+
*/
|
|
21
|
+
isConfigured(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Create provider from environment variables
|
|
24
|
+
*/
|
|
25
|
+
static fromEnv(config: {
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
apiKey?: string;
|
|
28
|
+
model?: string;
|
|
29
|
+
}): OpenAICompatibleProvider;
|
|
30
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI-compatible LLM Provider
|
|
3
|
+
* Supports: OpenAI, Azure OpenAI, Together AI, Groq, DeepSeek, and any OpenAI-compatible API
|
|
4
|
+
*/
|
|
5
|
+
import { LLMProvider, LLMProviderType, } from "../base.js";
|
|
6
|
+
export class OpenAICompatibleProvider extends LLMProvider {
|
|
7
|
+
config;
|
|
8
|
+
constructor(config) {
|
|
9
|
+
super(LLMProviderType.OpenAICompatible, config.model);
|
|
10
|
+
this.config = config;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generate text using OpenAI-compatible API
|
|
14
|
+
*/
|
|
15
|
+
async generate(messages, options) {
|
|
16
|
+
if (!this.isConfigured()) {
|
|
17
|
+
throw new Error("OpenAI-compatible provider is not configured properly");
|
|
18
|
+
}
|
|
19
|
+
const response = await fetch(`${this.config.baseUrl}/chat/completions`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
model: this.config.model,
|
|
27
|
+
messages,
|
|
28
|
+
max_tokens: options?.maxTokens,
|
|
29
|
+
temperature: options?.temperature,
|
|
30
|
+
top_p: options?.topP,
|
|
31
|
+
stream: false,
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
if (!response.ok) {
|
|
35
|
+
const error = await response.text();
|
|
36
|
+
throw new Error(`OpenAI-compatible API error: ${response.status} - ${error}`);
|
|
37
|
+
}
|
|
38
|
+
const data = (await response.json());
|
|
39
|
+
const choice = data.choices[0];
|
|
40
|
+
if (!choice) {
|
|
41
|
+
throw new Error("No choice returned from OpenAI API");
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
content: choice.message.content,
|
|
45
|
+
model: data.model,
|
|
46
|
+
tokensUsed: data.usage?.total_tokens ?? 0,
|
|
47
|
+
finishReason: choice.finish_reason,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if provider is configured
|
|
52
|
+
*/
|
|
53
|
+
isConfigured() {
|
|
54
|
+
return !!(this.config.apiKey && this.config.baseUrl);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Create provider from environment variables
|
|
58
|
+
*/
|
|
59
|
+
static fromEnv(config) {
|
|
60
|
+
const baseUrl = config.baseUrl ||
|
|
61
|
+
process.env.OPENAI_BASE_URL ||
|
|
62
|
+
process.env.AI_BASE_URL ||
|
|
63
|
+
"https://api.openai.com/v1";
|
|
64
|
+
const apiKey = config.apiKey ||
|
|
65
|
+
process.env.OPENAI_API_KEY ||
|
|
66
|
+
process.env.AI_API_KEY ||
|
|
67
|
+
"";
|
|
68
|
+
const model = config.model || process.env.AI_MODEL || "gpt-4o-mini";
|
|
69
|
+
if (!apiKey) {
|
|
70
|
+
console.warn("Warning: OpenAI-compatible provider missing API key");
|
|
71
|
+
}
|
|
72
|
+
return new OpenAICompatibleProvider({
|
|
73
|
+
baseUrl,
|
|
74
|
+
apiKey: expandEnvVar(apiKey),
|
|
75
|
+
model,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Expand environment variable in string (e.g., "${VAR_NAME}" -> actual value)
|
|
81
|
+
*/
|
|
82
|
+
function expandEnvVar(value) {
|
|
83
|
+
if (!value) {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
const envVarMatch = value.match(/^\$\{([^}]+)\}$/);
|
|
87
|
+
if (envVarMatch?.[1]) {
|
|
88
|
+
const envVar = envVarMatch[1];
|
|
89
|
+
const envValue = process.env[envVar];
|
|
90
|
+
return envValue ?? value;
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
}
|
package/dist/schemas/config.d.ts
CHANGED
|
@@ -14,6 +14,48 @@ export declare const GatesSchema: z.ZodObject<{
|
|
|
14
14
|
requirePlanApproval: z.ZodDefault<z.ZodBoolean>;
|
|
15
15
|
requireTestPass: z.ZodDefault<z.ZodBoolean>;
|
|
16
16
|
}, z.core.$strip>;
|
|
17
|
+
declare const LLMProviderTypeSchema: z.ZodEnum<{
|
|
18
|
+
"openai-compatible": "openai-compatible";
|
|
19
|
+
anthropic: "anthropic";
|
|
20
|
+
ollama: "ollama";
|
|
21
|
+
}>;
|
|
22
|
+
declare const AIConfigSchema: z.ZodOptional<z.ZodObject<{
|
|
23
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
24
|
+
provider: z.ZodDefault<z.ZodEnum<{
|
|
25
|
+
"openai-compatible": "openai-compatible";
|
|
26
|
+
anthropic: "anthropic";
|
|
27
|
+
ollama: "ollama";
|
|
28
|
+
}>>;
|
|
29
|
+
apiKey: z.ZodOptional<z.ZodString>;
|
|
30
|
+
models: z.ZodDefault<z.ZodObject<{
|
|
31
|
+
default: z.ZodDefault<z.ZodString>;
|
|
32
|
+
planning: z.ZodOptional<z.ZodString>;
|
|
33
|
+
execution: z.ZodOptional<z.ZodString>;
|
|
34
|
+
analysis: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>>;
|
|
36
|
+
planningProvider: z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
"openai-compatible": "openai-compatible";
|
|
38
|
+
anthropic: "anthropic";
|
|
39
|
+
ollama: "ollama";
|
|
40
|
+
}>>;
|
|
41
|
+
planningApiKey: z.ZodOptional<z.ZodString>;
|
|
42
|
+
executionProvider: z.ZodOptional<z.ZodEnum<{
|
|
43
|
+
"openai-compatible": "openai-compatible";
|
|
44
|
+
anthropic: "anthropic";
|
|
45
|
+
ollama: "ollama";
|
|
46
|
+
}>>;
|
|
47
|
+
executionApiKey: z.ZodOptional<z.ZodString>;
|
|
48
|
+
analysisProvider: z.ZodOptional<z.ZodEnum<{
|
|
49
|
+
"openai-compatible": "openai-compatible";
|
|
50
|
+
anthropic: "anthropic";
|
|
51
|
+
ollama: "ollama";
|
|
52
|
+
}>>;
|
|
53
|
+
analysisApiKey: z.ZodOptional<z.ZodString>;
|
|
54
|
+
ollamaBaseUrl: z.ZodDefault<z.ZodString>;
|
|
55
|
+
openaiBaseUrl: z.ZodDefault<z.ZodString>;
|
|
56
|
+
autoContinueTask: z.ZodDefault<z.ZodBoolean>;
|
|
57
|
+
clearContextOnComplete: z.ZodDefault<z.ZodBoolean>;
|
|
58
|
+
}, z.core.$strip>>;
|
|
17
59
|
export declare const TaskflowConfigSchema: z.ZodObject<{
|
|
18
60
|
version: z.ZodDefault<z.ZodString>;
|
|
19
61
|
projectType: z.ZodDefault<z.ZodString>;
|
|
@@ -36,5 +78,45 @@ export declare const TaskflowConfigSchema: z.ZodObject<{
|
|
|
36
78
|
validate: z.ZodOptional<z.ZodString>;
|
|
37
79
|
test: z.ZodOptional<z.ZodString>;
|
|
38
80
|
}, z.core.$strip>>;
|
|
81
|
+
ai: z.ZodOptional<z.ZodObject<{
|
|
82
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
83
|
+
provider: z.ZodDefault<z.ZodEnum<{
|
|
84
|
+
"openai-compatible": "openai-compatible";
|
|
85
|
+
anthropic: "anthropic";
|
|
86
|
+
ollama: "ollama";
|
|
87
|
+
}>>;
|
|
88
|
+
apiKey: z.ZodOptional<z.ZodString>;
|
|
89
|
+
models: z.ZodDefault<z.ZodObject<{
|
|
90
|
+
default: z.ZodDefault<z.ZodString>;
|
|
91
|
+
planning: z.ZodOptional<z.ZodString>;
|
|
92
|
+
execution: z.ZodOptional<z.ZodString>;
|
|
93
|
+
analysis: z.ZodOptional<z.ZodString>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
95
|
+
planningProvider: z.ZodOptional<z.ZodEnum<{
|
|
96
|
+
"openai-compatible": "openai-compatible";
|
|
97
|
+
anthropic: "anthropic";
|
|
98
|
+
ollama: "ollama";
|
|
99
|
+
}>>;
|
|
100
|
+
planningApiKey: z.ZodOptional<z.ZodString>;
|
|
101
|
+
executionProvider: z.ZodOptional<z.ZodEnum<{
|
|
102
|
+
"openai-compatible": "openai-compatible";
|
|
103
|
+
anthropic: "anthropic";
|
|
104
|
+
ollama: "ollama";
|
|
105
|
+
}>>;
|
|
106
|
+
executionApiKey: z.ZodOptional<z.ZodString>;
|
|
107
|
+
analysisProvider: z.ZodOptional<z.ZodEnum<{
|
|
108
|
+
"openai-compatible": "openai-compatible";
|
|
109
|
+
anthropic: "anthropic";
|
|
110
|
+
ollama: "ollama";
|
|
111
|
+
}>>;
|
|
112
|
+
analysisApiKey: z.ZodOptional<z.ZodString>;
|
|
113
|
+
ollamaBaseUrl: z.ZodDefault<z.ZodString>;
|
|
114
|
+
openaiBaseUrl: z.ZodDefault<z.ZodString>;
|
|
115
|
+
autoContinueTask: z.ZodDefault<z.ZodBoolean>;
|
|
116
|
+
clearContextOnComplete: z.ZodDefault<z.ZodBoolean>;
|
|
117
|
+
}, z.core.$strip>>;
|
|
39
118
|
}, z.core.$strip>;
|
|
40
119
|
export type TaskflowConfig = z.infer<typeof TaskflowConfigSchema>;
|
|
120
|
+
export type AIConfig = z.infer<typeof AIConfigSchema>;
|
|
121
|
+
export type LLMProviderType = z.infer<typeof LLMProviderTypeSchema>;
|
|
122
|
+
export {};
|
package/dist/schemas/config.js
CHANGED
|
@@ -12,6 +12,40 @@ export const GatesSchema = z.object({
|
|
|
12
12
|
requirePlanApproval: z.boolean().default(true),
|
|
13
13
|
requireTestPass: z.boolean().default(true),
|
|
14
14
|
});
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// AI Configuration Schema
|
|
17
|
+
// ============================================================================
|
|
18
|
+
const LLMProviderTypeSchema = z.enum([
|
|
19
|
+
"openai-compatible",
|
|
20
|
+
"anthropic",
|
|
21
|
+
"ollama",
|
|
22
|
+
]);
|
|
23
|
+
const AIModelsSchema = z.object({
|
|
24
|
+
default: z.string().default("gpt-4o-mini"),
|
|
25
|
+
planning: z.string().optional(),
|
|
26
|
+
execution: z.string().optional(),
|
|
27
|
+
analysis: z.string().optional(),
|
|
28
|
+
});
|
|
29
|
+
const AIConfigSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
enabled: z.boolean().default(false),
|
|
32
|
+
provider: LLMProviderTypeSchema.default("openai-compatible"),
|
|
33
|
+
apiKey: z.string().optional(),
|
|
34
|
+
models: AIModelsSchema.default({
|
|
35
|
+
default: "gpt-4o-mini",
|
|
36
|
+
}),
|
|
37
|
+
planningProvider: LLMProviderTypeSchema.optional(),
|
|
38
|
+
planningApiKey: z.string().optional(),
|
|
39
|
+
executionProvider: LLMProviderTypeSchema.optional(),
|
|
40
|
+
executionApiKey: z.string().optional(),
|
|
41
|
+
analysisProvider: LLMProviderTypeSchema.optional(),
|
|
42
|
+
analysisApiKey: z.string().optional(),
|
|
43
|
+
ollamaBaseUrl: z.string().default("http://localhost:11434"),
|
|
44
|
+
openaiBaseUrl: z.string().default("https://api.openai.com/v1"),
|
|
45
|
+
autoContinueTask: z.boolean().default(false),
|
|
46
|
+
clearContextOnComplete: z.boolean().default(true),
|
|
47
|
+
})
|
|
48
|
+
.optional();
|
|
15
49
|
export const TaskflowConfigSchema = z.object({
|
|
16
50
|
version: z.string().default("2.0"),
|
|
17
51
|
projectType: z.string().default("custom"),
|
|
@@ -31,4 +65,5 @@ export const TaskflowConfigSchema = z.object({
|
|
|
31
65
|
test: z.string().optional(),
|
|
32
66
|
})
|
|
33
67
|
.optional(),
|
|
68
|
+
ai: AIConfigSchema,
|
|
34
69
|
});
|
package/package.json
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
2
|
+
"name": "@krr2020/taskflow-core",
|
|
3
|
+
"version": "0.1.0-beta.5",
|
|
4
|
+
"description": "Core logic for Taskflow - AI-first task management and workflow system",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"bin": {
|
|
13
|
+
"taskflow": "./bin/taskflow.js"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"bin",
|
|
18
|
+
"templates"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"test": "vitest"
|
|
23
|
+
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": "./dist/index.js",
|
|
27
|
+
"types": "./dist/index.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./config": {
|
|
30
|
+
"import": "./dist/config.js",
|
|
31
|
+
"types": "./dist/config.d.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"zod": "4.3.2",
|
|
36
|
+
"execa": "9.6.1",
|
|
37
|
+
"commander": "14.0.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "5.9.3",
|
|
41
|
+
"vitest": "4.0.16",
|
|
42
|
+
"@types/node": "25.0.3"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export type PackageManager = "npm" | "pnpm" | "yarn" | "bun";
|
|
2
|
-
export interface PackageManagerCommands {
|
|
3
|
-
run: string;
|
|
4
|
-
exec: string;
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Detect the package manager used in the project
|
|
8
|
-
*/
|
|
9
|
-
export declare function detectPackageManager(projectRoot: string): PackageManager;
|
|
10
|
-
/**
|
|
11
|
-
* Get the run command prefix for the detected package manager
|
|
12
|
-
*/
|
|
13
|
-
export declare function getRunCommand(projectRoot: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* Get the exec command prefix for the detected package manager
|
|
16
|
-
*/
|
|
17
|
-
export declare function getExecCommand(projectRoot: string): string;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
const COMMANDS = {
|
|
4
|
-
npm: {
|
|
5
|
-
run: "npm run",
|
|
6
|
-
exec: "npx",
|
|
7
|
-
},
|
|
8
|
-
pnpm: {
|
|
9
|
-
run: "pnpm run",
|
|
10
|
-
exec: "pnpm exec",
|
|
11
|
-
},
|
|
12
|
-
yarn: {
|
|
13
|
-
run: "yarn run",
|
|
14
|
-
exec: "yarn run",
|
|
15
|
-
},
|
|
16
|
-
bun: {
|
|
17
|
-
run: "bun run",
|
|
18
|
-
exec: "bun x",
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Detect the package manager used in the project
|
|
23
|
-
*/
|
|
24
|
-
export function detectPackageManager(projectRoot) {
|
|
25
|
-
if (fs.existsSync(path.join(projectRoot, "pnpm-lock.yaml"))) {
|
|
26
|
-
return "pnpm";
|
|
27
|
-
}
|
|
28
|
-
if (fs.existsSync(path.join(projectRoot, "yarn.lock"))) {
|
|
29
|
-
return "yarn";
|
|
30
|
-
}
|
|
31
|
-
if (fs.existsSync(path.join(projectRoot, "bun.lockb"))) {
|
|
32
|
-
return "bun";
|
|
33
|
-
}
|
|
34
|
-
if (fs.existsSync(path.join(projectRoot, "package-lock.json"))) {
|
|
35
|
-
return "npm";
|
|
36
|
-
}
|
|
37
|
-
// Default to npm if no lock file found
|
|
38
|
-
return "npm";
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Get the run command prefix for the detected package manager
|
|
42
|
-
*/
|
|
43
|
-
export function getRunCommand(projectRoot) {
|
|
44
|
-
const pm = detectPackageManager(projectRoot);
|
|
45
|
-
return COMMANDS[pm].run;
|
|
46
|
-
}
|
|
47
|
-
/**
|
|
48
|
-
* Get the exec command prefix for the detected package manager
|
|
49
|
-
*/
|
|
50
|
-
export function getExecCommand(projectRoot) {
|
|
51
|
-
const pm = detectPackageManager(projectRoot);
|
|
52
|
-
return COMMANDS[pm].exec;
|
|
53
|
-
}
|