diff --git a/package.json b/package.json index 8ad3cde..7be7e5d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "promptl-ai", - "version": "0.7.0", + "version": "0.7.1", "author": "Latitude Data", "license": "MIT", "description": "Compiler for PromptL, the prompt language", diff --git a/src/compiler/base/nodes/for.test.ts b/src/compiler/base/nodes/for.test.ts index 912192a..9e0269d 100644 --- a/src/compiler/base/nodes/for.test.ts +++ b/src/compiler/base/nodes/for.test.ts @@ -1,5 +1,3 @@ -import CompileError from '$promptl/error/error' -import { getExpectedError } from '$promptl/test/helpers' import { Message, MessageContent, TextContent } from '$promptl/types' import { describe, expect, it } from 'vitest' @@ -71,12 +69,11 @@ describe('each loops', async () => { const prompt1 = `{{ for elemenet in ['a', 'b', 'c'] }} {{foo = 5}} {{ endfor }} {{foo}}` const prompt2 = `{{foo = 5}} {{ for element in ['a', 'b', 'c'] }} {{foo = 7}} {{ endfor }} {{foo}}` const prompt3 = `{{foo = 5}} {{ for element in [1, 2, 3] }} {{foo += element}} {{ endfor }} {{foo}}` - const action1 = () => render({ prompt: prompt1, parameters: {} }) - const error1 = await getExpectedError(action1, CompileError) + const result1 = await getCompiledText(prompt1) const result2 = await getCompiledText(prompt2) const result3 = await getCompiledText(prompt3) - expect(error1.code).toBe('variable-not-declared') + expect(result1).toBe('') expect(result2).toBe('7') expect(result3).toBe('11') }) diff --git a/src/compiler/base/nodes/tags/ref.test.ts b/src/compiler/base/nodes/tags/ref.test.ts index 5cf743e..e34ad88 100644 --- a/src/compiler/base/nodes/tags/ref.test.ts +++ b/src/compiler/base/nodes/tags/ref.test.ts @@ -56,7 +56,8 @@ describe('ref tags', async () => { child: 'child message', } - const action = () => render({ prompt: prompts['parent'], adapter: Adapters.default }) + const action = () => + render({ prompt: prompts['parent'], adapter: Adapters.default }) const error = await getExpectedError(action, CompileError) expect(error.code).toBe('missing-reference-function') }) @@ -83,16 +84,19 @@ describe('ref tags', async () => { parent: '', } - const action = () => - render({ - prompt: prompts['parent'], - parameters: { foo: 'bar' }, - referenceFn: buildReferenceFn(prompts), - adapter: Adapters.default, - }) - - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') + const result = await render({ + prompt: prompts['parent'], + referenceFn: buildReferenceFn(prompts), + adapter: Adapters.default, + }) + expect(result.messages.length).toBe(1) + const message = result.messages[0]! as SystemMessage + expect(message.content).toEqual([ + { + type: 'text', + text: 'Child message:', + }, + ]) }) it('referenced prompts can receive parameters as tag attributes', async () => { @@ -336,12 +340,12 @@ describe('ref tags', async () => { {{ bar }} {{ endfor }} - `) + `), } const metadata = await scan({ prompt: prompts['parent'], - referenceFn: buildReferenceFn(prompts) + referenceFn: buildReferenceFn(prompts), }) const result = await render({ @@ -351,18 +355,19 @@ describe('ref tags', async () => { }) expect(result.messages.length).toBe(2) - const [ firstMessage, secondMessage ] = result.messages as [UserMessage, SystemMessage] + const [firstMessage, secondMessage] = result.messages as [ + UserMessage, + SystemMessage, + ] expect(firstMessage.role).toBe(MessageRole.user) expect(firstMessage.content.length).toBe(3) expect(firstMessage.content).toEqual([ - { type: 'text', text: '11'}, - { type: 'text', text: '12'}, - { type: 'text', text: '13'}, + { type: 'text', text: '11' }, + { type: 'text', text: '12' }, + { type: 'text', text: '13' }, ]) expect(secondMessage.role).toBe(MessageRole.system) expect(secondMessage.content.length).toBe(1) - expect(secondMessage.content).toEqual([ - { type: 'text', text: '10' } - ]) + expect(secondMessage.content).toEqual([{ type: 'text', text: '10' }]) }) }) diff --git a/src/compiler/base/nodes/tags/scope.test.ts b/src/compiler/base/nodes/tags/scope.test.ts index 679c2e2..64ca851 100644 --- a/src/compiler/base/nodes/tags/scope.test.ts +++ b/src/compiler/base/nodes/tags/scope.test.ts @@ -1,13 +1,7 @@ import { Adapters, Chain, render } from '$promptl/index' import { complete } from '$promptl/compiler/test/helpers' import { removeCommonIndent } from '$promptl/compiler/utils' -import CompileError from '$promptl/error/error' -import { getExpectedError } from '$promptl/test/helpers' -import { - MessageRole, - SystemMessage, - UserMessage, -} from '$promptl/types' +import { MessageRole, SystemMessage, UserMessage } from '$promptl/types' import { describe, expect, it, vi } from 'vitest' describe('scope tags', async () => { @@ -48,7 +42,7 @@ describe('scope tags', async () => { `) const result = await render({ prompt, adapter: Adapters.default }) - + expect(result.messages.length).toBe(1) const message = result.messages[0]! as SystemMessage expect(message.content).toEqual([ @@ -67,18 +61,19 @@ describe('scope tags', async () => { const prompt = removeCommonIndent(` {{ foo = 'bar' }} - {{ foo }} + {{ foo == 'bar' }} `) - const action = () => render({ - prompt, - parameters: { foo: 'baz' }, - adapter: Adapters.default - }) - - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') + const result = await render({ prompt, adapter: Adapters.default }) + expect(result.messages.length).toBe(1) + const message = result.messages[0]! as SystemMessage + expect(message.content).toEqual([ + { + type: 'text', + text: 'false', + }, + ]) }) it('can inherit parameters from parents if explicitly passed', async () => { @@ -91,7 +86,7 @@ describe('scope tags', async () => { const result = await render({ prompt, parameters: { foo: 'bar' }, - adapter: Adapters.default + adapter: Adapters.default, }) expect(result.messages.length).toBe(1) diff --git a/src/compiler/chain.test.ts b/src/compiler/chain.test.ts index f8fef30..da53525 100644 --- a/src/compiler/chain.test.ts +++ b/src/compiler/chain.test.ts @@ -343,19 +343,6 @@ describe('chain', async () => { {{foo}} `) - const incorrectPrompt = removeCommonIndent(` - {{foo = 5}} - - {{if true}} - {{bar = 1}} - - {{ bar++}} - - {{endif}} - - {{bar}} - `) - const correctChain = new Chain({ prompt: correctPrompt, adapter: Adapters.default, @@ -371,16 +358,6 @@ describe('chain', async () => { }, ], }) - - const incorrectChain = new Chain({ - prompt: incorrectPrompt, - parameters: {}, - adapter: Adapters.default, - }) - - const action = () => complete({ chain: incorrectChain }) - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') }) it('maintains the scope in for loops', async () => { @@ -419,23 +396,6 @@ describe('chain', async () => { }) }) - it('cannot access variables created in a loop outside its scope', async () => { - const prompt = removeCommonIndent(` - {{for i in [1, 2, 3]}} - {{foo = i}} - - {{endfor}} - - {{foo}} - `) - - const chain = new Chain({ prompt, adapter: Adapters.default }) - - const action = () => complete({ chain }) - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') - }) - it('maintains the scope in nested loops', async () => { const prompt = removeCommonIndent(` {{ foo = 0 }} diff --git a/src/compiler/compile.test.ts b/src/compiler/compile.test.ts index 3a0ad1e..6c14b81 100644 --- a/src/compiler/compile.test.ts +++ b/src/compiler/compile.test.ts @@ -173,18 +173,12 @@ describe('variable assignment', async () => { expect(result).toBe('5') }) - it('cannot reference undefined variables', async () => { + it('undefined variables do not cause an error', async () => { const prompt = ` {{ foo }} ` - const action = () => - render({ - prompt: removeCommonIndent(prompt), - parameters: {}, - adapter: Adapters.default, - }) - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') + const result = await getCompiledText(prompt) + expect(result).toBe('') }) it('parameters are available as variables in the prompt', async () => { @@ -227,14 +221,8 @@ describe('variable assignment', async () => { {{ endif }} {{ foo }} ` - const action = () => - render({ - prompt: removeCommonIndent(prompt), - parameters: {}, - adapter: Adapters.default, - }) - const error = await getExpectedError(action, CompileError) - expect(error.code).toBe('variable-not-declared') + const result = await getCompiledText(prompt) + expect(result).toBe('') }) it('variables can be modified from an inner scope', async () => { diff --git a/src/compiler/logic/nodes/identifier.ts b/src/compiler/logic/nodes/identifier.ts index 33bd632..bd712a2 100644 --- a/src/compiler/logic/nodes/identifier.ts +++ b/src/compiler/logic/nodes/identifier.ts @@ -9,13 +9,9 @@ import type { Identifier } from 'estree' * ### Identifier * Represents a variable from the scope. */ -export async function resolve({ - node, - scope, - raiseError, -}: ResolveNodeProps) { +export async function resolve({ node, scope }: ResolveNodeProps) { if (!scope.exists(node.name)) { - raiseError(errors.variableNotDeclared(node.name), node) + return undefined } return scope.get(node.name) }