@ekzs/cli 0.3.5 → 0.3.8
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/LICENSE +21 -0
- package/README.md +12 -12
- package/dist/commands/ask.d.ts.map +1 -1
- package/dist/commands/ask.js +12 -5
- package/dist/commands/local-agent.d.ts.map +1 -1
- package/dist/commands/local-agent.js +47 -3
- package/dist/lib/context.d.ts +12 -2
- package/dist/lib/context.d.ts.map +1 -1
- package/dist/lib/context.js +75 -23
- package/dist/lib/doctor-quiet.d.ts +3 -1
- package/dist/lib/doctor-quiet.d.ts.map +1 -1
- package/dist/lib/doctor-quiet.js +16 -2
- package/dist/lib/local-answer.d.ts +4 -0
- package/dist/lib/local-answer.d.ts.map +1 -0
- package/dist/lib/local-answer.js +26 -0
- package/dist/lib/providers/agent-runner.d.ts +1 -0
- package/dist/lib/providers/agent-runner.d.ts.map +1 -1
- package/dist/lib/providers/agent-runner.js +48 -22
- package/dist/lib/providers/catalog.d.ts +14 -0
- package/dist/lib/providers/catalog.d.ts.map +1 -1
- package/dist/lib/providers/catalog.js +125 -38
- package/dist/lib/providers/chat.d.ts.map +1 -1
- package/dist/lib/providers/chat.js +46 -31
- package/dist/lib/providers/cursor-runner.d.ts.map +1 -1
- package/dist/lib/providers/cursor-runner.js +16 -8
- package/dist/lib/providers/http.d.ts +6 -0
- package/dist/lib/providers/http.d.ts.map +1 -0
- package/dist/lib/providers/http.js +35 -0
- package/dist/lib/providers/ui.d.ts.map +1 -1
- package/dist/lib/providers/ui.js +4 -3
- package/dist/lib/skills.d.ts +3 -1
- package/dist/lib/skills.d.ts.map +1 -1
- package/dist/lib/skills.js +18 -8
- package/dist/lib/terminal-answer.d.ts +5 -0
- package/dist/lib/terminal-answer.d.ts.map +1 -0
- package/dist/lib/terminal-answer.js +55 -0
- package/package.json +2 -2
|
@@ -13,7 +13,21 @@ export type ProviderDefinition = {
|
|
|
13
13
|
models: string[];
|
|
14
14
|
keyHint: string;
|
|
15
15
|
docsUrl: string;
|
|
16
|
+
capabilities: {
|
|
17
|
+
requiresApiKey: boolean;
|
|
18
|
+
supportsTools: boolean;
|
|
19
|
+
supportsStreaming: boolean;
|
|
20
|
+
supportsReasoning: boolean;
|
|
21
|
+
liteTimeoutMs: number;
|
|
22
|
+
agentTimeoutMs: number;
|
|
23
|
+
};
|
|
16
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Model IDs synced from official provider docs (May 2026).
|
|
27
|
+
* Sources: cursor.com/docs, developers.openai.com, platform.claude.com,
|
|
28
|
+
* api-docs.deepseek.com, platform.kimi.ai, console.groq.com/docs/models,
|
|
29
|
+
* docs.mistral.ai, ai.google.dev/gemini-api/docs/models, ollama.com/library
|
|
30
|
+
*/
|
|
17
31
|
export declare const PROVIDER_CATALOG: ProviderDefinition[];
|
|
18
32
|
export declare function getProviderDefinition(id: string): ProviderDefinition | undefined;
|
|
19
33
|
export declare function resolveProviderModel(def: ProviderDefinition, storedModel?: string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,mBAAmB,GAAG,WAAW,CAAC;AAExE,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,UAAU,GACV,MAAM,GACN,MAAM,GACN,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/catalog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,mBAAmB,GAAG,WAAW,CAAC;AAExE,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,WAAW,GACX,UAAU,GACV,MAAM,GACN,MAAM,GACN,SAAS,GACT,QAAQ,GACR,QAAQ,CAAC;AAEb,MAAM,MAAM,kBAAkB,GAAG;IAC/B,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE;QACZ,cAAc,EAAE,OAAO,CAAC;QACxB,aAAa,EAAE,OAAO,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC;QAC3B,iBAAiB,EAAE,OAAO,CAAC;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH,CAAC;AAWF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,kBAAkB,EA2LhD,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAEhF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,kBAAkB,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAK1F"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
const CLOUD_AGENT_CAPABILITIES = {
|
|
2
|
+
requiresApiKey: true,
|
|
3
|
+
supportsTools: true,
|
|
4
|
+
supportsStreaming: false,
|
|
5
|
+
supportsReasoning: false,
|
|
6
|
+
liteTimeoutMs: 20_000,
|
|
7
|
+
agentTimeoutMs: 60_000,
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Model IDs synced from official provider docs (May 2026).
|
|
11
|
+
* Sources: cursor.com/docs, developers.openai.com, platform.claude.com,
|
|
12
|
+
* api-docs.deepseek.com, platform.kimi.ai, console.groq.com/docs/models,
|
|
13
|
+
* docs.mistral.ai, ai.google.dev/gemini-api/docs/models, ollama.com/library
|
|
14
|
+
*/
|
|
1
15
|
export const PROVIDER_CATALOG = [
|
|
2
16
|
{
|
|
3
17
|
id: "cursor",
|
|
@@ -7,110 +21,183 @@ export const PROVIDER_CATALOG = [
|
|
|
7
21
|
defaultModel: "composer-2.5-fast",
|
|
8
22
|
models: [
|
|
9
23
|
"composer-2.5-fast",
|
|
10
|
-
"composer-2-fast",
|
|
11
24
|
"composer-2.5",
|
|
25
|
+
"composer-2-fast",
|
|
12
26
|
"composer-2",
|
|
13
|
-
"claude-4.6-sonnet-
|
|
14
|
-
"claude-opus-4-7
|
|
15
|
-
"
|
|
16
|
-
"gemini-3.
|
|
17
|
-
"gpt-5.3-codex",
|
|
18
|
-
"gpt-5.5-medium",
|
|
27
|
+
"claude-4.6-sonnet-thinking",
|
|
28
|
+
"claude-opus-4-7",
|
|
29
|
+
"gpt-5.5",
|
|
30
|
+
"gemini-3.5-flash",
|
|
19
31
|
"kimi-k2.5",
|
|
20
32
|
],
|
|
21
33
|
keyHint: "crsr_…",
|
|
22
34
|
docsUrl: "https://cursor.com/dashboard/integrations",
|
|
35
|
+
capabilities: {
|
|
36
|
+
requiresApiKey: true,
|
|
37
|
+
supportsTools: true,
|
|
38
|
+
supportsStreaming: true,
|
|
39
|
+
supportsReasoning: false,
|
|
40
|
+
liteTimeoutMs: 20_000,
|
|
41
|
+
agentTimeoutMs: 90_000,
|
|
42
|
+
},
|
|
23
43
|
},
|
|
24
44
|
{
|
|
25
45
|
id: "openai",
|
|
26
46
|
name: "OpenAI",
|
|
27
47
|
kind: "openai-compatible",
|
|
28
|
-
description: "GPT-
|
|
29
|
-
defaultModel: "gpt-
|
|
48
|
+
description: "GPT-5.5 frontier · GPT-5.4 · o-series",
|
|
49
|
+
defaultModel: "gpt-5.5",
|
|
30
50
|
defaultBaseUrl: "https://api.openai.com/v1",
|
|
31
|
-
models: [
|
|
51
|
+
models: [
|
|
52
|
+
"gpt-5.5",
|
|
53
|
+
"gpt-5.4",
|
|
54
|
+
"gpt-5.4-mini",
|
|
55
|
+
"gpt-5.4-nano",
|
|
56
|
+
"gpt-4.1",
|
|
57
|
+
"gpt-4.1-mini",
|
|
58
|
+
"gpt-4o",
|
|
59
|
+
"gpt-4o-mini",
|
|
60
|
+
"o3",
|
|
61
|
+
"o4-mini",
|
|
62
|
+
],
|
|
32
63
|
keyHint: "sk-…",
|
|
33
64
|
docsUrl: "https://platform.openai.com/api-keys",
|
|
65
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
34
66
|
},
|
|
35
67
|
{
|
|
36
68
|
id: "anthropic",
|
|
37
69
|
name: "Anthropic",
|
|
38
70
|
kind: "anthropic",
|
|
39
|
-
description: "Claude Sonnet
|
|
40
|
-
defaultModel: "claude-sonnet-4-
|
|
71
|
+
description: "Claude Opus 4.7 · Sonnet 4.6 · Haiku 4.5",
|
|
72
|
+
defaultModel: "claude-sonnet-4-6",
|
|
41
73
|
models: [
|
|
42
|
-
"claude-sonnet-4-
|
|
43
|
-
"claude-opus-4-
|
|
44
|
-
"claude-
|
|
74
|
+
"claude-sonnet-4-6",
|
|
75
|
+
"claude-opus-4-7",
|
|
76
|
+
"claude-haiku-4-5-20251001",
|
|
77
|
+
"claude-opus-4-6",
|
|
78
|
+
"claude-sonnet-4-5-20250929",
|
|
79
|
+
"claude-opus-4-5-20251101",
|
|
45
80
|
],
|
|
46
81
|
keyHint: "sk-ant-…",
|
|
47
82
|
docsUrl: "https://console.anthropic.com/settings/keys",
|
|
83
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
48
84
|
},
|
|
49
85
|
{
|
|
50
86
|
id: "deepseek",
|
|
51
87
|
name: "DeepSeek",
|
|
52
88
|
kind: "openai-compatible",
|
|
53
|
-
description: "DeepSeek
|
|
54
|
-
defaultModel: "deepseek-
|
|
55
|
-
defaultBaseUrl: "https://api.deepseek.com",
|
|
56
|
-
models: ["deepseek-chat", "deepseek-reasoner"],
|
|
89
|
+
description: "DeepSeek V4 Pro · V4 Flash",
|
|
90
|
+
defaultModel: "deepseek-v4-flash",
|
|
91
|
+
defaultBaseUrl: "https://api.deepseek.com/v1",
|
|
92
|
+
models: ["deepseek-v4-flash", "deepseek-v4-pro", "deepseek-chat", "deepseek-reasoner"],
|
|
57
93
|
keyHint: "sk-…",
|
|
58
94
|
docsUrl: "https://platform.deepseek.com/api_keys",
|
|
95
|
+
capabilities: {
|
|
96
|
+
...CLOUD_AGENT_CAPABILITIES,
|
|
97
|
+
supportsReasoning: true,
|
|
98
|
+
},
|
|
59
99
|
},
|
|
60
100
|
{
|
|
61
101
|
id: "kimi",
|
|
62
102
|
name: "Kimi (Moonshot)",
|
|
63
103
|
kind: "openai-compatible",
|
|
64
|
-
description: "Moonshot
|
|
65
|
-
defaultModel: "
|
|
66
|
-
defaultBaseUrl: "https://api.moonshot.
|
|
67
|
-
models: [
|
|
104
|
+
description: "Kimi K2.6 · K2.5 · Moonshot V1",
|
|
105
|
+
defaultModel: "kimi-k2.6",
|
|
106
|
+
defaultBaseUrl: "https://api.moonshot.ai/v1",
|
|
107
|
+
models: [
|
|
108
|
+
"kimi-k2.6",
|
|
109
|
+
"kimi-k2.5",
|
|
110
|
+
"moonshot-v1-8k",
|
|
111
|
+
"moonshot-v1-32k",
|
|
112
|
+
"moonshot-v1-128k",
|
|
113
|
+
],
|
|
68
114
|
keyHint: "sk-…",
|
|
69
|
-
docsUrl: "https://platform.
|
|
115
|
+
docsUrl: "https://platform.kimi.ai/docs/models",
|
|
116
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
70
117
|
},
|
|
71
118
|
{
|
|
72
119
|
id: "groq",
|
|
73
120
|
name: "Groq",
|
|
74
121
|
kind: "openai-compatible",
|
|
75
|
-
description: "Fast
|
|
122
|
+
description: "Fast Llama · GPT-OSS · Qwen3",
|
|
76
123
|
defaultModel: "llama-3.3-70b-versatile",
|
|
77
124
|
defaultBaseUrl: "https://api.groq.com/openai/v1",
|
|
78
|
-
models: [
|
|
125
|
+
models: [
|
|
126
|
+
"llama-3.3-70b-versatile",
|
|
127
|
+
"llama-3.1-8b-instant",
|
|
128
|
+
"openai/gpt-oss-120b",
|
|
129
|
+
"openai/gpt-oss-20b",
|
|
130
|
+
"qwen/qwen3-32b",
|
|
131
|
+
"meta-llama/llama-4-scout-17b-16e-instruct",
|
|
132
|
+
],
|
|
79
133
|
keyHint: "gsk_…",
|
|
80
|
-
docsUrl: "https://console.groq.com/
|
|
134
|
+
docsUrl: "https://console.groq.com/docs/models",
|
|
135
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
81
136
|
},
|
|
82
137
|
{
|
|
83
138
|
id: "mistral",
|
|
84
139
|
name: "Mistral",
|
|
85
140
|
kind: "openai-compatible",
|
|
86
|
-
description: "Mistral Large",
|
|
141
|
+
description: "Mistral Large · Small · Codestral",
|
|
87
142
|
defaultModel: "mistral-large-latest",
|
|
88
143
|
defaultBaseUrl: "https://api.mistral.ai/v1",
|
|
89
|
-
models: [
|
|
144
|
+
models: [
|
|
145
|
+
"mistral-large-latest",
|
|
146
|
+
"mistral-small-latest",
|
|
147
|
+
"mistral-medium-latest",
|
|
148
|
+
"codestral-latest",
|
|
149
|
+
"devstral-latest",
|
|
150
|
+
"magistral-medium-latest",
|
|
151
|
+
],
|
|
90
152
|
keyHint: "…",
|
|
91
|
-
docsUrl: "https://
|
|
153
|
+
docsUrl: "https://docs.mistral.ai/models/overview",
|
|
154
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
92
155
|
},
|
|
93
156
|
{
|
|
94
157
|
id: "google",
|
|
95
158
|
name: "Google Gemini",
|
|
96
159
|
kind: "openai-compatible",
|
|
97
|
-
description: "Gemini
|
|
98
|
-
defaultModel: "gemini-
|
|
160
|
+
description: "Gemini 3.5 · 3.1 · 2.5",
|
|
161
|
+
defaultModel: "gemini-3.5-flash",
|
|
99
162
|
defaultBaseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
100
|
-
models: [
|
|
163
|
+
models: [
|
|
164
|
+
"gemini-3.5-flash",
|
|
165
|
+
"gemini-3.1-pro-preview",
|
|
166
|
+
"gemini-3.1-flash-lite-preview",
|
|
167
|
+
"gemini-2.5-pro",
|
|
168
|
+
"gemini-2.5-flash",
|
|
169
|
+
"gemini-2.5-flash-lite",
|
|
170
|
+
],
|
|
101
171
|
keyHint: "AI…",
|
|
102
|
-
docsUrl: "https://
|
|
172
|
+
docsUrl: "https://ai.google.dev/gemini-api/docs/models",
|
|
173
|
+
capabilities: CLOUD_AGENT_CAPABILITIES,
|
|
103
174
|
},
|
|
104
175
|
{
|
|
105
176
|
id: "ollama",
|
|
106
177
|
name: "Ollama",
|
|
107
178
|
kind: "openai-compatible",
|
|
108
|
-
description: "Local models",
|
|
109
|
-
defaultModel: "llama3.
|
|
179
|
+
description: "Local models (tags match `ollama run`)",
|
|
180
|
+
defaultModel: "llama3.3",
|
|
110
181
|
defaultBaseUrl: "http://127.0.0.1:11434/v1",
|
|
111
|
-
models: [
|
|
182
|
+
models: [
|
|
183
|
+
"llama3.3",
|
|
184
|
+
"llama3.2",
|
|
185
|
+
"qwen3:8b",
|
|
186
|
+
"qwen2.5-coder:7b",
|
|
187
|
+
"deepseek-r1:8b",
|
|
188
|
+
"mistral",
|
|
189
|
+
"gemma3:4b",
|
|
190
|
+
],
|
|
112
191
|
keyHint: "ollama (optional)",
|
|
113
|
-
docsUrl: "https://ollama.com",
|
|
192
|
+
docsUrl: "https://ollama.com/library",
|
|
193
|
+
capabilities: {
|
|
194
|
+
requiresApiKey: false,
|
|
195
|
+
supportsTools: false,
|
|
196
|
+
supportsStreaming: false,
|
|
197
|
+
supportsReasoning: false,
|
|
198
|
+
liteTimeoutMs: 10_000,
|
|
199
|
+
agentTimeoutMs: 30_000,
|
|
200
|
+
},
|
|
114
201
|
},
|
|
115
202
|
];
|
|
116
203
|
export function getProviderDefinition(id) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/chat.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGnE,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"chat.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/chat.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAGnE,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,kBAAkB,CAAC;AAsH1B,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,KAAK,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GAAG,OAAO,CAAC,OAAO,CAAC,CA6DnB"}
|
|
@@ -1,44 +1,51 @@
|
|
|
1
|
-
import { buildBootstrapContext } from "../context.js";
|
|
1
|
+
import { buildBootstrapContext, isLiteTurn, needsIntegrationContext } from "../context.js";
|
|
2
2
|
import { languageInstruction } from "../locale.js";
|
|
3
3
|
import { agentScopeBlock } from "../scope.js";
|
|
4
4
|
import { fail, info, ok } from "../output.js";
|
|
5
5
|
import { ProviderSetupError, requireActiveCredentials, } from "./credentials.js";
|
|
6
|
-
|
|
6
|
+
import { deepseekRequestBody, fetchWithTimeout, resolveChatCompletionsUrl, } from "./http.js";
|
|
7
|
+
import { formatTerminalAnswer, terminalStyleInstruction } from "../terminal-answer.js";
|
|
8
|
+
function buildAskSystemPrompt(ctx, locale, lite) {
|
|
9
|
+
const diagnostics = lite
|
|
10
|
+
? { issues: ctx.doctor.issues.slice(0, 6), rails: ctx.doctor.rails, envKeys: Object.keys(ctx.env) }
|
|
11
|
+
: {
|
|
12
|
+
issues: ctx.doctor.issues,
|
|
13
|
+
warnings: ctx.doctor.warnings,
|
|
14
|
+
rails: ctx.doctor.rails,
|
|
15
|
+
health: ctx.doctor.health,
|
|
16
|
+
scan: ctx.scan.slice(0, 12),
|
|
17
|
+
env: ctx.env,
|
|
18
|
+
};
|
|
7
19
|
return `You are **Ekz Connect** — an e-Kwanza v2.4 integration assistant.
|
|
8
20
|
Answer in clear, actionable steps. You are in **ask mode**: explain and guide only; do not claim you edited files.
|
|
9
21
|
|
|
10
22
|
${agentScopeBlock(locale)}
|
|
11
23
|
|
|
12
|
-
${languageInstruction(locale)}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
rails: ctx.doctor.rails,
|
|
19
|
-
health: ctx.doctor.health,
|
|
20
|
-
scan: ctx.scan.slice(0, 12),
|
|
21
|
-
env: ctx.env,
|
|
22
|
-
}, null, 2)}`;
|
|
24
|
+
${languageInstruction(locale)}
|
|
25
|
+
|
|
26
|
+
${terminalStyleInstruction(locale)}
|
|
27
|
+
|
|
28
|
+
## Project context (doctor + scan)
|
|
29
|
+
${JSON.stringify(diagnostics, null, 2)}`;
|
|
23
30
|
}
|
|
24
|
-
async function chatOpenAiCompatible(creds, messages) {
|
|
25
|
-
const
|
|
26
|
-
const url = base.endsWith("/chat/completions") ? base : `${base}/chat/completions`;
|
|
31
|
+
async function chatOpenAiCompatible(creds, messages, options) {
|
|
32
|
+
const url = resolveChatCompletionsUrl(creds.baseUrl);
|
|
27
33
|
const headers = {
|
|
28
34
|
"Content-Type": "application/json",
|
|
29
35
|
};
|
|
30
36
|
if (creds.apiKey && creds.apiKey !== "ollama") {
|
|
31
37
|
headers.Authorization = `Bearer ${creds.apiKey}`;
|
|
32
38
|
}
|
|
33
|
-
const
|
|
39
|
+
const body = deepseekRequestBody(creds.model, {
|
|
40
|
+
model: creds.model,
|
|
41
|
+
messages,
|
|
42
|
+
temperature: 0.2,
|
|
43
|
+
}, { thinking: options?.thinking });
|
|
44
|
+
const res = await fetchWithTimeout(url, {
|
|
34
45
|
method: "POST",
|
|
35
46
|
headers,
|
|
36
|
-
body: JSON.stringify(
|
|
37
|
-
|
|
38
|
-
messages,
|
|
39
|
-
temperature: 0.2,
|
|
40
|
-
}),
|
|
41
|
-
});
|
|
47
|
+
body: JSON.stringify(body),
|
|
48
|
+
}, options?.timeoutMs);
|
|
42
49
|
const data = (await res.json().catch(() => ({})));
|
|
43
50
|
if (!res.ok) {
|
|
44
51
|
throw new Error(data.error?.message ?? `Provider error (${res.status})`);
|
|
@@ -48,8 +55,8 @@ async function chatOpenAiCompatible(creds, messages) {
|
|
|
48
55
|
throw new Error("Empty response from provider.");
|
|
49
56
|
return text;
|
|
50
57
|
}
|
|
51
|
-
async function chatAnthropic(creds, system, question) {
|
|
52
|
-
const res = await
|
|
58
|
+
async function chatAnthropic(creds, system, question, timeoutMs) {
|
|
59
|
+
const res = await fetchWithTimeout("https://api.anthropic.com/v1/messages", {
|
|
53
60
|
method: "POST",
|
|
54
61
|
headers: {
|
|
55
62
|
"Content-Type": "application/json",
|
|
@@ -62,7 +69,7 @@ async function chatAnthropic(creds, system, question) {
|
|
|
62
69
|
system,
|
|
63
70
|
messages: [{ role: "user", content: question }],
|
|
64
71
|
}),
|
|
65
|
-
});
|
|
72
|
+
}, timeoutMs);
|
|
66
73
|
const data = (await res.json().catch(() => ({})));
|
|
67
74
|
if (!res.ok) {
|
|
68
75
|
throw new Error(data.error?.message ?? `Anthropic error (${res.status})`);
|
|
@@ -78,7 +85,8 @@ async function chatAnthropic(creds, system, question) {
|
|
|
78
85
|
}
|
|
79
86
|
export async function executeByokAskTurn(options) {
|
|
80
87
|
const locale = options.locale ?? "pt";
|
|
81
|
-
const
|
|
88
|
+
const lite = isLiteTurn(options.question);
|
|
89
|
+
const ctx = await buildBootstrapContext(options.cwd, { includeScan: !lite });
|
|
82
90
|
let creds;
|
|
83
91
|
try {
|
|
84
92
|
creds = options.creds ?? requireActiveCredentials(locale);
|
|
@@ -98,20 +106,27 @@ export async function executeByokAskTurn(options) {
|
|
|
98
106
|
: "Cursor ask uses the Cursor agent path — switch provider or use agent mode.");
|
|
99
107
|
return false;
|
|
100
108
|
}
|
|
101
|
-
const system = buildAskSystemPrompt(ctx, locale);
|
|
109
|
+
const system = buildAskSystemPrompt(ctx, locale, lite);
|
|
110
|
+
const timeoutMs = lite
|
|
111
|
+
? creds.definition.capabilities.liteTimeoutMs
|
|
112
|
+
: creds.definition.capabilities.agentTimeoutMs;
|
|
102
113
|
if (!options.quiet) {
|
|
103
114
|
info(`${creds.definition.name} · ${creds.model}`);
|
|
104
115
|
}
|
|
105
116
|
try {
|
|
106
117
|
const answer = creds.definition.kind === "anthropic"
|
|
107
|
-
? await chatAnthropic(creds, system, options.question)
|
|
118
|
+
? await chatAnthropic(creds, system, options.question, timeoutMs)
|
|
108
119
|
: await chatOpenAiCompatible(creds, [
|
|
109
120
|
{ role: "system", content: system },
|
|
110
121
|
{ role: "user", content: options.question },
|
|
111
|
-
]
|
|
122
|
+
], {
|
|
123
|
+
thinking: creds.definition.capabilities.supportsReasoning &&
|
|
124
|
+
needsIntegrationContext(options.question),
|
|
125
|
+
timeoutMs,
|
|
126
|
+
});
|
|
112
127
|
if (!options.quiet)
|
|
113
128
|
ok(creds.definition.name);
|
|
114
|
-
console.log("\n" + answer);
|
|
129
|
+
console.log("\n" + formatTerminalAnswer(answer));
|
|
115
130
|
return true;
|
|
116
131
|
}
|
|
117
132
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/cursor-runner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"cursor-runner.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/cursor-runner.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,cAAc,CAAC;AAKnE,OAAO,EAAiB,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC/D,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,iBAAe,YAAY,CAAC,KAAK,EAAE,QAAQ,iBAI1C;AAED,iBAAe,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1F;AAED,wBAAsB,oBAAoB,CAAC,OAAO,EAAE;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,SAAS,CAAC;CACnB,GAAG,OAAO,CAAC,OAAO,CAAC,CA0CnB;AAED,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { resolve } from "path";
|
|
2
|
-
import { buildBootstrapContext } from "../context.js";
|
|
2
|
+
import { buildBootstrapContext, isLiteTurn } from "../context.js";
|
|
3
3
|
import { resolveComposerModel } from "../composer-model.js";
|
|
4
4
|
import { languageInstruction } from "../locale.js";
|
|
5
5
|
import { fail } from "../output.js";
|
|
6
6
|
import { agentScopeBlock } from "../scope.js";
|
|
7
|
+
import { formatTerminalDelta, terminalStyleInstruction } from "../terminal-answer.js";
|
|
7
8
|
import { toolDone, toolError, toolRunning } from "../theme.js";
|
|
8
9
|
import { loadCursorSdk } from "./cursor-sdk.js";
|
|
9
10
|
async function disposeAgent(agent) {
|
|
@@ -17,8 +18,9 @@ async function streamRun(agent, prompt, locale) {
|
|
|
17
18
|
const { AgentBusyError, CursorAgentError } = await loadCursorSdk(locale);
|
|
18
19
|
const sendOptions = {
|
|
19
20
|
onDelta: ({ update }) => {
|
|
20
|
-
if (update.type === "text-delta" && update.text)
|
|
21
|
-
process.stdout.write(update.text);
|
|
21
|
+
if (update.type === "text-delta" && update.text) {
|
|
22
|
+
process.stdout.write(formatTerminalDelta(update.text));
|
|
23
|
+
}
|
|
22
24
|
},
|
|
23
25
|
};
|
|
24
26
|
let run;
|
|
@@ -51,17 +53,23 @@ async function streamRun(agent, prompt, locale) {
|
|
|
51
53
|
}
|
|
52
54
|
export async function executeCursorAskTurn(options) {
|
|
53
55
|
const cwd = resolve(options.cwd);
|
|
54
|
-
const
|
|
56
|
+
const lite = isLiteTurn(options.question);
|
|
57
|
+
const ctx = await buildBootstrapContext(cwd, { includeScan: !lite });
|
|
55
58
|
const model = resolveComposerModel(process.env, options.creds.model);
|
|
56
59
|
const { Agent } = await loadCursorSdk(options.locale);
|
|
60
|
+
const diagnostics = lite
|
|
61
|
+
? { issues: ctx.doctor.issues.slice(0, 6), rails: ctx.doctor.rails, envKeys: Object.keys(ctx.env) }
|
|
62
|
+
: { issues: ctx.doctor.issues, scan: ctx.scan.slice(0, 12), env: ctx.env };
|
|
57
63
|
const prompt = `${agentScopeBlock(options.locale)}
|
|
58
64
|
|
|
59
|
-
${languageInstruction(options.locale)}
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
${languageInstruction(options.locale)}
|
|
66
|
+
|
|
67
|
+
${terminalStyleInstruction(options.locale)}
|
|
68
|
+
|
|
69
|
+
You are in ask mode: answer only. Do not edit files or run tools unless the user explicitly asks for a command example.
|
|
62
70
|
|
|
63
71
|
## Project context
|
|
64
|
-
${JSON.stringify(
|
|
72
|
+
${JSON.stringify(diagnostics, null, 2)}
|
|
65
73
|
|
|
66
74
|
## Question
|
|
67
75
|
${options.question}`;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function resolveChatCompletionsUrl(baseUrl?: string): string;
|
|
2
|
+
export declare function fetchWithTimeout(url: string, init: RequestInit, timeoutMs?: number): Promise<Response>;
|
|
3
|
+
export declare function deepseekRequestBody(model: string, body: Record<string, unknown>, options?: {
|
|
4
|
+
thinking?: boolean;
|
|
5
|
+
}): Record<string, unknown>;
|
|
6
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/http.ts"],"names":[],"mappings":"AAEA,wBAAgB,yBAAyB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKlE;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,WAAW,EACjB,SAAS,SAAqB,GAC7B,OAAO,CAAC,QAAQ,CAAC,CAanB;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GAC/B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOzB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
2
|
+
export function resolveChatCompletionsUrl(baseUrl) {
|
|
3
|
+
const base = (baseUrl ?? "https://api.openai.com/v1").replace(/\/$/, "");
|
|
4
|
+
if (base.endsWith("/chat/completions"))
|
|
5
|
+
return base;
|
|
6
|
+
if (base.endsWith("/v1"))
|
|
7
|
+
return `${base}/chat/completions`;
|
|
8
|
+
return `${base}/chat/completions`;
|
|
9
|
+
}
|
|
10
|
+
export async function fetchWithTimeout(url, init, timeoutMs = DEFAULT_TIMEOUT_MS) {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
13
|
+
try {
|
|
14
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
18
|
+
throw new Error(`Provider request timed out after ${Math.round(timeoutMs / 1000)}s.`);
|
|
19
|
+
}
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
clearTimeout(timer);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function deepseekRequestBody(model, body, options) {
|
|
27
|
+
if (!model.startsWith("deepseek-v4"))
|
|
28
|
+
return body;
|
|
29
|
+
if (options?.thinking === false)
|
|
30
|
+
return body;
|
|
31
|
+
return {
|
|
32
|
+
...body,
|
|
33
|
+
thinking: { type: "enabled" },
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../src/lib/providers/ui.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AA4N9C,gEAAgE;AAChE,wBAAsB,sBAAsB,CAAC,MAAM,GAAE,SAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAoBvF;AAED,wBAAsB,uBAAuB,CAAC,MAAM,GAAE,SAAgB,iBAuDrE;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMnE"}
|
package/dist/lib/providers/ui.js
CHANGED
|
@@ -140,15 +140,16 @@ async function configureProvider(id, locale) {
|
|
|
140
140
|
}
|
|
141
141
|
const keyPrompt = t(locale, `Cola a API key (${def.keyHint}): `, `Paste API key (${def.keyHint}): `, `粘贴 API key (${def.keyHint}): `);
|
|
142
142
|
const apiKey = await askLine(keyPrompt, true);
|
|
143
|
-
if (!apiKey) {
|
|
143
|
+
if (!apiKey && def.capabilities.requiresApiKey) {
|
|
144
144
|
warn(t(locale, "Chave vazia — cancelado.", "Empty key — cancelled.", "密钥为空,已取消。"));
|
|
145
145
|
return false;
|
|
146
146
|
}
|
|
147
|
+
const storedApiKey = apiKey || def.id;
|
|
147
148
|
const model = await pickModel(id, locale);
|
|
148
149
|
if (!model)
|
|
149
150
|
return false;
|
|
150
|
-
setStoredProvider(id, { apiKey, model });
|
|
151
|
-
ok(t(locale, `Guardado ${def.name} · ${model} (${maskApiKey(
|
|
151
|
+
setStoredProvider(id, { apiKey: storedApiKey, model });
|
|
152
|
+
ok(t(locale, `Guardado ${def.name} · ${model} (${maskApiKey(storedApiKey)})`, `Saved ${def.name} · ${model} (${maskApiKey(storedApiKey)})`, `已保存 ${def.name} · ${model} (${maskApiKey(storedApiKey)})`));
|
|
152
153
|
return true;
|
|
153
154
|
}
|
|
154
155
|
function resolveRowTarget(rows, target) {
|
package/dist/lib/skills.d.ts
CHANGED
|
@@ -7,7 +7,9 @@ export type EkzSkill = {
|
|
|
7
7
|
declare const SKILL_IDS: readonly ["ekz-connect", "ekz-payment-core-architecture", "ekz-ekwanza-provider-adapter", "ekz-webhook-normalization", "ekz-one-time-product-payments", "ekz-ticket-invite-selling", "ekz-subscription-billing", "ekz-overage-billing", "ekz-integration-playbook", "ekz-data-layer-design", "ekz-data-postgres", "ekz-data-mysql", "ekz-data-sqlite", "ekz-data-mongo", "ekz-sdk-cli"];
|
|
8
8
|
export type EkzSkillId = (typeof SKILL_IDS)[number];
|
|
9
9
|
export declare function loadAllSkills(): EkzSkill[];
|
|
10
|
-
export declare function selectSkillsForTask(task: string, scanRules?: string[]
|
|
10
|
+
export declare function selectSkillsForTask(task: string, scanRules?: string[], options?: {
|
|
11
|
+
lite?: boolean;
|
|
12
|
+
}): EkzSkill[];
|
|
11
13
|
export declare function formatSkillsForPrompt(skills: EkzSkill[]): string;
|
|
12
14
|
export declare function listSkillIds(): string[];
|
|
13
15
|
/** @deprecated use formatSkillsForPrompt(selectSkillsForTask(...)) */
|
package/dist/lib/skills.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,QAAA,MAAM,SAAS,yXAgBL,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,QAAA,MAAM,SAAS,yXAgBL,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAoIpD,wBAAgB,aAAa,IAAI,QAAQ,EAAE,CAkB1C;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3B,QAAQ,EAAE,CA8CZ;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAIhE;AAED,wBAAgB,YAAY,IAAI,MAAM,EAAE,CAQvC;AAED,sEAAsE;AACtE,eAAO,MAAM,kBAAkB,6IAGiB,CAAC"}
|
package/dist/lib/skills.js
CHANGED
|
@@ -132,7 +132,10 @@ function loadSkillFromDir(root, id) {
|
|
|
132
132
|
const { name, description, body } = parseFrontmatter(raw);
|
|
133
133
|
return { id, name: name || id, description, body };
|
|
134
134
|
}
|
|
135
|
+
let cachedSkills = null;
|
|
135
136
|
export function loadAllSkills() {
|
|
137
|
+
if (cachedSkills)
|
|
138
|
+
return cachedSkills;
|
|
136
139
|
const roots = resolveSkillsRoots();
|
|
137
140
|
const out = [];
|
|
138
141
|
for (const id of SKILL_IDS) {
|
|
@@ -144,12 +147,16 @@ export function loadAllSkills() {
|
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
}
|
|
150
|
+
cachedSkills = out;
|
|
147
151
|
return out;
|
|
148
152
|
}
|
|
149
|
-
export function selectSkillsForTask(task, scanRules) {
|
|
153
|
+
export function selectSkillsForTask(task, scanRules, options) {
|
|
150
154
|
const all = loadAllSkills();
|
|
151
155
|
const byId = new Map(all.map((s) => [s.id, s]));
|
|
152
156
|
const selected = new Set(["ekz-connect"]);
|
|
157
|
+
if (options?.lite) {
|
|
158
|
+
return [byId.get("ekz-connect")].filter((s) => Boolean(s));
|
|
159
|
+
}
|
|
153
160
|
const haystack = [task, ...(scanRules ?? [])].join("\n");
|
|
154
161
|
for (const { pattern, skills } of TASK_SKILL_MAP) {
|
|
155
162
|
if (pattern.test(haystack)) {
|
|
@@ -164,14 +171,17 @@ export function selectSkillsForTask(task, scanRules) {
|
|
|
164
171
|
selected.has("ekz-integration-playbook")) {
|
|
165
172
|
selected.add("ekz-data-layer-design");
|
|
166
173
|
}
|
|
167
|
-
//
|
|
174
|
+
// Full integration bundle only when the task actually needs it.
|
|
168
175
|
if (selected.size === 1) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
176
|
+
const needsBundle = /ekwanza|webhook|gpo|emis|ticket|checkout|integr|fix|audit|payment|rail|sdk|connect|scan|doctor|env/i.test(task);
|
|
177
|
+
if (needsBundle) {
|
|
178
|
+
selected.add("ekz-payment-core-architecture");
|
|
179
|
+
selected.add("ekz-ekwanza-provider-adapter");
|
|
180
|
+
selected.add("ekz-webhook-normalization");
|
|
181
|
+
selected.add("ekz-integration-playbook");
|
|
182
|
+
selected.add("ekz-data-layer-design");
|
|
183
|
+
selected.add("ekz-sdk-cli");
|
|
184
|
+
}
|
|
175
185
|
}
|
|
176
186
|
return SKILL_IDS.filter((id) => selected.has(id))
|
|
177
187
|
.map((id) => byId.get(id))
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EkzLocale } from "./locale.js";
|
|
2
|
+
export declare function formatTerminalDelta(text: string): string;
|
|
3
|
+
export declare function formatTerminalAnswer(text: string): string;
|
|
4
|
+
export declare function terminalStyleInstruction(locale: EkzLocale): string;
|
|
5
|
+
//# sourceMappingURL=terminal-answer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-answer.d.ts","sourceRoot":"","sources":["../../src/lib/terminal-answer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAkB7C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASzD;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CA4BlE"}
|