create-nola-lang 0.1.13 → 0.1.15
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/README.md +8 -3
- package/dist/add.d.ts +3 -0
- package/dist/add.js +2 -1
- package/dist/checkout.js +1 -0
- package/dist/{chunk-LUSVIOAN.js → chunk-UTVGG44K.js} +124 -95
- package/dist/examples.d.ts +4 -2
- package/dist/examples.js +4 -2
- package/dist/flow.d.ts +20 -3
- package/dist/flow.js +49 -17
- package/dist/github.d.ts +1 -1
- package/dist/github.js +1 -1
- package/dist/index.js +1 -1
- package/dist/launch.d.ts +2 -2
- package/dist/launch.js +1 -1
- package/dist/main.js +1 -1
- package/dist/node-version.d.ts +3 -2
- package/dist/node-version.js +4 -3
- package/dist/package-manager.d.ts +5 -0
- package/dist/package-manager.js +7 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +1 -1
- package/dist/registry.d.ts +21 -12
- package/dist/registry.js +27 -5
- package/dist/scaffold.d.ts +36 -16
- package/dist/scaffold.js +96 -116
- package/package.json +1 -1
- package/skills/nola/SKILL.md +72 -17
- package/skills/nola/references/config.md +35 -6
- package/skills/nola/references/patterns.md +129 -31
- package/skills/nola/references/pitfalls.md +318 -56
- package/skills/nola/references/syntax.md +345 -121
- package/templates/empty/package.json +5 -5
- package/templates/empty/src/main.tsi +8 -0
- package/templates/empty/src/main.ts +0 -5
- package/templates/feature-extraction/README.md +0 -20
- package/templates/feature-extraction/nola.config.ts +0 -14
- package/templates/feature-extraction/nola.replay.jsonl +0 -2
- package/templates/feature-extraction/package.json +0 -22
- package/templates/feature-extraction/src/main.tsi +0 -22
- package/templates/feature-extraction/tsconfig.json +0 -12
- package/templates/function-calling/README.md +0 -21
- package/templates/function-calling/nola.config.ts +0 -14
- package/templates/function-calling/nola.replay.jsonl +0 -1
- package/templates/function-calling/package.json +0 -22
- package/templates/function-calling/src/main.tsi +0 -12
- package/templates/function-calling/src/tickets.ts +0 -17
- package/templates/function-calling/tsconfig.json +0 -12
- package/templates/typescript-interop/README.md +0 -15
- package/templates/typescript-interop/nola.config.ts +0 -14
- package/templates/typescript-interop/nola.replay.jsonl +0 -1
- package/templates/typescript-interop/package.json +0 -22
- package/templates/typescript-interop/src/main.ts +0 -8
- package/templates/typescript-interop/src/person.tsi +0 -11
- package/templates/typescript-interop/tsconfig.json +0 -12
|
@@ -15,14 +15,14 @@ a parenthesized expression will not parse.
|
|
|
15
15
|
```tsi
|
|
16
16
|
export infer function summarize(.text: string, useFast: boolean) {
|
|
17
17
|
// WRONG
|
|
18
|
-
const a = ask with "fast" `a rough summary
|
|
19
|
-
const b = ask with provider.fast `a rough summary
|
|
18
|
+
const a = ask with "fast" `a rough summary`: string;
|
|
19
|
+
const b = ask with provider.fast `a rough summary`: string;
|
|
20
20
|
|
|
21
21
|
// RIGHT — name it in nola.config.ts, then use that name
|
|
22
|
-
const c = ask with fast `a rough summary
|
|
22
|
+
const c = ask with fast `a rough summary`: string;
|
|
23
23
|
|
|
24
24
|
// RIGHT — dynamic choice
|
|
25
|
-
const d = ask (..`a rough summary
|
|
25
|
+
const d = ask (..`a rough summary`: string).withModel(useFast ? "fast" : "careful");
|
|
26
26
|
|
|
27
27
|
return { a, b, c, d };
|
|
28
28
|
}
|
|
@@ -53,28 +53,27 @@ function summarize(.text: string) {
|
|
|
53
53
|
|
|
54
54
|
// RIGHT
|
|
55
55
|
export infer function summarize(.text: string) {
|
|
56
|
-
return ask `a one-sentence summary
|
|
56
|
+
return ask `a one-sentence summary`: string;
|
|
57
57
|
}
|
|
58
58
|
```
|
|
59
59
|
|
|
60
60
|
If the function is genuinely plain TypeScript, drop the `.`; the parameter is
|
|
61
61
|
an ordinary argument.
|
|
62
62
|
|
|
63
|
-
##
|
|
63
|
+
## NOLA1019 — the marker slot is reserved
|
|
64
64
|
|
|
65
|
-
>
|
|
65
|
+
> the marker after an infer function's name is reserved for a future Nola version — write the instruction as a context statement in the body: `…`.
|
|
66
66
|
|
|
67
67
|
```tsi
|
|
68
|
-
// WRONG —
|
|
68
|
+
// WRONG — the instruction in the reserved slot
|
|
69
69
|
export infer function f`be terse`(.t: string) {
|
|
70
|
-
`
|
|
71
|
-
return ask `the kind`<string>;
|
|
70
|
+
return ask `the kind`: string;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
|
-
// RIGHT —
|
|
73
|
+
// RIGHT — a context statement in the body
|
|
75
74
|
export infer function f(.t: string) {
|
|
76
75
|
`be terse`
|
|
77
|
-
return ask `the kind
|
|
76
|
+
return ask `the kind`: string;
|
|
78
77
|
}
|
|
79
78
|
```
|
|
80
79
|
|
|
@@ -89,16 +88,16 @@ infer function — nor in a class field initializer or `static` block.
|
|
|
89
88
|
|
|
90
89
|
```tsi
|
|
91
90
|
// WRONG
|
|
92
|
-
const g = async () => ask `the kind
|
|
91
|
+
const g = async () => ask `the kind`: string; // plain closure
|
|
93
92
|
|
|
94
93
|
export infer function f(.t: string) {
|
|
95
|
-
const h = () => ask `the kind
|
|
94
|
+
const h = () => ask `the kind`: string; // nested closure
|
|
96
95
|
return h();
|
|
97
96
|
}
|
|
98
97
|
|
|
99
98
|
// RIGHT — ask directly in the body, or at the top level of the module
|
|
100
99
|
export infer function f(.t: string) {
|
|
101
|
-
return ask `the kind
|
|
100
|
+
return ask `the kind`: string;
|
|
102
101
|
}
|
|
103
102
|
export const kind = ask f("…");
|
|
104
103
|
```
|
|
@@ -107,32 +106,165 @@ Constructing an extractor outside a body is fine — only resolving it is
|
|
|
107
106
|
restricted:
|
|
108
107
|
|
|
109
108
|
```tsi
|
|
110
|
-
export const nameIntent = ..`the user's full name
|
|
109
|
+
export const nameIntent = ..`the user's full name`: string; // legal, inert
|
|
111
110
|
```
|
|
112
111
|
|
|
113
|
-
## NOLA2014 — a typed template outside `ask` needs the dots
|
|
112
|
+
## NOLA2014 — a typed template outside `ask` and a call's slots needs the dots
|
|
114
113
|
|
|
115
|
-
> a typed template literal is an extractor only directly after `ask
|
|
114
|
+
> a typed template literal is an extractor only directly after `ask` or in a call's argument list; write ..`…`<T> here.
|
|
116
115
|
|
|
117
|
-
The `..` is implied
|
|
118
|
-
|
|
116
|
+
The `..` is implied directly after `ask` and in a call's slots (an argument,
|
|
117
|
+
or a value nested in plain object/array literals there). Anywhere else a bare
|
|
118
|
+
template is an ordinary string, so an extractor there needs its sigil. The
|
|
119
|
+
code is raised for the angle-bracket spelling; a colon-typed template in such
|
|
120
|
+
a place (`` const stored = `the user's full name`: string ``) is a plain
|
|
121
|
+
syntax error instead:
|
|
119
122
|
|
|
120
123
|
```tsi
|
|
121
124
|
declare function createTicket(title: string): Promise<string>;
|
|
122
125
|
|
|
123
126
|
infer function file(.request: string) {
|
|
124
|
-
const wrong =
|
|
125
|
-
const right = ask createTicket(
|
|
127
|
+
const wrong = `a short title`<string>; // NOLA2014 — stored: dots required
|
|
128
|
+
const right = ask createTicket(`a short title`: string); // a slot: the dots are implied
|
|
126
129
|
return right;
|
|
127
130
|
}
|
|
128
|
-
export const stored = ..`the user's full name
|
|
131
|
+
export const stored = ..`the user's full name`: string; // stored: dots required
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## NOLA1018 — a colon type with nothing on its line
|
|
135
|
+
|
|
136
|
+
> expected a type after the extractor's `:` on the same line — write `…`: T.
|
|
137
|
+
|
|
138
|
+
The colon spelling `` ask `the ticket id`: string `` takes the colon glued,
|
|
139
|
+
spaced or on the next line (`` `p` : string `` and `` `p`\n : string `` are the
|
|
140
|
+
same ask — a line break alone never ends an ask) and needs the type on the
|
|
141
|
+
colon's line. Two more traps come with it, both from the type having no
|
|
142
|
+
closing delimiter:
|
|
143
|
+
|
|
144
|
+
```tsi
|
|
145
|
+
interface User { name: string }
|
|
146
|
+
|
|
147
|
+
infer function f(.doc: string) {
|
|
148
|
+
const a = ask `the user`: User.withRetry(2); // the TYPE `User.withRetry`, called with 2 — TS error
|
|
149
|
+
const b = ask `the user`<User>.withRetry(2); // RIGHT
|
|
150
|
+
const c = ask `the tags`: string[].withRetry(2); // RIGHT — a delimited type ends the type
|
|
151
|
+
return { b, c };
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
A bare type name followed by `.` continues as a qualified type name, and `<`
|
|
156
|
+
after a type name opens type arguments (`` `n`: User < 5 `` is not a
|
|
157
|
+
comparison). Chain intent methods after a parenthesized extractor
|
|
158
|
+
(`` ask (..`the user`: User).withRetry(2) ``), after a delimited type
|
|
159
|
+
(`string[]`, `Array<User>`, `{…}`, `(User)`), or after `<T>`.
|
|
160
|
+
|
|
161
|
+
## NOLA1020 — a value in a context statement must be simple
|
|
162
|
+
|
|
163
|
+
> a value in a context statement is a name, a call or a bracketed expression,
|
|
164
|
+
> followed by text or the end of the statement — wrap anything else in
|
|
165
|
+
> parentheses, or assign it to a local first (`await`, `ask` and `this` cannot
|
|
166
|
+
> be values).
|
|
167
|
+
|
|
168
|
+
The same code, with ask-site wording, covers an ask sequence: `this`,
|
|
169
|
+
`await`, `ask`, `function` or `class` where a value would start after a
|
|
170
|
+
text, a value ending in a backtick (`` ask `p` new Foo `more` ``), and text
|
|
171
|
+
after the type (`` ask `p`: T `more` `` — the type ends the sequence; move
|
|
172
|
+
the text before `: T`).
|
|
173
|
+
|
|
174
|
+
```tsi
|
|
175
|
+
export infer function total(.items: string[], a: number, b: number) {
|
|
176
|
+
// WRONG — an operator after a value
|
|
177
|
+
`total` a + b `items`;
|
|
178
|
+
// RIGHT
|
|
179
|
+
`total` (a + b) `items`;
|
|
180
|
+
return ask `a summary`: string;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`this` is the same kind of mistake: an item is a hoisted function of its own,
|
|
185
|
+
so its `this` is not the infer function's. A bare `this` after text is
|
|
186
|
+
NOLA1020; in parentheses or in a `${}` hole it is TS2683 in `nola check` and
|
|
187
|
+
the editor (and `undefined` at run time). Assign it to a local first:
|
|
188
|
+
|
|
189
|
+
```tsi
|
|
190
|
+
export infer function greet(this: { user: string }) {
|
|
191
|
+
// WRONG — NOLA1020 (bare `this`); `(this.user)` and `${this.user}` are TS2683
|
|
192
|
+
`Greet` this.user `warmly.`;
|
|
193
|
+
// RIGHT — a local, then its name
|
|
194
|
+
const user = this.user;
|
|
195
|
+
`Greet` user `warmly.`;
|
|
196
|
+
return ask `a one-line greeting`: string;
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Also:
|
|
201
|
+
|
|
202
|
+
- A value never ends with a backtick: `` `x` foo<string> `more` `` and
|
|
203
|
+
`` `x` new Foo `more` `` are NOLA1020 too (the text would be read as a
|
|
204
|
+
tagged template) — write `(foo<string>)`, `(new Foo)` or `new Foo()`.
|
|
205
|
+
- `typeof`, `void`, `await`, `ask`, `this`, `..`, `function` and `class`
|
|
206
|
+
right after text are NOLA1020. Parenthesize `typeof`, `void`, functions and
|
|
207
|
+
classes. `await`, `ask` and `this` cannot be values even in parentheses (an
|
|
208
|
+
item is read at each ask, outside the async body, in a function of its own:
|
|
209
|
+
`(await x)` is TS1308, `(this.x)` is TS2683, `(ask …)` is NOLA2010) —
|
|
210
|
+
compute the value into a `const` first and write its name.
|
|
211
|
+
- A NAME at the start of a line begins a new statement (JavaScript's own
|
|
212
|
+
rule), so `` `analyze` `` on one line and `foo(x)` on the next are a context
|
|
213
|
+
statement and a call. Keep values on the text's line, or start the line with
|
|
214
|
+
`(` or `[`.
|
|
215
|
+
- The mirror image: a CODE line that starts with `[` or `(` right after a
|
|
216
|
+
context statement continues it and becomes its value — no error, but
|
|
217
|
+
whatever the code returns (`undefined` for a `forEach`) lands in the
|
|
218
|
+
prompt, and the code runs at every ask. End the context statement with
|
|
219
|
+
`;`.
|
|
220
|
+
|
|
221
|
+
## An operator after the text is not a context statement
|
|
222
|
+
|
|
223
|
+
No diagnostic: `` `Page ` + oncall `` is ordinary JavaScript — a string
|
|
224
|
+
concatenation whose result is dropped — so the model never sees it.
|
|
225
|
+
|
|
226
|
+
```tsi
|
|
227
|
+
export infer function page(.ticket: string, oncall: string) {
|
|
228
|
+
// WRONG — plain concatenation, nothing reaches the model
|
|
229
|
+
`Page ` + oncall + ` when the ticket is an outage.`;
|
|
230
|
+
// RIGHT — juxtapose the parts, or use a hole
|
|
231
|
+
`Page` oncall `when the ticket is an outage.`;
|
|
232
|
+
`Page ${oncall} when the ticket is an outage.`;
|
|
233
|
+
return ask `the severity`: string;
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## NOLA2017 — a context statement outside a scope body
|
|
238
|
+
|
|
239
|
+
> a context statement is only legal in a scope body — directly in an infer
|
|
240
|
+
> function or at module level.
|
|
241
|
+
|
|
242
|
+
> a context statement cannot be the unbraced body of an `if`, a loop or a
|
|
243
|
+
> label — wrap it in braces.
|
|
244
|
+
|
|
245
|
+
```tsi
|
|
246
|
+
export infer function go(.items: string[], urgent: boolean) {
|
|
247
|
+
// WRONG — inside a callback, no ask can carry it
|
|
248
|
+
items.forEach((it) => {
|
|
249
|
+
`note` it;
|
|
250
|
+
});
|
|
251
|
+
// WRONG — an unbraced body
|
|
252
|
+
if (urgent) `Answer quickly.`;
|
|
253
|
+
// RIGHT — directly in the body, before the asks that should see it
|
|
254
|
+
`items:` items;
|
|
255
|
+
return ask `a summary`: string;
|
|
256
|
+
}
|
|
129
257
|
```
|
|
130
258
|
|
|
259
|
+
A class `static` block and a namespace body are outside a scope body too.
|
|
260
|
+
Inside braces (`if (urgent) { … }`) a context statement is legal and applies
|
|
261
|
+
to the asks inside them.
|
|
262
|
+
|
|
131
263
|
## NOLA2002 — a type the compiler cannot turn into a schema
|
|
132
264
|
|
|
133
265
|
> unsupported type for intent schema: …
|
|
134
266
|
|
|
135
|
-
An extractor's
|
|
267
|
+
An extractor's type must RESOLVE to a JSON-shaped value — the TypeScript
|
|
136
268
|
checker decides, so unions (`Refund | Chargeback`, `string | null`),
|
|
137
269
|
`Partial<T>` / `Pick` / `Omit`, `interface … extends`, intersections,
|
|
138
270
|
`Record<string, T>`, tuples, generics applied with arguments and types from
|
|
@@ -143,16 +275,16 @@ functions and a generic declaration used without arguments (`Box<T>` — write
|
|
|
143
275
|
```tsi
|
|
144
276
|
export infer function tally(.doc: string) {
|
|
145
277
|
// WRONG
|
|
146
|
-
const wrong = ask `counts per label
|
|
278
|
+
const wrong = ask `counts per label`: Map<string, number>;
|
|
147
279
|
|
|
148
280
|
// RIGHT — a JSON-shaped type; convert afterwards in plain TS
|
|
149
|
-
const counts = ask `counts per label
|
|
281
|
+
const counts = ask `counts per label`: { label: string; count: number }[];
|
|
150
282
|
const asMap = new Map(counts.map((c) => [c.label, c.count]));
|
|
151
283
|
return asMap;
|
|
152
284
|
}
|
|
153
285
|
```
|
|
154
286
|
|
|
155
|
-
Always give an extractor a concrete
|
|
287
|
+
Always give an extractor a concrete type in an expression position. An
|
|
156
288
|
extractor is a value-producing expression; it is not a statement, a type, or a
|
|
157
289
|
declaration.
|
|
158
290
|
|
|
@@ -169,18 +301,18 @@ values are serialized into the prompt.
|
|
|
169
301
|
```tsi
|
|
170
302
|
// WRONG
|
|
171
303
|
export infer function topLabel(.index: Map<string, number>) {
|
|
172
|
-
return ask `the label with the highest count
|
|
304
|
+
return ask `the label with the highest count`: string;
|
|
173
305
|
}
|
|
174
306
|
|
|
175
307
|
// RIGHT — pass a JSON-shaped view as the contextual parameter
|
|
176
308
|
export infer function topLabel(.index: { label: string; count: number }[]) {
|
|
177
|
-
return ask `the label with the highest count
|
|
309
|
+
return ask `the label with the highest count`: string;
|
|
178
310
|
}
|
|
179
311
|
|
|
180
312
|
// RIGHT — keep the exotic value, but as a PLAIN parameter (the LLM never
|
|
181
313
|
// sees its value, so nothing needs deriving)
|
|
182
314
|
export infer function topLabel(.summary: string, index: Map<string, number>) {
|
|
183
|
-
const label = ask `the label with the highest count
|
|
315
|
+
const label = ask `the label with the highest count`: string;
|
|
184
316
|
return { label, count: index.get(label) ?? 0 };
|
|
185
317
|
}
|
|
186
318
|
```
|
|
@@ -199,9 +331,9 @@ export default defineConfig({
|
|
|
199
331
|
Keep that value a literal — the editor reads it statically and never executes
|
|
200
332
|
your config.
|
|
201
333
|
|
|
202
|
-
## NOLA2004 — a call-intent slot with no
|
|
334
|
+
## NOLA2004 — a call-intent slot with no type
|
|
203
335
|
|
|
204
|
-
> an extractor used as a call-intent argument must have an explicit
|
|
336
|
+
> an extractor used as a call-intent argument must have an explicit type — write ..`…`: T here.
|
|
205
337
|
|
|
206
338
|
```tsi
|
|
207
339
|
declare function createTicket(title: string, priority: number): Promise<string>;
|
|
@@ -210,12 +342,111 @@ export infer function fileTicket(.request: string) {
|
|
|
210
342
|
// WRONG — the slot has no type
|
|
211
343
|
const wrong = ask createTicket(..`a short ticket title`, 2);
|
|
212
344
|
|
|
213
|
-
// RIGHT
|
|
214
|
-
const id = ask createTicket(
|
|
345
|
+
// RIGHT (the slot's `..` is implied; `..`a short ticket title`: string` works too)
|
|
346
|
+
const id = ask createTicket(`a short ticket title`: string, 2);
|
|
215
347
|
return id;
|
|
216
348
|
}
|
|
217
349
|
```
|
|
218
350
|
|
|
351
|
+
A bare template with no type, `` createTicket(`a short ticket title`, 2) ``,
|
|
352
|
+
is not a slot at all: it is a plain string argument and the call stays an
|
|
353
|
+
ordinary call — no error, and no model request.
|
|
354
|
+
|
|
355
|
+
## NOLA1021 / NOLA1022 — a tool list holds functions
|
|
356
|
+
|
|
357
|
+
> a tool list holds functions — a name, a member, an expression that is one function, or a group (a module or an object of functions, an array of them), bare or spread; a literal cannot be one, and the list is not empty.
|
|
358
|
+
|
|
359
|
+
The brackets after an ask's template are a TOOL LIST (tool use). An entry is
|
|
360
|
+
a value: a name or dotted chain (one function, or a group — a module, an
|
|
361
|
+
object of functions, an array of them), a spread of a group, or an
|
|
362
|
+
expression that is one function. A literal (a string, a number, an arrow,
|
|
363
|
+
an object or array literal) or an empty list is NOLA1021, and a call written
|
|
364
|
+
in the list — describing the arguments in place — is reserved (NOLA1022):
|
|
365
|
+
|
|
366
|
+
```tsi
|
|
367
|
+
// not-checked — WRONG
|
|
368
|
+
const a = ask `find the files` [searchFiles, "readFile"]: string[]; // NOLA1021
|
|
369
|
+
const b = ask `get the user` [getUser(`the id`: string)]: User; // NOLA1022 — reserved
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
```tsi
|
|
373
|
+
// RIGHT
|
|
374
|
+
const a = ask `find the files` [searchFiles, fs.readFile]: string[];
|
|
375
|
+
const g = ask `find the files` [fileTools, ...moreTools]: string[]; // a group by name, a group flattened
|
|
376
|
+
const b = ask `get the user` [getUser]: User; // the arguments come from getUser's signature
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## NOLA1023 — a typed ask in a ternary's consequent
|
|
380
|
+
|
|
381
|
+
> a typed extractor directly in a ternary's consequent — parenthesize it: `cond ? (ask `p`: T) : y`.
|
|
382
|
+
|
|
383
|
+
Two colons with different meanings would sit side by side, so the typed ask
|
|
384
|
+
goes in parentheses (an untyped ask, a call intent and the `<T>` form need
|
|
385
|
+
none; the alternate position is free):
|
|
386
|
+
|
|
387
|
+
```tsi
|
|
388
|
+
// not-checked — WRONG
|
|
389
|
+
const t = cond ? ask `the title`: string : "untitled";
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
```tsi
|
|
393
|
+
// RIGHT
|
|
394
|
+
const t = cond ? (ask `the title`: string) : "untitled";
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
## NOLA2018 — a tool list entry the compiler cannot use
|
|
398
|
+
|
|
399
|
+
An entry that is neither one function nor a group (a value, a type-only
|
|
400
|
+
import, a class, a union of function types — `const f = cond ? a : b` —
|
|
401
|
+
`any`), a function under a spread, a group reached through an expression
|
|
402
|
+
(`[groups[0]]` — name it or spread it), a method reached through a call
|
|
403
|
+
(`api.client().search` — name the object first), a group with nothing
|
|
404
|
+
callable, or
|
|
405
|
+
two tools that would share one name on the wire (`a.b` beside `a_b`; the
|
|
406
|
+
same function twice; a spread's `search` beside another). Name a function
|
|
407
|
+
or a group, keep the names distinct, offer colliding groups bare so their
|
|
408
|
+
names carry the prefix. A parameter the walk cannot derive — a rest
|
|
409
|
+
parameter, a `Map`, a generic parameter — is NOLA2002 at the entry; a group
|
|
410
|
+
member the walk cannot use fails the group, naming the member.
|
|
411
|
+
|
|
412
|
+
## NOLA2019 — a reserved shape of the ask sequence
|
|
413
|
+
|
|
414
|
+
Tools beside a call: `` ask `use` [searchFiles] `then` createUser(`id`: string) ``
|
|
415
|
+
is the kind where the loop runs and the call's slots are the answer —
|
|
416
|
+
designed, not built. Offer the function as a tool, or make the call its own
|
|
417
|
+
ask after the tool-use ask. Also a `..` sequence inside a call's slot
|
|
418
|
+
(`` fn(..`t` user: string) ``): a slot's instruction is one text.
|
|
419
|
+
|
|
420
|
+
## NOLA2020 — an ask sequence that cannot mean one thing
|
|
421
|
+
|
|
422
|
+
Two calls with typed slots (an ask makes one call — split the asks); a
|
|
423
|
+
`: T` beside a call (the call's result is the type — drop it); text after
|
|
424
|
+
a bare call (`` ask f(`x`: string) `more` `` — put the words first:
|
|
425
|
+
`` ask `more` f(`x`: string) ``); a call with typed slots inside a data
|
|
426
|
+
value (`` ask `use` (createUser(`id`: string)) `go`: T `` — write it bare
|
|
427
|
+
between texts, it is the action, not data).
|
|
428
|
+
|
|
429
|
+
## NOLA3019 – NOLA3022 — tool use at run time
|
|
430
|
+
|
|
431
|
+
- NOLA3019: the resolved model cannot request tool calls (a hand-written
|
|
432
|
+
`LanguageModel`, a mock without `{ tools: true }`, `typesafe()`, a vendor
|
|
433
|
+
model with `toolUse: false`). Route the
|
|
434
|
+
ask to `openai` / `anthropic` / `google` / `"nola"`, or brand the mock.
|
|
435
|
+
Refused before the network.
|
|
436
|
+
- NOLA3020: the model kept calling tools past the cap (`.withMaxTurns(n)`,
|
|
437
|
+
else `ask.maxTurns`, 10). Raise the cap, give it tools that answer in fewer
|
|
438
|
+
calls, or sharpen the task. Definitive; the transcript rides the error.
|
|
439
|
+
- NOLA3021: a tool threw. Fix the tool, or return the failure as a value
|
|
440
|
+
when the model should recover from it. Invalid arguments never reach the
|
|
441
|
+
function — they go back to the model as that call's result.
|
|
442
|
+
- NOLA3022: the list could not be built when the ask ran — a value that is
|
|
443
|
+
not what its type promised (a group member that is not a function, a
|
|
444
|
+
tuple of another length), a function with no name (an anonymous arrow in
|
|
445
|
+
an array), or two tools with one wire name. Before the network.
|
|
446
|
+
|
|
447
|
+
`.withRetry(n)` on a tool-use ask re-runs the WHOLE loop, tools included:
|
|
448
|
+
only with tools that are safe to repeat.
|
|
449
|
+
|
|
219
450
|
## NOLA3010 — bare `await` on a raw extract or call intent
|
|
220
451
|
|
|
221
452
|
> extract/call intents carry no construction scope — only `ask` supplies their
|
|
@@ -285,7 +516,7 @@ import { Person } from "./models.js"; // WRONG — kept at run time; mod
|
|
|
285
516
|
|
|
286
517
|
`__nola` and any identifier starting with `__nola` are reserved in `.tsi`.
|
|
287
518
|
`__nola.ask(...)`, `__nola.intents.ExtractIntent(...)`, `__nola.types.string()`
|
|
288
|
-
and `
|
|
519
|
+
and `__nola_module_ctx()` are what the compiler EMITS — they are not an API you
|
|
289
520
|
call, and writing them by hand is an error.
|
|
290
521
|
|
|
291
522
|
```tsi
|
|
@@ -297,36 +528,58 @@ export infer function read(.doc: string) {
|
|
|
297
528
|
);
|
|
298
529
|
|
|
299
530
|
// RIGHT
|
|
300
|
-
const v = ask `the value
|
|
531
|
+
const v = ask `the value`: string;
|
|
301
532
|
return v;
|
|
302
533
|
}
|
|
303
534
|
```
|
|
304
535
|
|
|
305
|
-
##
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
536
|
+
## NOLA2010 — a Nola construct inside a context statement or a hole
|
|
537
|
+
|
|
538
|
+
> Nola constructs are not allowed inside a context statement or an instruction
|
|
539
|
+
> literal's hole; a hinted call intent used as a value must be parenthesized.
|
|
540
|
+
|
|
541
|
+
A context statement is read at each ask, outside the async body, and call
|
|
542
|
+
hints are re-emitted from source, so `ask` and `..` cannot appear in a context
|
|
543
|
+
statement's parenthesized value, bracketed value or `${}` hole, nor in a call
|
|
544
|
+
hint's hole (written bare right after the text, they are NOLA1020). A call
|
|
545
|
+
intent is a legal value, but a HINTED one, `` fn`hint`(…) ``, must be
|
|
546
|
+
parenthesized or written in a `${}` hole (an empty marker too): bare, the
|
|
547
|
+
backtick after `fn` is read as the next text part and the arguments as a
|
|
548
|
+
value of their own, so it is no call intent — a `` ..`x`: T `` in the
|
|
549
|
+
arguments is left as a bare extractor, and that is this error (a `` `x`: T ``
|
|
550
|
+
there is a syntax error at its colon, since a parenthesized group has no
|
|
551
|
+
slots); plain arguments may raise no error at all and render the wrong text.
|
|
552
|
+
A sigil-less call intent (`` fn(`x`: T) ``) needs no parentheses. Otherwise
|
|
553
|
+
compute the value first and interpolate the result, or move the ask into the
|
|
554
|
+
function body.
|
|
310
555
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
556
|
+
```tsi
|
|
557
|
+
declare function escalate(team: string): void;
|
|
558
|
+
|
|
559
|
+
export infer function route(.ticket: string) {
|
|
560
|
+
// WRONG — the hint's backtick starts the next text part: NOLA2010 at the extractor
|
|
561
|
+
`If the ticket is an outage,` escalate`page the on-call engineer`(..`the team to page`: string);
|
|
562
|
+
// RIGHT — parenthesized (or written in a `${}` hole)
|
|
563
|
+
`If the ticket is an outage,` (escalate`page the on-call engineer`(`the team to page`: string));
|
|
564
|
+
// RIGHT — no hint, no parentheses
|
|
565
|
+
`If the ticket is an outage,` escalate(`the team to page`: string);
|
|
566
|
+
return ask `the label for the ticket`: string;
|
|
567
|
+
}
|
|
568
|
+
```
|
|
316
569
|
|
|
317
|
-
##
|
|
570
|
+
## NOLA3015 — the Node loader under Bun or Deno
|
|
318
571
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
572
|
+
`nola run` and `node --import nola-lang/register` ARE Node's module-hooks API;
|
|
573
|
+
Bun and Deno do not run them. On Bun, run `.tsi` from source through
|
|
574
|
+
`@nola-lang/bun` instead: `preload = ["@nola-lang/bun/preload"]` in
|
|
575
|
+
`bunfig.toml`, then `bun src/main.tsi` (see config.md, "Running on Bun").
|
|
576
|
+
Deno cannot load `.tsi` at all — run on Node. Any package manager is fine
|
|
577
|
+
(`bun install`, `bun run start`: the `nola` bin is a Node script).
|
|
322
578
|
|
|
323
|
-
##
|
|
579
|
+
## NOLA3023 — Bun older than 1.3
|
|
324
580
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
the `nola` bin is a Node script), but `bun --bun`, `bun src/main.ts` and
|
|
328
|
-
`deno run` cannot load `.tsi`. Run on Node: `nola run` or
|
|
329
|
-
`node --import nola-lang/register src/main.ts`.
|
|
581
|
+
`@nola-lang/bun` needs `process.getBuiltinModule` (Bun ≥ 1.3). Run
|
|
582
|
+
`bun upgrade`.
|
|
330
583
|
|
|
331
584
|
## Other things that will not parse
|
|
332
585
|
|
|
@@ -336,3 +589,12 @@ the `nola` bin is a Node script), but `bun --bun`, `bun src/main.ts` and
|
|
|
336
589
|
- `infer` on a method, arrow function or function expression — top-level
|
|
337
590
|
function declarations only.
|
|
338
591
|
- `fn(..)` — the bare derive-all call form is reserved (NOLA1004).
|
|
592
|
+
- `` cond ? ask `p` : y `` — a colon on the extractor's line is its type,
|
|
593
|
+
spaced or glued, so the ask reads `y` as its type and the ternary loses its
|
|
594
|
+
alternate: NOLA1023. A typed ask standing bare as a consequent is the same
|
|
595
|
+
code — parenthesize it: `` cond ? (ask `p`: T) : y ``, on one line or
|
|
596
|
+
three: the formatted `` cond\n ? ask `p`\n : y `` reads `y` as the type
|
|
597
|
+
too, since a line break alone never ends an ask.
|
|
598
|
+
- `` fn(`x` [tools]: T) `` — a tool list is never a call slot; a bracket
|
|
599
|
+
there keeps its JavaScript meaning. The list goes on the ask site or the
|
|
600
|
+
stored `..` form only.
|