11import { spawnSync } from 'child_process' ;
2- import { existsSync , readFileSync , readdirSync , realpathSync } from 'fs' ;
3- import { homedir } from 'os' ;
2+ import {
3+ chmodSync ,
4+ closeSync ,
5+ existsSync ,
6+ mkdtempSync ,
7+ openSync ,
8+ readFileSync ,
9+ readdirSync ,
10+ realpathSync ,
11+ rmSync ,
12+ } from 'fs' ;
13+ import { homedir , tmpdir } from 'os' ;
414import { dirname , join , resolve } from 'path' ;
515import { compareSemanticVersions , isSemanticVersion } from '@core/semver' ;
616
@@ -325,11 +335,6 @@ export function resolveConfiguredPluginSpec(value: unknown): ConfiguredPluginSpe
325335}
326336
327337export function getOpenCodePluginDiagnostic ( ) : OpenCodePluginDiagnostic {
328- const result = spawnSync ( opencodeBin ( ) , [ 'debug' , 'config' , '--pure' ] , {
329- encoding : 'utf8' ,
330- env : process . env ,
331- timeout : 30_000 ,
332- } ) ;
333338 const failed = ( message : string ) : OpenCodePluginDiagnostic => ( {
334339 ok : false ,
335340 spec : '' ,
@@ -339,53 +344,81 @@ export function getOpenCodePluginDiagnostic(): OpenCodePluginDiagnostic {
339344 packageDir : null ,
340345 error : message ,
341346 } ) ;
342- if ( result . error ) {
343- return failed ( `[supertask] 无法读取 OpenCode 最终配置: ${ result . error . message } ` ) ;
344- }
345- if ( result . status !== 0 ) {
346- const detail = `${ result . stderr ?? '' } ` . trim ( ) ;
347- return failed ( `[supertask] 无法读取 OpenCode 最终配置: ${ detail || `退出码 ${ result . status } ` } ` ) ;
348- }
347+ let outputDirectory : string | null = null ;
348+ let outputFd : number | null = null ;
349349
350- let config : unknown ;
351350 try {
352- config = JSON . parse ( `${ result . stdout ?? '' } ` ) ;
353- } catch {
354- return failed ( '[supertask] OpenCode 最终配置不是有效 JSON' ) ;
355- }
351+ outputDirectory = mkdtempSync ( join ( tmpdir ( ) , 'opencode-supertask-config-' ) ) ;
352+ chmodSync ( outputDirectory , 0o700 ) ;
353+ const outputPath = join ( outputDirectory , 'resolved-config.json' ) ;
354+ outputFd = openSync ( outputPath , 'w' , 0o600 ) ;
355+ const result = spawnSync ( opencodeBin ( ) , [ 'debug' , 'config' , '--pure' ] , {
356+ encoding : 'utf8' ,
357+ env : process . env ,
358+ timeout : 30_000 ,
359+ stdio : [ 'ignore' , outputFd , 'pipe' ] ,
360+ } ) ;
361+ closeSync ( outputFd ) ;
362+ outputFd = null ;
363+ if ( result . error ) {
364+ return failed ( `[supertask] 无法读取 OpenCode 最终配置: ${ result . error . message } ` ) ;
365+ }
366+ if ( result . status !== 0 ) {
367+ const detail = `${ result . stderr ?? '' } ` . trim ( ) ;
368+ return failed ( `[supertask] 无法读取 OpenCode 最终配置: ${ detail || `退出码 ${ result . status } ` } ` ) ;
369+ }
356370
357- let configured : ConfiguredPluginSpec ;
358- try {
359- configured = resolveConfiguredPluginSpec ( config ) ;
360- } catch ( error ) {
361- return failed ( error instanceof Error ? error . message : String ( error ) ) ;
362- }
363- if ( ! configured . exact || configured . version === null ) {
364- return {
365- ok : false ,
366- ...configured ,
367- cachedVersion : null ,
368- packageDir : null ,
369- error : `[supertask] OpenCode 插件必须固定精确版本,不能使用 ${ configured . spec } ` ,
370- } ;
371- }
372- try {
373- const installed = resolveInstalledPluginVersion ( configured . version ) ;
374- return {
375- ok : true ,
376- ...configured ,
377- cachedVersion : installed . version ,
378- packageDir : installed . packageDir ,
379- error : null ,
380- } ;
371+ let config : unknown ;
372+ try {
373+ config = JSON . parse ( readFileSync ( outputPath , 'utf8' ) ) ;
374+ } catch {
375+ return failed ( '[supertask] OpenCode 最终配置不是有效 JSON' ) ;
376+ }
377+
378+ let configured : ConfiguredPluginSpec ;
379+ try {
380+ configured = resolveConfiguredPluginSpec ( config ) ;
381+ } catch ( error ) {
382+ return failed ( error instanceof Error ? error . message : String ( error ) ) ;
383+ }
384+ if ( ! configured . exact || configured . version === null ) {
385+ return {
386+ ok : false ,
387+ ...configured ,
388+ cachedVersion : null ,
389+ packageDir : null ,
390+ error : `[supertask] OpenCode 插件必须固定精确版本,不能使用 ${ configured . spec } ` ,
391+ } ;
392+ }
393+ try {
394+ const installed = resolveInstalledPluginVersion ( configured . version ) ;
395+ return {
396+ ok : true ,
397+ ...configured ,
398+ cachedVersion : installed . version ,
399+ packageDir : installed . packageDir ,
400+ error : null ,
401+ } ;
402+ } catch ( error ) {
403+ return {
404+ ok : false ,
405+ ...configured ,
406+ cachedVersion : null ,
407+ packageDir : null ,
408+ error : error instanceof Error ? error . message : String ( error ) ,
409+ } ;
410+ }
381411 } catch ( error ) {
382- return {
383- ok : false ,
384- ...configured ,
385- cachedVersion : null ,
386- packageDir : null ,
387- error : error instanceof Error ? error . message : String ( error ) ,
388- } ;
412+ return failed ( `[supertask] 无法读取 OpenCode 最终配置: ${ error instanceof Error ? error . message : String ( error ) } ` ) ;
413+ } finally {
414+ if ( outputFd !== null ) {
415+ try {
416+ closeSync ( outputFd ) ;
417+ } catch {
418+ // The descriptor may already be closed after a spawn failure.
419+ }
420+ }
421+ if ( outputDirectory !== null ) rmSync ( outputDirectory , { recursive : true , force : true } ) ;
389422 }
390423}
391424
0 commit comments