maistro 1.2.14 → 1.2.17
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/app.d.ts +5 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +76 -1
- package/dist/app.js.map +1 -1
- package/dist/envFile.d.ts +11 -0
- package/dist/envFile.d.ts.map +1 -0
- package/dist/envFile.js +56 -0
- package/dist/envFile.js.map +1 -0
- package/dist/planner.d.ts +2 -1
- package/dist/planner.d.ts.map +1 -1
- package/dist/planner.js +38 -0
- package/dist/planner.js.map +1 -1
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/app.d.ts
CHANGED
|
@@ -69,6 +69,11 @@ export declare class MaistroApp {
|
|
|
69
69
|
* Uses full-screen approach for each step
|
|
70
70
|
*/
|
|
71
71
|
private handleDiscovery;
|
|
72
|
+
/**
|
|
73
|
+
* Prompt user for each required secret one at a time.
|
|
74
|
+
* Returns a map of envVar -> value for secrets the user provided, or null if cancelled.
|
|
75
|
+
*/
|
|
76
|
+
private promptForSecrets;
|
|
72
77
|
/**
|
|
73
78
|
* Handle discovery phase for planning requests (no skip option)
|
|
74
79
|
* This is used when the user submits a planning request to refine the plan.
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAmOA,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAG9B,OAAO,CAAC,cAAc,CAA+B;gBAEzC,WAAW,GAAE,MAAY;IAsBrC,OAAO,CAAC,eAAe;IASvB;;;OAGG;YACW,qBAAqB;IA+CnC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkH5B;;;OAGG;YACW,iBAAiB;IAiE/B;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;;OAGG;IACG,YAAY,CAAC,SAAS,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAqFtD;;;OAGG;YACW,iBAAiB;IAwD/B;;OAEG;YACW,sBAAsB;IAsCpC;;;OAGG;YACW,iBAAiB;IAoB/B;;;OAGG;YACW,oBAAoB;IAkClC;;OAEG;YACW,qBAAqB;IA4BnC;;OAEG;YACW,gBAAgB;IAoB9B;;;OAGG;YACW,qBAAqB;IAoEnC;;;OAGG;YACW,eAAe;IAwJ7B;;;OAGG;YACW,gBAAgB;IAiD9B;;;OAGG;YACW,uBAAuB;IAyErC;;OAEG;YACW,4BAA4B;IAkE1C;;OAEG;YACW,oBAAoB;IAiElC;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,UAAU;IAQlB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IA2J7B,OAAO,CAAC,iBAAiB,CAAM;IAC/B,OAAO,CAAC,gBAAgB,CAAK;IAE7B;;;OAGG;YACW,YAAY;IAyT1B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA2CxB;;OAEG;YACW,aAAa;IAsmB3B;;;OAGG;YACW,iBAAiB;IAgI/B;;OAEG;YACW,cAAc;IAwU5B,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAS;IAE9B;;OAEG;YACW,gBAAgB;IAkB9B;;OAEG;YACW,gBAAgB;IAe9B;;;OAGG;YACW,WAAW;IAsEzB;;;OAGG;YACW,mBAAmB;IA8BjC;;;OAGG;YACW,cAAc;IAkB5B;;;;OAIG;YACW,6BAA6B;IAqI3C;;;OAGG;YACW,aAAa;IA+B3B;;;;OAIG;YACW,sBAAsB;IA8MpC;;;;OAIG;YACW,sBAAsB;YA2GtB,UAAU;IA8HxB,OAAO,CAAC,YAAY;IAmFpB;;;OAGG;YACW,eAAe;IAqD7B;;OAEG;YACW,cAAc;IAsO5B;;OAEG;YACW,oBAAoB;IAwBlC;;OAEG;YACW,eAAe;IAU7B;;OAEG;YACW,wBAAwB;YAsBxB,gBAAgB;IA4B9B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAsD;IAEpF;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqB3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAO1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAKzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAQ/B;;OAEG;IACH,OAAO,CAAC,eAAe;IASvB;;OAEG;IACH,OAAO,CAAC,sBAAsB;YAoEhB,SAAS;YAiIT,sBAAsB;CAkcrC"}
|
package/dist/app.js
CHANGED
|
@@ -6,6 +6,7 @@ import { exec } from 'node:child_process';
|
|
|
6
6
|
import { Orchestrator } from './orchestrator.js';
|
|
7
7
|
import { InteractiveUI, ExitRequestedError, formatTaskStatus, formatTaskStatusIcon, formatStatusName, formatBlockedStatus, progressBar } from './ui.js';
|
|
8
8
|
import { planTasks, generateReadme, discoverRequirements, buildProjectContext, formatContextForDecomposition } from './planner.js';
|
|
9
|
+
import { readExistingEnvVars, writeSecretsToEnvFile } from './envFile.js';
|
|
9
10
|
import { isTaskBlocked } from './taskQueue.js';
|
|
10
11
|
import { isClaudeCodeInstalled, isClaudeCodeAuthenticated, testClaudeInteraction, launchClaudeLogin, loadConfig, saveConfig, } from './config.js';
|
|
11
12
|
import { initLogger, getLogger } from './logger.js';
|
|
@@ -768,6 +769,16 @@ export class MaistroApp {
|
|
|
768
769
|
answers[question.id] = answer;
|
|
769
770
|
getLogger()?.info('Discovery answer', { questionId: question.id, question: question.question, answer });
|
|
770
771
|
}
|
|
772
|
+
// Prompt for required secrets if any were detected
|
|
773
|
+
const collectedSecrets = {};
|
|
774
|
+
if (result.requiredSecrets && result.requiredSecrets.length > 0) {
|
|
775
|
+
const secretResults = await this.promptForSecrets(result.requiredSecrets);
|
|
776
|
+
if (secretResults === null) {
|
|
777
|
+
// User cancelled
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
Object.assign(collectedSecrets, secretResults);
|
|
781
|
+
}
|
|
771
782
|
// Show confirmation screen (full-screen)
|
|
772
783
|
this.ui.clear();
|
|
773
784
|
this.showHeader();
|
|
@@ -779,6 +790,19 @@ export class MaistroApp {
|
|
|
779
790
|
const label = question ? question.id.replace(/-/g, ' ').replace(/^\w/, c => c.toUpperCase()) : id;
|
|
780
791
|
console.log(` \x1b[36m${label}:\x1b[0m ${value}`);
|
|
781
792
|
}
|
|
793
|
+
// Show secrets status summary
|
|
794
|
+
if (result.requiredSecrets && result.requiredSecrets.length > 0) {
|
|
795
|
+
console.log('\n\x1b[90mSecrets/Credentials:\x1b[0m');
|
|
796
|
+
for (const secret of result.requiredSecrets) {
|
|
797
|
+
const provided = collectedSecrets[secret.envVar];
|
|
798
|
+
if (provided) {
|
|
799
|
+
console.log(` \x1b[32m✓\x1b[0m \x1b[33m${secret.envVar}\x1b[0m — provided`);
|
|
800
|
+
}
|
|
801
|
+
else {
|
|
802
|
+
console.log(` \x1b[90m○\x1b[0m \x1b[33m${secret.envVar}\x1b[0m — skipped`);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
782
806
|
console.log('');
|
|
783
807
|
const confirmChoice = await this.ui.quickPick([
|
|
784
808
|
{ key: 'y', label: 'Continue', description: 'Create plan with these preferences' },
|
|
@@ -793,15 +817,66 @@ export class MaistroApp {
|
|
|
793
817
|
if (confirmChoice === null) {
|
|
794
818
|
return null;
|
|
795
819
|
}
|
|
796
|
-
|
|
820
|
+
// Write collected secrets to .env.local
|
|
821
|
+
if (Object.keys(collectedSecrets).length > 0) {
|
|
822
|
+
writeSecretsToEnvFile(this.projectPath, collectedSecrets);
|
|
823
|
+
}
|
|
824
|
+
getLogger()?.info('Discovery completed', { summary: result.summary, answers, requiredSecrets: result.requiredSecrets, secretsProvided: Object.keys(collectedSecrets) });
|
|
797
825
|
return {
|
|
798
826
|
summary: result.summary,
|
|
799
827
|
questions: result.questions,
|
|
800
828
|
assumptions: result.assumptions,
|
|
801
829
|
answers,
|
|
802
830
|
confirmed: true,
|
|
831
|
+
requiredSecrets: result.requiredSecrets,
|
|
803
832
|
};
|
|
804
833
|
}
|
|
834
|
+
/**
|
|
835
|
+
* Prompt user for each required secret one at a time.
|
|
836
|
+
* Returns a map of envVar -> value for secrets the user provided, or null if cancelled.
|
|
837
|
+
*/
|
|
838
|
+
async promptForSecrets(secrets) {
|
|
839
|
+
const collected = {};
|
|
840
|
+
// Check which secrets already exist in .env or .env.local
|
|
841
|
+
const existing = readExistingEnvVars(this.projectPath);
|
|
842
|
+
for (let i = 0; i < secrets.length; i++) {
|
|
843
|
+
const secret = secrets[i];
|
|
844
|
+
const existingValue = existing[secret.envVar];
|
|
845
|
+
const progressText = `Secret ${i + 1} of ${secrets.length}`;
|
|
846
|
+
if (existingValue) {
|
|
847
|
+
// Already present - show and let user confirm or update
|
|
848
|
+
const choice = await this.fullScreenMenu({
|
|
849
|
+
title: progressText,
|
|
850
|
+
subtitle: `\x1b[33m${secret.envVar}\x1b[0m — ${secret.name} (${secret.service})\n\nAlready set in .env file: ${existingValue.slice(0, 8)}${'*'.repeat(Math.max(0, existingValue.length - 8))}`,
|
|
851
|
+
items: [
|
|
852
|
+
{ key: 'k', label: 'Keep', description: 'Keep existing value' },
|
|
853
|
+
{ key: 'u', label: 'Update', description: 'Enter a new value' },
|
|
854
|
+
],
|
|
855
|
+
exitOnDoubleEscape: true,
|
|
856
|
+
});
|
|
857
|
+
if (choice === null)
|
|
858
|
+
return null;
|
|
859
|
+
if (choice === 'k')
|
|
860
|
+
continue;
|
|
861
|
+
// Fall through to prompt for new value
|
|
862
|
+
}
|
|
863
|
+
const phaseLabel = secret.phase === 'both' ? 'build + runtime' : secret.phase;
|
|
864
|
+
const subtitle = `\x1b[33m${secret.envVar}\x1b[0m — ${secret.name} (${secret.service})\n\n\x1b[90mObtain from:\x1b[0m ${secret.obtainFrom}\n\x1b[90mNeeded at:\x1b[0m ${phaseLabel}`;
|
|
865
|
+
const value = await this.fullScreenTextInput({
|
|
866
|
+
title: progressText,
|
|
867
|
+
subtitle,
|
|
868
|
+
placeholder: 'paste your secret value... (Enter to skip)',
|
|
869
|
+
hint: 'Enter to continue, Esc to cancel setup',
|
|
870
|
+
exitOnDoubleEscape: true,
|
|
871
|
+
});
|
|
872
|
+
if (value === null)
|
|
873
|
+
return null; // User cancelled
|
|
874
|
+
if (value.trim()) {
|
|
875
|
+
collected[secret.envVar] = value.trim();
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
return collected;
|
|
879
|
+
}
|
|
805
880
|
/**
|
|
806
881
|
* Handle discovery phase for planning requests (no skip option)
|
|
807
882
|
* This is used when the user submits a planning request to refine the plan.
|