@shreyassp002/pinionos-emulator 0.2.0 → 0.2.1

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- <img src="assets/logo.jpg" alt="PinionOS Emulator Logo" width="220" />
3
+ <img src="https://github.com/Shreyassp002/pinionos-emulator/blob/main/assets/logo.jpg" alt="PinionOS Emulator Logo" width="220" />
4
4
 
5
5
  # PinionOS Emulator
6
6
 
@@ -79,9 +79,16 @@ Your emulator MCP server currently exposes:
79
79
 
80
80
  ## Quick Start
81
81
 
82
+ Install in your project:
83
+
84
+ ```bash
85
+ npm install @shreyassp002/pinionos-emulator
86
+ ```
87
+
88
+ Start emulator (local install):
89
+
82
90
  ```bash
83
- npm install
84
- npm start
91
+ npx pinionos-emulator
85
92
  ```
86
93
 
87
94
  Health check:
@@ -96,14 +103,33 @@ Headless mode:
96
103
  npx pinionos-emulator --no-dashboard
97
104
  ```
98
105
 
106
+ Optional global install:
107
+
108
+ ```bash
109
+ npm install -g @shreyassp002/pinionos-emulator
110
+ pinionos-emulator
111
+ ```
112
+
99
113
  ## CLI Commands
100
114
 
115
+ Local install (recommended):
116
+
117
+ ```bash
118
+ npx pinionos-emulator start
119
+ npx pinionos-emulator mcp
120
+ npx pinionos-emulator init
121
+ ```
122
+
123
+ Global install:
124
+
101
125
  ```bash
102
126
  pinionos-emulator start
103
127
  pinionos-emulator mcp
104
128
  pinionos-emulator init
105
129
  ```
106
130
 
131
+ `start` is the default command, so `npx pinionos-emulator` and `pinionos-emulator` are equivalent to `... start`.
132
+
107
133
  Useful options:
108
134
  - `--port <n>`
109
135
  - `--x402`
@@ -174,12 +174,13 @@ function buildDashboard(port) {
174
174
  // eslint-disable-next-line @typescript-eslint/no-var-requires
175
175
  const contrib = require('blessed-contrib');
176
176
  const screen = blessed.screen({ smartCSR: true, title: 'PinionOS Emulator', fullUnicode: true });
177
- const grid = new contrib.grid({ rows: 24, cols: 12, screen });
177
+ const grid = new contrib.grid({ rows: 24, cols: 12, screen, hideBorder: true });
178
178
  const header = asContentWidget(grid.set(0, 0, 8, 12, blessed.box, {
179
179
  tags: true,
180
- border: { type: 'line' },
181
- style: { border: { fg: 'cyan' } },
182
- label: ' {bold}PINION OS EMULATOR{/bold} '
180
+ align: 'center',
181
+ valign: 'middle',
182
+ wrap: false,
183
+ style: { fg: 'cyan' }
183
184
  }));
184
185
  const prices = asContentWidget(grid.set(8, 0, 5, 5, blessed.box, {
185
186
  border: { type: 'line' },
@@ -3,51 +3,61 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildHeaderText = buildHeaderText;
4
4
  exports.printHeader = printHeader;
5
5
  const colors_1 = require("../colors");
6
- function line(width) {
7
- return '═'.repeat(Math.max(0, width));
6
+ const version_1 = require("../../version");
7
+ function terminalWidth() {
8
+ return process.stdout.columns ?? 100;
8
9
  }
9
- function boxWrap(contentLines, width = 78) {
10
- const top = `╔${line(width)}╗`;
11
- const bottom = `╚${line(width)}╝`;
12
- const lines = contentLines.map((lineText) => {
13
- const clean = lineText.slice(0, width);
14
- return `║${clean.padEnd(width, ' ')}║`;
15
- });
16
- return [top, ...lines, bottom].join('\n');
17
- }
18
- function figletBanner() {
10
+ function figletBanner(columns) {
19
11
  try {
20
12
  // eslint-disable-next-line @typescript-eslint/no-var-requires
21
13
  const figlet = require('figlet');
22
- return figlet.textSync('PINION OS', { font: 'ANSI Shadow' });
14
+ const font = columns >= 118 ? 'ANSI Shadow' : 'Small';
15
+ return figlet.textSync('PINION OS', { font }).split('\n').filter((line) => line.trim().length > 0);
23
16
  }
24
17
  catch {
18
+ if (columns >= 118) {
19
+ return [
20
+ '██████╗ ██╗███╗ ██╗██╗ ██████╗ ███╗ ██╗ ██████╗ ███████╗',
21
+ '██╔══██╗██║████╗ ██║██║██╔═══██╗████╗ ██║██╔═══██╗██╔════╝',
22
+ '██████╔╝██║██╔██╗ ██║██║██║ ██║██╔██╗ ██║██║ ██║███████╗',
23
+ '██╔═══╝ ██║██║╚██╗██║██║██║ ██║██║╚██╗██║██║ ██║╚════██║',
24
+ '██║ ██║██║ ╚████║██║╚██████╔╝██║ ╚████║╚██████╔╝███████║',
25
+ '╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝'
26
+ ];
27
+ }
25
28
  return [
26
- '██████╗ ██╗███╗ ██╗██╗ ██████╗ ███╗ ██╗ ██████╗ ███████╗',
27
- '██╔══██╗██║████╗ ██║██║██╔═══██╗████╗ ██║██╔═══██╗██╔════╝',
28
- '██████╔╝██║██╔██╗ ██║██║██║ ██║██╔██╗ ██║██║ ██║███████╗',
29
- '██╔═══╝ ██║██║╚██╗██║██║██║ ██║██║╚██╗██║██║ ██║╚════██║',
30
- '██║ ██║██║ ╚████║██║╚██████╔╝██║ ╚████║╚██████╔╝███████║',
31
- '╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝ ╚══════╝'
32
- ].join('\n');
29
+ ' ___ ___ _ _ ___ ___ _ _ ___ ___ ',
30
+ ' | _ \\_ _| \\| |_ _/ _ \\| \\| | / _ \\/ __|',
31
+ ' | _/| || .` || | (_) | .` | | (_) \\__ \\',
32
+ ' |_| |___|_|\\_|___\\___/|_|\\_| \\___/|___/'
33
+ ];
33
34
  }
34
35
  }
36
+ function fit(text, maxLen = 68) {
37
+ if (text.length <= maxLen)
38
+ return text;
39
+ if (maxLen <= 3)
40
+ return '.'.repeat(maxLen);
41
+ return `${text.slice(0, maxLen - 3)}...`;
42
+ }
35
43
  function buildHeaderText(port, totalCalls = 0, errorCount = 0, uptimeStr = '00:00:00', x402Payments = 0, opts) {
36
- const bannerLines = figletBanner().split('\n').filter(Boolean);
44
+ const cols = terminalWidth();
45
+ const maxLen = Math.max(42, Math.min(104, cols - 12));
46
+ const bannerLines = figletBanner(cols);
47
+ const version = (0, version_1.getAppVersion)();
37
48
  const networkName = opts?.network ?? 'base';
38
49
  const chainId = opts?.chainId ?? 8453;
39
- const subtitle1 = `E M U L A T O R v1.0.0 · http://localhost:${port}`;
50
+ const subtitle1 = fit(`E M U L A T O R v${version} | http://localhost:${port}`, maxLen);
40
51
  const features = [];
41
52
  if (opts?.x402Mode)
42
53
  features.push('x402: ON');
43
54
  if (opts?.recording)
44
55
  features.push('REC');
45
- const featureTag = features.length > 0 ? ` · ${features.join(' · ')}` : '';
46
- const subtitle2 = `Zero-cost local simulator for PinionOS skills & agents · Network: ${networkName} (${chainId})${featureTag}`;
47
- const x402Tag = x402Payments > 0 ? ` x402: ${x402Payments}` : '';
48
- const subtitle3 = `Calls: ${totalCalls} Errors: ${errorCount}${x402Tag} Uptime: ${uptimeStr} Press q to quit`;
49
- const all = ['', ...bannerLines, '', subtitle1, subtitle2, subtitle3, ''];
50
- return `${colors_1.COLORS.cyan}${boxWrap(all)}${colors_1.COLORS.reset}`;
56
+ const featureTag = features.length > 0 ? ` | ${features.join(' | ')}` : '';
57
+ const subtitle2 = fit(`Zero-cost local simulator for PinionOS skills & agents | Network: ${networkName} (${chainId})${featureTag}`, maxLen);
58
+ const x402Tag = x402Payments > 0 ? ` | x402:${x402Payments}` : '';
59
+ const subtitle3 = fit(`Calls: ${totalCalls} | Errors: ${errorCount}${x402Tag} | Uptime: ${uptimeStr} | Press q to quit`, maxLen);
60
+ return `${colors_1.COLORS.cyan}${[...bannerLines, '', subtitle1, subtitle2, subtitle3].join('\n')}${colors_1.COLORS.reset}`;
51
61
  }
52
62
  function printHeader(port = 4020) {
53
63
  process.stdout.write('\x1Bc');
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getAppVersion = getAppVersion;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ let cachedVersion = null;
10
+ function normalizeVersion(value) {
11
+ if (typeof value !== 'string')
12
+ return null;
13
+ const trimmed = value.trim();
14
+ return trimmed.length > 0 ? trimmed : null;
15
+ }
16
+ function findNearestPackageJson(startDir) {
17
+ let dir = node_path_1.default.resolve(startDir);
18
+ while (true) {
19
+ const candidate = node_path_1.default.join(dir, 'package.json');
20
+ if (node_fs_1.default.existsSync(candidate))
21
+ return candidate;
22
+ const parent = node_path_1.default.dirname(dir);
23
+ if (parent === dir)
24
+ return null;
25
+ dir = parent;
26
+ }
27
+ }
28
+ function getAppVersion() {
29
+ if (cachedVersion)
30
+ return cachedVersion;
31
+ const fromEnv = normalizeVersion(process.env.npm_package_version);
32
+ if (fromEnv) {
33
+ cachedVersion = fromEnv;
34
+ return cachedVersion;
35
+ }
36
+ try {
37
+ const packagePath = findNearestPackageJson(__dirname);
38
+ if (packagePath) {
39
+ const raw = node_fs_1.default.readFileSync(packagePath, 'utf8');
40
+ const parsed = JSON.parse(raw);
41
+ const fromPkg = normalizeVersion(parsed.version);
42
+ if (fromPkg) {
43
+ cachedVersion = fromPkg;
44
+ return cachedVersion;
45
+ }
46
+ }
47
+ }
48
+ catch {
49
+ // fallback below
50
+ }
51
+ cachedVersion = '0.0.0';
52
+ return cachedVersion;
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shreyassp002/pinionos-emulator",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Local PinionOS emulator for free agent development",
5
5
  "main": "dist/src/emulator.js",
6
6
  "bin": {