unicodemanager 0.6.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/LICENSE ADDED
@@ -0,0 +1,35 @@
1
+ UniCode-Manager Custom License v1.0
2
+
3
+ Copyright (c) 2026 Youcef Benabdallah. All rights reserved.
4
+
5
+ 1. Permitted Use
6
+ This software may only be used to generate, scaffold, build, and manage
7
+ extensions (".codix" packages) for the Unicode CLI ecosystem.
8
+
9
+ 2. Restrictions
10
+ You may NOT copy, modify, redistribute, reverse-engineer, decompile,
11
+ sublicense, or otherwise reuse any portion of this package's source code,
12
+ in whole or in part, for any purpose other than the permitted use stated
13
+ above. This includes, without limitation, using the code as a template,
14
+ incorporating it into other software, or republishing it.
15
+
16
+ 3. No Modification of Package Identity
17
+ The package name "unicodemanager" and display name "UniCode-Manager"
18
+ must remain unchanged. You may not publish forks, modified versions,
19
+ or derivative packages under the same or similar names.
20
+
21
+ 4. Disclaimer of Warranty
22
+ THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25
+
26
+ 5. Limitation of Liability
27
+ IN NO EVENT SHALL THE DEVELOPER (YOUCEF BENABDALLAH) BE LIABLE FOR ANY
28
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
29
+ OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
30
+ THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE USER ASSUMES ALL RISK AND
31
+ RESPONSIBILITY FOR ANY ISSUES ARISING FROM USE OF THIS SOFTWARE.
32
+
33
+ 6. Acceptance
34
+ By using this software, you accept and agree to all terms of this license.
35
+ If you do not agree, you must delete all copies immediately.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # UniCode-Manager
2
+
3
+ **Unicode CLI extension packaging and management toolkit** — build, scaffold, and publish `.codix` extensions.
4
+
5
+ Part of the [Unicode CLI](https://github.com/youcefdev/unicode) ecosystem.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g unicodemanager
11
+ ```
12
+
13
+ Or use directly with `npx` (no install needed):
14
+
15
+ ```bash
16
+ npx unicode build
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ Create a new extension:
22
+
23
+ ```bash
24
+ npx unicode init my-extension
25
+ cd my-extension
26
+ ```
27
+
28
+ Build it into a `.codix` package:
29
+
30
+ ```bash
31
+ npx unicode build
32
+ ```
33
+
34
+ Install it into Unicode CLI:
35
+
36
+ ```bash
37
+ unicode --install-extension my-extension.1.0.0.unicode.codix
38
+ ```
39
+
40
+ ## CLI Commands
41
+
42
+ | Command | Description |
43
+ |---------|-------------|
44
+ | `npx unicode init <name>` | Scaffold a new extension project |
45
+ | `npx unicode build [dir]` | Build `.codix` from extension directory |
46
+ | `npx unicode pack <dir>` | Pack extension into `.codix` (alias for build) |
47
+ | `npx unicode --help` | Show help |
48
+ | `npx unicode --version` | Show version |
49
+
50
+ ## Extension Structure
51
+
52
+ ```
53
+ my-extension/
54
+ ├── extension.json # Manifest (id, name, version, main, contributes)
55
+ ├── package.json # Node.js package
56
+ ├── main.js # Entry point with hook handlers
57
+ ├── node_modules/ # Dependencies (optional)
58
+ └── .gitignore
59
+ ```
60
+
61
+ ## Hook Protocol
62
+
63
+ Extensions communicate with the Unicode CLI via a simple subprocess protocol:
64
+
65
+ ```bash
66
+ node main.js --hook on_ai_response --data "AI response text"
67
+ ```
68
+
69
+ The extension writes the modified text to stdout. Supported hooks:
70
+
71
+ - `on_ai_response` — Modify AI responses before display
72
+ - `on_user_input` — Modify user input before sending to AI
73
+ - `on_command` — Intercept commands
74
+
75
+
76
+
77
+ ## License
78
+ 2026 Youcef Benabdallah
package/bin/unicode.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ // CLI entry point for `npx unicode` / `npx unicodemanager`
4
+ require('../index.js');
package/index.js ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+
3
+ const build = require('./lib/build');
4
+ const init = require('./lib/init');
5
+ const pack = require('./lib/pack');
6
+
7
+ const pkg = require('./package.json');
8
+
9
+ function printHelp() {
10
+ console.log(`
11
+ ${pkg.displayName} v${pkg.version}
12
+ ${pkg.description}
13
+
14
+ Usage:
15
+ npx unicode build Build .codix from current directory
16
+ npx unicode init <name> Scaffold a new extension project
17
+ npx unicode pack <source-dir> Pack extension directory into .codix
18
+ npx unicode --help Show this help
19
+ npx unicode --version Show version
20
+
21
+ Examples:
22
+ npx unicode init my-extension
23
+ cd my-extension
24
+ npx unicode build
25
+ npx unicode --install-extension my-extension.1.0.0.unicode.codix
26
+ `);
27
+ }
28
+
29
+ async function main() {
30
+ const args = process.argv.slice(2);
31
+ const cmd = args[0] || '';
32
+
33
+ if (cmd === '--version' || cmd === '-v') {
34
+ console.log(`${pkg.version}`);
35
+ return;
36
+ }
37
+
38
+ if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
39
+ printHelp();
40
+ return;
41
+ }
42
+
43
+ if (cmd === 'build') {
44
+ await build.run(args.slice(1));
45
+ return;
46
+ }
47
+
48
+ if (cmd === 'init') {
49
+ await init.run(args.slice(1));
50
+ return;
51
+ }
52
+
53
+ if (cmd === 'pack') {
54
+ await pack.run(args.slice(1));
55
+ return;
56
+ }
57
+
58
+ // No valid command
59
+ printHelp();
60
+ }
61
+
62
+ main().catch(err => {
63
+ console.error(' ✗', err.message);
64
+ process.exit(1);
65
+ });
package/lib/build.js ADDED
@@ -0,0 +1,72 @@
1
+ // lib/build.js — Build .codix from extension directory
2
+ // Usage: npx unicode build [source-dir] [output-file]
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const pack = require('./pack');
7
+
8
+ async function run(args) {
9
+ const srcDir = path.resolve(args[0] || process.cwd());
10
+ const outFile = args[1] || '';
11
+
12
+ // Validate source directory
13
+ if (!fs.existsSync(srcDir)) {
14
+ console.error(` ✗ Source directory not found: ${srcDir}`);
15
+ process.exit(1);
16
+ }
17
+
18
+ // Check for manifest
19
+ const manifestPath = path.join(srcDir, 'extension.json');
20
+ const pkgPath = path.join(srcDir, 'package.json');
21
+
22
+ if (!fs.existsSync(manifestPath) && !fs.existsSync(pkgPath)) {
23
+ console.error(` ✗ No extension.json or package.json found in ${srcDir}`);
24
+ console.error(' Run `npx unicode init <name>` to create a new extension.');
25
+ process.exit(1);
26
+ }
27
+
28
+ // Read manifest for name/version
29
+ let manifest;
30
+ try {
31
+ if (fs.existsSync(manifestPath)) {
32
+ manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
33
+ } else {
34
+ manifest = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
35
+ }
36
+ } catch (e) {
37
+ console.error(' ✗ Invalid manifest JSON:', e.message);
38
+ process.exit(1);
39
+ }
40
+
41
+ const name = manifest.id || manifest.name || path.basename(srcDir);
42
+ const version = manifest.version || '1.0.0';
43
+ const filename = outFile || `${name}.${version}.unicode.codix`;
44
+ const outPath = path.resolve(filename);
45
+
46
+ console.log(`\n Building extension: ${name} v${version}`);
47
+ console.log(` From: ${srcDir}`);
48
+ console.log(` To: ${outPath}`);
49
+
50
+ // Ensure node_modules are installed if package.json has dependencies
51
+ if (fs.existsSync(pkgPath)) {
52
+ const pkgData = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
53
+ const hasDeps = pkgData.dependencies && Object.keys(pkgData.dependencies).length > 0;
54
+ if (hasDeps) {
55
+ console.log(' Installing dependencies...');
56
+ const { execSync } = require('child_process');
57
+ try {
58
+ execSync('npm install --production', { cwd: srcDir, stdio: 'pipe' });
59
+ } catch (e) {
60
+ console.warn(' ⚠ npm install failed (non-fatal):', e.message);
61
+ }
62
+ }
63
+ }
64
+
65
+ // Pack it
66
+ await pack.run([srcDir, outPath]);
67
+
68
+ console.log(` ✓ Build complete: ${filename}`);
69
+ console.log(` Install: unicode --install-extension "${outPath}"`);
70
+ }
71
+
72
+ module.exports = { run };
package/lib/init.js ADDED
@@ -0,0 +1,138 @@
1
+ // lib/init.js — Scaffold a new Unicode extension project
2
+ // Usage: npx unicode init <extension-name>
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const TEMPLATE_FILES = {
8
+ 'extension.json': (name, displayName) => JSON.stringify({
9
+ id: name,
10
+ name: displayName,
11
+ version: '1.0.0',
12
+ author: '',
13
+ description: 'A Unicode CLI extension',
14
+ main: 'main.js',
15
+ engines: { unicode: '>=0.6.0' },
16
+ contributes: {
17
+ hooks: ['on_ai_response', 'on_user_input'],
18
+ commands: [],
19
+ themes: []
20
+ }
21
+ }, null, 2),
22
+
23
+ 'package.json': (name, displayName) => JSON.stringify({
24
+ name: name,
25
+ version: '1.0.0',
26
+ description: 'A Unicode CLI extension',
27
+ main: 'main.js',
28
+ scripts: {
29
+ build: 'npx unicode build',
30
+ test: 'node main.js --test'
31
+ },
32
+ keywords: ['unicode', 'extension', 'codix'],
33
+ engines: { node: '>=14.0.0' }
34
+ }, null, 2),
35
+
36
+ 'main.js': (name) => `#!/usr/bin/env node
37
+
38
+ // Unicode CLI Extension — ${name}
39
+ // Hook protocol: called with --hook <name> --data <json-string>
40
+ // Respond via stdout with modified string (or original to passthrough)
41
+
42
+ const hooks = {
43
+ on_ai_response: (text) => {
44
+ // Modify AI responses here
45
+ return text;
46
+ },
47
+
48
+ on_user_input: (text) => {
49
+ // Modify user input here
50
+ return text;
51
+ },
52
+
53
+ on_command: (data) => {
54
+ // Intercept commands here
55
+ return data;
56
+ }
57
+ };
58
+
59
+ function main() {
60
+ const args = process.argv.slice(2);
61
+ let hook = '';
62
+ let data = '';
63
+
64
+ for (let i = 0; i < args.length; i++) {
65
+ if (args[i] === '--hook' && i + 1 < args.length) hook = args[++i];
66
+ else if (args[i] === '--data' && i + 1 < args.length) data = args[++i];
67
+ }
68
+
69
+ if (hook && hooks[hook]) {
70
+ process.stdout.write(hooks[hook](data));
71
+ } else if (hook) {
72
+ process.stdout.write(data);
73
+ } else {
74
+ const pkg = require('./package.json');
75
+ process.stdout.write(JSON.stringify({
76
+ id: pkg.name,
77
+ name: pkg.name,
78
+ version: pkg.version,
79
+ description: pkg.description,
80
+ hooks: Object.keys(hooks)
81
+ }));
82
+ }
83
+ }
84
+
85
+ main();
86
+ `,
87
+
88
+ '.gitignore': () => `node_modules/
89
+ *.zip
90
+ *.codix
91
+ `,
92
+ };
93
+
94
+ function run(args) {
95
+ const extName = args[0];
96
+ if (!extName) {
97
+ console.log(' Usage: npx unicode init <extension-name>');
98
+ console.log(' Example: npx unicode init my-cool-extension');
99
+ process.exit(1);
100
+ }
101
+
102
+ // Validate name
103
+ if (!/^[a-z0-9][a-z0-9_-]*$/i.test(extName)) {
104
+ console.error(' ✗ Extension name must start with a letter or number and contain only letters, numbers, hyphens, and underscores.');
105
+ process.exit(1);
106
+ }
107
+
108
+ const destDir = path.resolve(extName);
109
+ if (fs.existsSync(destDir)) {
110
+ console.error(` ✗ Directory already exists: ${destDir}`);
111
+ process.exit(1);
112
+ }
113
+
114
+ const displayName = extName
115
+ .replace(/[-_]/g, ' ')
116
+ .replace(/\b\w/g, c => c.toUpperCase());
117
+
118
+ console.log(`\n Creating extension: ${extName}`);
119
+ console.log(` At: ${destDir}`);
120
+
121
+ fs.mkdirSync(destDir, { recursive: true });
122
+
123
+ // Write template files
124
+ for (const [filename, generator] of Object.entries(TEMPLATE_FILES)) {
125
+ const content = generator(extName, displayName);
126
+ fs.writeFileSync(path.join(destDir, filename), content, 'utf-8');
127
+ console.log(` ✓ Created: ${filename}`);
128
+ }
129
+
130
+ console.log(`\n ✓ Extension scaffolded successfully!`);
131
+ console.log(`\n Next steps:`);
132
+ console.log(` cd ${extName}`);
133
+ console.log(` npm install`);
134
+ console.log(` # Edit main.js to add your logic`);
135
+ console.log(` npx unicode build # Package as .codix`);
136
+ }
137
+
138
+ module.exports = { run };
package/lib/pack.js ADDED
@@ -0,0 +1,77 @@
1
+ // lib/pack.js — Pack extension directory into .codix (ZIP archive)
2
+ // Usage: npx unicode pack <source-dir> [output-file]
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const { execSync } = require('child_process');
7
+
8
+ function readJson(filePath) {
9
+ try {
10
+ return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
15
+
16
+ async function run(args) {
17
+ const srcDir = path.resolve(args[0] || process.cwd());
18
+ const outFile = args[1] || '';
19
+
20
+ // Validate source
21
+ if (!fs.existsSync(srcDir)) {
22
+ console.error(` ✗ Source directory not found: ${srcDir}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ // Read manifest
27
+ let manifest = readJson(path.join(srcDir, 'extension.json'));
28
+ if (!manifest) manifest = readJson(path.join(srcDir, 'package.json'));
29
+ if (!manifest) {
30
+ console.error(` ✗ No extension.json or package.json found in ${srcDir}`);
31
+ process.exit(1);
32
+ }
33
+
34
+ const name = manifest.id || manifest.name || 'extension';
35
+ const version = manifest.version || '1.0.0';
36
+ const filename = outFile || `${name}.${version}.unicode.codix`;
37
+ const outPath = path.resolve(filename);
38
+
39
+ console.log(` Packaging: ${name} v${version}`);
40
+ console.log(` From: ${srcDir}`);
41
+ console.log(` To: ${outPath}`);
42
+
43
+ // Create ZIP via PowerShell Compress-Archive, then rename .zip → .codix
44
+ const tmpZip = outPath.replace(/\.codix$/, '.zip');
45
+ const cmd = `powershell -NoProfile -Command "Compress-Archive -Path '${srcDir}\\*' -DestinationPath '${tmpZip}' -Force"`;
46
+
47
+ try {
48
+ execSync(cmd, { stdio: 'pipe', timeout: 30000 });
49
+ } catch (e) {
50
+ console.error(' ✗ Failed to create archive:', e.message);
51
+ process.exit(1);
52
+ }
53
+
54
+ if (!fs.existsSync(tmpZip)) {
55
+ console.error(' ✗ Archive was not created');
56
+ process.exit(1);
57
+ }
58
+
59
+ // Rename .zip → .codix
60
+ try {
61
+ // Remove existing output if any
62
+ if (fs.existsSync(outPath)) fs.unlinkSync(outPath);
63
+ fs.renameSync(tmpZip, outPath);
64
+ } catch (e) {
65
+ console.error(' ✗ Failed to rename archive:', e.message);
66
+ process.exit(1);
67
+ }
68
+
69
+ // Show size
70
+ const size = fs.statSync(outPath).size;
71
+ const sizeStr = size > 1024 * 1024
72
+ ? (size / 1024 / 1024).toFixed(1) + ' MB'
73
+ : (size / 1024).toFixed(1) + ' KB';
74
+ console.log(` ✓ Packed: ${filename} (${sizeStr})`);
75
+ }
76
+
77
+ module.exports = { run };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "unicodemanager",
3
+ "displayName": "UniCode-Manager",
4
+ "version": "0.6.7",
5
+ "description": "Unicode CLI extension packaging and management toolkit — build, scaffold, and publish .codix extensions",
6
+ "author": "Youcef Benabdallah",
7
+ "license": "MIT",
8
+ "main": "index.js",
9
+ "bin": {
10
+ "unicode": "bin/unicode.js",
11
+ "unicodemanager": "bin/unicode.js"
12
+ },
13
+ "keywords": [
14
+ "unicode",
15
+ "cli",
16
+ "extension",
17
+ "codix",
18
+ "plugin",
19
+ "ai",
20
+ "agent"
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/youcefdev/unicode"
25
+ },
26
+ "engines": {
27
+ "node": ">=14.0.0"
28
+ },
29
+ "files": [
30
+ "index.js",
31
+ "bin/",
32
+ "lib/",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "scripts": {
37
+ "build": "node bin/unicode.js build",
38
+ "start": "node bin/unicode.js",
39
+ "pack": "node bin/unicode.js pack",
40
+ "init": "node bin/unicode.js init"
41
+ }
42
+ }