@djolex999/vir-cli 0.18.1 → 0.19.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.
@@ -0,0 +1,85 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { cpSync, readFileSync, rmSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { VIR_DIR } from "../config.js";
6
+ // dist/ui/macNotifier.js → <package root>/assets/Vir.app
7
+ const BUNDLED_APP = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "assets", "Vir.app");
8
+ export const INSTALLED_APP = join(VIR_DIR, "Vir.app");
9
+ const EXECUTABLE = join(INSTALLED_APP, "Contents", "MacOS", "vir-notifier");
10
+ const LSREGISTER = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
11
+ export function bundleVersion(infoPlist) {
12
+ const m = /<key>CFBundleVersion<\/key>\s*<string>([^<]+)<\/string>/.exec(infoPlist);
13
+ return m?.[1] ?? null;
14
+ }
15
+ export function parsePermission(stdout) {
16
+ const s = stdout.trim();
17
+ return s === "allowed" || s === "denied" || s === "undetermined" ? s : null;
18
+ }
19
+ function readBundleVersion(app) {
20
+ try {
21
+ return bundleVersion(readFileSync(join(app, "Contents", "Info.plist"), "utf8"));
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ }
27
+ /**
28
+ * Installs (or upgrades) ~/.vir/Vir.app from the copy shipped in the package
29
+ * and registers it with LaunchServices. Without registration the notification
30
+ * daemon can't resolve dev.vir.app and rejects it as "not allowed", so this
31
+ * re-registers on every call (~30ms): cheap insurance against a rebuilt
32
+ * LaunchServices database. Returns false off macOS or when the package has no
33
+ * helper (a source checkout that never ran npm run build:notifier).
34
+ */
35
+ export function ensureNotifierApp() {
36
+ if (process.platform !== "darwin")
37
+ return false;
38
+ const bundled = readBundleVersion(BUNDLED_APP);
39
+ if (bundled === null)
40
+ return false;
41
+ if (readBundleVersion(INSTALLED_APP) !== bundled) {
42
+ rmSync(INSTALLED_APP, { recursive: true, force: true });
43
+ cpSync(BUNDLED_APP, INSTALLED_APP, { recursive: true });
44
+ }
45
+ spawnSync(LSREGISTER, ["-f", INSTALLED_APP], { stdio: "ignore" });
46
+ return true;
47
+ }
48
+ /**
49
+ * Posts through Vir.app. False means "use the fallback": no helper, or the
50
+ * user hasn't allowed vir yet. Never prompts for permission (see main.swift).
51
+ */
52
+ export function notifyViaApp(title, message) {
53
+ if (!ensureNotifierApp())
54
+ return false;
55
+ const r = spawnSync(EXECUTABLE, ["notify", title, message], {
56
+ stdio: "ignore",
57
+ timeout: 15_000,
58
+ });
59
+ return r.status === 0;
60
+ }
61
+ export function notifierPermission() {
62
+ if (!ensureNotifierApp())
63
+ return null;
64
+ const r = spawnSync(EXECUTABLE, ["status"], {
65
+ encoding: "utf8",
66
+ timeout: 15_000,
67
+ });
68
+ return r.status === 0 ? parsePermission(r.stdout) : null;
69
+ }
70
+ /**
71
+ * Shows the macOS "vir would like to send notifications" prompt and blocks
72
+ * until the user answers (the helper gives up after 10 minutes). Interactive
73
+ * commands only: an unanswered prompt is withdrawn when the helper exits and
74
+ * macOS then records a denial.
75
+ */
76
+ export function requestNotifierPermission() {
77
+ if (!ensureNotifierApp())
78
+ return null;
79
+ const r = spawnSync(EXECUTABLE, ["request"], {
80
+ encoding: "utf8",
81
+ stdio: ["ignore", "pipe", "inherit"],
82
+ });
83
+ return r.status === 0 ? parsePermission(r.stdout) : null;
84
+ }
85
+ //# sourceMappingURL=macNotifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macNotifier.js","sourceRoot":"","sources":["../../src/ui/macNotifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { notifyViaApp } from "./macNotifier.js";
3
+ // Desktop notification, platform-aware and best-effort. macOS posts through
4
+ // Vir.app (shown as "vir" with the vir icon) and falls back to osascript
5
+ // (shown as "Script Editor") until the user has allowed vir's notifications;
6
+ // Linux uses notify-send when present; every other platform silently skips.
7
+ // All paths use spawnSync arg-arrays (no shell, no injection) and the whole
8
+ // thing is wrapped so a notification failure never crashes the pipeline.
9
+ export function notify(title, message) {
10
+ try {
11
+ if (process.platform === "darwin") {
12
+ if (notifyViaApp(title, message))
13
+ return;
14
+ const safeTitle = escapeAppleScript(title);
15
+ const safeMessage = escapeAppleScript(message);
16
+ spawnSync("osascript", [
17
+ "-e",
18
+ `display notification "${safeMessage}" with title "${safeTitle}" sound name "Glass"`,
19
+ ], { stdio: "ignore" });
20
+ }
21
+ else if (process.platform === "linux") {
22
+ const which = spawnSync("which", ["notify-send"], { stdio: "ignore" });
23
+ if (which.status === 0) {
24
+ spawnSync("notify-send", [title, message], { stdio: "ignore" });
25
+ }
26
+ }
27
+ // win32 + everything else: no notification mechanism, skip silently.
28
+ }
29
+ catch {
30
+ // notification failure must never crash the pipeline
31
+ }
32
+ }
33
+ function escapeAppleScript(s) {
34
+ return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
35
+ }
36
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/ui/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,4EAA4E;AAC5E,yEAAyE;AACzE,6EAA6E;AAC7E,4EAA4E;AAC5E,4EAA4E;AAC5E,yEAAyE;AACzE,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,OAAe;IACnD,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YAClC,IAAI,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC;gBAAE,OAAO;YACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAC/C,SAAS,CACP,WAAW,EACX;gBACE,IAAI;gBACJ,yBAAyB,WAAW,iBAAiB,SAAS,sBAAsB;aACrF,EACD,EAAE,KAAK,EAAE,QAAQ,EAAE,CACpB,CAAC;QACJ,CAAC;aAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvB,SAAS,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QACD,qEAAqE;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;IACvD,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,CAAS;IAClC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djolex999/vir-cli",
3
- "version": "0.18.1",
3
+ "version": "0.19.0",
4
4
  "description": "An LLM Wiki for Claude Code, in your Obsidian vault.",
5
5
  "author": "Djordje Markovi\u0107 <djordje@growthq.rs>",
6
6
  "license": "MIT",
@@ -31,11 +31,13 @@
31
31
  "files": [
32
32
  "dist",
33
33
  "assets/vir_graph_spiral.svg",
34
+ "assets/Vir.app",
34
35
  "README.md",
35
36
  "LICENSE"
36
37
  ],
37
38
  "scripts": {
38
39
  "build": "tsc",
40
+ "build:notifier": "native/notifier/build.sh",
39
41
  "prepublishOnly": "npm run build && npm test",
40
42
  "dev": "tsc --watch",
41
43
  "start": "node dist/cli.js",