From 058078a4c0658834af8047055a9cd6ac088dc3e3 Mon Sep 17 00:00:00 2001 From: Andrew Mikofalvy Date: Wed, 15 Oct 2025 13:43:33 -0700 Subject: [PATCH 1/3] PRD-5208: export type definitions string from agents-sdk --- ...pull.llm-generate.type-definitions.test.ts | 4 +- agents-cli/src/codegen/file-generators.ts | 5 +- agents-cli/src/codegen/unified-generator.ts | 5 +- agents-cli/src/commands/pull.llm-generate.ts | 260 +--------------- .../content/docs/codegen-utilities.mdx | 290 ++++++++++++++++++ agents-docs/navigation.ts | 9 +- .../__tests__/utils/codegen-helpers.test.ts | 170 ++++++++++ packages/agents-sdk/src/index.ts | 7 + .../agents-sdk/src/utils/codegen-helpers.ts | 226 ++++++++++++++ 9 files changed, 714 insertions(+), 262 deletions(-) create mode 100644 agents-docs/content/docs/codegen-utilities.mdx create mode 100644 packages/agents-sdk/src/__tests__/utils/codegen-helpers.test.ts create mode 100644 packages/agents-sdk/src/utils/codegen-helpers.ts diff --git a/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts b/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts index 3fe91eaa6..8f5bbb096 100644 --- a/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts +++ b/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts @@ -48,8 +48,8 @@ describe('getTypeDefinitions', () => { // Set default mock implementations mockJoin.mockImplementation((...args: string[]) => args.join('/')); - // Dynamically import the function after mocks are set up - const module = await import('../../commands/pull.llm-generate.js'); + // Dynamically import the function from SDK after mocks are set up + const module = await import('@inkeep/agents-sdk'); getTypeDefinitions = module.getTypeDefinitions; }); diff --git a/agents-cli/src/codegen/file-generators.ts b/agents-cli/src/codegen/file-generators.ts index 8715fce59..b1f429758 100644 --- a/agents-cli/src/codegen/file-generators.ts +++ b/agents-cli/src/codegen/file-generators.ts @@ -9,12 +9,11 @@ import { writeFileSync } from 'node:fs'; import type { FullAgentDefinition, ModelSettings } from '@inkeep/agents-core'; import { cleanGeneratedCode, - createModel, - generateTextWithPlaceholders, getTypeDefinitions, IMPORT_INSTRUCTIONS, NAMING_CONVENTION_RULES, -} from '../commands/pull.llm-generate'; +} from '@inkeep/agents-sdk'; +import { createModel, generateTextWithPlaceholders } from '../commands/pull.llm-generate'; import type { DetectedPatterns } from './pattern-analyzer'; import type { FileInfo, GenerationPlan } from './plan-builder'; import type { VariableNameRegistry } from './variable-name-registry'; diff --git a/agents-cli/src/codegen/unified-generator.ts b/agents-cli/src/codegen/unified-generator.ts index 0c8f49516..fb231c000 100644 --- a/agents-cli/src/codegen/unified-generator.ts +++ b/agents-cli/src/codegen/unified-generator.ts @@ -9,12 +9,11 @@ import { writeFileSync } from 'node:fs'; import type { FullProjectDefinition, ModelSettings } from '@inkeep/agents-core'; import { cleanGeneratedCode, - createModel, - generateTextWithPlaceholders, getTypeDefinitions, IMPORT_INSTRUCTIONS, NAMING_CONVENTION_RULES, -} from '../commands/pull.llm-generate'; +} from '@inkeep/agents-sdk'; +import { createModel, generateTextWithPlaceholders } from '../commands/pull.llm-generate'; import type { DetectedPatterns } from './pattern-analyzer'; import type { FileInfo, GenerationPlan } from './plan-builder'; diff --git a/agents-cli/src/commands/pull.llm-generate.ts b/agents-cli/src/commands/pull.llm-generate.ts index b521a4327..f492d3208 100644 --- a/agents-cli/src/commands/pull.llm-generate.ts +++ b/agents-cli/src/commands/pull.llm-generate.ts @@ -1,10 +1,15 @@ -import { readFileSync, writeFileSync } from 'node:fs'; -import { createRequire } from 'node:module'; +import { writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { anthropic, createAnthropic } from '@ai-sdk/anthropic'; import { createOpenAI, openai } from '@ai-sdk/openai'; import type { FullAgentDefinition, ModelSettings } from '@inkeep/agents-core'; -import { ANTHROPIC_MODELS, GOOGLE_MODELS, OPENAI_MODELS } from '@inkeep/agents-core'; +import { + cleanGeneratedCode, + getTypeDefinitions, + IMPORT_INSTRUCTIONS, + NAMING_CONVENTION_RULES, + PROJECT_JSON_EXAMPLE, +} from '@inkeep/agents-sdk'; import { generateText } from 'ai'; import { calculateTokenSavings, @@ -12,46 +17,6 @@ import { restorePlaceholders, } from './pull.placeholder-system'; -// Create require function for ESM context -const require = createRequire(import.meta.url); - -/** - * Read the complete type definitions from @inkeep/agents-sdk package - * This provides the LLM with full type context for generating code - * @internal - Exported for testing purposes - */ -export function getTypeDefinitions(): string { - try { - // Resolve package from node_modules using require.resolve - // This mirrors TypeScript's actual module resolution and works in: - // - Monorepo workspaces (resolves to workspace package) - // - Published packages (resolves to node_modules) - // - Different environments (no hardcoded relative paths) - const sdkPackagePath = require.resolve('@inkeep/agents-sdk/package.json'); - const sdkPackageDir = join(sdkPackagePath, '..'); - const sdkDtsPath = join(sdkPackageDir, 'dist/index.d.ts'); - - // Read the entire declaration file - let the LLM see all available types - const dtsContent = readFileSync(sdkDtsPath, 'utf-8'); - - return ` -TYPESCRIPT TYPE DEFINITIONS (from @inkeep/agents-sdk): - -The following is the complete type definition file from '@inkeep/agents-sdk'. - ----START OF TYPE DEFINITIONS--- -${dtsContent} ----END OF TYPE DEFINITIONS--- -`; - } catch (error) { - // Fallback to comment if extraction fails - console.warn('Could not read type definitions:', error); - return ` -// Type definitions from @inkeep/agents-sdk could not be loaded. -`; - } -} - /** * Create a language model instance from configuration * Similar to ModelFactory but simplified for CLI use @@ -87,215 +52,6 @@ export function createModel(config: ModelSettings): any { } } -const PROJECT_JSON_EXAMPLE = ` ----START OF PROJECT JSON EXAMPLE--- -{ - "id": "my-project", - "name": "My Project", - "description": "test test", - "models": { - "base": { - "model": "${ANTHROPIC_MODELS.CLAUDE_OPUS_4_1_20250805}", - "providerOptions": { - "temperature": 0.7, - "maxTokens": 2096 - } - }, - "structuredOutput": { - "model": "${OPENAI_MODELS.GPT_4_1_MINI_20250414}", - "providerOptions": { - "temperature": 0.4, - "maxTokens": 2048 - } - }, - "summarizer": { - "model": "${OPENAI_MODELS.GPT_5_NANO_20250807}", - "providerOptions": { - "temperature": 0.8, - "maxTokens": 1024 - } - } - }, - "stopWhen": { - "transferCountIs": 10, - "stepCountIs": 24 - }, - "agent": { - "customer-service": { - "id": "customer-service", - "name": "customer-service", - "description": "respond to customer service requests", - "defaultSubAgentId": "router", - "subAgents": { - "refund-agent": { - "id": "refund-agent", - "name": "Refund Agent", - "description": "This agent is responsible for refunding customer orders", - "prompt": "Refund customer orders based on the following criteria:\n- Order is under $100\n- Order was placed in the last 30 days\n- Customer has no other refunds in the last 30 days", - "models": { - "base": { - "model": "${GOOGLE_MODELS.GEMINI_2_5_FLASH}" - } - }, - "stopWhen": { - "stepCountIs": 24 - }, - "canTransferTo": ["router"], - "canDelegateTo": [], - "dataComponents": [], - "artifactComponents": [], - "canUse": [] - }, - "router": { - "id": "router", - "name": "Router", - "description": "Routing incoming requests", - "prompt": "You route incoming requests to the correect agent", - "models": null, - "stopWhen": { - "stepCountIs": 24 - }, - "canTransferTo": ["refund-agent"], - "canDelegateTo": [], - "dataComponents": [], - "artifactComponents": [], - "canUse": [] - } - }, - "createdAt": "2025-10-05T16:40:22.655Z", - "updatedAt": "2025-10-05T16:43:26.813Z", - "models": { - "base": { - "model": "${ANTHROPIC_MODELS.CLAUDE_SONNET_4_20250514}", - "providerOptions": { - "temperature": 0.5 - } - } - }, - "statusUpdates": { - "numEvents": 10, - "timeInSeconds": 13 - }, - "stopWhen": { - "transferCountIs": 5 - } - } - }, - "tools": {}, - "dataComponents": { - "listorders": { - "id": "listorders", - "name": "ListOrders", - "description": "Display a list of customer orders", - "props": { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "type": "object", - "description": "An object containing a list of orders.", - "properties": { - "orders": { - "type": "array", - "description": "A list of order objects.", - "items": { - "type": "object", - "description": "An individual order with identifying and creation details.", - "properties": { - "id": { - "type": "string", - "description": "Unique identifier for the order." - }, - "name": { - "type": "string", - "description": "Human-readable name or label for the order." - }, - "createdAt": { - "type": "string", - "format": "date-time", - "description": "Timestamp when the order was created, in ISO 8601 format." - } - }, - "required": ["id", "name", "createdAt"] - } - } - }, - "required": ["orders"] - } - } - }, - "artifactComponents": {}, - "credentialReferences": {}, - "createdAt": "2025-10-05T16:25:10.238Z", - "updatedAt": "2025-10-05T16:27:27.777Z" -} ----END OF PROJECT JSON EXAMPLE--- -`; - -/** - * Reusable naming convention rules for all LLM generation functions - * @internal - Exported for use in codegen modules - */ -export const NAMING_CONVENTION_RULES = ` -CRITICAL NAMING CONVENTION RULES (Apply to ALL imports/exports): -- File names ALWAYS use the exact original ID. IDs are made of file safe characters (e.g., '../tools/inkeep_facts', '../data-components/user-profile') -- Name of consts and variables, especially ones that are exported ones, MUST be camelCase versions of the ID, unless the ID is random/UUID then take it verbatim. -- Conversion rules for import/export names: - - IDs with underscores: 'inkeep_facts' → inkeepFacts - - IDs with hyphens: 'weather-api' → weatherApi - - IDs with both: 'my_weather-api' → myWeatherApi - - Random/UUID IDs: Keep as-is (e.g., 'fUI2riwrBVJ6MepT8rjx0' → fUI2riwrBVJ6MepT8rjx0) - - IDs starting with uppercase: Make first letter lowercase unless it's an acronym or random or UUID -- The ID field in the exported object keeps the original format -- Examples: - - Tool: import { inkeepFacts } from '../tools/inkeep_facts'; export const inkeepFacts = mcpTool({ id: 'inkeep_facts', ... }) - - Component: import { userProfile } from '../data-components/user-profile'; export const userProfile = dataComponent({ id: 'user-profile', ... }) - - Agent: import { myAgent } from './agent/my-agent'; export const myAgent = agent({ id: 'my-agent', ... }) -`; - -/** - * Import instruction rules for LLM generation - * @internal - Exported for use in codegen modules - */ -export const IMPORT_INSTRUCTIONS = ` -CRITICAL: All imports MUST be alphabetically sorted (both named imports and path names) - -CRITICAL IMPORT PATTERNS: -- Tools: Import from '../tools/{toolId}' (individual files) -- Data components: Import from '../data-components/{componentId}' (individual files) -- Artifact components: Import from '../artifact-components/{componentId}' (individual files) -- Agent: Import from './agent/{agentId}' (individual files) - -NEVER use barrel imports from directories: -❌ WRONG: import { ordersList, refundApproval } from '../data-components'; -✅ CORRECT: - import { ordersList } from '../data-components/orders-list'; - import { refundApproval } from '../data-components/refund-approval'; - -EXAMPLES: -// Multiple data components - each from individual file: -import { ordersList } from '../data-components/orders-list'; -import { refundApproval } from '../data-components/refund-approval'; - -// Tools - each from individual file: -import { inkeepFacts } from '../tools/inkeep_facts'; -import { weatherApi } from '../tools/weather-api'; - -// Agent - each from individual file: -import { inkeepQaAgent } from './agent/inkeep-qa-agent'; -import { weatherAgent } from './agent/weather-agent'; -`; - -/** - * Clean generated text by removing markdown code fences - * @internal - Exported for use in codegen modules - */ -export function cleanGeneratedCode(text: string): string { - // Remove opening and closing markdown code fences - // Handles ```typescript, ```ts, or just ``` - return text - .replace(/^```(?:typescript|ts)?\n?/, '') - .replace(/\n?```$/, '') - .trim(); -} - /** * Enhanced generateText wrapper with placeholder support * diff --git a/agents-docs/content/docs/codegen-utilities.mdx b/agents-docs/content/docs/codegen-utilities.mdx new file mode 100644 index 000000000..fe4f38503 --- /dev/null +++ b/agents-docs/content/docs/codegen-utilities.mdx @@ -0,0 +1,290 @@ +--- +title: Code generation utilities +sidebarTitle: Codegen utilities +description: Utilities for LLM-based code generation and TypeScript file creation +keywords: code generation, LLM, TypeScript, utilities, SDK, codegen helpers +--- + +The Agents SDK provides utilities for LLM-based code generation, particularly useful for creating TypeScript files from project definitions. + +## Overview + +These utilities are used internally by the CLI's `pull` command but are exported from the SDK for use in custom code generation tools and workflows. + +## Available utilities + +### Constants + +#### `NAMING_CONVENTION_RULES` + +A comprehensive guide for naming conventions when generating TypeScript code from agent definitions. + +```typescript +import { NAMING_CONVENTION_RULES } from '@inkeep/agents-sdk'; + +// Use in LLM prompts to ensure consistent naming +const prompt = `Generate TypeScript code following these rules: +${NAMING_CONVENTION_RULES}`; +``` + +**Key rules:** +- File names use the original ID exactly +- Exported variable names use camelCase versions of IDs +- Handles underscores (`inkeep_facts` → `inkeepFacts`) +- Handles hyphens (`weather-api` → `weatherApi`) +- Preserves random/UUID IDs as-is +- ID field in objects keeps original format + +#### `IMPORT_INSTRUCTIONS` + +Guidelines for import patterns and organization in generated TypeScript files. + +```typescript +import { IMPORT_INSTRUCTIONS } from '@inkeep/agents-sdk'; + +// Use in LLM prompts to ensure correct import patterns +const prompt = `Generate imports following these patterns: +${IMPORT_INSTRUCTIONS}`; +``` + +**Key patterns:** +- Tools: `import { toolName } from '../tools/{toolId}'` +- Data components: `import { componentName } from '../data-components/{componentId}'` +- Artifact components: `import { componentName } from '../artifact-components/{componentId}'` +- Agents: `import { agentName } from './agent/{agentId}'` +- All imports must be alphabetically sorted +- Never use barrel imports from directories + +#### `PROJECT_JSON_EXAMPLE` + +A complete example of a project JSON structure, useful for providing context to LLMs when generating project code. + +```typescript +import { PROJECT_JSON_EXAMPLE } from '@inkeep/agents-sdk'; + +// Use in LLM prompts to provide structural examples +const prompt = `Generate a project following this example: +${PROJECT_JSON_EXAMPLE}`; +``` + +### Functions + +#### `cleanGeneratedCode(text: string): string` + +Removes markdown code fences from LLM-generated code. + +```typescript +import { cleanGeneratedCode } from '@inkeep/agents-sdk'; + +const rawLLMOutput = `\`\`\`typescript +export const myAgent = agent({ + id: 'my-agent', + name: 'My Agent' +}); +\`\`\``; + +const cleanCode = cleanGeneratedCode(rawLLMOutput); +// Result: "export const myAgent = agent({\n id: 'my-agent',\n name: 'My Agent'\n});" +``` + +**Features:** +- Removes opening code fences (`\`\`\`typescript`, `\`\`\`ts`, `\`\`\``) +- Removes closing code fences (`\`\`\``) +- Trims whitespace +- Preserves internal code structure + +#### `getTypeDefinitions(): string` + +Reads and formats the complete TypeScript type definitions from the Agents SDK package. + +```typescript +import { getTypeDefinitions } from '@inkeep/agents-sdk'; + +// Use in LLM prompts to provide full type context +const typeInfo = getTypeDefinitions(); +const prompt = `Generate TypeScript code using these types: +${typeInfo}`; +``` + +**Features:** +- Automatically resolves SDK package location +- Reads from `dist/index.d.ts` +- Formats with clear boundaries for LLM parsing +- Provides fallback message if types can't be loaded +- Works in monorepos and published packages + +## Usage examples + +### Basic code generation workflow + +```typescript +import { + cleanGeneratedCode, + getTypeDefinitions, + NAMING_CONVENTION_RULES, + IMPORT_INSTRUCTIONS, + PROJECT_JSON_EXAMPLE, +} from '@inkeep/agents-sdk'; +import { generateText } from 'ai'; +import { anthropic } from '@ai-sdk/anthropic'; + +async function generateAgentFile(agentData: any, outputPath: string) { + // Construct comprehensive prompt with utilities + const prompt = `Generate a TypeScript file for an Inkeep agent. + +AGENT DATA: +${JSON.stringify(agentData, null, 2)} + +${getTypeDefinitions()} + +${NAMING_CONVENTION_RULES} + +${IMPORT_INSTRUCTIONS} + +EXAMPLE: +${PROJECT_JSON_EXAMPLE} + +Generate ONLY the TypeScript code without markdown formatting.`; + + // Generate code with LLM + const { text } = await generateText({ + model: anthropic('claude-sonnet-4-20250514'), + prompt, + temperature: 0.1, + }); + + // Clean and save the generated code + const cleanCode = cleanGeneratedCode(text); + await fs.writeFile(outputPath, cleanCode); +} +``` + +### Custom naming convention enforcement + +```typescript +import { NAMING_CONVENTION_RULES } from '@inkeep/agents-sdk'; + +function validateGeneratedCode(code: string, originalId: string): boolean { + // Extract the exported name from code + const exportMatch = code.match(/export const (\w+) =/); + if (!exportMatch) return false; + + const exportedName = exportMatch[1]; + + // Check if it follows naming conventions + const expectedName = convertIdToVariableName(originalId); + + return exportedName === expectedName; +} + +function convertIdToVariableName(id: string): string { + // Implement naming rules from NAMING_CONVENTION_RULES + return id + .replace(/[-_]/g, ' ') + .split(' ') + .map((word, index) => + index === 0 + ? word.charAt(0).toLowerCase() + word.slice(1) + : word.charAt(0).toUpperCase() + word.slice(1) + ) + .join(''); +} +``` + +### Building comprehensive prompts + +```typescript +import { + getTypeDefinitions, + NAMING_CONVENTION_RULES, + IMPORT_INSTRUCTIONS, +} from '@inkeep/agents-sdk'; + +function createToolGenerationPrompt(toolData: any) { + return `Generate a TypeScript file for an Inkeep tool. + +TOOL DATA: +${JSON.stringify(toolData, null, 2)} + +TYPE DEFINITIONS: +${getTypeDefinitions()} + +NAMING CONVENTIONS: +${NAMING_CONVENTION_RULES} + +IMPORT PATTERNS: +${IMPORT_INSTRUCTIONS} + +REQUIREMENTS: +1. Import mcpTool from '@inkeep/agents-sdk' +2. Use proper naming conventions for exports +3. Follow import patterns for dependencies +4. Generate clean, well-formatted TypeScript + +Generate ONLY the TypeScript code.`; +} +``` + +## Best practices + +### Using with LLMs + +1. **Provide full context**: Include type definitions, naming rules, and examples in your prompts +2. **Be specific**: Combine multiple utilities to create comprehensive prompts +3. **Clean output**: Always use `cleanGeneratedCode` to remove markdown artifacts +4. **Validate**: Check generated code against naming conventions + +### Error handling + +```typescript +import { getTypeDefinitions } from '@inkeep/agents-sdk'; + +function safeGetTypeDefinitions(): string { + try { + return getTypeDefinitions(); + } catch (error) { + console.warn('Failed to load type definitions:', error); + // Provide minimal fallback + return '// Type definitions not available'; + } +} +``` + +### Temperature settings + +For code generation, use low temperature values for consistency: + +```typescript +const { text } = await generateText({ + model: model, + prompt: prompt, + temperature: 0.1, // Low temperature for consistent code generation + maxOutputTokens: 4000, +}); +``` + +## Integration with CLI + +These utilities are used internally by the `inkeep pull` command to generate TypeScript files from cloud-based agent definitions. You can use them to build similar code generation workflows. + +## Type safety + +All utilities maintain TypeScript type safety: + +```typescript +// Type-safe usage +const typeDefinitions: string = getTypeDefinitions(); +const cleanCode: string = cleanGeneratedCode(rawCode); + +// Constants are strongly typed +const rules: string = NAMING_CONVENTION_RULES; +const instructions: string = IMPORT_INSTRUCTIONS; +const example: string = PROJECT_JSON_EXAMPLE; +``` + +## See also + +- [CLI pull command](/cli-pull) - Uses these utilities for code generation +- [Project structure](/project-structure) - Understanding generated file organization +- [Agent configuration](/agents/configuration) - Details on agent definitions + diff --git a/agents-docs/navigation.ts b/agents-docs/navigation.ts index 5494c2e26..c9420728d 100644 --- a/agents-docs/navigation.ts +++ b/agents-docs/navigation.ts @@ -6,7 +6,12 @@ export default { { group: 'Get Started', icon: 'LuZap', - pages: ['get-started/quick-start', 'get-started/push-pull', 'get-started/traces', 'get-started/credentials'], + pages: [ + 'get-started/quick-start', + 'get-started/push-pull', + 'get-started/traces', + 'get-started/credentials', + ], }, 'concepts', ], @@ -49,6 +54,7 @@ export default { 'typescript-sdk/environments', 'typescript-sdk/push-pull-workflows', 'typescript-sdk/cli-reference', + 'codegen-utilities', ], }, 'typescript-sdk/data-operations', @@ -103,7 +109,6 @@ export default { 'talk-to-your-agents/react/custom-trigger', 'talk-to-your-agents/react/side-bar-chat', 'talk-to-your-agents/react/embedded-chat', - ], }, { diff --git a/packages/agents-sdk/src/__tests__/utils/codegen-helpers.test.ts b/packages/agents-sdk/src/__tests__/utils/codegen-helpers.test.ts new file mode 100644 index 000000000..d2e7acee7 --- /dev/null +++ b/packages/agents-sdk/src/__tests__/utils/codegen-helpers.test.ts @@ -0,0 +1,170 @@ +import { describe, expect, it } from 'vitest'; +import { + cleanGeneratedCode, + getTypeDefinitions, + IMPORT_INSTRUCTIONS, + NAMING_CONVENTION_RULES, + PROJECT_JSON_EXAMPLE, +} from '../../utils/codegen-helpers'; + +describe('codegen-helpers', () => { + describe('NAMING_CONVENTION_RULES', () => { + it('should be a non-empty string', () => { + expect(typeof NAMING_CONVENTION_RULES).toBe('string'); + expect(NAMING_CONVENTION_RULES.length).toBeGreaterThan(0); + }); + + it('should contain key naming patterns', () => { + expect(NAMING_CONVENTION_RULES).toContain('camelCase'); + expect(NAMING_CONVENTION_RULES).toContain('inkeep_facts'); + expect(NAMING_CONVENTION_RULES).toContain('inkeepFacts'); + expect(NAMING_CONVENTION_RULES).toContain('weather-api'); + expect(NAMING_CONVENTION_RULES).toContain('weatherApi'); + }); + + it('should include examples for different resource types', () => { + expect(NAMING_CONVENTION_RULES).toContain('Tool:'); + expect(NAMING_CONVENTION_RULES).toContain('Component:'); + expect(NAMING_CONVENTION_RULES).toContain('Agent:'); + }); + }); + + describe('IMPORT_INSTRUCTIONS', () => { + it('should be a non-empty string', () => { + expect(typeof IMPORT_INSTRUCTIONS).toBe('string'); + expect(IMPORT_INSTRUCTIONS.length).toBeGreaterThan(0); + }); + + it('should contain import path patterns', () => { + expect(IMPORT_INSTRUCTIONS).toContain('../tools/'); + expect(IMPORT_INSTRUCTIONS).toContain('../data-components/'); + expect(IMPORT_INSTRUCTIONS).toContain('../artifact-components/'); + expect(IMPORT_INSTRUCTIONS).toContain('./agent/'); + }); + + it('should warn against barrel imports', () => { + expect(IMPORT_INSTRUCTIONS).toContain('NEVER use barrel imports'); + expect(IMPORT_INSTRUCTIONS).toContain('❌ WRONG:'); + expect(IMPORT_INSTRUCTIONS).toContain('✅ CORRECT:'); + }); + + it('should mention alphabetical sorting', () => { + expect(IMPORT_INSTRUCTIONS).toContain('alphabetically sorted'); + }); + }); + + describe('PROJECT_JSON_EXAMPLE', () => { + it('should be a non-empty string', () => { + expect(typeof PROJECT_JSON_EXAMPLE).toBe('string'); + expect(PROJECT_JSON_EXAMPLE.length).toBeGreaterThan(0); + }); + + it('should contain valid JSON structure markers', () => { + expect(PROJECT_JSON_EXAMPLE).toContain('---START OF PROJECT JSON EXAMPLE---'); + expect(PROJECT_JSON_EXAMPLE).toContain('---END OF PROJECT JSON EXAMPLE---'); + }); + + it('should include key project properties', () => { + expect(PROJECT_JSON_EXAMPLE).toContain('"id"'); + expect(PROJECT_JSON_EXAMPLE).toContain('"name"'); + expect(PROJECT_JSON_EXAMPLE).toContain('"models"'); + expect(PROJECT_JSON_EXAMPLE).toContain('"agent"'); + }); + + it('should include model examples', () => { + expect(PROJECT_JSON_EXAMPLE).toContain('base'); + expect(PROJECT_JSON_EXAMPLE).toContain('structuredOutput'); + expect(PROJECT_JSON_EXAMPLE).toContain('summarizer'); + }); + + it('should include component examples', () => { + expect(PROJECT_JSON_EXAMPLE).toContain('dataComponents'); + expect(PROJECT_JSON_EXAMPLE).toContain('tools'); + expect(PROJECT_JSON_EXAMPLE).toContain('artifactComponents'); + }); + }); + + describe('cleanGeneratedCode', () => { + it('should remove typescript markdown code fences', () => { + const input = '```typescript\nconst x = 1;\n```'; + const expected = 'const x = 1;'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should remove ts markdown code fences', () => { + const input = '```ts\nconst x = 1;\n```'; + const expected = 'const x = 1;'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should remove plain markdown code fences', () => { + const input = '```\nconst x = 1;\n```'; + const expected = 'const x = 1;'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should trim whitespace', () => { + const input = '\n\n const x = 1; \n\n'; + const expected = 'const x = 1;'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should handle code without fences', () => { + const input = 'const x = 1;'; + const expected = 'const x = 1;'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should handle multi-line code', () => { + const input = `\`\`\`typescript +const x = 1; +const y = 2; +const z = x + y; +\`\`\``; + const expected = `const x = 1; +const y = 2; +const z = x + y;`; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + + it('should handle code with markdown fence but no language', () => { + const input = '```\nimport { agent } from "@inkeep/agents-sdk";\n```'; + const expected = 'import { agent } from "@inkeep/agents-sdk";'; + expect(cleanGeneratedCode(input)).toBe(expected); + }); + }); + + describe('getTypeDefinitions', () => { + it('should return a non-empty string', () => { + const result = getTypeDefinitions(); + expect(typeof result).toBe('string'); + expect(result.length).toBeGreaterThan(0); + }); + + it('should contain type definition markers', () => { + const result = getTypeDefinitions(); + expect(result).toContain('TYPESCRIPT TYPE DEFINITIONS'); + expect(result).toContain('@inkeep/agents-sdk'); + }); + + it('should contain type definition boundaries or fallback', () => { + const result = getTypeDefinitions(); + const hasTypeDefinitions = + result.includes('---START OF TYPE DEFINITIONS---') && + result.includes('---END OF TYPE DEFINITIONS---'); + const hasFallback = result.includes( + 'Type definitions from @inkeep/agents-sdk could not be loaded' + ); + + expect(hasTypeDefinitions || hasFallback).toBe(true); + }); + + it('should attempt to load actual type definitions in normal conditions', () => { + const result = getTypeDefinitions(); + + if (result.includes('---START OF TYPE DEFINITIONS---')) { + expect(result).toContain('---END OF TYPE DEFINITIONS---'); + } + }); + }); +}); diff --git a/packages/agents-sdk/src/index.ts b/packages/agents-sdk/src/index.ts index 886f15b57..bbd9369a7 100644 --- a/packages/agents-sdk/src/index.ts +++ b/packages/agents-sdk/src/index.ts @@ -44,3 +44,10 @@ export { StatusComponent, type StatusComponentInterface } from './status-compone export { SubAgent } from './subAgent'; export { Tool } from './tool'; export type * from './types'; +export { + cleanGeneratedCode, + getTypeDefinitions, + IMPORT_INSTRUCTIONS, + NAMING_CONVENTION_RULES, + PROJECT_JSON_EXAMPLE, +} from './utils/codegen-helpers'; diff --git a/packages/agents-sdk/src/utils/codegen-helpers.ts b/packages/agents-sdk/src/utils/codegen-helpers.ts new file mode 100644 index 000000000..e4243999f --- /dev/null +++ b/packages/agents-sdk/src/utils/codegen-helpers.ts @@ -0,0 +1,226 @@ +import { readFileSync } from 'node:fs'; +import { createRequire } from 'node:module'; +import { join } from 'node:path'; +import { ANTHROPIC_MODELS, GOOGLE_MODELS, OPENAI_MODELS } from '@inkeep/agents-core'; + +const require = createRequire(import.meta.url); + +export const NAMING_CONVENTION_RULES = ` +CRITICAL NAMING CONVENTION RULES (Apply to ALL imports/exports): +- File names ALWAYS use the exact original ID. IDs are made of file safe characters (e.g., '../tools/inkeep_facts', '../data-components/user-profile') +- Name of consts and variables, especially ones that are exported ones, MUST be camelCase versions of the ID, unless the ID is random/UUID then take it verbatim. +- Conversion rules for import/export names: + - IDs with underscores: 'inkeep_facts' → inkeepFacts + - IDs with hyphens: 'weather-api' → weatherApi + - IDs with both: 'my_weather-api' → myWeatherApi + - Random/UUID IDs: Keep as-is (e.g., 'fUI2riwrBVJ6MepT8rjx0' → fUI2riwrBVJ6MepT8rjx0) + - IDs starting with uppercase: Make first letter lowercase unless it's an acronym or random or UUID +- The ID field in the exported object keeps the original format +- Examples: + - Tool: import { inkeepFacts } from '../tools/inkeep_facts'; export const inkeepFacts = mcpTool({ id: 'inkeep_facts', ... }) + - Component: import { userProfile } from '../data-components/user-profile'; export const userProfile = dataComponent({ id: 'user-profile', ... }) + - Agent: import { myAgent } from './agent/my-agent'; export const myAgent = agent({ id: 'my-agent', ... }) +`; + +export const IMPORT_INSTRUCTIONS = ` +CRITICAL: All imports MUST be alphabetically sorted (both named imports and path names) + +CRITICAL IMPORT PATTERNS: +- Tools: Import from '../tools/{toolId}' (individual files) +- Data components: Import from '../data-components/{componentId}' (individual files) +- Artifact components: Import from '../artifact-components/{componentId}' (individual files) +- Agent: Import from './agent/{agentId}' (individual files) + +NEVER use barrel imports from directories: +❌ WRONG: import { ordersList, refundApproval } from '../data-components'; +✅ CORRECT: + import { ordersList } from '../data-components/orders-list'; + import { refundApproval } from '../data-components/refund-approval'; + +EXAMPLES: +// Multiple data components - each from individual file: +import { ordersList } from '../data-components/orders-list'; +import { refundApproval } from '../data-components/refund-approval'; + +// Tools - each from individual file: +import { inkeepFacts } from '../tools/inkeep_facts'; +import { weatherApi } from '../tools/weather-api'; + +// Agent - each from individual file: +import { inkeepQaAgent } from './agent/inkeep-qa-agent'; +import { weatherAgent } from './agent/weather-agent'; +`; + +export const PROJECT_JSON_EXAMPLE = ` +---START OF PROJECT JSON EXAMPLE--- +{ + "id": "my-project", + "name": "My Project", + "description": "test test", + "models": { + "base": { + "model": "${ANTHROPIC_MODELS.CLAUDE_OPUS_4_1_20250805}", + "providerOptions": { + "temperature": 0.7, + "maxTokens": 2096 + } + }, + "structuredOutput": { + "model": "${OPENAI_MODELS.GPT_4_1_MINI_20250414}", + "providerOptions": { + "temperature": 0.4, + "maxTokens": 2048 + } + }, + "summarizer": { + "model": "${OPENAI_MODELS.GPT_5_NANO_20250807}", + "providerOptions": { + "temperature": 0.8, + "maxTokens": 1024 + } + } + }, + "stopWhen": { + "transferCountIs": 10, + "stepCountIs": 24 + }, + "agent": { + "customer-service": { + "id": "customer-service", + "name": "customer-service", + "description": "respond to customer service requests", + "defaultSubAgentId": "router", + "subAgents": { + "refund-agent": { + "id": "refund-agent", + "name": "Refund Agent", + "description": "This agent is responsible for refunding customer orders", + "prompt": "Refund customer orders based on the following criteria:\n- Order is under $100\n- Order was placed in the last 30 days\n- Customer has no other refunds in the last 30 days", + "models": { + "base": { + "model": "${GOOGLE_MODELS.GEMINI_2_5_FLASH}" + } + }, + "stopWhen": { + "stepCountIs": 24 + }, + "canTransferTo": ["router"], + "canDelegateTo": [], + "dataComponents": [], + "artifactComponents": [], + "canUse": [] + }, + "router": { + "id": "router", + "name": "Router", + "description": "Routing incoming requests", + "prompt": "You route incoming requests to the correect agent", + "models": null, + "stopWhen": { + "stepCountIs": 24 + }, + "canTransferTo": ["refund-agent"], + "canDelegateTo": [], + "dataComponents": [], + "artifactComponents": [], + "canUse": [] + } + }, + "createdAt": "2025-10-05T16:40:22.655Z", + "updatedAt": "2025-10-05T16:43:26.813Z", + "models": { + "base": { + "model": "${ANTHROPIC_MODELS.CLAUDE_SONNET_4_20250514}", + "providerOptions": { + "temperature": 0.5 + } + } + }, + "statusUpdates": { + "numEvents": 10, + "timeInSeconds": 13 + }, + "stopWhen": { + "transferCountIs": 5 + } + } + }, + "tools": {}, + "dataComponents": { + "listorders": { + "id": "listorders", + "name": "ListOrders", + "description": "Display a list of customer orders", + "props": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "description": "An object containing a list of orders.", + "properties": { + "orders": { + "type": "array", + "description": "A list of order objects.", + "items": { + "type": "object", + "description": "An individual order with identifying and creation details.", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the order." + }, + "name": { + "type": "string", + "description": "Human-readable name or label for the order." + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "Timestamp when the order was created, in ISO 8601 format." + } + }, + "required": ["id", "name", "createdAt"] + } + } + }, + "required": ["orders"] + } + } + }, + "artifactComponents": {}, + "credentialReferences": {}, + "createdAt": "2025-10-05T16:25:10.238Z", + "updatedAt": "2025-10-05T16:27:27.777Z" +} +---END OF PROJECT JSON EXAMPLE--- +`; + +export function cleanGeneratedCode(text: string): string { + return text + .replace(/^```(?:typescript|ts)?\n?/, '') + .replace(/\n?```$/, '') + .trim(); +} + +export function getTypeDefinitions(): string { + try { + const sdkPackagePath = require.resolve('@inkeep/agents-sdk/package.json'); + const sdkPackageDir = join(sdkPackagePath, '..'); + const sdkDtsPath = join(sdkPackageDir, 'dist/index.d.ts'); + + const dtsContent = readFileSync(sdkDtsPath, 'utf-8'); + + return ` +TYPESCRIPT TYPE DEFINITIONS (from @inkeep/agents-sdk): + +The following is the complete type definition file from '@inkeep/agents-sdk'. + +---START OF TYPE DEFINITIONS--- +${dtsContent} +---END OF TYPE DEFINITIONS--- +`; + } catch (error) { + console.warn('Could not read type definitions:', error); + return ` +// Type definitions from @inkeep/agents-sdk could not be loaded. +`; + } +} From 727000e87d6a6a7d99f20ff91822cbafdf65eb00 Mon Sep 17 00:00:00 2001 From: Andrew Mikofalvy Date: Wed, 15 Oct 2025 13:44:32 -0700 Subject: [PATCH 2/3] moved type definition tests --- .../codegen-helpers-type-definitions.test.ts | 96 +------------------ 1 file changed, 3 insertions(+), 93 deletions(-) rename agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts => packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts (69%) diff --git a/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts b/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts similarity index 69% rename from agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts rename to packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts index 8f5bbb096..1f7cbb122 100644 --- a/agents-cli/src/__tests__/commands/pull.llm-generate.type-definitions.test.ts +++ b/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts @@ -2,7 +2,6 @@ import { readFileSync } from 'node:fs'; import { join } from 'node:path'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -// Mock modules before importing vi.mock('node:fs', async (importOriginal) => { const actual = await importOriginal(); return { @@ -42,14 +41,12 @@ describe('getTypeDefinitions', () => { beforeEach(async () => { vi.clearAllMocks(); - vi.resetModules(); // Reset modules to ensure fresh import + vi.resetModules(); consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); - // Set default mock implementations mockJoin.mockImplementation((...args: string[]) => args.join('/')); - // Dynamically import the function from SDK after mocks are set up - const module = await import('@inkeep/agents-sdk'); + const module = await import('../../utils/codegen-helpers'); getTypeDefinitions = module.getTypeDefinitions; }); @@ -75,13 +72,10 @@ export interface ModelSettings { export declare function project(config: ProjectConfig): Project; export declare function agent(config: AgentConfig): Agent;`; - // Mock readFileSync to return the mock DTS content mockReadFileSync.mockReturnValue(mockDtsContent); - // Call the function (it will use the real require.resolve but read our mocked file) const result = getTypeDefinitions(); - // Verify the output format expect(result).toContain('TYPESCRIPT TYPE DEFINITIONS (from @inkeep/agents-sdk):'); expect(result).toContain('---START OF TYPE DEFINITIONS---'); expect(result).toContain('---END OF TYPE DEFINITIONS---'); @@ -89,7 +83,6 @@ export declare function agent(config: AgentConfig): Agent;`; expect(result).toContain('export interface AgentConfig'); expect(result).toContain('export interface ModelSettings'); - // Verify readFileSync was called expect(mockReadFileSync).toHaveBeenCalled(); }); @@ -100,14 +93,12 @@ export declare function agent(config: AgentConfig): Agent;`; const result = getTypeDefinitions(); - // Verify the format includes all required markers expect(result).toContain('TYPESCRIPT TYPE DEFINITIONS (from @inkeep/agents-sdk):'); expect(result).toContain('The following is the complete type definition file'); expect(result).toContain('---START OF TYPE DEFINITIONS---'); expect(result).toContain('---END OF TYPE DEFINITIONS---'); expect(result).toContain(mockDtsContent); - // Verify the markers are in the correct order const startIndex = result.indexOf('---START OF TYPE DEFINITIONS---'); const endIndex = result.indexOf('---END OF TYPE DEFINITIONS---'); const contentIndex = result.indexOf(mockDtsContent); @@ -119,17 +110,14 @@ export declare function agent(config: AgentConfig): Agent;`; describe('error handling', () => { it('should handle file read errors gracefully', () => { - // Mock readFileSync to throw an error mockReadFileSync.mockImplementation(() => { throw new Error('ENOENT: no such file or directory'); }); const result = getTypeDefinitions(); - // Should return fallback message expect(result).toContain('Type definitions from @inkeep/agents-sdk could not be loaded'); - // Should log warning expect(consoleWarnSpy).toHaveBeenCalledWith( 'Could not read type definitions:', expect.any(Error) @@ -137,7 +125,6 @@ export declare function agent(config: AgentConfig): Agent;`; }); it('should log warning details when errors occur', () => { - // Mock readFileSync to throw a specific error const testError = new Error('ENOENT: no such file or directory'); mockReadFileSync.mockImplementation(() => { throw testError; @@ -145,7 +132,6 @@ export declare function agent(config: AgentConfig): Agent;`; getTypeDefinitions(); - // Verify console.warn was called with error details expect(consoleWarnSpy).toHaveBeenCalledTimes(1); expect(consoleWarnSpy).toHaveBeenCalledWith('Could not read type definitions:', testError); }); @@ -157,9 +143,6 @@ export declare function agent(config: AgentConfig): Agent;`; getTypeDefinitions(); - // Verify the path construction happens: - // 1. First call: join(packageJsonPath, '..') to get package dir - // 2. Second call: join(packageDir, 'dist/index.d.ts') to get DTS path expect(mockJoin).toHaveBeenCalledTimes(2); expect(mockJoin).toHaveBeenNthCalledWith(1, expect.any(String), '..'); expect(mockJoin).toHaveBeenNthCalledWith(2, expect.any(String), 'dist/index.d.ts'); @@ -187,8 +170,6 @@ export { project }; const result = getTypeDefinitions(); - // The returned content should include the exact DTS content - // without any modifications to whitespace or formatting expect(result).toContain(exactDtsContent); expect(result).toContain('// Copyright notice'); expect(result).toContain('export interface AgentConfig'); @@ -203,14 +184,12 @@ export { project }; const result = getTypeDefinitions(); - // Should still have the wrapper even with empty content expect(result).toContain('TYPESCRIPT TYPE DEFINITIONS'); expect(result).toContain('---START OF TYPE DEFINITIONS---'); expect(result).toContain('---END OF TYPE DEFINITIONS---'); }); it('should handle large DTS files', () => { - // Create a large DTS content (simulating a real SDK file) const largeDtsContent = Array(1000) .fill(null) .map((_, i) => `export interface Type${i} { prop: string; }`) @@ -227,74 +206,5 @@ export { project }; expect(result).toContain('---END OF TYPE DEFINITIONS---'); }); }); - - describe('integration with prompt generation', () => { - it('should be included in index file generation prompts', () => { - // This tests that getTypeDefinitions() is properly integrated - // into the prompt templates for generateIndexFile - const promptTemplate = `Generate a TypeScript index.ts file for an Inkeep project with the following data: - -PROJECT JSON DATA: -{{DATA}} - - -\${getTypeDefinitions()} - -\${NAMING_CONVENTION_RULES}`; - - expect(promptTemplate).toContain('getTypeDefinitions()'); - }); - - it('should be included in agent generation prompts', () => { - const promptTemplate = `AGENT DATA: -{{DATA}} - -AGENT ID: {{AGENT_ID}} - -\${getTypeDefinitions()} - -IMPORTANT CONTEXT:`; - - expect(promptTemplate).toContain('getTypeDefinitions()'); - }); - - it('should be included in tool generation prompts', () => { - const promptTemplate = `TOOL DATA: -{{DATA}} - -TOOL ID: {{TOOL_ID}} - -\${getTypeDefinitions()} - -\${NAMING_CONVENTION_RULES}`; - - expect(promptTemplate).toContain('getTypeDefinitions()'); - }); - - it('should be included in data component generation prompts', () => { - const promptTemplate = `DATA COMPONENT DATA: -{{DATA}} - -COMPONENT ID: {{COMPONENT_ID}} - -\${getTypeDefinitions()} - -\${NAMING_CONVENTION_RULES}`; - - expect(promptTemplate).toContain('getTypeDefinitions()'); - }); - - it('should be included in artifact component generation prompts', () => { - const promptTemplate = `ARTIFACT COMPONENT DATA: -{{DATA}} - -COMPONENT ID: {{COMPONENT_ID}} - -\${getTypeDefinitions()} - -\${NAMING_CONVENTION_RULES}`; - - expect(promptTemplate).toContain('getTypeDefinitions()'); - }); - }); }); + From 66329f7c47d212de43c9359633d98e93ab3418f9 Mon Sep 17 00:00:00 2001 From: Andrew Mikofalvy Date: Wed, 15 Oct 2025 16:39:39 -0700 Subject: [PATCH 3/3] fix: update package.json exports to point to compiled output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed 10 failing CLI tests by updating package.json files to point to compiled JavaScript instead of TypeScript source files. Root cause: Node.js cannot import TypeScript files directly. When the CLI tests spawned Node.js processes, imports of @inkeep/agents-sdk and @inkeep/agents-core would fail with ERR_UNKNOWN_FILE_EXTENSION because package.json pointed to src/index.ts instead of dist/index.js. Changes: - packages/agents-sdk/package.json: Set main to dist/index.js, added types field and proper exports configuration - packages/agents-core/package.json: Set main to dist/index.js, updated all exports to point to compiled output with type definitions - Both clean-package.config.json files: Emptied replace objects since package.json now has publish-ready configuration All 273 CLI tests now pass. This follows standard TypeScript monorepo patterns where package.json always points to compiled output. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../agents-core/clean-package.config.json | 37 +----------------- packages/agents-core/package.json | 38 +++++++++++++++---- packages/agents-sdk/clean-package.config.json | 12 +----- packages/agents-sdk/package.json | 10 ++++- .../codegen-helpers-type-definitions.test.ts | 20 ++++++++-- 5 files changed, 58 insertions(+), 59 deletions(-) diff --git a/packages/agents-core/clean-package.config.json b/packages/agents-core/clean-package.config.json index 8889d7656..f55eb8ba3 100644 --- a/packages/agents-core/clean-package.config.json +++ b/packages/agents-core/clean-package.config.json @@ -1,38 +1,3 @@ { - "replace": { - "main": "dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./schema": { - "types": "./dist/db/schema.d.ts", - "import": "./dist/db/schema.js" - }, - "./types": { - "types": "./dist/types/index.d.ts", - "import": "./dist/types/index.js" - }, - "./validation": { - "types": "./dist/validation/index.d.ts", - "import": "./dist/validation/index.js" - }, - "./client-exports": { - "types": "./dist/client-exports.d.ts", - "import": "./dist/client-exports.js" - }, - "./constants/models": { - "types": "./dist/constants/models.d.ts", - "import": "./dist/constants/models.js" - }, - "./utils/schema-conversion": { - "types": "./dist/utils/schema-conversion.d.ts", - "import": "./dist/utils/schema-conversion.js" - }, - "./drizzle": "./drizzle/", - "./package.json": "./package.json" - } - } + "replace": {} } diff --git a/packages/agents-core/package.json b/packages/agents-core/package.json index e1a4b794a..e9a91e357 100644 --- a/packages/agents-core/package.json +++ b/packages/agents-core/package.json @@ -4,17 +4,39 @@ "description": "Agents Core contains the database schema, types, and validation schemas for Inkeep Agent Framework, along with core components.", "type": "module", "license": "SEE LICENSE IN LICENSE.md", - "main": "./src/index.ts", + "main": "dist/index.js", "types": "./dist/index.d.ts", "exports": { - ".": "./src/index.ts", - "./constants/models": "./src/constants/models.ts", - "./schema": "./src/db/schema.ts", - "./types": "./src/types/index.ts", - "./validation": "./src/validation/index.ts", - "./client-exports": "./src/client-exports.ts", + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./schema": { + "types": "./dist/db/schema.d.ts", + "import": "./dist/db/schema.js" + }, + "./types": { + "types": "./dist/types/index.d.ts", + "import": "./dist/types/index.js" + }, + "./validation": { + "types": "./dist/validation/index.d.ts", + "import": "./dist/validation/index.js" + }, + "./client-exports": { + "types": "./dist/client-exports.d.ts", + "import": "./dist/client-exports.js" + }, + "./constants/models": { + "types": "./dist/constants/models.d.ts", + "import": "./dist/constants/models.js" + }, + "./utils/schema-conversion": { + "types": "./dist/utils/schema-conversion.d.ts", + "import": "./dist/utils/schema-conversion.js" + }, "./drizzle": "./drizzle/", - "./utils/schema-conversion": "./src/utils/schema-conversion.ts" + "./package.json": "./package.json" }, "scripts": { "build": "tsup", diff --git a/packages/agents-sdk/clean-package.config.json b/packages/agents-sdk/clean-package.config.json index 0d430d096..f55eb8ba3 100644 --- a/packages/agents-sdk/clean-package.config.json +++ b/packages/agents-sdk/clean-package.config.json @@ -1,13 +1,3 @@ { - "replace": { - "main": "dist/index.js", - "types": "dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "import": "./dist/index.js" - }, - "./package.json": "./package.json" - } - } + "replace": {} } diff --git a/packages/agents-sdk/package.json b/packages/agents-sdk/package.json index 89930cbe8..385892178 100644 --- a/packages/agents-sdk/package.json +++ b/packages/agents-sdk/package.json @@ -2,8 +2,16 @@ "name": "@inkeep/agents-sdk", "version": "0.22.3", "description": "Agents SDK for building and managing agents in the Inkeep Agent Framework", - "main": "src/index.ts", + "main": "dist/index.js", + "types": "dist/index.d.ts", "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./package.json": "./package.json" + }, "scripts": { "build": "tsup", "test": "ENVIRONMENT=test vitest --run", diff --git a/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts b/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts index 1f7cbb122..919451bd9 100644 --- a/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts +++ b/packages/agents-sdk/src/__tests__/utils/codegen-helpers-type-definitions.test.ts @@ -3,7 +3,7 @@ import { join } from 'node:path'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; vi.mock('node:fs', async (importOriginal) => { - const actual = await importOriginal(); + const actual = (await importOriginal()) as any; return { ...actual, default: { @@ -19,7 +19,7 @@ vi.mock('node:fs', async (importOriginal) => { }); vi.mock('node:path', async (importOriginal) => { - const actual = await importOriginal(); + const actual = (await importOriginal()) as any; return { ...actual, default: { @@ -32,6 +32,21 @@ vi.mock('node:path', async (importOriginal) => { }; }); +vi.mock('node:module', async (importOriginal) => { + const actual = (await importOriginal()) as any; + return { + ...actual, + createRequire: vi.fn(() => ({ + resolve: vi.fn((moduleName: string) => { + if (moduleName === '@inkeep/agents-sdk/package.json') { + return '/mock/path/to/package.json'; + } + return moduleName; + }), + })), + }; +}); + const mockReadFileSync = vi.mocked(readFileSync); const mockJoin = vi.mocked(join); @@ -207,4 +222,3 @@ export { project }; }); }); }); -