yaver-cli 1.99.16 → 1.99.25

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yaver-cli",
3
- "version": "1.99.16",
3
+ "version": "1.99.25",
4
4
  "mcpName": "io.github.kivanccakmak/yaver",
5
5
  "description": "Unified npm bootstrap for the Yaver agent, SDK injection, and local-first developer runtime",
6
6
  "bin": {
package/src/analyzer.js CHANGED
@@ -16,6 +16,7 @@ const PURE_JS_PACKAGES = new Set([
16
16
  '@react-navigation/material-top-tabs',
17
17
  'react-native-web', 'react-dom',
18
18
  '@expo/metro-runtime', 'expo-router', 'expo-splash-screen', 'expo-status-bar',
19
+ 'three', '@react-three/fiber', '@react-three/drei',
19
20
  ]);
20
21
 
21
22
  // Packages that LOOK native (react-native-*) but are pure JS
@@ -0,0 +1,173 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { spawnSync } = require('child_process');
4
+
5
+ const FEEDBACK_HELP = `
6
+ yaver feedback — install the Yaver Feedback SDK into the current project
7
+
8
+ Commands:
9
+ init [--platform <p>] Install the right feedback SDK for this project
10
+ Platforms: web, react-native, expo, flutter
11
+ (autodetected from package.json / pubspec.yaml)
12
+
13
+ The web and mobile SDKs are separate packages on purpose:
14
+ yaver-feedback-web — browsers (screen recording, voice, shake-free trigger)
15
+ yaver-feedback-react-native — RN / Expo (shake-to-report, BlackBox, native recording)
16
+ yaver_feedback — Flutter (NavigatorObserver, Flutter error handler)
17
+
18
+ Other feedback subcommands (setup, list, etc.) are forwarded to the Go agent.
19
+ `;
20
+
21
+ function detectPackageManager(dir) {
22
+ if (fs.existsSync(path.join(dir, 'bun.lockb')) || fs.existsSync(path.join(dir, 'bun.lock'))) return 'bun';
23
+ if (fs.existsSync(path.join(dir, 'pnpm-lock.yaml'))) return 'pnpm';
24
+ if (fs.existsSync(path.join(dir, 'yarn.lock'))) return 'yarn';
25
+ return 'npm';
26
+ }
27
+
28
+ function jsInstallCommand(pm, pkg) {
29
+ switch (pm) {
30
+ case 'bun': return ['bun', ['add', pkg]];
31
+ case 'pnpm': return ['pnpm', ['add', pkg]];
32
+ case 'yarn': return ['yarn', ['add', pkg]];
33
+ default: return ['npm', ['install', pkg]];
34
+ }
35
+ }
36
+
37
+ function detectPlatform(dir) {
38
+ if (fs.existsSync(path.join(dir, 'pubspec.yaml'))) return 'flutter';
39
+
40
+ const pkgPath = path.join(dir, 'package.json');
41
+ if (!fs.existsSync(pkgPath)) return null;
42
+
43
+ let pkg;
44
+ try {
45
+ pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
46
+ } catch {
47
+ return null;
48
+ }
49
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
50
+
51
+ if (deps.expo) return 'expo';
52
+ if (deps['react-native']) return 'react-native';
53
+ if (deps.next || deps.vite || deps.react || deps.vue || deps.svelte || deps['@angular/core']) return 'web';
54
+
55
+ return null;
56
+ }
57
+
58
+ function nextSteps(platform) {
59
+ switch (platform) {
60
+ case 'web':
61
+ return [
62
+ 'Call YaverFeedback.init({ trigger: "floating-button" }) in your app entry (dev mode only).',
63
+ 'On first click, the SDK prompts the user to sign in via its built-in modal',
64
+ '(Apple / Google / GitHub / GitLab / Microsoft / email).',
65
+ 'Make sure `yaver serve` is running on your dev machine so feedback has somewhere to land.',
66
+ ];
67
+ case 'expo':
68
+ case 'react-native':
69
+ return [
70
+ 'Wrap your dev app with YaverFeedback.init(...) in a debug-only entry block.',
71
+ 'Add <FeedbackModal /> (or the floating button) to your root component.',
72
+ 'Shake the device / simulator to trigger the report sheet.',
73
+ ];
74
+ case 'flutter':
75
+ return [
76
+ 'Call YaverFeedback.init(...) in main() before runApp().',
77
+ 'Add the YaverFeedback overlay or button to your app root.',
78
+ 'Use wrapFlutterErrorHandler() if you want automatic error capture.',
79
+ ];
80
+ default:
81
+ return [];
82
+ }
83
+ }
84
+
85
+ function platformPackage(platform) {
86
+ switch (platform) {
87
+ case 'web': return { pm: null, pkg: 'yaver-feedback-web' };
88
+ case 'expo':
89
+ case 'react-native': return { pm: null, pkg: 'yaver-feedback-react-native' };
90
+ case 'flutter': return { pm: 'flutter', pkg: 'yaver_feedback' };
91
+ default: return null;
92
+ }
93
+ }
94
+
95
+ function parsePlatformFlag(args) {
96
+ const i = args.indexOf('--platform');
97
+ if (i >= 0 && args[i + 1]) return args[i + 1];
98
+ return null;
99
+ }
100
+
101
+ async function feedbackInit(args) {
102
+ const dir = process.cwd();
103
+ let platform = parsePlatformFlag(args);
104
+ const autodetected = !platform;
105
+ if (!platform) platform = detectPlatform(dir);
106
+
107
+ if (!platform) {
108
+ console.error('❌ Could not detect a supported project in this directory.');
109
+ console.error(' Run from a folder with package.json (web / RN / Expo) or pubspec.yaml (Flutter).');
110
+ console.error(' Or force it: yaver feedback init --platform <web|react-native|expo|flutter>');
111
+ process.exit(1);
112
+ }
113
+
114
+ const target = platformPackage(platform);
115
+ if (!target) {
116
+ console.error(`❌ Unknown platform: ${platform}`);
117
+ console.error(' Supported: web, react-native, expo, flutter');
118
+ process.exit(1);
119
+ }
120
+
121
+ if (autodetected) {
122
+ console.log(`🔍 Detected platform: ${platform}`);
123
+ }
124
+
125
+ let cmd, cmdArgs;
126
+ if (target.pm === 'flutter') {
127
+ cmd = 'flutter';
128
+ cmdArgs = ['pub', 'add', target.pkg];
129
+ } else {
130
+ const pm = detectPackageManager(dir);
131
+ [cmd, cmdArgs] = jsInstallCommand(pm, target.pkg);
132
+ console.log(`📦 Package manager: ${pm}`);
133
+ }
134
+
135
+ console.log(`➡️ ${cmd} ${cmdArgs.join(' ')}\n`);
136
+
137
+ const res = spawnSync(cmd, cmdArgs, { stdio: 'inherit', cwd: dir });
138
+ if (res.error) {
139
+ console.error(`\n❌ Failed to run ${cmd}: ${res.error.message}`);
140
+ process.exit(1);
141
+ }
142
+ if (res.status !== 0) {
143
+ process.exit(res.status || 1);
144
+ }
145
+
146
+ console.log(`\n✅ Installed ${target.pkg}\n`);
147
+ const steps = nextSteps(platform);
148
+ if (steps.length > 0) {
149
+ console.log('Next steps:');
150
+ for (const s of steps) console.log(` • ${s}`);
151
+ console.log('');
152
+ }
153
+ }
154
+
155
+ async function feedback(args) {
156
+ const sub = args[0];
157
+
158
+ if (!sub || sub === '--help' || sub === '-h' || sub === 'help') {
159
+ console.log(FEEDBACK_HELP);
160
+ process.exit(0);
161
+ }
162
+
163
+ if (sub === 'init') {
164
+ await feedbackInit(args.slice(1));
165
+ return;
166
+ }
167
+
168
+ // Forward everything else (setup, list, ...) to the Go agent.
169
+ const { runAgentCommand } = require('../agent-runtime');
170
+ await runAgentCommand(['feedback', ...args]);
171
+ }
172
+
173
+ module.exports = { feedback };
package/src/index.js CHANGED
@@ -7,6 +7,7 @@ const { devices } = require('./commands/devices');
7
7
  const { modules } = require('./commands/modules');
8
8
  const { reset } = require('./commands/reset');
9
9
  const { status } = require('./commands/status');
10
+ const { feedback } = require('./commands/feedback');
10
11
 
11
12
  const PUSH_HELP = `
12
13
  yaver push — Push existing React Native projects to the Yaver mobile host
@@ -48,6 +49,13 @@ Push-to-device commands:
48
49
  yaver push reset Clear pushed bundle on the selected device
49
50
  yaver push status Show project + device push status
50
51
 
52
+ Feedback SDK commands (web and mobile SDKs are separate packages):
53
+ yaver feedback init Install the right feedback SDK for this project
54
+ yaver feedback init --platform web Force web (yaver-feedback-web)
55
+ yaver feedback init --platform react-native Force RN (yaver-feedback-react-native)
56
+ yaver feedback init --platform expo Expo (yaver-feedback-react-native)
57
+ yaver feedback init --platform flutter Flutter (yaver_feedback)
58
+
51
59
  Compatibility:
52
60
  yaver-push <command> Legacy alias for the push subcommands above
53
61
 
@@ -134,6 +142,14 @@ async function runUnified(args) {
134
142
  return;
135
143
  }
136
144
 
145
+ if (command === 'feedback') {
146
+ // `feedback init` is handled locally in JS so web devs who never install
147
+ // the Go binary can still wire up the SDK. Other subcommands (list, show,
148
+ // fix, delete) fall through to the Go agent inside feedback() itself.
149
+ await feedback(args.slice(1));
150
+ return;
151
+ }
152
+
137
153
  if (command === 'npm-agent-info') {
138
154
  const info = resolveAgentInfo();
139
155
  console.log(JSON.stringify(info, null, 2));
@@ -12,6 +12,12 @@ const fs = require("fs");
12
12
  const os = require("os");
13
13
  const path = require("path");
14
14
 
15
+ const CODING_RUNNER_BOOTSTRAP = [
16
+ { command: "claude", pkg: "@anthropic-ai/claude-code", label: "Claude Code" },
17
+ { command: "codex", pkg: "@openai/codex", label: "OpenAI Codex" },
18
+ { command: "opencode", pkg: "opencode-ai", label: "OpenCode" },
19
+ ];
20
+
15
21
  function envEnabled(name) {
16
22
  const raw = String(process.env[name] || "").trim().toLowerCase();
17
23
  return raw === "1" || raw === "true" || raw === "yes";
@@ -28,6 +34,36 @@ function log(message) {
28
34
  console.error(`[yaver postinstall] ${message}`);
29
35
  }
30
36
 
37
+ function commandExists(name) {
38
+ try {
39
+ execSync(`command -v ${name}`, { stdio: ["ignore", "pipe", "ignore"] });
40
+ return true;
41
+ } catch (_) {
42
+ return false;
43
+ }
44
+ }
45
+
46
+ function installMissingCodingRunners() {
47
+ const missing = CODING_RUNNER_BOOTSTRAP.filter((entry) => !commandExists(entry.command));
48
+ if (missing.length === 0) {
49
+ log("Claude Code, Codex, and OpenCode already exist on PATH.");
50
+ return;
51
+ }
52
+
53
+ const npmCmd = (process.env.npm_execpath || "npm").trim() || "npm";
54
+ const packages = missing.map((entry) => entry.pkg);
55
+ const labels = missing.map((entry) => entry.label).join(", ");
56
+ try {
57
+ execSync(
58
+ `"${npmCmd}" install -g --no-fund --no-audit ${packages.join(" ")}`,
59
+ { stdio: "inherit" },
60
+ );
61
+ log(`Installed missing coding runners: ${labels}.`);
62
+ } catch (error) {
63
+ log(`Skipping coding runner bootstrap: ${error.message}`);
64
+ }
65
+ }
66
+
31
67
  // Make sure `yaver` resolves on PATH for the next shell session. npm's
32
68
  // global prefix (e.g. ~/.npm-global/bin) is not on PATH by default on
33
69
  // most Linux distros — so `npm install -g yaver-cli` succeeds but
@@ -101,6 +137,9 @@ async function main() {
101
137
  return;
102
138
  }
103
139
  if (envEnabled("YAVER_SKIP_POSTINSTALL_MOBILE")) {
140
+ if (!envEnabled("YAVER_SKIP_POSTINSTALL_RUNNERS")) {
141
+ installMissingCodingRunners();
142
+ }
104
143
  return;
105
144
  }
106
145
 
@@ -110,6 +149,10 @@ async function main() {
110
149
  } catch (error) {
111
150
  log(`Skipping mobile bootstrap: ${error.message}`);
112
151
  }
152
+
153
+ if (!envEnabled("YAVER_SKIP_POSTINSTALL_RUNNERS")) {
154
+ installMissingCodingRunners();
155
+ }
113
156
  }
114
157
 
115
158
  main()