@staticn0va/wigolo 0.3.0 → 0.4.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 (184) hide show
  1. package/README.md +67 -2
  2. package/SKILL.md +149 -0
  3. package/dist/cache/change-detector.d.ts +7 -0
  4. package/dist/cache/change-detector.d.ts.map +1 -0
  5. package/dist/cache/change-detector.js +43 -0
  6. package/dist/cache/change-detector.js.map +1 -0
  7. package/dist/cache/diff-summary.d.ts +2 -0
  8. package/dist/cache/diff-summary.d.ts.map +1 -0
  9. package/dist/cache/diff-summary.js +87 -0
  10. package/dist/cache/diff-summary.js.map +1 -0
  11. package/dist/cache/store.d.ts +2 -0
  12. package/dist/cache/store.d.ts.map +1 -1
  13. package/dist/cache/store.js +10 -0
  14. package/dist/cache/store.js.map +1 -1
  15. package/dist/cli/auth.d.ts +2 -0
  16. package/dist/cli/auth.d.ts.map +1 -0
  17. package/dist/cli/auth.js +95 -0
  18. package/dist/cli/auth.js.map +1 -0
  19. package/dist/cli/daemon.d.ts +6 -1
  20. package/dist/cli/daemon.d.ts.map +1 -1
  21. package/dist/cli/daemon.js +56 -3
  22. package/dist/cli/daemon.js.map +1 -1
  23. package/dist/cli/doctor.d.ts +8 -0
  24. package/dist/cli/doctor.d.ts.map +1 -0
  25. package/dist/cli/doctor.js +153 -0
  26. package/dist/cli/doctor.js.map +1 -0
  27. package/dist/cli/health.d.ts +1 -1
  28. package/dist/cli/health.d.ts.map +1 -1
  29. package/dist/cli/health.js +41 -3
  30. package/dist/cli/health.js.map +1 -1
  31. package/dist/cli/index.d.ts +1 -1
  32. package/dist/cli/index.d.ts.map +1 -1
  33. package/dist/cli/index.js +1 -1
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/cli/plugin.d.ts +5 -0
  36. package/dist/cli/plugin.d.ts.map +1 -0
  37. package/dist/cli/plugin.js +188 -0
  38. package/dist/cli/plugin.js.map +1 -0
  39. package/dist/cli/shell.d.ts +2 -0
  40. package/dist/cli/shell.d.ts.map +1 -0
  41. package/dist/cli/shell.js +86 -0
  42. package/dist/cli/shell.js.map +1 -0
  43. package/dist/cli/warmup.d.ts +4 -0
  44. package/dist/cli/warmup.d.ts.map +1 -1
  45. package/dist/cli/warmup.js +78 -2
  46. package/dist/cli/warmup.js.map +1 -1
  47. package/dist/config.d.ts +10 -0
  48. package/dist/config.d.ts.map +1 -1
  49. package/dist/config.js +27 -0
  50. package/dist/config.js.map +1 -1
  51. package/dist/daemon/health-check.d.ts +16 -0
  52. package/dist/daemon/health-check.d.ts.map +1 -0
  53. package/dist/daemon/health-check.js +36 -0
  54. package/dist/daemon/health-check.js.map +1 -0
  55. package/dist/daemon/http-server.d.ts +26 -0
  56. package/dist/daemon/http-server.d.ts.map +1 -0
  57. package/dist/daemon/http-server.js +282 -0
  58. package/dist/daemon/http-server.js.map +1 -0
  59. package/dist/daemon/proxy.d.ts +10 -0
  60. package/dist/daemon/proxy.d.ts.map +1 -0
  61. package/dist/daemon/proxy.js +99 -0
  62. package/dist/daemon/proxy.js.map +1 -0
  63. package/dist/fetch/action-executor.d.ts +28 -0
  64. package/dist/fetch/action-executor.d.ts.map +1 -0
  65. package/dist/fetch/action-executor.js +86 -0
  66. package/dist/fetch/action-executor.js.map +1 -0
  67. package/dist/fetch/auth.d.ts +2 -1
  68. package/dist/fetch/auth.d.ts.map +1 -1
  69. package/dist/fetch/auth.js +30 -2
  70. package/dist/fetch/auth.js.map +1 -1
  71. package/dist/fetch/browser-pool.d.ts +30 -11
  72. package/dist/fetch/browser-pool.d.ts.map +1 -1
  73. package/dist/fetch/browser-pool.js +165 -49
  74. package/dist/fetch/browser-pool.js.map +1 -1
  75. package/dist/fetch/browser-selector.d.ts +17 -0
  76. package/dist/fetch/browser-selector.d.ts.map +1 -0
  77. package/dist/fetch/browser-selector.js +70 -0
  78. package/dist/fetch/browser-selector.js.map +1 -0
  79. package/dist/fetch/browser-types.d.ts +3 -0
  80. package/dist/fetch/browser-types.d.ts.map +1 -0
  81. package/dist/fetch/browser-types.js +45 -0
  82. package/dist/fetch/browser-types.js.map +1 -0
  83. package/dist/fetch/cdp-client.d.ts +9 -0
  84. package/dist/fetch/cdp-client.d.ts.map +1 -0
  85. package/dist/fetch/cdp-client.js +90 -0
  86. package/dist/fetch/cdp-client.js.map +1 -0
  87. package/dist/fetch/router.d.ts +4 -1
  88. package/dist/fetch/router.d.ts.map +1 -1
  89. package/dist/fetch/router.js +8 -2
  90. package/dist/fetch/router.js.map +1 -1
  91. package/dist/index.js +39 -3
  92. package/dist/index.js.map +1 -1
  93. package/dist/instructions.d.ts +26 -0
  94. package/dist/instructions.d.ts.map +1 -0
  95. package/dist/instructions.js +101 -0
  96. package/dist/instructions.js.map +1 -0
  97. package/dist/logger.d.ts +1 -1
  98. package/dist/logger.d.ts.map +1 -1
  99. package/dist/plugins/loader.d.ts +20 -0
  100. package/dist/plugins/loader.d.ts.map +1 -0
  101. package/dist/plugins/loader.js +162 -0
  102. package/dist/plugins/loader.js.map +1 -0
  103. package/dist/plugins/registry.d.ts +26 -0
  104. package/dist/plugins/registry.d.ts.map +1 -0
  105. package/dist/plugins/registry.js +68 -0
  106. package/dist/plugins/registry.js.map +1 -0
  107. package/dist/plugins/validate.d.ts +9 -0
  108. package/dist/plugins/validate.d.ts.map +1 -0
  109. package/dist/plugins/validate.js +70 -0
  110. package/dist/plugins/validate.js.map +1 -0
  111. package/dist/repl/commands/cache.d.ts +4 -0
  112. package/dist/repl/commands/cache.d.ts.map +1 -0
  113. package/dist/repl/commands/cache.js +44 -0
  114. package/dist/repl/commands/cache.js.map +1 -0
  115. package/dist/repl/commands/crawl.d.ts +7 -0
  116. package/dist/repl/commands/crawl.d.ts.map +1 -0
  117. package/dist/repl/commands/crawl.js +42 -0
  118. package/dist/repl/commands/crawl.js.map +1 -0
  119. package/dist/repl/commands/extract.d.ts +5 -0
  120. package/dist/repl/commands/extract.d.ts.map +1 -0
  121. package/dist/repl/commands/extract.js +37 -0
  122. package/dist/repl/commands/extract.js.map +1 -0
  123. package/dist/repl/commands/fetch.d.ts +5 -0
  124. package/dist/repl/commands/fetch.d.ts.map +1 -0
  125. package/dist/repl/commands/fetch.js +53 -0
  126. package/dist/repl/commands/fetch.js.map +1 -0
  127. package/dist/repl/commands/search.d.ts +5 -0
  128. package/dist/repl/commands/search.d.ts.map +1 -0
  129. package/dist/repl/commands/search.js +62 -0
  130. package/dist/repl/commands/search.js.map +1 -0
  131. package/dist/repl/commands/types.d.ts +9 -0
  132. package/dist/repl/commands/types.d.ts.map +1 -0
  133. package/dist/repl/commands/types.js +2 -0
  134. package/dist/repl/commands/types.js.map +1 -0
  135. package/dist/repl/formatters.d.ts +10 -0
  136. package/dist/repl/formatters.d.ts.map +1 -0
  137. package/dist/repl/formatters.js +209 -0
  138. package/dist/repl/formatters.js.map +1 -0
  139. package/dist/repl/parser.d.ts +9 -0
  140. package/dist/repl/parser.d.ts.map +1 -0
  141. package/dist/repl/parser.js +84 -0
  142. package/dist/repl/parser.js.map +1 -0
  143. package/dist/repl/shell.d.ts +8 -0
  144. package/dist/repl/shell.d.ts.map +1 -0
  145. package/dist/repl/shell.js +156 -0
  146. package/dist/repl/shell.js.map +1 -0
  147. package/dist/search/context-formatter.d.ts +3 -0
  148. package/dist/search/context-formatter.d.ts.map +1 -0
  149. package/dist/search/context-formatter.js +56 -0
  150. package/dist/search/context-formatter.js.map +1 -0
  151. package/dist/search/engines/bing.d.ts +1 -0
  152. package/dist/search/engines/bing.d.ts.map +1 -1
  153. package/dist/search/engines/bing.js +27 -1
  154. package/dist/search/engines/bing.js.map +1 -1
  155. package/dist/searxng/bootstrap.d.ts +30 -0
  156. package/dist/searxng/bootstrap.d.ts.map +1 -1
  157. package/dist/searxng/bootstrap.js +150 -23
  158. package/dist/searxng/bootstrap.js.map +1 -1
  159. package/dist/searxng/process.d.ts +13 -1
  160. package/dist/searxng/process.d.ts.map +1 -1
  161. package/dist/searxng/process.js +52 -2
  162. package/dist/searxng/process.js.map +1 -1
  163. package/dist/server/backend-status.d.ts +11 -0
  164. package/dist/server/backend-status.d.ts.map +1 -0
  165. package/dist/server/backend-status.js +27 -0
  166. package/dist/server/backend-status.js.map +1 -0
  167. package/dist/server.d.ts +17 -0
  168. package/dist/server.d.ts.map +1 -1
  169. package/dist/server.js +228 -91
  170. package/dist/server.js.map +1 -1
  171. package/dist/tools/cache.d.ts +2 -1
  172. package/dist/tools/cache.d.ts.map +1 -1
  173. package/dist/tools/cache.js +56 -1
  174. package/dist/tools/cache.js.map +1 -1
  175. package/dist/tools/fetch.d.ts.map +1 -1
  176. package/dist/tools/fetch.js +16 -1
  177. package/dist/tools/fetch.js.map +1 -1
  178. package/dist/tools/search.d.ts +2 -1
  179. package/dist/tools/search.d.ts.map +1 -1
  180. package/dist/tools/search.js +26 -4
  181. package/dist/tools/search.js.map +1 -1
  182. package/dist/types.d.ts +49 -0
  183. package/dist/types.d.ts.map +1 -1
  184. package/package.json +36 -3
@@ -1,5 +1,58 @@
1
- export function runDaemon(_args) {
2
- process.stderr.write('[wigolo] Daemon mode: Coming in v2\n');
3
- process.stderr.write('[wigolo] For now, use stdio mode: npx @staticn0va/wigolo\n');
1
+ import { getConfig } from '../config.js';
2
+ import { DaemonHttpServer } from '../daemon/http-server.js';
3
+ function log(msg) {
4
+ process.stderr.write(`[wigolo serve] ${msg}\n`);
5
+ }
6
+ export function parseDaemonArgs(args) {
7
+ const config = getConfig();
8
+ let port = config.daemonPort;
9
+ let host = config.daemonHost;
10
+ for (let i = 0; i < args.length; i++) {
11
+ if (args[i] === '--port' && i + 1 < args.length) {
12
+ const parsed = parseInt(args[i + 1], 10);
13
+ if (!isNaN(parsed)) {
14
+ port = parsed;
15
+ }
16
+ i++;
17
+ }
18
+ else if (args[i] === '--host' && i + 1 < args.length) {
19
+ host = args[i + 1];
20
+ i++;
21
+ }
22
+ }
23
+ return { port, host };
24
+ }
25
+ export function runDaemon(args) {
26
+ const parsed = parseDaemonArgs(args);
27
+ log(`Starting daemon on ${parsed.host}:${parsed.port}...`);
28
+ const daemon = new DaemonHttpServer({
29
+ port: parsed.port,
30
+ host: parsed.host,
31
+ });
32
+ daemon.start()
33
+ .then((url) => {
34
+ log(`Daemon running at ${url}`);
35
+ log(`Health check: curl ${url}/health`);
36
+ log(`MCP endpoint: ${url}/mcp (StreamableHTTP)`);
37
+ log(`SSE endpoint: ${url}/sse`);
38
+ log('');
39
+ log('Press Ctrl+C to stop.');
40
+ })
41
+ .catch((err) => {
42
+ log(`Failed to start daemon: ${err instanceof Error ? err.message : String(err)}`);
43
+ process.exit(1);
44
+ });
45
+ const shutdown = async () => {
46
+ log('Shutting down daemon...');
47
+ try {
48
+ await daemon.stop();
49
+ }
50
+ catch (err) {
51
+ log(`Shutdown error: ${err instanceof Error ? err.message : String(err)}`);
52
+ }
53
+ process.exit(0);
54
+ };
55
+ process.on('SIGINT', () => void shutdown());
56
+ process.on('SIGTERM', () => void shutdown());
4
57
  }
5
58
  //# sourceMappingURL=daemon.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAC,KAAe;IACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAC7D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;AACrF,CAAC"}
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/cli/daemon.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Exit code contract:
3
+ * - 0 when all required components OK, or only optional packages (Trafilatura/FlashRank) missing.
4
+ * - 1 when any required component is degraded: Python missing, Playwright browsers missing,
5
+ * SearXNG bootstrap failed/no_runtime, or SearXNG process supposed to be up but isn't.
6
+ */
7
+ export declare function runDoctor(dataDir: string): Promise<number>;
8
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"AAwDA;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgFhE"}
@@ -0,0 +1,153 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { existsSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+ import { getBootstrapState } from '../searxng/bootstrap.js';
5
+ import { isProcessAlive } from '../searxng/process.js';
6
+ function out(line = '') { process.stderr.write(`${line}\n`); }
7
+ function checkPython() {
8
+ const r = spawnSync('python3', ['--version'], { encoding: 'utf-8' });
9
+ if (r.status !== 0 || r.error)
10
+ return { ok: false };
11
+ const match = (r.stdout || r.stderr || '').match(/Python (\d+\.\d+\.\d+)/);
12
+ return { ok: true, version: match?.[1] };
13
+ }
14
+ function checkDocker() {
15
+ const r = spawnSync('docker', ['--version'], { encoding: 'utf-8' });
16
+ if (r.status !== 0 || r.error)
17
+ return { ok: false };
18
+ return { ok: true, version: (r.stdout || '').trim() };
19
+ }
20
+ function checkPlaywright() {
21
+ let installed = false;
22
+ let version;
23
+ try {
24
+ const r = spawnSync('npx', ['playwright', '--version'], { encoding: 'utf-8', timeout: 5000 });
25
+ if (r.status === 0) {
26
+ installed = true;
27
+ const m = r.stdout.match(/(\d+\.\d+\.\d+)/);
28
+ version = m?.[1];
29
+ }
30
+ }
31
+ catch { /* ignore */ }
32
+ // Browser detection — light check
33
+ const probe = (browser) => {
34
+ const r = spawnSync('npx', ['playwright', 'install', '--dry-run', browser], { encoding: 'utf-8', timeout: 5000 });
35
+ return r.status === 0 && !/is not installed/i.test(r.stdout + r.stderr);
36
+ };
37
+ return { installed, version, browsers: { chromium: probe('chromium'), firefox: probe('firefox'), webkit: probe('webkit') } };
38
+ }
39
+ function checkPyPackage(name) {
40
+ const r = spawnSync('python3', ['-c', `import ${name}; print(${name}.__version__)`], { encoding: 'utf-8' });
41
+ if (r.status !== 0 || r.error)
42
+ return { ok: false };
43
+ return { ok: true, version: (r.stdout || '').trim() };
44
+ }
45
+ function humanRetry(nextRetryAt) {
46
+ if (!nextRetryAt)
47
+ return 'not scheduled';
48
+ const when = new Date(nextRetryAt);
49
+ const mins = Math.round((when.getTime() - Date.now()) / 60_000);
50
+ if (mins < 0)
51
+ return `${nextRetryAt} (ready now)`;
52
+ if (mins < 60)
53
+ return `${nextRetryAt} (in ${mins} minutes)`;
54
+ const hrs = Math.round(mins / 60);
55
+ return `${nextRetryAt} (in ${hrs} hours)`;
56
+ }
57
+ /**
58
+ * Exit code contract:
59
+ * - 0 when all required components OK, or only optional packages (Trafilatura/FlashRank) missing.
60
+ * - 1 when any required component is degraded: Python missing, Playwright browsers missing,
61
+ * SearXNG bootstrap failed/no_runtime, or SearXNG process supposed to be up but isn't.
62
+ */
63
+ export async function runDoctor(dataDir) {
64
+ let degraded = false;
65
+ out(`[wigolo doctor] Data dir: ${dataDir}`);
66
+ out('');
67
+ const py = checkPython();
68
+ const dk = checkDocker();
69
+ out('[wigolo doctor] Runtime:');
70
+ out(` Python 3: ${py.ok ? `available (${py.version ?? 'unknown'})` : 'not available'}`);
71
+ out(` Docker: ${dk.ok ? `available (${dk.version})` : 'not available'}`);
72
+ if (!py.ok && !dk.ok)
73
+ degraded = true;
74
+ out('');
75
+ const pw = checkPlaywright();
76
+ out('[wigolo doctor] Playwright:');
77
+ out(` Installation: ${pw.installed ? `installed${pw.version ? ` (v${pw.version})` : ''}` : 'not installed'}`);
78
+ out(` Browsers: chromium ${pw.browsers.chromium ? 'OK' : 'missing'} firefox ${pw.browsers.firefox ? 'OK' : 'missing'} webkit ${pw.browsers.webkit ? 'OK' : 'missing'}`);
79
+ if (!pw.installed || !pw.browsers.chromium)
80
+ degraded = true;
81
+ out('');
82
+ const traf = checkPyPackage('trafilatura');
83
+ const flash = checkPyPackage('flashrank');
84
+ out('[wigolo doctor] Optional Python packages:');
85
+ out(` Trafilatura: ${traf.ok ? `installed (v${traf.version})` : 'not installed'}`);
86
+ out(` FlashRank: ${flash.ok ? `installed (v${flash.version})` : 'not installed'}`);
87
+ out('');
88
+ const state = getBootstrapState(dataDir);
89
+ out('[wigolo doctor] SearXNG install:');
90
+ if (!state) {
91
+ out(' status: not bootstrapped — run `npx @staticn0va/wigolo warmup`');
92
+ degraded = true;
93
+ }
94
+ else if (state.status === 'ready') {
95
+ out(` status: ready`);
96
+ out(` path: ${state.searxngPath ?? 'unknown'}`);
97
+ }
98
+ else {
99
+ out(` status: ${state.status}`);
100
+ if (state.attempts !== undefined)
101
+ out(` attempts: ${state.attempts} / 3`);
102
+ if (state.lastAttemptAt)
103
+ out(` lastAttemptAt: ${state.lastAttemptAt}`);
104
+ if (state.nextRetryAt || state.status === 'failed')
105
+ out(` nextRetryAt: ${humanRetry(state.nextRetryAt)}`);
106
+ if (state.lastError?.command)
107
+ out(` command: ${state.lastError.command}`);
108
+ if (state.lastError?.exitCode !== undefined)
109
+ out(` exit code: ${state.lastError.exitCode}`);
110
+ if (state.lastError?.message)
111
+ out(` message: ${state.lastError.message}`);
112
+ if (state.lastError?.stderr) {
113
+ out(' stderr:');
114
+ for (const line of state.lastError.stderr.split('\n').slice(0, 20))
115
+ out(` ${line}`);
116
+ }
117
+ degraded = true;
118
+ }
119
+ out('');
120
+ const lockPath = join(dataDir, 'searxng.lock');
121
+ if (existsSync(lockPath)) {
122
+ try {
123
+ const lock = JSON.parse(readFileSync(lockPath, 'utf-8'));
124
+ if (lock.pid && isProcessAlive(lock.pid)) {
125
+ out(`[wigolo doctor] SearXNG process: running (pid ${lock.pid}, port ${lock.port ?? '?'})`);
126
+ }
127
+ else {
128
+ out('[wigolo doctor] SearXNG process: lock exists but pid is dead');
129
+ if (state?.status === 'ready')
130
+ degraded = true;
131
+ }
132
+ }
133
+ catch {
134
+ out('[wigolo doctor] SearXNG process: lock file unparseable');
135
+ }
136
+ }
137
+ else {
138
+ out('[wigolo doctor] SearXNG process: not running');
139
+ if (state?.status === 'ready')
140
+ degraded = true;
141
+ }
142
+ if (state?.status === 'failed') {
143
+ out('');
144
+ out('[wigolo doctor] Recovery:');
145
+ if (state.nextRetryAt)
146
+ out(` - Wait until next auto-retry (${humanRetry(state.nextRetryAt)}), or`);
147
+ out(` - Force retry now: npx @staticn0va/wigolo warmup --force`);
148
+ }
149
+ out('');
150
+ out(`[wigolo doctor] Overall: ${degraded ? 'DEGRADED' : 'OK'}`);
151
+ return degraded ? 1 : 0;
152
+ }
153
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare function runHealthCheck(): void;
1
+ export declare function runHealthCheck(): Promise<number>;
2
2
  //# sourceMappingURL=health.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,IAAI,IAAI,CAGrC"}
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAMA,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAyCtD"}
@@ -1,5 +1,43 @@
1
- export function runHealthCheck() {
2
- process.stderr.write('[wigolo] Health check: Coming in v2\n');
3
- process.stderr.write('[wigolo] Daemon mode is required for health checks.\n');
1
+ import { getConfig } from '../config.js';
2
+ function log(msg) {
3
+ process.stderr.write(`[wigolo health] ${msg}\n`);
4
+ }
5
+ export async function runHealthCheck() {
6
+ const config = getConfig();
7
+ const host = config.daemonHost;
8
+ const port = config.daemonPort;
9
+ const url = `http://${host}:${port}/health`;
10
+ try {
11
+ const response = await fetch(url, {
12
+ signal: AbortSignal.timeout(5000),
13
+ });
14
+ if (!response.ok) {
15
+ log(`Daemon returned HTTP ${response.status}`);
16
+ const text = await response.text().catch(() => '');
17
+ if (text)
18
+ log(text);
19
+ return 1;
20
+ }
21
+ const report = await response.json();
22
+ log(`Status: ${report.status}`);
23
+ log(`SearXNG: ${report.searxng}`);
24
+ log(`Browsers: ${report.browsers}`);
25
+ log(`Cache: ${report.cache}`);
26
+ log(`Uptime: ${report.uptime_seconds}s`);
27
+ log('');
28
+ log(JSON.stringify(report, null, 2));
29
+ return report.status === 'healthy' ? 0 : 1;
30
+ }
31
+ catch (err) {
32
+ const message = err instanceof Error ? err.message : String(err);
33
+ if (message.includes('ECONNREFUSED') || message.includes('fetch failed') || message.includes('timed out')) {
34
+ log(`Daemon is not running at ${host}:${port}`);
35
+ log(`Start it with: npx @staticn0va/wigolo serve`);
36
+ }
37
+ else {
38
+ log(`Health check failed: ${message}`);
39
+ }
40
+ return 1;
41
+ }
4
42
  }
5
43
  //# sourceMappingURL=health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC9D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;AAChF,CAAC"}
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/cli/health.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,SAAS,GAAG,CAAC,GAAW;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC;IAC/B,MAAM,GAAG,GAAG,UAAU,IAAI,IAAI,IAAI,SAAS,CAAC;IAE5C,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,GAAG,CAAC,wBAAwB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAC/C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACpB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAErC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QAChC,GAAG,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,GAAG,CAAC,aAAa,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QACpC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QAC9B,GAAG,CAAC,WAAW,MAAM,CAAC,cAAc,GAAG,CAAC,CAAC;QACzC,GAAG,CAAC,EAAE,CAAC,CAAC;QACR,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAErC,OAAO,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAEjE,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC1G,GAAG,CAAC,4BAA4B,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;YAChD,GAAG,CAAC,6CAA6C,CAAC,CAAC;QACrD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;QACzC,CAAC;QAED,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
@@ -1,4 +1,4 @@
1
- export type Command = 'mcp' | 'warmup' | 'serve' | 'health';
1
+ export type Command = 'mcp' | 'warmup' | 'serve' | 'health' | 'doctor' | 'auth' | 'plugin' | 'shell';
2
2
  export interface ParsedCommand {
3
3
  command: Command;
4
4
  args: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAQ1D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErG,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAID,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAQ1D"}
package/dist/cli/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const KNOWN_COMMANDS = new Set(['warmup', 'serve', 'health']);
1
+ const KNOWN_COMMANDS = new Set(['warmup', 'serve', 'health', 'doctor', 'auth', 'plugin', 'shell']);
2
2
  export function parseCommand(argv) {
3
3
  const first = argv[0];
4
4
  if (first && KNOWN_COMMANDS.has(first)) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAOA,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEnF,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEtB,IAAI,KAAK,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,KAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAOA,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAExH,MAAM,UAAU,YAAY,CAAC,IAAc;IACzC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEtB,IAAI,KAAK,IAAI,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,OAAO,EAAE,KAAgB,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACtC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function runPluginAdd(gitUrl: string): void;
2
+ export declare function runPluginList(): void;
3
+ export declare function runPluginRemove(name: string): void;
4
+ export declare function runPluginCommand(args: string[]): void;
5
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/cli/plugin.ts"],"names":[],"mappings":"AAgDA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CA+CjD;AAED,wBAAgB,aAAa,IAAI,IAAI,CAwDpC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAoBlD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAkCrD"}
@@ -0,0 +1,188 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { existsSync, readdirSync, readFileSync, mkdirSync, rmSync, statSync } from 'node:fs';
3
+ import { join, basename } from 'node:path';
4
+ import { getConfig } from '../config.js';
5
+ function log(msg) {
6
+ process.stderr.write(`[wigolo plugin] ${msg}\n`);
7
+ }
8
+ function extractRepoName(gitUrl) {
9
+ // Handle SSH-style URLs: git@github.com:user/repo.git
10
+ if (gitUrl.includes(':') && !gitUrl.includes('://')) {
11
+ const parts = gitUrl.split(':');
12
+ const pathPart = parts[parts.length - 1];
13
+ const name = basename(pathPart, '.git');
14
+ if (!name)
15
+ throw new Error('could not extract repo name from URL');
16
+ return name;
17
+ }
18
+ // Handle HTTPS URLs
19
+ try {
20
+ const url = new URL(gitUrl);
21
+ const pathParts = url.pathname.split('/').filter(Boolean);
22
+ if (pathParts.length === 0) {
23
+ throw new Error('could not extract repo name from URL');
24
+ }
25
+ const last = pathParts[pathParts.length - 1];
26
+ return last.endsWith('.git') ? last.slice(0, -4) : last;
27
+ }
28
+ catch (err) {
29
+ if (err instanceof TypeError) {
30
+ throw new Error(`invalid git URL: ${gitUrl}`);
31
+ }
32
+ throw err;
33
+ }
34
+ }
35
+ function validatePluginName(name) {
36
+ if (!name || name.trim().length === 0) {
37
+ throw new Error('plugin name is required');
38
+ }
39
+ if (name.includes('/') || name.includes('\\') || name.includes('..')) {
40
+ throw new Error(`invalid plugin name: ${name} (must not contain path separators or "..")`);
41
+ }
42
+ if (name.startsWith('/')) {
43
+ throw new Error(`invalid plugin name: ${name} (must not be an absolute path)`);
44
+ }
45
+ }
46
+ export function runPluginAdd(gitUrl) {
47
+ if (!gitUrl || gitUrl.trim().length === 0) {
48
+ throw new Error('git url is required');
49
+ }
50
+ const config = getConfig();
51
+ const pluginsDir = config.pluginsDir;
52
+ const repoName = extractRepoName(gitUrl);
53
+ const targetDir = join(pluginsDir, repoName);
54
+ if (existsSync(targetDir)) {
55
+ throw new Error(`plugin "${repoName}" already exists at ${targetDir}. ` +
56
+ `Remove it first: wigolo plugin remove ${repoName}`);
57
+ }
58
+ mkdirSync(pluginsDir, { recursive: true });
59
+ log(`cloning ${gitUrl} into ${targetDir}...`);
60
+ try {
61
+ execFileSync('git', ['clone', '--depth', '1', gitUrl, repoName], {
62
+ cwd: pluginsDir,
63
+ stdio: 'pipe',
64
+ timeout: 60000,
65
+ });
66
+ }
67
+ catch (err) {
68
+ const message = err instanceof Error ? err.message : String(err);
69
+ throw new Error(`clone failed: ${message}`);
70
+ }
71
+ log(`plugin "${repoName}" installed successfully`);
72
+ // Check for package.json with main field
73
+ const pkgPath = join(targetDir, 'package.json');
74
+ if (!existsSync(pkgPath)) {
75
+ log('WARNING: plugin has no package.json -- it may not load correctly');
76
+ }
77
+ else {
78
+ try {
79
+ const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
80
+ if (!pkg.main) {
81
+ log('WARNING: package.json has no "main" field -- plugin may not load');
82
+ }
83
+ }
84
+ catch {
85
+ log('WARNING: package.json is not valid JSON');
86
+ }
87
+ }
88
+ }
89
+ export function runPluginList() {
90
+ const config = getConfig();
91
+ const pluginsDir = config.pluginsDir;
92
+ if (!existsSync(pluginsDir)) {
93
+ log('no plugins installed');
94
+ return;
95
+ }
96
+ let entries;
97
+ try {
98
+ entries = readdirSync(pluginsDir);
99
+ }
100
+ catch {
101
+ log('no plugins installed (could not read plugins directory)');
102
+ return;
103
+ }
104
+ const plugins = [];
105
+ for (const entry of entries) {
106
+ const dir = join(pluginsDir, entry);
107
+ let stat;
108
+ try {
109
+ stat = statSync(dir);
110
+ }
111
+ catch {
112
+ continue;
113
+ }
114
+ if (!stat.isDirectory() && !stat.isSymbolicLink())
115
+ continue;
116
+ let name = entry;
117
+ let version = 'unknown';
118
+ try {
119
+ const pkg = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf-8'));
120
+ name = pkg.name ?? entry;
121
+ version = pkg.version ?? 'unknown';
122
+ }
123
+ catch {
124
+ // package.json missing or malformed -- use directory name
125
+ }
126
+ plugins.push({ name, version, dir });
127
+ }
128
+ if (plugins.length === 0) {
129
+ log('no plugins installed');
130
+ return;
131
+ }
132
+ log(`installed plugins (${plugins.length}):\n`);
133
+ for (const p of plugins) {
134
+ process.stderr.write(` ${p.name} (${p.version})\n`);
135
+ process.stderr.write(` ${p.dir}\n\n`);
136
+ }
137
+ }
138
+ export function runPluginRemove(name) {
139
+ validatePluginName(name);
140
+ const config = getConfig();
141
+ const pluginsDir = config.pluginsDir;
142
+ const targetDir = join(pluginsDir, name);
143
+ if (!existsSync(targetDir)) {
144
+ throw new Error(`plugin "${name}" not found at ${targetDir}`);
145
+ }
146
+ log(`removing plugin "${name}"...`);
147
+ try {
148
+ rmSync(targetDir, { recursive: true, force: true });
149
+ }
150
+ catch (err) {
151
+ const message = err instanceof Error ? err.message : String(err);
152
+ throw new Error(`remove "${name}" failed: ${message}`);
153
+ }
154
+ log(`plugin "${name}" removed successfully`);
155
+ }
156
+ export function runPluginCommand(args) {
157
+ const subcommand = args[0];
158
+ switch (subcommand) {
159
+ case 'add': {
160
+ const gitUrl = args[1];
161
+ if (!gitUrl) {
162
+ process.stderr.write('Usage: wigolo plugin add <git-url>\n');
163
+ return;
164
+ }
165
+ runPluginAdd(gitUrl);
166
+ break;
167
+ }
168
+ case 'list':
169
+ runPluginList();
170
+ break;
171
+ case 'remove': {
172
+ const name = args[1];
173
+ if (!name) {
174
+ process.stderr.write('Usage: wigolo plugin remove <name>\n');
175
+ return;
176
+ }
177
+ runPluginRemove(name);
178
+ break;
179
+ }
180
+ default:
181
+ process.stderr.write('Usage: wigolo plugin <add|list|remove>\n\n' +
182
+ ' add <git-url> Clone a plugin repository\n' +
183
+ ' list List installed plugins\n' +
184
+ ' remove <name> Remove an installed plugin\n');
185
+ break;
186
+ }
187
+ }
188
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../src/cli/plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function runShell(args: string[]): Promise<void>;
2
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/cli/shell.ts"],"names":[],"mappings":"AAoBA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuE5D"}
@@ -0,0 +1,86 @@
1
+ import { join } from 'node:path';
2
+ import { mkdirSync } from 'node:fs';
3
+ import { SmartRouter } from '../fetch/router.js';
4
+ import { BrowserPool } from '../fetch/browser-pool.js';
5
+ import { httpFetch } from '../fetch/http-client.js';
6
+ import { initDatabase, closeDatabase } from '../cache/db.js';
7
+ import { SearxngClient } from '../search/searxng.js';
8
+ import { DuckDuckGoEngine } from '../search/engines/duckduckgo.js';
9
+ import { BingEngine } from '../search/engines/bing.js';
10
+ import { StartpageEngine } from '../search/engines/startpage.js';
11
+ import { resolveSearchBackend, getBootstrapState } from '../searxng/bootstrap.js';
12
+ import { SearxngProcess } from '../searxng/process.js';
13
+ import { BackendStatus } from '../server/backend-status.js';
14
+ import { getConfig } from '../config.js';
15
+ import { createLogger } from '../logger.js';
16
+ import { startShell } from '../repl/shell.js';
17
+ const log = createLogger('cli');
18
+ export async function runShell(args) {
19
+ const config = getConfig();
20
+ const jsonMode = args.includes('--json');
21
+ mkdirSync(config.dataDir, { recursive: true });
22
+ initDatabase(join(config.dataDir, 'wigolo.db'));
23
+ const httpClient = {
24
+ fetch: (url, options) => httpFetch(url, options),
25
+ };
26
+ const browserPool = new BrowserPool();
27
+ const router = new SmartRouter(httpClient, browserPool);
28
+ const backendStatus = new BackendStatus();
29
+ const searchEngines = [
30
+ new BingEngine(),
31
+ new DuckDuckGoEngine(),
32
+ new StartpageEngine(),
33
+ ];
34
+ let searxngProcess = null;
35
+ try {
36
+ const backend = await resolveSearchBackend();
37
+ if (backend.type === 'external' && backend.url) {
38
+ searchEngines.unshift(new SearxngClient(backend.url));
39
+ backendStatus.markHealthy();
40
+ log.info('shell using external SearXNG', { url: backend.url });
41
+ }
42
+ else if (backend.type === 'native' && backend.searxngPath) {
43
+ const state = getBootstrapState(config.dataDir);
44
+ if (state?.status === 'ready') {
45
+ searxngProcess = new SearxngProcess(backend.searxngPath, config.dataDir, {
46
+ onUnhealthy: (reason) => {
47
+ backendStatus.markUnhealthy(reason);
48
+ const idx = searchEngines.findIndex(e => e.name === 'searxng');
49
+ if (idx >= 0)
50
+ searchEngines.splice(idx, 1);
51
+ log.warn('SearXNG unhealthy in shell', { reason });
52
+ },
53
+ onHealthy: () => {
54
+ const url = searxngProcess?.getUrl();
55
+ if (!url)
56
+ return;
57
+ backendStatus.markHealthy();
58
+ if (!searchEngines.some(e => e.name === 'searxng')) {
59
+ searchEngines.unshift(new SearxngClient(url));
60
+ }
61
+ },
62
+ });
63
+ const url = await searxngProcess.start();
64
+ if (url) {
65
+ searchEngines.unshift(new SearxngClient(url));
66
+ backendStatus.markHealthy();
67
+ log.info('SearXNG ready for shell', { url });
68
+ }
69
+ }
70
+ }
71
+ }
72
+ catch (err) {
73
+ log.warn('SearXNG setup failed for shell, using direct scraping', { error: String(err) });
74
+ backendStatus.markUnhealthy(`SearXNG setup failed: ${String(err)}`);
75
+ }
76
+ try {
77
+ await startShell({ router, engines: searchEngines, backendStatus }, { jsonMode });
78
+ }
79
+ finally {
80
+ if (searxngProcess)
81
+ await searxngProcess.stop();
82
+ await browserPool.shutdown();
83
+ closeDatabase();
84
+ }
85
+ }
86
+ //# sourceMappingURL=shell.js.map