@geravant/sinain 1.6.2 → 1.6.4

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/launcher.js CHANGED
@@ -129,7 +129,7 @@ async function main() {
129
129
  try {
130
130
  const depCheck = IS_WINDOWS
131
131
  ? 'python3 -c "import PIL; import skimage"'
132
- : 'python3 -c "import PIL; import skimage; import Quartz"';
132
+ : 'python3 -c "import PIL; import skimage; import Quartz; import Vision"';
133
133
  execSync(depCheck, { stdio: "pipe" });
134
134
  } catch {
135
135
  log("Installing sense_client Python dependencies...");
@@ -216,7 +216,41 @@ async function main() {
216
216
  warn("flutter not found — overlay source found but can't build");
217
217
  }
218
218
  } else {
219
- warn("overlay not found — run: sinain setup-overlay");
219
+ // Auto-download overlay if not found
220
+ log("overlay not found — downloading from GitHub Releases...");
221
+ try {
222
+ const { downloadOverlay } = await import("./setup-overlay.js");
223
+ const success = await downloadOverlay({ silent: false });
224
+ if (success) {
225
+ // Re-find and launch the freshly downloaded overlay
226
+ const freshOverlay = findOverlay();
227
+ if (freshOverlay?.type === "prebuilt") {
228
+ if (!IS_WINDOWS) {
229
+ try {
230
+ execSync(`xattr -cr "${freshOverlay.path}"`, { stdio: "pipe" });
231
+ } catch { /* no quarantine */ }
232
+ }
233
+ log("Starting overlay (pre-built)...");
234
+ const binary = IS_WINDOWS
235
+ ? freshOverlay.path
236
+ : path.join(freshOverlay.path, "Contents/MacOS/sinain_hud");
237
+ startProcess("overlay", binary, [], { color: MAGENTA });
238
+ await sleep(2000);
239
+ const overlayChild = children.find(c => c.name === "overlay");
240
+ if (overlayChild && !overlayChild.proc.killed && overlayChild.proc.exitCode === null) {
241
+ ok(`overlay running (pid:${overlayChild.pid})`);
242
+ overlayStatus = "running";
243
+ } else {
244
+ warn("overlay exited early — check logs above");
245
+ overlayStatus = "failed";
246
+ }
247
+ }
248
+ } else {
249
+ warn("overlay auto-download failed — run: sinain setup-overlay");
250
+ }
251
+ } catch (e) {
252
+ warn(`overlay auto-download failed: ${e.message}`);
253
+ }
220
254
  }
221
255
  }
222
256
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geravant/sinain",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "Ambient AI overlay invisible to screen capture — real-time insights from audio + screen context",
5
5
  "type": "module",
6
6
  "bin": {
@@ -4,6 +4,7 @@ numpy>=1.24
4
4
  pytesseract>=0.3
5
5
  requests>=2.31
6
6
  pyobjc-framework-Quartz>=10.0; sys_platform == "darwin"
7
+ pyobjc-framework-Vision>=10.0; sys_platform == "darwin"
7
8
  mss>=9.0; sys_platform == "win32"
8
9
  psutil>=5.9; sys_platform == "win32"
9
10
  winrt-Windows.Media.Ocr>=2.0; sys_platform == "win32"
package/setup-overlay.js CHANGED
@@ -37,25 +37,36 @@ function ok(msg) { console.log(`${BOLD}[setup-overlay]${RESET} ${GREEN}✓${RE
37
37
  function warn(msg) { console.log(`${BOLD}[setup-overlay]${RESET} ${YELLOW}⚠${RESET} ${msg}`); }
38
38
  function fail(msg) { console.error(`${BOLD}[setup-overlay]${RESET} ${RED}✗${RESET} ${msg}`); process.exit(1); }
39
39
 
40
- // ── Parse flags ──────────────────────────────────────────────────────────────
40
+ // ── Entry point (only when run directly, not when imported) ──────────────────
41
41
 
42
- const args = process.argv.slice(2);
43
- const fromSource = args.includes("--from-source");
44
- const forceUpdate = args.includes("--update");
42
+ const isMain = process.argv[1] && (
43
+ import.meta.url === `file://${process.argv[1]}` ||
44
+ import.meta.url === new URL(process.argv[1], "file://").href
45
+ );
45
46
 
46
- if (fromSource) {
47
- await buildFromSource();
48
- } else {
49
- await downloadPrebuilt();
47
+ if (isMain) {
48
+ const args = process.argv.slice(2);
49
+ const fromSource = args.includes("--from-source");
50
+ const forceUpdate = args.includes("--update");
51
+
52
+ if (fromSource) {
53
+ await buildFromSource();
54
+ } else {
55
+ await downloadOverlay({ forceUpdate });
56
+ }
50
57
  }
51
58
 
52
59
  // ── Download pre-built .app ──────────────────────────────────────────────────
53
60
 
54
- async function downloadPrebuilt() {
61
+ export async function downloadOverlay({ silent = false, forceUpdate = false } = {}) {
62
+ const _log = silent ? () => {} : log;
63
+ const _ok = silent ? () => {} : ok;
64
+ const _warn = silent ? () => {} : warn;
65
+
55
66
  fs.mkdirSync(APP_DIR, { recursive: true });
56
67
 
57
68
  // Find latest overlay release
58
- log("Checking for latest overlay release...");
69
+ _log("Checking for latest overlay release...");
59
70
  let release;
60
71
  try {
61
72
  const res = await fetch(`${RELEASES_API}?per_page=20`, {
@@ -67,6 +78,7 @@ async function downloadPrebuilt() {
67
78
  release = releases.find(r => r.tag_name?.startsWith("overlay-v"));
68
79
  if (!release) throw new Error("No overlay release found");
69
80
  } catch (e) {
81
+ if (silent) return false;
70
82
  fail(`Failed to fetch releases: ${e.message}\n Try: sinain setup-overlay --from-source`);
71
83
  }
72
84
 
@@ -78,21 +90,22 @@ async function downloadPrebuilt() {
78
90
  try {
79
91
  const local = JSON.parse(fs.readFileSync(VERSION_FILE, "utf-8"));
80
92
  if (local.tag === tag) {
81
- ok(`Overlay already up-to-date (${version})`);
82
- return;
93
+ _ok(`Overlay already up-to-date (${version})`);
94
+ return true;
83
95
  }
84
- log(`Updating: ${local.tag} → ${tag}`);
96
+ _log(`Updating: ${local.tag} → ${tag}`);
85
97
  } catch { /* corrupt version file — re-download */ }
86
98
  }
87
99
 
88
100
  // Find the .zip asset for this platform
89
101
  const zipAsset = release.assets?.find(a => a.name === ASSET_NAME);
90
102
  if (!zipAsset) {
103
+ if (silent) return false;
91
104
  fail(`Release ${tag} has no ${ASSET_NAME} asset.\n Try: sinain setup-overlay --from-source`);
92
105
  }
93
106
 
94
107
  // Download with progress
95
- log(`Downloading overlay ${version} for ${IS_WINDOWS ? "Windows" : "macOS"} (${formatBytes(zipAsset.size)})...`);
108
+ _log(`Downloading overlay ${version} for ${IS_WINDOWS ? "Windows" : "macOS"} (${formatBytes(zipAsset.size)})...`);
96
109
  const zipPath = path.join(APP_DIR, ASSET_NAME);
97
110
 
98
111
  try {
@@ -112,17 +125,18 @@ async function downloadPrebuilt() {
112
125
  if (done) break;
113
126
  chunks.push(value);
114
127
  downloaded += value.length;
115
- if (total > 0) {
128
+ if (total > 0 && !silent) {
116
129
  const pct = Math.round((downloaded / total) * 100);
117
130
  process.stdout.write(`\r${BOLD}[setup-overlay]${RESET} ${DIM}${pct}% (${formatBytes(downloaded)} / ${formatBytes(total)})${RESET}`);
118
131
  }
119
132
  }
120
- process.stdout.write("\n");
133
+ if (!silent) process.stdout.write("\n");
121
134
 
122
135
  const buffer = Buffer.concat(chunks);
123
136
  fs.writeFileSync(zipPath, buffer);
124
- ok(`Downloaded ${formatBytes(buffer.length)}`);
137
+ _ok(`Downloaded ${formatBytes(buffer.length)}`);
125
138
  } catch (e) {
139
+ if (silent) return false;
126
140
  fail(`Download failed: ${e.message}`);
127
141
  }
128
142
 
@@ -132,7 +146,7 @@ async function downloadPrebuilt() {
132
146
  }
133
147
 
134
148
  // Extract
135
- log("Extracting...");
149
+ _log("Extracting...");
136
150
  if (IS_WINDOWS) {
137
151
  try {
138
152
  execSync(
@@ -140,6 +154,7 @@ async function downloadPrebuilt() {
140
154
  { stdio: "pipe" }
141
155
  );
142
156
  } catch (e) {
157
+ if (silent) return false;
143
158
  fail(`Extraction failed: ${e.message}`);
144
159
  }
145
160
  } else {
@@ -150,6 +165,7 @@ async function downloadPrebuilt() {
150
165
  try {
151
166
  execSync(`unzip -o -q "${zipPath}" -d "${APP_DIR}"`, { stdio: "pipe" });
152
167
  } catch (e) {
168
+ if (silent) return false;
153
169
  fail(`Extraction failed: ${e.message}`);
154
170
  }
155
171
  }
@@ -170,12 +186,15 @@ async function downloadPrebuilt() {
170
186
  // Clean up zip
171
187
  fs.unlinkSync(zipPath);
172
188
 
173
- ok(`Overlay ${version} installed`);
174
- console.log(`
189
+ _ok(`Overlay ${version} installed`);
190
+ if (!silent) {
191
+ console.log(`
175
192
  ${GREEN}✓${RESET} Overlay ready!
176
193
  Location: ${APP_PATH}
177
194
  The overlay will auto-start with: ${BOLD}sinain start${RESET}
178
195
  `);
196
+ }
197
+ return true;
179
198
  }
180
199
 
181
200
  // ── Build from source (legacy) ───────────────────────────────────────────────