@shreyassp002/pinionos-emulator 0.1.2 → 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,5 +1,7 @@
1
1
  <div align="center">
2
2
 
3
+ <img src="https://github.com/Shreyassp002/pinionos-emulator/blob/main/assets/logo.jpg" alt="PinionOS Emulator Logo" width="220" />
4
+
3
5
  # PinionOS Emulator
4
6
 
5
7
  **Local PinionOS-compatible backend for product development and testing**
@@ -77,9 +79,16 @@ Your emulator MCP server currently exposes:
77
79
 
78
80
  ## Quick Start
79
81
 
82
+ Install in your project:
83
+
84
+ ```bash
85
+ npm install @shreyassp002/pinionos-emulator
86
+ ```
87
+
88
+ Start emulator (local install):
89
+
80
90
  ```bash
81
- npm install
82
- npm start
91
+ npx pinionos-emulator
83
92
  ```
84
93
 
85
94
  Health check:
@@ -94,14 +103,33 @@ Headless mode:
94
103
  npx pinionos-emulator --no-dashboard
95
104
  ```
96
105
 
106
+ Optional global install:
107
+
108
+ ```bash
109
+ npm install -g @shreyassp002/pinionos-emulator
110
+ pinionos-emulator
111
+ ```
112
+
97
113
  ## CLI Commands
98
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
+
99
125
  ```bash
100
126
  pinionos-emulator start
101
127
  pinionos-emulator mcp
102
128
  pinionos-emulator init
103
129
  ```
104
130
 
131
+ `start` is the default command, so `npx pinionos-emulator` and `pinionos-emulator` are equivalent to `... start`.
132
+
105
133
  Useful options:
106
134
  - `--port <n>`
107
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.1.2",
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": {