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
package/dist/flow.js
CHANGED
|
@@ -16,9 +16,9 @@ import { acquireKey, SignInRequiredError } from "./key.js";
|
|
|
16
16
|
import { realLauncher } from "./launch.js";
|
|
17
17
|
import { nodeVersionWarning } from "./node-version.js";
|
|
18
18
|
import { openBrowser } from "./open-url.js";
|
|
19
|
-
import { detectPackageManager, packageManagerCommands } from "./package-manager.js";
|
|
19
|
+
import { defaultRuntime, detectPackageManager, isRuntime, packageManagerCommands } from "./package-manager.js";
|
|
20
20
|
import { isProviderId, PROVIDERS, providerById, providerIds } from "./providers.js";
|
|
21
|
-
import { entryFile, exampleNames, featuredNames,
|
|
21
|
+
import { entryFile, exampleNames, featuredNames, templateByName, templateNames } from "./registry.js";
|
|
22
22
|
import { ownVersion, scaffold, vendorEnvVar } from "./scaffold.js";
|
|
23
23
|
import { applyTrial } from "./trial.js";
|
|
24
24
|
const DEFAULT_DIR = "nola-app";
|
|
@@ -62,9 +62,10 @@ function templateOption(t) {
|
|
|
62
62
|
/*
|
|
63
63
|
* The template step is TWO menus (clack's select has no sections): the first
|
|
64
64
|
* lists the first-menu templates — feature-extraction, function-calling,
|
|
65
|
-
* typescript-interop, triage-ticket (the featured
|
|
66
|
-
* "More examples…" row; that row opens the
|
|
67
|
-
* Back row to return. `--template <name>`
|
|
65
|
+
* agent-loop, typescript-interop, triage-ticket (the featured examples),
|
|
66
|
+
* empty (the one builtin) — and one "More examples…" row; that row opens the
|
|
67
|
+
* remaining curated examples, with a Back row to return. `--template <name>`
|
|
68
|
+
* answers either level directly.
|
|
68
69
|
*/
|
|
69
70
|
export const TEMPLATE_QUESTION = "Select a template:";
|
|
70
71
|
export const EXAMPLE_QUESTION = "Select an example:";
|
|
@@ -72,11 +73,7 @@ export const EXAMPLE_QUESTION = "Select an example:";
|
|
|
72
73
|
export const MORE_EXAMPLES = "more-examples";
|
|
73
74
|
/** the examples menu's last row — back to the first menu */
|
|
74
75
|
export const BACK = "back";
|
|
75
|
-
/** `
|
|
76
|
-
const builtinNames = () => TEMPLATES.filter((t) => t.source === "builtin")
|
|
77
|
-
.map((t) => `"${t.name}"`)
|
|
78
|
-
.join(", ");
|
|
79
|
-
/** The first menu: the builtin templates and the featured example in registry order, then the examples row. */
|
|
76
|
+
/** The first menu: the featured examples and `empty` in registry order, then the examples row. */
|
|
80
77
|
export function templateMenu() {
|
|
81
78
|
const featured = featuredNames().map((name) => templateOption(templateByName(name)));
|
|
82
79
|
return [...featured, { value: MORE_EXAMPLES, label: "More examples…", hint: exampleNames().join(", ") }];
|
|
@@ -84,8 +81,14 @@ export function templateMenu() {
|
|
|
84
81
|
/** The second menu: the curated examples the first menu does not carry, in registry order, then Back. */
|
|
85
82
|
export function exampleMenu() {
|
|
86
83
|
const examples = exampleNames().map((name) => templateOption(templateByName(name)));
|
|
87
|
-
return [...examples, { value: BACK, label: "← Back", hint: "the
|
|
84
|
+
return [...examples, { value: BACK, label: "← Back", hint: "the first menu" }];
|
|
88
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* The note a failed example fetch gets (interactive: the menu is asked
|
|
88
|
+
* again). Only `empty` ships inside the CLI; every other template is fetched
|
|
89
|
+
* from GitHub, so an offline machine can still scaffold that one.
|
|
90
|
+
*/
|
|
91
|
+
export const FETCH_FAILURE_HINT = 'Only "empty" ships inside the CLI and needs no download — every other template is fetched from GitHub.';
|
|
89
92
|
/** Ask the two-level template menu until a template is chosen; null = cancelled. */
|
|
90
93
|
async function selectTemplate(prompter) {
|
|
91
94
|
for (;;) {
|
|
@@ -227,13 +230,22 @@ async function resolveProvider(input, prompter, template) {
|
|
|
227
230
|
return choice;
|
|
228
231
|
}
|
|
229
232
|
}
|
|
233
|
+
/** `--runtime`, else the manager's default (bun → bun). Validated up front like the other flags. */
|
|
234
|
+
function resolveRuntime(input) {
|
|
235
|
+
if (input.runtime !== undefined) {
|
|
236
|
+
if (!isRuntime(input.runtime))
|
|
237
|
+
throw new Error(`invalid --runtime "${input.runtime}" (valid: node, bun)`);
|
|
238
|
+
return input.runtime;
|
|
239
|
+
}
|
|
240
|
+
return defaultRuntime(input.packageManager ?? "npm");
|
|
241
|
+
}
|
|
230
242
|
/** The provider and setup (editor + agents) questions, in that order, shared by every outcome site; null = cancelled. */
|
|
231
243
|
async function resolveExtras(input, prompter, dir, template) {
|
|
232
244
|
const provider = await resolveProvider(input, prompter, template);
|
|
233
245
|
if (provider === null)
|
|
234
246
|
return null;
|
|
235
247
|
const setup = await resolveSetup(input, prompter, dir);
|
|
236
|
-
return setup === null ? null : { provider, ...setup };
|
|
248
|
+
return setup === null ? null : { provider, ...setup, runtime: resolveRuntime(input) };
|
|
237
249
|
}
|
|
238
250
|
/** Args fill prompts; whatever is missing is asked (never asked non-interactively). */
|
|
239
251
|
export async function resolveScaffoldOptions(input, prompter) {
|
|
@@ -243,6 +255,9 @@ export async function resolveScaffoldOptions(input, prompter) {
|
|
|
243
255
|
if (input.ide !== undefined && input.ide !== "vscode" && input.ide !== "none") {
|
|
244
256
|
throw new Error(`invalid --ide "${input.ide}" (valid: vscode, none)`);
|
|
245
257
|
}
|
|
258
|
+
if (input.runtime !== undefined && !isRuntime(input.runtime)) {
|
|
259
|
+
throw new Error(`invalid --runtime "${input.runtime}" (valid: node, bun)`);
|
|
260
|
+
}
|
|
246
261
|
if (input.agents !== undefined)
|
|
247
262
|
parseAgentsFlag(input.agents); // throws on unknown ids
|
|
248
263
|
flaggedProvider(input); // throws on an unknown id or a contradiction
|
|
@@ -370,10 +385,14 @@ export function plainPrompter() {
|
|
|
370
385
|
export const FLOW_OPTIONS = {
|
|
371
386
|
template: {
|
|
372
387
|
type: "string",
|
|
373
|
-
description: "template to scaffold
|
|
388
|
+
description: "template to scaffold: feature-extraction (the default), function-calling, agent-loop, typescript-interop, triage-ticket, empty, or another curated example",
|
|
374
389
|
},
|
|
375
390
|
add: { type: "boolean", description: "add Nola to the existing project in [dir] instead of scaffolding" },
|
|
376
391
|
ide: { type: "string", description: "editor setup: vscode (the default) | none" },
|
|
392
|
+
runtime: {
|
|
393
|
+
type: "string",
|
|
394
|
+
description: "runtime the project runs on: node | bun (default: bun when bun ran the scaffolder — bunfig.toml preload + `bun src/main.tsi`)",
|
|
395
|
+
},
|
|
377
396
|
agents: {
|
|
378
397
|
type: "string",
|
|
379
398
|
description: `agent skill files: ${AGENT_IDS.join(",")} | all | none (default: claude,universal)`,
|
|
@@ -593,6 +612,8 @@ export async function runFlow(args, opts = {}) {
|
|
|
593
612
|
agents: args.agents,
|
|
594
613
|
provider: args.provider,
|
|
595
614
|
trial: args.trial,
|
|
615
|
+
runtime: args.runtime,
|
|
616
|
+
packageManager: pm,
|
|
596
617
|
keyPath,
|
|
597
618
|
signIn: signInNow,
|
|
598
619
|
cwd: opts.cwd,
|
|
@@ -606,7 +627,7 @@ export async function runFlow(args, opts = {}) {
|
|
|
606
627
|
}
|
|
607
628
|
if (outcome.kind === "add") {
|
|
608
629
|
const grant = outcome.provider === "nola" ? await obtainTrial(prompter, opts, interactive) : null;
|
|
609
|
-
const result = await addNola(outcome.dir, { provider: outcome.provider });
|
|
630
|
+
const result = await addNola(outcome.dir, { provider: outcome.provider, runtime: outcome.runtime });
|
|
610
631
|
const trial = grant
|
|
611
632
|
? await applyTrial(outcome.dir, { apiKey: grant.apiKey, hasConfig: !result.wrote.includes("nola.config.ts") })
|
|
612
633
|
: { wrote: [], skipped: [] };
|
|
@@ -626,7 +647,12 @@ export async function runFlow(args, opts = {}) {
|
|
|
626
647
|
}
|
|
627
648
|
const lines = [
|
|
628
649
|
packageManagerCommands(pm).install,
|
|
629
|
-
|
|
650
|
+
...(outcome.runtime === "bun"
|
|
651
|
+
? [
|
|
652
|
+
'bunfig.toml: preload = ["@nola-lang/bun/preload"] (runs .tsi from source under Bun)',
|
|
653
|
+
'optional start script: "start": "bun src/main.ts"',
|
|
654
|
+
]
|
|
655
|
+
: ['optional start script: "start": "nola run src/main.ts"']),
|
|
630
656
|
'tsconfig tip: directory-style include (e.g. ["src"]) lets the editor see .tsi files',
|
|
631
657
|
commented(CONSOLE_COMMAND, CONSOLE_NOTE),
|
|
632
658
|
];
|
|
@@ -641,7 +667,13 @@ export async function runFlow(args, opts = {}) {
|
|
|
641
667
|
const grant = outcome.provider === "nola" ? await obtainTrial(prompter, opts, interactive) : null;
|
|
642
668
|
// A nola choice without a key (declined sign-in, API failure) scaffolds the plain template — the note above says why.
|
|
643
669
|
const provider = outcome.provider === "nola" ? (grant ? "nola" : "none") : outcome.provider;
|
|
644
|
-
const { files } = await scaffold(outcome.dir, {
|
|
670
|
+
const { files } = await scaffold(outcome.dir, {
|
|
671
|
+
template: outcome.template,
|
|
672
|
+
force: outcome.force,
|
|
673
|
+
provider,
|
|
674
|
+
ide: outcome.ide,
|
|
675
|
+
runtime: outcome.runtime,
|
|
676
|
+
});
|
|
645
677
|
let trialWrote = [];
|
|
646
678
|
if (grant) {
|
|
647
679
|
const trial = await applyTrial(outcome.dir, { apiKey: grant.apiKey, hasConfig: false });
|
|
@@ -675,7 +707,7 @@ export async function runFlow(args, opts = {}) {
|
|
|
675
707
|
}
|
|
676
708
|
catch (err) {
|
|
677
709
|
if (err instanceof ExampleFetchError && interactive) {
|
|
678
|
-
prompter.note(`${err.message}\
|
|
710
|
+
prompter.note(`${err.message}\n${FETCH_FAILURE_HINT}`);
|
|
679
711
|
input.dir = outcome.dir; // keep the chosen dir, re-pick the template
|
|
680
712
|
input.template = undefined;
|
|
681
713
|
continue;
|
package/dist/github.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** Network/acquisition failure — the builtin
|
|
1
|
+
/** Network/acquisition failure — `empty`, the one builtin template, always works offline. */
|
|
2
2
|
export declare class ExampleFetchError extends Error {
|
|
3
3
|
}
|
|
4
4
|
export type FetchLike = (url: string) => Promise<{
|
package/dist/github.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Production example acquisition: GitHub Trees API + raw file fetches. */
|
|
2
2
|
const REPO = "nola-lang/nola";
|
|
3
|
-
/** Network/acquisition failure — the builtin
|
|
3
|
+
/** Network/acquisition failure — `empty`, the one builtin template, always works offline. */
|
|
4
4
|
export class ExampleFetchError extends Error {
|
|
5
5
|
}
|
|
6
6
|
/** Try the lockstep release tag first; a repo without that tag serves main. */
|
package/dist/index.js
CHANGED
package/dist/launch.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface Launcher {
|
|
|
17
17
|
/**
|
|
18
18
|
* `code <dir> [<dir>/<entry>]`, detached; "not-found" when VS Code's `code`
|
|
19
19
|
* command is not on PATH. `entry` is a project-relative file to open as the
|
|
20
|
-
* active editor on top of the folder (the
|
|
20
|
+
* active editor on top of the folder (the template's entry file).
|
|
21
21
|
*/
|
|
22
22
|
openVscode(dir: string, entry?: string): Promise<"opened" | "not-found">;
|
|
23
23
|
}
|
|
@@ -25,7 +25,7 @@ export interface Launcher {
|
|
|
25
25
|
* The arguments that open a project in VS Code: the folder alone, or the
|
|
26
26
|
* folder plus one file. `code <folder> <file>` opens the folder as the
|
|
27
27
|
* workspace and the file as the active editor — that is how the scaffold
|
|
28
|
-
* lands the user on
|
|
28
|
+
* lands the user on the entry file instead of an empty window.
|
|
29
29
|
*/
|
|
30
30
|
export declare function vscodeArgs(dir: string, entry?: string): string[];
|
|
31
31
|
/**
|
package/dist/launch.js
CHANGED
|
@@ -5,7 +5,7 @@ import { join } from "node:path";
|
|
|
5
5
|
* The arguments that open a project in VS Code: the folder alone, or the
|
|
6
6
|
* folder plus one file. `code <folder> <file>` opens the folder as the
|
|
7
7
|
* workspace and the file as the active editor — that is how the scaffold
|
|
8
|
-
* lands the user on
|
|
8
|
+
* lands the user on the entry file instead of an empty window.
|
|
9
9
|
*/
|
|
10
10
|
export function vscodeArgs(dir, entry) {
|
|
11
11
|
return entry === undefined ? [dir] : [dir, join(dir, entry)];
|
package/dist/main.js
CHANGED
package/dist/node-version.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Node floor the docs state. Plain `.ts` (
|
|
3
|
-
* is loaded by Node's native type
|
|
2
|
+
* The Node floor the docs state. Plain `.ts` (an example's `src/main.ts`, or the
|
|
3
|
+
* plain modules a `.tsi` entry imports) is loaded by Node's native type
|
|
4
|
+
* stripping, which is on by default only from
|
|
4
5
|
* 22.18 on the 22 line and 23.6 on the 23 line; before that it sits behind
|
|
5
6
|
* `--experimental-strip-types` and the default loader rejects `.ts` outright
|
|
6
7
|
* (ERR_UNKNOWN_FILE_EXTENSION) — `npm start` and the F5 launch both die on
|
package/dist/node-version.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Node floor the docs state. Plain `.ts` (
|
|
3
|
-
* is loaded by Node's native type
|
|
2
|
+
* The Node floor the docs state. Plain `.ts` (an example's `src/main.ts`, or the
|
|
3
|
+
* plain modules a `.tsi` entry imports) is loaded by Node's native type
|
|
4
|
+
* stripping, which is on by default only from
|
|
4
5
|
* 22.18 on the 22 line and 23.6 on the 23 line; before that it sits behind
|
|
5
6
|
* `--experimental-strip-types` and the default loader rejects `.ts` outright
|
|
6
7
|
* (ERR_UNKNOWN_FILE_EXTENSION) — `npm start` and the F5 launch both die on
|
|
@@ -47,7 +48,7 @@ export function nodeVersionWarning(version = process.versions.node) {
|
|
|
47
48
|
return undefined;
|
|
48
49
|
const lines = [
|
|
49
50
|
`Node ${version} is older than Nola needs: Node >= ${NODE_FLOOR}, the first release that runs .ts files natively.`,
|
|
50
|
-
"On this Node, `npm start` and the VS Code F5 launch fail with ERR_UNKNOWN_FILE_EXTENSION
|
|
51
|
+
"On this Node, `npm start` and the VS Code F5 launch fail with ERR_UNKNOWN_FILE_EXTENSION on the first plain .ts file they load.",
|
|
51
52
|
];
|
|
52
53
|
if (hasStripTypesFlag(version)) {
|
|
53
54
|
lines.push("Upgrade Node (recommended), or set NODE_OPTIONS=--experimental-strip-types for `npm start` and add", '"--experimental-strip-types" to runtimeArgs in .vscode/launch.json.');
|
|
@@ -14,4 +14,9 @@ export interface PackageManagerCommands {
|
|
|
14
14
|
run: string;
|
|
15
15
|
}
|
|
16
16
|
export declare function packageManagerCommands(pm: PackageManager): PackageManagerCommands;
|
|
17
|
+
/** The runtime a scaffold targets: Node (the loader, `nola run`) or Bun (`@nola-lang/bun`'s preload, `bun src/main.tsi`). */
|
|
18
|
+
export type Runtime = "node" | "bun";
|
|
19
|
+
export declare function isRuntime(value: string): value is Runtime;
|
|
20
|
+
/** `bun create nola` produces a Bun project unless `--runtime node` says otherwise; every other manager scaffolds for Node. */
|
|
21
|
+
export declare function defaultRuntime(pm: PackageManager): Runtime;
|
|
17
22
|
//# sourceMappingURL=package-manager.d.ts.map
|
package/dist/package-manager.js
CHANGED
|
@@ -5,4 +5,11 @@ export function detectPackageManager(userAgent = process.env.npm_config_user_age
|
|
|
5
5
|
export function packageManagerCommands(pm) {
|
|
6
6
|
return { install: `${pm} install`, start: `${pm} start`, run: `${pm} run` };
|
|
7
7
|
}
|
|
8
|
+
export function isRuntime(value) {
|
|
9
|
+
return value === "node" || value === "bun";
|
|
10
|
+
}
|
|
11
|
+
/** `bun create nola` produces a Bun project unless `--runtime node` says otherwise; every other manager scaffolds for Node. */
|
|
12
|
+
export function defaultRuntime(pm) {
|
|
13
|
+
return pm === "bun" ? "bun" : "node";
|
|
14
|
+
}
|
|
8
15
|
//# sourceMappingURL=package-manager.js.map
|
package/dist/providers.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* template registry: `nola` is the platform, labelled "nola: dev" so the row
|
|
5
5
|
* reads as a mode of the project rather than a fourth vendor (the free trial, or a key on the
|
|
6
6
|
* account — see `keyPath`), the four vendors write a bring-your-own config,
|
|
7
|
-
* `none` is the offline default (the
|
|
7
|
+
* `none` is the offline default (the template's own config: a recorded ledger or a mock). typesafe.ai
|
|
8
8
|
* serves literal unions and booleans only; it is listed for every template all
|
|
9
9
|
* the same, and `providerOptions` (flow.ts) brackets that caveat into its hint.
|
|
10
10
|
*/
|
package/dist/providers.js
CHANGED
|
@@ -10,7 +10,7 @@ export const PROVIDERS = [
|
|
|
10
10
|
},
|
|
11
11
|
{ id: "google", label: "Gemini", hint: 'google("gemini-2.5-flash"), reads GEMINI_API_KEY', envVar: "GEMINI_API_KEY", model: 'google("gemini-2.5-flash")' },
|
|
12
12
|
{ id: "typesafe", label: "typesafe.ai", hint: "typesafe(), reads TYPESAFE_API_KEY", envVar: "TYPESAFE_API_KEY", model: "typesafe()" },
|
|
13
|
-
{ id: "none", label: "Skip for now", hint: "the
|
|
13
|
+
{ id: "none", label: "Skip for now", hint: "keeps the template's own config (the recorded ones run offline); pick a model in nola.config.ts later" },
|
|
14
14
|
];
|
|
15
15
|
export function providerById(id) {
|
|
16
16
|
return PROVIDERS.find((p) => p.id === id);
|
package/dist/registry.d.ts
CHANGED
|
@@ -2,31 +2,40 @@
|
|
|
2
2
|
* The template menu. Static by design: it is versioned in lockstep with the
|
|
3
3
|
* git tag the example fetcher pulls from, so names and labels cannot drift.
|
|
4
4
|
*
|
|
5
|
+
* `empty` is the ONLY builtin template (config + tsconfig + a stub entry,
|
|
6
|
+
* shipped inside this package). Every other template IS a curated example:
|
|
7
|
+
* its files come from `examples/` — on disk in a dev checkout, from GitHub
|
|
8
|
+
* (the lockstep release tag) in production — and the scaffolder adds the
|
|
9
|
+
* project name, the lockstep ranges, the recommended `.gitignore`, the
|
|
10
|
+
* chosen provider's config and the next-steps comment on top.
|
|
11
|
+
*
|
|
5
12
|
* The first menu leads (in this order) and is organized BY FEATURE:
|
|
6
|
-
* `feature-extraction` (the default)
|
|
7
|
-
* `.tsi` file with a top-level ask — the
|
|
13
|
+
* `feature-extraction` (the default), `function-calling` and `tool-use` are
|
|
14
|
+
* each one `.tsi` file with a top-level ask — the three things Nola does —
|
|
15
|
+
* `agent-loop` is the same shape around a top-level `while`,
|
|
8
16
|
* `typescript-interop` is the infer-function shape called from plain
|
|
9
|
-
* TypeScript, `triage-ticket`
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
17
|
+
* TypeScript, `triage-ticket` the one-file shape on a non-chat vendor, then
|
|
18
|
+
* `empty` (a stub `src/main.tsi` to write your own in). The other curated
|
|
19
|
+
* examples follow (behind "More examples…").
|
|
20
|
+
* extract-person is deliberately absent — typescript-interop IS
|
|
21
|
+
* extract-person plus the replay ledger.
|
|
14
22
|
*/
|
|
15
23
|
export interface TemplateDef {
|
|
16
24
|
name: string;
|
|
17
25
|
/** one-line menu description */
|
|
18
26
|
label: string;
|
|
27
|
+
/** where the files come from: this package's `templates/` dir, or `examples/` */
|
|
19
28
|
source: "builtin" | "example";
|
|
20
29
|
/**
|
|
21
|
-
* An example listed on the FIRST menu, in registry order beside
|
|
22
|
-
*
|
|
23
|
-
*
|
|
30
|
+
* An example listed on the FIRST menu, in registry order beside `empty`,
|
|
31
|
+
* instead of behind "More examples…". Its files still come from examples/
|
|
32
|
+
* (`source` is unchanged).
|
|
24
33
|
*/
|
|
25
34
|
featured?: true;
|
|
26
35
|
/**
|
|
27
36
|
* The file that IS the program — what `start` runs, launch.json's
|
|
28
37
|
* `program`, what VS Code opens, where the next-steps comment lands.
|
|
29
|
-
* Absent = the plain-TS `src/main.ts`
|
|
38
|
+
* Absent = the plain-TS `src/main.ts` the other examples have.
|
|
30
39
|
*/
|
|
31
40
|
entry?: string;
|
|
32
41
|
/**
|
|
@@ -43,7 +52,7 @@ export interface TemplateDef {
|
|
|
43
52
|
/** What a template runs unless it names its own entry: the plain-TS main. */
|
|
44
53
|
export declare const DEFAULT_ENTRY = "src/main.ts";
|
|
45
54
|
export declare const TEMPLATES: readonly TemplateDef[];
|
|
46
|
-
/** The first menu's templates: the
|
|
55
|
+
/** The first menu's templates: the featured examples and `empty`, in registry order. */
|
|
47
56
|
export declare function featuredNames(): string[];
|
|
48
57
|
/** The examples behind "More examples…": every example the first menu does not carry. */
|
|
49
58
|
export declare function exampleNames(): string[];
|
package/dist/registry.js
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
/** What a template runs unless it names its own entry: the plain-TS main. */
|
|
2
2
|
export const DEFAULT_ENTRY = "src/main.ts";
|
|
3
3
|
export const TEMPLATES = [
|
|
4
|
-
{
|
|
4
|
+
{
|
|
5
|
+
name: "feature-extraction",
|
|
6
|
+
label: "extract typed data from context",
|
|
7
|
+
source: "example",
|
|
8
|
+
featured: true,
|
|
9
|
+
entry: "src/main.tsi",
|
|
10
|
+
},
|
|
5
11
|
{
|
|
6
12
|
name: "function-calling",
|
|
7
13
|
label: "call an async function from a TypeScript file",
|
|
8
|
-
source: "
|
|
14
|
+
source: "example",
|
|
15
|
+
featured: true,
|
|
16
|
+
entry: "src/main.tsi",
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: "tool-use",
|
|
20
|
+
label: "offer functions as tools: the model calls them as it needs before it answers",
|
|
21
|
+
source: "example",
|
|
22
|
+
featured: true,
|
|
23
|
+
entry: "src/main.tsi",
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "agent-loop",
|
|
27
|
+
label: "an agent loop in one .tsi file: a top-level while with an ask, and a context statement read on every pass",
|
|
28
|
+
source: "example",
|
|
29
|
+
featured: true,
|
|
9
30
|
entry: "src/main.tsi",
|
|
10
31
|
},
|
|
11
32
|
{
|
|
12
33
|
name: "typescript-interop",
|
|
13
34
|
label: "an infer function example, imported and awaited from plain TypeScript",
|
|
14
|
-
source: "
|
|
35
|
+
source: "example",
|
|
36
|
+
featured: true,
|
|
15
37
|
},
|
|
16
38
|
{
|
|
17
39
|
name: "triage-ticket",
|
|
@@ -21,7 +43,7 @@ export const TEMPLATES = [
|
|
|
21
43
|
entry: "src/main.tsi",
|
|
22
44
|
provider: { label: "typesafe.ai", envVar: "TYPESAFE_API_KEY" },
|
|
23
45
|
},
|
|
24
|
-
{ name: "empty", label: "nola.config + tsconfig only, bring your own code", source: "builtin" },
|
|
46
|
+
{ name: "empty", label: "nola.config + tsconfig only, bring your own code", source: "builtin", entry: "src/main.tsi" },
|
|
25
47
|
{ name: "file-ticket", label: "call intents: the model fills a function's arguments", source: "example" },
|
|
26
48
|
{ name: "extract-resume", label: "nested arrays of objects, JSDoc schema descriptions", source: "example" },
|
|
27
49
|
{ name: "extract-invoice", label: "same-file type references, optional fields", source: "example" },
|
|
@@ -29,7 +51,7 @@ export const TEMPLATES = [
|
|
|
29
51
|
{ name: "chain-of-thought", label: "two asks sharing accumulating context", source: "example" },
|
|
30
52
|
{ name: "research-notes", label: "TS control flow orchestrating nola functions", source: "example" },
|
|
31
53
|
];
|
|
32
|
-
/** The first menu's templates: the
|
|
54
|
+
/** The first menu's templates: the featured examples and `empty`, in registry order. */
|
|
33
55
|
export function featuredNames() {
|
|
34
56
|
return TEMPLATES.filter((t) => t.source === "builtin" || t.featured).map((t) => t.name);
|
|
35
57
|
}
|
package/dist/scaffold.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Runtime } from "./package-manager.js";
|
|
1
2
|
import { type ProviderId } from "./providers.js";
|
|
2
3
|
export interface ScaffoldResult {
|
|
3
4
|
root: string;
|
|
@@ -13,18 +14,22 @@ export interface ScaffoldOptions {
|
|
|
13
14
|
/**
|
|
14
15
|
* The inference provider chosen in the wizard; default "none" (the
|
|
15
16
|
* template's own config). Any live provider replaces `nola.config.ts` with
|
|
16
|
-
* that provider's config
|
|
17
|
-
* the matching README notes.
|
|
17
|
+
* that provider's config and drops the offline templates' replay ledger.
|
|
18
18
|
*/
|
|
19
19
|
provider?: ProviderId;
|
|
20
20
|
/**
|
|
21
21
|
* The editor chosen in the wizard; default "none". Decides the next-steps
|
|
22
|
-
* comment
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* editor-neutral.
|
|
22
|
+
* comment that opens the template's entry file: with VS Code it names F5,
|
|
23
|
+
* breakpoints and the recommended extension (all of which the .vscode
|
|
24
|
+
* files the flow writes make true); without one it stays editor-neutral.
|
|
26
25
|
*/
|
|
27
26
|
ide?: "vscode" | "none";
|
|
27
|
+
/**
|
|
28
|
+
* The runtime the project runs on; default "node". "bun" adds bunfig.toml with the
|
|
29
|
+
* @nola-lang/bun preload, a `bun <entry>` start script, the devDependency and
|
|
30
|
+
* engines.bun — build/check stay the Node CLI (spec 2026-10-14-bun-support).
|
|
31
|
+
*/
|
|
32
|
+
runtime?: Runtime;
|
|
28
33
|
}
|
|
29
34
|
/** The config a live provider choice writes over the template's own (`templates/_providers/<id>.config.ts`). */
|
|
30
35
|
export declare function providerConfigUrl(provider: Exclude<ProviderId, "none">): URL;
|
|
@@ -41,24 +46,39 @@ export declare function vendorEnvVar(template: string, provider: ProviderId): st
|
|
|
41
46
|
* `.gitignore` keeps trackable (`!.env.example`), so it can be committed.
|
|
42
47
|
*/
|
|
43
48
|
export declare function envExample(envVar: string): string;
|
|
49
|
+
/** The Bun project's bunfig.toml: the preload for `bun src/main.tsi` and for `bun test`. */
|
|
50
|
+
export declare const BUNFIG_TOML = "preload = [\"@nola-lang/bun/preload\"]\n\n[test]\npreload = [\"@nola-lang/bun/preload\"]\n";
|
|
51
|
+
/** The Bun floor @nola-lang/bun needs (process.getBuiltinModule). */
|
|
52
|
+
export declare const BUN_ENGINE = ">=1.3.0";
|
|
53
|
+
/** A Bun project's manifest additions on top of the template's: the start script, the devDependency, engines.bun. */
|
|
54
|
+
export declare function applyBunRuntime(content: string, opts: {
|
|
55
|
+
entry: string;
|
|
56
|
+
version: string;
|
|
57
|
+
}): string;
|
|
44
58
|
/**
|
|
45
|
-
* Add the recommended `.gitignore` to
|
|
46
|
-
*
|
|
47
|
-
* so they carry none
|
|
59
|
+
* Add the recommended `.gitignore` to a template's files. Templates are
|
|
60
|
+
* copied as committed — examples from `examples/`, where the monorepo's root
|
|
61
|
+
* ignore file covers them — so they carry none; one a template does carry wins.
|
|
48
62
|
*/
|
|
49
63
|
export declare function withRecommendedGitignore(files: Map<string, string>): Promise<Map<string, string>>;
|
|
50
64
|
/**
|
|
51
|
-
* The comment that opens the entry file (
|
|
52
|
-
* of
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* what make F5 and the extension
|
|
65
|
+
* The comment that opens the entry file (the `.tsi` entry of a one-file
|
|
66
|
+
* template and of `empty`, else the plain-TS src/main.ts) — the file the
|
|
67
|
+
* scaffold lands the user on (VS Code opens it as the active editor), so it
|
|
68
|
+
* carries the first three things to do. The VS Code variant only ships with
|
|
69
|
+
* the editor step's .vscode files, which are what make F5 and the extension
|
|
70
|
+
* prompt real.
|
|
56
71
|
*/
|
|
57
|
-
export declare function nextStepsComment(ide: "vscode" | "none", template: string): string;
|
|
72
|
+
export declare function nextStepsComment(ide: "vscode" | "none", template: string, runtime?: Runtime): string;
|
|
58
73
|
export declare function ownVersion(): Promise<string>;
|
|
59
74
|
/**
|
|
60
75
|
* Lay a template down into `targetDir`. One implementation serves both entry
|
|
61
|
-
* points
|
|
76
|
+
* points — the `create-nola-lang` bin (`npm create nola-lang`) and `nola init`
|
|
77
|
+
* — and both sources: the files are collected as committed, then the scaffold
|
|
78
|
+
* adds what a project needs on top — the chosen provider's config (dropping
|
|
79
|
+
* the replay ledger), the project name and the lockstep ranges in
|
|
80
|
+
* package.json, the recommended .gitignore, the vendor key's .env.example,
|
|
81
|
+
* and the next-steps comment at the top of the entry file.
|
|
62
82
|
*/
|
|
63
83
|
export declare function scaffold(targetDir: string, opts?: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
64
84
|
//# sourceMappingURL=scaffold.d.ts.map
|