maskweaver 0.9.6 → 0.9.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/dist/plugin/index.js +13 -2
- package/dist/shared/generate-agents.d.ts +22 -0
- package/dist/shared/generate-agents.js +341 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/weave/gherkin.d.ts +43 -0
- package/dist/weave/gherkin.js +307 -0
- package/dist/weave/phase-manager.js +59 -0
- package/dist/weave/stages/build.js +16 -0
- package/dist/weave/stages/execute.d.ts +8 -1
- package/dist/weave/stages/execute.js +105 -0
- package/dist/weave/stages/plan.js +24 -0
- package/dist/weave/stages/refine.js +75 -0
- package/dist/weave/types.d.ts +11 -1
- package/package.json +3 -3
- package/postinstall.mjs +174 -71
package/dist/plugin/index.js
CHANGED
|
@@ -16,7 +16,7 @@ import { createMaskSaveTool } from './tools/maskSave.js';
|
|
|
16
16
|
import { createSquadTool } from './tools/squad.js';
|
|
17
17
|
import { createWeaveTool } from './tools/weave.js';
|
|
18
18
|
import { createSlashcommandTool } from './tools/slashcommand.js';
|
|
19
|
-
import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, } from '../shared/generate-agents.js';
|
|
19
|
+
import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, writeAutoDetectedConfig, } from '../shared/generate-agents.js';
|
|
20
20
|
const BUILD_COMMAND_TEMPLATE = `Use the \`weave\` tool with \`command="build"\`.
|
|
21
21
|
|
|
22
22
|
Forward the user arguments from \`$ARGUMENTS\` to the build command:
|
|
@@ -34,6 +34,13 @@ const REMOVED_WEAVE_COMMAND_FILES = [
|
|
|
34
34
|
'weave-task.md',
|
|
35
35
|
'weave-task-auto.md',
|
|
36
36
|
'wave-task-auto.md',
|
|
37
|
+
'weave-approve-plan.md',
|
|
38
|
+
'weave-design.md',
|
|
39
|
+
'weave-flow.md',
|
|
40
|
+
'weave-plan.md',
|
|
41
|
+
'weave-research.md',
|
|
42
|
+
'weave-spec.md',
|
|
43
|
+
'weave-switch.md',
|
|
37
44
|
];
|
|
38
45
|
function getAssetsDir() {
|
|
39
46
|
try {
|
|
@@ -628,7 +635,11 @@ export const MaskweaverPlugin = async ({ client, directory, project, worktree, $
|
|
|
628
635
|
if (createdGlobalConfig) {
|
|
629
636
|
pluginLog(client, 'info', `Created global config: ${path.relative(os.homedir(), createdGlobalConfig)}`);
|
|
630
637
|
}
|
|
631
|
-
const
|
|
638
|
+
const autoDetected = writeAutoDetectedConfig(directory);
|
|
639
|
+
if (autoDetected) {
|
|
640
|
+
pluginLog(client, 'info', `Auto-detected subscription: ${autoDetected.detection.primary} (${autoDetected.detection.subscriptions.join(', ')}) — created ${path.relative(directory, autoDetected.path)}`);
|
|
641
|
+
}
|
|
642
|
+
const createdRuntimeConfig = !autoDetected ? writeDefaultRuntimeConfig(directory) : null;
|
|
632
643
|
if (createdRuntimeConfig) {
|
|
633
644
|
pluginLog(client, 'info', `Created project config: ${path.relative(directory, createdRuntimeConfig)}`);
|
|
634
645
|
}
|
|
@@ -17,6 +17,28 @@ export declare function generatePoolAgentFiles(pool: ModelPoolEntry[], agentsDir
|
|
|
17
17
|
export declare function generatePoolAgentFilesFromConfig(projectDir: string, agentsDir: string, options?: {
|
|
18
18
|
force?: boolean;
|
|
19
19
|
}): GenerateAgentsResult;
|
|
20
|
+
export type DetectedSubscription = 'opencode-go' | 'zai-coding-plan';
|
|
21
|
+
export interface SubscriptionDetectionResult {
|
|
22
|
+
subscriptions: DetectedSubscription[];
|
|
23
|
+
primary: DetectedSubscription;
|
|
24
|
+
evidence: string[];
|
|
25
|
+
allProviders: ProviderInfo[];
|
|
26
|
+
}
|
|
27
|
+
export interface ProviderInfo {
|
|
28
|
+
name: string;
|
|
29
|
+
subscription: DetectedSubscription | null;
|
|
30
|
+
authType: string;
|
|
31
|
+
active: boolean;
|
|
32
|
+
}
|
|
33
|
+
export declare function detectSubscriptionsFromCli(): SubscriptionDetectionResult;
|
|
34
|
+
export declare function detectSubscriptionsFromConfig(opencodeConfig: Record<string, any>): SubscriptionDetectionResult;
|
|
35
|
+
export declare function buildPoolFromDetection(detection: SubscriptionDetectionResult): any[];
|
|
36
|
+
export declare function buildConfigFromDetection(detection: SubscriptionDetectionResult): Record<string, any>;
|
|
37
|
+
export declare function formatProviderChecklist(detection: SubscriptionDetectionResult): string;
|
|
38
|
+
export declare function writeAutoDetectedConfig(projectDir: string): {
|
|
39
|
+
path: string;
|
|
40
|
+
detection: SubscriptionDetectionResult;
|
|
41
|
+
} | null;
|
|
20
42
|
export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
21
43
|
readonly dummyHumans: {
|
|
22
44
|
readonly pool: readonly [{
|
|
@@ -100,6 +100,343 @@ export function generatePoolAgentFilesFromConfig(projectDir, agentsDir, options
|
|
|
100
100
|
errors: ['No maskweaver.config.json found with dummyHumans configuration. Create one or run `weave init-config` to generate a default.'],
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
+
import { spawnSync } from 'node:child_process';
|
|
104
|
+
function readOpencodeConfig(basePath) {
|
|
105
|
+
const candidates = [
|
|
106
|
+
path.join(basePath, 'opencode.json'),
|
|
107
|
+
path.join(basePath, 'opencode.jsonc'),
|
|
108
|
+
path.join(os.homedir(), '.config', 'opencode', 'opencode.json'),
|
|
109
|
+
path.join(os.homedir(), '.config', 'opencode', 'opencode.jsonc'),
|
|
110
|
+
];
|
|
111
|
+
for (const candidate of candidates) {
|
|
112
|
+
if (!fs.existsSync(candidate))
|
|
113
|
+
continue;
|
|
114
|
+
try {
|
|
115
|
+
let content = fs.readFileSync(candidate, 'utf-8');
|
|
116
|
+
content = content.replace(/\/\/.*$/gm, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
|
117
|
+
const parsed = JSON.parse(content);
|
|
118
|
+
if (parsed && typeof parsed === 'object')
|
|
119
|
+
return parsed;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
function runCli(command, args) {
|
|
128
|
+
try {
|
|
129
|
+
const result = spawnSync(command, args, {
|
|
130
|
+
encoding: 'utf-8',
|
|
131
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
132
|
+
timeout: 8000,
|
|
133
|
+
windowsHide: true,
|
|
134
|
+
});
|
|
135
|
+
if (result.error || result.status !== 0)
|
|
136
|
+
return null;
|
|
137
|
+
return result.stdout || null;
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const PROVIDER_MAP = {
|
|
144
|
+
'opencode go': 'opencode-go',
|
|
145
|
+
'opencode-go': 'opencode-go',
|
|
146
|
+
'z.ai coding plan': 'zai-coding-plan',
|
|
147
|
+
'zai-coding-plan': 'zai-coding-plan',
|
|
148
|
+
'z.ai': 'zai-coding-plan',
|
|
149
|
+
};
|
|
150
|
+
function parseProvidersList(output) {
|
|
151
|
+
const providers = [];
|
|
152
|
+
const lines = output.split('\n');
|
|
153
|
+
for (const line of lines) {
|
|
154
|
+
const stripped = line.replace(/\x1b\[[0-9;]*m/g, '').trim();
|
|
155
|
+
if (!stripped || stripped.startsWith('┌') || stripped.startsWith('└') || stripped.startsWith('│') || stripped.includes('credentials') || stripped.includes('environment'))
|
|
156
|
+
continue;
|
|
157
|
+
const match = stripped.match(/[●○◉◘]\s+(.+?)\s+(api|oauth|env)$/i);
|
|
158
|
+
if (match) {
|
|
159
|
+
const name = match[1].trim();
|
|
160
|
+
const authType = match[2].trim();
|
|
161
|
+
let subscription = null;
|
|
162
|
+
const nameLower = name.toLowerCase();
|
|
163
|
+
for (const [key, sub] of Object.entries(PROVIDER_MAP)) {
|
|
164
|
+
if (nameLower.includes(key)) {
|
|
165
|
+
subscription = sub;
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
providers.push({
|
|
170
|
+
name,
|
|
171
|
+
subscription,
|
|
172
|
+
authType,
|
|
173
|
+
active: stripped.includes('●'),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return providers;
|
|
178
|
+
}
|
|
179
|
+
function detectFromModels(output) {
|
|
180
|
+
const subs = new Set();
|
|
181
|
+
for (const line of output.split('\n')) {
|
|
182
|
+
const trimmed = line.trim();
|
|
183
|
+
if (trimmed.startsWith('opencode-go/'))
|
|
184
|
+
subs.add('opencode-go');
|
|
185
|
+
if (trimmed.startsWith('zai-coding-plan/'))
|
|
186
|
+
subs.add('zai-coding-plan');
|
|
187
|
+
}
|
|
188
|
+
return Array.from(subs);
|
|
189
|
+
}
|
|
190
|
+
export function detectSubscriptionsFromCli() {
|
|
191
|
+
const evidence = [];
|
|
192
|
+
const allProviders = [];
|
|
193
|
+
const subs = new Set();
|
|
194
|
+
const providersOutput = runCli('opencode', ['providers', 'list']);
|
|
195
|
+
if (providersOutput) {
|
|
196
|
+
const providers = parseProvidersList(providersOutput);
|
|
197
|
+
allProviders.push(...providers);
|
|
198
|
+
for (const p of providers) {
|
|
199
|
+
if (p.subscription) {
|
|
200
|
+
subs.add(p.subscription);
|
|
201
|
+
evidence.push(`provider: ${p.name} (${p.authType})`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
const modelsOutput = runCli('opencode', ['models']);
|
|
206
|
+
if (modelsOutput) {
|
|
207
|
+
const modelSubs = detectFromModels(modelsOutput);
|
|
208
|
+
for (const sub of modelSubs) {
|
|
209
|
+
if (!subs.has(sub)) {
|
|
210
|
+
subs.add(sub);
|
|
211
|
+
evidence.push(`models: ${sub}/* models available`);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
if (subs.size === 0) {
|
|
216
|
+
subs.add('opencode-go');
|
|
217
|
+
evidence.push('No subscription detected via CLI, defaulting to opencode-go');
|
|
218
|
+
}
|
|
219
|
+
const primary = subs.has('zai-coding-plan') ? 'zai-coding-plan' : 'opencode-go';
|
|
220
|
+
return {
|
|
221
|
+
subscriptions: Array.from(subs),
|
|
222
|
+
primary,
|
|
223
|
+
evidence,
|
|
224
|
+
allProviders,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
export function detectSubscriptionsFromConfig(opencodeConfig) {
|
|
228
|
+
const subs = new Set();
|
|
229
|
+
const evidence = [];
|
|
230
|
+
const modelFields = ['model', 'small_model', 'large_model'];
|
|
231
|
+
const configs = [opencodeConfig];
|
|
232
|
+
if (opencodeConfig.agent) {
|
|
233
|
+
for (const agentConfig of Object.values(opencodeConfig.agent)) {
|
|
234
|
+
if (agentConfig && typeof agentConfig === 'object')
|
|
235
|
+
configs.push(agentConfig);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const cfg of configs) {
|
|
239
|
+
for (const field of modelFields) {
|
|
240
|
+
const val = cfg[field];
|
|
241
|
+
if (typeof val !== 'string' || !val)
|
|
242
|
+
continue;
|
|
243
|
+
if (val.startsWith('opencode-go/')) {
|
|
244
|
+
subs.add('opencode-go');
|
|
245
|
+
evidence.push(`${field}: ${val}`);
|
|
246
|
+
}
|
|
247
|
+
else if (val.startsWith('zai-coding-plan/')) {
|
|
248
|
+
subs.add('zai-coding-plan');
|
|
249
|
+
evidence.push(`${field}: ${val}`);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (subs.size === 0) {
|
|
254
|
+
subs.add('opencode-go');
|
|
255
|
+
evidence.push('No provider detected in config, defaulting to opencode-go');
|
|
256
|
+
}
|
|
257
|
+
const primary = subs.has('zai-coding-plan') ? 'zai-coding-plan' : 'opencode-go';
|
|
258
|
+
return {
|
|
259
|
+
subscriptions: Array.from(subs),
|
|
260
|
+
primary,
|
|
261
|
+
evidence,
|
|
262
|
+
allProviders: [],
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function buildZaiPool() {
|
|
266
|
+
return [
|
|
267
|
+
{
|
|
268
|
+
id: 'glm-flash',
|
|
269
|
+
model: 'zai-coding-plan/glm-5-turbo',
|
|
270
|
+
tier: 'flash',
|
|
271
|
+
maxConcurrent: 1,
|
|
272
|
+
capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
|
|
273
|
+
costTier: 'low',
|
|
274
|
+
description: 'GLM-5 Turbo - 빠름. 단순 검색/포매팅/파일작업',
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
id: 'glm-general',
|
|
278
|
+
model: 'zai-coding-plan/glm-5.1',
|
|
279
|
+
tier: 'human',
|
|
280
|
+
maxConcurrent: 10,
|
|
281
|
+
capabilities: ['coding', 'testing', 'refactoring', 'backend'],
|
|
282
|
+
costTier: 'medium',
|
|
283
|
+
description: 'GLM-5.1 - 일반. 코딩/리팩토링/백엔드',
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'glm-premium',
|
|
287
|
+
model: 'zai-coding-plan/glm-5.1',
|
|
288
|
+
tier: 'premium',
|
|
289
|
+
maxConcurrent: 10,
|
|
290
|
+
capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
|
|
291
|
+
costTier: 'high',
|
|
292
|
+
description: 'GLM-5.1 - 고급 추론. 아키텍처/복잡 디버깅',
|
|
293
|
+
},
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
function buildOpencodeGoPool() {
|
|
297
|
+
return [
|
|
298
|
+
{
|
|
299
|
+
id: 'deepseek-flash',
|
|
300
|
+
model: 'opencode-go/deepseek-v4-flash',
|
|
301
|
+
tier: 'flash',
|
|
302
|
+
maxConcurrent: 5,
|
|
303
|
+
capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
|
|
304
|
+
costTier: 'low',
|
|
305
|
+
description: 'DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업',
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
id: 'deepseek-general',
|
|
309
|
+
model: 'opencode-go/deepseek-v4-flash',
|
|
310
|
+
tier: 'human',
|
|
311
|
+
maxConcurrent: 3,
|
|
312
|
+
capabilities: ['coding', 'testing', 'refactoring', 'backend'],
|
|
313
|
+
costTier: 'medium',
|
|
314
|
+
description: 'DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드',
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
id: 'qwen-vision',
|
|
318
|
+
model: 'opencode-go/qwen3.6-plus',
|
|
319
|
+
tier: 'human',
|
|
320
|
+
maxConcurrent: 3,
|
|
321
|
+
capabilities: ['vision', 'frontend', 'testing'],
|
|
322
|
+
costTier: 'medium',
|
|
323
|
+
description: 'Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: 'deepseek-pro',
|
|
327
|
+
model: 'opencode-go/deepseek-v4-pro',
|
|
328
|
+
tier: 'premium',
|
|
329
|
+
maxConcurrent: 2,
|
|
330
|
+
capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
|
|
331
|
+
costTier: 'high',
|
|
332
|
+
description: 'DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅',
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
id: 'kimi-vision',
|
|
336
|
+
model: 'opencode-go/kimi-k2.6',
|
|
337
|
+
tier: 'premium',
|
|
338
|
+
maxConcurrent: 2,
|
|
339
|
+
capabilities: ['vision', 'reasoning', 'complex-coding', 'architecture', 'debugging'],
|
|
340
|
+
costTier: 'high',
|
|
341
|
+
description: 'Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론',
|
|
342
|
+
},
|
|
343
|
+
];
|
|
344
|
+
}
|
|
345
|
+
function buildOperatorModel(primary) {
|
|
346
|
+
switch (primary) {
|
|
347
|
+
case 'zai-coding-plan':
|
|
348
|
+
return {
|
|
349
|
+
model: 'zai-coding-plan/glm-5.1',
|
|
350
|
+
maxConcurrent: 10,
|
|
351
|
+
description: 'Squad Operator model - 작업 오케스트레이션 및 고급 추론',
|
|
352
|
+
};
|
|
353
|
+
default:
|
|
354
|
+
return {
|
|
355
|
+
model: 'opencode-go/deepseek-v4-pro',
|
|
356
|
+
maxConcurrent: 2,
|
|
357
|
+
description: 'Squad Operator model - 작업 오케스트레이션 및 고급 추론',
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
export function buildPoolFromDetection(detection) {
|
|
362
|
+
const pool = [];
|
|
363
|
+
if (detection.subscriptions.includes('opencode-go')) {
|
|
364
|
+
pool.push(...buildOpencodeGoPool());
|
|
365
|
+
}
|
|
366
|
+
if (detection.subscriptions.includes('zai-coding-plan')) {
|
|
367
|
+
pool.push(...buildZaiPool());
|
|
368
|
+
}
|
|
369
|
+
if (pool.length === 0) {
|
|
370
|
+
pool.push(...buildOpencodeGoPool());
|
|
371
|
+
}
|
|
372
|
+
return pool;
|
|
373
|
+
}
|
|
374
|
+
export function buildConfigFromDetection(detection) {
|
|
375
|
+
const pool = buildPoolFromDetection(detection);
|
|
376
|
+
const operator = buildOperatorModel(detection.primary);
|
|
377
|
+
return {
|
|
378
|
+
dummyHumans: { pool },
|
|
379
|
+
operator,
|
|
380
|
+
memory: { provider: 'text-only', enabled: false },
|
|
381
|
+
gdc: { enabled: 'auto', strictVerify: false, autoSyncOnPrepare: true },
|
|
382
|
+
language: 'ko',
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
export function formatProviderChecklist(detection) {
|
|
386
|
+
const lines = ['감지된 프로바이더:'];
|
|
387
|
+
lines.push('');
|
|
388
|
+
if (detection.allProviders.length > 0) {
|
|
389
|
+
for (const p of detection.allProviders) {
|
|
390
|
+
const marker = p.subscription && detection.subscriptions.includes(p.subscription) ? '[x]' : '[ ]';
|
|
391
|
+
const sub = p.subscription ? ` → ${p.subscription}` : '';
|
|
392
|
+
lines.push(` ${marker} ${p.name} (${p.authType})${sub}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
for (const sub of detection.subscriptions) {
|
|
397
|
+
lines.push(` [x] ${sub}`);
|
|
398
|
+
}
|
|
399
|
+
lines.push(` [ ] (다른 구독이 있다면 maskweaver.config.json에서 추가하세요)`);
|
|
400
|
+
}
|
|
401
|
+
lines.push('');
|
|
402
|
+
lines.push(`선택된 구독: ${detection.subscriptions.join(', ')}`);
|
|
403
|
+
lines.push(`기본 구독: ${detection.primary}`);
|
|
404
|
+
lines.push('');
|
|
405
|
+
lines.push('구독을 변경하려면 maskweaver.config.json의 dummyHumans.pool을 편집하세요.');
|
|
406
|
+
return lines.join('\n');
|
|
407
|
+
}
|
|
408
|
+
export function writeAutoDetectedConfig(projectDir) {
|
|
409
|
+
let detection;
|
|
410
|
+
try {
|
|
411
|
+
detection = detectSubscriptionsFromCli();
|
|
412
|
+
}
|
|
413
|
+
catch {
|
|
414
|
+
const opencodeConfig = readOpencodeConfig(projectDir);
|
|
415
|
+
if (!opencodeConfig)
|
|
416
|
+
return null;
|
|
417
|
+
detection = detectSubscriptionsFromConfig(opencodeConfig);
|
|
418
|
+
}
|
|
419
|
+
const targetPath = path.join(projectDir, 'maskweaver.config.json');
|
|
420
|
+
const existingConfig = fs.existsSync(targetPath)
|
|
421
|
+
? (() => { try {
|
|
422
|
+
return JSON.parse(fs.readFileSync(targetPath, 'utf-8'));
|
|
423
|
+
}
|
|
424
|
+
catch {
|
|
425
|
+
return null;
|
|
426
|
+
} })()
|
|
427
|
+
: null;
|
|
428
|
+
if (existingConfig?.dummyHumans?.pool?.length > 0) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
const newConfig = buildConfigFromDetection(detection);
|
|
432
|
+
try {
|
|
433
|
+
fs.writeFileSync(targetPath, JSON.stringify(newConfig, null, 2) + '\n', 'utf-8');
|
|
434
|
+
return { path: targetPath, detection };
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
103
440
|
export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
104
441
|
dummyHumans: {
|
|
105
442
|
pool: [
|
|
@@ -185,6 +522,10 @@ export function writeDefaultRuntimeConfig(projectDir) {
|
|
|
185
522
|
if (fs.existsSync(targetPath)) {
|
|
186
523
|
return null;
|
|
187
524
|
}
|
|
525
|
+
const autoResult = writeAutoDetectedConfig(projectDir);
|
|
526
|
+
if (autoResult) {
|
|
527
|
+
return autoResult.path;
|
|
528
|
+
}
|
|
188
529
|
try {
|
|
189
530
|
fs.writeFileSync(targetPath, JSON.stringify(DEFAULT_RUNTIME_CONFIG_TEMPLATE, null, 2) + '\n', 'utf-8');
|
|
190
531
|
return targetPath;
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.9.
|
|
1
|
+
export declare const VERSION = "0.9.8";
|
|
2
2
|
export declare function getVersionString(): string;
|
package/dist/version.js
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { GherkinScenario, WeavePhase, WeaveTask } from './types.js';
|
|
2
|
+
export interface ParsedFeature {
|
|
3
|
+
feature: string;
|
|
4
|
+
description: string;
|
|
5
|
+
scenarios: ParsedScenario[];
|
|
6
|
+
}
|
|
7
|
+
export interface ParsedScenario {
|
|
8
|
+
name: string;
|
|
9
|
+
given: string[];
|
|
10
|
+
when: string[];
|
|
11
|
+
then: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare function parseGherkinText(text: string): ParsedFeature | null;
|
|
14
|
+
export declare function parseGherkinBlock(block: string): GherkinScenario[];
|
|
15
|
+
export declare function formatGherkinScenario(scenario: GherkinScenario): string;
|
|
16
|
+
export declare function formatGherkinFeature(featureName: string, scenarios: GherkinScenario[]): string;
|
|
17
|
+
export declare function formatGherkinForTask(task: WeaveTask): string;
|
|
18
|
+
export declare function formatGherkinChecklist(scenarios: GherkinScenario[]): string;
|
|
19
|
+
export declare function ensureFeaturesDir(basePath: string): Promise<string>;
|
|
20
|
+
export declare function writeFeatureFile(basePath: string, phaseId: string, phaseName: string, scenarios: GherkinScenario[]): Promise<string>;
|
|
21
|
+
export declare function writeAllFeatureFiles(basePath: string, phases: WeavePhase[]): Promise<Map<string, string>>;
|
|
22
|
+
export declare function generateGherkinForPhase(phase: {
|
|
23
|
+
id: string;
|
|
24
|
+
name: string;
|
|
25
|
+
doneWhen: string;
|
|
26
|
+
}): GherkinScenario[];
|
|
27
|
+
export declare function generateGherkinForTask(task: {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
testCase?: string;
|
|
31
|
+
}, phase: {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
doneWhen: string;
|
|
35
|
+
}): GherkinScenario;
|
|
36
|
+
export interface BDDFrameworkInfo {
|
|
37
|
+
detected: boolean;
|
|
38
|
+
framework: 'cucumber' | 'jest-cucumber' | 'pytest-bdd' | 'behave' | 'unknown' | null;
|
|
39
|
+
testCommand: string | null;
|
|
40
|
+
featureDir: string | null;
|
|
41
|
+
}
|
|
42
|
+
export declare function detectBDDFramework(projectPath: string): BDDFrameworkInfo;
|
|
43
|
+
export declare function generateGherkinVerificationPrompt(phase: WeavePhase, task?: WeaveTask): string;
|