@cccarv82/freya 3.7.5 → 3.7.7

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": "@cccarv82/freya",
3
- "version": "3.7.5",
3
+ "version": "3.7.7",
4
4
  "description": "Personal AI Assistant with local-first persistence",
5
5
  "scripts": {
6
6
  "health": "node scripts/validate-data.js && node scripts/validate-structure.js",
@@ -21,7 +21,7 @@
21
21
  const fs = require('fs');
22
22
  const path = require('path');
23
23
  const crypto = require('crypto');
24
- const { spawn } = require('child_process');
24
+ const { spawn, execSync } = require('child_process');
25
25
  const os = require('os');
26
26
 
27
27
  // Parse args
@@ -58,10 +58,19 @@ function run(cmd, args, cwd, extraEnv) {
58
58
  const env = extraEnv ? { ...process.env, ...extraEnv } : process.env;
59
59
  try {
60
60
  if (process.platform === 'win32') {
61
- const comspec = process.env.ComSpec || 'cmd.exe';
62
- child = spawn(comspec, ['/d', '/s', '/c', cmd, ...args], { cwd, shell: false, env });
61
+ // Use PowerShell fnm/nvm set PATH only in PS profile,
62
+ // cmd.exe cannot find npm global .cmd shims like copilot.
63
+ // Do NOT use -NoProfile: profile is what loads fnm PATH entries.
64
+ const escapedArgs = args.map(a => {
65
+ const escaped = String(a).replace(/'/g, "''");
66
+ return `'${escaped}'`;
67
+ });
68
+ const psCommand = `& '${cmd}' ${escapedArgs.join(' ')}`;
69
+ child = spawn('powershell.exe', [
70
+ '-NoLogo', '-Command', psCommand
71
+ ], { cwd, env, windowsHide: true });
63
72
  } else {
64
- child = spawn(cmd, args, { cwd, shell: false, env });
73
+ child = spawn(cmd, args, { cwd, shell: true, env });
65
74
  }
66
75
  } catch (e) {
67
76
  return resolve({ code: 1, stdout: '', stderr: e.message || String(e) });
@@ -189,28 +198,75 @@ async function main() {
189
198
  // Step 3: Extract tasks/blockers from each daily log via planner
190
199
  console.log('── Step 3: Extracting tasks & blockers via planner ──');
191
200
 
192
- // Detect copilot command: try user override, then 'copilot', then 'gh copilot'
193
- let cmd = process.env.COPILOT_CMD || '';
194
- if (!cmd) {
195
- // Quick test: try 'copilot --version'
196
- const testCopilot = await run('copilot', ['--version'], workspaceDir);
197
- if (testCopilot.code === 0) {
198
- cmd = 'copilot';
201
+ // Detect copilot use same approach as web.js (resolve full path)
202
+ let copilotResolved = process.env.COPILOT_CMD || '';
203
+ if (!copilotResolved) {
204
+ console.log(' ℹ Detecting copilot CLI...');
205
+ if (process.platform === 'win32') {
206
+ // Try 'where' first (system PATH)
207
+ try {
208
+ const p = execSync('where copilot 2>nul', { encoding: 'utf8', timeout: 5000 }).trim().split(/\r?\n/)[0];
209
+ if (p && fs.existsSync(p)) copilotResolved = p;
210
+ } catch { }
211
+ // Use PowerShell to resolve (works with fnm, nvm-windows, etc.)
212
+ if (!copilotResolved) {
213
+ try {
214
+ const p = execSync(
215
+ 'powershell.exe -NoProfile -Command "(Get-Command copilot -ErrorAction SilentlyContinue).Source"',
216
+ { encoding: 'utf8', timeout: 10000 }
217
+ ).trim();
218
+ if (p && fs.existsSync(p)) copilotResolved = p;
219
+ } catch { }
220
+ }
221
+ // Try gh copilot
222
+ if (!copilotResolved) {
223
+ try {
224
+ const p = execSync(
225
+ 'powershell.exe -NoProfile -Command "(Get-Command gh -ErrorAction SilentlyContinue).Source"',
226
+ { encoding: 'utf8', timeout: 10000 }
227
+ ).trim();
228
+ if (p && fs.existsSync(p)) copilotResolved = `gh-copilot:${p}`;
229
+ } catch { }
230
+ }
199
231
  } else {
200
- // Try 'gh copilot' via 'gh'
201
- const testGh = await run('gh', ['copilot', '--version'], workspaceDir);
202
- if (testGh.code === 0) {
203
- cmd = 'gh';
204
- console.log(' ℹ Using "gh copilot" as planner command');
205
- } else {
206
- cmd = 'copilot'; // default, will fail with clear error
207
- console.log(' ⚠ Could not detect copilot CLI. Set COPILOT_CMD env var if needed.');
208
- console.log(` copilot test: code=${testCopilot.code} stderr=${(testCopilot.stderr || '').slice(0, 200)}`);
209
- console.log(` gh copilot test: code=${testGh.code} stderr=${(testGh.stderr || '').slice(0, 200)}`);
232
+ try {
233
+ const p = execSync('which copilot 2>/dev/null', { encoding: 'utf8', timeout: 5000 }).trim();
234
+ if (p) copilotResolved = p;
235
+ } catch { }
236
+ if (!copilotResolved) {
237
+ try {
238
+ const p = execSync('which gh 2>/dev/null', { encoding: 'utf8', timeout: 5000 }).trim();
239
+ if (p) copilotResolved = `gh-copilot:${p}`;
240
+ } catch { }
210
241
  }
211
242
  }
243
+ if (!copilotResolved) {
244
+ copilotResolved = 'copilot'; // last resort fallback
245
+ }
246
+ }
247
+ // Verify it works
248
+ const testArgs = copilotResolved.startsWith('gh-copilot:')
249
+ ? { cmd: copilotResolved.slice('gh-copilot:'.length), args: ['copilot', '--version'] }
250
+ : { cmd: copilotResolved, args: ['--version'] };
251
+ const testResult = await run(testArgs.cmd, testArgs.args, workspaceDir);
252
+ if (testResult.code === 0) {
253
+ console.log(` ✓ Found: ${(testResult.stdout || '').trim().split(/\r?\n/)[0]}`);
254
+ } else {
255
+ console.log(' ❌ Could not find copilot CLI.');
256
+ console.log(` stderr: ${(testResult.stderr || '').slice(0, 200)}`);
257
+ console.log(' Skipping task/blocker extraction.');
258
+ dl.db.save();
259
+ console.log('\n✅ Retroactive ingestion complete (embeddings only)!');
260
+ return;
261
+ }
262
+ // Helper to build spawn args (same as copilotSpawnArgs in web.js)
263
+ function buildCopilotArgs(extraArgs) {
264
+ if (copilotResolved.startsWith('gh-copilot:')) {
265
+ const ghPath = copilotResolved.slice('gh-copilot:'.length);
266
+ return { cmd: ghPath, args: ['copilot', ...extraArgs] };
267
+ }
268
+ return { cmd: copilotResolved, args: extraArgs };
212
269
  }
213
- const useGhCopilot = cmd === 'gh';
214
270
  const agentEnv = { FREYA_WORKSPACE_DIR: workspaceDir };
215
271
  const slugMap = readProjectSlugMap(workspaceDir);
216
272
  const validTaskCats = new Set(['DO_NOW', 'SCHEDULE', 'DELEGATE', 'IGNORE']);
@@ -263,18 +319,18 @@ IMPORTANTE: Extraia APENAS informações explícitas do log. NÃO invente dados.
263
319
 
264
320
  try {
265
321
  let r;
266
- const baseArgs = useGhCopilot
267
- ? ['copilot', '-s', '--no-color', '--stream', 'off']
268
- : ['-s', '--no-color', '--stream', 'off'];
322
+ const copilotExtra = ['-s', '--no-color', '--stream', 'off'];
269
323
 
270
324
  if (fullPrompt.length > SAFE_ARG_LEN) {
271
325
  const tmpFile = path.join(os.tmpdir(), `freya-retro-${Date.now()}.txt`);
272
326
  fs.writeFileSync(tmpFile, fullPrompt, 'utf8');
273
327
  const filePrompt = `Leia o arquivo abaixo e extraia tasks/blockers conforme as instruções contidas nele.\nARQUIVO: ${tmpFile}`;
274
- r = await run(cmd, [...baseArgs, '--add-dir', os.tmpdir(), '--allow-all-tools', '-p', filePrompt], workspaceDir, agentEnv);
328
+ const { cmd: sc, args: sa } = buildCopilotArgs([...copilotExtra, '--add-dir', os.tmpdir(), '--allow-all-tools', '-p', filePrompt]);
329
+ r = await run(sc, sa, workspaceDir, agentEnv);
275
330
  try { fs.unlinkSync(tmpFile); } catch { }
276
331
  } else {
277
- r = await run(cmd, [...baseArgs, '-p', fullPrompt], workspaceDir, agentEnv);
332
+ const { cmd: sc, args: sa } = buildCopilotArgs([...copilotExtra, '-p', fullPrompt]);
333
+ r = await run(sc, sa, workspaceDir, agentEnv);
278
334
  }
279
335
 
280
336
  const out = (r.stdout + r.stderr).trim();
@@ -283,7 +339,7 @@ IMPORTANTE: Extraia APENAS informações explícitas do log. NÃO invente dados.
283
339
  // On first error, show verbose diagnostic
284
340
  if (totalErrors === 1) {
285
341
  console.log(`\n ⚠ Planner diagnostic for ${date}:`);
286
- console.log(` Command: ${cmd} ${(useGhCopilot ? baseArgs : ['-s', '--no-color', '--stream', 'off', '-p', '...']).join(' ')}`);
342
+ console.log(` Command: ${copilotResolved} -s --no-color --stream off -p ...`);
287
343
  console.log(` Exit code: ${r.code}`);
288
344
  console.log(` stdout: ${(r.stdout || '').slice(0, 300)}`);
289
345
  console.log(` stderr: ${(r.stderr || '').slice(0, 300)}`);