@neuvybe/jarvis 0.1.1 → 0.3.0

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 +25 -157
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,75 +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);
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'),1):(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) {
10
+ const data = await res.json();
11
+ if (typeof data.version === 'string') {
12
+ writeFileSync(${JSON.stringify(e)}, JSON.stringify({
13
+ lastCheckedAt: Date.now(),
14
+ latestVersion: data.version,
15
+ }));
55
16
  }
56
17
  }
57
- };
58
- var logger = new Logger();
59
-
60
- // src/index.ts
61
- var COMMANDS = [
62
- "init",
63
- "start",
64
- "stop",
65
- "restart",
66
- "status",
67
- "doctor",
68
- "devices",
69
- "upgrade",
70
- "config"
71
- ];
72
- 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
73
20
 
74
21
  Usage:
75
22
  jarvis [options] Start a Jarvis session (primary activation)
@@ -80,10 +27,10 @@ Commands:
80
27
  start Start the local core service
81
28
  stop Stop the local core service
82
29
  restart Restart the local core service
83
- status Show service/core/config status
30
+ status Show version and check for updates
84
31
  doctor Run diagnostics
85
32
  devices List audio devices
86
- upgrade Upgrade the installed CLI/core
33
+ upgrade Upgrade the installed CLI to the latest published version
87
34
  config Inspect/edit configuration
88
35
 
89
36
  Options:
@@ -92,92 +39,13 @@ Options:
92
39
  --text, --no-voice Force text-only operation
93
40
  -h, --help Print usage
94
41
  -v, --version Print version
95
- `;
96
- function readVersion() {
97
- try {
98
- const raw = readFileSync(new URL("../package.json", import.meta.url), "utf8");
99
- const parsed = JSON.parse(raw);
100
- return typeof parsed.version === "string" ? parsed.version : "0.0.0";
101
- } catch {
102
- return "0.0.0";
103
- }
104
- }
105
- function isLogLevel(value) {
106
- return value === "debug" || value === "info" || value === "warn" || value === "error";
107
- }
108
- var STUB_MESSAGES = {
109
- init: "initializing...",
110
- start: "starting...",
111
- stop: "stopping...",
112
- restart: "restarting...",
113
- status: "status: not implemented yet",
114
- doctor: "running diagnostics...",
115
- devices: "listing devices...",
116
- upgrade: "checking for upgrades...",
117
- config: "config: not implemented yet"
118
- };
119
- function run(argv) {
120
- let command;
121
- let project;
122
- let textOnly = false;
123
- let wantHelp = false;
124
- let wantVersion = false;
125
- for (let i = 0; i < argv.length; i++) {
126
- const arg = argv[i];
127
- if (arg === "-h" || arg === "--help") {
128
- wantHelp = true;
129
- } else if (arg === "-v" || arg === "--version") {
130
- wantVersion = true;
131
- } else if (arg === "--text" || arg === "--no-voice") {
132
- textOnly = true;
133
- } else if (arg === "--log-level") {
134
- const value = argv[++i];
135
- if (value === void 0 || !isLogLevel(value)) {
136
- process.stderr.write("error: --log-level expects one of debug|info|warn|error\n");
137
- return 1;
138
- }
139
- logger.setLevel(value);
140
- } else if (arg === "--project") {
141
- const value = argv[++i];
142
- if (value === void 0) {
143
- process.stderr.write("error: --project expects a path\n");
144
- return 1;
145
- }
146
- project = value;
147
- } else if (arg.startsWith("-")) {
148
- 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}'
149
45
 
150
- ${USAGE}`);
151
- return 1;
152
- } else if (command === void 0) {
153
- command = arg;
154
- } else {
155
- 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}'
156
47
 
157
- ${USAGE}`);
158
- return 1;
159
- }
160
- }
161
- if (wantVersion) {
162
- process.stdout.write(`${readVersion()}
163
- `);
164
- return 0;
165
- }
166
- if (wantHelp) {
167
- process.stdout.write(USAGE);
168
- return 0;
169
- }
170
- if (command === void 0) {
171
- logger.info("activating...", { project: project ?? process.cwd(), textOnly });
172
- return 0;
173
- }
174
- if (!COMMANDS.includes(command)) {
175
- 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}'
176
50
 
177
- ${USAGE}`);
178
- return 1;
179
- }
180
- logger.info(STUB_MESSAGES[command]);
181
- return 0;
182
- }
183
- process.exitCode = run(process.argv.slice(2));
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.1.1",
3
+ "version": "0.3.0",
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
  }