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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
7 changes: 2 additions & 5 deletions src/compiler/base/nodes/for.test.ts
Original file line number Diff line number Diff line change
@@ -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'

Expand Down Expand Up @@ -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')
})
Expand Down
45 changes: 25 additions & 20 deletions src/compiler/base/nodes/tags/ref.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
Expand All @@ -83,16 +84,19 @@ describe('ref tags', async () => {
parent: '<prompt path="child" />',
}

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 () => {
Expand Down Expand Up @@ -336,12 +340,12 @@ describe('ref tags', async () => {
{{ bar }}
</content-text>
{{ endfor }}
`)
`),
}

const metadata = await scan({
prompt: prompts['parent'],
referenceFn: buildReferenceFn(prompts)
referenceFn: buildReferenceFn(prompts),
})

const result = await render({
Expand All @@ -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' }])
})
})
31 changes: 13 additions & 18 deletions src/compiler/base/nodes/tags/scope.test.ts
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand Down Expand Up @@ -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([
Expand All @@ -67,18 +61,19 @@ describe('scope tags', async () => {
const prompt = removeCommonIndent(`
{{ foo = 'bar' }}
<scope>
{{ foo }}
{{ foo == 'bar' }}
</scope>
`)

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 () => {
Expand All @@ -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)
Expand Down
40 changes: 0 additions & 40 deletions src/compiler/chain.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,19 +343,6 @@ describe('chain', async () => {
{{foo}}
`)

const incorrectPrompt = removeCommonIndent(`
{{foo = 5}}

{{if true}}
{{bar = 1}}
<step>
{{ bar++}}
</step>
{{endif}}

{{bar}}
`)

const correctChain = new Chain({
prompt: correctPrompt,
adapter: Adapters.default,
Expand All @@ -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 () => {
Expand Down Expand Up @@ -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}}
<step />
{{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 }}
Expand Down
22 changes: 5 additions & 17 deletions src/compiler/compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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 () => {
Expand Down
8 changes: 2 additions & 6 deletions src/compiler/logic/nodes/identifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,9 @@ import type { Identifier } from 'estree'
* ### Identifier
* Represents a variable from the scope.
*/
export async function resolve({
node,
scope,
raiseError,
}: ResolveNodeProps<Identifier>) {
export async function resolve({ node, scope }: ResolveNodeProps<Identifier>) {
if (!scope.exists(node.name)) {
raiseError(errors.variableNotDeclared(node.name), node)
return undefined
}
return scope.get(node.name)
}
Expand Down