skillo 0.2.5 → 0.2.8

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 (67) hide show
  1. package/README.md +198 -198
  2. package/dist/api-client-BF6GDR7Q.js +12 -0
  3. package/dist/{chunk-WJKZWKER.js → chunk-63FVALWX.js} +1 -1
  4. package/dist/chunk-63FVALWX.js.map +1 -0
  5. package/dist/chunk-6GOJPFZ7.js +113 -0
  6. package/dist/chunk-6GOJPFZ7.js.map +1 -0
  7. package/dist/chunk-6UGTWBUW.js +89 -0
  8. package/dist/chunk-6UGTWBUW.js.map +1 -0
  9. package/dist/{chunk-2CVEPT6U.js → chunk-73NUWYUO.js} +2 -2
  10. package/dist/chunk-73NUWYUO.js.map +1 -0
  11. package/dist/chunk-QIV4VIXA.js +221 -0
  12. package/dist/chunk-QIV4VIXA.js.map +1 -0
  13. package/dist/{chunk-CPL3P2OF.js → chunk-QUXHHRRK.js} +2 -2
  14. package/dist/chunk-QUXHHRRK.js.map +1 -0
  15. package/dist/{chunk-ODOZM4QV.js → chunk-RQ2SC5HW.js} +72 -10
  16. package/dist/chunk-RQ2SC5HW.js.map +1 -0
  17. package/dist/chunk-U53QWUOR.js +727 -0
  18. package/dist/chunk-U53QWUOR.js.map +1 -0
  19. package/dist/chunk-VAQ73XPE.js +68 -0
  20. package/dist/chunk-VAQ73XPE.js.map +1 -0
  21. package/dist/chunk-XLJGCOVT.js +975 -0
  22. package/dist/chunk-XLJGCOVT.js.map +1 -0
  23. package/dist/{claude-watcher-N6GN6WHJ.js → claude-watcher-WKGBJYKN.js} +65 -3
  24. package/dist/claude-watcher-WKGBJYKN.js.map +1 -0
  25. package/dist/cli.js +499 -1807
  26. package/dist/cli.js.map +1 -1
  27. package/dist/{config-P5EM5L7N.js → config-ZOKAP2LJ.js} +3 -3
  28. package/dist/daemon-6DTCMOJB.js +28 -0
  29. package/dist/daemon-runner.js +352 -65
  30. package/dist/daemon-runner.js.map +1 -1
  31. package/dist/database-KQY5OSCS.js +9 -0
  32. package/dist/git-OGUSYBJS.js +16 -0
  33. package/dist/git-OGUSYBJS.js.map +1 -0
  34. package/dist/git-OUAHIOY2.js +110 -0
  35. package/dist/git-OUAHIOY2.js.map +1 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/{paths-INOKEM66.js → paths-MPOZBOKE.js} +2 -2
  38. package/dist/paths-MPOZBOKE.js.map +1 -0
  39. package/dist/project-OFU2W6MH.js +19 -0
  40. package/dist/project-OFU2W6MH.js.map +1 -0
  41. package/dist/shell-NZABRJLA.js +16 -0
  42. package/dist/shell-NZABRJLA.js.map +1 -0
  43. package/dist/skill-installer-F67OAOQN.js +121 -0
  44. package/dist/skill-installer-F67OAOQN.js.map +1 -0
  45. package/dist/{skill-usage-detector-EO26MRYV.js → skill-usage-detector-MSW5VWQZ.js} +2 -2
  46. package/dist/skill-usage-detector-MSW5VWQZ.js.map +1 -0
  47. package/dist/{tray-YOL4R2RH.js → tray-WKFGUUTO.js} +117 -179
  48. package/dist/tray-WKFGUUTO.js.map +1 -0
  49. package/package.json +62 -63
  50. package/scripts/postinstall.mjs +415 -364
  51. package/scripts/tray-helper-darwin +0 -0
  52. package/scripts/tray-helper-darwin.swift +180 -180
  53. package/scripts/tray-helper-linux.py +322 -0
  54. package/scripts/tray-helper-windows.cs +322 -0
  55. package/dist/api-client-KUQW7FSC.js +0 -12
  56. package/dist/chunk-2CVEPT6U.js.map +0 -1
  57. package/dist/chunk-CPL3P2OF.js.map +0 -1
  58. package/dist/chunk-ODOZM4QV.js.map +0 -1
  59. package/dist/chunk-WJKZWKER.js.map +0 -1
  60. package/dist/claude-watcher-N6GN6WHJ.js.map +0 -1
  61. package/dist/database-F3BFFZKG.js +0 -9
  62. package/dist/skill-usage-detector-EO26MRYV.js.map +0 -1
  63. package/dist/tray-YOL4R2RH.js.map +0 -1
  64. /package/dist/{api-client-KUQW7FSC.js.map → api-client-BF6GDR7Q.js.map} +0 -0
  65. /package/dist/{config-P5EM5L7N.js.map → config-ZOKAP2LJ.js.map} +0 -0
  66. /package/dist/{database-F3BFFZKG.js.map → daemon-6DTCMOJB.js.map} +0 -0
  67. /package/dist/{paths-INOKEM66.js.map → database-KQY5OSCS.js.map} +0 -0
@@ -1,96 +1,20 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ StatusWriter
4
+ } from "./chunk-6UGTWBUW.js";
2
5
  import {
3
6
  ensureDirectory,
4
7
  getDataDir
5
- } from "./chunk-WJKZWKER.js";
8
+ } from "./chunk-63FVALWX.js";
6
9
 
7
10
  // src/tray/tray.ts
8
- import SysTrayModule from "systray2";
9
- import { readFileSync as readFileSync2, existsSync as existsSync2, writeFileSync as writeFileSync2, unlinkSync, chmodSync, readdirSync } from "fs";
11
+ import { readFileSync, existsSync, writeFileSync, unlinkSync, chmodSync, statSync } from "fs";
10
12
  import { exec, execSync, spawn } from "child_process";
11
- import { join as join2, dirname } from "path";
12
- import { platform, homedir } from "os";
13
+ import { join, dirname } from "path";
14
+ import { platform } from "os";
13
15
  import { fileURLToPath } from "url";
14
-
15
- // src/utils/status-writer.ts
16
- import { writeFileSync, readFileSync, existsSync } from "fs";
17
- import { join } from "path";
18
- var STATUS_FILE = "daemon-status.json";
19
- var WRITE_INTERVAL_MS = 1e4;
20
- var StatusWriter = class _StatusWriter {
21
- intervalId = null;
22
- status;
23
- filePath;
24
- constructor() {
25
- this.filePath = join(getDataDir(), STATUS_FILE);
26
- this.status = {
27
- running: true,
28
- pid: process.pid,
29
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
30
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
31
- claudeWatcher: { lastSync: null, promptsSynced: 0, lastError: null },
32
- skillDetector: { deployedSkills: 0, usagesDetected: 0, lastDetection: null, lastError: null },
33
- trackedProjects: [],
34
- activeSessions: 0
35
- };
36
- }
37
- /** Start periodic writes */
38
- start() {
39
- ensureDirectory(getDataDir());
40
- this.write();
41
- this.intervalId = setInterval(() => this.write(), WRITE_INTERVAL_MS);
42
- }
43
- /** Stop writing and mark as not running */
44
- stop() {
45
- if (this.intervalId) {
46
- clearInterval(this.intervalId);
47
- this.intervalId = null;
48
- }
49
- this.status.running = false;
50
- this.status.pid = null;
51
- this.status.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
52
- this.write();
53
- }
54
- /** Merge partial status updates */
55
- update(partial) {
56
- if (partial.claudeWatcher) {
57
- this.status.claudeWatcher = { ...this.status.claudeWatcher, ...partial.claudeWatcher };
58
- delete partial.claudeWatcher;
59
- }
60
- if (partial.skillDetector) {
61
- this.status.skillDetector = { ...this.status.skillDetector, ...partial.skillDetector };
62
- delete partial.skillDetector;
63
- }
64
- Object.assign(this.status, partial);
65
- }
66
- /** Get the status file path */
67
- static getStatusFilePath() {
68
- return join(getDataDir(), STATUS_FILE);
69
- }
70
- /** Read current status from disk (static, for tray/status commands) */
71
- static read() {
72
- const filePath = _StatusWriter.getStatusFilePath();
73
- try {
74
- if (existsSync(filePath)) {
75
- return JSON.parse(readFileSync(filePath, "utf-8"));
76
- }
77
- } catch {
78
- }
79
- return null;
80
- }
81
- write() {
82
- this.status.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
83
- try {
84
- writeFileSync(this.filePath, JSON.stringify(this.status, null, 2), "utf-8");
85
- } catch {
86
- }
87
- }
88
- };
89
-
90
- // src/tray/tray.ts
91
- var SysTray = SysTrayModule.default || SysTrayModule;
92
16
  var SEPARATOR = { title: "<SEPARATOR>", tooltip: "", enabled: true };
93
- var ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAhklEQVQ4T2NkoBAwUqifgWoGMDIyNjAyMP5nYGD4T8gFjHADGBkZAxgZGQMIGQK3gYmJqYCRkfE/IyPj/4KCgv9whzAyMDIwMDL+Z2Bk/M/AwMjwn4GBsaCgoOA/uhehuwBuACMjI9wQBgYGBkZGxv8FBQUBcBfgC0e4C4gJR7gBxIQj1QwAAFbxMBHleBQjAAAAAElFTkSuQmCC";
17
+ var ICON_BASE64 = "iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEE0lEQVR4nM2YS4gcRRjHOz4THyEqGKIePAiKeFECJggqGvcggl68KKxiTjklB8UHCQSMIplV8KAevOjeNHoxxyyCEBCML0Qvgd2Z7urqZ1VXdVXXVr92PmlIYBh2Znu6e2f3D7/bzFc/Zqr7+6oMY4cDAHsB4NTGxsZXxm4OANxUluViURRrZVlCWZY/GrsxAHBDlmWv5Xl+Nc9zGOGCsduitT6mtf4zTVMYR2v9nbFbIqU8liTJb0opmESSJDsvLIR4Wkr5i5QSavB95wIAcLjO5xhjT8RxfCmOY5iBboUBYAEA3qnzWSnlvVEUnWCMXY6iaMgYg62Ioqi7LQEA95dl6QHA/lm/6/v+Q5TSzwghnFIKkyCEdCdcluVPRVEMAeD2pjXCMLwzCIIzYRjKMAxhE7oRLory5aIooCLP8xNt63med9DzvGXf92EUz/PaCwPArXmeD0aESZqmj7QubBiG4zgvuq6LXNeFCsdx2gtnWXZ8rBtV4DzPn+pC2rbtexBCK7ZtA0KovXCappezLINx0jQtsyz7FAAOdDFTWJb1pWVZ7VpzJaO13tisjY7ga62PV/NBW/F+v3+0VQGl1BGtNdSkartPGjsZrfWz6+vrUBel1FAptSylPLgjwkKIR6cNK1PgSqlTAHDzXIUBYE+SJH6SJNCQf6WUz89VWghxpuakNY2LjLEH5yIMAPuEEH8IIaAlSgjx3ly2iVLqvjiO/+lAGuI4/m8u24QQsp9z/jXnfDjjjAsTuDCXbcI5f4FzvsY5h7YwxjRj7ONqittWaQC4JYqik4yxuM5gzrbGYYy9Ymx3giA4RCn9hlI6jKII2kIp/RZjfNu2i1NKj1JKr0w7TdD6/F6NtHNpMoSQRUKIRwiBNoRh+JExrzDGDoRh+HkQBMWEYxDUIOWc323MM67rPub7/s9BEEATwjB8vdHf3FY8CIJXfd83x89vNTjbRPh9AHiprbRlWfsqAd/312cQ/nDmhYqiWMrzfFgUxTkAuLGtOELoAdd1lz3Pg61wXfetmRfIsmxp5Bx3qbrNMToIxnjBcZz+9dPyZti2/fDMhZVSvbFTRaSUOtnFr+37/h0Y4y8cx4FxMMZXGhWVUp7fbDCXUv6aJMnjRgexbfsNjHGGMYbrIIQWGxUTQvSmjIkbQoiLcRwf6UD6zepe4trdxF+NT+BRFPVq3jqucM4Xmi4EAHssy7qKEKqEnzOahhDSq9n/fUrp29Xrq+lalmWtmKb5g9EmQRAsTWuhQRCQMAzPVsN9m3X6/f5e0zT/Xl1dbXc94Lpub8J7knqe90H1pBsdxDTNd9fW1p5pXQhjvDT2uhGO43zS7/db36dtSxBCS9ee3AQhdM40zbuM3ZzBYHDaNM3zg8Hg0E67jOZ/1kjldsi1/g0AAAAASUVORK5CYII=";
94
18
  var TRAY_PID_FILE = "tray.pid";
95
19
  var STATUS_POLL_MS = 3e3;
96
20
  function formatTimeAgo(isoString) {
@@ -219,51 +143,8 @@ function handleClick(title, cleanup) {
219
143
  cleanup();
220
144
  }
221
145
  }
222
- function findDarwinHelper() {
223
- const candidates = [
224
- join2(getDataDir(), "tray-helper-darwin"),
225
- join2(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin"),
226
- join2(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin")
227
- ];
228
- for (const p of candidates) {
229
- if (existsSync2(p)) return p;
230
- }
231
- return null;
232
- }
233
- function compileDarwinHelper() {
234
- const srcCandidates = [
235
- join2(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin.swift"),
236
- join2(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin.swift")
237
- ];
238
- let src = null;
239
- for (const p of srcCandidates) {
240
- if (existsSync2(p)) {
241
- src = p;
242
- break;
243
- }
244
- }
245
- if (!src) return null;
246
- const out = join2(getDataDir(), "tray-helper-darwin");
247
- try {
248
- execSync(`swiftc "${src}" -o "${out}" -O 2>/dev/null`, { timeout: 6e4 });
249
- chmodSync(out, 493);
250
- return out;
251
- } catch {
252
- return null;
253
- }
254
- }
255
- async function startDarwinTray(pidFile) {
256
- let helperPath = findDarwinHelper();
257
- if (!helperPath) {
258
- helperPath = compileDarwinHelper();
259
- }
260
- if (!helperPath) {
261
- await startSystray2Tray(pidFile);
262
- return;
263
- }
264
- const initialStatus = readStatus();
265
- const menu = buildMenu(initialStatus);
266
- const helper = spawn(helperPath, [], {
146
+ async function runNativeHelper(command, args, pidFile) {
147
+ const helper = spawn(command, args, {
267
148
  stdio: ["pipe", "pipe", "ignore"]
268
149
  });
269
150
  const cleanup = () => {
@@ -304,6 +185,8 @@ async function startDarwinTray(pidFile) {
304
185
  helper.stdout.on("data", onData);
305
186
  setTimeout(() => reject(new Error("Tray helper did not become ready")), 1e4);
306
187
  });
188
+ const initialStatus = readStatus();
189
+ const menu = buildMenu(initialStatus);
307
190
  helper.stdin.write(JSON.stringify(menu) + "\n");
308
191
  let clickBuf = "";
309
192
  helper.stdout.on("data", (data) => {
@@ -333,76 +216,131 @@ async function startDarwinTray(pidFile) {
333
216
  await new Promise(() => {
334
217
  });
335
218
  }
336
- function fixSystrayBinaryPermissions() {
337
- if (platform() === "win32") return;
338
- try {
339
- const cacheDir = join2(homedir(), ".cache", "node-systray");
340
- if (!existsSync2(cacheDir)) return;
341
- for (const ver of readdirSync(cacheDir)) {
342
- const dir = join2(cacheDir, ver);
343
- for (const file of readdirSync(dir)) {
344
- if (file.startsWith("tray_")) {
345
- chmodSync(join2(dir, file), 493);
346
- }
347
- }
219
+ function findDarwinHelper() {
220
+ const candidates = [
221
+ join(getDataDir(), "tray-helper-darwin"),
222
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin"),
223
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin")
224
+ ];
225
+ for (const p of candidates) {
226
+ if (existsSync(p)) return p;
227
+ }
228
+ return null;
229
+ }
230
+ function compileDarwinHelper() {
231
+ const srcCandidates = [
232
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-darwin.swift"),
233
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-darwin.swift")
234
+ ];
235
+ let src = null;
236
+ for (const p of srcCandidates) {
237
+ if (existsSync(p)) {
238
+ src = p;
239
+ break;
348
240
  }
241
+ }
242
+ if (!src) return null;
243
+ const out = join(getDataDir(), "tray-helper-darwin");
244
+ try {
245
+ execSync(`swiftc "${src}" -o "${out}" -O 2>/dev/null`, { timeout: 6e4 });
246
+ chmodSync(out, 493);
247
+ return out;
349
248
  } catch {
249
+ return null;
350
250
  }
351
251
  }
352
- async function startSystray2Tray(pidFile) {
353
- fixSystrayBinaryPermissions();
354
- const initialStatus = readStatus();
355
- const menu = buildMenu(initialStatus);
356
- const systray = new SysTray({
357
- menu,
358
- debug: false,
359
- copyDir: true
360
- });
361
- const cleanup = () => {
362
- try {
363
- unlinkSync(pidFile);
364
- } catch {
365
- }
366
- systray.kill(false);
367
- process.exit(0);
368
- };
369
- process.on("SIGINT", cleanup);
370
- process.on("SIGTERM", cleanup);
371
- await systray.ready();
372
- systray.onClick(async (action) => {
373
- handleClick(action.item.title, cleanup);
374
- });
375
- setInterval(async () => {
252
+ function findOrCompileWindowsHelper() {
253
+ const exePath = join(getDataDir(), "tray-helper-windows.exe");
254
+ const srcCandidates = [
255
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-windows.cs"),
256
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-windows.cs")
257
+ ];
258
+ const src = srcCandidates.find((p) => existsSync(p)) || null;
259
+ if (!src) return existsSync(exePath) ? exePath : null;
260
+ if (existsSync(exePath)) {
376
261
  try {
377
- const status = readStatus();
378
- const updatedMenu = buildMenu(status);
379
- await systray.sendAction({ type: "update-menu", menu: updatedMenu });
262
+ const srcStat = statSync(src);
263
+ const exeStat = statSync(exePath);
264
+ if (srcStat.mtimeMs <= exeStat.mtimeMs) return exePath;
380
265
  } catch {
381
266
  }
382
- }, STATUS_POLL_MS);
383
- await new Promise(() => {
384
- });
267
+ }
268
+ const cscPaths = [
269
+ "C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\csc.exe",
270
+ "C:\\Windows\\Microsoft.NET\\Framework\\v4.0.30319\\csc.exe"
271
+ ];
272
+ const csc = cscPaths.find((p) => existsSync(p));
273
+ if (!csc) return existsSync(exePath) ? exePath : null;
274
+ try {
275
+ execSync(
276
+ `"${csc}" /nologo /target:winexe /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.Web.Extensions.dll /out:"${exePath}" "${src}"`,
277
+ { timeout: 3e4, shell: "cmd.exe" }
278
+ );
279
+ return exePath;
280
+ } catch {
281
+ return existsSync(exePath) ? exePath : null;
282
+ }
283
+ }
284
+ function findLinuxHelper() {
285
+ const scriptCandidates = [
286
+ join(dirname(fileURLToPath(import.meta.url)), "..", "scripts", "tray-helper-linux.py"),
287
+ join(dirname(fileURLToPath(import.meta.url)), "scripts", "tray-helper-linux.py")
288
+ ];
289
+ const script = scriptCandidates.find((p) => existsSync(p)) || null;
290
+ if (!script) return null;
291
+ try {
292
+ execSync("python3 --version", { stdio: "ignore" });
293
+ return { python: "python3", script };
294
+ } catch {
295
+ }
296
+ try {
297
+ const ver = execSync("python --version", { encoding: "utf-8" });
298
+ if (ver.includes("Python 3")) return { python: "python", script };
299
+ } catch {
300
+ }
301
+ return null;
385
302
  }
386
303
  async function startTray() {
387
- const pidFile = join2(getDataDir(), TRAY_PID_FILE);
304
+ const pidFile = join(getDataDir(), TRAY_PID_FILE);
388
305
  ensureDirectory(getDataDir());
389
- if (existsSync2(pidFile)) {
306
+ if (existsSync(pidFile)) {
390
307
  try {
391
- const pid = parseInt(readFileSync2(pidFile, "utf-8").trim(), 10);
308
+ const pid = parseInt(readFileSync(pidFile, "utf-8").trim(), 10);
392
309
  process.kill(pid, 0);
393
310
  console.error("Tray icon is already running (PID: " + pid + ")");
394
311
  process.exit(1);
395
312
  } catch {
396
313
  }
397
314
  }
398
- writeFileSync2(pidFile, String(process.pid));
399
- if (platform() === "darwin") {
400
- await startDarwinTray(pidFile);
315
+ writeFileSync(pidFile, String(process.pid));
316
+ const os = platform();
317
+ if (os === "darwin") {
318
+ let helperPath = findDarwinHelper();
319
+ if (!helperPath) {
320
+ helperPath = compileDarwinHelper();
321
+ }
322
+ if (!helperPath) {
323
+ console.error("Could not find or compile tray helper. Install Xcode Command Line Tools: xcode-select --install");
324
+ process.exit(1);
325
+ }
326
+ await runNativeHelper(helperPath, [], pidFile);
327
+ } else if (os === "win32") {
328
+ const helperPath = findOrCompileWindowsHelper();
329
+ if (!helperPath) {
330
+ console.error("Could not find or compile tray helper. Requires .NET Framework 4.x (pre-installed on Windows 10/11).");
331
+ process.exit(1);
332
+ }
333
+ await runNativeHelper(helperPath, [], pidFile);
401
334
  } else {
402
- await startSystray2Tray(pidFile);
335
+ const result = findLinuxHelper();
336
+ if (!result) {
337
+ console.error("Could not find tray helper. Requires python3 with PyGObject (python3-gi).");
338
+ process.exit(1);
339
+ }
340
+ await runNativeHelper(result.python, [result.script], pidFile);
403
341
  }
404
342
  }
405
343
  export {
406
344
  startTray
407
345
  };
408
- //# sourceMappingURL=tray-YOL4R2RH.js.map
346
+ //# sourceMappingURL=tray-WKFGUUTO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tray/tray.ts"],"sourcesContent":["/**\r\n * Skillo System Tray Icon\r\n *\r\n * Shows daemon status, tracked projects, sync info in the system tray.\r\n * Reads ~/.skillo/daemon-status.json (written by StatusWriter in daemon).\r\n *\r\n * macOS: native Swift helper (scripts/tray-helper-darwin.swift).\r\n * Windows: native C# helper (scripts/tray-helper-windows.cs, .NET Framework 4.x).\r\n * Linux: native Python3 helper (scripts/tray-helper-linux.py, PyGObject/GTK).\r\n */\r\n\r\nimport { readFileSync, existsSync, writeFileSync, unlinkSync, chmodSync, statSync } from \"fs\";\r\nimport { exec, execSync, spawn } from \"child_process\";\r\nimport { join, dirname } from \"path\";\r\nimport { platform } from \"os\";\r\nimport { fileURLToPath } from \"url\";\r\nimport { StatusWriter, type DaemonStatus } from \"../utils/status-writer.js\";\r\nimport { getDataDir, ensureDirectory } from \"../utils/paths.js\";\r\n\r\ntype MenuItem = {\r\n title: string;\r\n tooltip: string;\r\n checked?: boolean;\r\n enabled?: boolean;\r\n hidden?: boolean;\r\n items?: MenuItem[];\r\n};\r\n\r\ntype Menu = {\r\n icon: string;\r\n title: string;\r\n tooltip: string;\r\n items: MenuItem[];\r\n};\r\n\r\nconst SEPARATOR: MenuItem = { title: \"<SEPARATOR>\", tooltip: \"\", enabled: true };\r\n\r\n// Skillo \"S\" logo as 44x44 white-on-transparent PNG (from public/logo.svg)\r\n// macOS: isTemplate=true auto-inverts for dark/light mode\r\n// Windows/Linux: white logo on dark tray background\r\nconst ICON_BASE64 =\r\n \"iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE\" +\r\n \"E0lEQVR4nM2YS4gcRRjHOz4THyEqGKIePAiKeFECJggqGvcggl68KKxiTjklB8UHCQSMIplV\" +\r\n \"8KAevOjeNHoxxyyCEBCML0Qvgd2Z7urqZ1VXdVXXVr92PmlIYBh2Znu6e2f3D7/bzFc/Zqr7\" +\r\n \"+6oMY4cDAHsB4NTGxsZXxm4OANxUluViURRrZVlCWZY/GrsxAHBDlmWv5Xl+Nc9zGOGCsdui\" +\r\n \"tT6mtf4zTVMYR2v9nbFbIqU8liTJb0opmESSJDsvLIR4Wkr5i5QSavB95wIAcLjO5xhjT8Rx\" +\r\n \"fCmOY5iBboUBYAEA3qnzWSnlvVEUnWCMXY6iaMgYg62Ioqi7LQEA95dl6QHA/lm/6/v+Q5TS\" +\r\n \"zwghnFIKkyCEdCdcluVPRVEMAeD2pjXCMLwzCIIzYRjKMAxhE7oRLory5aIooCLP8xNt63med9\" +\r\n \"DzvGXf92EUz/PaCwPArXmeD0aESZqmj7QubBiG4zgvuq6LXNeFCsdx2gtnWXZ8rBtV4DzPn+\" +\r\n \"pC2rbtexBCK7ZtA0KovXCappezLINx0jQtsyz7FAAOdDFTWJb1pWVZ7VpzJaO13tisjY7ga62P\" +\r\n \"V/NBW/F+v3+0VQGl1BGtNdSkartPGjsZrfWz6+vrUBel1FAptSylPLgjwkKIR6cNK1PgSqlTAH\" +\r\n \"DzXIUBYE+SJH6SJNCQf6WUz89VWghxpuakNY2LjLEH5yIMAPuEEH8IIaAlSgjx3ly2iVLqvj\" +\r\n \"iO/+lAGuI4/m8u24QQsp9z/jXnfDjjjAsTuDCXbcI5f4FzvsY5h7YwxjRj7ONqittWaQC4JY\" +\r\n \"qik4yxuM5gzrbGYYy9Ymx3giA4RCn9hlI6jKII2kIp/RZjfNu2i1NKj1JKr0w7TdD6/F6NtH\" +\r\n \"NpMoSQRUKIRwiBNoRh+JExrzDGDoRh+HkQBMWEYxDUIOWc323MM67rPub7/s9BEEATwjB8vdHf\" +\r\n \"3FY8CIJXfd83x89vNTjbRPh9AHiprbRlWfsqAd/312cQ/nDmhYqiWMrzfFgUxTkAuLGtOELo\" +\r\n \"Add1lz3Pg61wXfetmRfIsmxp5Bx3qbrNMToIxnjBcZz+9dPyZti2/fDMhZVSvbFTRaSUOtnFr+\" +\r\n \"37/h0Y4y8cx4FxMMZXGhWVUp7fbDCXUv6aJMnjRgexbfsNjHGGMYbrIIQWGxUTQvSmjIkbQo\" +\r\n \"iLcRwf6UD6zepe4trdxF+NT+BRFPVq3jqucM4Xmi4EAHssy7qKEKqEnzOahhDSq9n/fUrp29\" +\r\n \"Xrq+lalmWtmKb5g9EmQRAsTWuhQRCQMAzPVsN9m3X6/f5e0zT/Xl1dbXc94Lpub8J7knqe90\" +\r\n \"H1pBsdxDTNd9fW1p5pXQhjvDT2uhGO43zS7/db36dtSxBCS9ee3AQhdM40zbuM3ZzBYHDaNM\" +\r\n \"3zg8Hg0E67jOZ/1kjldsi1/g0AAAAASUVORK5CYII=\";\r\n\r\nconst TRAY_PID_FILE = \"tray.pid\";\r\nconst STATUS_POLL_MS = 3000;\r\n\r\nfunction formatTimeAgo(isoString: string | null | undefined): string {\r\n if (!isoString) return \"Never\";\r\n const diff = Date.now() - new Date(isoString).getTime();\r\n const seconds = Math.floor(diff / 1000);\r\n if (seconds < 60) return \"Just now\";\r\n const minutes = Math.floor(seconds / 60);\r\n if (minutes < 60) return `${minutes} min ago`;\r\n const hours = Math.floor(minutes / 60);\r\n if (hours < 24) return `${hours}h ago`;\r\n const days = Math.floor(hours / 24);\r\n return `${days}d ago`;\r\n}\r\n\r\nfunction readStatus(): DaemonStatus | null {\r\n return StatusWriter.read();\r\n}\r\n\r\nfunction buildMenu(status: DaemonStatus | null): Menu {\r\n const running = status?.running ?? false;\r\n const statusIcon = running ? \"\\u25CF\" : \"\\u25CB\"; // ● or ○\r\n const statusText = running ? \"Running\" : \"Stopped\";\r\n\r\n const projects = status?.trackedProjects ?? [];\r\n const projectItems: MenuItem[] = projects.length > 0\r\n ? projects.map((p) => ({\r\n title: ` ${p.name}`,\r\n tooltip: p.path,\r\n enabled: false,\r\n checked: false,\r\n }))\r\n : [{\r\n title: \" (none)\",\r\n tooltip: \"No tracked projects\",\r\n enabled: false,\r\n checked: false,\r\n }];\r\n\r\n const items: MenuItem[] = [\r\n {\r\n title: `${statusIcon} Skillo \\u2014 ${statusText}`,\r\n tooltip: \"Daemon status\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: status?.user ? `Logged in as: ${status.user}` : \"Not logged in\",\r\n tooltip: \"User info\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: `Tracked Projects (${projects.length})`,\r\n tooltip: \"Projects being tracked\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n ...projectItems,\r\n SEPARATOR,\r\n {\r\n title: `Last sync: ${formatTimeAgo(status?.claudeWatcher?.lastSync)}`,\r\n tooltip: \"Last Claude conversation sync\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n {\r\n title: `Prompts synced: ${status?.claudeWatcher?.promptsSynced ?? 0}`,\r\n tooltip: \"Total prompts synced\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n {\r\n title: `Skills detected: ${status?.skillDetector?.usagesDetected ?? 0}`,\r\n tooltip: \"Skill usages detected\",\r\n enabled: false,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: running ? \"Stop Daemon\" : \"Start Daemon\",\r\n tooltip: running ? \"Stop the Skillo daemon\" : \"Start the Skillo daemon\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n {\r\n title: \"Open Dashboard\",\r\n tooltip: \"Open Skillo dashboard in browser\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n SEPARATOR,\r\n {\r\n title: \"Quit Tray\",\r\n tooltip: \"Hide tray icon (daemon keeps running)\",\r\n enabled: true,\r\n checked: false,\r\n },\r\n ];\r\n\r\n return {\r\n icon: ICON_BASE64,\r\n title: \"\",\r\n tooltip: `Skillo \\u2014 ${statusText}`,\r\n items,\r\n };\r\n}\r\n\r\nfunction openBrowser(url: string) {\r\n const os = platform();\r\n let cmd: string;\r\n if (os === \"darwin\") {\r\n cmd = `open \"${url}\"`;\r\n } else if (os === \"win32\") {\r\n cmd = `start \"\" \"${url}\"`;\r\n } else {\r\n cmd = `xdg-open \"${url}\"`;\r\n }\r\n exec(cmd, () => {});\r\n}\r\n\r\nfunction execSkillo(args: string) {\r\n exec(`skillo ${args}`, () => {});\r\n}\r\n\r\nfunction handleClick(title: string, cleanup: () => void) {\r\n if (title === \"Stop Daemon\" || title === \"Start Daemon\") {\r\n execSkillo(title === \"Stop Daemon\" ? \"stop\" : \"start\");\r\n } else if (title === \"Open Dashboard\") {\r\n openBrowser(\"https://www.skillo.one/dashboard\");\r\n } else if (title === \"Quit Tray\") {\r\n cleanup();\r\n }\r\n}\r\n\r\n// ── Shared native helper runner ───────────────────────────────────────────────\r\n\r\nasync function runNativeHelper(\r\n command: string,\r\n args: string[],\r\n pidFile: string,\r\n): Promise<void> {\r\n const helper = spawn(command, args, {\r\n stdio: [\"pipe\", \"pipe\", \"ignore\"],\r\n });\r\n\r\n const cleanup = () => {\r\n try { unlinkSync(pidFile); } catch { /* ignore */ }\r\n helper.kill();\r\n process.exit(0);\r\n };\r\n process.on(\"SIGINT\", cleanup);\r\n process.on(\"SIGTERM\", cleanup);\r\n helper.on(\"exit\", () => {\r\n try { unlinkSync(pidFile); } catch { /* ignore */ }\r\n process.exit(0);\r\n });\r\n\r\n // Wait for {\"type\":\"ready\"} with 10s timeout\r\n await new Promise<void>((resolve, reject) => {\r\n let buf = \"\";\r\n const onData = (data: Buffer) => {\r\n buf += data.toString();\r\n const lines = buf.split(\"\\n\");\r\n buf = lines.pop() || \"\";\r\n for (const line of lines) {\r\n if (!line.trim()) continue;\r\n try {\r\n const msg = JSON.parse(line);\r\n if (msg.type === \"ready\") {\r\n helper.stdout!.removeListener(\"data\", onData);\r\n resolve();\r\n }\r\n } catch { /* ignore parse errors */ }\r\n }\r\n };\r\n helper.stdout!.on(\"data\", onData);\r\n setTimeout(() => reject(new Error(\"Tray helper did not become ready\")), 10000);\r\n });\r\n\r\n // Send initial menu\r\n const initialStatus = readStatus();\r\n const menu = buildMenu(initialStatus);\r\n helper.stdin!.write(JSON.stringify(menu) + \"\\n\");\r\n\r\n // Listen for clicks\r\n let clickBuf = \"\";\r\n helper.stdout!.on(\"data\", (data: Buffer) => {\r\n clickBuf += data.toString();\r\n const lines = clickBuf.split(\"\\n\");\r\n clickBuf = lines.pop() || \"\";\r\n for (const line of lines) {\r\n if (!line.trim()) continue;\r\n try {\r\n const msg = JSON.parse(line);\r\n if (msg.type === \"clicked\" && msg.item) {\r\n handleClick(msg.item.title, cleanup);\r\n }\r\n } catch { /* ignore */ }\r\n }\r\n });\r\n\r\n // Poll and update\r\n setInterval(() => {\r\n try {\r\n const status = readStatus();\r\n const updatedMenu = buildMenu(status);\r\n const action = { type: \"update-menu\", menu: updatedMenu };\r\n helper.stdin!.write(JSON.stringify(action) + \"\\n\");\r\n } catch { /* ignore */ }\r\n }, STATUS_POLL_MS);\r\n\r\n await new Promise(() => {});\r\n}\r\n\r\n// ── macOS native tray (Swift helper) ─────────────────────────────────────────\r\n\r\nfunction findDarwinHelper(): string | null {\r\n const candidates = [\r\n join(getDataDir(), \"tray-helper-darwin\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-darwin\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-darwin\"),\r\n ];\r\n for (const p of candidates) {\r\n if (existsSync(p)) return p;\r\n }\r\n return null;\r\n}\r\n\r\nfunction compileDarwinHelper(): string | null {\r\n const srcCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-darwin.swift\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-darwin.swift\"),\r\n ];\r\n let src: string | null = null;\r\n for (const p of srcCandidates) {\r\n if (existsSync(p)) { src = p; break; }\r\n }\r\n if (!src) return null;\r\n\r\n const out = join(getDataDir(), \"tray-helper-darwin\");\r\n try {\r\n execSync(`swiftc \"${src}\" -o \"${out}\" -O 2>/dev/null`, { timeout: 60000 });\r\n chmodSync(out, 0o755);\r\n return out;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n// ── Windows native tray (C# helper) ──────────────────────────────────────────\r\n\r\nfunction findOrCompileWindowsHelper(): string | null {\r\n const exePath = join(getDataDir(), \"tray-helper-windows.exe\");\r\n const srcCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-windows.cs\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-windows.cs\"),\r\n ];\r\n\r\n const src = srcCandidates.find((p) => existsSync(p)) || null;\r\n if (!src) return existsSync(exePath) ? exePath : null;\r\n\r\n // Check if recompile needed (source newer than binary)\r\n if (existsSync(exePath)) {\r\n try {\r\n const srcStat = statSync(src);\r\n const exeStat = statSync(exePath);\r\n if (srcStat.mtimeMs <= exeStat.mtimeMs) return exePath; // cached\r\n } catch { /* recompile on error */ }\r\n }\r\n\r\n // Find csc.exe\r\n const cscPaths = [\r\n \"C:\\\\Windows\\\\Microsoft.NET\\\\Framework64\\\\v4.0.30319\\\\csc.exe\",\r\n \"C:\\\\Windows\\\\Microsoft.NET\\\\Framework\\\\v4.0.30319\\\\csc.exe\",\r\n ];\r\n const csc = cscPaths.find((p) => existsSync(p));\r\n if (!csc) return existsSync(exePath) ? exePath : null;\r\n\r\n try {\r\n execSync(\r\n `\"${csc}\" /nologo /target:winexe /r:System.Windows.Forms.dll /r:System.Drawing.dll /r:System.Web.Extensions.dll /out:\"${exePath}\" \"${src}\"`,\r\n { timeout: 30000, shell: \"cmd.exe\" },\r\n );\r\n return exePath;\r\n } catch {\r\n return existsSync(exePath) ? exePath : null;\r\n }\r\n}\r\n\r\n// ── Linux native tray (Python3 helper) ───────────────────────────────────────\r\n\r\nfunction findLinuxHelper(): { python: string; script: string } | null {\r\n const scriptCandidates = [\r\n join(dirname(fileURLToPath(import.meta.url)), \"..\", \"scripts\", \"tray-helper-linux.py\"),\r\n join(dirname(fileURLToPath(import.meta.url)), \"scripts\", \"tray-helper-linux.py\"),\r\n ];\r\n\r\n const script = scriptCandidates.find((p) => existsSync(p)) || null;\r\n if (!script) return null;\r\n\r\n // Find python3\r\n try {\r\n execSync(\"python3 --version\", { stdio: \"ignore\" });\r\n return { python: \"python3\", script };\r\n } catch { /* try next */ }\r\n\r\n try {\r\n const ver = execSync(\"python --version\", { encoding: \"utf-8\" });\r\n if (ver.includes(\"Python 3\")) return { python: \"python\", script };\r\n } catch { /* not available */ }\r\n\r\n return null;\r\n}\r\n\r\n// ── Entry point ──────────────────────────────────────────────────────────────\r\n\r\nexport async function startTray(): Promise<void> {\r\n const pidFile = join(getDataDir(), TRAY_PID_FILE);\r\n ensureDirectory(getDataDir());\r\n\r\n // Check if another tray is already running\r\n if (existsSync(pidFile)) {\r\n try {\r\n const pid = parseInt(readFileSync(pidFile, \"utf-8\").trim(), 10);\r\n process.kill(pid, 0);\r\n console.error(\"Tray icon is already running (PID: \" + pid + \")\");\r\n process.exit(1);\r\n } catch {\r\n // Stale PID file, continue\r\n }\r\n }\r\n\r\n writeFileSync(pidFile, String(process.pid));\r\n\r\n const os = platform();\r\n\r\n if (os === \"darwin\") {\r\n let helperPath = findDarwinHelper();\r\n if (!helperPath) {\r\n helperPath = compileDarwinHelper();\r\n }\r\n if (!helperPath) {\r\n console.error(\"Could not find or compile tray helper. Install Xcode Command Line Tools: xcode-select --install\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(helperPath, [], pidFile);\r\n } else if (os === \"win32\") {\r\n const helperPath = findOrCompileWindowsHelper();\r\n if (!helperPath) {\r\n console.error(\"Could not find or compile tray helper. Requires .NET Framework 4.x (pre-installed on Windows 10/11).\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(helperPath, [], pidFile);\r\n } else {\r\n const result = findLinuxHelper();\r\n if (!result) {\r\n console.error(\"Could not find tray helper. Requires python3 with PyGObject (python3-gi).\");\r\n process.exit(1);\r\n }\r\n await runNativeHelper(result.python, [result.script], pidFile);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,63 +1,62 @@
1
- {
2
- "name": "skillo",
3
- "version": "0.2.5",
4
- "description": "Autonomous workflow learning & skill generation system - Learn workflows by observation, not explanation",
5
- "keywords": [
6
- "cli",
7
- "workflow",
8
- "automation",
9
- "ai",
10
- "skills",
11
- "claude",
12
- "claude-code",
13
- "learning",
14
- "terminal"
15
- ],
16
- "author": "Erkan Dogan",
17
- "license": "UNLICENSED",
18
- "homepage": "https://skillo.one",
19
- "type": "module",
20
- "bin": {
21
- "skillo": "./dist/cli.js"
22
- },
23
- "main": "./dist/index.js",
24
- "types": "./dist/index.d.ts",
25
- "exports": {
26
- ".": {
27
- "import": "./dist/index.js",
28
- "types": "./dist/index.d.ts"
29
- }
30
- },
31
- "files": [
32
- "dist",
33
- "scripts",
34
- "assets",
35
- "README.md"
36
- ],
37
- "engines": {
38
- "node": ">=18.0.0"
39
- },
40
- "scripts": {
41
- "build": "tsup",
42
- "dev": "tsup --watch",
43
- "start": "node dist/cli.js",
44
- "typecheck": "tsc --noEmit",
45
- "lint": "eslint src/",
46
- "postinstall": "node scripts/postinstall.mjs",
47
- "prepublishOnly": "npm run build"
48
- },
49
- "dependencies": {
50
- "chalk": "^5.4.1",
51
- "commander": "^13.1.0",
52
- "ora": "^8.2.0",
53
- "sql.js": "^1.12.0",
54
- "systray2": "^2.1.4",
55
- "yaml": "^2.7.0"
56
- },
57
- "devDependencies": {
58
- "@types/node": "^22.10.10",
59
- "@types/sql.js": "^1.4.9",
60
- "tsup": "^8.3.5",
61
- "typescript": "^5.7.3"
62
- }
63
- }
1
+ {
2
+ "name": "skillo",
3
+ "version": "0.2.8",
4
+ "description": "Autonomous workflow learning & skill generation system - Learn workflows by observation, not explanation",
5
+ "keywords": [
6
+ "cli",
7
+ "workflow",
8
+ "automation",
9
+ "ai",
10
+ "skills",
11
+ "claude",
12
+ "claude-code",
13
+ "learning",
14
+ "terminal"
15
+ ],
16
+ "author": "Erkan Dogan",
17
+ "license": "UNLICENSED",
18
+ "homepage": "https://skillo.one",
19
+ "type": "module",
20
+ "bin": {
21
+ "skillo": "./dist/cli.js"
22
+ },
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "import": "./dist/index.js",
28
+ "types": "./dist/index.d.ts"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "scripts",
34
+ "assets",
35
+ "README.md"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "scripts": {
41
+ "build": "tsup",
42
+ "dev": "tsup --watch",
43
+ "start": "node dist/cli.js",
44
+ "typecheck": "tsc --noEmit",
45
+ "lint": "eslint src/",
46
+ "postinstall": "node scripts/postinstall.mjs",
47
+ "prepublishOnly": "npm run build"
48
+ },
49
+ "dependencies": {
50
+ "chalk": "^5.4.1",
51
+ "commander": "^13.1.0",
52
+ "ora": "^8.2.0",
53
+ "sql.js": "^1.12.0",
54
+ "yaml": "^2.7.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/node": "^22.10.10",
58
+ "@types/sql.js": "^1.4.9",
59
+ "tsup": "^8.3.5",
60
+ "typescript": "^5.7.3"
61
+ }
62
+ }