vipcare 0.3.28 → 0.3.30

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/bin/vip.js CHANGED
@@ -36,9 +36,19 @@ function spinner(msg) {
36
36
  return () => { clearInterval(id); process.stdout.write(`\r${' '.repeat(msg.length + 4)}\r`); };
37
37
  }
38
38
 
39
+ function saveRawSource(personSlug, sourceName, content) {
40
+ const rawDir = path.join(getProfilesDir(), '.raw', personSlug);
41
+ fs.mkdirSync(rawDir, { recursive: true });
42
+ const safeName = sourceName.replace(/[^\w.-]/g, '_').substring(0, 80);
43
+ const filePath = path.join(rawDir, `${safeName}.md`);
44
+ fs.writeFileSync(filePath, content, 'utf-8');
45
+ return filePath;
46
+ }
47
+
39
48
  function gatherData(person) {
40
49
  const rawParts = [];
41
50
  const sources = [];
51
+ const personSlug = slugify(person.name || 'unknown');
42
52
 
43
53
  if (person.twitterHandle) {
44
54
  console.log(c.dim(` Fetching Twitter @${person.twitterHandle}...`));
@@ -46,6 +56,7 @@ function gatherData(person) {
46
56
  if (data?.rawOutput) {
47
57
  rawParts.push(`=== Twitter (@${person.twitterHandle}) ===\n${data.rawOutput}`);
48
58
  sources.push(`https://twitter.com/${person.twitterHandle}`);
59
+ saveRawSource(personSlug, `twitter_${person.twitterHandle}`, `# Twitter @${person.twitterHandle}\n\nSource: https://twitter.com/${person.twitterHandle}\nFetched: ${new Date().toISOString()}\n\n${data.rawOutput}`);
49
60
  } else if (!twitter.isAvailable()) {
50
61
  console.log(c.yellow(' (bird CLI not found, skipping Twitter)'));
51
62
  }
@@ -56,6 +67,12 @@ function gatherData(person) {
56
67
  if (person.rawSnippets.length) {
57
68
  rawParts.push('=== Web Search Results ===');
58
69
  rawParts.push(...person.rawSnippets);
70
+ // Save each snippet as a raw source file
71
+ person.rawSnippets.forEach((snippet, i) => {
72
+ const url = person.otherUrls?.[i] || `search_result_${i}`;
73
+ const safeName = url.replace(/https?:\/\//, '').replace(/[^\w.-]/g, '_').substring(0, 60);
74
+ saveRawSource(personSlug, safeName, `# Search Result\n\nSource: ${url}\nFetched: ${new Date().toISOString()}\n\n${snippet}`);
75
+ });
59
76
  }
60
77
 
61
78
  if (rawParts.length < 2 && person.name) {
@@ -64,9 +81,12 @@ function gatherData(person) {
64
81
  for (const r of results) {
65
82
  rawParts.push(`${r.title}\n${r.body}`);
66
83
  if (!sources.includes(r.url)) sources.push(r.url);
84
+ const safeName = r.url.replace(/https?:\/\//, '').replace(/[^\w.-]/g, '_').substring(0, 60);
85
+ saveRawSource(personSlug, safeName, `# ${r.title}\n\nSource: ${r.url}\nFetched: ${new Date().toISOString()}\n\n${r.body}`);
67
86
  }
68
87
  }
69
88
 
89
+ console.log(c.dim(` Raw data saved to ${path.join(getProfilesDir(), '.raw', personSlug)}/`));
70
90
  return [rawParts.join('\n\n'), sources];
71
91
  }
72
92
 
@@ -83,13 +103,14 @@ program.name('vip').description('VIP Profile Builder - Auto-build VIP person pro
83
103
  // --- add ---
84
104
  program.command('add')
85
105
  .description('Add a new VIP profile')
86
- .argument('<query>', 'Name or URL')
106
+ .argument('<query...>', 'Name (multiple words) or URL')
87
107
  .option('-c, --company <company>', 'Company name')
88
108
  .option('--dry-run', 'Print without saving')
89
109
  .option('--no-ai', 'Skip AI synthesis')
90
110
  .option('-f, --force', 'Overwrite existing')
91
111
  .option('-y, --youtube <urls...>', 'YouTube video URLs to transcribe')
92
- .action(async (query, opts) => {
112
+ .action(async (queryParts, opts) => {
113
+ const query = queryParts.join(' ');
93
114
  console.log(c.cyan(`Resolving ${query}...`));
94
115
 
95
116
  let person;
@@ -38,8 +38,8 @@ function callClaudeCli(prompt, timeout = 600000) {
38
38
  const tmpFile = path.join(os.tmpdir(), `vip-prompt-${Date.now()}.txt`);
39
39
  try {
40
40
  fs.writeFileSync(tmpFile, prompt);
41
- // Disable tools (text-only), no session persistence
42
- const result = spawnSync('claude', ['--print', '--tools', '', '--no-session-persistence'], {
41
+ // Disable tools (text-only), skip permissions, no session persistence
42
+ const result = spawnSync('claude', ['--print', '--tools', '', '--no-session-persistence', '--dangerously-skip-permissions'], {
43
43
  input: prompt,
44
44
  encoding: 'utf-8',
45
45
  timeout,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vipcare",
3
- "version": "0.3.28",
3
+ "version": "0.3.30",
4
4
  "description": "Auto-build VIP person profiles from Twitter/LinkedIn public data",
5
5
  "type": "module",
6
6
  "bin": {