edsger 0.38.0 → 0.38.2

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.
@@ -1,2 +1,2 @@
1
1
  import { type EdsgerConfig } from '../../types/index.js';
2
- export declare function executeIntelligenceQuery(currentPrompt: string, systemPrompt: string, _config: EdsgerConfig, verbose?: boolean): Promise<Record<string, unknown> | null>;
2
+ export declare function executeIntelligenceQuery(currentPrompt: string, systemPrompt: string, _config: EdsgerConfig, verbose?: boolean, cwd?: string): Promise<Record<string, unknown> | null>;
@@ -35,7 +35,7 @@ async function* prompt(analysisPrompt) {
35
35
  message: { role: 'user', content: analysisPrompt },
36
36
  };
37
37
  }
38
- export async function executeIntelligenceQuery(currentPrompt, systemPrompt, _config, verbose) {
38
+ export async function executeIntelligenceQuery(currentPrompt, systemPrompt, _config, verbose, cwd) {
39
39
  let lastAssistantResponse = '';
40
40
  let structuredResult = null;
41
41
  let turnCount = 0;
@@ -51,6 +51,7 @@ export async function executeIntelligenceQuery(currentPrompt, systemPrompt, _con
51
51
  model: DEFAULT_MODEL,
52
52
  maxTurns: 1000,
53
53
  permissionMode: 'bypassPermissions',
54
+ ...(cwd ? { cwd } : {}),
54
55
  },
55
56
  })) {
56
57
  if (verbose) {
@@ -1,6 +1,5 @@
1
1
  import { batchCreateCompetitors, type Competitor, type CompetitorSnapshot, type IntelligenceReport, saveReport, saveSnapshot, updateReport } from '../../api/intelligence.js';
2
2
  import { type EdsgerConfig } from '../../types/index.js';
3
- import { executeIntelligenceQuery } from './agent.js';
4
3
  import { prepareIntelligenceContext } from './context.js';
5
4
  interface CompetitorRef {
6
5
  id: string;
@@ -43,7 +42,7 @@ export interface IntelligenceAnalysisResult {
43
42
  /** Injectable dependencies for testing. Production code uses the defaults. */
44
43
  export interface IntelligenceDeps {
45
44
  prepareContext: typeof prepareIntelligenceContext;
46
- executeQuery: typeof executeIntelligenceQuery;
45
+ executeQuery: (currentPrompt: string, systemPrompt: string, config: EdsgerConfig, verbose?: boolean, cwd?: string) => Promise<Record<string, unknown> | null>;
47
46
  batchCreate: typeof batchCreateCompetitors;
48
47
  saveSnap: typeof saveSnapshot;
49
48
  saveRpt: typeof saveReport;
@@ -1,5 +1,7 @@
1
+ import { getGitHubConfigByProduct } from '../../api/github.js';
1
2
  import { batchCreateCompetitors, saveReport, saveSnapshot, updateReport, } from '../../api/intelligence.js';
2
3
  import { logError, logInfo, logSuccess, logWarning, } from '../../utils/logger.js';
4
+ import { cloneFeatureRepo, ensureWorkspaceDir, } from '../../workspace/workspace-manager.js';
3
5
  import { executeIntelligenceQuery } from './agent.js';
4
6
  import { prepareIntelligenceContext } from './context.js';
5
7
  import { createIntelligenceSystemPrompt } from './prompts.js';
@@ -75,16 +77,37 @@ const defaultDeps = {
75
77
  export async function analyseIntelligence(options, config, deps = defaultDeps) {
76
78
  const { productId, reportType = 'competitive', verbose, guidance, reportId, } = options;
77
79
  try {
78
- // 1. Prepare context
80
+ // 1. Clone product repo if GitHub is configured
81
+ let repoCwd;
82
+ try {
83
+ const githubConfig = await getGitHubConfigByProduct(productId, verbose);
84
+ if (githubConfig.configured &&
85
+ githubConfig.token &&
86
+ githubConfig.owner &&
87
+ githubConfig.repo) {
88
+ const workspaceRoot = ensureWorkspaceDir();
89
+ const { repoPath } = cloneFeatureRepo(workspaceRoot, `intel-${productId}`, githubConfig.owner, githubConfig.repo, githubConfig.token);
90
+ repoCwd = repoPath;
91
+ logInfo(`Repository cloned to: ${repoCwd}`);
92
+ }
93
+ else {
94
+ logInfo(`No GitHub repo configured, running without codebase access. ${githubConfig.message || ''}`);
95
+ }
96
+ }
97
+ catch (error) {
98
+ logInfo(`Could not clone repo (continuing without codebase): ${error instanceof Error ? error.message : String(error)}`);
99
+ }
100
+ const hasCodebase = !!repoCwd;
101
+ // 2. Prepare context
79
102
  logInfo('Preparing intelligence analysis context...');
80
103
  const { context, analysisPrompt } = await deps.prepareContext(productId, verbose, reportType, guidance);
81
104
  const needsDiscovery = context.confirmedCompetitors.length === 0;
82
- const systemPrompt = createIntelligenceSystemPrompt(needsDiscovery);
83
- // 2. Run AI analysis
105
+ const systemPrompt = createIntelligenceSystemPrompt(needsDiscovery, hasCodebase);
106
+ // 3. Run AI analysis
84
107
  logInfo(needsDiscovery
85
108
  ? 'No competitors found — AI will discover competitors first...'
86
109
  : `Analyzing ${context.confirmedCompetitors.length} confirmed competitors...`);
87
- const analysisResult = await deps.executeQuery(analysisPrompt, systemPrompt, config, verbose);
110
+ const analysisResult = await deps.executeQuery(analysisPrompt, systemPrompt, config, verbose, repoCwd);
88
111
  if (!analysisResult) {
89
112
  logError('Intelligence analysis returned no results');
90
113
  return {
@@ -1,2 +1,2 @@
1
- export declare const createIntelligenceSystemPrompt: (needsDiscovery: boolean) => string;
1
+ export declare const createIntelligenceSystemPrompt: (needsDiscovery: boolean, hasCodebase?: boolean) => string;
2
2
  export declare const createIntelligencePromptWithContext: (productId: string, contextInfo: string, reportType: string, needsDiscovery: boolean) => string;
@@ -1,17 +1,22 @@
1
- export const createIntelligenceSystemPrompt = (needsDiscovery) => {
1
+ export const createIntelligenceSystemPrompt = (needsDiscovery, hasCodebase = false) => {
2
+ const codebaseStep = hasCodebase
3
+ ? `1. **Explore the Codebase**: BEFORE doing any research, use your tools to read README, CLAUDE.md, package.json, and key source files to deeply understand what the product actually does, its features, tech stack, and unique selling points. This gives you an accurate picture of "what we have" for comparison against competitors.
4
+ `
5
+ : '';
6
+ const stepOffset = hasCodebase ? 1 : 0;
2
7
  return `You are an expert product strategist and competitive intelligence analyst. Your task is to research the market, analyze competitors, and produce actionable intelligence reports.
3
8
 
4
- **Your Role**: Use web search extensively to gather real-time data about competitors, market trends, and user sentiment. Never guess or fabricate data — only report what you find through actual research.
9
+ **Your Role**: Use web search extensively to gather real-time data about competitors, market trends, and user sentiment. Never guess or fabricate data — only report what you find through actual research.${hasCodebase ? ' You also have access to the product codebase — use it to understand exact capabilities for accurate competitor comparison.' : ''}
5
10
 
6
11
  **Analysis Process**:
7
- ${needsDiscovery
8
- ? `1. **Discover Competitors**: Search the web for products competing in the same space. Use queries like "{product} alternatives", "{product} vs", "{category} best tools", and check App Store/Play Store for similar apps. Find 5-10 relevant competitors.
9
- 2. **Deep Competitor Research**: For each competitor, search their website, app store pages, social media mentions, and review sites to extract features, pricing, ratings, and recent changes.`
10
- : `1. **Deep Competitor Research**: For each registered competitor, search their website, app store pages, social media mentions, and review sites to extract current features, pricing, ratings, and recent changes.
11
- 2. **Discover New Competitors**: Also search for new entrants or products that weren't previously tracked.`}
12
- 3. **Market Signal Collection**: Search for relevant discussions on Reddit, Hacker News, Twitter/X, Product Hunt, and industry blogs to understand market sentiment and trends.
13
- 4. **Change Detection**: Compare what you find against any previous snapshot data provided. Note new features, pricing changes, version updates, and sentiment shifts.
14
- 5. **Strategic Analysis**: Synthesize all data into actionable insights — threats, opportunities, and specific recommendations.
12
+ ${codebaseStep}${needsDiscovery
13
+ ? `${stepOffset + 1}. **Discover Competitors**: Search the web for products competing in the same space. Use queries like "{product} alternatives", "{product} vs", "{category} best tools", and check App Store/Play Store for similar apps. Find 5-10 relevant competitors.
14
+ ${stepOffset + 2}. **Deep Competitor Research**: For each competitor, search their website, app store pages, social media mentions, and review sites to extract features, pricing, ratings, and recent changes.`
15
+ : `${stepOffset + 1}. **Deep Competitor Research**: For each registered competitor, search their website, app store pages, social media mentions, and review sites to extract current features, pricing, ratings, and recent changes.
16
+ ${stepOffset + 2}. **Discover New Competitors**: Also search for new entrants or products that weren't previously tracked.`}
17
+ ${stepOffset + 3}. **Market Signal Collection**: Search for relevant discussions on Reddit, Hacker News, Twitter/X, Product Hunt, and industry blogs to understand market sentiment and trends.
18
+ ${stepOffset + 4}. **Change Detection**: Compare what you find against any previous snapshot data provided. Note new features, pricing changes, version updates, and sentiment shifts.
19
+ ${stepOffset + 5}. **Strategic Analysis**: Synthesize all data into actionable insights — threats, opportunities, and specific recommendations.${hasCodebase ? ` Compare competitor features against what exists in the codebase to identify real gaps and advantages.` : ''}
15
20
 
16
21
  **Research Requirements**:
17
22
  - You MUST use web search for EVERY competitor. Do NOT rely on training data alone.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.38.0",
3
+ "version": "0.38.2",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"