maiass 5.7.31 → 5.7.33

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.
@@ -0,0 +1,215 @@
1
+ // Changelog management for MAIASS - matches bashmaiass implementation
2
+ import { execSync } from 'child_process';
3
+ import fs from 'fs/promises';
4
+ import { log } from './logger.js';
5
+ import { SYMBOLS } from './symbols.js';
6
+
7
+ /**
8
+ * Execute git command and return output
9
+ * @param {string} command - Git command to execute
10
+ * @returns {string|null} Command output or null if failed
11
+ */
12
+ function executeGitCommand(command) {
13
+ try {
14
+ return execSync(command, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'ignore'] }).trim();
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+
20
+ /**
21
+ * Get the last changelog commit hash
22
+ * @param {string} changelogPath - Path to changelog file
23
+ * @returns {string|null} Commit hash or null
24
+ */
25
+ function getLastChangelogCommit(changelogPath) {
26
+ try {
27
+ const content = execSync(`cat "${changelogPath}"`, { encoding: 'utf8' });
28
+ const match = content.match(/^## (.+)$/m);
29
+ if (match) {
30
+ const lastVersion = match[1].trim();
31
+ const hash = executeGitCommand(`git log -1 --format="%H" -S"## ${lastVersion}" -- "${changelogPath}"`);
32
+ if (hash) return hash;
33
+ }
34
+ } catch {}
35
+
36
+ // Fallback to first commit
37
+ return executeGitCommand('git rev-list --max-parents=0 HEAD');
38
+ }
39
+
40
+ /**
41
+ * Update changelog files with new version and commits
42
+ * @param {string} changelogPath - Directory containing changelog
43
+ * @param {string} version - New version number
44
+ * @returns {Promise<void>}
45
+ */
46
+ export async function updateChangelog(changelogPath = '.', version) {
47
+ const changelogName = process.env.MAIASS_CHANGELOG_NAME || 'CHANGELOG.md';
48
+ const changelogInternalName = process.env.MAIASS_CHANGELOG_INTERNAL_NAME || '.CHANGELOG_internal.md';
49
+ const changelogInternalPath = process.env.MAIASS_CHANGELOG_INTERNAL_PATH || changelogPath;
50
+
51
+ const changelogFile = `${changelogPath}/${changelogName}`;
52
+ const changelogInternalFile = `${changelogInternalPath}/${changelogInternalName}`;
53
+
54
+ // Get last changelog commit
55
+ let lastChangelogCommit = null;
56
+ try {
57
+ await fs.access(changelogFile);
58
+ lastChangelogCommit = getLastChangelogCommit(changelogFile);
59
+ } catch {}
60
+
61
+ if (!lastChangelogCommit) {
62
+ lastChangelogCommit = executeGitCommand('git rev-list --max-parents=0 HEAD');
63
+ }
64
+
65
+ if (!lastChangelogCommit) {
66
+ log.info(SYMBOLS.INFO, 'No commits found, skipping changelog');
67
+ return;
68
+ }
69
+
70
+ const logRange = `${lastChangelogCommit}..HEAD`;
71
+
72
+ // Get commits for main changelog (remove JIRA tickets, filter out merges/bumps)
73
+ const rawCommits = executeGitCommand(`git log ${logRange} --pretty=format:"%B"`);
74
+
75
+ let changelog = '';
76
+ if (rawCommits) {
77
+ // Process commits: filter and format
78
+ const commits = rawCommits.split('\n\n').filter(commit => {
79
+ const firstLine = commit.split('\n')[0].toLowerCase();
80
+ return !firstLine.match(/^(ncl|merge|bump|fixing merge conflicts)/i);
81
+ });
82
+
83
+ const formattedCommits = commits.map(commit => {
84
+ // Remove JIRA ticket from start
85
+ const cleaned = commit.replace(/^\[?[A-Z]+-[0-9]+\]?[\s:—-]+/gm, '');
86
+ const lines = cleaned.split('\n').filter(l => l.trim());
87
+
88
+ if (lines.length === 0) return '';
89
+
90
+ // First line as bullet, rest as indented sub-bullets
91
+ let result = `- ${lines[0]}`;
92
+ for (let i = 1; i < lines.length; i++) {
93
+ if (lines[i].trim()) {
94
+ result += `\n\t${lines[i]}`;
95
+ }
96
+ }
97
+ return result;
98
+ }).filter(c => c);
99
+
100
+ changelog = formattedCommits.join('\n');
101
+ }
102
+
103
+ // Get commits for internal changelog (with author names)
104
+ const rawInternalCommits = executeGitCommand(`git log ${logRange} --pretty=format:"%an%n%B"`);
105
+
106
+ let changelogInternal = '';
107
+ if (rawInternalCommits) {
108
+ // Process internal commits with author
109
+ const commitBlocks = rawInternalCommits.split('\n\n').filter(block => {
110
+ const lines = block.split('\n');
111
+ if (lines.length < 2) return false;
112
+ const subject = lines[1].toLowerCase();
113
+ return !subject.match(/^(ncl|merge|bump|fixing merge conflicts)/i);
114
+ });
115
+
116
+ const formattedInternal = commitBlocks.map(block => {
117
+ const lines = block.split('\n').filter(l => l.trim());
118
+ if (lines.length < 2) return '';
119
+
120
+ const author = lines[0];
121
+ const subject = lines[1]; // Keep JIRA ticket in internal changelog
122
+
123
+ let result = `- ${author}: ${subject}`;
124
+ for (let i = 2; i < lines.length; i++) {
125
+ if (lines[i].trim()) {
126
+ result += `\n\t${lines[i]}`;
127
+ }
128
+ }
129
+ return result;
130
+ }).filter(c => c);
131
+
132
+ changelogInternal = formattedInternal.join('\n');
133
+ }
134
+
135
+ // Get current date
136
+ const now = new Date();
137
+ const humanDate = now.toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' });
138
+ const weekday = now.toLocaleDateString('en-GB', { weekday: 'long' });
139
+ const longHumanDate = `${humanDate} (${weekday})`;
140
+
141
+ // Update main changelog
142
+ if (!changelog) {
143
+ log.info(SYMBOLS.INFO, 'No changelog to add');
144
+ } else {
145
+ try {
146
+ let existingContent = '';
147
+ try {
148
+ existingContent = await fs.readFile(changelogFile, 'utf8');
149
+ } catch {}
150
+
151
+ if (existingContent) {
152
+ const lines = existingContent.split('\n');
153
+ const firstVersion = lines[0]?.match(/^## (.+)$/)?.[1];
154
+ const secondLine = lines[1];
155
+
156
+ // Check if we're updating the same minor version on the same date
157
+ const currentMinor = version.split('.').slice(0, 2).join('.');
158
+ const existingMinor = firstVersion?.split('.').slice(0, 2).join('.');
159
+
160
+ if (currentMinor === existingMinor && secondLine === humanDate) {
161
+ // Replace existing entry
162
+ const newContent = `## ${version}\n${humanDate}\n\n${changelog}\n${lines.slice(3).join('\n')}`;
163
+ await fs.writeFile(changelogFile, newContent, 'utf8');
164
+ } else {
165
+ // Add new entry
166
+ const newContent = `## ${version}\n${humanDate}\n\n${changelog}\n\n${existingContent}`;
167
+ await fs.writeFile(changelogFile, newContent, 'utf8');
168
+ }
169
+ } else {
170
+ // Create new file
171
+ await fs.writeFile(changelogFile, `## ${version}\n${humanDate}\n\n${changelog}\n`, 'utf8');
172
+ }
173
+
174
+ log.success(SYMBOLS.CHECKMARK, `Updated ${changelogName}`);
175
+ } catch (error) {
176
+ log.error(SYMBOLS.CROSS, `Failed to update ${changelogName}: ${error.message}`);
177
+ }
178
+ }
179
+
180
+ // Update internal changelog
181
+ if (!changelogInternal) {
182
+ log.info(SYMBOLS.INFO, 'No commits for internal changelog - updating version header only');
183
+ }
184
+
185
+ try {
186
+ await fs.access(changelogInternalFile);
187
+
188
+ let existingContent = await fs.readFile(changelogInternalFile, 'utf8');
189
+ const lines = existingContent.split('\n');
190
+ const firstVersion = lines[0]?.match(/^## (.+)$/)?.[1];
191
+ const secondLine = lines[1];
192
+
193
+ // Check if we're updating the same minor version on the same date
194
+ const currentMinor = version.split('.').slice(0, 2).join('.');
195
+ const existingMinor = firstVersion?.split('.').slice(0, 2).join('.');
196
+
197
+ const contentToAdd = changelogInternal || '';
198
+
199
+ if (currentMinor === existingMinor && secondLine === longHumanDate) {
200
+ // Replace existing entry
201
+ const newContent = `## ${version}\n${longHumanDate}\n\n${contentToAdd}\n${lines.slice(3).join('\n')}`;
202
+ await fs.writeFile(changelogInternalFile, newContent, 'utf8');
203
+ } else {
204
+ // Add new entry
205
+ const newContent = `## ${version}\n${longHumanDate}\n\n${contentToAdd}\n\n${existingContent}`;
206
+ await fs.writeFile(changelogInternalFile, newContent, 'utf8');
207
+ }
208
+
209
+ log.success(SYMBOLS.CHECKMARK, `Updated ${changelogInternalName}`);
210
+ } catch (error) {
211
+ log.info(SYMBOLS.INFO, `Internal changelog ${changelogInternalFile} does not exist, skipping`);
212
+ }
213
+ }
214
+
215
+ export default { updateChangelog };
package/maiass.mjs CHANGED
@@ -107,55 +107,66 @@ if (args.includes('--help') || args.includes('-h') || command === 'help') {
107
107
  process.exit(0);
108
108
  }
109
109
 
110
- // Command routing
111
- switch (command) {
112
- case 'hello':
113
- console.log(colors.BCyan('Hello from MAIASS!'));
114
- break;
115
-
116
- case 'env':
117
- displayEnvironmentVariables();
118
- break;
119
-
120
- case 'git-info':
121
- const gitInfo = getGitInfo();
122
- displayGitInfo(gitInfo);
123
- break;
124
-
125
- case 'config':
126
- handleConfigCommand(process.argv.slice(3));
127
- break;
128
-
129
- case 'version':
130
- handleVersionCommand(process.argv.slice(3));
131
- break;
132
-
133
- case 'account-info':
134
- handleAccountInfoCommand({
135
- json: args.includes('--json')
136
- });
137
- break;
138
-
139
- case 'maiass':
140
- // Handle the main MAIASS workflow
141
- handleMaiassCommand({
142
- _: process.argv.slice(2).filter(arg => !arg.startsWith('--')),
143
- 'commits-only': args.includes('--commits-only') || args.includes('-c'),
144
- 'auto-stage': args.includes('--auto-stage'),
145
- 'auto': args.includes('--auto'),
146
- 'version-bump': versionBump,
147
- 'dry-run': args.includes('--dry-run') || args.includes('-d'),
148
- force: args.includes('--force') || args.includes('-f'),
149
- silent: args.includes('--silent') || args.includes('-s'),
150
- tag: getArgValue(args, '--tag') || getArgValue(args, '-t')
151
- });
152
- break;
153
-
154
- default:
155
- console.error(`Unknown command: ${command}`);
156
- console.log('Run `maiass --help` for available commands.');
157
- process.exit(1);
158
- }
110
+ // Command routing (wrapped in async IIFE to handle async commands)
111
+ (async () => {
112
+ switch (command) {
113
+ case 'hello':
114
+ console.log(colors.BCyan('Hello from MAIASS!'));
115
+ break;
116
+
117
+ case 'env':
118
+ displayEnvironmentVariables();
119
+ break;
120
+
121
+ case 'git-info':
122
+ const gitInfo = getGitInfo();
123
+ displayGitInfo(gitInfo);
124
+ break;
125
+
126
+ case 'config':
127
+ await handleConfigCommand(process.argv.slice(3));
128
+ break;
129
+
130
+ case 'version':
131
+ await handleVersionCommand(process.argv.slice(3));
132
+ break;
133
+
134
+ case 'account-info':
135
+ await handleAccountInfoCommand({
136
+ json: args.includes('--json')
137
+ });
138
+ break;
139
+
140
+ case 'maiass':
141
+ // Handle the main MAIASS workflow
142
+ await handleMaiassCommand({
143
+ _: process.argv.slice(2).filter(arg => !arg.startsWith('--')),
144
+ 'commits-only': args.includes('--commits-only') || args.includes('-c'),
145
+ 'auto-stage': args.includes('--auto-stage'),
146
+ 'auto': args.includes('--auto'),
147
+ 'version-bump': versionBump,
148
+ 'dry-run': args.includes('--dry-run') || args.includes('-d'),
149
+ force: args.includes('--force') || args.includes('-f'),
150
+ silent: args.includes('--silent') || args.includes('-s'),
151
+ tag: getArgValue(args, '--tag') || getArgValue(args, '-t')
152
+ });
153
+ break;
154
+
155
+ default:
156
+ console.error(`Unknown command: ${command}`);
157
+ console.log('Run `maiass --help` for available commands.');
158
+ process.exit(1);
159
+ }
160
+
161
+ // Exit cleanly after successful command execution
162
+ process.exit(0);
163
+ })().catch(error => {
164
+ console.error(colors.Red(`${SYMBOLS.CROSS} Fatal error: ${error.message}`));
165
+ if (process.env.MAIASS_DEBUG === 'true') {
166
+ console.error(colors.Gray(error.stack));
167
+ }
168
+ process.exit(1);
169
+ });
159
170
 
160
171
  // Helper function to get argument values
161
172
  function getArgValue(args, flag) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "maiass",
3
3
  "type": "module",
4
- "version": "5.7.31",
4
+ "version": "5.7.33",
5
5
  "description": "MAIASS - Modular AI-Augmented Semantic Scribe - Intelligent Git workflow automation",
6
6
  "main": "maiass.mjs",
7
7
  "bin": {
@@ -10,6 +10,15 @@
10
10
  },
11
11
  "author": "Velvary Pty Ltd",
12
12
  "license": "GPL-3.0-only",
13
+ "files": [
14
+ "lib/",
15
+ "maiass.mjs",
16
+ "maiass.cjs",
17
+ "maiass-standalone.cjs",
18
+ "setup-env.js",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
13
22
  "engines": {
14
23
  "node": ">=18.0.0"
15
24
  },
package/build.js DELETED
@@ -1,127 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Cross-platform build script for maiass
4
- * Builds binaries for all supported platforms and architectures
5
- */
6
-
7
- import { execSync } from 'child_process';
8
- import fs from 'fs';
9
- import path from 'path';
10
- import colors from './lib/colors.js';
11
-
12
- const targets = [
13
- 'node18-macos-x64',
14
- 'node18-macos-arm64',
15
- 'node18-linux-x64',
16
- 'node18-linux-arm64',
17
- 'node18-win-x64',
18
- 'node18-win-arm64'
19
- ];
20
-
21
- const platformNames = {
22
- 'node18-macos-x64': 'macOS Intel',
23
- 'node18-macos-arm64': 'macOS Apple Silicon',
24
- 'node18-linux-x64': 'Linux x64',
25
- 'node18-linux-arm64': 'Linux ARM64',
26
- 'node18-win-x64': 'Windows x64',
27
- 'node18-win-arm64': 'Windows ARM64'
28
- };
29
-
30
- function buildForTarget(target) {
31
- console.log(colors.BBlue(`Building for ${platformNames[target]}...`));
32
-
33
- // Map target to output filename
34
- const outputNames = {
35
- 'node18-macos-x64': 'maiass-macos-x64',
36
- 'node18-macos-arm64': 'maiass-macos-arm64',
37
- 'node18-linux-x64': 'maiass-linux-x64',
38
- 'node18-linux-arm64': 'maiass-linux-arm64',
39
- 'node18-win-x64': 'maiass-win-x64.exe',
40
- 'node18-win-arm64': 'maiass-win-arm64.exe'
41
- };
42
-
43
- const outputName = outputNames[target];
44
- const outputPath = `build/${outputName}`;
45
-
46
- try {
47
- execSync(`npx pkg . --target ${target} --output ${outputPath}`, {
48
- stdio: 'inherit',
49
- encoding: 'utf8'
50
- });
51
- console.log(colors.Green(`✓ Successfully built for ${platformNames[target]} -> ${outputName}`));
52
-
53
- // Code sign macOS binaries
54
- if (target.includes('macos') && process.platform === 'darwin') {
55
- try {
56
- console.log(colors.BBlue(` 🔐 Code signing ${outputName}...`));
57
- execSync(`./scripts/codesign.sh "${outputPath}"`, { stdio: 'pipe' });
58
- console.log(colors.Green(` ✓ Code signed ${outputName}`));
59
- } catch (error) {
60
- console.log(colors.Yellow(` ⚠️ Code signing failed for ${outputName} (continuing without signing)`));
61
- console.log(colors.Gray(` ${error.message.split('\n')[0]}`));
62
- }
63
- }
64
-
65
- // Code sign Windows binaries
66
- if (target.includes('win')) {
67
- try {
68
- console.log(colors.BBlue(` 🔐 Code signing ${outputName}...`));
69
- execSync(`./scripts/codesign-windows.sh "${outputPath}"`, { stdio: 'pipe' });
70
- console.log(colors.Green(` ✓ Code signed ${outputName}`));
71
- } catch (error) {
72
- console.log(colors.Yellow(` ⚠️ Windows code signing failed for ${outputName} (continuing without signing)`));
73
- console.log(colors.Gray(` ${error.message.split('\n')[0]}`));
74
- }
75
- }
76
-
77
- return true;
78
- } catch (error) {
79
- console.log(colors.Red(`✗ Failed to build for ${platformNames[target]}: ${error.message}`));
80
- return false;
81
- }
82
- }
83
-
84
- function main() {
85
- console.log(colors.Aqua('MAIASS Cross-Platform Build'));
86
- console.log(colors.White('Building binaries for all supported platforms...\n'));
87
-
88
- // Ensure build directory exists and is clean
89
- if (fs.existsSync('build')) {
90
- // Clean the build directory
91
- const files = fs.readdirSync('build');
92
- for (const file of files) {
93
- if (file !== '.DS_Store') {
94
- fs.unlinkSync(path.join('build', file));
95
- }
96
- }
97
- } else {
98
- fs.mkdirSync('build');
99
- }
100
-
101
- let successful = 0;
102
- let failed = 0;
103
-
104
- for (const target of targets) {
105
- if (buildForTarget(target)) {
106
- successful++;
107
- } else {
108
- failed++;
109
- }
110
- console.log(''); // Add spacing between builds
111
- }
112
-
113
- console.log(colors.White('\n=== Build Summary ==='));
114
- console.log(colors.Green(`Successful builds: ${successful}`));
115
- if (failed > 0) {
116
- console.log(colors.Red(`Failed builds: ${failed}`));
117
- }
118
-
119
- if (successful === targets.length) {
120
- console.log(colors.Green('\n🎉 All builds completed successfully!'));
121
- console.log(colors.White('Binaries are available in the build/ directory'));
122
- } else {
123
- console.log(colors.Yellow('\n⚠️ Some builds failed. Check the output above for details.'));
124
- }
125
- }
126
-
127
- main();