@vibe-lang/runtime 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +46 -0
- package/src/ast/index.ts +375 -0
- package/src/ast.ts +2 -0
- package/src/debug/advanced-features.ts +482 -0
- package/src/debug/bun-inspector.ts +424 -0
- package/src/debug/handoff-manager.ts +283 -0
- package/src/debug/index.ts +150 -0
- package/src/debug/runner.ts +365 -0
- package/src/debug/server.ts +565 -0
- package/src/debug/stack-merger.ts +267 -0
- package/src/debug/state.ts +581 -0
- package/src/debug/test/advanced-features.test.ts +300 -0
- package/src/debug/test/e2e.test.ts +218 -0
- package/src/debug/test/handoff-manager.test.ts +256 -0
- package/src/debug/test/runner.test.ts +256 -0
- package/src/debug/test/stack-merger.test.ts +163 -0
- package/src/debug/test/state.test.ts +400 -0
- package/src/debug/test/ts-debug-integration.test.ts +374 -0
- package/src/debug/test/ts-import-tracker.test.ts +125 -0
- package/src/debug/test/ts-source-map.test.ts +169 -0
- package/src/debug/ts-import-tracker.ts +151 -0
- package/src/debug/ts-source-map.ts +171 -0
- package/src/errors/index.ts +124 -0
- package/src/index.ts +358 -0
- package/src/lexer/index.ts +348 -0
- package/src/lexer.ts +2 -0
- package/src/parser/index.ts +792 -0
- package/src/parser/parse.ts +45 -0
- package/src/parser/test/async.test.ts +248 -0
- package/src/parser/test/destructuring.test.ts +167 -0
- package/src/parser/test/do-expression.test.ts +486 -0
- package/src/parser/test/errors/do-expression.test.ts +95 -0
- package/src/parser/test/errors/error-locations.test.ts +230 -0
- package/src/parser/test/errors/invalid-expressions.test.ts +144 -0
- package/src/parser/test/errors/missing-tokens.test.ts +126 -0
- package/src/parser/test/errors/model-declaration.test.ts +185 -0
- package/src/parser/test/errors/nested-blocks.test.ts +226 -0
- package/src/parser/test/errors/unclosed-delimiters.test.ts +122 -0
- package/src/parser/test/errors/unexpected-tokens.test.ts +120 -0
- package/src/parser/test/import-export.test.ts +143 -0
- package/src/parser/test/literals.test.ts +404 -0
- package/src/parser/test/model-declaration.test.ts +161 -0
- package/src/parser/test/nested-blocks.test.ts +402 -0
- package/src/parser/test/parser.test.ts +743 -0
- package/src/parser/test/private.test.ts +136 -0
- package/src/parser/test/template-literal.test.ts +127 -0
- package/src/parser/test/tool-declaration.test.ts +302 -0
- package/src/parser/test/ts-block.test.ts +252 -0
- package/src/parser/test/type-annotations.test.ts +254 -0
- package/src/parser/visitor/helpers.ts +330 -0
- package/src/parser/visitor.ts +794 -0
- package/src/parser.ts +2 -0
- package/src/runtime/ai/cache-chunking.test.ts +69 -0
- package/src/runtime/ai/cache-chunking.ts +73 -0
- package/src/runtime/ai/client.ts +109 -0
- package/src/runtime/ai/context.ts +168 -0
- package/src/runtime/ai/formatters.ts +316 -0
- package/src/runtime/ai/index.ts +38 -0
- package/src/runtime/ai/language-ref.ts +38 -0
- package/src/runtime/ai/providers/anthropic.ts +253 -0
- package/src/runtime/ai/providers/google.ts +201 -0
- package/src/runtime/ai/providers/openai.ts +156 -0
- package/src/runtime/ai/retry.ts +100 -0
- package/src/runtime/ai/return-tools.ts +301 -0
- package/src/runtime/ai/test/client.test.ts +83 -0
- package/src/runtime/ai/test/formatters.test.ts +485 -0
- package/src/runtime/ai/test/retry.test.ts +137 -0
- package/src/runtime/ai/test/return-tools.test.ts +450 -0
- package/src/runtime/ai/test/tool-loop.test.ts +319 -0
- package/src/runtime/ai/test/tool-schema.test.ts +241 -0
- package/src/runtime/ai/tool-loop.ts +203 -0
- package/src/runtime/ai/tool-schema.ts +151 -0
- package/src/runtime/ai/types.ts +113 -0
- package/src/runtime/ai-logger.ts +255 -0
- package/src/runtime/ai-provider.ts +347 -0
- package/src/runtime/async/dependencies.ts +276 -0
- package/src/runtime/async/executor.ts +293 -0
- package/src/runtime/async/index.ts +43 -0
- package/src/runtime/async/scheduling.ts +163 -0
- package/src/runtime/async/test/dependencies.test.ts +284 -0
- package/src/runtime/async/test/executor.test.ts +388 -0
- package/src/runtime/context.ts +357 -0
- package/src/runtime/exec/ai.ts +139 -0
- package/src/runtime/exec/expressions.ts +475 -0
- package/src/runtime/exec/frames.ts +26 -0
- package/src/runtime/exec/functions.ts +305 -0
- package/src/runtime/exec/interpolation.ts +312 -0
- package/src/runtime/exec/statements.ts +604 -0
- package/src/runtime/exec/tools.ts +129 -0
- package/src/runtime/exec/typescript.ts +215 -0
- package/src/runtime/exec/variables.ts +279 -0
- package/src/runtime/index.ts +975 -0
- package/src/runtime/modules.ts +452 -0
- package/src/runtime/serialize.ts +103 -0
- package/src/runtime/state.ts +489 -0
- package/src/runtime/stdlib/core.ts +45 -0
- package/src/runtime/stdlib/directory.test.ts +156 -0
- package/src/runtime/stdlib/edit.test.ts +154 -0
- package/src/runtime/stdlib/fastEdit.test.ts +201 -0
- package/src/runtime/stdlib/glob.test.ts +106 -0
- package/src/runtime/stdlib/grep.test.ts +144 -0
- package/src/runtime/stdlib/index.ts +16 -0
- package/src/runtime/stdlib/readFile.test.ts +123 -0
- package/src/runtime/stdlib/tools/index.ts +707 -0
- package/src/runtime/stdlib/writeFile.test.ts +157 -0
- package/src/runtime/step.ts +969 -0
- package/src/runtime/test/ai-context.test.ts +1086 -0
- package/src/runtime/test/ai-result-object.test.ts +419 -0
- package/src/runtime/test/ai-tool-flow.test.ts +859 -0
- package/src/runtime/test/async-execution-order.test.ts +618 -0
- package/src/runtime/test/async-execution.test.ts +344 -0
- package/src/runtime/test/async-nested.test.ts +660 -0
- package/src/runtime/test/async-parallel-timing.test.ts +546 -0
- package/src/runtime/test/basic1.test.ts +154 -0
- package/src/runtime/test/binary-operators.test.ts +431 -0
- package/src/runtime/test/break-statement.test.ts +257 -0
- package/src/runtime/test/context-modes.test.ts +650 -0
- package/src/runtime/test/context.test.ts +466 -0
- package/src/runtime/test/core-functions.test.ts +228 -0
- package/src/runtime/test/e2e.test.ts +88 -0
- package/src/runtime/test/error-locations/error-locations.test.ts +80 -0
- package/src/runtime/test/error-locations/main-error.vibe +4 -0
- package/src/runtime/test/error-locations/main-import-error.vibe +3 -0
- package/src/runtime/test/error-locations/utils/helper.vibe +5 -0
- package/src/runtime/test/for-in.test.ts +312 -0
- package/src/runtime/test/helpers.ts +69 -0
- package/src/runtime/test/imports.test.ts +334 -0
- package/src/runtime/test/json-expressions.test.ts +232 -0
- package/src/runtime/test/literals.test.ts +372 -0
- package/src/runtime/test/logical-indexing.test.ts +478 -0
- package/src/runtime/test/member-methods.test.ts +324 -0
- package/src/runtime/test/model-config.test.ts +338 -0
- package/src/runtime/test/null-handling.test.ts +342 -0
- package/src/runtime/test/private-visibility.test.ts +332 -0
- package/src/runtime/test/runtime-state.test.ts +514 -0
- package/src/runtime/test/scoping.test.ts +370 -0
- package/src/runtime/test/string-interpolation.test.ts +354 -0
- package/src/runtime/test/template-literal.test.ts +181 -0
- package/src/runtime/test/tool-execution.test.ts +467 -0
- package/src/runtime/test/tool-schema-generation.test.ts +477 -0
- package/src/runtime/test/tostring.test.ts +210 -0
- package/src/runtime/test/ts-block.test.ts +594 -0
- package/src/runtime/test/ts-error-location.test.ts +231 -0
- package/src/runtime/test/types.test.ts +732 -0
- package/src/runtime/test/verbose-logger.test.ts +710 -0
- package/src/runtime/test/vibe-expression.test.ts +54 -0
- package/src/runtime/test/vibe-value-errors.test.ts +541 -0
- package/src/runtime/test/while.test.ts +232 -0
- package/src/runtime/tools/builtin.ts +30 -0
- package/src/runtime/tools/directory-tools.ts +70 -0
- package/src/runtime/tools/file-tools.ts +228 -0
- package/src/runtime/tools/index.ts +5 -0
- package/src/runtime/tools/registry.ts +48 -0
- package/src/runtime/tools/search-tools.ts +134 -0
- package/src/runtime/tools/security.ts +36 -0
- package/src/runtime/tools/system-tools.ts +312 -0
- package/src/runtime/tools/test/fixtures/base-types.ts +40 -0
- package/src/runtime/tools/test/fixtures/test-types.ts +132 -0
- package/src/runtime/tools/test/registry.test.ts +713 -0
- package/src/runtime/tools/test/security.test.ts +86 -0
- package/src/runtime/tools/test/system-tools.test.ts +679 -0
- package/src/runtime/tools/test/ts-schema.test.ts +357 -0
- package/src/runtime/tools/ts-schema.ts +341 -0
- package/src/runtime/tools/types.ts +89 -0
- package/src/runtime/tools/utility-tools.ts +198 -0
- package/src/runtime/ts-eval.ts +126 -0
- package/src/runtime/types.ts +797 -0
- package/src/runtime/validation.ts +160 -0
- package/src/runtime/verbose-logger.ts +459 -0
- package/src/runtime.ts +2 -0
- package/src/semantic/analyzer-context.ts +62 -0
- package/src/semantic/analyzer-validators.ts +575 -0
- package/src/semantic/analyzer-visitors.ts +534 -0
- package/src/semantic/analyzer.ts +83 -0
- package/src/semantic/index.ts +11 -0
- package/src/semantic/symbol-table.ts +58 -0
- package/src/semantic/test/async-validation.test.ts +301 -0
- package/src/semantic/test/compress-validation.test.ts +179 -0
- package/src/semantic/test/const-reassignment.test.ts +111 -0
- package/src/semantic/test/control-flow.test.ts +346 -0
- package/src/semantic/test/destructuring.test.ts +185 -0
- package/src/semantic/test/duplicate-declarations.test.ts +168 -0
- package/src/semantic/test/export-validation.test.ts +111 -0
- package/src/semantic/test/fixtures/math.ts +31 -0
- package/src/semantic/test/imports.test.ts +148 -0
- package/src/semantic/test/json-type.test.ts +68 -0
- package/src/semantic/test/literals.test.ts +127 -0
- package/src/semantic/test/model-validation.test.ts +179 -0
- package/src/semantic/test/prompt-validation.test.ts +343 -0
- package/src/semantic/test/scoping.test.ts +312 -0
- package/src/semantic/test/tool-validation.test.ts +306 -0
- package/src/semantic/test/ts-type-checking.test.ts +563 -0
- package/src/semantic/test/type-constraints.test.ts +111 -0
- package/src/semantic/test/type-inference.test.ts +87 -0
- package/src/semantic/test/type-validation.test.ts +552 -0
- package/src/semantic/test/undefined-variables.test.ts +163 -0
- package/src/semantic/ts-block-checker.ts +204 -0
- package/src/semantic/ts-signatures.ts +194 -0
- package/src/semantic/ts-types.ts +170 -0
- package/src/semantic/types.ts +58 -0
- package/tests/fixtures/conditional-logic.vibe +14 -0
- package/tests/fixtures/function-call.vibe +16 -0
- package/tests/fixtures/imports/cycle-detection/a.vibe +6 -0
- package/tests/fixtures/imports/cycle-detection/b.vibe +5 -0
- package/tests/fixtures/imports/cycle-detection/main.vibe +3 -0
- package/tests/fixtures/imports/module-isolation/main-b.vibe +8 -0
- package/tests/fixtures/imports/module-isolation/main.vibe +9 -0
- package/tests/fixtures/imports/module-isolation/moduleA.vibe +6 -0
- package/tests/fixtures/imports/module-isolation/moduleB.vibe +6 -0
- package/tests/fixtures/imports/nested-import/helper.vibe +6 -0
- package/tests/fixtures/imports/nested-import/main.vibe +3 -0
- package/tests/fixtures/imports/nested-import/utils.ts +3 -0
- package/tests/fixtures/imports/nested-isolation/file2.vibe +15 -0
- package/tests/fixtures/imports/nested-isolation/file3.vibe +10 -0
- package/tests/fixtures/imports/nested-isolation/main.vibe +21 -0
- package/tests/fixtures/imports/pure-cycle/a.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/b.vibe +5 -0
- package/tests/fixtures/imports/pure-cycle/main.vibe +3 -0
- package/tests/fixtures/imports/ts-boolean/checks.ts +14 -0
- package/tests/fixtures/imports/ts-boolean/main.vibe +10 -0
- package/tests/fixtures/imports/ts-boolean/type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-boolean/use-constant.vibe +18 -0
- package/tests/fixtures/imports/ts-error-handling/helpers.ts +42 -0
- package/tests/fixtures/imports/ts-error-handling/main.vibe +5 -0
- package/tests/fixtures/imports/ts-import/main.vibe +4 -0
- package/tests/fixtures/imports/ts-import/math.ts +9 -0
- package/tests/fixtures/imports/ts-variables/call-non-function.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/data.ts +10 -0
- package/tests/fixtures/imports/ts-variables/import-json.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-type-mismatch.vibe +5 -0
- package/tests/fixtures/imports/ts-variables/import-variable.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/greet.vibe +5 -0
- package/tests/fixtures/imports/vibe-import/main.vibe +3 -0
- package/tests/fixtures/multiple-ai-calls.vibe +10 -0
- package/tests/fixtures/simple-greeting.vibe +6 -0
- package/tests/fixtures/template-literals.vibe +11 -0
- package/tests/integration/basic-ai/basic-ai.integration.test.ts +166 -0
- package/tests/integration/basic-ai/basic-ai.vibe +12 -0
- package/tests/integration/bug-fix/bug-fix.integration.test.ts +201 -0
- package/tests/integration/bug-fix/buggy-code.ts +22 -0
- package/tests/integration/bug-fix/fix-bug.vibe +21 -0
- package/tests/integration/compress/compress.integration.test.ts +206 -0
- package/tests/integration/destructuring/destructuring.integration.test.ts +92 -0
- package/tests/integration/hello-world-translator/hello-world-translator.integration.test.ts +61 -0
- package/tests/integration/line-annotator/context-modes.integration.test.ts +261 -0
- package/tests/integration/line-annotator/line-annotator.integration.test.ts +148 -0
- package/tests/integration/multi-feature/cumulative-sum.integration.test.ts +75 -0
- package/tests/integration/multi-feature/number-analyzer.integration.test.ts +191 -0
- package/tests/integration/multi-feature/number-analyzer.vibe +59 -0
- package/tests/integration/tool-calls/tool-calls.integration.test.ts +93 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import { parse } from '../../parser/parse';
|
|
3
|
+
import { analyze } from '../index';
|
|
4
|
+
|
|
5
|
+
describe('Semantic Analysis - Tool Declaration', () => {
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// @param decorator validation
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
describe('@param decorator validation', () => {
|
|
11
|
+
test('valid @param referencing existing parameter', () => {
|
|
12
|
+
const ast = parse(`
|
|
13
|
+
tool greet(name: text): text
|
|
14
|
+
@description "Greet someone"
|
|
15
|
+
@param name "The person's name"
|
|
16
|
+
{
|
|
17
|
+
ts(name) { return "Hello, " + name }
|
|
18
|
+
}
|
|
19
|
+
`);
|
|
20
|
+
const errors = analyze(ast);
|
|
21
|
+
expect(errors).toHaveLength(0);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('valid @param for multiple parameters', () => {
|
|
25
|
+
const ast = parse(`
|
|
26
|
+
tool calculate(x: number, y: number, op: text): number
|
|
27
|
+
@description "Calculate"
|
|
28
|
+
@param x "First operand"
|
|
29
|
+
@param y "Second operand"
|
|
30
|
+
@param op "Operation"
|
|
31
|
+
{
|
|
32
|
+
ts(x, y, op) { return x + y }
|
|
33
|
+
}
|
|
34
|
+
`);
|
|
35
|
+
const errors = analyze(ast);
|
|
36
|
+
expect(errors).toHaveLength(0);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('error when @param references non-existent parameter', () => {
|
|
40
|
+
const ast = parse(`
|
|
41
|
+
tool greet(name: text): text
|
|
42
|
+
@description "Greet someone"
|
|
43
|
+
@param nonexistent "This param does not exist"
|
|
44
|
+
{
|
|
45
|
+
ts(name) { return "Hello, " + name }
|
|
46
|
+
}
|
|
47
|
+
`);
|
|
48
|
+
const errors = analyze(ast);
|
|
49
|
+
expect(errors).toHaveLength(1);
|
|
50
|
+
expect(errors[0].message).toContain("@param 'nonexistent' does not match any parameter");
|
|
51
|
+
expect(errors[0].message).toContain("Valid parameters: name");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('error when @param references non-existent parameter among multiple', () => {
|
|
55
|
+
const ast = parse(`
|
|
56
|
+
tool sendEmail(to: text, subject: text): boolean
|
|
57
|
+
@description "Send email"
|
|
58
|
+
@param to "Recipient"
|
|
59
|
+
@param body "This param does not exist"
|
|
60
|
+
{
|
|
61
|
+
ts(to, subject) { return true }
|
|
62
|
+
}
|
|
63
|
+
`);
|
|
64
|
+
const errors = analyze(ast);
|
|
65
|
+
expect(errors).toHaveLength(1);
|
|
66
|
+
expect(errors[0].message).toContain("@param 'body' does not match any parameter");
|
|
67
|
+
expect(errors[0].message).toContain("Valid parameters: to, subject");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('error when @param used on tool with no parameters', () => {
|
|
71
|
+
const ast = parse(`
|
|
72
|
+
tool getCurrentTime(): text
|
|
73
|
+
@description "Get current time"
|
|
74
|
+
@param time "There are no params"
|
|
75
|
+
{
|
|
76
|
+
ts() { return new Date().toISOString() }
|
|
77
|
+
}
|
|
78
|
+
`);
|
|
79
|
+
const errors = analyze(ast);
|
|
80
|
+
expect(errors).toHaveLength(1);
|
|
81
|
+
expect(errors[0].message).toContain("@param 'time' does not match any parameter");
|
|
82
|
+
expect(errors[0].message).toContain("Valid parameters: (none)");
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('multiple @param errors reported', () => {
|
|
86
|
+
const ast = parse(`
|
|
87
|
+
tool greet(name: text): text
|
|
88
|
+
@description "Greet"
|
|
89
|
+
@param foo "Does not exist"
|
|
90
|
+
@param bar "Also does not exist"
|
|
91
|
+
{
|
|
92
|
+
ts(name) { return "Hello" }
|
|
93
|
+
}
|
|
94
|
+
`);
|
|
95
|
+
const errors = analyze(ast);
|
|
96
|
+
expect(errors).toHaveLength(2);
|
|
97
|
+
expect(errors[0].message).toContain("@param 'foo'");
|
|
98
|
+
expect(errors[1].message).toContain("@param 'bar'");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('partial valid @params with one invalid', () => {
|
|
102
|
+
const ast = parse(`
|
|
103
|
+
tool search(query: text, limit: number): json
|
|
104
|
+
@description "Search"
|
|
105
|
+
@param query "Search query"
|
|
106
|
+
@param typo "This is a typo"
|
|
107
|
+
@param limit "Max results"
|
|
108
|
+
{
|
|
109
|
+
ts(query, limit) { return [] }
|
|
110
|
+
}
|
|
111
|
+
`);
|
|
112
|
+
const errors = analyze(ast);
|
|
113
|
+
expect(errors).toHaveLength(1);
|
|
114
|
+
expect(errors[0].message).toContain("@param 'typo'");
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// Tool type validation
|
|
120
|
+
// ============================================================================
|
|
121
|
+
|
|
122
|
+
describe('Tool type validation', () => {
|
|
123
|
+
test('valid Vibe types in parameters', () => {
|
|
124
|
+
const ast = parse(`
|
|
125
|
+
tool test(a: text, b: number, c: boolean, d: json): text
|
|
126
|
+
@description "Test"
|
|
127
|
+
{
|
|
128
|
+
ts(a, b, c, d) { return a }
|
|
129
|
+
}
|
|
130
|
+
`);
|
|
131
|
+
const errors = analyze(ast);
|
|
132
|
+
expect(errors).toHaveLength(0);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
test('valid array types in parameters', () => {
|
|
136
|
+
const ast = parse(`
|
|
137
|
+
tool test(items: text[], numbers: number[]): json[]
|
|
138
|
+
@description "Test"
|
|
139
|
+
{
|
|
140
|
+
ts(items, numbers) { return [] }
|
|
141
|
+
}
|
|
142
|
+
`);
|
|
143
|
+
const errors = analyze(ast);
|
|
144
|
+
expect(errors).toHaveLength(0);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('error for unknown type in parameter', () => {
|
|
148
|
+
const ast = parse(`
|
|
149
|
+
tool test(data: UnknownType): text
|
|
150
|
+
@description "Test"
|
|
151
|
+
{
|
|
152
|
+
ts(data) { return "" }
|
|
153
|
+
}
|
|
154
|
+
`);
|
|
155
|
+
const errors = analyze(ast);
|
|
156
|
+
expect(errors).toHaveLength(1);
|
|
157
|
+
expect(errors[0].message).toContain("Unknown type 'UnknownType'");
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
test('error for unknown return type', () => {
|
|
161
|
+
const ast = parse(`
|
|
162
|
+
tool test(name: text): UnknownReturn
|
|
163
|
+
@description "Test"
|
|
164
|
+
{
|
|
165
|
+
ts(name) { return {} }
|
|
166
|
+
}
|
|
167
|
+
`);
|
|
168
|
+
const errors = analyze(ast);
|
|
169
|
+
expect(errors).toHaveLength(1);
|
|
170
|
+
expect(errors[0].message).toContain("Unknown return type 'UnknownReturn'");
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test('imported type is valid when imported', () => {
|
|
174
|
+
const ast = parse(`
|
|
175
|
+
import { CustomerInfo } from "./types.ts"
|
|
176
|
+
|
|
177
|
+
tool processCustomer(info: CustomerInfo): json
|
|
178
|
+
@description "Process customer"
|
|
179
|
+
{
|
|
180
|
+
ts(info) { return {} }
|
|
181
|
+
}
|
|
182
|
+
`);
|
|
183
|
+
const errors = analyze(ast);
|
|
184
|
+
expect(errors).toHaveLength(0);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// Tool scope validation
|
|
190
|
+
// ============================================================================
|
|
191
|
+
|
|
192
|
+
describe('Tool scope validation', () => {
|
|
193
|
+
test('tool at global scope is valid', () => {
|
|
194
|
+
const ast = parse(`
|
|
195
|
+
tool greet(name: text): text
|
|
196
|
+
@description "Greet"
|
|
197
|
+
{
|
|
198
|
+
ts(name) { return "Hello" }
|
|
199
|
+
}
|
|
200
|
+
`);
|
|
201
|
+
const errors = analyze(ast);
|
|
202
|
+
expect(errors).toHaveLength(0);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Note: Parser currently doesn't allow tools inside blocks,
|
|
206
|
+
// so this test documents that behavior would be caught
|
|
207
|
+
// if it were syntactically allowed
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// Tool call validation - tools cannot be called directly
|
|
212
|
+
// ============================================================================
|
|
213
|
+
|
|
214
|
+
describe('Tool call validation', () => {
|
|
215
|
+
test('error when calling user-defined tool directly', () => {
|
|
216
|
+
const ast = parse(`
|
|
217
|
+
tool greet(name: text): text
|
|
218
|
+
@description "Greet"
|
|
219
|
+
{
|
|
220
|
+
ts(name) { return "Hello, " + name }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let result = greet("World")
|
|
224
|
+
`);
|
|
225
|
+
const errors = analyze(ast);
|
|
226
|
+
expect(errors).toHaveLength(1);
|
|
227
|
+
expect(errors[0].message).toContain("Cannot call tool 'greet' directly");
|
|
228
|
+
expect(errors[0].message).toContain("Tools can only be used by AI models");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('error when calling imported tool directly', () => {
|
|
232
|
+
const ast = parse(`
|
|
233
|
+
import { now } from "system/tools"
|
|
234
|
+
let timestamp = now()
|
|
235
|
+
`);
|
|
236
|
+
const errors = analyze(ast);
|
|
237
|
+
expect(errors).toHaveLength(1);
|
|
238
|
+
expect(errors[0].message).toContain("Cannot call tool 'now' directly");
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('error when calling multiple tools directly', () => {
|
|
242
|
+
const ast = parse(`
|
|
243
|
+
import { readFile, writeFile } from "system/tools"
|
|
244
|
+
let content = readFile("test.txt")
|
|
245
|
+
let _ = writeFile("out.txt", "data")
|
|
246
|
+
`);
|
|
247
|
+
const errors = analyze(ast);
|
|
248
|
+
expect(errors).toHaveLength(2);
|
|
249
|
+
expect(errors[0].message).toContain("Cannot call tool 'readFile' directly");
|
|
250
|
+
expect(errors[1].message).toContain("Cannot call tool 'writeFile' directly");
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test('no error when tool is used in model tools array', () => {
|
|
254
|
+
const ast = parse(`
|
|
255
|
+
tool greet(name: text): text
|
|
256
|
+
@description "Greet"
|
|
257
|
+
{
|
|
258
|
+
ts(name) { return "Hello, " + name }
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
model m = {
|
|
262
|
+
name: "gpt-4",
|
|
263
|
+
apiKey: "key",
|
|
264
|
+
url: "https://api.openai.com",
|
|
265
|
+
tools: [greet]
|
|
266
|
+
}
|
|
267
|
+
`);
|
|
268
|
+
const errors = analyze(ast);
|
|
269
|
+
expect(errors).toHaveLength(0);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test('no error when allTools is imported and used in model', () => {
|
|
273
|
+
const ast = parse(`
|
|
274
|
+
import { allTools } from "system/tools"
|
|
275
|
+
|
|
276
|
+
model m = {
|
|
277
|
+
name: "gpt-4",
|
|
278
|
+
apiKey: "key",
|
|
279
|
+
url: "https://api.openai.com",
|
|
280
|
+
tools: allTools
|
|
281
|
+
}
|
|
282
|
+
`);
|
|
283
|
+
const errors = analyze(ast);
|
|
284
|
+
expect(errors).toHaveLength(0);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test('tool declaration is valid but calling it is not', () => {
|
|
288
|
+
const ast = parse(`
|
|
289
|
+
tool double(n: number): number
|
|
290
|
+
@description "Double a number"
|
|
291
|
+
{
|
|
292
|
+
ts(n) { return n * 2 }
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Just referencing the tool is fine (e.g., for model tools array)
|
|
296
|
+
let toolRef = double
|
|
297
|
+
|
|
298
|
+
// But calling it is not allowed
|
|
299
|
+
let result = double(21)
|
|
300
|
+
`);
|
|
301
|
+
const errors = analyze(ast);
|
|
302
|
+
expect(errors).toHaveLength(1);
|
|
303
|
+
expect(errors[0].message).toContain("Cannot call tool 'double' directly");
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
});
|