maskweaver 0.10.1 → 0.11.0
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/tools/command-registry.js +5 -2
- package/dist/plugin/tools/weave.d.ts +3 -0
- package/dist/plugin/tools/weave.js +227 -59
- package/dist/shared/config.d.ts +1 -0
- package/dist/shared/generate-agents.d.ts +6 -1
- package/dist/shared/generate-agents.js +15 -2
- package/dist/shared/model-registry.js +4 -0
- package/dist/weave/context-manager.d.ts +87 -0
- package/dist/weave/context-manager.js +366 -0
- package/dist/weave/types.d.ts +93 -0
- package/dist/weave/wave-executor.d.ts +11 -0
- package/dist/weave/wave-executor.js +769 -0
- package/package.json +1 -1
|
@@ -91,7 +91,7 @@ const INLINE_DEFAULT = {
|
|
|
91
91
|
name: 'craft',
|
|
92
92
|
aliases: [],
|
|
93
93
|
deprecatedAliases: [],
|
|
94
|
-
description: '
|
|
94
|
+
description: '[DEPRECATED] Use build instead — it now auto-approves and runs craft+build+verify',
|
|
95
95
|
category: 'execution',
|
|
96
96
|
args: [
|
|
97
97
|
{ name: 'phaseId', type: 'string', required: false, description: 'Phase ID (auto-select if omitted)' },
|
|
@@ -99,7 +99,7 @@ const INLINE_DEFAULT = {
|
|
|
99
99
|
],
|
|
100
100
|
mdFile: 'weave-craft.md',
|
|
101
101
|
handler: 'handleCraft',
|
|
102
|
-
examples: ['weave command=
|
|
102
|
+
examples: ['weave command=build (use this instead)'],
|
|
103
103
|
},
|
|
104
104
|
{
|
|
105
105
|
name: 'build',
|
|
@@ -112,6 +112,7 @@ const INLINE_DEFAULT = {
|
|
|
112
112
|
{ name: 'phaseIds', type: 'string', required: false, description: 'Comma-separated phase IDs for run action' },
|
|
113
113
|
{ name: 'buildId', type: 'string', required: false, description: 'Build ID for status/stop/resume/sync actions' },
|
|
114
114
|
{ name: 'maxRetries', type: 'number', default: 3, min: 1, max: 10, description: 'Maximum retries per task (for run action)' },
|
|
115
|
+
{ name: 'taskResults', type: 'string', required: false, description: 'JSON array of TaskResult from previous wave (for resume)' },
|
|
115
116
|
{ name: 'maxIterations', type: 'number', default: 1, min: 1, max: 20, description: 'Maximum loop iterations before blocking' },
|
|
116
117
|
{ name: 'maxNoProgress', type: 'number', default: 1, min: 0, max: 10, description: 'Maximum repeated no-progress failures before blocking' },
|
|
117
118
|
],
|
|
@@ -216,12 +217,14 @@ const INLINE_DEFAULT = {
|
|
|
216
217
|
args: [
|
|
217
218
|
{ name: 'sync', type: 'boolean', default: false, description: 'Force regenerate agent .md files from config pool' },
|
|
218
219
|
{ name: 'init', type: 'boolean', default: false, description: 'Create default maskweaver.config.json with pool template' },
|
|
220
|
+
{ name: 'force', type: 'boolean', default: false, description: 'Force re-detect subscription and overwrite maskweaver.config.json' },
|
|
219
221
|
],
|
|
220
222
|
mdFile: 'weave-agents.md',
|
|
221
223
|
handler: 'handleAgents',
|
|
222
224
|
examples: [
|
|
223
225
|
'weave command=agents sync=true',
|
|
224
226
|
'weave command=agents init=true',
|
|
227
|
+
'weave command=agents force=true',
|
|
225
228
|
],
|
|
226
229
|
},
|
|
227
230
|
{
|
|
@@ -13,6 +13,7 @@ export declare function createWeaveTool(): {
|
|
|
13
13
|
}>>;
|
|
14
14
|
sync: z.ZodOptional<z.ZodBoolean>;
|
|
15
15
|
init: z.ZodOptional<z.ZodBoolean>;
|
|
16
|
+
force: z.ZodOptional<z.ZodBoolean>;
|
|
16
17
|
docsPath: z.ZodOptional<z.ZodString>;
|
|
17
18
|
phaseId: z.ZodOptional<z.ZodString>;
|
|
18
19
|
projectName: z.ZodOptional<z.ZodString>;
|
|
@@ -56,6 +57,7 @@ export declare function createWeaveTool(): {
|
|
|
56
57
|
deep: z.ZodOptional<z.ZodBoolean>;
|
|
57
58
|
maxRetries: z.ZodOptional<z.ZodNumber>;
|
|
58
59
|
buildId: z.ZodOptional<z.ZodString>;
|
|
60
|
+
taskResults: z.ZodOptional<z.ZodString>;
|
|
59
61
|
phaseIds: z.ZodOptional<z.ZodString>;
|
|
60
62
|
};
|
|
61
63
|
execute: (args: {
|
|
@@ -97,6 +99,7 @@ export declare function createWeaveTool(): {
|
|
|
97
99
|
deep?: boolean;
|
|
98
100
|
maxRetries?: number;
|
|
99
101
|
buildId?: string;
|
|
102
|
+
taskResults?: string;
|
|
100
103
|
phaseIds?: string;
|
|
101
104
|
}, context: {
|
|
102
105
|
worktree: string;
|
|
@@ -18,8 +18,7 @@ import { archiveChange } from '../../weave/stages/archive.js';
|
|
|
18
18
|
import { generateStatusReport, handleUserResponse } from '../../weave/stages/handoff.js';
|
|
19
19
|
import { analyzeCodebase, runGraphifyAnalysis, readMapResult } from '../../weave/stages/map.js';
|
|
20
20
|
import { interview as interviewStage, listInterviewStates } from '../../weave/stages/intake.js';
|
|
21
|
-
import {
|
|
22
|
-
import { WeaveOrchestrator } from '../../weave/orchestrator.js';
|
|
21
|
+
import { generateBuildId } from '../../weave/stages/build.js';
|
|
23
22
|
import { getPhaseManager } from '../../weave/phase-manager.js';
|
|
24
23
|
import { recommendVerificationCommands, formatRecommendedCommandsAsBash } from '../../weave/verification/index.js';
|
|
25
24
|
import { createWeaveWorktree, listWeaveWorktrees, resolveWeaveWorktree, removeWeaveWorktree, ensureIgnoreOverride, ensureWeaveState, } from '../../weave/worktree.js';
|
|
@@ -27,10 +26,11 @@ import { ensureGitRepo, stageAllChanges, listStagedFiles, hasStagedChanges, comm
|
|
|
27
26
|
import { scanFilesForSecrets, loadSecretScanConfig, shouldBlockOnFindings, formatSecretScanReport } from '../../weave/security/secret-scan.js';
|
|
28
27
|
import { searchTroubleshooting, recordTroubleshooting, GlobalKnowledge } from '../../weave/knowledge/global.js';
|
|
29
28
|
import { ensureChangeArtifact, readChangeMetadata, writeChangeVerificationReport } from '../../weave/change-artifacts.js';
|
|
29
|
+
import { advanceBuildStep } from '../../weave/wave-executor.js';
|
|
30
30
|
import { analyzeParallelOpportunities, executionPlanToSquadTasks } from '../../weave/bridge.js';
|
|
31
31
|
import { acquireLoopOperatorLock, appendLoopEvent, createLoopRun, ensureLoopContract, listLoopRuns, readLoopRun, releaseLoopOperatorLock, refreshLoopOperatorLock, requestLoopStop, toLoopOperatorStatePath, resolveLoopId, toLoopRunPath, updateLoopRun, writeLoopOperatorState, writeLoopAttemptControllerNotes, writeLoopAttemptTaskBundle, writeLoopAttemptWorkerBrief, writeLoopAttemptVerificationReport, } from '../../weave/loop.js';
|
|
32
32
|
import { getEffectiveGdcConfig, runGdcMachineCommand, countGdcCheckIssues, getStatsNodeSummary, } from '../../weave/gdc.js';
|
|
33
|
-
import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, } from '../../shared/generate-agents.js';
|
|
33
|
+
import { generatePoolAgentFilesFromConfig, writeDefaultRuntimeConfig, writeDefaultPluginConfig, writeAutoDetectedConfig, formatProviderChecklist, } from '../../shared/generate-agents.js';
|
|
34
34
|
import { resolveCommand, loadCommandsJson } from './command-registry.js';
|
|
35
35
|
export function createWeaveTool() {
|
|
36
36
|
return {
|
|
@@ -61,6 +61,8 @@ export function createWeaveTool() {
|
|
|
61
61
|
.describe('Force regenerate agent .md files from config pool (for agents command)'),
|
|
62
62
|
init: z.boolean().optional()
|
|
63
63
|
.describe('Create default maskweaver.config.json with pool template (for agents command)'),
|
|
64
|
+
force: z.boolean().optional()
|
|
65
|
+
.describe('Force re-detect subscription and overwrite maskweaver.config.json (for agents command)'),
|
|
64
66
|
docsPath: z.string().optional()
|
|
65
67
|
.describe('Path to requirements documents (for design command)'),
|
|
66
68
|
phaseId: z.string().optional()
|
|
@@ -129,6 +131,8 @@ export function createWeaveTool() {
|
|
|
129
131
|
.describe('Maximum retries per task (for build command)'),
|
|
130
132
|
buildId: z.string().optional()
|
|
131
133
|
.describe('Build ID to resume (for build-resume command)'),
|
|
134
|
+
taskResults: z.string().optional()
|
|
135
|
+
.describe('JSON array of TaskResult from previous wave (for resume)'),
|
|
132
136
|
phaseIds: z.string().optional()
|
|
133
137
|
.describe('Comma-separated phase IDs (for build command)'),
|
|
134
138
|
},
|
|
@@ -163,7 +167,7 @@ export function createWeaveTool() {
|
|
|
163
167
|
result = await handleApprovePlan(args, basePath);
|
|
164
168
|
break;
|
|
165
169
|
case 'craft':
|
|
166
|
-
result = await
|
|
170
|
+
result = '> ⚠️ `craft` is deprecated. Use `weave command=build` instead — it now auto-approves and runs the full build loop (craft + build + verify).\n\n' + await handleBuildUnified(args, basePath);
|
|
167
171
|
break;
|
|
168
172
|
case 'build':
|
|
169
173
|
result = await handleBuildUnified(args, basePath);
|
|
@@ -1945,48 +1949,90 @@ async function handleInterview(args, basePath) {
|
|
|
1945
1949
|
}
|
|
1946
1950
|
async function handleBuild(args, basePath) {
|
|
1947
1951
|
const lines = [];
|
|
1948
|
-
lines.push('## 🏗️ Build');
|
|
1952
|
+
lines.push('## 🏗️ Build (Wave)');
|
|
1949
1953
|
lines.push('');
|
|
1950
1954
|
const manager = getPhaseManager(basePath);
|
|
1951
1955
|
const plan = await manager.loadPlan();
|
|
1952
1956
|
if (!plan) {
|
|
1953
|
-
return 'Error: No active plan found. Run `weave command=
|
|
1957
|
+
return 'Error: No active plan found. Run `weave command=prepare docsPath="docs/"` first.';
|
|
1954
1958
|
}
|
|
1955
1959
|
if (!plan.planApproved) {
|
|
1956
|
-
|
|
1960
|
+
plan.planApproved = true;
|
|
1961
|
+
plan.planApprovedAt = new Date().toISOString();
|
|
1962
|
+
plan.planApprovalNotes = 'Auto-approved by build command.';
|
|
1963
|
+
await manager.savePlan(plan);
|
|
1964
|
+
lines.push(`> ⚡ Plan auto-approved: **${plan.projectName}**`);
|
|
1965
|
+
lines.push('');
|
|
1957
1966
|
}
|
|
1958
|
-
|
|
1959
|
-
lines.push('');
|
|
1960
|
-
const orchestrator = new WeaveOrchestrator();
|
|
1967
|
+
const changeId = plan.activeChangeId || plan.planName || 'main';
|
|
1961
1968
|
const buildId = generateBuildId();
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
lines.push('Starting autonomous build loop...');
|
|
1965
|
-
lines.push('');
|
|
1966
|
-
const result = await executeBuildLoop({
|
|
1967
|
-
plan,
|
|
1968
|
-
state,
|
|
1969
|
-
orchestrator,
|
|
1970
|
-
basePath,
|
|
1971
|
-
maxRetries: args.maxRetries,
|
|
1972
|
-
phaseIds: args.phaseIds ? args.phaseIds.split(',').map((id) => id.trim()).filter(Boolean) : undefined,
|
|
1973
|
-
onMessage: (msg) => { onMessages.push(msg); },
|
|
1974
|
-
});
|
|
1975
|
-
for (const msg of onMessages) {
|
|
1976
|
-
lines.push(msg);
|
|
1977
|
-
}
|
|
1969
|
+
lines.push(`Plan: **${plan.projectName}** (approved at ${plan.planApprovedAt || 'N/A'})`);
|
|
1970
|
+
lines.push(`Build: \`${buildId}\``);
|
|
1978
1971
|
lines.push('');
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1972
|
+
try {
|
|
1973
|
+
const decision = await advanceBuildStep({
|
|
1974
|
+
plan,
|
|
1975
|
+
basePath,
|
|
1976
|
+
buildId,
|
|
1977
|
+
changeId,
|
|
1978
|
+
maxRetries: args.maxRetries || 3,
|
|
1979
|
+
phaseIds: args.phaseIds ? args.phaseIds.split(',').map(s => s.trim()).filter(Boolean) : undefined,
|
|
1980
|
+
});
|
|
1981
|
+
switch (decision.kind) {
|
|
1982
|
+
case 'dispatch_wave': {
|
|
1983
|
+
lines.push(`### Wave ${decision.wave.waveIndex} — ${decision.contracts.length} task(s)`);
|
|
1984
|
+
lines.push(`Parallel-safe: ${decision.wave.parallelSafe ? '✅ Yes' : '⚠️ No (sequential)'}`);
|
|
1985
|
+
lines.push('');
|
|
1986
|
+
for (const contract of decision.contracts) {
|
|
1987
|
+
lines.push(`#### ${contract.taskId} — \`${contract.subagentType}\`${contract.mask ? ` (${contract.mask})` : ''}`);
|
|
1988
|
+
lines.push(`- Allowed: ${contract.allowedPaths.length > 0 ? contract.allowedPaths.join(', ') : '*'}`);
|
|
1989
|
+
lines.push(`- Verify: ${contract.verifyCommands.join('; ') || 'none'}`);
|
|
1990
|
+
lines.push(`- Brief: \`${contract.briefPath}\``);
|
|
1991
|
+
lines.push(`- Context: \`${contract.contextPath}\``);
|
|
1992
|
+
lines.push('');
|
|
1993
|
+
lines.push('```');
|
|
1994
|
+
lines.push(`Task(${contract.subagentType}, prompt=Read ${contract.briefPath} and execute the task.)`);
|
|
1995
|
+
lines.push('```');
|
|
1996
|
+
lines.push('');
|
|
1997
|
+
}
|
|
1998
|
+
lines.push('---');
|
|
1999
|
+
lines.push(`After Task() calls complete, pass results:`);
|
|
2000
|
+
lines.push('```');
|
|
2001
|
+
lines.push(`weave command=build action=resume buildId="${buildId}" taskResults='[{"taskId":"<id>","phaseId":"<pid>","status":"succeeded","changedFiles":["file.ts"],"createdSymbols":[],"downstreamExports":[]}]'`);
|
|
2002
|
+
lines.push('```');
|
|
2003
|
+
break;
|
|
2004
|
+
}
|
|
2005
|
+
case 'verify': {
|
|
2006
|
+
lines.push(`### Verifying Wave ${decision.waveIndex}`);
|
|
2007
|
+
lines.push('Running verification commands...');
|
|
2008
|
+
break;
|
|
2009
|
+
}
|
|
2010
|
+
case 'repair': {
|
|
2011
|
+
lines.push(`### 🔧 Repair: ${decision.contract.taskId}`);
|
|
2012
|
+
lines.push(`Failure: ${decision.failureKind}`);
|
|
2013
|
+
lines.push('');
|
|
2014
|
+
lines.push('```');
|
|
2015
|
+
lines.push(`Task(${decision.contract.subagentType}, prompt=Read ${decision.contract.briefPath} and fix the issues.)`);
|
|
2016
|
+
lines.push('```');
|
|
2017
|
+
break;
|
|
2018
|
+
}
|
|
2019
|
+
case 'blocked': {
|
|
2020
|
+
lines.push(`### ⛔ Blocked`);
|
|
2021
|
+
lines.push(decision.reason);
|
|
2022
|
+
if (decision.failedTasks.length > 0) {
|
|
2023
|
+
lines.push(`Failed tasks: ${decision.failedTasks.join(', ')}`);
|
|
2024
|
+
}
|
|
2025
|
+
break;
|
|
2026
|
+
}
|
|
2027
|
+
case 'complete': {
|
|
2028
|
+
lines.push('### ✅ Build Complete');
|
|
2029
|
+
lines.push(decision.summary);
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
1984
2033
|
}
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
if (result.tasksEscalated > 0 || result.tasksFailed > 0) {
|
|
1988
|
-
lines.push('');
|
|
1989
|
-
lines.push('To resume after fixing issues: `weave command=build-resume buildId="<buildId>"`');
|
|
2034
|
+
catch (e) {
|
|
2035
|
+
lines.push(`❌ Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
1990
2036
|
}
|
|
1991
2037
|
return lines.join('\n');
|
|
1992
2038
|
}
|
|
@@ -1995,31 +2041,87 @@ async function handleBuildResume(args, basePath) {
|
|
|
1995
2041
|
lines.push('## 🔄 Build Resume');
|
|
1996
2042
|
lines.push('');
|
|
1997
2043
|
if (!args.buildId) {
|
|
1998
|
-
return 'Error: buildId is required. Use `weave command=build
|
|
1999
|
-
}
|
|
2000
|
-
const state = await loadBuildState(basePath, args.buildId);
|
|
2001
|
-
if (!state) {
|
|
2002
|
-
return `Error: Build state not found: ${args.buildId}`;
|
|
2003
|
-
}
|
|
2004
|
-
if (state.status !== 'blocked') {
|
|
2005
|
-
return `Build ${args.buildId} is not blocked (status: ${state.status}). No need to resume.`;
|
|
2044
|
+
return 'Error: buildId is required. Use `weave command=build action=resume buildId="<id>"`.';
|
|
2006
2045
|
}
|
|
2007
2046
|
const manager = getPhaseManager(basePath);
|
|
2008
2047
|
const plan = await manager.loadPlan();
|
|
2009
2048
|
if (!plan) {
|
|
2010
2049
|
return 'Error: No active plan found.';
|
|
2011
2050
|
}
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
}
|
|
2022
|
-
|
|
2051
|
+
const changeId = plan.activeChangeId || plan.planName || 'main';
|
|
2052
|
+
let lastResults = [];
|
|
2053
|
+
if (args.taskResults) {
|
|
2054
|
+
try {
|
|
2055
|
+
lastResults = JSON.parse(args.taskResults);
|
|
2056
|
+
}
|
|
2057
|
+
catch {
|
|
2058
|
+
lines.push('> ⚠️ Could not parse taskResults, proceeding without previous results.');
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
else {
|
|
2062
|
+
lines.push('> ⚠️ No taskResults provided. Pass results from Task() calls as JSON:');
|
|
2063
|
+
lines.push('> `weave command=build action=resume buildId="..." taskResults=\'[{"taskId":"...","phaseId":"...","status":"succeeded","changedFiles":[],"createdSymbols":[],"downstreamExports":[]}]\'`');
|
|
2064
|
+
lines.push('');
|
|
2065
|
+
}
|
|
2066
|
+
try {
|
|
2067
|
+
const decision = await advanceBuildStep({
|
|
2068
|
+
plan,
|
|
2069
|
+
basePath,
|
|
2070
|
+
buildId: args.buildId,
|
|
2071
|
+
changeId,
|
|
2072
|
+
lastResults: lastResults.length > 0 ? lastResults : undefined,
|
|
2073
|
+
maxRetries: args.maxRetries || 3,
|
|
2074
|
+
});
|
|
2075
|
+
switch (decision.kind) {
|
|
2076
|
+
case 'dispatch_wave': {
|
|
2077
|
+
lines.push(`### Next Wave ${decision.wave.waveIndex} — ${decision.contracts.length} task(s)`);
|
|
2078
|
+
lines.push(`Parallel-safe: ${decision.wave.parallelSafe ? '✅ Yes' : '⚠️ No'}`);
|
|
2079
|
+
lines.push('');
|
|
2080
|
+
for (const contract of decision.contracts) {
|
|
2081
|
+
lines.push(`#### ${contract.taskId} — \`${contract.subagentType}\``);
|
|
2082
|
+
lines.push('```');
|
|
2083
|
+
lines.push(`Task(${contract.subagentType}, prompt=Read ${contract.briefPath} and execute the task.)`);
|
|
2084
|
+
lines.push('```');
|
|
2085
|
+
lines.push('');
|
|
2086
|
+
}
|
|
2087
|
+
lines.push(`After Task() calls complete, pass results:`);
|
|
2088
|
+
lines.push('```');
|
|
2089
|
+
lines.push(`weave command=build action=resume buildId="${args.buildId}" taskResults='[{"taskId":"<id>","phaseId":"<pid>","status":"succeeded","changedFiles":["file.ts"],"createdSymbols":[],"downstreamExports":[]}]'`);
|
|
2090
|
+
lines.push('```');
|
|
2091
|
+
break;
|
|
2092
|
+
}
|
|
2093
|
+
case 'repair': {
|
|
2094
|
+
lines.push(`### 🔧 Repair: ${decision.contract.taskId}`);
|
|
2095
|
+
lines.push(`Failure: ${decision.failureKind}`);
|
|
2096
|
+
lines.push('```');
|
|
2097
|
+
lines.push(`Task(${decision.contract.subagentType}, prompt=Read ${decision.contract.briefPath} and fix.)`);
|
|
2098
|
+
lines.push('```');
|
|
2099
|
+
lines.push('');
|
|
2100
|
+
lines.push(`After fix, pass results:`);
|
|
2101
|
+
lines.push('```');
|
|
2102
|
+
lines.push(`weave command=build action=resume buildId="${args.buildId}" taskResults='[{"taskId":"${decision.contract.taskId}","phaseId":"${decision.contract.phaseId}","status":"succeeded","changedFiles":[],"createdSymbols":[],"downstreamExports":[]}]'`);
|
|
2103
|
+
lines.push('```');
|
|
2104
|
+
break;
|
|
2105
|
+
}
|
|
2106
|
+
case 'blocked': {
|
|
2107
|
+
lines.push('### ⛔ Build Blocked');
|
|
2108
|
+
lines.push(decision.reason);
|
|
2109
|
+
break;
|
|
2110
|
+
}
|
|
2111
|
+
case 'complete': {
|
|
2112
|
+
lines.push('### ✅ Build Complete');
|
|
2113
|
+
lines.push(decision.summary);
|
|
2114
|
+
break;
|
|
2115
|
+
}
|
|
2116
|
+
case 'verify': {
|
|
2117
|
+
lines.push(`### Verifying Wave ${decision.waveIndex}...`);
|
|
2118
|
+
break;
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
catch (e) {
|
|
2123
|
+
lines.push(`❌ Error: ${e instanceof Error ? e.message : String(e)}`);
|
|
2124
|
+
}
|
|
2023
2125
|
return lines.join('\n');
|
|
2024
2126
|
}
|
|
2025
2127
|
async function handleCraft(args, basePath) {
|
|
@@ -2429,6 +2531,59 @@ async function handleInitConfig(basePath) {
|
|
|
2429
2531
|
lines.push('> with your model pool, then run `weave sync-agents` in any project to apply it.');
|
|
2430
2532
|
return lines.join('\n');
|
|
2431
2533
|
}
|
|
2534
|
+
async function handleWaveBuildStatus(buildId, basePath) {
|
|
2535
|
+
const manager = getPhaseManager(basePath);
|
|
2536
|
+
const plan = await manager.loadPlan();
|
|
2537
|
+
if (!plan)
|
|
2538
|
+
return null;
|
|
2539
|
+
const changeId = plan.activeChangeId || plan.planName || 'main';
|
|
2540
|
+
const buildDir = path.join(basePath, 'changes', changeId, 'builds', buildId);
|
|
2541
|
+
if (!fs.existsSync(buildDir))
|
|
2542
|
+
return null;
|
|
2543
|
+
const lines = [];
|
|
2544
|
+
lines.push(`## Wave Build Status: \`${buildId}\``);
|
|
2545
|
+
lines.push('');
|
|
2546
|
+
const wavesDir = path.join(buildDir, 'waves');
|
|
2547
|
+
if (fs.existsSync(wavesDir)) {
|
|
2548
|
+
const waveFiles = fs.readdirSync(wavesDir).filter(f => f.startsWith('wave-')).sort();
|
|
2549
|
+
for (const wf of waveFiles) {
|
|
2550
|
+
const content = fs.readFileSync(path.join(wavesDir, wf), 'utf-8');
|
|
2551
|
+
lines.push(`### ${wf.replace('.md', '')}`);
|
|
2552
|
+
lines.push('```');
|
|
2553
|
+
lines.push(content.slice(0, 2000));
|
|
2554
|
+
lines.push('```');
|
|
2555
|
+
lines.push('');
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
const tasksDir = path.join(buildDir, 'tasks');
|
|
2559
|
+
if (fs.existsSync(tasksDir)) {
|
|
2560
|
+
const taskDirs = fs.readdirSync(tasksDir, { withFileTypes: true }).filter(d => d.isDirectory());
|
|
2561
|
+
lines.push(`### Tasks (${taskDirs.length})`);
|
|
2562
|
+
lines.push('');
|
|
2563
|
+
for (const td of taskDirs) {
|
|
2564
|
+
const resultPath = path.join(tasksDir, td.name, 'result.md');
|
|
2565
|
+
const briefPath = path.join(tasksDir, td.name, 'brief.md');
|
|
2566
|
+
if (fs.existsSync(resultPath)) {
|
|
2567
|
+
const resultContent = fs.readFileSync(resultPath, 'utf-8');
|
|
2568
|
+
const statusMatch = resultContent.match(/\*\*Status:\*\*\s*(\w+)/);
|
|
2569
|
+
lines.push(`- ${td.name}: ${statusMatch?.[1] || 'unknown'}`);
|
|
2570
|
+
}
|
|
2571
|
+
else if (fs.existsSync(briefPath)) {
|
|
2572
|
+
lines.push(`- ${td.name}: dispatched (no result yet)`);
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
lines.push('');
|
|
2576
|
+
}
|
|
2577
|
+
const contextIndexPath = path.join(buildDir, 'context-index.yaml');
|
|
2578
|
+
if (fs.existsSync(contextIndexPath)) {
|
|
2579
|
+
lines.push('### Context Index');
|
|
2580
|
+
lines.push('```yaml');
|
|
2581
|
+
lines.push(fs.readFileSync(contextIndexPath, 'utf-8').slice(0, 1500));
|
|
2582
|
+
lines.push('```');
|
|
2583
|
+
lines.push('');
|
|
2584
|
+
}
|
|
2585
|
+
return lines.join('\n');
|
|
2586
|
+
}
|
|
2432
2587
|
async function handleBuildUnified(args, basePath) {
|
|
2433
2588
|
const action = args.action || 'run';
|
|
2434
2589
|
switch (action) {
|
|
@@ -2439,13 +2594,16 @@ async function handleBuildUnified(args, basePath) {
|
|
|
2439
2594
|
case 'status': {
|
|
2440
2595
|
const loopId = args.buildId || args.loopId;
|
|
2441
2596
|
if (!loopId)
|
|
2442
|
-
return 'Error: buildId
|
|
2597
|
+
return 'Error: buildId is required. Example: weave command=build action=status buildId="build-20250428-a1b2"';
|
|
2598
|
+
const waveStatus = await handleWaveBuildStatus(loopId, basePath);
|
|
2599
|
+
if (waveStatus)
|
|
2600
|
+
return waveStatus;
|
|
2443
2601
|
return handleLoopStatus({ loopId }, basePath);
|
|
2444
2602
|
}
|
|
2445
2603
|
case 'stop': {
|
|
2446
2604
|
const loopId = args.buildId || args.loopId;
|
|
2447
2605
|
if (!loopId)
|
|
2448
|
-
return 'Error: buildId
|
|
2606
|
+
return 'Error: buildId is required. Example: weave command=build action=stop buildId="build-20250428-a1b2"';
|
|
2449
2607
|
return handleLoopStop({ loopId, context: undefined }, basePath);
|
|
2450
2608
|
}
|
|
2451
2609
|
case 'list':
|
|
@@ -2461,10 +2619,20 @@ async function handleBuildUnified(args, basePath) {
|
|
|
2461
2619
|
}
|
|
2462
2620
|
}
|
|
2463
2621
|
async function handleAgents(args, basePath) {
|
|
2464
|
-
if (!args.sync && !args.init) {
|
|
2465
|
-
return 'Error: agents requires an action. Use `sync=true` to regenerate agent files,
|
|
2622
|
+
if (!args.sync && !args.init && !args.force) {
|
|
2623
|
+
return 'Error: agents requires an action. Use `sync=true` to regenerate agent files, `init=true` to create default config, or `force=true` to re-detect subscription and overwrite config.';
|
|
2466
2624
|
}
|
|
2467
2625
|
const sections = [];
|
|
2626
|
+
if (args.force) {
|
|
2627
|
+
const result = writeAutoDetectedConfig(basePath, true);
|
|
2628
|
+
if (result) {
|
|
2629
|
+
sections.push(`## ✅ Config Force-Updated\n\nAuto-detected subscription: \`${result.detection.primary}\` (${result.detection.subscriptions.join(', ')})\n\n\`\`\`\n${formatProviderChecklist(result.detection)}\n\`\`\`\n\nWrote to: \`${toWorkspaceRelative(basePath, result.path)}\``);
|
|
2630
|
+
}
|
|
2631
|
+
else {
|
|
2632
|
+
sections.push('## ❌ Force update failed\n\nCould not auto-detect subscription. Make sure opencode CLI is available.');
|
|
2633
|
+
}
|
|
2634
|
+
sections.push(await handleSyncAgents(basePath));
|
|
2635
|
+
}
|
|
2468
2636
|
if (args.sync) {
|
|
2469
2637
|
sections.push(await handleSyncAgents(basePath));
|
|
2470
2638
|
}
|
package/dist/shared/config.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ export declare function detectSubscriptionsFromConfig(opencodeConfig: Record<str
|
|
|
35
35
|
export declare function buildPoolFromDetection(detection: SubscriptionDetectionResult): any[];
|
|
36
36
|
export declare function buildConfigFromDetection(detection: SubscriptionDetectionResult): Record<string, any>;
|
|
37
37
|
export declare function formatProviderChecklist(detection: SubscriptionDetectionResult): string;
|
|
38
|
-
export declare function writeAutoDetectedConfig(projectDir: string): {
|
|
38
|
+
export declare function writeAutoDetectedConfig(projectDir: string, force?: boolean): {
|
|
39
39
|
path: string;
|
|
40
40
|
detection: SubscriptionDetectionResult;
|
|
41
41
|
} | null;
|
|
@@ -48,6 +48,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
|
48
48
|
readonly maxConcurrent: 5;
|
|
49
49
|
readonly capabilities: readonly ["search", "formatting", "simple-coding", "file-ops"];
|
|
50
50
|
readonly costTier: "low";
|
|
51
|
+
readonly priority: 1;
|
|
51
52
|
readonly description: "DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업";
|
|
52
53
|
}, {
|
|
53
54
|
readonly id: "deepseek-general";
|
|
@@ -56,6 +57,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
|
56
57
|
readonly maxConcurrent: 3;
|
|
57
58
|
readonly capabilities: readonly ["coding", "testing", "refactoring", "backend"];
|
|
58
59
|
readonly costTier: "medium";
|
|
60
|
+
readonly priority: 2;
|
|
59
61
|
readonly description: "DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드";
|
|
60
62
|
}, {
|
|
61
63
|
readonly id: "qwen-vision";
|
|
@@ -64,6 +66,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
|
64
66
|
readonly maxConcurrent: 3;
|
|
65
67
|
readonly capabilities: readonly ["vision", "frontend", "testing"];
|
|
66
68
|
readonly costTier: "medium";
|
|
69
|
+
readonly priority: 1;
|
|
67
70
|
readonly description: "Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트";
|
|
68
71
|
}, {
|
|
69
72
|
readonly id: "deepseek-pro";
|
|
@@ -72,6 +75,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
|
72
75
|
readonly maxConcurrent: 2;
|
|
73
76
|
readonly capabilities: readonly ["architecture", "debugging", "reasoning", "complex-coding", "refactoring"];
|
|
74
77
|
readonly costTier: "high";
|
|
78
|
+
readonly priority: 2;
|
|
75
79
|
readonly description: "DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅";
|
|
76
80
|
}, {
|
|
77
81
|
readonly id: "kimi-vision";
|
|
@@ -80,6 +84,7 @@ export declare const DEFAULT_RUNTIME_CONFIG_TEMPLATE: {
|
|
|
80
84
|
readonly maxConcurrent: 2;
|
|
81
85
|
readonly capabilities: readonly ["vision", "reasoning", "complex-coding", "architecture", "debugging"];
|
|
82
86
|
readonly costTier: "high";
|
|
87
|
+
readonly priority: 1;
|
|
83
88
|
readonly description: "Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론";
|
|
84
89
|
}];
|
|
85
90
|
};
|
|
@@ -271,6 +271,7 @@ function buildZaiPool() {
|
|
|
271
271
|
maxConcurrent: 1,
|
|
272
272
|
capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
|
|
273
273
|
costTier: 'low',
|
|
274
|
+
priority: 1,
|
|
274
275
|
description: 'GLM-5 Turbo - 빠름. 단순 검색/포매팅/파일작업',
|
|
275
276
|
},
|
|
276
277
|
{
|
|
@@ -280,6 +281,7 @@ function buildZaiPool() {
|
|
|
280
281
|
maxConcurrent: 10,
|
|
281
282
|
capabilities: ['coding', 'testing', 'refactoring', 'backend'],
|
|
282
283
|
costTier: 'medium',
|
|
284
|
+
priority: 1,
|
|
283
285
|
description: 'GLM-5.1 - 일반. 코딩/리팩토링/백엔드',
|
|
284
286
|
},
|
|
285
287
|
{
|
|
@@ -289,6 +291,7 @@ function buildZaiPool() {
|
|
|
289
291
|
maxConcurrent: 10,
|
|
290
292
|
capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
|
|
291
293
|
costTier: 'high',
|
|
294
|
+
priority: 1,
|
|
292
295
|
description: 'GLM-5.1 - 고급 추론. 아키텍처/복잡 디버깅',
|
|
293
296
|
},
|
|
294
297
|
];
|
|
@@ -302,6 +305,7 @@ function buildOpencodeGoPool() {
|
|
|
302
305
|
maxConcurrent: 5,
|
|
303
306
|
capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
|
|
304
307
|
costTier: 'low',
|
|
308
|
+
priority: 1,
|
|
305
309
|
description: 'DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업',
|
|
306
310
|
},
|
|
307
311
|
{
|
|
@@ -311,6 +315,7 @@ function buildOpencodeGoPool() {
|
|
|
311
315
|
maxConcurrent: 3,
|
|
312
316
|
capabilities: ['coding', 'testing', 'refactoring', 'backend'],
|
|
313
317
|
costTier: 'medium',
|
|
318
|
+
priority: 2,
|
|
314
319
|
description: 'DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드',
|
|
315
320
|
},
|
|
316
321
|
{
|
|
@@ -320,6 +325,7 @@ function buildOpencodeGoPool() {
|
|
|
320
325
|
maxConcurrent: 3,
|
|
321
326
|
capabilities: ['vision', 'frontend', 'testing'],
|
|
322
327
|
costTier: 'medium',
|
|
328
|
+
priority: 1,
|
|
323
329
|
description: 'Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트',
|
|
324
330
|
},
|
|
325
331
|
{
|
|
@@ -329,6 +335,7 @@ function buildOpencodeGoPool() {
|
|
|
329
335
|
maxConcurrent: 2,
|
|
330
336
|
capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
|
|
331
337
|
costTier: 'high',
|
|
338
|
+
priority: 2,
|
|
332
339
|
description: 'DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅',
|
|
333
340
|
},
|
|
334
341
|
{
|
|
@@ -338,6 +345,7 @@ function buildOpencodeGoPool() {
|
|
|
338
345
|
maxConcurrent: 2,
|
|
339
346
|
capabilities: ['vision', 'reasoning', 'complex-coding', 'architecture', 'debugging'],
|
|
340
347
|
costTier: 'high',
|
|
348
|
+
priority: 1,
|
|
341
349
|
description: 'Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론',
|
|
342
350
|
},
|
|
343
351
|
];
|
|
@@ -405,7 +413,7 @@ export function formatProviderChecklist(detection) {
|
|
|
405
413
|
lines.push('구독을 변경하려면 maskweaver.config.json의 dummyHumans.pool을 편집하세요.');
|
|
406
414
|
return lines.join('\n');
|
|
407
415
|
}
|
|
408
|
-
export function writeAutoDetectedConfig(projectDir) {
|
|
416
|
+
export function writeAutoDetectedConfig(projectDir, force) {
|
|
409
417
|
let detection;
|
|
410
418
|
try {
|
|
411
419
|
detection = detectSubscriptionsFromCli();
|
|
@@ -425,7 +433,7 @@ export function writeAutoDetectedConfig(projectDir) {
|
|
|
425
433
|
return null;
|
|
426
434
|
} })()
|
|
427
435
|
: null;
|
|
428
|
-
if (existingConfig?.dummyHumans?.pool?.length > 0) {
|
|
436
|
+
if (!force && existingConfig?.dummyHumans?.pool?.length > 0) {
|
|
429
437
|
return null;
|
|
430
438
|
}
|
|
431
439
|
const newConfig = buildConfigFromDetection(detection);
|
|
@@ -447,6 +455,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
|
447
455
|
maxConcurrent: 5,
|
|
448
456
|
capabilities: ['search', 'formatting', 'simple-coding', 'file-ops'],
|
|
449
457
|
costTier: 'low',
|
|
458
|
+
priority: 1,
|
|
450
459
|
description: 'DeepSeek V4 Flash - 빠름. 단순 검색/포매팅/파일작업',
|
|
451
460
|
},
|
|
452
461
|
{
|
|
@@ -456,6 +465,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
|
456
465
|
maxConcurrent: 3,
|
|
457
466
|
capabilities: ['coding', 'testing', 'refactoring', 'backend'],
|
|
458
467
|
costTier: 'medium',
|
|
468
|
+
priority: 2,
|
|
459
469
|
description: 'DeepSeek V4 Flash - 일반. 코딩/리팩토링/백엔드',
|
|
460
470
|
},
|
|
461
471
|
{
|
|
@@ -465,6 +475,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
|
465
475
|
maxConcurrent: 3,
|
|
466
476
|
capabilities: ['vision', 'frontend', 'testing'],
|
|
467
477
|
costTier: 'medium',
|
|
478
|
+
priority: 1,
|
|
468
479
|
description: 'Qwen 3.6 Plus - 비전. 이미지 분석/프론트엔드/테스트',
|
|
469
480
|
},
|
|
470
481
|
{
|
|
@@ -474,6 +485,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
|
474
485
|
maxConcurrent: 2,
|
|
475
486
|
capabilities: ['architecture', 'debugging', 'reasoning', 'complex-coding', 'refactoring'],
|
|
476
487
|
costTier: 'high',
|
|
488
|
+
priority: 2,
|
|
477
489
|
description: 'DeepSeek V4 Pro - 고급 추론. 아키텍처/복잡 디버깅',
|
|
478
490
|
},
|
|
479
491
|
{
|
|
@@ -483,6 +495,7 @@ export const DEFAULT_RUNTIME_CONFIG_TEMPLATE = {
|
|
|
483
495
|
maxConcurrent: 2,
|
|
484
496
|
capabilities: ['vision', 'reasoning', 'complex-coding', 'architecture', 'debugging'],
|
|
485
497
|
costTier: 'high',
|
|
498
|
+
priority: 1,
|
|
486
499
|
description: 'Kimi K2.6 - 비전 고급. 이미지 분석/복잡 추론',
|
|
487
500
|
},
|
|
488
501
|
],
|
|
@@ -187,6 +187,10 @@ export class ModelRegistry {
|
|
|
187
187
|
return -1;
|
|
188
188
|
if (!slotA.available && slotB.available)
|
|
189
189
|
return 1;
|
|
190
|
+
const priA = a.priority ?? 0;
|
|
191
|
+
const priB = b.priority ?? 0;
|
|
192
|
+
if (priB !== priA)
|
|
193
|
+
return priB - priA;
|
|
190
194
|
if (preferCheap) {
|
|
191
195
|
const costDiff = COST_ORDER[a.costTier] - COST_ORDER[b.costTier];
|
|
192
196
|
if (costDiff !== 0)
|