@aws-blocks/bb-agent 0.3.5 → 0.4.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/DESIGN.md +65 -17
- package/README.md +73 -6
- package/dist/agent.aws.d.ts +15 -1
- package/dist/agent.aws.d.ts.map +1 -1
- package/dist/agent.aws.js +49 -0
- package/dist/agent.d.ts +82 -14
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +238 -57
- package/dist/agentcore-bundle.d.ts +12 -0
- package/dist/agentcore-bundle.d.ts.map +1 -0
- package/dist/agentcore-bundle.js +150 -0
- package/dist/agentcore-bundle.test.d.ts +2 -0
- package/dist/agentcore-bundle.test.d.ts.map +1 -0
- package/dist/agentcore-bundle.test.js +46 -0
- package/dist/agentcore-entry.d.ts +21 -0
- package/dist/agentcore-entry.d.ts.map +1 -0
- package/dist/agentcore-entry.js +120 -0
- package/dist/agentcore-runtime.cdk.d.ts +27 -0
- package/dist/agentcore-runtime.cdk.d.ts.map +1 -0
- package/dist/agentcore-runtime.cdk.js +168 -0
- package/dist/index.aws.d.ts +1 -0
- package/dist/index.aws.d.ts.map +1 -1
- package/dist/index.cdk.d.ts +10 -4
- package/dist/index.cdk.d.ts.map +1 -1
- package/dist/index.cdk.js +27 -28
- package/dist/index.cdk.test.js +128 -51
- package/dist/index.mock.d.ts +1 -0
- package/dist/index.mock.d.ts.map +1 -1
- package/dist/index.test.js +404 -1
- package/dist/model-factory.d.ts +2 -2
- package/dist/model-factory.d.ts.map +1 -1
- package/dist/model-factory.js +2 -2
- package/dist/providers/canned.d.ts +8 -1
- package/dist/providers/canned.d.ts.map +1 -1
- package/dist/providers/canned.js +127 -42
- package/dist/types.d.ts +63 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -9
- package/src/agent.aws.ts +58 -1
- package/src/agent.ts +269 -56
- package/src/agentcore-bundle.test.ts +52 -0
- package/src/agentcore-bundle.ts +162 -0
- package/src/agentcore-entry.ts +134 -0
- package/src/agentcore-runtime.cdk.ts +203 -0
- package/src/index.aws.ts +3 -0
- package/src/index.cdk.test.ts +145 -53
- package/src/index.cdk.ts +29 -31
- package/src/index.mock.ts +3 -0
- package/src/index.test.ts +449 -1
- package/src/model-factory.ts +3 -3
- package/src/providers/canned.ts +131 -36
- package/src/types.ts +64 -1
- package/src/version.ts +1 -1
- package/dist/job-event-source.d.ts +0 -19
- package/dist/job-event-source.d.ts.map +0 -1
- package/dist/job-event-source.js +0 -20
- package/src/job-event-source.ts +0 -21
package/dist/providers/canned.js
CHANGED
|
@@ -19,27 +19,45 @@ const CANNED_RESPONSES = {
|
|
|
19
19
|
help: 'I can help you with weather, orders, and general questions. [canned response]',
|
|
20
20
|
};
|
|
21
21
|
const DEFAULT_RESPONSE = 'This is a canned mock response. No real model was called. [canned]';
|
|
22
|
+
/**
|
|
23
|
+
* Pick a canned text response by keyword, matched on word boundaries for the same reason
|
|
24
|
+
* tool matching is: substring matching fired `order` inside "reorder" and `help` inside
|
|
25
|
+
* "helper", the same false-positive class the tool matcher avoids.
|
|
26
|
+
*/
|
|
22
27
|
function matchResponse(prompt) {
|
|
23
28
|
const lower = prompt.toLowerCase();
|
|
24
29
|
for (const [keyword, response] of Object.entries(CANNED_RESPONSES)) {
|
|
25
|
-
if (lower
|
|
30
|
+
if (promptMentionsWord(lower, keyword))
|
|
26
31
|
return response;
|
|
27
32
|
}
|
|
28
33
|
return DEFAULT_RESPONSE;
|
|
29
34
|
}
|
|
35
|
+
const wordPatternCache = new Map();
|
|
30
36
|
/**
|
|
31
|
-
*
|
|
37
|
+
* Compile a word-boundary matcher for a word or phrase, cached by phrase.
|
|
32
38
|
* Uses `\b...\b` rather than substring `includes()` so a tool word like "cat"
|
|
33
39
|
* (from `getCat`) is NOT triggered by an unrelated word like "category", and
|
|
34
|
-
* "pass" (from `getPass`) is not triggered by "password".
|
|
35
|
-
* escaped so punctuation in tool names can't break the pattern
|
|
40
|
+
* "pass" (from `getPass`) is not triggered by "password". Regex metacharacters are
|
|
41
|
+
* escaped so punctuation in tool names can't break the pattern, and internal
|
|
42
|
+
* whitespace becomes `\s+` so a multi-word phrase tolerates irregular spacing.
|
|
43
|
+
* Compiled patterns are cached because matching re-runs for every tool on every
|
|
44
|
+
* `stream()` call, and the key space is bounded by the agent's tool and trigger set.
|
|
36
45
|
*/
|
|
46
|
+
function wordBoundaryPattern(phrase) {
|
|
47
|
+
let pattern = wordPatternCache.get(phrase);
|
|
48
|
+
if (!pattern) {
|
|
49
|
+
const escaped = phrase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/\s+/g, '\\s+');
|
|
50
|
+
pattern = new RegExp(`\\b${escaped}\\b`);
|
|
51
|
+
wordPatternCache.set(phrase, pattern);
|
|
52
|
+
}
|
|
53
|
+
return pattern;
|
|
54
|
+
}
|
|
55
|
+
/** Match a word against an already-lowercased prompt on word boundaries. */
|
|
37
56
|
function promptMentionsWord(lowerPrompt, word) {
|
|
38
|
-
|
|
39
|
-
return new RegExp(`\\b${escaped}\\b`).test(lowerPrompt);
|
|
57
|
+
return wordBoundaryPattern(word).test(lowerPrompt);
|
|
40
58
|
}
|
|
41
59
|
/** Find ALL tools mentioned in the prompt (for parallel tool calls). */
|
|
42
|
-
function findAllToolMatches(prompt, toolSpecs) {
|
|
60
|
+
function findAllToolMatches(prompt, toolSpecs, hints) {
|
|
43
61
|
if (!toolSpecs?.length)
|
|
44
62
|
return [];
|
|
45
63
|
const lower = prompt.toLowerCase();
|
|
@@ -50,7 +68,16 @@ function findAllToolMatches(prompt, toolSpecs) {
|
|
|
50
68
|
// Split camelCase into words (getWeather -> "get weather") and match each
|
|
51
69
|
// on word boundaries. Skip short words (<=2 chars) to avoid noise.
|
|
52
70
|
const words = t.name.replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase().split(' ');
|
|
53
|
-
|
|
71
|
+
if (words.some(w => w.length > 2 && promptMentionsWord(lower, w)))
|
|
72
|
+
return true;
|
|
73
|
+
// Extra trigger keywords declared via `cannedTriggers`. Single and multi-word triggers
|
|
74
|
+
// both match on word boundaries (consistent with tool-name matching), so "log in" is not
|
|
75
|
+
// triggered by "backlog in" and internal whitespace is flexible (matches one-or-more spaces).
|
|
76
|
+
const triggers = hints?.get(t.name)?.triggers;
|
|
77
|
+
return triggers?.some(tr => {
|
|
78
|
+
const low = tr.trim().toLowerCase();
|
|
79
|
+
return low ? wordBoundaryPattern(low).test(lower) : false;
|
|
80
|
+
}) ?? false;
|
|
54
81
|
}).map(t => t.name);
|
|
55
82
|
}
|
|
56
83
|
/** Check if the last message contains a tool result — means we're in the follow-up after a tool call. */
|
|
@@ -75,49 +102,108 @@ function getToolResultText(messages) {
|
|
|
75
102
|
}
|
|
76
103
|
return results.join(' | ');
|
|
77
104
|
}
|
|
105
|
+
/** Sentinel for a property whose shape carries no usable signal (distinct from a legitimate `null`/`0`/`false`). */
|
|
106
|
+
const NO_PLACEHOLDER = Symbol('no-placeholder');
|
|
107
|
+
/**
|
|
108
|
+
* Resolve one property's placeholder value, or `NO_PLACEHOLDER` if its shape gives no signal.
|
|
109
|
+
* Order matters: an authored `default` (from Zod `.default()`) is the most realistic value, then
|
|
110
|
+
* a fixed `const`/`enum` member, then a union variant, then a per-type placeholder. `!== undefined`
|
|
111
|
+
* rather than truthiness so a `default` of `0`, `false`, or `''` is honored.
|
|
112
|
+
*/
|
|
113
|
+
function placeholderForProperty(prop) {
|
|
114
|
+
if (prop?.default !== undefined)
|
|
115
|
+
return prop.default;
|
|
116
|
+
if (prop?.const !== undefined)
|
|
117
|
+
return prop.const;
|
|
118
|
+
if (prop?.enum?.length)
|
|
119
|
+
return prop.enum[0];
|
|
120
|
+
// Zod unions (`z.union`, `z.discriminatedUnion`) surface as anyOf/oneOf; any one
|
|
121
|
+
// satisfying variant is enough for a mock, so take the first that resolves.
|
|
122
|
+
const variants = prop?.anyOf ?? prop?.oneOf;
|
|
123
|
+
if (Array.isArray(variants)) {
|
|
124
|
+
for (const variant of variants) {
|
|
125
|
+
const resolved = placeholderForProperty(variant);
|
|
126
|
+
if (resolved !== NO_PLACEHOLDER)
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
switch (prop?.type) {
|
|
131
|
+
case 'string': return 'sample';
|
|
132
|
+
case 'number':
|
|
133
|
+
case 'integer': return 1;
|
|
134
|
+
case 'boolean': return true;
|
|
135
|
+
case 'array': return [];
|
|
136
|
+
case 'object': return generatePlaceholderInput(prop);
|
|
137
|
+
default: return NO_PLACEHOLDER;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
78
140
|
/** Generate placeholder input from a JSON Schema. Produces values that pass validation. */
|
|
79
141
|
function generatePlaceholderInput(schema) {
|
|
80
142
|
if (!schema || typeof schema !== 'object')
|
|
81
143
|
return {};
|
|
82
|
-
if (schema.type
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
else if (prop.type === 'array') {
|
|
98
|
-
result[key] = [];
|
|
99
|
-
}
|
|
100
|
-
else if (prop.type === 'object') {
|
|
101
|
-
result[key] = generatePlaceholderInput(prop);
|
|
102
|
-
}
|
|
144
|
+
if (schema.type !== 'object' || !schema.properties)
|
|
145
|
+
return {};
|
|
146
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
147
|
+
const result = {};
|
|
148
|
+
for (const [key, prop] of Object.entries(schema.properties)) {
|
|
149
|
+
const value = placeholderForProperty(prop);
|
|
150
|
+
if (value !== NO_PLACEHOLDER) {
|
|
151
|
+
result[key] = value;
|
|
152
|
+
}
|
|
153
|
+
else if (required.includes(key)) {
|
|
154
|
+
// An unrecognized shape (untyped, or a union of only unrecognized variants) yields no
|
|
155
|
+
// placeholder. Omitting a *required* field makes the emitted call fail validation before
|
|
156
|
+
// the tool ever runs, so fall back to a string. Optional fields stay omitted: absence is
|
|
157
|
+
// valid there, and inventing a wrong-typed value would break calls that used to work.
|
|
158
|
+
result[key] = 'sample';
|
|
103
159
|
}
|
|
104
|
-
return result;
|
|
105
160
|
}
|
|
106
|
-
return
|
|
161
|
+
return result;
|
|
162
|
+
}
|
|
163
|
+
const warnedExampleKeys = new Set();
|
|
164
|
+
/**
|
|
165
|
+
* Warn (once per tool+field) when a `cannedExamples` key isn't a field of the tool's
|
|
166
|
+
* inputSchema — almost always a typo in the hint. Only ever reached through the canned
|
|
167
|
+
* provider, which is local-dev-only, so this never warns in a deployed agent. The value
|
|
168
|
+
* is still merged through and nothing throws: a bad hint must not break local dev.
|
|
169
|
+
* Skipped when the schema exposes no `properties`, where unknown keys are unknowable.
|
|
170
|
+
*/
|
|
171
|
+
function warnUnknownExampleKeys(toolName, examples, inputSchema) {
|
|
172
|
+
const properties = inputSchema?.properties;
|
|
173
|
+
if (!properties)
|
|
174
|
+
return;
|
|
175
|
+
for (const key of Object.keys(examples)) {
|
|
176
|
+
if (key in properties)
|
|
177
|
+
continue;
|
|
178
|
+
const seen = `${toolName}.${key}`;
|
|
179
|
+
if (warnedExampleKeys.has(seen))
|
|
180
|
+
continue;
|
|
181
|
+
warnedExampleKeys.add(seen);
|
|
182
|
+
console.warn(`[canned] cannedExamples for tool "${toolName}" sets "${key}", which is not a field of its ` +
|
|
183
|
+
`parameters schema (${Object.keys(properties).join(', ') || 'none'}). Check for a typo — the value is still sent.`);
|
|
184
|
+
}
|
|
107
185
|
}
|
|
108
|
-
/**
|
|
109
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Look up a tool's inputSchema from toolSpecs and generate placeholder input, shallow-merging
|
|
188
|
+
* any `cannedExamples` (from hints) on top so realistic values win over generated placeholders.
|
|
189
|
+
*/
|
|
190
|
+
function getToolInput(toolName, toolSpecs, hints) {
|
|
110
191
|
const spec = toolSpecs?.find(t => t.name === toolName);
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
192
|
+
const base = spec?.inputSchema ? generatePlaceholderInput(spec.inputSchema) : {};
|
|
193
|
+
const examples = hints?.get(toolName)?.examples;
|
|
194
|
+
if (!examples)
|
|
195
|
+
return JSON.stringify(base);
|
|
196
|
+
warnUnknownExampleKeys(toolName, examples, spec?.inputSchema);
|
|
197
|
+
return JSON.stringify({ ...base, ...examples });
|
|
114
198
|
}
|
|
115
199
|
let toolCallCounter = 0;
|
|
116
200
|
export class CannedProvider extends Model {
|
|
117
201
|
config;
|
|
118
|
-
|
|
202
|
+
hints;
|
|
203
|
+
constructor(options) {
|
|
119
204
|
super();
|
|
120
|
-
this.config = { modelId:
|
|
205
|
+
this.config = { modelId: options?.modelId ?? 'canned-mock' };
|
|
206
|
+
this.hints = options?.hints ?? new Map();
|
|
121
207
|
}
|
|
122
208
|
updateConfig(config) {
|
|
123
209
|
Object.assign(this.config, config);
|
|
@@ -137,7 +223,7 @@ export class CannedProvider extends Model {
|
|
|
137
223
|
return;
|
|
138
224
|
}
|
|
139
225
|
// Check if prompt mentions tool names — trigger tool call(s)
|
|
140
|
-
const toolMatches = findAllToolMatches(prompt, options?.toolSpecs);
|
|
226
|
+
const toolMatches = findAllToolMatches(prompt, options?.toolSpecs, this.hints);
|
|
141
227
|
if (toolMatches.length > 1) {
|
|
142
228
|
yield* this.emitParallelToolCalls(toolMatches, options?.toolSpecs);
|
|
143
229
|
return;
|
|
@@ -148,7 +234,6 @@ export class CannedProvider extends Model {
|
|
|
148
234
|
return;
|
|
149
235
|
}
|
|
150
236
|
// Default: keyword-based text response
|
|
151
|
-
// Default: keyword-based text response
|
|
152
237
|
yield* this.emitText(matchResponse(prompt));
|
|
153
238
|
}
|
|
154
239
|
/** Emit a text response as ModelStreamEvents. */
|
|
@@ -168,7 +253,7 @@ export class CannedProvider extends Model {
|
|
|
168
253
|
for (const toolName of toolNames) {
|
|
169
254
|
const toolUseId = `canned-tool-${++toolCallCounter}`;
|
|
170
255
|
yield { type: 'modelContentBlockStartEvent', start: { type: 'toolUseStart', name: toolName, toolUseId } };
|
|
171
|
-
yield { type: 'modelContentBlockDeltaEvent', delta: { type: 'toolUseInputDelta', input: getToolInput(toolName, toolSpecs) } };
|
|
256
|
+
yield { type: 'modelContentBlockDeltaEvent', delta: { type: 'toolUseInputDelta', input: getToolInput(toolName, toolSpecs, this.hints) } };
|
|
172
257
|
yield { type: 'modelContentBlockStopEvent' };
|
|
173
258
|
}
|
|
174
259
|
yield { type: 'modelMessageStopEvent', stopReason: 'toolUse' };
|
|
@@ -179,7 +264,7 @@ export class CannedProvider extends Model {
|
|
|
179
264
|
const toolUseId = `canned-tool-${++toolCallCounter}`;
|
|
180
265
|
yield { type: 'modelMessageStartEvent', role: 'assistant' };
|
|
181
266
|
yield { type: 'modelContentBlockStartEvent', start: { type: 'toolUseStart', name: toolName, toolUseId } };
|
|
182
|
-
yield { type: 'modelContentBlockDeltaEvent', delta: { type: 'toolUseInputDelta', input: getToolInput(toolName, toolSpecs) } };
|
|
267
|
+
yield { type: 'modelContentBlockDeltaEvent', delta: { type: 'toolUseInputDelta', input: getToolInput(toolName, toolSpecs, this.hints) } };
|
|
183
268
|
yield { type: 'modelContentBlockStopEvent' };
|
|
184
269
|
yield { type: 'modelMessageStopEvent', stopReason: 'toolUse' };
|
|
185
270
|
yield { type: 'modelMetadataEvent', usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 }, metrics: { latencyMs: 0 } };
|
package/dist/types.d.ts
CHANGED
|
@@ -78,7 +78,39 @@ export interface AgentConfig<TContext = DefaultToolContext> {
|
|
|
78
78
|
*/
|
|
79
79
|
toolContextSchema?: z.ZodType<TContext>;
|
|
80
80
|
conversation?: ConversationManagerConfig;
|
|
81
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Safety cap on the number of **model (Bedrock) invocations per turn**.
|
|
83
|
+
*
|
|
84
|
+
* The agent runs a reason→act loop where each iteration is one model call,
|
|
85
|
+
* optionally followed by tool calls; a model call that requests no tools ends
|
|
86
|
+
* the turn. Model calls are the unit Bedrock bills for, so this is the most
|
|
87
|
+
* direct guard against a runaway agent that loops indefinitely — and because
|
|
88
|
+
* every tool round needs a model call, it transitively bounds tool loops too.
|
|
89
|
+
*
|
|
90
|
+
* When the cap is hit the turn is stopped and the client receives an `error`
|
|
91
|
+
* chunk instead of `done`. Raise it for agents that legitimately reason over
|
|
92
|
+
* many steps, or set it to `false` to disable the cap entirely. This bounds
|
|
93
|
+
* call *count*, not tokens or wall-clock — pair it with a billing/CloudWatch
|
|
94
|
+
* alarm for defense in depth.
|
|
95
|
+
*
|
|
96
|
+
* Scope: the count covers the whole turn, including across a human-in-the-loop
|
|
97
|
+
* interrupt — it is kept in the agent's session state, so `resume()` continues
|
|
98
|
+
* on the same budget rather than starting a fresh one. Must be a positive
|
|
99
|
+
* integer or `false`; anything else throws `InvalidModelConfigException`.
|
|
100
|
+
*/
|
|
101
|
+
maxLlmCalls?: number | false;
|
|
102
|
+
/**
|
|
103
|
+
* Safety cap on the number of **tool calls per turn**.
|
|
104
|
+
*
|
|
105
|
+
* Bounds tool-loop runaways specifically (a turn that keeps invoking tools).
|
|
106
|
+
* Parallel tool batches count each individual call. Raise it for agents that
|
|
107
|
+
* legitimately chain many tools in a single turn, or set it to `false` to
|
|
108
|
+
* disable the cap entirely. When the cap is hit the turn is stopped and the
|
|
109
|
+
* client receives an `error` chunk instead of `done`. Like `maxLlmCalls`, the
|
|
110
|
+
* count covers the whole turn (it survives `resume()` after an interrupt) and
|
|
111
|
+
* must be a positive integer or `false`.
|
|
112
|
+
*/
|
|
113
|
+
maxToolIterations?: number | false;
|
|
82
114
|
/** Controls how text chunks are published to the client via Realtime.
|
|
83
115
|
* - `'token'`: publish every text delta immediately
|
|
84
116
|
* - `'block'` (default): buffer text and publish when a full content block completes
|
|
@@ -98,6 +130,12 @@ export interface AgentConfig<TContext = DefaultToolContext> {
|
|
|
98
130
|
* Ignored by the mock and browser runtimes.
|
|
99
131
|
*/
|
|
100
132
|
removalPolicy?: 'destroy' | 'retain';
|
|
133
|
+
/**
|
|
134
|
+
* @internal Pre-built AgentCore code-asset directory to use instead of co-bundling the app
|
|
135
|
+
* backend at synth. Set by unit tests and apps that pre-bundle; normal apps leave this unset
|
|
136
|
+
* and the backend is co-bundled automatically. Ignored by the mock/browser runtimes.
|
|
137
|
+
*/
|
|
138
|
+
agentcoreAssetPath?: string;
|
|
101
139
|
/** Optional logger for internal operations. When omitted, a default Logger at error level is created. */
|
|
102
140
|
logger?: ChildLogger;
|
|
103
141
|
}
|
|
@@ -171,6 +209,30 @@ export interface ToolDefinition<TContext = DefaultToolContext, TParams extends z
|
|
|
171
209
|
* - `interrupt` — pause the agent for human input
|
|
172
210
|
*/
|
|
173
211
|
handler: (args: ToolHandlerArgs<z.infer<TParams>, TContext>) => Promise<JSONValue>;
|
|
212
|
+
/**
|
|
213
|
+
* Local-dev only. Realistic tool input for the `canned` mock provider. Shallow-merged
|
|
214
|
+
* over the generated placeholder input (your fields win; unspecified fields fall back to
|
|
215
|
+
* schema defaults / generic placeholders). The merge is one level deep — a nested-object
|
|
216
|
+
* example replaces that whole generated sub-object rather than deep-merging into it.
|
|
217
|
+
* Ignored by the bedrock/openai providers.
|
|
218
|
+
*/
|
|
219
|
+
cannedExamples?: Record<string, JSONValue>;
|
|
220
|
+
/**
|
|
221
|
+
* Local-dev only. Extra keyword phrases that make the `canned` mock provider select this
|
|
222
|
+
* tool, in addition to the tool name and its camelCase words. Single and multi-word phrases
|
|
223
|
+
* match on word boundaries (so "log in" is not triggered by "backlog in"). Ignored by the
|
|
224
|
+
* bedrock/openai providers.
|
|
225
|
+
*/
|
|
226
|
+
cannedTriggers?: string[];
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Local-dev hints for the `canned` mock provider, keyed by tool name and threaded from
|
|
230
|
+
* `ToolDefinition.cannedExamples`/`cannedTriggers` into the provider (Strands strips these
|
|
231
|
+
* fields when converting tools, so they're plumbed explicitly). Ignored by real providers.
|
|
232
|
+
*/
|
|
233
|
+
export interface CannedToolHints {
|
|
234
|
+
examples?: Record<string, JSONValue>;
|
|
235
|
+
triggers?: string[];
|
|
174
236
|
}
|
|
175
237
|
/**
|
|
176
238
|
* @internal Brand applied by the per-call `tool()` factory. Not forgeable by a plain
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,mCAAmC;AACnC,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,SAAS,EAAE,CAAC;AAEtG,MAAM,WAAW,WAAW;IAC3B;;;;OAIG;IACH,QAAQ,EAAE,SAAS,GAAG,YAAY,GAAG,QAAQ,CAAC;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qJAAqJ;IACrJ,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,eAAe;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAErD,MAAM,WAAW,WAAW,CAAC,QAAQ,GAAG,kBAAkB;IACzD;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE;QACP,sHAAsH;QACtH,QAAQ,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;QACvC,mGAAmG;QACnG,KAAK,CAAC,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;KACpC,CAAC;IACF,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC9B;;;;;;;;;;;;OAYG;IACH,iBAAiB,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACxC,YAAY,CAAC,EAAE,yBAAyB,CAAC;IACzC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aws-blocks/bb-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/aws-devtools-labs/aws-blocks.git",
|
|
@@ -35,28 +35,35 @@
|
|
|
35
35
|
"./client": {
|
|
36
36
|
"types": "./dist/index.hooks.d.ts",
|
|
37
37
|
"default": "./dist/index.hooks.js"
|
|
38
|
+
},
|
|
39
|
+
"./agentcore": {
|
|
40
|
+
"types": "./dist/agentcore-entry.d.ts",
|
|
41
|
+
"default": "./dist/agentcore-entry.js"
|
|
38
42
|
}
|
|
39
43
|
},
|
|
40
44
|
"scripts": {
|
|
41
45
|
"prebuild": "node ../../scripts/generate-version.mjs Agent",
|
|
42
46
|
"build": "tsc --build",
|
|
43
|
-
"test": "node --test dist/index.test.js && node --conditions=cdk --test dist/index.cdk.test.js"
|
|
47
|
+
"test": "node --test dist/index.test.js && node --conditions=cdk --test dist/index.cdk.test.js && node --test dist/agentcore-bundle.test.js"
|
|
44
48
|
},
|
|
45
49
|
"dependencies": {
|
|
46
|
-
"@aws-blocks/bb-
|
|
47
|
-
"@aws-blocks/bb-
|
|
48
|
-
"@aws-blocks/bb-
|
|
49
|
-
"@aws-blocks/bb-
|
|
50
|
-
"@aws-blocks/
|
|
51
|
-
"@aws-blocks/core": "^0.3.0",
|
|
50
|
+
"@aws-blocks/bb-distributed-table": "^0.1.7",
|
|
51
|
+
"@aws-blocks/bb-file-bucket": "^0.2.0",
|
|
52
|
+
"@aws-blocks/bb-logger": "^0.1.6",
|
|
53
|
+
"@aws-blocks/bb-realtime": "^0.2.0",
|
|
54
|
+
"@aws-blocks/core": "^0.4.0",
|
|
52
55
|
"@aws-sdk/client-bedrock": "^3.700.0",
|
|
56
|
+
"@aws-sdk/client-bedrock-agentcore": "^3.700.0",
|
|
53
57
|
"@opentelemetry/api": "^1.9.0",
|
|
54
|
-
"@strands-agents/sdk": "
|
|
58
|
+
"@strands-agents/sdk": "^1.7.0",
|
|
59
|
+
"bedrock-agentcore": "^0.4.0",
|
|
60
|
+
"esbuild": "^0.27.0",
|
|
55
61
|
"openai": "^6.7.0",
|
|
56
62
|
"ulid": "^2.3.0",
|
|
57
63
|
"zod": "^4.1.12"
|
|
58
64
|
},
|
|
59
65
|
"devDependencies": {
|
|
66
|
+
"@aws-blocks/bb-lambda-compute": "^0.4.0",
|
|
60
67
|
"@aws-sdk/client-bedrock-runtime": "^3.700.0",
|
|
61
68
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
62
69
|
"@types/node": "^20.0.0",
|
package/src/agent.aws.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
|
+
import { getConfig } from '@aws-blocks/core';
|
|
4
6
|
import type { ScopeParent } from '@aws-blocks/core';
|
|
5
7
|
import type { FileBucket } from '@aws-blocks/bb-file-bucket';
|
|
8
|
+
import { BedrockAgentCoreClient, InvokeAgentRuntimeCommand } from '@aws-sdk/client-bedrock-agentcore';
|
|
6
9
|
import type { SnapshotStorage } from '@strands-agents/sdk';
|
|
7
10
|
import { S3Storage } from '@strands-agents/sdk/session/s3-storage';
|
|
8
11
|
import type { S3StorageConfig } from '@strands-agents/sdk/session/s3-storage';
|
|
9
|
-
import { AgentBase } from './agent.js';
|
|
12
|
+
import { AgentBase, type AgentTurnPayload } from './agent.js';
|
|
13
|
+
import { AgentErrors, blocksAgentError } from './errors.js';
|
|
10
14
|
import type { AgentConfig, DefaultToolContext } from './types.js';
|
|
11
15
|
import { BedrockModels } from './models.js';
|
|
12
16
|
|
|
17
|
+
/**
|
|
18
|
+
* AgentCore requires a `runtimeSessionId` of at least 33 characters. Conversation/channel ids
|
|
19
|
+
* are UUIDs (36 chars) in the normal path and pass through unchanged; anything shorter is hashed
|
|
20
|
+
* to a stable 64-char hex id — stable per input, so a conversation keeps routing to one warm
|
|
21
|
+
* microVM across turns/resumes.
|
|
22
|
+
*/
|
|
23
|
+
function toRuntimeSessionId(base: string): string {
|
|
24
|
+
return base.length >= 33 ? base : createHash('sha256').update(base).digest('hex');
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
/**
|
|
14
28
|
* Builds the deployed Agent's snapshot storage, pinning S3Storage to the Lambda
|
|
15
29
|
* execution region (`AWS_REGION`) so non-us-east-1 deploys use the correct regional
|
|
@@ -24,7 +38,50 @@ export function createDeployedSnapshotStorage(
|
|
|
24
38
|
}
|
|
25
39
|
|
|
26
40
|
export class Agent<TContext = DefaultToolContext> extends AgentBase<TContext> {
|
|
41
|
+
private _agentCore?: BedrockAgentCoreClient;
|
|
42
|
+
|
|
27
43
|
constructor(scope: ScopeParent, id: string, config: AgentConfig<TContext>) {
|
|
28
44
|
super(scope, id, config, config.model?.deployed ?? BedrockModels.BALANCED, createDeployedSnapshotStorage);
|
|
29
45
|
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Run the turn on the AgentCore Runtime that hosts this agent's loop.
|
|
49
|
+
*
|
|
50
|
+
* Returns as soon as the runtime has ACCEPTED the turn: `agentcore-entry` starts `runAgent()`
|
|
51
|
+
* as a background async task (which streams chunks to Realtime under the runtime's own role)
|
|
52
|
+
* and responds immediately, so this `InvokeAgentRuntime` call does NOT hold the connection for
|
|
53
|
+
* the turn's duration — the loop keeps running server-side for up to the 8h session lifetime.
|
|
54
|
+
* `runtimeSessionId` is keyed by conversationId so a conversation's turns/resumes reuse one
|
|
55
|
+
* warm microVM.
|
|
56
|
+
*
|
|
57
|
+
* @internal Internal compute seam; not customer API.
|
|
58
|
+
*/
|
|
59
|
+
protected override async dispatchTurn(payload: AgentTurnPayload<TContext>): Promise<void> {
|
|
60
|
+
const runtimeArnKey = `BB_AGENT_${this.fullId}_RUNTIME_ARN`;
|
|
61
|
+
const runtimeArn = await getConfig(runtimeArnKey);
|
|
62
|
+
if (!runtimeArn) {
|
|
63
|
+
throw blocksAgentError(
|
|
64
|
+
AgentErrors.StreamFailed,
|
|
65
|
+
`AgentCore Runtime ARN not found (config key ${runtimeArnKey}). Ensure the app build produced the AgentCore asset and the stack deployed the Runtime.`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
this._agentCore ??= new BedrockAgentCoreClient({});
|
|
69
|
+
const body = {
|
|
70
|
+
prompt: payload.message,
|
|
71
|
+
channelId: payload.channelId,
|
|
72
|
+
conversationId: payload.conversationId,
|
|
73
|
+
userId: payload.userId,
|
|
74
|
+
interruptResponses: payload.interruptResponses,
|
|
75
|
+
context: payload.context,
|
|
76
|
+
};
|
|
77
|
+
await this._agentCore.send(
|
|
78
|
+
new InvokeAgentRuntimeCommand({
|
|
79
|
+
agentRuntimeArn: runtimeArn,
|
|
80
|
+
runtimeSessionId: toRuntimeSessionId(payload.conversationId ?? payload.channelId),
|
|
81
|
+
contentType: 'application/json',
|
|
82
|
+
accept: 'application/json',
|
|
83
|
+
payload: new TextEncoder().encode(JSON.stringify(body)),
|
|
84
|
+
}),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
30
87
|
}
|