@loopstack/claude-module 0.21.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/dist/claude.module.d.ts +3 -0
- package/dist/claude.module.d.ts.map +1 -0
- package/dist/claude.module.js +40 -0
- package/dist/claude.module.js.map +1 -0
- package/dist/documents/claude-message-document.d.ts +14 -0
- package/dist/documents/claude-message-document.d.ts.map +1 -0
- package/dist/documents/claude-message-document.js +41 -0
- package/dist/documents/claude-message-document.js.map +1 -0
- package/dist/documents/claude-message-document.yaml +5 -0
- package/dist/documents/index.d.ts +2 -0
- package/dist/documents/index.d.ts.map +1 -0
- package/dist/documents/index.js +18 -0
- package/dist/documents/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/claude-generate-tool-base.schema.d.ts +20 -0
- package/dist/schemas/claude-generate-tool-base.schema.d.ts.map +1 -0
- package/dist/schemas/claude-generate-tool-base.schema.js +24 -0
- package/dist/schemas/claude-generate-tool-base.schema.js.map +1 -0
- package/dist/services/claude-client.service.d.ts +8 -0
- package/dist/services/claude-client.service.d.ts.map +1 -0
- package/dist/services/claude-client.service.js +40 -0
- package/dist/services/claude-client.service.js.map +1 -0
- package/dist/services/claude-messages-helper.service.d.ts +10 -0
- package/dist/services/claude-messages-helper.service.d.ts.map +1 -0
- package/dist/services/claude-messages-helper.service.js +39 -0
- package/dist/services/claude-messages-helper.service.js.map +1 -0
- package/dist/services/claude-tools-helper.service.d.ts +6 -0
- package/dist/services/claude-tools-helper.service.d.ts.map +1 -0
- package/dist/services/claude-tools-helper.service.js +43 -0
- package/dist/services/claude-tools-helper.service.js.map +1 -0
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +20 -0
- package/dist/services/index.js.map +1 -0
- package/dist/tools/claude-delegate-tool-call.tool.d.ts +19 -0
- package/dist/tools/claude-delegate-tool-call.tool.d.ts.map +1 -0
- package/dist/tools/claude-delegate-tool-call.tool.js +102 -0
- package/dist/tools/claude-delegate-tool-call.tool.js.map +1 -0
- package/dist/tools/claude-generate-document.tool.d.ts +10 -0
- package/dist/tools/claude-generate-document.tool.d.ts.map +1 -0
- package/dist/tools/claude-generate-document.tool.js +64 -0
- package/dist/tools/claude-generate-document.tool.js.map +1 -0
- package/dist/tools/claude-generate-object.tool.d.ts +33 -0
- package/dist/tools/claude-generate-object.tool.d.ts.map +1 -0
- package/dist/tools/claude-generate-object.tool.js +131 -0
- package/dist/tools/claude-generate-object.tool.js.map +1 -0
- package/dist/tools/claude-generate-text.tool.d.ts +32 -0
- package/dist/tools/claude-generate-text.tool.d.ts.map +1 -0
- package/dist/tools/claude-generate-text.tool.js +112 -0
- package/dist/tools/claude-generate-text.tool.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +21 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types/claude.types.d.ts +19 -0
- package/dist/types/claude.types.d.ts.map +1 -0
- package/dist/types/claude.types.js +9 -0
- package/dist/types/claude.types.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +18 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cache.utils.d.ts +11 -0
- package/dist/utils/cache.utils.d.ts.map +1 -0
- package/dist/utils/cache.utils.js +36 -0
- package/dist/utils/cache.utils.js.map +1 -0
- package/package.json +76 -0
- package/src/claude.module.ts +32 -0
- package/src/documents/claude-message-document.ts +26 -0
- package/src/documents/claude-message-document.yaml +5 -0
- package/src/documents/index.ts +1 -0
- package/src/index.ts +3 -0
- package/src/schemas/claude-generate-tool-base.schema.ts +23 -0
- package/src/services/claude-client.service.ts +34 -0
- package/src/services/claude-messages-helper.service.ts +41 -0
- package/src/services/claude-tools-helper.service.ts +38 -0
- package/src/services/index.ts +3 -0
- package/src/tools/claude-delegate-tool-call.tool.ts +125 -0
- package/src/tools/claude-generate-document.tool.ts +66 -0
- package/src/tools/claude-generate-object.tool.ts +151 -0
- package/src/tools/claude-generate-text.tool.ts +120 -0
- package/src/tools/index.ts +4 -0
- package/src/types/claude.types.ts +34 -0
- package/src/types/index.ts +1 -0
- package/src/utils/cache.utils.ts +59 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import { Inject } from '@nestjs/common';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import {
|
|
5
|
+
Input,
|
|
6
|
+
RunContext,
|
|
7
|
+
Tool,
|
|
8
|
+
ToolInterface,
|
|
9
|
+
ToolResult,
|
|
10
|
+
WorkflowInterface,
|
|
11
|
+
WorkflowMetadataInterface,
|
|
12
|
+
} from '@loopstack/common';
|
|
13
|
+
import { ClaudeGenerateToolBaseSchema } from '../schemas/claude-generate-tool-base.schema';
|
|
14
|
+
import { ClaudeClientService } from '../services';
|
|
15
|
+
import { ClaudeMessagesHelperService } from '../services';
|
|
16
|
+
import { ClaudeToolsHelperService } from '../services';
|
|
17
|
+
import { applyCacheBreakpoints } from '../utils/cache.utils';
|
|
18
|
+
|
|
19
|
+
export const ClaudeGenerateTextSchema = ClaudeGenerateToolBaseSchema.extend({
|
|
20
|
+
tools: z.array(z.string()).optional(),
|
|
21
|
+
}).strict();
|
|
22
|
+
|
|
23
|
+
type ClaudeGenerateTextArgsType = z.infer<typeof ClaudeGenerateTextSchema>;
|
|
24
|
+
|
|
25
|
+
@Tool({
|
|
26
|
+
config: {
|
|
27
|
+
description: 'Generates text using the Anthropic Claude API',
|
|
28
|
+
},
|
|
29
|
+
})
|
|
30
|
+
export class ClaudeGenerateText implements ToolInterface<ClaudeGenerateTextArgsType> {
|
|
31
|
+
@Inject()
|
|
32
|
+
private readonly claudeClientService: ClaudeClientService;
|
|
33
|
+
@Inject()
|
|
34
|
+
private readonly claudeMessagesHelperService: ClaudeMessagesHelperService;
|
|
35
|
+
@Inject()
|
|
36
|
+
private readonly claudeToolsHelperService: ClaudeToolsHelperService;
|
|
37
|
+
|
|
38
|
+
@Input({
|
|
39
|
+
schema: ClaudeGenerateTextSchema,
|
|
40
|
+
})
|
|
41
|
+
args: ClaudeGenerateTextArgsType;
|
|
42
|
+
|
|
43
|
+
async execute(
|
|
44
|
+
args: ClaudeGenerateTextArgsType,
|
|
45
|
+
ctx: RunContext,
|
|
46
|
+
parent: WorkflowInterface,
|
|
47
|
+
runtime: WorkflowMetadataInterface,
|
|
48
|
+
): Promise<ToolResult> {
|
|
49
|
+
const client = this.claudeClientService.getClient(args.claude);
|
|
50
|
+
const model = this.claudeClientService.getModel(args.claude);
|
|
51
|
+
|
|
52
|
+
const messages: Anthropic.MessageParam[] = [];
|
|
53
|
+
|
|
54
|
+
if (args.prompt) {
|
|
55
|
+
messages.push({ role: 'user', content: args.prompt });
|
|
56
|
+
} else {
|
|
57
|
+
const resolved = this.claudeMessagesHelperService.getMessages(runtime.documents, {
|
|
58
|
+
messages: args.messages as Anthropic.MessageParam[],
|
|
59
|
+
messagesSearchTag: args.messagesSearchTag,
|
|
60
|
+
});
|
|
61
|
+
messages.push(...resolved);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const tools = args.tools ? this.claudeToolsHelperService.getTools(args.tools, parent) : undefined;
|
|
65
|
+
|
|
66
|
+
const response = await this.handleGenerateText(client, {
|
|
67
|
+
model,
|
|
68
|
+
messages,
|
|
69
|
+
system: args.system,
|
|
70
|
+
maxTokens: args.claude?.maxTokens,
|
|
71
|
+
tools,
|
|
72
|
+
cache: args.claude?.cache,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
data: response,
|
|
77
|
+
metadata: {
|
|
78
|
+
usage: {
|
|
79
|
+
inputTokens: response.usage.input_tokens,
|
|
80
|
+
outputTokens: response.usage.output_tokens,
|
|
81
|
+
cacheCreationInputTokens: response.usage.cache_creation_input_tokens ?? 0,
|
|
82
|
+
cacheReadInputTokens: response.usage.cache_read_input_tokens ?? 0,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private async handleGenerateText(
|
|
89
|
+
client: Anthropic,
|
|
90
|
+
options: {
|
|
91
|
+
model: string;
|
|
92
|
+
messages: Anthropic.MessageParam[];
|
|
93
|
+
system?: string;
|
|
94
|
+
maxTokens?: number;
|
|
95
|
+
tools?: Anthropic.Tool[];
|
|
96
|
+
cache?: boolean;
|
|
97
|
+
},
|
|
98
|
+
): Promise<Anthropic.Message> {
|
|
99
|
+
const { system, tools, messages } = options.cache
|
|
100
|
+
? applyCacheBreakpoints({ system: options.system, tools: options.tools, messages: options.messages })
|
|
101
|
+
: { system: options.system, tools: options.tools, messages: options.messages };
|
|
102
|
+
|
|
103
|
+
const startTime = performance.now();
|
|
104
|
+
try {
|
|
105
|
+
const stream = client.messages.stream({
|
|
106
|
+
model: options.model,
|
|
107
|
+
messages,
|
|
108
|
+
max_tokens: options.maxTokens ?? 4096,
|
|
109
|
+
...(system ? { system } : {}),
|
|
110
|
+
...(tools ? { tools } : {}),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return await stream.finalMessage();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
const errorResponseTime = performance.now() - startTime;
|
|
116
|
+
console.error(`Request failed after ${errorResponseTime}ms:`, error);
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for creating a Claude client and selecting a model.
|
|
5
|
+
*/
|
|
6
|
+
export interface ClaudeModelConfig {
|
|
7
|
+
/** Model name (e.g. 'claude-sonnet-4-20250514'). Falls back to CLAUDE_MODEL env var. */
|
|
8
|
+
model?: string;
|
|
9
|
+
/** Environment variable name containing the API key. Falls back to ANTHROPIC_API_KEY. */
|
|
10
|
+
envApiKey?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Options for a Claude messages API call.
|
|
15
|
+
*/
|
|
16
|
+
export interface ClaudeGenerateOptions {
|
|
17
|
+
messages: Anthropic.MessageParam[];
|
|
18
|
+
system?: string;
|
|
19
|
+
tools?: Anthropic.Tool[];
|
|
20
|
+
maxTokens?: number;
|
|
21
|
+
toolChoice?: Anthropic.MessageCreateParams['tool_choice'];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A tool definition in Anthropic's native format.
|
|
26
|
+
*/
|
|
27
|
+
export interface ClaudeToolDefinition {
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
input_schema: Anthropic.Tool['input_schema'];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Re-export Anthropic namespace for consumer convenience
|
|
34
|
+
export { default as Anthropic } from '@anthropic-ai/sdk';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './claude.types';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
|
|
3
|
+
const CACHE_CONTROL: Anthropic.CacheControlEphemeral = { type: 'ephemeral' };
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a copy of the API call options with prompt caching breakpoints applied.
|
|
7
|
+
*
|
|
8
|
+
* Breakpoints are placed on:
|
|
9
|
+
* 1. The system prompt (stable across turns)
|
|
10
|
+
* 2. The last tool definition (stable across turns)
|
|
11
|
+
* 3. The last content block of the last message (covers growing conversation)
|
|
12
|
+
*
|
|
13
|
+
* Does not mutate the input — returns new objects with cache_control markers.
|
|
14
|
+
*/
|
|
15
|
+
export function applyCacheBreakpoints(options: {
|
|
16
|
+
system?: string | Anthropic.TextBlockParam[];
|
|
17
|
+
tools?: Anthropic.Tool[];
|
|
18
|
+
messages: Anthropic.MessageParam[];
|
|
19
|
+
}): {
|
|
20
|
+
system?: string | Anthropic.TextBlockParam[];
|
|
21
|
+
tools?: Anthropic.Tool[];
|
|
22
|
+
messages: Anthropic.MessageParam[];
|
|
23
|
+
} {
|
|
24
|
+
// 1. System prompt → convert string to block array with cache_control
|
|
25
|
+
let system: string | Anthropic.TextBlockParam[] | undefined = options.system;
|
|
26
|
+
if (system && typeof system === 'string') {
|
|
27
|
+
system = [{ type: 'text', text: system, cache_control: CACHE_CONTROL }];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 2. Last tool definition — shallow-clone the array and mark the last entry
|
|
31
|
+
let tools = options.tools;
|
|
32
|
+
if (tools?.length) {
|
|
33
|
+
tools = [...tools];
|
|
34
|
+
const last = tools.length - 1;
|
|
35
|
+
tools[last] = { ...tools[last], cache_control: CACHE_CONTROL };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// 3. Last message — clone only the last message and mark its last content block
|
|
39
|
+
let messages = options.messages;
|
|
40
|
+
if (messages.length > 0) {
|
|
41
|
+
messages = [...messages];
|
|
42
|
+
const lastIdx = messages.length - 1;
|
|
43
|
+
const lastMsg = messages[lastIdx];
|
|
44
|
+
|
|
45
|
+
if (typeof lastMsg.content === 'string') {
|
|
46
|
+
messages[lastIdx] = {
|
|
47
|
+
...lastMsg,
|
|
48
|
+
content: [{ type: 'text', text: lastMsg.content, cache_control: CACHE_CONTROL }],
|
|
49
|
+
};
|
|
50
|
+
} else if (Array.isArray(lastMsg.content) && lastMsg.content.length > 0) {
|
|
51
|
+
const blocks: Anthropic.ContentBlockParam[] = [...lastMsg.content];
|
|
52
|
+
const lastBlockIdx = blocks.length - 1;
|
|
53
|
+
blocks[lastBlockIdx] = { ...blocks[lastBlockIdx], cache_control: CACHE_CONTROL } as Anthropic.ContentBlockParam;
|
|
54
|
+
messages[lastIdx] = { ...lastMsg, content: blocks };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return { system, tools, messages };
|
|
59
|
+
}
|