wirejs-deploy-amplify-basic 0.1.146-llm → 0.1.148-llm

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.
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "dependencies": {
4
4
  "jsdom": "^25.0.1",
5
- "wirejs-dom": "^1.0.42",
6
- "wirejs-resources": "^0.1.146-llm"
5
+ "wirejs-dom": "^1.0.44",
6
+ "wirejs-resources": "^0.1.148-llm"
7
7
  }
8
8
  }
@@ -1,4 +1,4 @@
1
- import { LLM as BaseLLM, LLMMessage, LLMChunk, Resource } from 'wirejs-resources';
1
+ import { LLM as BaseLLM, LLMMessage, ContinueConversationOptions, Resource } from 'wirejs-resources';
2
2
  export declare class LLM extends BaseLLM {
3
3
  private bedrockClient;
4
4
  constructor(scope: Resource | string, id: string, options: {
@@ -11,5 +11,5 @@ export declare class LLM extends BaseLLM {
11
11
  private invokeBedrock;
12
12
  private streamBedrock;
13
13
  private invokeModel;
14
- continueConversation(history: LLMMessage[], onChunk?: (chunk: LLMChunk) => void | Promise<void>): Promise<LLMMessage>;
14
+ continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, }: ContinueConversationOptions): Promise<LLMMessage>;
15
15
  }
@@ -39,33 +39,37 @@ export class LLM extends BaseLLM {
39
39
  };
40
40
  return modelMap[model] || model;
41
41
  }
42
- async invokeBedrock(modelId, messages, stream) {
42
+ async invokeBedrock(modelId, systemPrompt, messages, stream, abortSignal) {
43
43
  if (stream) {
44
44
  const command = new ConverseStreamCommand({
45
45
  modelId,
46
46
  messages: this.convertToBedrockFormat(messages),
47
- system: this.systemPrompt ? [{
48
- text: this.systemPrompt
47
+ system: systemPrompt ? [{
48
+ text: systemPrompt
49
49
  }] : undefined
50
50
  });
51
- return await this.bedrockClient.send(command);
51
+ return await this.bedrockClient.send(command, { abortSignal });
52
52
  }
53
53
  else {
54
54
  const command = new ConverseCommand({
55
55
  modelId,
56
56
  messages: this.convertToBedrockFormat(messages),
57
- system: this.systemPrompt ? [{
58
- text: this.systemPrompt
57
+ system: systemPrompt ? [{
58
+ text: systemPrompt
59
59
  }] : undefined
60
60
  });
61
- return await this.bedrockClient.send(command);
61
+ return await this.bedrockClient.send(command, { abortSignal });
62
62
  }
63
63
  }
64
- async streamBedrock(response, onChunk) {
64
+ async streamBedrock(response, onChunk, abortSignal) {
65
65
  if (!response.stream)
66
66
  return null;
67
67
  let content = '';
68
68
  for await (const chunk of response.stream) {
69
+ // Check if request was aborted
70
+ if (abortSignal?.aborted) {
71
+ throw new Error('Request was cancelled');
72
+ }
69
73
  const chunkText = chunk.contentBlockDelta?.delta?.text;
70
74
  if (chunkText) {
71
75
  content += chunkText;
@@ -92,16 +96,16 @@ export class LLM extends BaseLLM {
92
96
  content
93
97
  };
94
98
  }
95
- async invokeModel(model, history, onChunk, maxRetries = 10) {
99
+ async invokeModel(model, systemPrompt, history, onChunk, abortSignal, maxRetries = 10) {
96
100
  const stream = typeof onChunk === 'function';
97
101
  for (let i = 0; i < maxRetries; i++) {
98
102
  try {
99
103
  const modelId = this.getModelId(model);
100
104
  if (modelId !== model)
101
105
  console.log(`Mapped ${model} to ${modelId}`);
102
- const response = await this.invokeBedrock(modelId, history, stream);
106
+ const response = await this.invokeBedrock(modelId, systemPrompt, history, stream, abortSignal);
103
107
  if (stream) {
104
- return this.streamBedrock(response, onChunk);
108
+ return this.streamBedrock(response, onChunk, abortSignal);
105
109
  }
106
110
  else {
107
111
  const data = JSON.parse(new TextDecoder().decode(response.body));
@@ -112,6 +116,9 @@ export class LLM extends BaseLLM {
112
116
  }
113
117
  }
114
118
  catch (error) {
119
+ if (error.name === 'AbortError') {
120
+ throw new Error('Request was cancelled');
121
+ }
115
122
  if (error.name === 'ThrottlingException') {
116
123
  console.warn(`ThrottlingException encountered for model ${model}. Retrying...`);
117
124
  await new Promise(resolve => setTimeout(resolve, i * 1000 + Math.random() * 1000));
@@ -124,27 +131,51 @@ export class LLM extends BaseLLM {
124
131
  }
125
132
  throw new Error("Exceeded max retries trying to invoke " + model);
126
133
  }
127
- async continueConversation(history, onChunk) {
128
- // models are expected to be given in priority order. first one that doesn't
129
- // throw a fit wins.
130
- for (const model of this.models) {
131
- try {
132
- const result = await this.invokeModel(model, history, onChunk);
133
- if (!result)
134
- throw new Error("No response from model.");
135
- return result;
136
- }
137
- catch (error) {
138
- console.log(`Attempt failed with model: ${model}`);
139
- console.error(error);
140
- if (error.name === 'ValidationException' && error.message?.includes('model')) {
141
- continue;
134
+ async continueConversation({ history, onChunk, timeoutSeconds, systemPrompt, }) {
135
+ const controller = new AbortController();
136
+ let timeoutId;
137
+ if (timeoutSeconds) {
138
+ timeoutId = setTimeout(() => {
139
+ controller.abort();
140
+ }, timeoutSeconds * 1000);
141
+ }
142
+ try {
143
+ // models are expected to be given in priority order. first one that doesn't
144
+ // throw a fit wins.
145
+ for (const model of this.models) {
146
+ try {
147
+ const result = await this.invokeModel(model, (systemPrompt ?? this.systemPrompt) ?? '', history, onChunk, controller.signal);
148
+ if (!result)
149
+ throw new Error("No response from model.");
150
+ if (timeoutId) {
151
+ clearTimeout(timeoutId);
152
+ }
153
+ return result;
142
154
  }
143
- if (error.name === 'AccessDeniedException') {
144
- continue;
155
+ catch (error) {
156
+ if (error.name === 'AbortError' || error.message?.includes('cancelled')) {
157
+ throw new Error(`Request timed out after ${timeoutSeconds} seconds`);
158
+ }
159
+ console.log(`Attempt failed with model: ${model}`);
160
+ console.error(error);
161
+ if (error.name === 'ValidationException' && error.message?.includes('model')) {
162
+ continue;
163
+ }
164
+ if (error.name === 'AccessDeniedException') {
165
+ continue;
166
+ }
145
167
  }
146
168
  }
147
169
  }
170
+ catch (error) {
171
+ if (timeoutId) {
172
+ clearTimeout(timeoutId);
173
+ }
174
+ throw error;
175
+ }
176
+ if (timeoutId) {
177
+ clearTimeout(timeoutId);
178
+ }
148
179
  const message = this.createBedrockInstructionMessage(`None of the attempted models are not available in your AWS account. ` +
149
180
  `Please enable it in the AWS Bedrock console:\n\n` +
150
181
  `1. Go to AWS Bedrock Console (https://console.aws.amazon.com/bedrock/)\n` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wirejs-deploy-amplify-basic",
3
- "version": "0.1.146-llm",
3
+ "version": "0.1.148-llm",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -43,8 +43,8 @@
43
43
  "jsdom": "^25.0.0",
44
44
  "recursive-copy": "^2.0.14",
45
45
  "rimraf": "^6.0.1",
46
- "wirejs-dom": "^1.0.42",
47
- "wirejs-resources": "^0.1.146-llm"
46
+ "wirejs-dom": "^1.0.44",
47
+ "wirejs-resources": "^0.1.148-llm"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@aws-amplify/backend": "^1.14.0",