Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,16 @@ export default [
files: ['src/**/*.ts'],
tsconfig: './src/tsconfig.json',
}),
// Prevent non-vended-tools from importing vended-tools
noVendedToolsImports({
files: ['src/**/*.ts'],
ignores: ['src/vended-tools/**/*.ts'],
}),
// Then unit-test rules to UTs
unitTestRules({
files: ['src/**/__tests__/**/*.ts'],
tsconfig: './src/tsconfig.json',
}),
// Apply SDK rules to vended_tool files
sdkRules({
files: ['vended_tools/**/*.ts'],
tsconfig: './vended_tools/tsconfig.json',
}),
// Then unit-test rules to UTs
unitTestRules({
files: ['vended_tools/**/__tests__/**/*.ts'],
tsconfig: './vended_tools/tsconfig.json',
}),
// Apply UT rules to the integ tests
unitTestRules({
files: ['tests_integ/**/*.ts'],
Expand Down Expand Up @@ -122,3 +117,24 @@ function integTestRules(options) {
},
}
}

function noVendedToolsImports(options) {
return {
files: options.files,
ignores: options.ignores,
rules: {
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['**/vended-tools', '**/vended-tools/**'],
message:
'Core SDK files should not import from vended-tools. Vended tools are optional and independently importable.',
},
],
},
],
},
}
}
28 changes: 14 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@
"default": "./dist/src/models/bedrock.js"
},
"./vended_tools/notebook": {
"types": "./dist/vended_tools/notebook/index.d.ts",
"default": "./dist/vended_tools/notebook/index.js"
"types": "./dist/src/vended-tools/notebook/index.d.ts",
"default": "./dist/src/vended-tools/notebook/index.js"
},
"./vended_tools/file_editor": {
"types": "./dist/vended_tools/file_editor/index.d.ts",
"default": "./dist/vended_tools/file_editor/index.js"
"types": "./dist/src/vended-tools/file_editor/index.d.ts",
"default": "./dist/src/vended-tools/file_editor/index.js"
},
"./vended_tools/http_request": {
"types": "./dist/vended_tools/http_request/index.d.ts",
"default": "./dist/vended_tools/http_request/index.js"
"types": "./dist/src/vended-tools/http_request/index.d.ts",
"default": "./dist/src/vended-tools/http_request/index.js"
},
"./vended_tools/bash": {
"types": "./dist/vended_tools/bash/index.d.ts",
"default": "./dist/vended_tools/bash/index.js"
"types": "./dist/src/vended-tools/bash/index.d.ts",
"default": "./dist/src/vended-tools/bash/index.js"
}
},
"scripts": {
"build": "tsc --project src/tsconfig.json && tsc --project vended_tools/tsconfig.json",
"build": "tsc --project src/tsconfig.json",
"check": "npm run lint && npm run format && npm run type-check && npm run test:coverage && npm run test:package",
"clean": "rm -rf node_modules dist package-lock.json",
"test": "vitest run --project unit-node",
Expand All @@ -55,11 +55,11 @@
"test:all": "vitest run --project unit-node --project unit-browser",
"test:all:coverage": "vitest run --coverage --project unit-node --project unit-browser",
"test:package": "cd test/packages/esm-module && npm install && node esm.js && cd ../cjs-module && npm install && node cjs.js",
"lint": "eslint src tests_integ vended_tools",
"lint:fix": "eslint src tests_integ vended_tools --fix",
"format": "prettier --write src tests_integ vended_tools",
"format:check": "prettier --check src tests_integ vended_tools",
"type-check": "tsc --noEmit --project src/tsconfig.json && tsc --noEmit --project vended_tools/tsconfig.json && tsc --noEmit --project tests_integ/tsconfig.json",
"lint": "eslint src tests_integ",
"lint:fix": "eslint src tests_integ --fix",
"format": "prettier --write src tests_integ",
"format:check": "prettier --check src tests_integ",
"type-check": "tsc --noEmit --project src/tsconfig.json && tsc --noEmit --project tests_integ/tsconfig.json",
"type-check:watch": "tsc --noEmit --watch",
"prepare": "npm run build && husky"
},
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,16 @@ export type { ToolSpec, ToolUse, ToolResultStatus, ToolChoice } from './tools/ty

// Tool interface and related types
export type {
Tool,
InvokableTool,
ToolContext,
ToolStreamEventData,
ToolStreamEvent,
ToolStreamGenerator,
} from './tools/tool.js'

// Tool base class
export { Tool } from './tools/tool.js'

// FunctionTool implementation
export { FunctionTool } from './tools/function-tool.js'

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { describe, it, expect, vi, afterEach } from 'vitest'
import { bash } from '../index.js'
import { BashTimeoutError, BashSessionError, type BashOutput } from '../index.js'
import type { ToolContext } from '../../../src/index.js'
import { AgentState } from '../../../src/agent/state.js'
import { isNode } from '../../../src/__fixtures__/environment.js'
import type { ToolContext } from '../../../index.js'
import { AgentState } from '../../../agent/state.js'
import { isNode } from '../../../__fixtures__/environment.js'

// Skip all tests if not in Node.js environment
describe.skipIf(!isNode || process.platform === 'win32')('bash tool', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-env node */
import { tool } from '../../src/tools/zod-tool.js'
import { tool } from '../../tools/zod-tool.js'
import { z } from 'zod'
import { spawn, type ChildProcess } from 'child_process'
import { Buffer } from 'buffer'
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { fileEditor } from '../file-editor.js'
import type { ToolContext } from '../../../src/index.js'
import { AgentState } from '../../../src/agent/state.js'
import type { ToolContext } from '../../../index.js'
import { AgentState } from '../../../agent/state.js'
import { promises as fs } from 'fs'
import * as path from 'path'
import { tmpdir } from 'os'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { tool } from '../../src/tools/zod-tool.js'
import { tool } from '../../tools/zod-tool.js'
import { z } from 'zod'
import type { IFileReader } from './types.js'
import { promises as fs } from 'fs'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-env browser, node */
import { tool } from '../../src/tools/zod-tool.js'
import { tool } from '../../tools/zod-tool.js'
import { z } from 'zod'

/**
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { describe, it, expect } from 'vitest'
import { notebook } from '../notebook.js'
import type { NotebookState } from '../types.js'
import type { ToolContext } from '../../../src/index.js'
import { AgentState } from '../../../src/agent/state.js'
import type { ToolContext } from '../../../index.js'
import { AgentState } from '../../../agent/state.js'

describe('notebook tool', () => {
// Helper to create fresh state and context for each test
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { tool } from '../../src/index.js'
import { tool } from '../../index.js'
import { z } from 'zod'
import type { NotebookState } from './types.js'

Expand Down
File renamed without changes.
21 changes: 20 additions & 1 deletion test/packages/cjs-module/cjs.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
* This script runs in a pure Node.js ES module environment.
*/

const { Agent, BedrockModel, tool } = require('@strands-agents/sdk')
const { Agent, BedrockModel, tool, Tool } = require('@strands-agents/sdk')

const { notebook } = require('@strands-agents/sdk/vended_tools/notebook')
const { fileEditor } = require('@strands-agents/sdk/vended_tools/file_editor')
const { httpRequest } = require('@strands-agents/sdk/vended_tools/http_request')
const { bash } = require('@strands-agents/sdk/vended_tools/bash')

const { z } = require('zod')

console.log('✓ Import from main entry point successful')
Expand Down Expand Up @@ -54,6 +60,19 @@ async function main() {
if (agent.tools.length == 0) {
throw new Error('Tool was not correctly added to the agent')
}

const tools = {
notebook,
fileEditor,
httpRequest,
bash,
}

for (const tool of Object.values(tools)) {
if (!(tool instanceof Tool)) {
throw new Error(`Tool ${tool.name} isn't an instance of a tool`)
}
}
}

main().catch((error) => {
Expand Down
47 changes: 46 additions & 1 deletion test/packages/esm-module/esm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
* This script runs in a pure Node.js ES module environment.
*/

import { Agent, BedrockModel, tool } from '@strands-agents/sdk'
import { Agent, BedrockModel, tool, Tool } from '@strands-agents/sdk'

import { notebook } from '@strands-agents/sdk/vended_tools/notebook'
import { fileEditor } from '@strands-agents/sdk/vended_tools/file_editor'
import { httpRequest } from '@strands-agents/sdk/vended_tools/http_request'
import { bash } from '@strands-agents/sdk/vended_tools/bash'

import { z } from 'zod'

console.log('✓ Import from main entry point successful')
Expand Down Expand Up @@ -53,3 +59,42 @@ const agent = new Agent({
if (agent.tools.length == 0) {
throw new Error('Tool was not correctly added to the agent')
}

async function validateScratchpad() {
let context = { agent: agent }
notebook.invoke(
{
mode: 'create',
name: 'scratchpad',
newStr: 'Content',
},
context
)

const result = await notebook.invoke(
{
mode: 'read',
name: 'scratchpad',
},
context
)

if (result !== 'Content') {
throw new Error(`Tool returned invalid response: ${result}`)
}

console.log('Notebook created successful')
}

const tools = {
notebook,
fileEditor,
httpRequest,
bash,
}

for (const tool of Object.values(tools)) {
if (!(tool instanceof Tool)) {
throw new Error(`Tool ${tool.name} isn't an instance of a tool`)
}
}
2 changes: 1 addition & 1 deletion tests_integ/bash.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it, expect } from 'vitest'
import { Agent, BedrockModel } from '$/sdk/index.js'
import { bash } from '../vended_tools/bash/index.js'
import { bash } from '$/sdk/vended-tools/bash/index.js'
import { getMessageText, shouldRunTests } from './__fixtures__/model-test-helpers.js'

describe.skipIf(!(await shouldRunTests()) || process.platform === 'win32')(
Expand Down
2 changes: 1 addition & 1 deletion tests_integ/file-editor.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { Agent, BedrockModel } from '$/sdk/index.js'
import { fileEditor } from '../vended_tools/file_editor/index.js'
import { fileEditor } from '$/sdk/vended-tools/file_editor/index.js'
import { collectGenerator } from '$/sdk/__fixtures__/model-test-helpers.js'
import { shouldRunTests } from './__fixtures__/model-test-helpers.js'
import { promises as fs } from 'fs'
Expand Down
2 changes: 1 addition & 1 deletion tests_integ/notebook.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect } from 'vitest'
import { Agent, BedrockModel } from '$/sdk/index.js'
import type { AgentStreamEvent, AgentResult } from '$/sdk/index.js'
import { notebook } from '../vended_tools/notebook/index.js'
import { notebook } from '$/sdk/vended-tools/notebook/index.js'
import { collectGenerator } from '$/sdk/__fixtures__/model-test-helpers.js'
import { shouldRunTests } from './__fixtures__/model-test-helpers.js'

Expand Down
7 changes: 3 additions & 4 deletions tests_integ/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
"extends": "../tsconfig.base.json",
"compilerOptions": {
"paths": {
"$/sdk/*": ["../src/*"],
"$/vended/*": ["../vended_tools/*"]
"$/sdk/*": ["../src/*"]
},
"types": ["vite/client", "vitest/importMeta"]
"types": ["vite/client", "vitest/importMeta", "@types/node"]
},
"references": [{ "path": "../src/tsconfig.json" }, { "path": "../vended_tools/tsconfig.json" }]
"references": [{ "path": "../src/tsconfig.json" }]
}
7 changes: 0 additions & 7 deletions vended_tools/tsconfig.json

This file was deleted.

16 changes: 8 additions & 8 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))

// Conditionally exclude bash tool from coverage on Windows
// since tests are skipped on Windows (bash not available)
const coverageExclude = ['src/**/__tests__/**', 'src/**/__fixtures__/**', 'vended_tools/**/__tests__/**']
const coverageExclude = ['src/**/__tests__/**', 'src/**/__fixtures__/**', 'src/vended-tools/**/__tests__/**']
if (process.platform === 'win32') {
coverageExclude.push('vended_tools/bash/**')
coverageExclude.push('src/vended-tools/bash/**')
}

const getAwsCredentials: BrowserCommand<[], AwsCredentialIdentity> = async ({ testPath, provider }) => {
Expand All @@ -35,7 +35,7 @@ export default defineConfig({
projects: [
{
test: {
include: ['src/**/__tests__/**/*.test.ts', 'vended_tools/**/__tests__/**/*.test.ts'],
include: ['src/**/__tests__/**/*.test.ts', 'src/vended-tools/**/__tests__/**/*.test.ts'],
includeSource: ['src/**/*.{js,ts}'],
name: { label: 'unit-node', color: 'green' },
typecheck: {
Expand All @@ -47,8 +47,8 @@ export default defineConfig({
},
{
test: {
include: ['src/**/__tests__/**/*.test.ts', 'vended_tools/**/__tests__/**/*.test.ts'],
exclude: ['vended_tools/file_editor/**/*.test.ts', 'vended_tools/bash/**/*.test.ts'],
include: ['src/**/__tests__/**/*.test.ts'],
exclude: ['src/vended-tools/file_editor/**/*.test.ts', 'src/vended-tools/bash/**/*.test.ts'],
name: { label: 'unit-browser', color: 'cyan' },
browser: {
enabled: true,
Expand All @@ -66,7 +66,7 @@ export default defineConfig({
test: {
alias: {
'$/sdk': path.resolve(__dirname, './src'),
'$/vended': path.resolve(__dirname, './vended_tools'),
'$/vended': path.resolve(__dirname, './src/vended-tools'),
},
include: ['tests_integ/**/*.test.ts'],
exclude: ['tests_integ/**/*.browser.test.ts'],
Expand All @@ -83,7 +83,7 @@ export default defineConfig({
test: {
alias: {
'$/sdk': path.resolve(__dirname, './src'),
'$/vended': path.resolve(__dirname, './vended_tools'),
'$/vended': path.resolve(__dirname, './src/vended-tools'),
},
include: ['tests_integ/**/*.browser.test.ts'],
name: { label: 'integ-browser', color: 'yellow' },
Expand Down Expand Up @@ -117,7 +117,7 @@ export default defineConfig({
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
include: ['src/**/*.{ts,js}', 'vended_tools/**/*.{ts,js}'],
include: ['src/**/*.{ts,js}', 'src/vended-tools/**/*.{ts,js}'],
exclude: coverageExclude,
thresholds: {
lines: 80,
Expand Down