Skip to content

Commit 54f55e2

Browse files
committed
🐛 fix(anthropic_client): Update anthropic client to use messages in a proper way
1 parent 5058850 commit 54f55e2

File tree

16 files changed

+81
-101
lines changed

16 files changed

+81
-101
lines changed

.github/workflows/update_views.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
- "prompts/**/*.md"
88
- "prompts/prompt.md"
99
- "src/app/**/*.ts"
10-
- "src/app/system_prompts/**/*.md"
10+
- "src/system_prompts/**/*.md"
1111
- "src/app/templates/*.md"
1212

1313
jobs:
@@ -20,7 +20,7 @@ jobs:
2020

2121
- name: Validate critical files
2222
run: |
23-
if [ ! -f "src/app/system_prompts/prompt_analysis_agent/prompt.md" ]; then
23+
if [ ! -f "src/system_prompts/prompt_analysis_agent/prompt.md" ]; then
2424
echo "Error: AI prompt analyzer file is missing"
2525
exit 1
2626
fi
@@ -58,7 +58,7 @@ jobs:
5858
- name: Check for system prompt changes
5959
id: check_changes
6060
run: |
61-
if git diff --name-only HEAD^ HEAD | grep -q "src/app/system_prompts/prompt_analysis_agent/"; then
61+
if git diff --name-only HEAD^ HEAD | grep -q "src/system_prompts/prompt_analysis_agent/"; then
6262
echo "FORCE_REGENERATE=true" >> $GITHUB_ENV
6363
else
6464
echo "FORCE_REGENERATE=false" >> $GITHUB_ENV

README.md

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,7 @@ Detailed setup instructions in [Getting Started](#-getting-started).
7171
prompt-library-cli
7272
```
7373

74-
For all CLI options, run:
7574

76-
```sh
77-
prompt-library-cli --help
78-
```
79-
80-
### List Prompts and Categories
81-
82-
```sh
83-
prompt-library-cli prompts --list
84-
prompt-library-cli prompts --categories
85-
```
8675

8776
### Sync Personal Library
8877

@@ -203,7 +192,7 @@ prompt-library-cli execute --help
203192

204193
Fragments are reusable prompt components:
205194

206-
1. Create `.md` files in `fragments` directory under the appropriate [categories](/src/app/system_prompts/prompt_analysis_agent/prompt.md)).
195+
1. Create `.md` files in `fragments` directory under the appropriate [categories](/src/system_prompts/prompt_analysis_agent/prompt.md)).
207196
2. Reference in prompts: `` (e.g., `` for `awesome_guidelines.md`).
208197
3. Manage and use via CLI.
209198

src/app/config/app.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const appConfig: AppConfig = {
1919
PROMPTS_DIR: 'prompts',
2020
FRAGMENTS_DIR: 'fragments',
2121
TEMPLATES_DIR: path.join('src', 'app', 'templates'),
22-
ANALYZER_PROMPT_PATH: path.join('src', 'app', 'system_prompts', 'prompt_analysis_agent', 'prompt.md'),
22+
ANALYZER_PROMPT_PATH: path.join('src', 'system_prompts', 'prompt_analysis_agent', 'prompt.md'),
2323
README_PATH: 'README.md',
2424
VIEW_FILE_NAME: 'README.md',
2525
VIEW_TEMPLATE_NAME: 'sub_readme.md',

src/app/templates/main_readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ prompt-library-cli execute --help
159159

160160
Fragments are reusable prompt components:
161161

162-
1. Create `.md` files in `fragments` directory under the appropriate [categories](/src/app/system_prompts/prompt_analysis_agent/prompt.md)).
162+
1. Create `.md` files in `fragments` directory under the appropriate [categories](/src/system_prompts/prompt_analysis_agent/prompt.md)).
163163
2. Reference in prompts: `{{FRAGMENT_NAME}}` (e.g., `{{AWESOME_GUIDELINES}}` for `awesome_guidelines.md`).
164164
3. Manage and use via CLI.
165165

src/app/utils/prompt_operations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export async function processMetadataGeneration(promptContent: string): Promise<
2424
PROMPT_TO_ANALYZE: promptContent,
2525
AVAILABLE_PROMPT_FRAGMENTS: availableFragments
2626
};
27-
const content = await processPromptContent(analyzerPrompt, variables, false);
27+
const content = await processPromptContent([{ role: 'user', content: analyzerPrompt }], variables, false);
2828
const yamlContent = extractOutputContent(content);
2929
return parseYamlContent(yamlContent);
3030
} catch (error) {

src/cli/commands/execute.command.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,15 +234,21 @@ Note:
234234
}
235235

236236
try {
237-
const result = await processPromptContent(promptContent, userInputs, false, undefined, (event) => {
238-
if (event.type === 'content_block_delta') {
239-
if ('text' in event.delta) {
240-
process.stdout.write(event.delta.text);
241-
} else if ('partial_json' in event.delta) {
242-
process.stdout.write(event.delta.partial_json);
237+
const result = await processPromptContent(
238+
[{ role: 'user', content: promptContent }],
239+
userInputs,
240+
!ciMode, // Use streaming if not in CI mode
241+
async (inputs) => inputs, // Simple pass-through function for resolveInputs
242+
(event) => {
243+
if (event.type === 'content_block_delta') {
244+
if ('text' in event.delta) {
245+
process.stdout.write(event.delta.text);
246+
} else if ('partial_json' in event.delta) {
247+
process.stdout.write(event.delta.partial_json);
248+
}
243249
}
244250
}
245-
});
251+
);
246252

247253
if (typeof result === 'string') {
248254
console.log(result);

src/cli/commands/prompts.command.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ class PromptCommand extends BaseCommand {
254254
return;
255255
}
256256

257-
await this.pressKeyToContinue();
257+
// await this.pressKeyToContinue();
258258
}
259259

260260
async assignValueToVariable(promptId: string, variable: Variable): Promise<void> {
@@ -448,8 +448,6 @@ class PromptCommand extends BaseCommand {
448448
);
449449

450450
if (result) {
451-
// console.log(result);
452-
453451
while (true) {
454452
const nextAction = await this.showMenu<'continue' | 'back'>('What would you like to do next?', [
455453
{ name: chalk.green(chalk.bold('Continue conversation')), value: 'continue' }
@@ -459,7 +457,7 @@ class PromptCommand extends BaseCommand {
459457

460458
const userInput = await this.getMultilineInput(chalk.blue('You: '));
461459
const response = await this.handleApiResult(
462-
await conversationManager.continueConversation(userInput, true),
460+
await conversationManager.continueConversation(userInput),
463461
'Continued conversation'
464462
);
465463

src/cli/utils/content.util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,4 @@ export async function hasFragments(): Promise<boolean> {
2323
console.error('Error checking fragments directory:', error);
2424
return false;
2525
}
26-
}
26+
}

src/cli/utils/conversation.util.ts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
import chalk from 'chalk';
1+
// Updated ConversationManager class
22

33
import { processCliPromptContent, resolveCliInputs } from './prompt.cli.util';
44
import { getPromptFiles } from './prompt.util';
55
import { ApiResult } from '../../shared/types';
66
import logger from '../../shared/utils/logger';
77
import { processPromptContent, processPromptWithVariables } from '../../shared/utils/prompt_operations';
88

9+
interface ConversationMessage {
10+
role: 'human' | 'assistant';
11+
content: string;
12+
}
13+
914
export class ConversationManager {
10-
private conversationContext: string;
15+
private messages: ConversationMessage[];
1116
private promptId: string;
1217

1318
constructor(promptId: string) {
1419
this.promptId = promptId;
15-
this.conversationContext = '';
20+
this.messages = [];
1621
}
1722

1823
async initializeConversation(
@@ -29,18 +34,14 @@ export class ConversationManager {
2934
const { promptContent } = promptFilesResult.data;
3035
const resolvedInputs = isExecuteCommand ? userInputs : await resolveCliInputs(userInputs);
3136
const updatedPromptContent = await processPromptWithVariables(promptContent, resolvedInputs);
32-
let result: string;
37+
this.messages.push({ role: 'human', content: updatedPromptContent });
3338

34-
if (isExecuteCommand) {
35-
result = await processPromptContent(updatedPromptContent, {}, false);
36-
} else {
37-
console.log(chalk.green('\nHuman:'), updatedPromptContent);
38-
console.log(chalk.green('AI:'));
39-
result = await processCliPromptContent(updatedPromptContent, {}, true);
40-
}
39+
const result = await (isExecuteCommand
40+
? processPromptContent(this.messages, {}, false)
41+
: processCliPromptContent(this.messages, {}, true));
4142

4243
if (typeof result === 'string') {
43-
this.conversationContext = `Initial Prompt:\n${updatedPromptContent}\n\nAI: ${result}`;
44+
this.messages.push({ role: 'assistant', content: result });
4445
return { success: true, data: result };
4546
} else {
4647
return { success: false, error: 'Unexpected result format' };
@@ -54,22 +55,16 @@ export class ConversationManager {
5455
}
5556
}
5657

57-
async continueConversation(userInput: string, useStreaming: boolean): Promise<ApiResult<string>> {
58+
async continueConversation(userInput: string, useStreaming: boolean = true): Promise<ApiResult<string>> {
5859
try {
59-
const continuationPrompt = `${this.conversationContext}\n\nHuman: ${userInput}\n\nAI:`;
60-
let result: string;
60+
this.messages.push({ role: 'human', content: userInput });
6161

62-
if (!useStreaming) {
63-
result = await processPromptContent(continuationPrompt, {}, false);
64-
} else {
65-
console.log(chalk.green('\nHuman:'), userInput);
66-
console.log(chalk.green('\nAI:'));
67-
result = await processCliPromptContent(continuationPrompt, {}, true);
68-
console.log();
69-
}
62+
const result = useStreaming
63+
? await processCliPromptContent(this.messages, {}, true)
64+
: await processPromptContent(this.messages, {}, false);
7065

7166
if (typeof result === 'string') {
72-
this.conversationContext += `\nHuman: ${userInput}\nAI: ${result}`;
67+
this.messages.push({ role: 'assistant', content: result });
7368
return { success: true, data: result };
7469
} else {
7570
return { success: false, error: 'Unexpected result format' };

src/cli/utils/prompt.cli.util.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ export async function resolveCliInputs(inputs: Record<string, string>): Promise<
4545
}
4646

4747
export async function processCliPromptContent(
48-
promptContent: string,
48+
messages: { role: string; content: string }[],
4949
inputs: Record<string, string> = {},
5050
useStreaming: boolean = true
5151
): Promise<string> {
52-
return processPromptContent(promptContent, inputs, useStreaming, resolveCliInputs, (event) => {
53-
if (event.type === 'content_block_delta') {
52+
return processPromptContent(messages, inputs, useStreaming, resolveCliInputs, (event) => {
53+
if (event.type === 'content_block_delta' && event.delta) {
5454
if ('text' in event.delta) {
5555
process.stdout.write(event.delta.text);
5656
} else if ('partial_json' in event.delta) {

src/cli/utils/prompt.util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export async function executePrompt(
7171
}
7272

7373
const { promptContent } = promptFilesResult.data;
74-
const result = await processPromptContent(promptContent, userInputs, useStreaming);
74+
const result = await processPromptContent([{ role: 'user', content: promptContent }], userInputs, useStreaming);
7575
return { success: true, data: result };
7676
} catch (error) {
7777
return {

src/shared/utils/anthropic_client.ts

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ import logger from './logger';
55
import { config } from '../config';
66
import { commonConfig } from '../config/common.config';
77

8-
/**
9-
* Initializes and returns an Anthropic client.
10-
* @throws {Error} If the ANTHROPIC_API_KEY is not set in the environment.
11-
* @returns {Anthropic} An initialized Anthropic client.
12-
*/
138
export function initializeAnthropicClient(): Anthropic {
149
const apiKey = commonConfig.ANTHROPIC_API_KEY;
1510

@@ -22,25 +17,19 @@ export function initializeAnthropicClient(): Anthropic {
2217
return new Anthropic({ apiKey });
2318
}
2419

25-
/**
26-
* Sends a request to the Anthropic API in classic mode.
27-
* @param {Anthropic} client - The initialized Anthropic client.
28-
* @param {string} prompt - The prompt to send to the API.
29-
* @returns {Promise<Message>} The response from the Anthropic API.
30-
* @throws {Error} If there's an error sending the request to the API.
31-
*/
32-
export async function sendAnthropicRequestClassic(client: Anthropic, prompt: string): Promise<Message> {
20+
export async function sendAnthropicRequestClassic(
21+
client: Anthropic,
22+
messages: { role: string; content: string }[]
23+
): Promise<Message> {
3324
try {
3425
logger.info('Sending classic request to Anthropic API');
3526
const message = await client.messages.create({
3627
model: commonConfig.ANTHROPIC_MODEL,
3728
max_tokens: commonConfig.ANTHROPIC_MAX_TOKENS,
38-
messages: [
39-
{
40-
role: 'user',
41-
content: prompt
42-
}
43-
]
29+
messages: messages.map((msg) => ({
30+
role: msg.role === 'human' ? 'user' : 'assistant',
31+
content: msg.content
32+
}))
4433
});
4534
logger.info('Received classic response from Anthropic API');
4635
return message;
@@ -50,28 +39,19 @@ export async function sendAnthropicRequestClassic(client: Anthropic, prompt: str
5039
}
5140
}
5241

53-
/**
54-
* Sends a request to the Anthropic API in streaming mode.
55-
* @param {Anthropic} client - The initialized Anthropic client.
56-
* @param {string} prompt - The prompt to send to the API.
57-
* @returns {AsyncGenerator<MessageStreamEvent>} An async generator of message stream events.
58-
* @throws {Error} If there's an error sending the request to the API.
59-
*/
6042
export async function* sendAnthropicRequestStream(
6143
client: Anthropic,
62-
prompt: string
44+
messages: { role: string; content: string }[]
6345
): AsyncGenerator<MessageStreamEvent> {
6446
try {
6547
logger.info('Sending streaming request to Anthropic API');
66-
const stream = await client.messages.stream({
48+
const stream = client.messages.stream({
6749
model: config.ANTHROPIC_MODEL,
6850
max_tokens: config.ANTHROPIC_MAX_TOKENS,
69-
messages: [
70-
{
71-
role: 'user',
72-
content: prompt
73-
}
74-
]
51+
messages: messages.map((msg) => ({
52+
role: msg.role === 'human' ? 'user' : 'assistant',
53+
content: msg.content
54+
}))
7555
});
7656

7757
for await (const event of stream) {
@@ -93,7 +73,7 @@ export async function validateAnthropicApiKey(): Promise<boolean> {
9373
try {
9474
const client = initializeAnthropicClient();
9575
// Attempt a simple request to validate the API key
96-
await sendAnthropicRequestClassic(client, 'Test request');
76+
await sendAnthropicRequestClassic(client, [{ role: 'user', content: 'Test request' }]);
9777
logger.info('Anthropic API key is valid');
9878
return true;
9979
} catch (error) {

0 commit comments

Comments
 (0)