@neuvybe/jarvis 0.2.1 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +23 -227
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,142 +1,22 @@
1
1
  #!/usr/bin/env node
2
-
3
- // src/index.ts
4
- import { readFileSync } from "node:fs";
5
-
6
- // ../../packages/shared/dist/logger.js
7
- var ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
8
- function formatMeta(meta) {
9
- try {
10
- return JSON.stringify(meta, (_key, value) => {
11
- if (value instanceof Error) {
12
- return { name: value.name, message: value.message, stack: value.stack };
13
- }
14
- return value;
15
- });
16
- } catch {
17
- return "[unserializable meta]";
18
- }
19
- }
20
- var Logger = class {
21
- level;
22
- constructor(level = "info") {
23
- this.level = level;
24
- }
25
- setLevel(level) {
26
- this.level = level;
27
- }
28
- getLevel() {
29
- return this.level;
30
- }
31
- debug(message, meta) {
32
- this.emit("debug", message, meta);
33
- }
34
- info(message, meta) {
35
- this.emit("info", message, meta);
36
- }
37
- warn(message, meta) {
38
- this.emit("warn", message, meta);
39
- }
40
- error(message, meta) {
41
- this.emit("error", message, meta);
42
- }
43
- emit(level, message, meta) {
44
- if (ORDER[level] < ORDER[this.level])
45
- return;
46
- const ts = (/* @__PURE__ */ new Date()).toISOString();
47
- const tag = `[${ts}] ${level.toUpperCase()}`;
48
- const line = meta !== void 0 ? `${tag} ${message} ${formatMeta(meta)}` : `${tag} ${message}`;
49
- if (level === "error") {
50
- console.error(line);
51
- } else if (level === "warn") {
52
- console.warn(line);
53
- } else {
54
- console.log(line);
55
- }
56
- }
57
- };
58
- var logger = new Logger();
59
-
60
- // src/upgrade.ts
61
- import { execSync } from "node:child_process";
62
- var PACKAGE_NAME = "@neuvybe/jarvis";
63
- var REGISTRY_TIMEOUT_MS = 3e3;
64
- var SAFE_VERSION = /^[0-9A-Za-z.\-+]+$/;
65
- function isNewer(latest, current) {
66
- const parse = (v) => (v.split("-")[0] ?? "").split(".").map((n) => Number.parseInt(n, 10) || 0);
67
- const a = parse(latest);
68
- const b = parse(current);
69
- for (let i = 0; i < Math.max(a.length, b.length); i++) {
70
- const x = a[i] ?? 0;
71
- const y = b[i] ?? 0;
72
- if (x !== y) return x > y;
73
- }
74
- return false;
75
- }
76
- async function fetchLatestVersion() {
77
- try {
78
- const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
79
- headers: { accept: "application/json" },
80
- signal: AbortSignal.timeout(REGISTRY_TIMEOUT_MS)
81
- });
82
- if (!res.ok) return null;
2
+ import{readFileSync as M}from"node:fs";var v={debug:0,info:1,warn:2,error:3};function k(r){try{return JSON.stringify(r,(e,t)=>t instanceof Error?{name:t.name,message:t.message,stack:t.stack}:t)}catch{return"[unserializable meta]"}}var m=class{level;constructor(e="info"){this.level=e}setLevel(e){this.level=e}getLevel(){return this.level}debug(e,t){this.emit("debug",e,t)}info(e,t){this.emit("info",e,t)}warn(e,t){this.emit("warn",e,t)}error(e,t){this.emit("error",e,t)}emit(e,t,o){if(v[e]<v[this.level])return;let a=`[${new Date().toISOString()}] ${e.toUpperCase()}`,s=o!==void 0?`${a} ${t} ${k(o)}`:`${a} ${t}`;e==="error"?console.error(s):e==="warn"?console.warn(s):console.log(s)}},n=new m;import{execSync as y,spawnSync as S}from"node:child_process";import{existsSync as $}from"node:fs";import{join as j}from"node:path";function u(r,e){let t=a=>(a.split("-")[0]??"").split(".").map(s=>Number.parseInt(s,10)||0),o=t(r),c=t(e);for(let a=0;a<Math.max(o.length,c.length);a++){let s=o[a]??0,i=c[a]??0;if(s!==i)return s>i}return!1}var p=class{constructor(e){this.currentVersion=e}currentVersion;packageName="@neuvybe/jarvis";registryTimeoutMs=3e3;safeVersion=/^[0-9A-Za-z.\-+]+$/;npmCmd(){return process.platform==="win32"?"npm.cmd":"npm"}async fetchLatest(){try{let e=await fetch(`https://registry.npmjs.org/${this.packageName}/latest`,{headers:{accept:"application/json"},signal:AbortSignal.timeout(this.registryTimeoutMs)});if(!e.ok)return null;let t=await e.json();return typeof t.version=="string"?t.version:null}catch{return null}}async status(){n.info(`jarvis ${this.currentVersion}`);let e=await this.fetchLatest();return e===null?n.info("could not check for updates (offline?)"):u(e,this.currentVersion)?n.info(`upgrade available: ${this.currentVersion} -> ${e} (run: jarvis upgrade)`):n.info("up to date"),0}async upgrade(){n.info("checking for updates...");let e=await this.fetchLatest();if(e===null)return n.warn("could not reach the npm registry; try again later"),1;if(!u(e,this.currentVersion))return n.info(`already on the latest version (${this.currentVersion})`),0;if(!this.safeVersion.test(e))return n.error(`refusing to install unexpected version string: ${e}`),1;n.info(`upgrading ${this.currentVersion} -> ${e}...`),await this.stopCore();let t=`${this.npmCmd()} install -g ${this.packageName}@${e}`;try{y(t,{stdio:"inherit"})}catch{return n.error(`upgrade failed; run manually: ${this.npmCmd()} install -g ${this.packageName}@latest`),1}let o=this.resolveFreshEntrypoint();return o===null?(n.info(`upgraded to ${e}. run "jarvis --version" to confirm.`),0):(n.info("verifying the freshly installed jarvis..."),S(process.execPath,[o,"--version"],{stdio:"inherit"}).status!==0?(n.warn('upgrade installed but the fresh entrypoint exited abnormally; run "jarvis --version" to confirm'),0):(n.info(`upgraded to ${e}.`),0))}async stopCore(){return n.debug("stop-core hook: no daemon in v0.1; nothing to stop (proposal 0013 fills this in)"),Promise.resolve()}resolveFreshEntrypoint(){try{let e=y(`${this.npmCmd()} root -g`,{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();if(!e)return null;let t=j(e,this.packageName,"dist","index.js");return $(t)?t:null}catch{return null}}};import{spawn as N}from"node:child_process";import{existsSync as A,readFileSync as O,writeFileSync as P}from"node:fs";import{mkdirSync as x}from"node:fs";import{homedir as C}from"node:os";import{join as w,resolve as V}from"node:path";var g=class{envOverride="JARVIS_HOME";dirName=".jarvis";dir(){let e=process.env[this.envOverride]?.trim();return e?V(e):w(C(),this.dirName)}resolve(...e){return w(this.dir(),...e)}ensureDir(){let e=this.dir();return x(e,{recursive:!0,mode:448}),e}},b=new g;var d=class{constructor(e,t=b){this.currentVersion=e;this.home=t}currentVersion;home;packageName="@neuvybe/jarvis";cacheFile="update-check.json";ttlMs=360*60*1e3;cachePath(){return this.home.resolve(this.cacheFile)}read(){let e=this.cachePath();if(!A(e))return null;try{let t=JSON.parse(O(e,"utf8"));return typeof t.lastCheckedAt=="number"&&typeof t.latestVersion=="string"?{lastCheckedAt:t.lastCheckedAt,latestVersion:t.latestVersion}:null}catch{return null}}write(e,t){let o={lastCheckedAt:t,latestVersion:e};try{this.home.ensureDir(),P(this.cachePath(),JSON.stringify(o))}catch{}}isStale(e){let t=this.read();return!t||e-t.lastCheckedAt>this.ttlMs}notice(){let e=this.read();return!e||!u(e.latestVersion,this.currentVersion)?null:L(`upgrade available: ${this.currentVersion} -> ${e.latestVersion} (run: jarvis upgrade)`)}refreshInBackground(){try{let e=this.cachePath();this.home.ensureDir();let t=`
3
+ import { writeFileSync } from 'node:fs';
4
+ try {
5
+ const res = await fetch('https://registry.npmjs.org/${this.packageName}/latest', {
6
+ headers: { accept: 'application/json' },
7
+ signal: AbortSignal.timeout(5000),
8
+ });
9
+ if (res.ok) {
83
10
  const data = await res.json();
84
- return typeof data.version === "string" ? data.version : null;
85
- } catch {
86
- return null;
87
- }
88
- }
89
- async function runStatus(currentVersion) {
90
- logger.info(`jarvis ${currentVersion}`);
91
- const latest = await fetchLatestVersion();
92
- if (latest === null) {
93
- logger.info("could not check for updates (offline?)");
94
- } else if (isNewer(latest, currentVersion)) {
95
- logger.info(`update available: ${currentVersion} -> ${latest} (run: jarvis upgrade)`);
96
- } else {
97
- logger.info("up to date");
98
- }
99
- return 0;
100
- }
101
- async function runUpgrade(currentVersion) {
102
- logger.info("checking for updates...");
103
- const latest = await fetchLatestVersion();
104
- if (latest === null) {
105
- logger.warn("could not reach the npm registry; try again later");
106
- return 1;
107
- }
108
- if (!isNewer(latest, currentVersion)) {
109
- logger.info(`already on the latest version (${currentVersion})`);
110
- return 0;
111
- }
112
- if (!SAFE_VERSION.test(latest)) {
113
- logger.error(`refusing to install unexpected version string: ${latest}`);
114
- return 1;
115
- }
116
- logger.info(`upgrading ${currentVersion} -> ${latest}...`);
117
- try {
118
- execSync(`npm install -g ${PACKAGE_NAME}@${latest}`, { stdio: "inherit" });
119
- } catch {
120
- logger.error(`upgrade failed; run manually: npm install -g ${PACKAGE_NAME}@latest`);
121
- return 1;
11
+ if (typeof data.version === 'string') {
12
+ writeFileSync(${JSON.stringify(e)}, JSON.stringify({
13
+ lastCheckedAt: Date.now(),
14
+ latestVersion: data.version,
15
+ }));
16
+ }
122
17
  }
123
- logger.info(`upgraded to ${latest}. run "jarvis --version" to confirm.`);
124
- return 0;
125
- }
126
-
127
- // src/index.ts
128
- var COMMANDS = [
129
- "init",
130
- "start",
131
- "stop",
132
- "restart",
133
- "status",
134
- "doctor",
135
- "devices",
136
- "upgrade",
137
- "config"
138
- ];
139
- var USAGE = `jarvis - voice-first personal agent
18
+ } catch {}
19
+ `;N(process.execPath,["--input-type=module","-e",t],{detached:!0,stdio:"ignore"}).unref()}catch{n.debug("background update check skipped (could not refresh cache)")}}};function L(r){return process.stdout.isTTY?`\x1B[2m${r}\x1B[0m`:r}var F=["init","start","stop","restart","status","doctor","devices","upgrade","config"],f=`jarvis - voice-first personal agent
140
20
 
141
21
  Usage:
142
22
  jarvis [options] Start a Jarvis session (primary activation)
@@ -159,97 +39,13 @@ Options:
159
39
  --text, --no-voice Force text-only operation
160
40
  -h, --help Print usage
161
41
  -v, --version Print version
162
- `;
163
- function readVersion() {
164
- try {
165
- const raw = readFileSync(new URL("../package.json", import.meta.url), "utf8");
166
- const parsed = JSON.parse(raw);
167
- return typeof parsed.version === "string" ? parsed.version : "0.0.0";
168
- } catch {
169
- return "0.0.0";
170
- }
171
- }
172
- function isLogLevel(value) {
173
- return value === "debug" || value === "info" || value === "warn" || value === "error";
174
- }
175
- var STUB_MESSAGES = {
176
- init: "initializing...",
177
- start: "starting...",
178
- stop: "stopping...",
179
- restart: "restarting...",
180
- doctor: "running diagnostics...",
181
- devices: "listing devices...",
182
- config: "config: not implemented yet"
183
- };
184
- async function run(argv) {
185
- let command;
186
- let project;
187
- let textOnly = false;
188
- let wantHelp = false;
189
- let wantVersion = false;
190
- for (let i = 0; i < argv.length; i++) {
191
- const arg = argv[i];
192
- if (arg === "-h" || arg === "--help") {
193
- wantHelp = true;
194
- } else if (arg === "-v" || arg === "--version") {
195
- wantVersion = true;
196
- } else if (arg === "--text" || arg === "--no-voice") {
197
- textOnly = true;
198
- } else if (arg === "--log-level") {
199
- const value = argv[++i];
200
- if (value === void 0 || !isLogLevel(value)) {
201
- process.stderr.write("error: --log-level expects one of debug|info|warn|error\n");
202
- return 1;
203
- }
204
- logger.setLevel(value);
205
- } else if (arg === "--project") {
206
- const value = argv[++i];
207
- if (value === void 0) {
208
- process.stderr.write("error: --project expects a path\n");
209
- return 1;
210
- }
211
- project = value;
212
- } else if (arg.startsWith("-")) {
213
- process.stderr.write(`error: unknown option '${arg}'
42
+ `;function h(){try{let r=M(new URL("../package.json",import.meta.url),"utf8"),e=JSON.parse(r);return typeof e.version=="string"?e.version:"0.0.0"}catch{return"0.0.0"}}function E(r){return r==="debug"||r==="info"||r==="warn"||r==="error"}var D={init:"initializing...",start:"starting...",stop:"stopping...",restart:"restarting...",doctor:"running diagnostics...",devices:"listing devices...",config:"config: not implemented yet"};async function J(r){let e,t,o=!1,c=!1,a=!1;for(let s=0;s<r.length;s++){let i=r[s];if(i==="-h"||i==="--help")c=!0;else if(i==="-v"||i==="--version")a=!0;else if(i==="--text"||i==="--no-voice")o=!0;else if(i==="--log-level"){let l=r[++s];if(l===void 0||!E(l))return process.stderr.write(`error: --log-level expects one of debug|info|warn|error
43
+ `),1;n.setLevel(l)}else if(i==="--project"){let l=r[++s];if(l===void 0)return process.stderr.write(`error: --project expects a path
44
+ `),1;t=l}else{if(i.startsWith("-"))return process.stderr.write(`error: unknown option '${i}'
214
45
 
215
- ${USAGE}`);
216
- return 1;
217
- } else if (command === void 0) {
218
- command = arg;
219
- } else {
220
- process.stderr.write(`error: unexpected argument '${arg}'
46
+ ${f}`),1;if(e===void 0)e=i;else return process.stderr.write(`error: unexpected argument '${i}'
221
47
 
222
- ${USAGE}`);
223
- return 1;
224
- }
225
- }
226
- if (wantVersion) {
227
- process.stdout.write(`${readVersion()}
228
- `);
229
- return 0;
230
- }
231
- if (wantHelp) {
232
- process.stdout.write(USAGE);
233
- return 0;
234
- }
235
- if (command === void 0) {
236
- logger.info("activating...", { project: project ?? process.cwd(), textOnly });
237
- return 0;
238
- }
239
- if (!COMMANDS.includes(command)) {
240
- process.stderr.write(`error: unknown command '${command}'
48
+ ${f}`),1}}if(a)return process.stdout.write(`${h()}
49
+ `),0;if(c)return process.stdout.write(f),0;if(e===void 0){let s=new d(h()),i=s.notice();return i!==null&&n.info(i),s.isStale(Date.now())&&s.refreshInBackground(),n.info("activating...",{project:t??process.cwd(),textOnly:o}),0}return F.includes(e)?e==="status"?new p(h()).status():e==="upgrade"?new p(h()).upgrade():(n.info(D[e]),0):(process.stderr.write(`error: unknown command '${e}'
241
50
 
242
- ${USAGE}`);
243
- return 1;
244
- }
245
- if (command === "status") return runStatus(readVersion());
246
- if (command === "upgrade") return runUpgrade(readVersion());
247
- logger.info(STUB_MESSAGES[command]);
248
- return 0;
249
- }
250
- try {
251
- process.exitCode = await run(process.argv.slice(2));
252
- } catch (error) {
253
- logger.error("jarvis failed", { error });
254
- process.exitCode = 1;
255
- }
51
+ ${f}`),1)}try{process.exitCode=await J(process.argv.slice(2))}catch(r){n.error("jarvis failed",{error:r}),process.exitCode=1}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuvybe/jarvis",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Jarvis - a voice-first personal agent (CLI).",
@@ -28,7 +28,7 @@
28
28
  "dev": "tsx --conditions=development --env-file-if-exists=../../.env watch src/index.ts",
29
29
  "start": "tsx --conditions=development --env-file-if-exists=../../.env src/index.ts",
30
30
  "build": "tsc -b",
31
- "bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js",
31
+ "bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --minify --legal-comments=none --outfile=dist/index.js",
32
32
  "clean": "tsc -b --clean"
33
33
  }
34
34
  }