Skip to content
This repository was archived by the owner on Jun 3, 2026. It is now read-only.

Commit 4b5b009

Browse files
Task 05: Create Tool Interface Implementation (#20)
Implement the core Tool interface (and FunctionTool implementation) and related types. The Tool interface provides a streaming execution pattern that allows tools to yield progress events during execution before returning a final result. --------- Co-authored-by: Strands Agent <217235299+strands-agent@users.noreply.github.com> Co-authored-by: Mackenzie Zastrow <zastrowm@users.noreply.github.com>
1 parent e9e8b6a commit 4b5b009

9 files changed

Lines changed: 1061 additions & 9 deletions

File tree

.node-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
20.19.0
File renamed without changes.

AGENTS.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,41 @@ export function getData(): any {
232232
- Use TypeScript strict mode features
233233
- Leverage type inference where appropriate
234234

235+
### Class Field Naming Conventions
236+
237+
**Private fields**: Use underscore prefix for private class fields to improve readability and distinguish them from public members.
238+
239+
```typescript
240+
// ✅ Good: Private fields with underscore prefix
241+
export class Example {
242+
private readonly _config: Config
243+
private _state: State
244+
245+
constructor(config: Config) {
246+
this._config = config
247+
this._state = { initialized: false }
248+
}
249+
250+
public getConfig(): Config {
251+
return this._config
252+
}
253+
}
254+
255+
// ❌ Bad: No underscore for private fields
256+
export class Example {
257+
private readonly config: Config // Missing underscore
258+
259+
constructor(config: Config) {
260+
this.config = config
261+
}
262+
}
263+
```
264+
265+
**Rules**:
266+
- Private fields MUST use underscore prefix (e.g., `_field`)
267+
- Public fields MUST NOT use underscore prefix
268+
- This convention improves code readability and makes the distinction between public and private members immediately visible
269+
235270
### Documentation Requirements
236271

237272
**TSDoc format** (required for all exported functions):
@@ -457,6 +492,63 @@ describe('calculateTotal', () => {
457492
})
458493
```
459494

495+
### Object Assertion Best Practices
496+
497+
**Prefer testing entire objects at once** instead of individual properties for better readability and test coverage.
498+
499+
```typescript
500+
// ✅ Good: Verify entire object at once
501+
it('returns expected user object', () => {
502+
const user = getUser('123')
503+
expect(user).toEqual({
504+
id: '123',
505+
name: 'John Doe',
506+
email: 'john@example.com',
507+
isActive: true
508+
})
509+
})
510+
511+
// ✅ Good: Verify entire array of objects
512+
it('yields expected stream events', async () => {
513+
const events = await collectEvents(stream)
514+
expect(events).toEqual([
515+
{ type: 'streamEvent', data: 'Starting...' },
516+
{ type: 'streamEvent', data: 'Processing...' },
517+
{ type: 'streamEvent', data: 'Complete!' },
518+
])
519+
})
520+
521+
// ❌ Bad: Testing individual properties
522+
it('returns expected user object', () => {
523+
const user = getUser('123')
524+
expect(user).toBeDefined()
525+
expect(user.id).toBe('123')
526+
expect(user.name).toBe('John Doe')
527+
expect(user.email).toBe('john@example.com')
528+
expect(user.isActive).toBe(true)
529+
})
530+
531+
// ❌ Bad: Testing array elements individually in a loop
532+
it('yields expected stream events', async () => {
533+
const events = await collectEvents(stream)
534+
for (const event of events) {
535+
expect(event.type).toBe('streamEvent')
536+
expect(event).toHaveProperty('data')
537+
}
538+
})
539+
```
540+
541+
**Benefits of testing entire objects**:
542+
- **More concise**: Single assertion instead of multiple
543+
- **Better test coverage**: Catches unexpected additional or missing properties
544+
- **More readable**: Clear expectation of the entire structure
545+
- **Easier to maintain**: Changes to the object require updating one place
546+
547+
**Use cases**:
548+
- Always use `toEqual()` for object and array comparisons
549+
- Use `toBe()` only for primitive values and reference equality
550+
- When testing error objects, verify the entire structure including message and type
551+
460552
### Testing Guidelines
461553

462554
**Testing Approach:**

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
},
1818
"scripts": {
1919
"build": "tsc",
20+
"check": "npm run lint && npm run format && npm run type-check && npm run test:coverage",
2021
"clean": "rm -rf node_modules dist package-lock.json",
2122
"test": "vitest run --project unit",
2223
"test:watch": "vitest --project unit",

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ export type {
3535
ToolChoice,
3636
} from './tools/types'
3737

38+
// Tool interface and related types
39+
export type { Tool, ToolContext, ToolStreamEvent, ToolStreamGenerator } from './tools/tool'
40+
41+
// FunctionTool implementation
42+
export { FunctionTool } from './tools/function-tool'
43+
3844
// Streaming event types
3945
export type {
4046
Usage,

0 commit comments

Comments
 (0)