popeye-cli 1.0.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.
- package/.env.example +25 -0
- package/.prettierrc +8 -0
- package/README.md +320 -0
- package/dist/adapters/claude.d.ts +82 -0
- package/dist/adapters/claude.d.ts.map +1 -0
- package/dist/adapters/claude.js +230 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/openai.d.ts +48 -0
- package/dist/adapters/openai.d.ts.map +1 -0
- package/dist/adapters/openai.js +257 -0
- package/dist/adapters/openai.js.map +1 -0
- package/dist/auth/claude.d.ts +44 -0
- package/dist/auth/claude.d.ts.map +1 -0
- package/dist/auth/claude.js +139 -0
- package/dist/auth/claude.js.map +1 -0
- package/dist/auth/index.d.ts +61 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +141 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/keychain.d.ts +66 -0
- package/dist/auth/keychain.d.ts.map +1 -0
- package/dist/auth/keychain.js +125 -0
- package/dist/auth/keychain.js.map +1 -0
- package/dist/auth/openai-entry.d.ts +9 -0
- package/dist/auth/openai-entry.d.ts.map +1 -0
- package/dist/auth/openai-entry.js +410 -0
- package/dist/auth/openai-entry.js.map +1 -0
- package/dist/auth/openai.d.ts +71 -0
- package/dist/auth/openai.d.ts.map +1 -0
- package/dist/auth/openai.js +212 -0
- package/dist/auth/openai.js.map +1 -0
- package/dist/auth/server.d.ts +32 -0
- package/dist/auth/server.d.ts.map +1 -0
- package/dist/auth/server.js +213 -0
- package/dist/auth/server.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +10 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +162 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/config.d.ts +10 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +215 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/create.d.ts +10 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +240 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/index.d.ts +10 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +10 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +18 -0
- package/dist/cli/commands/resume.d.ts.map +1 -0
- package/dist/cli/commands/resume.js +241 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/status.d.ts +18 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +154 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +71 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/interactive.d.ts +9 -0
- package/dist/cli/interactive.d.ts.map +1 -0
- package/dist/cli/interactive.js +330 -0
- package/dist/cli/interactive.js.map +1 -0
- package/dist/cli/output.d.ts +182 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +355 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/config/defaults.d.ts +57 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +103 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +138 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +244 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +220 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +141 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/generators/index.d.ts +101 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +200 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/python.d.ts +48 -0
- package/dist/generators/python.d.ts.map +1 -0
- package/dist/generators/python.js +262 -0
- package/dist/generators/python.js.map +1 -0
- package/dist/generators/templates/index.d.ts +6 -0
- package/dist/generators/templates/index.d.ts.map +1 -0
- package/dist/generators/templates/index.js +6 -0
- package/dist/generators/templates/index.js.map +1 -0
- package/dist/generators/templates/python.d.ts +53 -0
- package/dist/generators/templates/python.d.ts.map +1 -0
- package/dist/generators/templates/python.js +454 -0
- package/dist/generators/templates/python.js.map +1 -0
- package/dist/generators/templates/typescript.d.ts +53 -0
- package/dist/generators/templates/typescript.d.ts.map +1 -0
- package/dist/generators/templates/typescript.js +394 -0
- package/dist/generators/templates/typescript.js.map +1 -0
- package/dist/generators/typescript.d.ts +64 -0
- package/dist/generators/typescript.d.ts.map +1 -0
- package/dist/generators/typescript.js +271 -0
- package/dist/generators/typescript.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/state/index.d.ts +168 -0
- package/dist/state/index.d.ts.map +1 -0
- package/dist/state/index.js +338 -0
- package/dist/state/index.js.map +1 -0
- package/dist/state/persistence.d.ts +91 -0
- package/dist/state/persistence.d.ts.map +1 -0
- package/dist/state/persistence.js +201 -0
- package/dist/state/persistence.js.map +1 -0
- package/dist/types/cli.d.ts +132 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +17 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/types/consensus.d.ts +111 -0
- package/dist/types/consensus.d.ts.map +1 -0
- package/dist/types/consensus.js +29 -0
- package/dist/types/consensus.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +13 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/project.d.ts +73 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +55 -0
- package/dist/types/project.js.map +1 -0
- package/dist/types/workflow.d.ts +236 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +74 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/workflow/consensus.d.ts +89 -0
- package/dist/workflow/consensus.d.ts.map +1 -0
- package/dist/workflow/consensus.js +220 -0
- package/dist/workflow/consensus.js.map +1 -0
- package/dist/workflow/execution-mode.d.ts +82 -0
- package/dist/workflow/execution-mode.d.ts.map +1 -0
- package/dist/workflow/execution-mode.js +346 -0
- package/dist/workflow/execution-mode.js.map +1 -0
- package/dist/workflow/index.d.ts +110 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +283 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/plan-mode.d.ts +83 -0
- package/dist/workflow/plan-mode.d.ts.map +1 -0
- package/dist/workflow/plan-mode.js +241 -0
- package/dist/workflow/plan-mode.js.map +1 -0
- package/dist/workflow/test-runner.d.ts +87 -0
- package/dist/workflow/test-runner.d.ts.map +1 -0
- package/dist/workflow/test-runner.js +273 -0
- package/dist/workflow/test-runner.js.map +1 -0
- package/eslint.config.js +25 -0
- package/package.json +66 -0
- package/src/adapters/claude.ts +298 -0
- package/src/adapters/openai.ts +300 -0
- package/src/auth/claude.ts +166 -0
- package/src/auth/index.ts +171 -0
- package/src/auth/keychain.ts +138 -0
- package/src/auth/openai-entry.ts +410 -0
- package/src/auth/openai.ts +260 -0
- package/src/auth/server.ts +252 -0
- package/src/cli/commands/auth.ts +194 -0
- package/src/cli/commands/config.ts +241 -0
- package/src/cli/commands/create.ts +308 -0
- package/src/cli/commands/index.ts +10 -0
- package/src/cli/commands/resume.ts +304 -0
- package/src/cli/commands/status.ts +189 -0
- package/src/cli/index.ts +90 -0
- package/src/cli/interactive.ts +418 -0
- package/src/cli/output.ts +410 -0
- package/src/config/defaults.ts +114 -0
- package/src/config/index.ts +315 -0
- package/src/config/schema.ts +164 -0
- package/src/generators/index.ts +251 -0
- package/src/generators/python.ts +318 -0
- package/src/generators/templates/index.ts +6 -0
- package/src/generators/templates/python.ts +465 -0
- package/src/generators/templates/typescript.ts +417 -0
- package/src/generators/typescript.ts +340 -0
- package/src/index.ts +13 -0
- package/src/state/index.ts +454 -0
- package/src/state/persistence.ts +230 -0
- package/src/types/cli.ts +146 -0
- package/src/types/consensus.ts +116 -0
- package/src/types/index.ts +64 -0
- package/src/types/project.ts +85 -0
- package/src/types/workflow.ts +149 -0
- package/src/workflow/consensus.ts +299 -0
- package/src/workflow/execution-mode.ts +517 -0
- package/src/workflow/index.ts +396 -0
- package/src/workflow/plan-mode.ts +356 -0
- package/src/workflow/test-runner.ts +345 -0
- package/tests/adapters/openai.test.ts +145 -0
- package/tests/config/config.test.ts +208 -0
- package/tests/generators/generators.test.ts +185 -0
- package/tests/types/consensus.test.ts +152 -0
- package/tests/types/project.test.ts +134 -0
- package/tests/workflow/consensus.test.ts +221 -0
- package/tests/workflow/test-runner.test.ts +214 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +22 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI API adapter
|
|
3
|
+
* Handles consensus reviews and plan validation
|
|
4
|
+
*/
|
|
5
|
+
import OpenAI from 'openai';
|
|
6
|
+
import type { ConsensusResult, ConsensusConfig, OpenAIModel } from '../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Create an OpenAI client with stored credentials
|
|
9
|
+
*/
|
|
10
|
+
export declare function createClient(): Promise<OpenAI>;
|
|
11
|
+
/**
|
|
12
|
+
* Request consensus review from OpenAI
|
|
13
|
+
*
|
|
14
|
+
* @param plan - The development plan to review
|
|
15
|
+
* @param context - Project context
|
|
16
|
+
* @param config - Consensus configuration
|
|
17
|
+
* @returns Consensus result
|
|
18
|
+
*/
|
|
19
|
+
export declare function requestConsensus(plan: string, context: string, config?: Partial<ConsensusConfig>): Promise<ConsensusResult>;
|
|
20
|
+
/**
|
|
21
|
+
* Parse the consensus response from OpenAI
|
|
22
|
+
* Extracts score, analysis, concerns, etc.
|
|
23
|
+
*/
|
|
24
|
+
export declare function parseConsensusResponse(response: string): ConsensusResult;
|
|
25
|
+
/**
|
|
26
|
+
* Validate that a model is available
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateModel(model: OpenAIModel): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* List available models
|
|
31
|
+
*/
|
|
32
|
+
export declare function listAvailableModels(): Promise<string[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Expand a brief idea into a full specification using OpenAI
|
|
35
|
+
*
|
|
36
|
+
* @param idea - The brief project idea
|
|
37
|
+
* @param language - Target programming language
|
|
38
|
+
* @returns Expanded specification
|
|
39
|
+
*/
|
|
40
|
+
export declare function expandIdea(idea: string, language: 'python' | 'typescript'): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Get feedback on generated code
|
|
43
|
+
*
|
|
44
|
+
* @param code - The code to review
|
|
45
|
+
* @param context - Context about what the code should do
|
|
46
|
+
*/
|
|
47
|
+
export declare function reviewCode(code: string, context: string): Promise<ConsensusResult>;
|
|
48
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIvF;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAQpD;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,OAAO,CAAC,eAAe,CAAM,GACpC,OAAO,CAAC,eAAe,CAAC,CA8B1B;AAgCD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAyBxE;AAuDD;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAQxE;AAED;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAiB7D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,YAAY,GAChC,OAAO,CAAC,MAAM,CAAC,CAkCjB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA+BxF"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI API adapter
|
|
3
|
+
* Handles consensus reviews and plan validation
|
|
4
|
+
*/
|
|
5
|
+
import OpenAI from 'openai';
|
|
6
|
+
import { getOpenAIToken } from '../auth/index.js';
|
|
7
|
+
import { DEFAULT_CONSENSUS_CONFIG } from '../types/consensus.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create an OpenAI client with stored credentials
|
|
10
|
+
*/
|
|
11
|
+
export async function createClient() {
|
|
12
|
+
const apiKey = await getOpenAIToken();
|
|
13
|
+
if (!apiKey) {
|
|
14
|
+
throw new Error('OpenAI API key not found. Run: popeye-cli auth openai');
|
|
15
|
+
}
|
|
16
|
+
return new OpenAI({ apiKey });
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Request consensus review from OpenAI
|
|
20
|
+
*
|
|
21
|
+
* @param plan - The development plan to review
|
|
22
|
+
* @param context - Project context
|
|
23
|
+
* @param config - Consensus configuration
|
|
24
|
+
* @returns Consensus result
|
|
25
|
+
*/
|
|
26
|
+
export async function requestConsensus(plan, context, config = {}) {
|
|
27
|
+
const { openaiModel = DEFAULT_CONSENSUS_CONFIG.openaiModel, temperature = DEFAULT_CONSENSUS_CONFIG.temperature, maxTokens = DEFAULT_CONSENSUS_CONFIG.maxTokens, } = config;
|
|
28
|
+
const client = await createClient();
|
|
29
|
+
// Build the consensus review prompt (matches spec section 11.1)
|
|
30
|
+
const prompt = buildConsensusPrompt(plan, context);
|
|
31
|
+
try {
|
|
32
|
+
const completion = await client.chat.completions.create({
|
|
33
|
+
model: openaiModel,
|
|
34
|
+
messages: [{ role: 'user', content: prompt }],
|
|
35
|
+
temperature,
|
|
36
|
+
max_tokens: maxTokens,
|
|
37
|
+
});
|
|
38
|
+
const response = completion.choices[0]?.message?.content || '';
|
|
39
|
+
return parseConsensusResponse(response);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (error instanceof OpenAI.RateLimitError) {
|
|
43
|
+
// Implement exponential backoff retry
|
|
44
|
+
await sleep(5000);
|
|
45
|
+
return requestConsensus(plan, context, config);
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build the consensus review prompt
|
|
52
|
+
* Follows spec section 11.1 format
|
|
53
|
+
*/
|
|
54
|
+
function buildConsensusPrompt(plan, context) {
|
|
55
|
+
return `You are a senior software architect reviewing a development plan.
|
|
56
|
+
Analyze the following plan for completeness, correctness, and feasibility.
|
|
57
|
+
|
|
58
|
+
PROJECT CONTEXT:
|
|
59
|
+
${context}
|
|
60
|
+
|
|
61
|
+
PROPOSED PLAN:
|
|
62
|
+
${plan}
|
|
63
|
+
|
|
64
|
+
Please provide:
|
|
65
|
+
1. ANALYSIS: Detailed review of the plan
|
|
66
|
+
2. STRENGTHS: What works well
|
|
67
|
+
3. CONCERNS: Issues or gaps identified
|
|
68
|
+
4. RECOMMENDATIONS: Specific improvements
|
|
69
|
+
5. CONSENSUS SCORE: A percentage (0-100%) indicating your agreement
|
|
70
|
+
- 95-100%: Ready for execution
|
|
71
|
+
- 80-94%: Minor revisions needed
|
|
72
|
+
- 60-79%: Significant revisions needed
|
|
73
|
+
- Below 60%: Major rework required
|
|
74
|
+
|
|
75
|
+
Format your consensus score as: CONSENSUS: [X]%
|
|
76
|
+
|
|
77
|
+
Be thorough but constructive in your feedback.`;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Parse the consensus response from OpenAI
|
|
81
|
+
* Extracts score, analysis, concerns, etc.
|
|
82
|
+
*/
|
|
83
|
+
export function parseConsensusResponse(response) {
|
|
84
|
+
// Extract consensus score
|
|
85
|
+
const scoreMatch = response.match(/CONSENSUS:\s*(\d+)%/i);
|
|
86
|
+
const score = scoreMatch ? parseInt(scoreMatch[1], 10) : 0;
|
|
87
|
+
// Extract sections
|
|
88
|
+
const analysis = extractSection(response, 'ANALYSIS', 'STRENGTHS');
|
|
89
|
+
const strengthsText = extractSection(response, 'STRENGTHS', 'CONCERNS');
|
|
90
|
+
const concernsText = extractSection(response, 'CONCERNS', 'RECOMMENDATIONS');
|
|
91
|
+
const recommendationsText = extractSection(response, 'RECOMMENDATIONS', 'CONSENSUS');
|
|
92
|
+
// Parse lists from sections
|
|
93
|
+
const strengths = parseList(strengthsText);
|
|
94
|
+
const concerns = parseList(concernsText);
|
|
95
|
+
const recommendations = parseList(recommendationsText);
|
|
96
|
+
return {
|
|
97
|
+
score,
|
|
98
|
+
analysis: analysis.trim(),
|
|
99
|
+
strengths,
|
|
100
|
+
concerns,
|
|
101
|
+
recommendations,
|
|
102
|
+
approved: score >= 95,
|
|
103
|
+
rawResponse: response,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Extract a section from the response between two headers
|
|
108
|
+
*/
|
|
109
|
+
function extractSection(response, startHeader, endHeader) {
|
|
110
|
+
const startPattern = new RegExp(`${startHeader}[:\\s]*`, 'i');
|
|
111
|
+
const endPattern = new RegExp(`${endHeader}[:\\s]*`, 'i');
|
|
112
|
+
const startMatch = response.match(startPattern);
|
|
113
|
+
if (!startMatch)
|
|
114
|
+
return '';
|
|
115
|
+
const startIndex = startMatch.index + startMatch[0].length;
|
|
116
|
+
const endMatch = response.slice(startIndex).match(endPattern);
|
|
117
|
+
if (!endMatch) {
|
|
118
|
+
return response.slice(startIndex).trim();
|
|
119
|
+
}
|
|
120
|
+
return response.slice(startIndex, startIndex + endMatch.index).trim();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Parse a bulleted or numbered list from text
|
|
124
|
+
*/
|
|
125
|
+
function parseList(text) {
|
|
126
|
+
if (!text)
|
|
127
|
+
return [];
|
|
128
|
+
const lines = text.split('\n');
|
|
129
|
+
const items = [];
|
|
130
|
+
for (const line of lines) {
|
|
131
|
+
// Match bullets (-, *, +) or numbers (1., 2., etc.)
|
|
132
|
+
const match = line.match(/^[\s]*[-*+][\s]+(.+)$|^[\s]*\d+\.[\s]+(.+)$/);
|
|
133
|
+
if (match) {
|
|
134
|
+
const item = (match[1] || match[2]).trim();
|
|
135
|
+
if (item) {
|
|
136
|
+
items.push(item);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
else if (line.trim() && !line.match(/^[A-Z]+:/)) {
|
|
140
|
+
// Non-empty line that's not a header
|
|
141
|
+
items.push(line.trim());
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return items;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Helper sleep function for rate limiting
|
|
148
|
+
*/
|
|
149
|
+
function sleep(ms) {
|
|
150
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate that a model is available
|
|
154
|
+
*/
|
|
155
|
+
export async function validateModel(model) {
|
|
156
|
+
try {
|
|
157
|
+
const client = await createClient();
|
|
158
|
+
const models = await client.models.list();
|
|
159
|
+
return models.data.some((m) => m.id === model);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* List available models
|
|
167
|
+
*/
|
|
168
|
+
export async function listAvailableModels() {
|
|
169
|
+
try {
|
|
170
|
+
const client = await createClient();
|
|
171
|
+
const models = await client.models.list();
|
|
172
|
+
return models.data
|
|
173
|
+
.filter((m) => m.id.includes('gpt-4') ||
|
|
174
|
+
m.id.includes('gpt-3.5') ||
|
|
175
|
+
m.id.startsWith('o1'))
|
|
176
|
+
.map((m) => m.id)
|
|
177
|
+
.sort();
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
return [];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Expand a brief idea into a full specification using OpenAI
|
|
185
|
+
*
|
|
186
|
+
* @param idea - The brief project idea
|
|
187
|
+
* @param language - Target programming language
|
|
188
|
+
* @returns Expanded specification
|
|
189
|
+
*/
|
|
190
|
+
export async function expandIdea(idea, language) {
|
|
191
|
+
const client = await createClient();
|
|
192
|
+
const prompt = `You are a senior software architect. A user wants to build a project with the following idea:
|
|
193
|
+
|
|
194
|
+
"${idea}"
|
|
195
|
+
|
|
196
|
+
The project will be implemented in ${language === 'python' ? 'Python' : 'TypeScript'}.
|
|
197
|
+
|
|
198
|
+
Expand this into a complete software specification including:
|
|
199
|
+
|
|
200
|
+
1. **Project Overview**: A clear description of what will be built
|
|
201
|
+
2. **Core Features**: List of main features and functionality
|
|
202
|
+
3. **Technical Requirements**:
|
|
203
|
+
- Language and framework choices
|
|
204
|
+
- Database requirements (if any)
|
|
205
|
+
- External APIs or services needed
|
|
206
|
+
- Authentication requirements (if any)
|
|
207
|
+
4. **Architecture Overview**: High-level system design
|
|
208
|
+
5. **API Specification** (if applicable): Key endpoints and their purposes
|
|
209
|
+
6. **Data Models**: Key entities and their relationships
|
|
210
|
+
7. **Non-Functional Requirements**: Performance, security, scalability considerations
|
|
211
|
+
8. **Deployment**: Docker configuration and deployment approach
|
|
212
|
+
|
|
213
|
+
Be specific and actionable. The specification should be detailed enough that a developer could implement it without further clarification.`;
|
|
214
|
+
const completion = await client.chat.completions.create({
|
|
215
|
+
model: 'gpt-4o',
|
|
216
|
+
messages: [{ role: 'user', content: prompt }],
|
|
217
|
+
temperature: 0.7,
|
|
218
|
+
max_tokens: 4096,
|
|
219
|
+
});
|
|
220
|
+
return completion.choices[0]?.message?.content || idea;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get feedback on generated code
|
|
224
|
+
*
|
|
225
|
+
* @param code - The code to review
|
|
226
|
+
* @param context - Context about what the code should do
|
|
227
|
+
*/
|
|
228
|
+
export async function reviewCode(code, context) {
|
|
229
|
+
const client = await createClient();
|
|
230
|
+
const prompt = `You are a senior software engineer reviewing code. Review the following code:
|
|
231
|
+
|
|
232
|
+
CONTEXT:
|
|
233
|
+
${context}
|
|
234
|
+
|
|
235
|
+
CODE:
|
|
236
|
+
\`\`\`
|
|
237
|
+
${code}
|
|
238
|
+
\`\`\`
|
|
239
|
+
|
|
240
|
+
Provide:
|
|
241
|
+
1. ANALYSIS: Overall code quality assessment
|
|
242
|
+
2. STRENGTHS: What's done well
|
|
243
|
+
3. CONCERNS: Issues, bugs, or improvements needed
|
|
244
|
+
4. RECOMMENDATIONS: Specific fixes or enhancements
|
|
245
|
+
5. CONSENSUS SCORE: A percentage (0-100%) of how production-ready this code is
|
|
246
|
+
|
|
247
|
+
Format your score as: CONSENSUS: [X]%`;
|
|
248
|
+
const completion = await client.chat.completions.create({
|
|
249
|
+
model: 'gpt-4o',
|
|
250
|
+
messages: [{ role: 'user', content: prompt }],
|
|
251
|
+
temperature: 0.3,
|
|
252
|
+
max_tokens: 2048,
|
|
253
|
+
});
|
|
254
|
+
const response = completion.choices[0]?.message?.content || '';
|
|
255
|
+
return parseConsensusResponse(response);
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAEjE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,MAAM,cAAc,EAAE,CAAC;IAEtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAY,EACZ,OAAe,EACf,SAAmC,EAAE;IAErC,MAAM,EACJ,WAAW,GAAG,wBAAwB,CAAC,WAAW,EAClD,WAAW,GAAG,wBAAwB,CAAC,WAAW,EAClD,SAAS,GAAG,wBAAwB,CAAC,SAAS,GAC/C,GAAG,MAAM,CAAC;IAEX,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,gEAAgE;IAChE,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACtD,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAC7C,WAAW;YACX,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;QAC/D,OAAO,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,MAAM,CAAC,cAAc,EAAE,CAAC;YAC3C,sCAAsC;YACtC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YAClB,OAAO,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB,CAAC,IAAY,EAAE,OAAe;IACzD,OAAO;;;;EAIP,OAAO;;;EAGP,IAAI;;;;;;;;;;;;;;;+CAeyC,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,0BAA0B;IAC1B,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3D,mBAAmB;IACnB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IACnE,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACxE,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,EAAE,UAAU,EAAE,iBAAiB,CAAC,CAAC;IAC7E,MAAM,mBAAmB,GAAG,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,WAAW,CAAC,CAAC;IAErF,4BAA4B;IAC5B,MAAM,SAAS,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;IACzC,MAAM,eAAe,GAAG,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAEvD,OAAO;QACL,KAAK;QACL,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE;QACzB,SAAS;QACT,QAAQ;QACR,eAAe;QACf,QAAQ,EAAE,KAAK,IAAI,EAAE;QACrB,WAAW,EAAE,QAAQ;KACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,QAAgB,EAAE,WAAmB,EAAE,SAAiB;IAC9E,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,GAAG,WAAW,SAAS,EAAE,GAAG,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,IAAI,MAAM,CAAC,GAAG,SAAS,SAAS,EAAE,GAAG,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAChD,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,UAAU,GAAG,UAAU,CAAC,KAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5D,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAE9D,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,CAAC;IAED,OAAO,QAAQ,CAAC,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,QAAQ,CAAC,KAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,oDAAoD;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACxE,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,IAAI,EAAE,CAAC;gBACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAClD,qCAAqC;YACrC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAkB;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAE1C,OAAO,MAAM,CAAC,IAAI;aACf,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;YACtB,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC;YACxB,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CACxB;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChB,IAAI,EAAE,CAAC;IACZ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,QAAiC;IAEjC,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG;;GAEd,IAAI;;qCAE8B,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY;;;;;;;;;;;;;;;;;2IAiBuD,CAAC;IAE1I,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACtD,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAC7C,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAAe;IAC5D,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,MAAM,MAAM,GAAG;;;EAGf,OAAO;;;;EAIP,IAAI;;;;;;;;;;sCAUgC,CAAC;IAErC,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;QACtD,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAC7C,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IAC/D,OAAO,sBAAsB,CAAC,QAAQ,CAAC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI authentication module
|
|
3
|
+
* Handles OAuth flow and token management for Claude CLI
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Claude authentication status
|
|
7
|
+
*/
|
|
8
|
+
export interface ClaudeAuthStatus {
|
|
9
|
+
authenticated: boolean;
|
|
10
|
+
user?: string;
|
|
11
|
+
expires?: string;
|
|
12
|
+
error?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Check if Claude CLI is already authenticated
|
|
16
|
+
* This checks for existing credentials in the keychain or environment
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkClaudeCLIAuth(): Promise<ClaudeAuthStatus>;
|
|
19
|
+
/**
|
|
20
|
+
* Authenticate with Claude CLI using browser-based OAuth flow
|
|
21
|
+
*
|
|
22
|
+
* @returns Promise that resolves to true if authentication was successful
|
|
23
|
+
*/
|
|
24
|
+
export declare function authenticateClaude(): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Logout from Claude CLI
|
|
27
|
+
* Removes stored credentials
|
|
28
|
+
*/
|
|
29
|
+
export declare function logoutClaude(): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Refresh Claude CLI authentication
|
|
32
|
+
* Re-authenticates if the current token is expired or invalid
|
|
33
|
+
*/
|
|
34
|
+
export declare function refreshClaudeAuth(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Get the Claude CLI token for API calls
|
|
37
|
+
*/
|
|
38
|
+
export declare function getClaudeToken(): Promise<string | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Ensure Claude CLI is authenticated
|
|
41
|
+
* Prompts for authentication if not already authenticated
|
|
42
|
+
*/
|
|
43
|
+
export declare function ensureClaudeAuth(): Promise<boolean>;
|
|
44
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/auth/claude.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAoBpE;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAiD3D;AAsBD;;;GAGG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAOlD;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAM1D;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAE7D;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CAQzD"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI authentication module
|
|
3
|
+
* Handles OAuth flow and token management for Claude CLI
|
|
4
|
+
*/
|
|
5
|
+
import open from 'open';
|
|
6
|
+
import { getClaudeCredential, setClaudeCredential, deleteClaudeCredential } from './keychain.js';
|
|
7
|
+
import { startAuthCallbackServer, findAvailablePort, getCallbackUrl } from './server.js';
|
|
8
|
+
/**
|
|
9
|
+
* Check if Claude CLI is already authenticated
|
|
10
|
+
* This checks for existing credentials in the keychain or environment
|
|
11
|
+
*/
|
|
12
|
+
export async function checkClaudeCLIAuth() {
|
|
13
|
+
try {
|
|
14
|
+
const token = await getClaudeCredential();
|
|
15
|
+
if (!token) {
|
|
16
|
+
return { authenticated: false };
|
|
17
|
+
}
|
|
18
|
+
// For now, we assume if there's a token, it's valid
|
|
19
|
+
// In production, you would validate the token with the Claude API
|
|
20
|
+
return {
|
|
21
|
+
authenticated: true,
|
|
22
|
+
user: 'claude-user', // Would be extracted from token in production
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return {
|
|
27
|
+
authenticated: false,
|
|
28
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Authenticate with Claude CLI using browser-based OAuth flow
|
|
34
|
+
*
|
|
35
|
+
* @returns Promise that resolves to true if authentication was successful
|
|
36
|
+
*/
|
|
37
|
+
export async function authenticateClaude() {
|
|
38
|
+
// Check if already authenticated
|
|
39
|
+
const existingAuth = await checkClaudeCLIAuth();
|
|
40
|
+
if (existingAuth.authenticated) {
|
|
41
|
+
console.log('Already authenticated with Claude CLI');
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
console.log('Claude CLI authentication required.');
|
|
45
|
+
console.log('Opening browser for login...\n');
|
|
46
|
+
try {
|
|
47
|
+
// Find an available port for the callback server
|
|
48
|
+
const port = await findAvailablePort(3000, 3100);
|
|
49
|
+
const callbackUrl = getCallbackUrl(port, 'claude');
|
|
50
|
+
// Start the callback server
|
|
51
|
+
const authPromise = startAuthCallbackServer({
|
|
52
|
+
port,
|
|
53
|
+
type: 'claude',
|
|
54
|
+
timeout: 300000, // 5 minutes
|
|
55
|
+
});
|
|
56
|
+
// Build the login URL
|
|
57
|
+
// Note: This is a placeholder URL. The actual Claude OAuth URL would be provided by Anthropic
|
|
58
|
+
const loginUrl = buildClaudeLoginUrl(callbackUrl);
|
|
59
|
+
console.log(`Waiting for authentication...`);
|
|
60
|
+
console.log(`(Browser opened to: ${loginUrl})\n`);
|
|
61
|
+
// Open the browser to the login URL
|
|
62
|
+
await open(loginUrl);
|
|
63
|
+
// Wait for the callback
|
|
64
|
+
const result = await authPromise;
|
|
65
|
+
if (result.success && result.token) {
|
|
66
|
+
// Store the token securely
|
|
67
|
+
await setClaudeCredential(result.token);
|
|
68
|
+
console.log('Claude CLI authenticated successfully!\n');
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.error(`Authentication failed: ${result.error || 'Unknown error'}`);
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
console.error(`Authentication error: ${error instanceof Error ? error.message : error}`);
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Build the Claude login URL with the callback redirect
|
|
83
|
+
*
|
|
84
|
+
* @param callbackUrl - The local callback URL
|
|
85
|
+
* @returns The full login URL
|
|
86
|
+
*/
|
|
87
|
+
function buildClaudeLoginUrl(callbackUrl) {
|
|
88
|
+
// This is a placeholder implementation
|
|
89
|
+
// The actual URL would be provided by Anthropic's OAuth configuration
|
|
90
|
+
const baseUrl = 'https://claude.ai/login';
|
|
91
|
+
const params = new URLSearchParams({
|
|
92
|
+
redirect_uri: callbackUrl,
|
|
93
|
+
client_id: 'popeye-cli',
|
|
94
|
+
response_type: 'code',
|
|
95
|
+
scope: 'cli',
|
|
96
|
+
});
|
|
97
|
+
return `${baseUrl}?${params.toString()}`;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Logout from Claude CLI
|
|
101
|
+
* Removes stored credentials
|
|
102
|
+
*/
|
|
103
|
+
export async function logoutClaude() {
|
|
104
|
+
const deleted = await deleteClaudeCredential();
|
|
105
|
+
if (deleted) {
|
|
106
|
+
console.log('Claude CLI credentials removed.');
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
console.log('No Claude CLI credentials found.');
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Refresh Claude CLI authentication
|
|
114
|
+
* Re-authenticates if the current token is expired or invalid
|
|
115
|
+
*/
|
|
116
|
+
export async function refreshClaudeAuth() {
|
|
117
|
+
// Remove existing credentials
|
|
118
|
+
await deleteClaudeCredential();
|
|
119
|
+
// Re-authenticate
|
|
120
|
+
return authenticateClaude();
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get the Claude CLI token for API calls
|
|
124
|
+
*/
|
|
125
|
+
export async function getClaudeToken() {
|
|
126
|
+
return getClaudeCredential();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Ensure Claude CLI is authenticated
|
|
130
|
+
* Prompts for authentication if not already authenticated
|
|
131
|
+
*/
|
|
132
|
+
export async function ensureClaudeAuth() {
|
|
133
|
+
const status = await checkClaudeCLIAuth();
|
|
134
|
+
if (status.authenticated) {
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
return authenticateClaude();
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/auth/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication orchestration module
|
|
3
|
+
* Coordinates authentication for both Claude CLI and OpenAI API
|
|
4
|
+
*/
|
|
5
|
+
import { type ClaudeAuthStatus } from './claude.js';
|
|
6
|
+
import { type OpenAIAuthStatus } from './openai.js';
|
|
7
|
+
import type { AuthStatus } from '../types/index.js';
|
|
8
|
+
export * from './claude.js';
|
|
9
|
+
export * from './openai.js';
|
|
10
|
+
export * from './keychain.js';
|
|
11
|
+
export * from './server.js';
|
|
12
|
+
/**
|
|
13
|
+
* Combined authentication status
|
|
14
|
+
*/
|
|
15
|
+
export interface CombinedAuthStatus {
|
|
16
|
+
claude: ClaudeAuthStatus;
|
|
17
|
+
openai: OpenAIAuthStatus;
|
|
18
|
+
fullyAuthenticated: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the authentication status for both services
|
|
22
|
+
*/
|
|
23
|
+
export declare function getAuthStatus(): Promise<CombinedAuthStatus>;
|
|
24
|
+
/**
|
|
25
|
+
* Get auth status formatted for CLI display
|
|
26
|
+
*/
|
|
27
|
+
export declare function getAuthStatusForDisplay(): Promise<AuthStatus>;
|
|
28
|
+
/**
|
|
29
|
+
* Ensure both services are authenticated
|
|
30
|
+
* Prompts for authentication if either is missing
|
|
31
|
+
*
|
|
32
|
+
* @returns True if both services are authenticated
|
|
33
|
+
*/
|
|
34
|
+
export declare function ensureAuthenticated(): Promise<boolean>;
|
|
35
|
+
/**
|
|
36
|
+
* Authenticate a specific service
|
|
37
|
+
*
|
|
38
|
+
* @param service - The service to authenticate ('claude', 'openai', or 'all')
|
|
39
|
+
* @returns True if authentication was successful
|
|
40
|
+
*/
|
|
41
|
+
export declare function authenticateService(service: 'claude' | 'openai' | 'all'): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Logout from a specific service or all services
|
|
44
|
+
*
|
|
45
|
+
* @param service - The service to logout from ('claude', 'openai', or 'all')
|
|
46
|
+
*/
|
|
47
|
+
export declare function logout(service: 'claude' | 'openai' | 'all'): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Check if a specific service is authenticated
|
|
50
|
+
*
|
|
51
|
+
* @param service - The service to check
|
|
52
|
+
* @returns True if the service is authenticated
|
|
53
|
+
*/
|
|
54
|
+
export declare function isAuthenticated(service: 'claude' | 'openai' | 'both'): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* Require authentication, throwing an error if not authenticated
|
|
57
|
+
*
|
|
58
|
+
* @throws Error if not authenticated
|
|
59
|
+
*/
|
|
60
|
+
export declare function requireAuth(): Promise<void>;
|
|
61
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAwD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAqD,KAAK,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAE5B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAWjE;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,UAAU,CAAC,CAenE;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,OAAO,CAAC,CA4B5D;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,GACnC,OAAO,CAAC,OAAO,CAAC,CASlB;AAED;;;;GAIG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAahF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW7F;AAED;;;;GAIG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAUjD"}
|