@stackfactor/agent-utils 1.0.0 → 1.0.1
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/README.md +293 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# @stackfactor/agent-utils
|
|
2
|
+
|
|
3
|
+
Shared utilities for StackFactor AI agent services — LangChain helpers, structured logging, error handling, and constants.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @stackfactor/agent-utils
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Modules
|
|
12
|
+
|
|
13
|
+
The package exports four modules:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { langChain, logger, errorHandling, constants } from "@stackfactor/agent-utils";
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## `langChain`
|
|
22
|
+
|
|
23
|
+
Unified interface for running LLM prompts, managing LangChain agents, and generating images across OpenAI, Anthropic, and Google providers.
|
|
24
|
+
|
|
25
|
+
### `langChain.runPromptWithModel(modelName, config, prompt, onProgressReport?, minPercent?, maxPercent?, expectsJsonResponse?, schema?, agentName?, tools?)`
|
|
26
|
+
|
|
27
|
+
Sends a prompt to an LLM and returns the response. Supports three execution modes:
|
|
28
|
+
|
|
29
|
+
- **Agentic** (`config.agentic === true`) — creates and runs a LangChain agent with tools.
|
|
30
|
+
- **Streaming** (`onProgressReport` provided) — streams the response with progress callbacks. Uses native `response_format` for OpenAI+schema, or NDJSON for other providers.
|
|
31
|
+
- **Non-streaming** — direct invocation with JSON extraction.
|
|
32
|
+
|
|
33
|
+
When `expectsJsonResponse` is `true` (the default), JSON escape instructions are injected and the response is parsed. If a Zod `schema` is provided, the parsed result is validated.
|
|
34
|
+
|
|
35
|
+
| Parameter | Type | Default | Description |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `modelName` | `string` | — | Model identifier: `"gpt-4o"`, `"claude-3-5-sonnet"`, `"gemini-1.5-pro"`, etc. |
|
|
38
|
+
| `config` | `object` | — | API keys (`openAIAPIKey`, `anthropicAPIKey`, `googleAPIKey`), `temperature`, `agentic`, `recursionLimit` |
|
|
39
|
+
| `prompt` | `string \| object[]` | — | Plain string or array of `{ role, content }` message objects |
|
|
40
|
+
| `onProgressReport` | `function \| null` | `null` | Async callback receiving `{ message, progress }` updates |
|
|
41
|
+
| `minPercent` | `number` | `0` | Lower bound for progress percentage |
|
|
42
|
+
| `maxPercent` | `number` | `100` | Upper bound for progress percentage |
|
|
43
|
+
| `expectsJsonResponse` | `boolean` | `true` | Parse response as JSON |
|
|
44
|
+
| `schema` | `ZodSchema \| null` | `null` | Zod schema for response validation |
|
|
45
|
+
| `agentName` | `string` | `"StackFactor"` | Display name for the agent (agentic mode) |
|
|
46
|
+
| `tools` | `any[]` | `[]` | LangChain tools available to the agent (agentic mode) |
|
|
47
|
+
|
|
48
|
+
**Returns:** JSON string (when `expectsJsonResponse` is `true`) or raw content string.
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
const result = await langChain.runPromptWithModel(
|
|
52
|
+
"gpt-4o",
|
|
53
|
+
{ openAIAPIKey: "sk-..." },
|
|
54
|
+
"Generate a summary of this document.",
|
|
55
|
+
);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### `langChain.runChatPromptWithModel(modelName, config, prompt, onProgressReport?)`
|
|
61
|
+
|
|
62
|
+
Sends a conversational chat prompt to an LLM and returns a plain HTML response. Built for the StackFactor Mentor chat feature — system messages are wrapped with topic-constraint instructions that decline off-topic questions.
|
|
63
|
+
|
|
64
|
+
| Parameter | Type | Default | Description |
|
|
65
|
+
|---|---|---|---|
|
|
66
|
+
| `modelName` | `string` | — | Model identifier |
|
|
67
|
+
| `config` | `object` | — | API keys and optional `temperature` |
|
|
68
|
+
| `prompt` | `string \| object[]` | — | Plain string or array of `{ role, content }` messages |
|
|
69
|
+
| `onProgressReport` | `function \| null` | `null` | Streaming progress callback |
|
|
70
|
+
|
|
71
|
+
**Returns:** Raw HTML string.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
const html = await langChain.runChatPromptWithModel(
|
|
75
|
+
"claude-3-5-sonnet",
|
|
76
|
+
{ anthropicAPIKey: "sk-ant-..." },
|
|
77
|
+
[
|
|
78
|
+
{ role: "system", content: "Topic: JavaScript closures" },
|
|
79
|
+
{ role: "user", content: "Explain closures with an example" },
|
|
80
|
+
],
|
|
81
|
+
);
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
### `langChain.createAIAgent(name, modelName, systemPrompt, tools?, responseFormat?, config, onReportProgress?, minPercent?, maxPercent?)`
|
|
87
|
+
|
|
88
|
+
Constructs a LangChain agent with a model, system prompt, and tools. When `onReportProgress` is provided, a `report_progress` tool is automatically added.
|
|
89
|
+
|
|
90
|
+
| Parameter | Type | Default | Description |
|
|
91
|
+
|---|---|---|---|
|
|
92
|
+
| `name` | `string` | — | Display name for the agent |
|
|
93
|
+
| `modelName` | `string` | — | LLM identifier |
|
|
94
|
+
| `systemPrompt` | `string` | — | System prompt describing agent behaviour |
|
|
95
|
+
| `tools` | `any[]` | `[]` | LangChain tool instances |
|
|
96
|
+
| `responseFormat` | `any` | — | Structured response format descriptor |
|
|
97
|
+
| `config` | `object` | — | API keys, temperature, etc. |
|
|
98
|
+
| `onReportProgress` | `Function \| null` | `null` | Progress callback |
|
|
99
|
+
| `minPercent` | `number` | `0` | Minimum reportable progress |
|
|
100
|
+
| `maxPercent` | `number` | `100` | Maximum reportable progress |
|
|
101
|
+
|
|
102
|
+
**Returns:** A configured LangChain agent instance.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### `langChain.runAIAgent(agent, prompt, config, onProgress?)`
|
|
107
|
+
|
|
108
|
+
Executes a LangChain agent with a user prompt. Registers callbacks for `tool_start`, `tool_end`, `agent_action`, and error events when `onProgress` is provided. Logs execution time on completion.
|
|
109
|
+
|
|
110
|
+
| Parameter | Type | Default | Description |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| `agent` | `any` | — | Agent created by `createAIAgent` |
|
|
113
|
+
| `prompt` | `string` | — | User message to send |
|
|
114
|
+
| `config` | `object` | — | `recursionLimit` (default: `25`) |
|
|
115
|
+
| `onProgress` | `Function \| null` | `null` | Progress event callback |
|
|
116
|
+
|
|
117
|
+
**Returns:** Raw response from the agent's `invoke` method.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const agent = langChain.createAIAgent(
|
|
121
|
+
"Summarizer",
|
|
122
|
+
"gpt-4o",
|
|
123
|
+
"You summarize documents concisely.",
|
|
124
|
+
[],
|
|
125
|
+
null,
|
|
126
|
+
{ openAIAPIKey: "sk-..." },
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const response = await langChain.runAIAgent(agent, "Summarize this text...", {});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
### `langChain.runPromptWithModelForImageGeneration(modelName, config, prompt, options?)`
|
|
135
|
+
|
|
136
|
+
Generates an image using OpenAI or Google AI models.
|
|
137
|
+
|
|
138
|
+
| Parameter | Type | Default | Description |
|
|
139
|
+
|---|---|---|---|
|
|
140
|
+
| `modelName` | `string` | — | Image model: `"dall-e-3"`, `"gpt-image-1.5"`, `"imagen-4.0-generate-001"`, `"gemini-3.0-pro-image"`, etc. |
|
|
141
|
+
| `config` | `object` | — | `openAIAPIKey` or `googleAPIKey` |
|
|
142
|
+
| `prompt` | `string` | — | Text prompt describing the image |
|
|
143
|
+
| `options` | `object` | `{}` | Provider-specific options (see below) |
|
|
144
|
+
|
|
145
|
+
**OpenAI options:** `size` (`"1024x1024"`, `"1792x1024"`, etc.), `style` (`"vivid"` or `"natural"`), `responseFormat` (`"url"` or `"b64_json"`), `n` (number of images).
|
|
146
|
+
|
|
147
|
+
**Google options:** `aspectRatio` (`"1:1"`, `"3:4"`, `"4:3"`, `"9:16"`, `"16:9"`), `numberOfImages`, `negativePrompt`.
|
|
148
|
+
|
|
149
|
+
**Returns:** `{ url?, b64_json?, revisedPrompt? }` for single images, or `{ images: [...] }` for multiple.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
const image = await langChain.runPromptWithModelForImageGeneration(
|
|
153
|
+
"dall-e-3",
|
|
154
|
+
{ openAIAPIKey: "sk-..." },
|
|
155
|
+
"A futuristic city skyline at sunset",
|
|
156
|
+
{ size: "1792x1024" },
|
|
157
|
+
);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### `langChain.throwErrorIfNotSuccessful(response)`
|
|
163
|
+
|
|
164
|
+
Guards that a response is a non-empty string. Throws an `INTERNAL_SERVER_ERROR` if not.
|
|
165
|
+
|
|
166
|
+
| Parameter | Type | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `response` | `any` | Value to validate |
|
|
169
|
+
|
|
170
|
+
**Returns:** The response string if valid.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## `logger`
|
|
175
|
+
|
|
176
|
+
GCP-compatible structured logging via Winston with OpenTelemetry trace enrichment.
|
|
177
|
+
|
|
178
|
+
### `logger.log(request, level, message, options?)`
|
|
179
|
+
|
|
180
|
+
Writes a structured log entry. Automatically enriches with OpenTelemetry `traceId` and `spanId` when an active span exists. Prepends the user's email from the request object when available.
|
|
181
|
+
|
|
182
|
+
| Parameter | Type | Default | Description |
|
|
183
|
+
|---|---|---|---|
|
|
184
|
+
| `request` | `any` | — | HTTP request object (reads `request.user.email`), or `null` |
|
|
185
|
+
| `level` | `LogLevel` | — | `"error"`, `"warn"`, `"info"`, `"http"`, `"verbose"`, `"debug"`, `"silly"` |
|
|
186
|
+
| `message` | `string` | — | Log message |
|
|
187
|
+
| `options` | `object` | `{}` | Additional structured fields (`service`, `requestId`, etc.) |
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
logger.log(req, logger.levels.info, "User signed in", { service: "auth" });
|
|
191
|
+
logger.log(null, logger.levels.error, "Connection failed");
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `logger.levels`
|
|
195
|
+
|
|
196
|
+
Enum-like object mapping level names to their string values:
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
logger.levels.error // "error"
|
|
200
|
+
logger.levels.warn // "warn"
|
|
201
|
+
logger.levels.info // "info"
|
|
202
|
+
logger.levels.http // "http"
|
|
203
|
+
logger.levels.verbose // "verbose"
|
|
204
|
+
logger.levels.debug // "debug"
|
|
205
|
+
logger.levels.silly // "silly"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## `errorHandling`
|
|
211
|
+
|
|
212
|
+
Factory for consistently shaped error payloads.
|
|
213
|
+
|
|
214
|
+
### `errorHandling.create(errorCode, errorMessage, details?)`
|
|
215
|
+
|
|
216
|
+
Creates a structured error object with a stack trace.
|
|
217
|
+
|
|
218
|
+
| Parameter | Type | Default | Description |
|
|
219
|
+
|---|---|---|---|
|
|
220
|
+
| `errorCode` | `number` | — | HTTP status code or application error code |
|
|
221
|
+
| `errorMessage` | `string` | — | Human-readable error description |
|
|
222
|
+
| `details` | `any` | `null` | Optional supplementary information |
|
|
223
|
+
|
|
224
|
+
**Returns:** `{ code, message, details, stack }`
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
throw errorHandling.create(404, "User not found");
|
|
228
|
+
throw errorHandling.create(400, "Validation failed", { field: "email" });
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## `constants`
|
|
234
|
+
|
|
235
|
+
Shared constants used across the package.
|
|
236
|
+
|
|
237
|
+
### `constants.HTTP_CODES`
|
|
238
|
+
|
|
239
|
+
| Constant | Value |
|
|
240
|
+
|---|---|
|
|
241
|
+
| `BAD_REQUEST` | `400` |
|
|
242
|
+
| `UNPROCESSABLE_ENTITY` | `422` |
|
|
243
|
+
| `INTERNAL_SERVER_ERROR` | `500` |
|
|
244
|
+
| `BAD_GATEWAY` | `502` |
|
|
245
|
+
|
|
246
|
+
### `constants.ERROR`
|
|
247
|
+
|
|
248
|
+
| Constant | Value |
|
|
249
|
+
|---|---|
|
|
250
|
+
| `UNABLE_TO_GENERATE_CONTENT` | `"Unable to generate content"` |
|
|
251
|
+
| `UNEXPECTED_ERROR` | `"An unexpected error occured..."` |
|
|
252
|
+
| `UNSUPPORTED_MODEL` | `"The specified model is not supported"` |
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Supported Models
|
|
257
|
+
|
|
258
|
+
### Text / Chat
|
|
259
|
+
|
|
260
|
+
| Provider | Model Prefix | Example |
|
|
261
|
+
|---|---|---|
|
|
262
|
+
| OpenAI | `gpt-` | `gpt-4o`, `gpt-4o-mini` |
|
|
263
|
+
| Anthropic | `claude-` | `claude-3-5-sonnet`, `claude-3-opus` |
|
|
264
|
+
| Google | `gemini-` | `gemini-1.5-pro`, `gemini-2.0-flash` |
|
|
265
|
+
|
|
266
|
+
### Image Generation
|
|
267
|
+
|
|
268
|
+
| Provider | Model Prefix | Example |
|
|
269
|
+
|---|---|---|
|
|
270
|
+
| OpenAI | `dall-e-`, `gpt-image-` | `dall-e-3`, `gpt-image-1.5` |
|
|
271
|
+
| Google | `imagen-`, `gemini-` | `imagen-4.0-generate-001`, `gemini-3.0-pro-image` |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Config Object
|
|
276
|
+
|
|
277
|
+
The `config` object accepted by LangChain methods supports the following keys:
|
|
278
|
+
|
|
279
|
+
| Key | Type | Description |
|
|
280
|
+
|---|---|---|
|
|
281
|
+
| `openAIAPIKey` | `string` | OpenAI API key |
|
|
282
|
+
| `anthropicAPIKey` | `string` | Anthropic API key |
|
|
283
|
+
| `googleAPIKey` | `string` | Google AI API key |
|
|
284
|
+
| `temperature` | `number` | Sampling temperature |
|
|
285
|
+
| `maxTokens` | `number` | Maximum output tokens (default: `200000`) |
|
|
286
|
+
| `agentic` | `boolean` | Enable agentic mode in `runPromptWithModel` |
|
|
287
|
+
| `recursionLimit` | `number` | Max agent steps (default: `25`) |
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## License
|
|
292
|
+
|
|
293
|
+
Not licensed — proprietary software of StackFactor Inc.
|