create-nola-lang 0.1.8 → 0.1.9
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/dist/{chunk-GUYF4NM5.js → chunk-KCGD4VJM.js} +15 -8
- package/dist/flow.js +13 -7
- package/dist/index.js +1 -1
- package/dist/main.js +1 -1
- package/dist/registry.d.ts +10 -0
- package/dist/registry.js +6 -0
- package/package.json +1 -1
- package/skills/nola/references/config.md +11 -4
|
@@ -151,7 +151,13 @@ var TEMPLATES = [
|
|
|
151
151
|
{ name: "extract-invoice", label: "same-file type references, optional fields", source: "example" },
|
|
152
152
|
{ name: "classify-message", label: "closed label sets: union alias, string enum, inline union", source: "example" },
|
|
153
153
|
{ name: "chain-of-thought", label: "two asks sharing accumulating context", source: "example" },
|
|
154
|
-
{ name: "research-notes", label: "TS control flow orchestrating nola functions", source: "example" }
|
|
154
|
+
{ name: "research-notes", label: "TS control flow orchestrating nola functions", source: "example" },
|
|
155
|
+
{
|
|
156
|
+
name: "triage-ticket",
|
|
157
|
+
label: "ticket triage: literal unions and booleans as typed questions; no provider question",
|
|
158
|
+
source: "example",
|
|
159
|
+
provider: { label: "typesafe.ai", envVar: "TYPESAFE_API_KEY" }
|
|
160
|
+
}
|
|
155
161
|
];
|
|
156
162
|
function templateByName(name) {
|
|
157
163
|
return TEMPLATES.find((t) => t.name === name);
|
|
@@ -1465,7 +1471,8 @@ var EDITOR_OPTIONS = [
|
|
|
1465
1471
|
{ value: "vscode", label: "VS Code", hint: ".vscode/ with a debug launch config + extension recommendation" }
|
|
1466
1472
|
];
|
|
1467
1473
|
function templateOption(t) {
|
|
1468
|
-
|
|
1474
|
+
const vendor = t.provider ? ` (${t.provider.label})` : "";
|
|
1475
|
+
return { value: t.name, label: t.source === "example" ? `example: ${t.name}${vendor}` : `${t.name}${vendor}`, hint: t.label };
|
|
1469
1476
|
}
|
|
1470
1477
|
async function resolveSetup(input, prompter, dir) {
|
|
1471
1478
|
const ide = input.ide === "vscode" || input.ide === "none" ? input.ide : void 0;
|
|
@@ -1519,10 +1526,10 @@ function flaggedProvider(input) {
|
|
|
1519
1526
|
}
|
|
1520
1527
|
return input.provider;
|
|
1521
1528
|
}
|
|
1522
|
-
async function resolveProvider(input, prompter) {
|
|
1529
|
+
async function resolveProvider(input, prompter, pinned = false) {
|
|
1523
1530
|
const flagged = flaggedProvider(input);
|
|
1524
1531
|
if (flagged !== void 0) return flagged;
|
|
1525
|
-
if (!input.interactive) return "none";
|
|
1532
|
+
if (pinned || !input.interactive) return "none";
|
|
1526
1533
|
const path = input.keyPath ?? { kind: "trial" };
|
|
1527
1534
|
while (true) {
|
|
1528
1535
|
const choice = await prompter.select(PROVIDER_QUESTION, providerOptions(path));
|
|
@@ -1532,8 +1539,8 @@ async function resolveProvider(input, prompter) {
|
|
|
1532
1539
|
return choice;
|
|
1533
1540
|
}
|
|
1534
1541
|
}
|
|
1535
|
-
async function resolveExtras(input, prompter, dir) {
|
|
1536
|
-
const provider = await resolveProvider(input, prompter);
|
|
1542
|
+
async function resolveExtras(input, prompter, dir, pinnedProvider = false) {
|
|
1543
|
+
const provider = await resolveProvider(input, prompter, pinnedProvider);
|
|
1537
1544
|
if (provider === null) return null;
|
|
1538
1545
|
const setup = await resolveSetup(input, prompter, dir);
|
|
1539
1546
|
return setup === null ? null : { provider, ...setup };
|
|
@@ -1630,7 +1637,7 @@ async function resolveScaffoldOptions(input, prompter) {
|
|
|
1630
1637
|
template = choice;
|
|
1631
1638
|
}
|
|
1632
1639
|
}
|
|
1633
|
-
const extras = await resolveExtras(input, prompter, dir);
|
|
1640
|
+
const extras = await resolveExtras(input, prompter, dir, templateByName(template)?.provider !== void 0);
|
|
1634
1641
|
if (extras === null) return { kind: "cancelled" };
|
|
1635
1642
|
return { kind: "scaffold", dir, template, force, ...extras };
|
|
1636
1643
|
}
|
|
@@ -1679,7 +1686,7 @@ function commented(command, note) {
|
|
|
1679
1686
|
}
|
|
1680
1687
|
function nextSteps(outcome, fileCount, name, pm, installed = false, grant = null) {
|
|
1681
1688
|
const cmd = packageManagerCommands(pm);
|
|
1682
|
-
const vendorEnv = providerById(outcome.provider)?.envVar;
|
|
1689
|
+
const vendorEnv = providerById(outcome.provider)?.envVar ?? (outcome.provider === "none" ? templateByName(outcome.template)?.provider?.envVar : void 0);
|
|
1683
1690
|
const startNote = grant ? grant.source === "trial" ? "25 free Nola runs \u2014 key in .env" : "key in .env (run `npx nola-lang account` to check the balance)" : vendorEnv ? `set ${vendorEnv} in .env first` : outcome.template === "empty" ? "set OPENAI_API_KEY first" : "runs offline \u2014 no API key needed";
|
|
1684
1691
|
const lines = [
|
|
1685
1692
|
...outcome.dir === "." ? [] : [`cd ${outcome.dir}`],
|
package/dist/flow.js
CHANGED
|
@@ -46,7 +46,9 @@ const EDITOR_OPTIONS = [
|
|
|
46
46
|
{ value: "vscode", label: "VS Code", hint: ".vscode/ with a debug launch config + extension recommendation" },
|
|
47
47
|
];
|
|
48
48
|
function templateOption(t) {
|
|
49
|
-
|
|
49
|
+
// a pinned template names its vendor in the row itself: `example: triage-ticket (typesafe.ai)`
|
|
50
|
+
const vendor = t.provider ? ` (${t.provider.label})` : "";
|
|
51
|
+
return { value: t.name, label: t.source === "example" ? `example: ${t.name}${vendor}` : `${t.name}${vendor}`, hint: t.label };
|
|
50
52
|
}
|
|
51
53
|
/**
|
|
52
54
|
* The setup step: a yes/no gate (default yes), then editor + coding agents in
|
|
@@ -133,11 +135,13 @@ function flaggedProvider(input) {
|
|
|
133
135
|
* one Enter away, Ctrl+C cancels). The key itself is minted later, on the
|
|
134
136
|
* stored session, after every question — nothing is consumed by a cancel.
|
|
135
137
|
*/
|
|
136
|
-
async function resolveProvider(input, prompter) {
|
|
138
|
+
async function resolveProvider(input, prompter, pinned = false) {
|
|
137
139
|
const flagged = flaggedProvider(input);
|
|
138
140
|
if (flagged !== undefined)
|
|
139
141
|
return flagged;
|
|
140
|
-
|
|
142
|
+
// A template whose own config names its vendor (triage-ticket → typesafe())
|
|
143
|
+
// is not asked: "none" keeps that config, and the outro names its env var.
|
|
144
|
+
if (pinned || !input.interactive)
|
|
141
145
|
return "none";
|
|
142
146
|
const path = input.keyPath ?? { kind: "trial" };
|
|
143
147
|
while (true) {
|
|
@@ -152,8 +156,8 @@ async function resolveProvider(input, prompter) {
|
|
|
152
156
|
}
|
|
153
157
|
}
|
|
154
158
|
/** The provider and setup (editor + agents) questions, in that order, shared by every outcome site; null = cancelled. */
|
|
155
|
-
async function resolveExtras(input, prompter, dir) {
|
|
156
|
-
const provider = await resolveProvider(input, prompter);
|
|
159
|
+
async function resolveExtras(input, prompter, dir, pinnedProvider = false) {
|
|
160
|
+
const provider = await resolveProvider(input, prompter, pinnedProvider);
|
|
157
161
|
if (provider === null)
|
|
158
162
|
return null;
|
|
159
163
|
const setup = await resolveSetup(input, prompter, dir);
|
|
@@ -263,7 +267,7 @@ export async function resolveScaffoldOptions(input, prompter) {
|
|
|
263
267
|
template = choice;
|
|
264
268
|
}
|
|
265
269
|
}
|
|
266
|
-
const extras = await resolveExtras(input, prompter, dir);
|
|
270
|
+
const extras = await resolveExtras(input, prompter, dir, templateByName(template)?.provider !== undefined);
|
|
267
271
|
if (extras === null)
|
|
268
272
|
return { kind: "cancelled" };
|
|
269
273
|
return { kind: "scaffold", dir, template, force, ...extras };
|
|
@@ -320,7 +324,9 @@ function commented(command, note) {
|
|
|
320
324
|
}
|
|
321
325
|
function nextSteps(outcome, fileCount, name, pm, installed = false, grant = null) {
|
|
322
326
|
const cmd = packageManagerCommands(pm);
|
|
323
|
-
|
|
327
|
+
// a chosen vendor's env var, else the one the template's own config reads (a pinned template under "none")
|
|
328
|
+
const vendorEnv = providerById(outcome.provider)?.envVar ??
|
|
329
|
+
(outcome.provider === "none" ? templateByName(outcome.template)?.provider?.envVar : undefined);
|
|
324
330
|
const startNote = grant
|
|
325
331
|
? grant.source === "trial"
|
|
326
332
|
? "25 free Nola runs — key in .env"
|
package/dist/index.js
CHANGED
package/dist/main.js
CHANGED
package/dist/registry.d.ts
CHANGED
|
@@ -9,6 +9,16 @@ export interface TemplateDef {
|
|
|
9
9
|
/** one-line menu description */
|
|
10
10
|
label: string;
|
|
11
11
|
source: "builtin" | "example";
|
|
12
|
+
/**
|
|
13
|
+
* The vendor the template's OWN config names. The flow skips the provider
|
|
14
|
+
* question for such a template (its config is the point of the example),
|
|
15
|
+
* the menu row carries `(<label>)`, and the outro names the env var; an
|
|
16
|
+
* explicit --provider flag still wins.
|
|
17
|
+
*/
|
|
18
|
+
provider?: {
|
|
19
|
+
label: string;
|
|
20
|
+
envVar: string;
|
|
21
|
+
};
|
|
12
22
|
}
|
|
13
23
|
export declare const TEMPLATES: readonly TemplateDef[];
|
|
14
24
|
export declare function templateByName(name: string): TemplateDef | undefined;
|
package/dist/registry.js
CHANGED
|
@@ -7,6 +7,12 @@ export const TEMPLATES = [
|
|
|
7
7
|
{ name: "classify-message", label: "closed label sets: union alias, string enum, inline union", source: "example" },
|
|
8
8
|
{ name: "chain-of-thought", label: "two asks sharing accumulating context", source: "example" },
|
|
9
9
|
{ name: "research-notes", label: "TS control flow orchestrating nola functions", source: "example" },
|
|
10
|
+
{
|
|
11
|
+
name: "triage-ticket",
|
|
12
|
+
label: "ticket triage: literal unions and booleans as typed questions; no provider question",
|
|
13
|
+
source: "example",
|
|
14
|
+
provider: { label: "typesafe.ai", envVar: "TYPESAFE_API_KEY" },
|
|
15
|
+
},
|
|
10
16
|
];
|
|
11
17
|
export function templateByName(name) {
|
|
12
18
|
return TEMPLATES.find((t) => t.name === name);
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ import { openai, mockProvider, withRetry } from "@nola-lang/providers";
|
|
|
10
10
|
`defineConfig`, the `nola` namespace (`nola.infer()`, `nola.tracer()`),
|
|
11
11
|
`terminalTrace()` and everything app-facing come from `@nola-lang/runtime`.
|
|
12
12
|
Everything bring-your-own — vendor factories (`openai`, `anthropic`,
|
|
13
|
-
`google`, `mockProvider`), resilience combinators (`withRetry`, `fallback`,
|
|
13
|
+
`google`, `typesafe`, `mockProvider`), resilience combinators (`withRetry`, `fallback`,
|
|
14
14
|
`roundRobin`, `constant`, `exponential`) and record/replay (`record`,
|
|
15
15
|
`replay`) — comes from `@nola-lang/providers`.
|
|
16
16
|
|
|
@@ -40,6 +40,13 @@ export default defineConfig({
|
|
|
40
40
|
`openai({ model })` requires an explicit model; optional fields are `apiKey`,
|
|
41
41
|
`apiKeyEnv` (default `"OPENAI_API_KEY"`), `baseUrl` and `fetch`.
|
|
42
42
|
|
|
43
|
+
`typesafe()` (typesafe.ai's Jev, reads `TYPESAFE_API_KEY`, model defaults to
|
|
44
|
+
`jev-latest`) is NOT a chat model: it serves only asks whose output type is a
|
|
45
|
+
string or number literal union, a boolean, or a flat object of those, and
|
|
46
|
+
fails definitively before the network on anything else. Use it behind
|
|
47
|
+
`fallback([typesafe(), openai({ model: "gpt-5-mini" })])` so other asks
|
|
48
|
+
escalate to a general model. Never scaffold it as the only model.
|
|
49
|
+
|
|
43
50
|
`nola` is a NAMESPACE, not a function (`nola({})` is a type error).
|
|
44
51
|
`nola.infer()` is the platform model — the Nola platform (api.nola.sh, or a
|
|
45
52
|
self-hosted console at `baseUrl`) serves inference and reads `NOLA_API_KEY`;
|
|
@@ -203,11 +210,11 @@ the providers package:
|
|
|
203
210
|
"check": "nola check"
|
|
204
211
|
},
|
|
205
212
|
"dependencies": {
|
|
206
|
-
"@nola-lang/providers": "^0.1.
|
|
207
|
-
"@nola-lang/runtime": "^0.1.
|
|
213
|
+
"@nola-lang/providers": "^0.1.9",
|
|
214
|
+
"@nola-lang/runtime": "^0.1.9"
|
|
208
215
|
},
|
|
209
216
|
"devDependencies": {
|
|
210
|
-
"nola-lang": "^0.1.
|
|
217
|
+
"nola-lang": "^0.1.9",
|
|
211
218
|
"typescript": "^5.6.0"
|
|
212
219
|
},
|
|
213
220
|
"engines": { "node": ">=22.18" }
|