@gitsense/gsc-utils 0.2.6 → 0.2.7
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/gsc-utils.cjs.js +138 -22
- package/dist/gsc-utils.esm.js +138 -22
- package/package.json +1 -1
- package/src/AnalyzerUtils/saver.js +2 -2
package/dist/gsc-utils.cjs.js
CHANGED
|
@@ -18,8 +18,8 @@ function getDefaultExportFromCjs (x) {
|
|
|
18
18
|
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0)
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
const fs$
|
|
22
|
-
const path$
|
|
21
|
+
const fs$7 = require$$0;
|
|
22
|
+
const path$5 = require$$1;
|
|
23
23
|
const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -53,12 +53,12 @@ function unescapeCodeBlocks(content) {
|
|
|
53
53
|
* @returns {Array} An array of message objects with role and content properties
|
|
54
54
|
*/
|
|
55
55
|
function getChatTemplateMessages$1(dirname, messageType) {
|
|
56
|
-
const messagesDir = path$
|
|
56
|
+
const messagesDir = path$5.join(dirname, messageType);
|
|
57
57
|
const messages = [];
|
|
58
58
|
|
|
59
59
|
try {
|
|
60
60
|
// Read all files in the directory
|
|
61
|
-
const files = fs$
|
|
61
|
+
const files = fs$7.readdirSync(messagesDir);
|
|
62
62
|
|
|
63
63
|
// Sort files numerically (1.md, 2.md, etc.)
|
|
64
64
|
const sortedFiles = files.sort((a, b) => {
|
|
@@ -69,9 +69,9 @@ function getChatTemplateMessages$1(dirname, messageType) {
|
|
|
69
69
|
|
|
70
70
|
// Process each file
|
|
71
71
|
for (const file of sortedFiles) {
|
|
72
|
-
if (path$
|
|
73
|
-
const filePath = path$
|
|
74
|
-
const fileContent = fs$
|
|
72
|
+
if (path$5.extname(file) === '.md') {
|
|
73
|
+
const filePath = path$5.join(messagesDir, file);
|
|
74
|
+
const fileContent = fs$7.readFileSync(filePath, 'utf8');
|
|
75
75
|
|
|
76
76
|
// Split by triple newline to separate metadata from content
|
|
77
77
|
const parts = fileContent.split('\n\n\n');
|
|
@@ -10925,8 +10925,8 @@ var dataValidator = {
|
|
|
10925
10925
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
10926
10926
|
*/
|
|
10927
10927
|
|
|
10928
|
-
const fs$
|
|
10929
|
-
const path$
|
|
10928
|
+
const fs$6 = require$$0.promises;
|
|
10929
|
+
const path$4 = require$$1;
|
|
10930
10930
|
|
|
10931
10931
|
/**
|
|
10932
10932
|
* Reads and parses the config.json file in a directory.
|
|
@@ -10935,9 +10935,9 @@ const path$3 = require$$1;
|
|
|
10935
10935
|
* or null if the file doesn't exist or is invalid.
|
|
10936
10936
|
*/
|
|
10937
10937
|
async function readConfig$1(dirPath) {
|
|
10938
|
-
const configPath = path$
|
|
10938
|
+
const configPath = path$4.join(dirPath, 'config.json');
|
|
10939
10939
|
try {
|
|
10940
|
-
const fileContent = await fs$
|
|
10940
|
+
const fileContent = await fs$6.readFile(configPath, 'utf8');
|
|
10941
10941
|
return JSON.parse(fileContent);
|
|
10942
10942
|
} catch (error) {
|
|
10943
10943
|
if (error.code !== 'ENOENT') {
|
|
@@ -10974,41 +10974,41 @@ async function getAnalyzers$2(analyzeMessagesBasePath) {
|
|
|
10974
10974
|
const analyzers = [];
|
|
10975
10975
|
|
|
10976
10976
|
try {
|
|
10977
|
-
const analyzerEntries = await fs$
|
|
10977
|
+
const analyzerEntries = await fs$6.readdir(analyzeMessagesBasePath, { withFileTypes: true });
|
|
10978
10978
|
|
|
10979
10979
|
for (const analyzerEntry of analyzerEntries) {
|
|
10980
10980
|
if (analyzerEntry.isDirectory() && isValidDirName(analyzerEntry.name)) {
|
|
10981
10981
|
const analyzerName = analyzerEntry.name;
|
|
10982
|
-
const analyzerPath = path$
|
|
10982
|
+
const analyzerPath = path$4.join(analyzeMessagesBasePath, analyzerName);
|
|
10983
10983
|
const analyzerConfig = await readConfig$1(analyzerPath);
|
|
10984
10984
|
const analyzerLabel = analyzerConfig?.label || analyzerName;
|
|
10985
10985
|
|
|
10986
|
-
const contentEntries = await fs$
|
|
10986
|
+
const contentEntries = await fs$6.readdir(analyzerPath, { withFileTypes: true });
|
|
10987
10987
|
|
|
10988
10988
|
for (const contentEntry of contentEntries) {
|
|
10989
10989
|
if (contentEntry.isDirectory() && isValidDirName(contentEntry.name)) {
|
|
10990
10990
|
const contentType = contentEntry.name;
|
|
10991
|
-
const contentPath = path$
|
|
10991
|
+
const contentPath = path$4.join(analyzerPath, contentType);
|
|
10992
10992
|
const contentConfig = await readConfig$1(contentPath);
|
|
10993
10993
|
const contentLabel = contentConfig?.label || contentType;
|
|
10994
10994
|
|
|
10995
|
-
const instructionsEntries = await fs$
|
|
10995
|
+
const instructionsEntries = await fs$6.readdir(contentPath, { withFileTypes: true });
|
|
10996
10996
|
|
|
10997
10997
|
for (const instructionsEntry of instructionsEntries) {
|
|
10998
10998
|
if (instructionsEntry.isDirectory() && isValidDirName(instructionsEntry.name)) {
|
|
10999
10999
|
const instructionsType = instructionsEntry.name;
|
|
11000
|
-
const instructionsPath = path$
|
|
11000
|
+
const instructionsPath = path$4.join(contentPath, instructionsType);
|
|
11001
11001
|
const instructionsConfig = await readConfig$1(instructionsPath);
|
|
11002
11002
|
const instructionsLabel = instructionsConfig?.label || instructionsType;
|
|
11003
11003
|
|
|
11004
11004
|
// Check for the existence of 1.md to confirm a valid analyzer configuration
|
|
11005
|
-
const instructionsFilePath = path$
|
|
11005
|
+
const instructionsFilePath = path$4.join(instructionsPath, '1.md');
|
|
11006
11006
|
try {
|
|
11007
|
-
await fs$
|
|
11007
|
+
await fs$6.access(instructionsFilePath); // Check if file exists and is accessible
|
|
11008
11008
|
|
|
11009
11009
|
// If analyzerName starts with 'tutorial-', check its last modified time.
|
|
11010
11010
|
if (analyzerName.startsWith('tutorial-')) {
|
|
11011
|
-
const stats = await fs$
|
|
11011
|
+
const stats = await fs$6.stat(instructionsFilePath);
|
|
11012
11012
|
const lastModified = stats.mtime.getTime(); // Get timestamp in milliseconds
|
|
11013
11013
|
const sixtyMinutesAgo = Date.now() - (60 * 60 * 1000); // Current time - 60 minutes in ms
|
|
11014
11014
|
|
|
@@ -11062,12 +11062,128 @@ var discovery = {
|
|
|
11062
11062
|
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash Thinking (v1.1.0)
|
|
11063
11063
|
*/
|
|
11064
11064
|
|
|
11065
|
-
require$$0.promises;
|
|
11065
|
+
const fs$5 = require$$0.promises;
|
|
11066
|
+
const path$3 = require$$1;
|
|
11066
11067
|
|
|
11068
|
+
/**
|
|
11069
|
+
* Saves or updates an analyzer configuration.
|
|
11070
|
+
*
|
|
11071
|
+
* This function takes the analyzer ID and its full instructions content,
|
|
11072
|
+
* parses the ID to determine the directory structure, creates directories
|
|
11073
|
+
* if necessary, saves the instructions to '1.md'. Optionally, it can
|
|
11074
|
+
* ensure config.json files exist with labels derived from directory names.
|
|
11075
|
+
*
|
|
11076
|
+
* @param {string} analyzeMessagesBasePath - The absolute or relative path to the 'messages/analyze' directory.
|
|
11077
|
+
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11078
|
+
* @param {string} instructionsContent - The full content of the analyzer instructions message to be saved in '1.md'.
|
|
11079
|
+
* @param {object} [options={}] - Optional configuration options.
|
|
11080
|
+
* @param {boolean} [options.ensureConfigs=false] - If true, ensures config.json files exist in the analyzer, content, and instructions directories. Defaults to false.
|
|
11081
|
+
* @returns {Promise<{success: boolean, message?: string}>} A promise that resolves with a result object.
|
|
11082
|
+
*/
|
|
11083
|
+
async function saveConfiguration$1(analyzeMessagesBasePath, analyzerId, instructionsContent, options = {}) {
|
|
11084
|
+
const { ensureConfigs = false } = options;
|
|
11067
11085
|
|
|
11068
|
-
|
|
11086
|
+
// 1. Validate inputs
|
|
11087
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
11088
|
+
return { success: false, message: 'analyzeMessagesBasePath is required.' };
|
|
11089
|
+
}
|
|
11090
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11091
|
+
return { success: false, message: 'analyzerId is required.' };
|
|
11092
|
+
}
|
|
11093
|
+
if (typeof instructionsContent !== 'string' || instructionsContent.trim() === '') {
|
|
11094
|
+
return { success: false, message: 'instructionsContent is required.' };
|
|
11095
|
+
}
|
|
11096
|
+
|
|
11097
|
+
// 2. Parse analyzerId
|
|
11098
|
+
const parts = analyzerId.split('::');
|
|
11099
|
+
if (parts.length !== 3) {
|
|
11100
|
+
return { success: false, message: `Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.` };
|
|
11101
|
+
}
|
|
11102
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
11103
|
+
|
|
11104
|
+
// Helper to validate directory names based on README.md rules
|
|
11105
|
+
const isValidDirName = (name) => {
|
|
11106
|
+
// Cannot start with underscore, cannot contain dots, must be alphanumeric, dash, or underscore
|
|
11107
|
+
return /^[a-zA-Z0-9_-]+$/.test(name) && !name.startsWith('_') && !name.includes('.');
|
|
11069
11108
|
};
|
|
11070
11109
|
|
|
11110
|
+
if (!isValidDirName(analyzerName)) {
|
|
11111
|
+
return { success: false, message: `Invalid analyzer name '${analyzerName}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11112
|
+
}
|
|
11113
|
+
if (!isValidDirName(contentType)) {
|
|
11114
|
+
return { success: false, message: `Invalid content type name '${contentType}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11115
|
+
}
|
|
11116
|
+
if (!isValidDirName(instructionsType)) {
|
|
11117
|
+
return { success: false, message: `Invalid instructions type name '${instructionsType}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11118
|
+
}
|
|
11119
|
+
|
|
11120
|
+
// 3. Construct directory paths
|
|
11121
|
+
const analyzerDir = path$3.join(analyzeMessagesBasePath, analyzerName);
|
|
11122
|
+
const contentDir = path$3.join(analyzerDir, contentType);
|
|
11123
|
+
const instructionsDir = path$3.join(contentDir, instructionsType);
|
|
11124
|
+
const instructionsFilePath = path$3.join(instructionsDir, '1.md');
|
|
11125
|
+
|
|
11126
|
+
try {
|
|
11127
|
+
// 4. Create directories recursively
|
|
11128
|
+
await fs$5.mkdir(instructionsDir, { recursive: true });
|
|
11129
|
+
|
|
11130
|
+
// 5. Save instructions content to 1.md
|
|
11131
|
+
const finalContent = `; role: assistant\n\n\n${instructionsContent}`;
|
|
11132
|
+
await fs$5.writeFile(instructionsFilePath, finalContent, 'utf8');
|
|
11133
|
+
|
|
11134
|
+
// 6. Optionally create/Update config.json files
|
|
11135
|
+
if (ensureConfigs) {
|
|
11136
|
+
await ensureConfigJson(analyzerDir, analyzerName);
|
|
11137
|
+
await ensureConfigJson(contentDir, contentType);
|
|
11138
|
+
await ensureConfigJson(instructionsDir, instructionsType);
|
|
11139
|
+
}
|
|
11140
|
+
|
|
11141
|
+
return { success: true, message: `Analyzer configuration '${analyzerId}' saved successfully.` };
|
|
11142
|
+
|
|
11143
|
+
} catch (error) {
|
|
11144
|
+
console.error(`Error saving analyzer configuration '${analyzerId}':`, error);
|
|
11145
|
+
return { success: false, message: `Failed to save analyzer configuration: ${error.message}` };
|
|
11146
|
+
}
|
|
11147
|
+
}
|
|
11148
|
+
|
|
11149
|
+
/**
|
|
11150
|
+
* Ensures a config.json file exists in the given directory with a label.
|
|
11151
|
+
* If the file exists, it reads it and adds the label if missing.
|
|
11152
|
+
* If the file doesn't exist, it creates it with the label.
|
|
11153
|
+
*
|
|
11154
|
+
* @param {string} dirPath - The path to the directory.
|
|
11155
|
+
* @param {string} label - The label to ensure is in the config.json.
|
|
11156
|
+
*/
|
|
11157
|
+
async function ensureConfigJson(dirPath, label) {
|
|
11158
|
+
const configPath = path$3.join(dirPath, 'config.json');
|
|
11159
|
+
let config = {};
|
|
11160
|
+
|
|
11161
|
+
try {
|
|
11162
|
+
const fileContent = await fs$5.readFile(configPath, 'utf8');
|
|
11163
|
+
config = JSON.parse(fileContent);
|
|
11164
|
+
} catch (error) {
|
|
11165
|
+
// If file doesn't exist or parsing fails, start with an empty config
|
|
11166
|
+
if (error.code !== 'ENOENT') {
|
|
11167
|
+
console.warn(`Failed to read or parse existing config.json in ${dirPath}: ${error.message}`);
|
|
11168
|
+
}
|
|
11169
|
+
config = {}; // Ensure config is an object even on error
|
|
11170
|
+
}
|
|
11171
|
+
|
|
11172
|
+
// Add or update the label if it's missing or empty
|
|
11173
|
+
if (!config.label || typeof config.label !== 'string' || config.label.trim() === '') {
|
|
11174
|
+
// Capitalize the first letter for the label
|
|
11175
|
+
config.label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
11176
|
+
}
|
|
11177
|
+
|
|
11178
|
+
// Write the updated config back to the file
|
|
11179
|
+
await fs$5.writeFile(configPath, JSON.stringify(config, null, 4), 'utf8');
|
|
11180
|
+
}
|
|
11181
|
+
|
|
11182
|
+
|
|
11183
|
+
var saver = {
|
|
11184
|
+
saveConfiguration: saveConfiguration$1,
|
|
11185
|
+
};
|
|
11186
|
+
|
|
11071
11187
|
/*
|
|
11072
11188
|
* Component: AnalyzerUtils Schema Loader
|
|
11073
11189
|
* Block-UUID: 0c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f
|
package/dist/gsc-utils.esm.js
CHANGED
|
@@ -16,8 +16,8 @@ function getDefaultExportFromCjs (x) {
|
|
|
16
16
|
* Authors: Claude 3.7 Sonnet (v1.0.0), Gemini 2.5 Pro (v1.1.0), Gemini 2.5 Flash Thinking (v1.2.0)
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
const fs$
|
|
20
|
-
const path$
|
|
19
|
+
const fs$7 = require$$0;
|
|
20
|
+
const path$5 = require$$1;
|
|
21
21
|
const ANALYZE_MESSAGE_REGEXP = /^# Analyze - `([^`]+)`\n/;
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -51,12 +51,12 @@ function unescapeCodeBlocks(content) {
|
|
|
51
51
|
* @returns {Array} An array of message objects with role and content properties
|
|
52
52
|
*/
|
|
53
53
|
function getChatTemplateMessages$1(dirname, messageType) {
|
|
54
|
-
const messagesDir = path$
|
|
54
|
+
const messagesDir = path$5.join(dirname, messageType);
|
|
55
55
|
const messages = [];
|
|
56
56
|
|
|
57
57
|
try {
|
|
58
58
|
// Read all files in the directory
|
|
59
|
-
const files = fs$
|
|
59
|
+
const files = fs$7.readdirSync(messagesDir);
|
|
60
60
|
|
|
61
61
|
// Sort files numerically (1.md, 2.md, etc.)
|
|
62
62
|
const sortedFiles = files.sort((a, b) => {
|
|
@@ -67,9 +67,9 @@ function getChatTemplateMessages$1(dirname, messageType) {
|
|
|
67
67
|
|
|
68
68
|
// Process each file
|
|
69
69
|
for (const file of sortedFiles) {
|
|
70
|
-
if (path$
|
|
71
|
-
const filePath = path$
|
|
72
|
-
const fileContent = fs$
|
|
70
|
+
if (path$5.extname(file) === '.md') {
|
|
71
|
+
const filePath = path$5.join(messagesDir, file);
|
|
72
|
+
const fileContent = fs$7.readFileSync(filePath, 'utf8');
|
|
73
73
|
|
|
74
74
|
// Split by triple newline to separate metadata from content
|
|
75
75
|
const parts = fileContent.split('\n\n\n');
|
|
@@ -10923,8 +10923,8 @@ var dataValidator = {
|
|
|
10923
10923
|
* Authors: Gemini 2.5 Flash (v1.0.0)
|
|
10924
10924
|
*/
|
|
10925
10925
|
|
|
10926
|
-
const fs$
|
|
10927
|
-
const path$
|
|
10926
|
+
const fs$6 = require$$0.promises;
|
|
10927
|
+
const path$4 = require$$1;
|
|
10928
10928
|
|
|
10929
10929
|
/**
|
|
10930
10930
|
* Reads and parses the config.json file in a directory.
|
|
@@ -10933,9 +10933,9 @@ const path$3 = require$$1;
|
|
|
10933
10933
|
* or null if the file doesn't exist or is invalid.
|
|
10934
10934
|
*/
|
|
10935
10935
|
async function readConfig$1(dirPath) {
|
|
10936
|
-
const configPath = path$
|
|
10936
|
+
const configPath = path$4.join(dirPath, 'config.json');
|
|
10937
10937
|
try {
|
|
10938
|
-
const fileContent = await fs$
|
|
10938
|
+
const fileContent = await fs$6.readFile(configPath, 'utf8');
|
|
10939
10939
|
return JSON.parse(fileContent);
|
|
10940
10940
|
} catch (error) {
|
|
10941
10941
|
if (error.code !== 'ENOENT') {
|
|
@@ -10972,41 +10972,41 @@ async function getAnalyzers$2(analyzeMessagesBasePath) {
|
|
|
10972
10972
|
const analyzers = [];
|
|
10973
10973
|
|
|
10974
10974
|
try {
|
|
10975
|
-
const analyzerEntries = await fs$
|
|
10975
|
+
const analyzerEntries = await fs$6.readdir(analyzeMessagesBasePath, { withFileTypes: true });
|
|
10976
10976
|
|
|
10977
10977
|
for (const analyzerEntry of analyzerEntries) {
|
|
10978
10978
|
if (analyzerEntry.isDirectory() && isValidDirName(analyzerEntry.name)) {
|
|
10979
10979
|
const analyzerName = analyzerEntry.name;
|
|
10980
|
-
const analyzerPath = path$
|
|
10980
|
+
const analyzerPath = path$4.join(analyzeMessagesBasePath, analyzerName);
|
|
10981
10981
|
const analyzerConfig = await readConfig$1(analyzerPath);
|
|
10982
10982
|
const analyzerLabel = analyzerConfig?.label || analyzerName;
|
|
10983
10983
|
|
|
10984
|
-
const contentEntries = await fs$
|
|
10984
|
+
const contentEntries = await fs$6.readdir(analyzerPath, { withFileTypes: true });
|
|
10985
10985
|
|
|
10986
10986
|
for (const contentEntry of contentEntries) {
|
|
10987
10987
|
if (contentEntry.isDirectory() && isValidDirName(contentEntry.name)) {
|
|
10988
10988
|
const contentType = contentEntry.name;
|
|
10989
|
-
const contentPath = path$
|
|
10989
|
+
const contentPath = path$4.join(analyzerPath, contentType);
|
|
10990
10990
|
const contentConfig = await readConfig$1(contentPath);
|
|
10991
10991
|
const contentLabel = contentConfig?.label || contentType;
|
|
10992
10992
|
|
|
10993
|
-
const instructionsEntries = await fs$
|
|
10993
|
+
const instructionsEntries = await fs$6.readdir(contentPath, { withFileTypes: true });
|
|
10994
10994
|
|
|
10995
10995
|
for (const instructionsEntry of instructionsEntries) {
|
|
10996
10996
|
if (instructionsEntry.isDirectory() && isValidDirName(instructionsEntry.name)) {
|
|
10997
10997
|
const instructionsType = instructionsEntry.name;
|
|
10998
|
-
const instructionsPath = path$
|
|
10998
|
+
const instructionsPath = path$4.join(contentPath, instructionsType);
|
|
10999
10999
|
const instructionsConfig = await readConfig$1(instructionsPath);
|
|
11000
11000
|
const instructionsLabel = instructionsConfig?.label || instructionsType;
|
|
11001
11001
|
|
|
11002
11002
|
// Check for the existence of 1.md to confirm a valid analyzer configuration
|
|
11003
|
-
const instructionsFilePath = path$
|
|
11003
|
+
const instructionsFilePath = path$4.join(instructionsPath, '1.md');
|
|
11004
11004
|
try {
|
|
11005
|
-
await fs$
|
|
11005
|
+
await fs$6.access(instructionsFilePath); // Check if file exists and is accessible
|
|
11006
11006
|
|
|
11007
11007
|
// If analyzerName starts with 'tutorial-', check its last modified time.
|
|
11008
11008
|
if (analyzerName.startsWith('tutorial-')) {
|
|
11009
|
-
const stats = await fs$
|
|
11009
|
+
const stats = await fs$6.stat(instructionsFilePath);
|
|
11010
11010
|
const lastModified = stats.mtime.getTime(); // Get timestamp in milliseconds
|
|
11011
11011
|
const sixtyMinutesAgo = Date.now() - (60 * 60 * 1000); // Current time - 60 minutes in ms
|
|
11012
11012
|
|
|
@@ -11060,12 +11060,128 @@ var discovery = {
|
|
|
11060
11060
|
* Authors: Gemini 2.5 Flash Thinking (v1.0.0), Gemini 2.5 Flash Thinking (v1.1.0)
|
|
11061
11061
|
*/
|
|
11062
11062
|
|
|
11063
|
-
require$$0.promises;
|
|
11063
|
+
const fs$5 = require$$0.promises;
|
|
11064
|
+
const path$3 = require$$1;
|
|
11064
11065
|
|
|
11066
|
+
/**
|
|
11067
|
+
* Saves or updates an analyzer configuration.
|
|
11068
|
+
*
|
|
11069
|
+
* This function takes the analyzer ID and its full instructions content,
|
|
11070
|
+
* parses the ID to determine the directory structure, creates directories
|
|
11071
|
+
* if necessary, saves the instructions to '1.md'. Optionally, it can
|
|
11072
|
+
* ensure config.json files exist with labels derived from directory names.
|
|
11073
|
+
*
|
|
11074
|
+
* @param {string} analyzeMessagesBasePath - The absolute or relative path to the 'messages/analyze' directory.
|
|
11075
|
+
* @param {string} analyzerId - The unique ID of the analyzer (format: 'analyzer_name::content_type::instructions_type').
|
|
11076
|
+
* @param {string} instructionsContent - The full content of the analyzer instructions message to be saved in '1.md'.
|
|
11077
|
+
* @param {object} [options={}] - Optional configuration options.
|
|
11078
|
+
* @param {boolean} [options.ensureConfigs=false] - If true, ensures config.json files exist in the analyzer, content, and instructions directories. Defaults to false.
|
|
11079
|
+
* @returns {Promise<{success: boolean, message?: string}>} A promise that resolves with a result object.
|
|
11080
|
+
*/
|
|
11081
|
+
async function saveConfiguration$1(analyzeMessagesBasePath, analyzerId, instructionsContent, options = {}) {
|
|
11082
|
+
const { ensureConfigs = false } = options;
|
|
11065
11083
|
|
|
11066
|
-
|
|
11084
|
+
// 1. Validate inputs
|
|
11085
|
+
if (typeof analyzeMessagesBasePath !== 'string' || analyzeMessagesBasePath.trim() === '') {
|
|
11086
|
+
return { success: false, message: 'analyzeMessagesBasePath is required.' };
|
|
11087
|
+
}
|
|
11088
|
+
if (typeof analyzerId !== 'string' || analyzerId.trim() === '') {
|
|
11089
|
+
return { success: false, message: 'analyzerId is required.' };
|
|
11090
|
+
}
|
|
11091
|
+
if (typeof instructionsContent !== 'string' || instructionsContent.trim() === '') {
|
|
11092
|
+
return { success: false, message: 'instructionsContent is required.' };
|
|
11093
|
+
}
|
|
11094
|
+
|
|
11095
|
+
// 2. Parse analyzerId
|
|
11096
|
+
const parts = analyzerId.split('::');
|
|
11097
|
+
if (parts.length !== 3) {
|
|
11098
|
+
return { success: false, message: `Invalid analyzerId format. Expected 'analyzer_name::content_type::instructions_type', but got '${analyzerId}'.` };
|
|
11099
|
+
}
|
|
11100
|
+
const [analyzerName, contentType, instructionsType] = parts;
|
|
11101
|
+
|
|
11102
|
+
// Helper to validate directory names based on README.md rules
|
|
11103
|
+
const isValidDirName = (name) => {
|
|
11104
|
+
// Cannot start with underscore, cannot contain dots, must be alphanumeric, dash, or underscore
|
|
11105
|
+
return /^[a-zA-Z0-9_-]+$/.test(name) && !name.startsWith('_') && !name.includes('.');
|
|
11067
11106
|
};
|
|
11068
11107
|
|
|
11108
|
+
if (!isValidDirName(analyzerName)) {
|
|
11109
|
+
return { success: false, message: `Invalid analyzer name '${analyzerName}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11110
|
+
}
|
|
11111
|
+
if (!isValidDirName(contentType)) {
|
|
11112
|
+
return { success: false, message: `Invalid content type name '${contentType}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11113
|
+
}
|
|
11114
|
+
if (!isValidDirName(instructionsType)) {
|
|
11115
|
+
return { success: false, message: `Invalid instructions type name '${instructionsType}'. Names must be alphanumeric, dash, or underscore, cannot start with underscore, and cannot contain dots.` };
|
|
11116
|
+
}
|
|
11117
|
+
|
|
11118
|
+
// 3. Construct directory paths
|
|
11119
|
+
const analyzerDir = path$3.join(analyzeMessagesBasePath, analyzerName);
|
|
11120
|
+
const contentDir = path$3.join(analyzerDir, contentType);
|
|
11121
|
+
const instructionsDir = path$3.join(contentDir, instructionsType);
|
|
11122
|
+
const instructionsFilePath = path$3.join(instructionsDir, '1.md');
|
|
11123
|
+
|
|
11124
|
+
try {
|
|
11125
|
+
// 4. Create directories recursively
|
|
11126
|
+
await fs$5.mkdir(instructionsDir, { recursive: true });
|
|
11127
|
+
|
|
11128
|
+
// 5. Save instructions content to 1.md
|
|
11129
|
+
const finalContent = `; role: assistant\n\n\n${instructionsContent}`;
|
|
11130
|
+
await fs$5.writeFile(instructionsFilePath, finalContent, 'utf8');
|
|
11131
|
+
|
|
11132
|
+
// 6. Optionally create/Update config.json files
|
|
11133
|
+
if (ensureConfigs) {
|
|
11134
|
+
await ensureConfigJson(analyzerDir, analyzerName);
|
|
11135
|
+
await ensureConfigJson(contentDir, contentType);
|
|
11136
|
+
await ensureConfigJson(instructionsDir, instructionsType);
|
|
11137
|
+
}
|
|
11138
|
+
|
|
11139
|
+
return { success: true, message: `Analyzer configuration '${analyzerId}' saved successfully.` };
|
|
11140
|
+
|
|
11141
|
+
} catch (error) {
|
|
11142
|
+
console.error(`Error saving analyzer configuration '${analyzerId}':`, error);
|
|
11143
|
+
return { success: false, message: `Failed to save analyzer configuration: ${error.message}` };
|
|
11144
|
+
}
|
|
11145
|
+
}
|
|
11146
|
+
|
|
11147
|
+
/**
|
|
11148
|
+
* Ensures a config.json file exists in the given directory with a label.
|
|
11149
|
+
* If the file exists, it reads it and adds the label if missing.
|
|
11150
|
+
* If the file doesn't exist, it creates it with the label.
|
|
11151
|
+
*
|
|
11152
|
+
* @param {string} dirPath - The path to the directory.
|
|
11153
|
+
* @param {string} label - The label to ensure is in the config.json.
|
|
11154
|
+
*/
|
|
11155
|
+
async function ensureConfigJson(dirPath, label) {
|
|
11156
|
+
const configPath = path$3.join(dirPath, 'config.json');
|
|
11157
|
+
let config = {};
|
|
11158
|
+
|
|
11159
|
+
try {
|
|
11160
|
+
const fileContent = await fs$5.readFile(configPath, 'utf8');
|
|
11161
|
+
config = JSON.parse(fileContent);
|
|
11162
|
+
} catch (error) {
|
|
11163
|
+
// If file doesn't exist or parsing fails, start with an empty config
|
|
11164
|
+
if (error.code !== 'ENOENT') {
|
|
11165
|
+
console.warn(`Failed to read or parse existing config.json in ${dirPath}: ${error.message}`);
|
|
11166
|
+
}
|
|
11167
|
+
config = {}; // Ensure config is an object even on error
|
|
11168
|
+
}
|
|
11169
|
+
|
|
11170
|
+
// Add or update the label if it's missing or empty
|
|
11171
|
+
if (!config.label || typeof config.label !== 'string' || config.label.trim() === '') {
|
|
11172
|
+
// Capitalize the first letter for the label
|
|
11173
|
+
config.label = label.charAt(0).toUpperCase() + label.slice(1);
|
|
11174
|
+
}
|
|
11175
|
+
|
|
11176
|
+
// Write the updated config back to the file
|
|
11177
|
+
await fs$5.writeFile(configPath, JSON.stringify(config, null, 4), 'utf8');
|
|
11178
|
+
}
|
|
11179
|
+
|
|
11180
|
+
|
|
11181
|
+
var saver = {
|
|
11182
|
+
saveConfiguration: saveConfiguration$1,
|
|
11183
|
+
};
|
|
11184
|
+
|
|
11069
11185
|
/*
|
|
11070
11186
|
* Component: AnalyzerUtils Schema Loader
|
|
11071
11187
|
* Block-UUID: 0c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f
|
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@ const path = require('path');
|
|
|
28
28
|
* @param {boolean} [options.ensureConfigs=false] - If true, ensures config.json files exist in the analyzer, content, and instructions directories. Defaults to false.
|
|
29
29
|
* @returns {Promise<{success: boolean, message?: string}>} A promise that resolves with a result object.
|
|
30
30
|
*/
|
|
31
|
-
async function
|
|
31
|
+
async function saveConfiguration(analyzeMessagesBasePath, analyzerId, instructionsContent, options = {}) {
|
|
32
32
|
const { ensureConfigs = false } = options;
|
|
33
33
|
|
|
34
34
|
// 1. Validate inputs
|
|
@@ -129,5 +129,5 @@ async function ensureConfigJson(dirPath, label) {
|
|
|
129
129
|
|
|
130
130
|
|
|
131
131
|
module.exports = {
|
|
132
|
-
|
|
132
|
+
saveConfiguration,
|
|
133
133
|
};
|