@aws-blocks/bb-agent 0.1.2 → 0.3.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 +66 -0
- package/README.md +20 -19
- package/dist/agent.aws.d.ts.map +1 -1
- package/dist/agent.aws.js +2 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +2 -1
- package/dist/agent.mock.js +1 -1
- package/dist/index.test.js +40 -5
- package/dist/models.d.ts +23 -13
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +27 -13
- package/dist/types.d.ts +25 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -7
- package/src/agent.aws.ts +2 -1
- package/src/agent.mock.ts +1 -1
- package/src/agent.ts +2 -1
- package/src/index.test.ts +46 -5
- package/src/models.ts +29 -13
- package/src/types.ts +22 -6
- package/src/version.ts +1 -1
package/DESIGN.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Agent — Design
|
|
2
|
+
|
|
3
|
+
Design document for the Agent Building Block. For usage, see [README.md](./README.md).
|
|
4
|
+
|
|
5
|
+
**Package:** `@aws-blocks/bb-agent`
|
|
6
|
+
**Type:** Composite (uses DistributedTable, Realtime, AsyncJob, FileBucket internally)
|
|
7
|
+
**AWS Services:** Bedrock, DynamoDB, S3, SQS, AppSync Events
|
|
8
|
+
**Agent Framework:** [Strands Agents SDK](https://strandsagents.com/)
|
|
9
|
+
|
|
10
|
+
## Architecture
|
|
11
|
+
|
|
12
|
+
The Agent BB is a composite Building Block — it creates and manages 4 internal BBs:
|
|
13
|
+
|
|
14
|
+
| Internal BB | Purpose | Created when |
|
|
15
|
+
|-------------|---------|-------------|
|
|
16
|
+
| **FileBucket** | Session persistence (Strands SessionManager) | Always |
|
|
17
|
+
| **DistributedTable** | Frontend message history | `inferenceOnly: false` |
|
|
18
|
+
| **Realtime** | Streaming chunks to caller | Always |
|
|
19
|
+
| **AsyncJob** | Async agent execution (avoids 29s API Gateway timeout) | Always |
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
stream() → AsyncJob.submit() → returns { channelId } immediately
|
|
23
|
+
↓
|
|
24
|
+
AsyncJob consumer
|
|
25
|
+
↓
|
|
26
|
+
runAgent() → Strands agent loop → publishes chunks to Realtime
|
|
27
|
+
→ persists messages to DistributedTable
|
|
28
|
+
→ SessionManager saves state to FileBucket
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Session Persistence
|
|
32
|
+
|
|
33
|
+
Two storage backends, same FileBucket BB:
|
|
34
|
+
- **AWS:** Strands' native `S3Storage` → FileBucket-provisioned S3 bucket
|
|
35
|
+
- **Local:** Custom `FileBucketSnapshotStorage` → FileBucket mock (mirrors S3Storage key layout exactly)
|
|
36
|
+
|
|
37
|
+
## Infrastructure (CDK)
|
|
38
|
+
|
|
39
|
+
The CDK class mirrors the runtime's BB creation:
|
|
40
|
+
- **Bedrock IAM:** `InvokeModel` + `InvokeModelWithResponseStream` on all foundation models and inference profiles
|
|
41
|
+
- **FileBucket:** `${id}-sessions` — session snapshot storage
|
|
42
|
+
- **DistributedTable:** `${id}-messages` — conversation history (only when `inferenceOnly: false`)
|
|
43
|
+
- **Realtime:** `${id}-rt` — streaming namespace `chunks`
|
|
44
|
+
- **AsyncJob:** `${id}-job` — job payload: `{ message, conversationId?, channelId }`
|
|
45
|
+
|
|
46
|
+
> **Note:** Internal Building Blocks are created on the parent scope (not `this`) to ensure correct nested-scope resolution on AWS.
|
|
47
|
+
|
|
48
|
+
## Model Providers
|
|
49
|
+
|
|
50
|
+
All providers are Strands model implementations, mapped from Blocks's `ModelConfig` via `model-factory.ts`:
|
|
51
|
+
|
|
52
|
+
| Provider | Strands Class | Use Case |
|
|
53
|
+
|----------|--------------|----------|
|
|
54
|
+
| `canned` | `CannedProvider` (custom) | Local dev — keyword-based responses with tool call support |
|
|
55
|
+
| `bedrock` | `BedrockModel` | AWS — Amazon Bedrock models |
|
|
56
|
+
| `openai-api` | `OpenAIModel` | Any OpenAI-compatible endpoint (OpenAI, Ollama, vLLM) |
|
|
57
|
+
|
|
58
|
+
## CannedProvider
|
|
59
|
+
|
|
60
|
+
Custom Strands model provider for local development. No network, no API keys, no costs.
|
|
61
|
+
|
|
62
|
+
- Returns instant keyword-based responses (e.g., prompt contains "weather" → weather response, otherwise a default canned response)
|
|
63
|
+
- Streams word by word, matching the same `ModelStreamEvent` protocol as Bedrock/OpenAI
|
|
64
|
+
- Triggers tool calls when the prompt mentions a tool name — splits camelCase names into words (e.g., "weather" matches `getWeather`) and emits Strands `toolUse` events
|
|
65
|
+
- After Strands executes the tool and sends the result back, returns a fixed acknowledgment (`"I called the tool and got a result."`)
|
|
66
|
+
- Token usage reports zeros (no real model call)
|
package/README.md
CHANGED
|
@@ -6,16 +6,17 @@ AI agent with streaming, tool calling, and conversation persistence. Powered by
|
|
|
6
6
|
|
|
7
7
|
**Requires:** `zod` ^4.0.0 as a peer dependency. Tool parameters use Zod schemas for validation. If you see `ZodType missing properties` errors, check your zod version.
|
|
8
8
|
|
|
9
|
+
> Design & mock parity details: [DESIGN.md](./DESIGN.md)
|
|
10
|
+
|
|
9
11
|
## Quick Start
|
|
10
12
|
|
|
11
13
|
```typescript
|
|
12
14
|
import { Scope } from '@aws-blocks/core';
|
|
13
|
-
import { Agent
|
|
15
|
+
import { Agent } from '@aws-blocks/bb-agent';
|
|
14
16
|
|
|
15
17
|
const scope = new Scope('my-app');
|
|
16
18
|
|
|
17
19
|
const agent = new Agent(scope, 'support-agent', {
|
|
18
|
-
model: { deployed: BedrockModels.DEFAULT },
|
|
19
20
|
systemPrompt: 'You are a helpful support agent.',
|
|
20
21
|
});
|
|
21
22
|
|
|
@@ -28,7 +29,7 @@ const result = await agent.stream('Until when are you open tomorrow?', { convers
|
|
|
28
29
|
const done = await result.complete();
|
|
29
30
|
console.log(done.text); // "We're open until 6pm tomorrow."
|
|
30
31
|
```
|
|
31
|
-
|
|
32
|
+
Uses [`BedrockModels.BALANCED`](#bedrock-presets) (Claude Sonnet 4.6) by default. See [Model Configuration](#model-configuration) for other presets, [Tools](#tools) for adding capabilities, and [Local Development](#local-development) for running without AWS Bedrock.
|
|
32
33
|
|
|
33
34
|
## API
|
|
34
35
|
|
|
@@ -47,7 +48,7 @@ const agent = new Agent(scope, id, config)
|
|
|
47
48
|
| `getPendingInterrupts(conversationId)` | `Promise<Array<...>>` | Get unanswered interrupts (for reload support). |
|
|
48
49
|
| `getChannel(channelId)` | `Promise<RealtimeChannel>` | Get a Realtime channel for subscribing to chunks. |
|
|
49
50
|
|
|
50
|
-
`stream()` submits the message to AsyncJob and returns immediately — no API Gateway timeout risk. The agent runs asynchronously and publishes chunks to Realtime.
|
|
51
|
+
`stream()` submits the message to AsyncJob and returns immediately — no API Gateway timeout risk. The agent runs asynchronously and publishes chunks to Realtime. The channel ID is resolved as `options.channelId || options.conversationId || crypto.randomUUID()` — empty strings are treated as unset and fall through to the next value.
|
|
51
52
|
|
|
52
53
|
**Important: Subscribe before sending.** The agent starts emitting chunks immediately after `stream()` is called. If you subscribe to the channel after calling `stream()`, early chunks may be dropped. Always subscribe first, await `established`, then send:
|
|
53
54
|
|
|
@@ -138,7 +139,7 @@ The `useChat` hook only surfaces `user`, `assistant`, and `approval` messages to
|
|
|
138
139
|
|
|
139
140
|
### Model Configuration
|
|
140
141
|
|
|
141
|
-
|
|
142
|
+
Model configuration is optional. When omitted, the agent defaults to `BedrockModels.BALANCED` (Claude Sonnet 4.6) for deployment. Local development works out of the box — the canned provider (keyword-based mock) is used automatically when no local model is specified.
|
|
142
143
|
|
|
143
144
|
| Option | Type | Description |
|
|
144
145
|
|--------|------|-------------|
|
|
@@ -190,14 +191,14 @@ model: {
|
|
|
190
191
|
|
|
191
192
|
#### Bedrock Presets
|
|
192
193
|
|
|
193
|
-
Pre-configured model presets for quick setup. Names are capability-based so the underlying model can be upgraded without breaking your code. These use cross-region
|
|
194
|
+
Pre-configured model presets for quick setup. Names are capability-based so the underlying model can be upgraded without breaking your code. These use [global inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html) — requests may be routed to any supported AWS region for optimal throughput. If your workload has data residency requirements, specify a region-scoped inference profile explicitly instead of using a preset.
|
|
194
195
|
|
|
195
196
|
```typescript
|
|
196
197
|
import { Agent, BedrockModels} from '@aws-blocks/bb-agent';
|
|
197
198
|
|
|
198
199
|
const agent = new Agent(scope, 'agent', {
|
|
199
200
|
model: {
|
|
200
|
-
deployed: BedrockModels.
|
|
201
|
+
deployed: BedrockModels.BALANCED,
|
|
201
202
|
},
|
|
202
203
|
systemPrompt: '...',
|
|
203
204
|
});
|
|
@@ -205,15 +206,15 @@ const agent = new Agent(scope, 'agent', {
|
|
|
205
206
|
|
|
206
207
|
| Preset | Current Model | Notes |
|
|
207
208
|
|--------|---------------|-------|
|
|
208
|
-
| `BedrockModels.
|
|
209
|
-
| `BedrockModels.
|
|
210
|
-
| `BedrockModels.FAST` | `
|
|
211
|
-
|
|
212
|
-
|
|
209
|
+
| `BedrockModels.BALANCED` | `global.anthropic.claude-sonnet-4-6` | Great tool use, balanced cost. Recommended default for most workloads. |
|
|
210
|
+
| `BedrockModels.SMART` | `global.anthropic.claude-opus-4-8` | Highest capability for the hardest tasks. |
|
|
211
|
+
| `BedrockModels.FAST` | `global.anthropic.claude-haiku-4-5-20251001-v1:0` | Lowest latency, still strong capabilities. |
|
|
212
|
+
|
|
213
|
+
> **Migrating?** `DEFAULT` → `BALANCED` (or `SMART` for highest capability). `BUDGET`/`MICRO` → `FAST`. The old presets are still available but deprecated. Please consider upgrading!
|
|
213
214
|
|
|
214
215
|
Override inference settings with spread:
|
|
215
216
|
```typescript
|
|
216
|
-
model: { deployed: { ...BedrockModels.
|
|
217
|
+
model: { deployed: { ...BedrockModels.BALANCED, inferenceConfig: { temperature: 0.9, maxTokens: 8192 } } }
|
|
217
218
|
```
|
|
218
219
|
|
|
219
220
|
#### Ollama Presets
|
|
@@ -225,7 +226,7 @@ import { Agent, BedrockModels, OllamaModels} from '@aws-blocks/bb-agent';
|
|
|
225
226
|
|
|
226
227
|
const agent = new Agent(scope, 'agent', {
|
|
227
228
|
model: {
|
|
228
|
-
deployed: BedrockModels.
|
|
229
|
+
deployed: BedrockModels.BALANCED,
|
|
229
230
|
local: OllamaModels.SMALL,
|
|
230
231
|
},
|
|
231
232
|
systemPrompt: '...',
|
|
@@ -262,7 +263,7 @@ To see detailed health check logs, pass a logger with `info` level:
|
|
|
262
263
|
import { Logger } from '@aws-blocks/bb-logger';
|
|
263
264
|
|
|
264
265
|
const agent = new Agent(scope, 'agent', {
|
|
265
|
-
model: { deployed: BedrockModels.
|
|
266
|
+
model: { deployed: BedrockModels.BALANCED },
|
|
266
267
|
systemPrompt: '...',
|
|
267
268
|
logger: new Logger(scope, 'agent-log', { level: 'info' }),
|
|
268
269
|
});
|
|
@@ -541,7 +542,7 @@ The Agent BB works without a frontend — for scripts, background jobs, or serve
|
|
|
541
542
|
import { Agent, BedrockModels } from '@aws-blocks/bb-agent';
|
|
542
543
|
|
|
543
544
|
const agent = new Agent(scope, 'summarizer', {
|
|
544
|
-
model: { deployed: BedrockModels.
|
|
545
|
+
model: { deployed: BedrockModels.BALANCED },
|
|
545
546
|
systemPrompt: 'Summarize the input concisely.',
|
|
546
547
|
});
|
|
547
548
|
|
|
@@ -560,7 +561,7 @@ import { Agent, BedrockModels, InterruptError } from '@aws-blocks/bb-agent';
|
|
|
560
561
|
import { z } from 'zod';
|
|
561
562
|
|
|
562
563
|
const refundBot = new Agent(scope, 'refunds', {
|
|
563
|
-
model: { deployed: BedrockModels.
|
|
564
|
+
model: { deployed: BedrockModels.BALANCED },
|
|
564
565
|
systemPrompt: 'You process customer refund requests.',
|
|
565
566
|
tools: (tool) => ({
|
|
566
567
|
issueRefund: tool({
|
|
@@ -687,7 +688,7 @@ import { Agent, BedrockModels } from '@aws-blocks/bb-agent';
|
|
|
687
688
|
const scope = new Scope('my-app');
|
|
688
689
|
|
|
689
690
|
const agent = new Agent(scope, 'chat', {
|
|
690
|
-
model: { deployed: BedrockModels.
|
|
691
|
+
model: { deployed: BedrockModels.BALANCED },
|
|
691
692
|
systemPrompt: 'You are a helpful assistant.',
|
|
692
693
|
});
|
|
693
694
|
|
|
@@ -751,7 +752,7 @@ const scope = new Scope('my-app');
|
|
|
751
752
|
const kb = new KnowledgeBase(scope, 'docs', { source: './knowledge' });
|
|
752
753
|
|
|
753
754
|
const agent = new Agent(scope, 'support', {
|
|
754
|
-
model: { deployed: BedrockModels.
|
|
755
|
+
model: { deployed: BedrockModels.BALANCED },
|
|
755
756
|
systemPrompt: 'You are a customer support agent. Look up orders and search documentation to help the user.',
|
|
756
757
|
toolContextSchema: z.object({ userId: z.string() }),
|
|
757
758
|
tools: (tool) => ({
|
package/dist/agent.aws.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.aws.d.ts","sourceRoot":"","sources":["../src/agent.aws.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.aws.d.ts","sourceRoot":"","sources":["../src/agent.aws.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGlE,qBAAa,KAAK,CAAC,QAAQ,GAAG,kBAAkB,CAAE,SAAQ,SAAS,CAAC,QAAQ,CAAC;gBAChE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC;CAGzE"}
|
package/dist/agent.aws.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { AgentBase } from './agent.js';
|
|
4
4
|
import { S3Storage } from '@strands-agents/sdk/session/s3-storage';
|
|
5
|
+
import { BedrockModels } from './models.js';
|
|
5
6
|
export class Agent extends AgentBase {
|
|
6
7
|
constructor(scope, id, config) {
|
|
7
|
-
super(scope, id, config, config.model.
|
|
8
|
+
super(scope, id, config, config.model?.deployed ?? BedrockModels.BALANCED, (bucket) => new S3Storage({ bucket: bucket.fullId }));
|
|
8
9
|
}
|
|
9
10
|
}
|
package/dist/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAA6C,MAAM,kBAAkB,CAAC;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAMzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D,OAAO,KAAK,EAAE,WAAW,EAAoB,iBAAiB,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,EAAyC,WAAW,EAAa,iBAAiB,EAAE,kBAAkB,EAA6B,MAAM,YAAY,CAAC;AA+D1P;;;;;;;;;GASG;AACH,qBAAa,SAAS,CAAC,QAAQ,GAAG,kBAAkB,CAAE,SAAQ,KAAK;IAClE,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAwB;IACtC,yFAAyF;IACzF,OAAO,CAAC,OAAO,CAAmC;IAClD,mCAAmC;IACnC,OAAO,CAAC,aAAa,CAAC,CAA8G;IACpI,6BAA6B;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAA4G;IAC7H,oDAAoD;IACpD,OAAO,CAAC,EAAE,CAAgC;IAC1C,mFAAmF;IACnF,OAAO,CAAC,GAAG,CAA6C;IACxD,mCAAmC;IACnC,OAAO,CAAC,WAAW,CAA0C;IAC7D,wDAAwD;IACxD,OAAO,CAAC,eAAe,CAAkB;IACzC,+CAA+C;IAC/C,OAAO,CAAC,aAAa,CAAa;IAClC,2FAA2F;IAC3F,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC;IAE3B;;;;;;OAMG;gBACS,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,EAAE,WAAW,EAAE,WAAW,GAAG,WAAW,EAAE,GAAG,SAAS,EAAE,qBAAqB,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,eAAe;IAgE/L;;;;;;;;OAQG;YACW,QAAQ;YA0GR,kBAAkB;IA+FhC;;;;;;;;OAQG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../src/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/agent.js
CHANGED
|
@@ -377,7 +377,7 @@ export class AgentBase extends Scope {
|
|
|
377
377
|
*/
|
|
378
378
|
async stream(message, options) {
|
|
379
379
|
const conversationId = options?.conversationId;
|
|
380
|
-
const channelId = options?.channelId
|
|
380
|
+
const channelId = options?.channelId || conversationId || crypto.randomUUID();
|
|
381
381
|
if (!options?.userId && !this.config.inferenceOnly)
|
|
382
382
|
throw blocksAgentError(AgentErrors.PersistenceRequired, 'userId is required when persistence is enabled. Pass it via options.userId.');
|
|
383
383
|
const userId = options?.userId ?? 'anonymous';
|
|
@@ -405,6 +405,7 @@ export class AgentBase extends Scope {
|
|
|
405
405
|
}
|
|
406
406
|
});
|
|
407
407
|
}),
|
|
408
|
+
toJSON() { return { channelId, channel: null }; },
|
|
408
409
|
};
|
|
409
410
|
}
|
|
410
411
|
/**
|
package/dist/agent.mock.js
CHANGED
|
@@ -5,7 +5,7 @@ import { FileBucketSnapshotStorage } from './file-bucket-snapshot-storage.js';
|
|
|
5
5
|
export class Agent extends AgentBase {
|
|
6
6
|
constructor(scope, id, config) {
|
|
7
7
|
// Canned provider is appended as implicit last fallback for local dev
|
|
8
|
-
const local = config.model
|
|
8
|
+
const local = config.model?.local;
|
|
9
9
|
const candidates = local ? (Array.isArray(local) ? [...local, { provider: 'canned' }] : [local, { provider: 'canned' }]) : [{ provider: 'canned' }];
|
|
10
10
|
super(scope, id, config, candidates, (bucket) => new FileBucketSnapshotStorage(bucket));
|
|
11
11
|
}
|
package/dist/index.test.js
CHANGED
|
@@ -97,6 +97,34 @@ describe('needsApproval and interrupt mutual exclusivity', () => {
|
|
|
97
97
|
assert.ok(result.channelId);
|
|
98
98
|
});
|
|
99
99
|
});
|
|
100
|
+
// ── AgentStreamResult.toJSON() ───────────────────────────────────────────────
|
|
101
|
+
describe('AgentStreamResult.toJSON()', () => {
|
|
102
|
+
test('serializes to { channelId, channel: null }', async () => {
|
|
103
|
+
const scope = new Scope('test-tojson');
|
|
104
|
+
const agent = new Agent(scope, 'tj', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
105
|
+
const result = await agent.stream('hello', { userId: 'test-user' });
|
|
106
|
+
const serialized = JSON.parse(JSON.stringify(result));
|
|
107
|
+
assert.deepStrictEqual(serialized, { channelId: result.channelId, channel: null });
|
|
108
|
+
assert.strictEqual('complete' in serialized, false);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
// ── stream() empty channelId fallback ────────────────────────────────────────
|
|
112
|
+
describe('stream() empty channelId fallback', () => {
|
|
113
|
+
test('empty channelId is treated as unset', async () => {
|
|
114
|
+
const scope = new Scope('test-empty-ch');
|
|
115
|
+
const agent = new Agent(scope, 'ec', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
116
|
+
const result = await agent.stream('hello', { userId: 'test-user', channelId: '' });
|
|
117
|
+
assert.notStrictEqual(result.channelId, '');
|
|
118
|
+
assert.ok(result.channelId.length > 0);
|
|
119
|
+
});
|
|
120
|
+
test('empty conversationId is treated as unset', async () => {
|
|
121
|
+
const scope = new Scope('test-empty-conv');
|
|
122
|
+
const agent = new Agent(scope, 'ev', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
123
|
+
const result = await agent.stream('hello', { userId: 'test-user', conversationId: '' });
|
|
124
|
+
assert.notStrictEqual(result.channelId, '');
|
|
125
|
+
assert.ok(result.channelId.length > 0);
|
|
126
|
+
});
|
|
127
|
+
});
|
|
100
128
|
// ── tool factory enforcement (compile-time) ──────────────────────────────────
|
|
101
129
|
describe('tool factory enforcement', () => {
|
|
102
130
|
// Regression: AgentConfig.tools is a callback `(tool) => Record<string, AgentTool>`.
|
|
@@ -839,10 +867,17 @@ describe('checkModelHealth', () => {
|
|
|
839
867
|
});
|
|
840
868
|
});
|
|
841
869
|
// ── Model Presets ─────────────────────────────────────────────────────────────
|
|
870
|
+
describe('default model', () => {
|
|
871
|
+
test('agent can be created without model config', () => {
|
|
872
|
+
const s = new Scope('test-default-model');
|
|
873
|
+
const agent = new Agent(s, 'no-model', { systemPrompt: 'test' });
|
|
874
|
+
assert.ok(agent);
|
|
875
|
+
});
|
|
876
|
+
});
|
|
842
877
|
describe('BedrockModels presets', () => {
|
|
843
|
-
test('
|
|
844
|
-
assert.strictEqual(BedrockModels.
|
|
845
|
-
assert.ok(BedrockModels.
|
|
878
|
+
test('BALANCED resolves to a bedrock provider', async () => {
|
|
879
|
+
assert.strictEqual(BedrockModels.BALANCED.provider, 'bedrock');
|
|
880
|
+
assert.ok(BedrockModels.BALANCED.modelId);
|
|
846
881
|
});
|
|
847
882
|
test('all presets have provider bedrock and a modelId', () => {
|
|
848
883
|
for (const [name, config] of Object.entries(BedrockModels)) {
|
|
@@ -850,8 +885,8 @@ describe('BedrockModels presets', () => {
|
|
|
850
885
|
assert.ok(config.modelId, `${name} should have a modelId`);
|
|
851
886
|
}
|
|
852
887
|
});
|
|
853
|
-
test('
|
|
854
|
-
const model = await createStrandsModel(BedrockModels.
|
|
888
|
+
test('BALANCED flows through createStrandsModel to BedrockModel', async () => {
|
|
889
|
+
const model = await createStrandsModel(BedrockModels.BALANCED);
|
|
855
890
|
assert.ok(model, 'should create a model instance');
|
|
856
891
|
});
|
|
857
892
|
});
|
package/dist/models.d.ts
CHANGED
|
@@ -1,32 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Pre-configured Bedrock model presets using
|
|
2
|
+
* Pre-configured Bedrock model presets using global inference profiles.
|
|
3
3
|
* Names are capability-based so the underlying model can be upgraded without breaking user code.
|
|
4
|
+
*
|
|
5
|
+
* **Note:** Global inference profiles route requests to any supported AWS region for
|
|
6
|
+
* optimal throughput. If your workload has data residency requirements, specify a
|
|
7
|
+
* region-scoped inference profile explicitly.
|
|
8
|
+
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html
|
|
4
9
|
*/
|
|
5
10
|
export declare const BedrockModels: {
|
|
6
|
-
/**
|
|
7
|
-
readonly
|
|
11
|
+
/** Great tool use, balanced cost — good middle tier for most workloads. Currently: Claude Sonnet 4.6. */
|
|
12
|
+
readonly BALANCED: {
|
|
8
13
|
readonly provider: "bedrock";
|
|
9
|
-
readonly modelId: "
|
|
14
|
+
readonly modelId: "global.anthropic.claude-sonnet-4-6";
|
|
10
15
|
};
|
|
11
|
-
/**
|
|
12
|
-
readonly
|
|
16
|
+
/** Highest capability for the hardest tasks. Currently: Claude Opus 4.8. */
|
|
17
|
+
readonly SMART: {
|
|
13
18
|
readonly provider: "bedrock";
|
|
14
|
-
readonly modelId: "
|
|
19
|
+
readonly modelId: "global.anthropic.claude-opus-4-8";
|
|
15
20
|
};
|
|
16
|
-
/**
|
|
21
|
+
/** Lowest latency, still strong capabilities. Currently: Claude Haiku 4.5. */
|
|
17
22
|
readonly FAST: {
|
|
18
23
|
readonly provider: "bedrock";
|
|
19
|
-
readonly modelId: "
|
|
24
|
+
readonly modelId: "global.anthropic.claude-haiku-4-5-20251001-v1:0";
|
|
25
|
+
};
|
|
26
|
+
/** @deprecated Use `BedrockModels.BALANCED` instead. */
|
|
27
|
+
readonly DEFAULT: {
|
|
28
|
+
readonly provider: "bedrock";
|
|
29
|
+
readonly modelId: "global.anthropic.claude-sonnet-4-6";
|
|
20
30
|
};
|
|
21
|
-
/**
|
|
31
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
22
32
|
readonly BUDGET: {
|
|
23
33
|
readonly provider: "bedrock";
|
|
24
|
-
readonly modelId: "
|
|
34
|
+
readonly modelId: "global.anthropic.claude-haiku-4-5-20251001-v1:0";
|
|
25
35
|
};
|
|
26
|
-
/**
|
|
36
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
27
37
|
readonly MICRO: {
|
|
28
38
|
readonly provider: "bedrock";
|
|
29
|
-
readonly modelId: "
|
|
39
|
+
readonly modelId: "global.anthropic.claude-haiku-4-5-20251001-v1:0";
|
|
30
40
|
};
|
|
31
41
|
};
|
|
32
42
|
/**
|
package/dist/models.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"AASA;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;IACzB,yGAAyG;;;;;IAKzG,4EAA4E;;;;;IAK5E,8EAA8E;;;;;IAM9E,wDAAwD;;;;;IAKxD,oDAAoD;;;;;IAKpD,oDAAoD;;;;;CAKL,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY;IACxB,kGAAkG;;;;;;;IAOlG,gGAAgG;;;;;;;IAOhG,+FAA+F;;;;;;;IAQ/F,4FAA4F;;;;;;;IAO5F,iFAAiF;;;;;;;CAOlC,CAAC"}
|
package/dist/models.js
CHANGED
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
const BALANCED_MODEL_ID = 'global.anthropic.claude-sonnet-4-6';
|
|
4
|
+
const SMART_MODEL_ID = 'global.anthropic.claude-opus-4-8';
|
|
5
|
+
const FAST_MODEL_ID = 'global.anthropic.claude-haiku-4-5-20251001-v1:0';
|
|
3
6
|
/**
|
|
4
|
-
* Pre-configured Bedrock model presets using
|
|
7
|
+
* Pre-configured Bedrock model presets using global inference profiles.
|
|
5
8
|
* Names are capability-based so the underlying model can be upgraded without breaking user code.
|
|
9
|
+
*
|
|
10
|
+
* **Note:** Global inference profiles route requests to any supported AWS region for
|
|
11
|
+
* optimal throughput. If your workload has data residency requirements, specify a
|
|
12
|
+
* region-scoped inference profile explicitly.
|
|
13
|
+
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html
|
|
6
14
|
*/
|
|
7
15
|
export const BedrockModels = {
|
|
8
|
-
/**
|
|
9
|
-
|
|
16
|
+
/** Great tool use, balanced cost — good middle tier for most workloads. Currently: Claude Sonnet 4.6. */
|
|
17
|
+
BALANCED: {
|
|
10
18
|
provider: 'bedrock',
|
|
11
|
-
modelId:
|
|
19
|
+
modelId: BALANCED_MODEL_ID,
|
|
12
20
|
},
|
|
13
|
-
/**
|
|
14
|
-
|
|
21
|
+
/** Highest capability for the hardest tasks. Currently: Claude Opus 4.8. */
|
|
22
|
+
SMART: {
|
|
15
23
|
provider: 'bedrock',
|
|
16
|
-
modelId:
|
|
24
|
+
modelId: SMART_MODEL_ID,
|
|
17
25
|
},
|
|
18
|
-
/**
|
|
26
|
+
/** Lowest latency, still strong capabilities. Currently: Claude Haiku 4.5. */
|
|
19
27
|
FAST: {
|
|
20
28
|
provider: 'bedrock',
|
|
21
|
-
modelId:
|
|
29
|
+
modelId: FAST_MODEL_ID,
|
|
30
|
+
},
|
|
31
|
+
/** @deprecated Use `BedrockModels.BALANCED` instead. */
|
|
32
|
+
DEFAULT: {
|
|
33
|
+
provider: 'bedrock',
|
|
34
|
+
modelId: BALANCED_MODEL_ID,
|
|
22
35
|
},
|
|
23
|
-
/**
|
|
36
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
24
37
|
BUDGET: {
|
|
25
38
|
provider: 'bedrock',
|
|
26
|
-
modelId:
|
|
39
|
+
modelId: FAST_MODEL_ID,
|
|
27
40
|
},
|
|
28
|
-
/**
|
|
41
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
29
42
|
MICRO: {
|
|
30
43
|
provider: 'bedrock',
|
|
31
|
-
modelId:
|
|
44
|
+
modelId: FAST_MODEL_ID,
|
|
32
45
|
},
|
|
33
46
|
};
|
|
34
47
|
/**
|
|
@@ -61,6 +74,7 @@ export const OllamaModels = {
|
|
|
61
74
|
apiKey: 'ollama',
|
|
62
75
|
},
|
|
63
76
|
/** Strong reasoning at moderate size. Currently: DeepSeek R1 14B (~9 GB, needs 16 GB VRAM). */
|
|
77
|
+
// TODO: DeepSeek R1 is strong at reasoning but weak at tool calling — swap to a more tool-capable model.
|
|
64
78
|
MEDIUM: {
|
|
65
79
|
provider: 'openai-api',
|
|
66
80
|
modelId: 'deepseek-r1:14b',
|
package/dist/types.d.ts
CHANGED
|
@@ -41,9 +41,9 @@ export interface AgentConfig<TContext = DefaultToolContext> {
|
|
|
41
41
|
* The agent does inference + tools only — no conversation history.
|
|
42
42
|
*/
|
|
43
43
|
inferenceOnly?: boolean;
|
|
44
|
-
model
|
|
45
|
-
/** Model(s) for AWS deployment. Tries candidates in order; throws if all fail. */
|
|
46
|
-
deployed
|
|
44
|
+
model?: {
|
|
45
|
+
/** Model(s) for AWS deployment. Tries candidates in order; throws if all fail. Defaults to BedrockModels.BALANCED. */
|
|
46
|
+
deployed?: ModelConfig | ModelConfig[];
|
|
47
47
|
/** Model(s) for local development. Tries candidates in order; canned is implicit last fallback. */
|
|
48
48
|
local?: ModelConfig | ModelConfig[];
|
|
49
49
|
};
|
|
@@ -235,7 +235,7 @@ export interface ToolCallRecord {
|
|
|
235
235
|
}
|
|
236
236
|
export interface StreamOptions<TContext = DefaultToolContext> {
|
|
237
237
|
conversationId?: string;
|
|
238
|
-
/** Channel ID for Realtime delivery. Defaults to conversationId or a random UUID. */
|
|
238
|
+
/** Channel ID for Realtime delivery. Defaults to conversationId or a random UUID. Empty strings are treated as unset. */
|
|
239
239
|
channelId?: string;
|
|
240
240
|
/** User ID for conversation scoping. Defaults to 'anonymous'. */
|
|
241
241
|
userId?: string;
|
|
@@ -247,14 +247,33 @@ export interface StreamOptions<TContext = DefaultToolContext> {
|
|
|
247
247
|
*/
|
|
248
248
|
context?: TContext;
|
|
249
249
|
}
|
|
250
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Returned by stream(). Provides the channelId and server-side convenience methods.
|
|
252
|
+
*
|
|
253
|
+
* Safe to return directly from API methods — `toJSON()` serializes to
|
|
254
|
+
* `{ channelId, channel: null }`. Only `channelId` is meaningful client-side;
|
|
255
|
+
* `channel` is explicitly `null` to signal the live handle is server-side only,
|
|
256
|
+
* and the `complete()` helper is dropped (functions don't serialize).
|
|
257
|
+
*/
|
|
251
258
|
export interface AgentStreamResult {
|
|
252
259
|
/** Realtime channel ID where chunks are published. */
|
|
253
260
|
channelId: string;
|
|
254
|
-
/**
|
|
261
|
+
/**
|
|
262
|
+
* Realtime channel handle (server-side only). Nulled by `toJSON()` — clients subscribe from `channelId` instead.
|
|
263
|
+
*
|
|
264
|
+
* @remarks
|
|
265
|
+
* Unlike `RealtimeChannel.toJSON()` which produces a hydratable descriptor, this is nulled
|
|
266
|
+
* because it's a `Promise` that can't round-trip. Clients reconstruct a subscribe-only
|
|
267
|
+
* channel from `channelId` via the `useChat` `subscribe` callback.
|
|
268
|
+
*/
|
|
255
269
|
channel: Promise<RealtimeChannel<AgentStreamChunk>>;
|
|
256
270
|
/** Wait for the complete response (server-side). Resolves when the done chunk arrives. */
|
|
257
271
|
complete: () => Promise<AgentStreamChunk>;
|
|
272
|
+
/** Only `{ channelId, channel: null }` is serialized when this object crosses the RPC boundary. */
|
|
273
|
+
toJSON(): {
|
|
274
|
+
channelId: string;
|
|
275
|
+
channel: null;
|
|
276
|
+
};
|
|
258
277
|
}
|
|
259
278
|
export interface AgentStreamChunk {
|
|
260
279
|
type: 'text-delta' | 'tool-call' | 'tool-result' | 'done' | 'error' | 'interrupt';
|
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,EAAE;
|
|
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.3.0",
|
|
4
4
|
"author": "Amazon Web Services",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"dist",
|
|
9
9
|
"MODELS.md",
|
|
10
10
|
"README.md",
|
|
11
|
+
"DESIGN.md",
|
|
11
12
|
"src",
|
|
12
13
|
"LICENSE"
|
|
13
14
|
],
|
|
@@ -33,12 +34,12 @@
|
|
|
33
34
|
"test": "node --test dist/index.test.js"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
|
-
"@aws-blocks/bb-async-job": "^0.1.
|
|
37
|
-
"@aws-blocks/bb-distributed-table": "^0.1.
|
|
38
|
-
"@aws-blocks/bb-file-bucket": "^0.1.
|
|
39
|
-
"@aws-blocks/bb-logger": "^0.1.
|
|
40
|
-
"@aws-blocks/bb-realtime": "^0.1.
|
|
41
|
-
"@aws-blocks/core": "^0.1.
|
|
37
|
+
"@aws-blocks/bb-async-job": "^0.1.2",
|
|
38
|
+
"@aws-blocks/bb-distributed-table": "^0.1.3",
|
|
39
|
+
"@aws-blocks/bb-file-bucket": "^0.1.2",
|
|
40
|
+
"@aws-blocks/bb-logger": "^0.1.2",
|
|
41
|
+
"@aws-blocks/bb-realtime": "^0.1.2",
|
|
42
|
+
"@aws-blocks/core": "^0.1.10",
|
|
42
43
|
"@aws-sdk/client-bedrock": "^3.700.0",
|
|
43
44
|
"@strands-agents/sdk": "~1.3.0",
|
|
44
45
|
"openai": "^6.7.0",
|
package/src/agent.aws.ts
CHANGED
|
@@ -5,9 +5,10 @@ import type { ScopeParent } from '@aws-blocks/core';
|
|
|
5
5
|
import { AgentBase } from './agent.js';
|
|
6
6
|
import { S3Storage } from '@strands-agents/sdk/session/s3-storage';
|
|
7
7
|
import type { AgentConfig, DefaultToolContext } from './types.js';
|
|
8
|
+
import { BedrockModels } from './models.js';
|
|
8
9
|
|
|
9
10
|
export class Agent<TContext = DefaultToolContext> extends AgentBase<TContext> {
|
|
10
11
|
constructor(scope: ScopeParent, id: string, config: AgentConfig<TContext>) {
|
|
11
|
-
super(scope, id, config, config.model.
|
|
12
|
+
super(scope, id, config, config.model?.deployed ?? BedrockModels.BALANCED, (bucket) => new S3Storage({ bucket: bucket.fullId }));
|
|
12
13
|
}
|
|
13
14
|
}
|
package/src/agent.mock.ts
CHANGED
|
@@ -9,7 +9,7 @@ import type { AgentConfig, DefaultToolContext } from './types.js';
|
|
|
9
9
|
export class Agent<TContext = DefaultToolContext> extends AgentBase<TContext> {
|
|
10
10
|
constructor(scope: ScopeParent, id: string, config: AgentConfig<TContext>) {
|
|
11
11
|
// Canned provider is appended as implicit last fallback for local dev
|
|
12
|
-
const local = config.model
|
|
12
|
+
const local = config.model?.local;
|
|
13
13
|
const candidates = local ? (Array.isArray(local) ? [...local, { provider: 'canned' as const }] : [local, { provider: 'canned' as const }]) : [{ provider: 'canned' as const }];
|
|
14
14
|
super(scope, id, config, candidates, (bucket) => new FileBucketSnapshotStorage(bucket));
|
|
15
15
|
}
|
package/src/agent.ts
CHANGED
|
@@ -403,7 +403,7 @@ export class AgentBase<TContext = DefaultToolContext> extends Scope {
|
|
|
403
403
|
*/
|
|
404
404
|
async stream(message: string, options?: StreamOptions<TContext>): Promise<AgentStreamResult> {
|
|
405
405
|
const conversationId = options?.conversationId;
|
|
406
|
-
const channelId = options?.channelId
|
|
406
|
+
const channelId = options?.channelId || conversationId || crypto.randomUUID();
|
|
407
407
|
if (!options?.userId && !this.config.inferenceOnly) throw blocksAgentError(AgentErrors.PersistenceRequired, 'userId is required when persistence is enabled. Pass it via options.userId.');
|
|
408
408
|
const userId = options?.userId ?? 'anonymous';
|
|
409
409
|
const context = this.resolveContext(options?.context);
|
|
@@ -428,6 +428,7 @@ export class AgentBase<TContext = DefaultToolContext> extends Scope {
|
|
|
428
428
|
}
|
|
429
429
|
});
|
|
430
430
|
}),
|
|
431
|
+
toJSON() { return { channelId, channel: null }; },
|
|
431
432
|
};
|
|
432
433
|
}
|
|
433
434
|
|
package/src/index.test.ts
CHANGED
|
@@ -115,6 +115,39 @@ describe('needsApproval and interrupt mutual exclusivity', () => {
|
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
|
|
118
|
+
// ── AgentStreamResult.toJSON() ───────────────────────────────────────────────
|
|
119
|
+
|
|
120
|
+
describe('AgentStreamResult.toJSON()', () => {
|
|
121
|
+
test('serializes to { channelId, channel: null }', async () => {
|
|
122
|
+
const scope = new Scope('test-tojson');
|
|
123
|
+
const agent = new Agent(scope, 'tj', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
124
|
+
const result = await agent.stream('hello', { userId: 'test-user' });
|
|
125
|
+
const serialized = JSON.parse(JSON.stringify(result));
|
|
126
|
+
assert.deepStrictEqual(serialized, { channelId: result.channelId, channel: null });
|
|
127
|
+
assert.strictEqual('complete' in serialized, false);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// ── stream() empty channelId fallback ────────────────────────────────────────
|
|
132
|
+
|
|
133
|
+
describe('stream() empty channelId fallback', () => {
|
|
134
|
+
test('empty channelId is treated as unset', async () => {
|
|
135
|
+
const scope = new Scope('test-empty-ch');
|
|
136
|
+
const agent = new Agent(scope, 'ec', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
137
|
+
const result = await agent.stream('hello', { userId: 'test-user', channelId: '' });
|
|
138
|
+
assert.notStrictEqual(result.channelId, '');
|
|
139
|
+
assert.ok(result.channelId.length > 0);
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('empty conversationId is treated as unset', async () => {
|
|
143
|
+
const scope = new Scope('test-empty-conv');
|
|
144
|
+
const agent = new Agent(scope, 'ev', { systemPrompt: 'test', model: { deployed: { provider: 'canned' }, local: { provider: 'canned' } } });
|
|
145
|
+
const result = await agent.stream('hello', { userId: 'test-user', conversationId: '' });
|
|
146
|
+
assert.notStrictEqual(result.channelId, '');
|
|
147
|
+
assert.ok(result.channelId.length > 0);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
118
151
|
// ── tool factory enforcement (compile-time) ──────────────────────────────────
|
|
119
152
|
|
|
120
153
|
describe('tool factory enforcement', () => {
|
|
@@ -983,10 +1016,18 @@ describe('checkModelHealth', () => {
|
|
|
983
1016
|
|
|
984
1017
|
// ── Model Presets ─────────────────────────────────────────────────────────────
|
|
985
1018
|
|
|
1019
|
+
describe('default model', () => {
|
|
1020
|
+
test('agent can be created without model config', () => {
|
|
1021
|
+
const s = new Scope('test-default-model');
|
|
1022
|
+
const agent = new Agent(s, 'no-model', { systemPrompt: 'test' });
|
|
1023
|
+
assert.ok(agent);
|
|
1024
|
+
});
|
|
1025
|
+
});
|
|
1026
|
+
|
|
986
1027
|
describe('BedrockModels presets', () => {
|
|
987
|
-
test('
|
|
988
|
-
assert.strictEqual(BedrockModels.
|
|
989
|
-
assert.ok(BedrockModels.
|
|
1028
|
+
test('BALANCED resolves to a bedrock provider', async () => {
|
|
1029
|
+
assert.strictEqual(BedrockModels.BALANCED.provider, 'bedrock');
|
|
1030
|
+
assert.ok(BedrockModels.BALANCED.modelId);
|
|
990
1031
|
});
|
|
991
1032
|
|
|
992
1033
|
test('all presets have provider bedrock and a modelId', () => {
|
|
@@ -996,8 +1037,8 @@ describe('BedrockModels presets', () => {
|
|
|
996
1037
|
}
|
|
997
1038
|
});
|
|
998
1039
|
|
|
999
|
-
test('
|
|
1000
|
-
const model = await createStrandsModel(BedrockModels.
|
|
1040
|
+
test('BALANCED flows through createStrandsModel to BedrockModel', async () => {
|
|
1041
|
+
const model = await createStrandsModel(BedrockModels.BALANCED);
|
|
1001
1042
|
assert.ok(model, 'should create a model instance');
|
|
1002
1043
|
});
|
|
1003
1044
|
});
|
package/src/models.ts
CHANGED
|
@@ -3,35 +3,50 @@
|
|
|
3
3
|
|
|
4
4
|
import type { ModelConfig } from './types.js';
|
|
5
5
|
|
|
6
|
+
const BALANCED_MODEL_ID = 'global.anthropic.claude-sonnet-4-6';
|
|
7
|
+
const SMART_MODEL_ID = 'global.anthropic.claude-opus-4-8';
|
|
8
|
+
const FAST_MODEL_ID = 'global.anthropic.claude-haiku-4-5-20251001-v1:0';
|
|
9
|
+
|
|
6
10
|
/**
|
|
7
|
-
* Pre-configured Bedrock model presets using
|
|
11
|
+
* Pre-configured Bedrock model presets using global inference profiles.
|
|
8
12
|
* Names are capability-based so the underlying model can be upgraded without breaking user code.
|
|
13
|
+
*
|
|
14
|
+
* **Note:** Global inference profiles route requests to any supported AWS region for
|
|
15
|
+
* optimal throughput. If your workload has data residency requirements, specify a
|
|
16
|
+
* region-scoped inference profile explicitly.
|
|
17
|
+
* @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html
|
|
9
18
|
*/
|
|
10
19
|
export const BedrockModels = {
|
|
11
|
-
/**
|
|
12
|
-
|
|
20
|
+
/** Great tool use, balanced cost — good middle tier for most workloads. Currently: Claude Sonnet 4.6. */
|
|
21
|
+
BALANCED: {
|
|
13
22
|
provider: 'bedrock',
|
|
14
|
-
modelId:
|
|
23
|
+
modelId: BALANCED_MODEL_ID,
|
|
15
24
|
},
|
|
16
|
-
/**
|
|
17
|
-
|
|
25
|
+
/** Highest capability for the hardest tasks. Currently: Claude Opus 4.8. */
|
|
26
|
+
SMART: {
|
|
18
27
|
provider: 'bedrock',
|
|
19
|
-
modelId:
|
|
28
|
+
modelId: SMART_MODEL_ID,
|
|
20
29
|
},
|
|
21
|
-
/**
|
|
30
|
+
/** Lowest latency, still strong capabilities. Currently: Claude Haiku 4.5. */
|
|
22
31
|
FAST: {
|
|
23
32
|
provider: 'bedrock',
|
|
24
|
-
modelId:
|
|
33
|
+
modelId: FAST_MODEL_ID,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/** @deprecated Use `BedrockModels.BALANCED` instead. */
|
|
37
|
+
DEFAULT: {
|
|
38
|
+
provider: 'bedrock',
|
|
39
|
+
modelId: BALANCED_MODEL_ID,
|
|
25
40
|
},
|
|
26
|
-
/**
|
|
41
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
27
42
|
BUDGET: {
|
|
28
43
|
provider: 'bedrock',
|
|
29
|
-
modelId:
|
|
44
|
+
modelId: FAST_MODEL_ID,
|
|
30
45
|
},
|
|
31
|
-
/**
|
|
46
|
+
/** @deprecated Use `BedrockModels.FAST` instead. */
|
|
32
47
|
MICRO: {
|
|
33
48
|
provider: 'bedrock',
|
|
34
|
-
modelId:
|
|
49
|
+
modelId: FAST_MODEL_ID,
|
|
35
50
|
},
|
|
36
51
|
} as const satisfies Record<string, ModelConfig>;
|
|
37
52
|
|
|
@@ -65,6 +80,7 @@ export const OllamaModels = {
|
|
|
65
80
|
apiKey: 'ollama',
|
|
66
81
|
},
|
|
67
82
|
/** Strong reasoning at moderate size. Currently: DeepSeek R1 14B (~9 GB, needs 16 GB VRAM). */
|
|
83
|
+
// TODO: DeepSeek R1 is strong at reasoning but weak at tool calling — swap to a more tool-capable model.
|
|
68
84
|
MEDIUM: {
|
|
69
85
|
provider: 'openai-api',
|
|
70
86
|
modelId: 'deepseek-r1:14b',
|
package/src/types.ts
CHANGED
|
@@ -48,9 +48,9 @@ export interface AgentConfig<TContext = DefaultToolContext> {
|
|
|
48
48
|
* The agent does inference + tools only — no conversation history.
|
|
49
49
|
*/
|
|
50
50
|
inferenceOnly?: boolean;
|
|
51
|
-
model
|
|
52
|
-
/** Model(s) for AWS deployment. Tries candidates in order; throws if all fail. */
|
|
53
|
-
deployed
|
|
51
|
+
model?: {
|
|
52
|
+
/** Model(s) for AWS deployment. Tries candidates in order; throws if all fail. Defaults to BedrockModels.BALANCED. */
|
|
53
|
+
deployed?: ModelConfig | ModelConfig[];
|
|
54
54
|
/** Model(s) for local development. Tries candidates in order; canned is implicit last fallback. */
|
|
55
55
|
local?: ModelConfig | ModelConfig[];
|
|
56
56
|
};
|
|
@@ -251,7 +251,7 @@ export interface ToolCallRecord {
|
|
|
251
251
|
|
|
252
252
|
export interface StreamOptions<TContext = DefaultToolContext> {
|
|
253
253
|
conversationId?: string;
|
|
254
|
-
/** Channel ID for Realtime delivery. Defaults to conversationId or a random UUID. */
|
|
254
|
+
/** Channel ID for Realtime delivery. Defaults to conversationId or a random UUID. Empty strings are treated as unset. */
|
|
255
255
|
channelId?: string;
|
|
256
256
|
/** User ID for conversation scoping. Defaults to 'anonymous'. */
|
|
257
257
|
userId?: string;
|
|
@@ -264,14 +264,30 @@ export interface StreamOptions<TContext = DefaultToolContext> {
|
|
|
264
264
|
context?: TContext;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
/**
|
|
267
|
+
/**
|
|
268
|
+
* Returned by stream(). Provides the channelId and server-side convenience methods.
|
|
269
|
+
*
|
|
270
|
+
* Safe to return directly from API methods — `toJSON()` serializes to
|
|
271
|
+
* `{ channelId, channel: null }`. Only `channelId` is meaningful client-side;
|
|
272
|
+
* `channel` is explicitly `null` to signal the live handle is server-side only,
|
|
273
|
+
* and the `complete()` helper is dropped (functions don't serialize).
|
|
274
|
+
*/
|
|
268
275
|
export interface AgentStreamResult {
|
|
269
276
|
/** Realtime channel ID where chunks are published. */
|
|
270
277
|
channelId: string;
|
|
271
|
-
/**
|
|
278
|
+
/**
|
|
279
|
+
* Realtime channel handle (server-side only). Nulled by `toJSON()` — clients subscribe from `channelId` instead.
|
|
280
|
+
*
|
|
281
|
+
* @remarks
|
|
282
|
+
* Unlike `RealtimeChannel.toJSON()` which produces a hydratable descriptor, this is nulled
|
|
283
|
+
* because it's a `Promise` that can't round-trip. Clients reconstruct a subscribe-only
|
|
284
|
+
* channel from `channelId` via the `useChat` `subscribe` callback.
|
|
285
|
+
*/
|
|
272
286
|
channel: Promise<RealtimeChannel<AgentStreamChunk>>;
|
|
273
287
|
/** Wait for the complete response (server-side). Resolves when the done chunk arrives. */
|
|
274
288
|
complete: () => Promise<AgentStreamChunk>;
|
|
289
|
+
/** Only `{ channelId, channel: null }` is serialized when this object crosses the RPC boundary. */
|
|
290
|
+
toJSON(): { channelId: string; channel: null };
|
|
275
291
|
}
|
|
276
292
|
|
|
277
293
|
export interface AgentStreamChunk {
|
package/src/version.ts
CHANGED