create-oke 0.18.4 → 0.19.0

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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/package.json +3 -3
  3. package/src/agents-md.ts +6 -4
  4. package/src/ai-setup/apply.test.ts +278 -0
  5. package/src/ai-setup/apply.ts +430 -52
  6. package/src/ai-setup/catalog.ts +250 -1343
  7. package/src/ai-setup/from-pref.ts +3 -71
  8. package/src/ai-setup/prompts.ts +60 -443
  9. package/src/cli.test.ts +21 -15
  10. package/src/cli.ts +20 -11
  11. package/src/create-defaults.test.ts +4 -4
  12. package/src/create-defaults.ts +3 -3
  13. package/src/customize-flow.test.ts +9 -15
  14. package/src/customize-flow.ts +59 -66
  15. package/src/drivers-catalog.ts +18 -23
  16. package/src/transform.test.ts +69 -10
  17. package/src/transform.ts +10 -35
  18. package/templates/advanced/.env.example +28 -11
  19. package/templates/advanced/.github/workflows/ci.yml +1 -1
  20. package/templates/advanced/oke.config.ts +3 -4
  21. package/templates/advanced/package.json +11 -10
  22. package/templates/advanced/src/app.ts +36 -1
  23. package/templates/advanced/src/core.ts +12 -11
  24. package/templates/advanced/src/db/schema.decl.ts +6 -2
  25. package/templates/advanced/src/db/seed/index.ts +4 -4
  26. package/templates/advanced/src/flows/main/route.ts +3 -2
  27. package/templates/advanced/src/flows/notes/[id]/archive.ts +5 -8
  28. package/templates/advanced/src/flows/notes/[id]/attach.ts +1 -4
  29. package/templates/advanced/src/flows/notes/[id]/get.ts +4 -7
  30. package/templates/advanced/src/flows/notes/[id]/summarize.ts +3 -4
  31. package/templates/advanced/src/flows/notes/create.ts +4 -6
  32. package/templates/advanced/src/flows/notes/digest.ts +6 -5
  33. package/templates/advanced/src/flows/notes/list.ts +4 -5
  34. package/templates/advanced/src/flows/notes/shapes.ts +13 -3
  35. package/templates/advanced/src/flows/notes/signals.ts +1 -2
  36. package/templates/advanced/src/vault.ts +138 -0
  37. package/templates/advanced/tests/advanced.test.ts +11 -8
  38. package/templates/advanced/web/src/App.css +7 -0
  39. package/templates/advanced/web/src/App.tsx +101 -1
  40. package/templates/advanced/web/src/client.ts +16 -3
  41. package/templates/advanced/web/vite.config.ts +1 -0
  42. package/templates/standard/.env.example +22 -11
  43. package/templates/standard/.github/workflows/ci.yml +1 -1
  44. package/templates/standard/oke.config.ts +3 -3
  45. package/templates/standard/package.json +11 -10
  46. package/templates/standard/src/app.ts +6 -1
  47. package/templates/standard/src/core.ts +10 -11
  48. package/templates/standard/src/db/schema.decl.ts +6 -2
  49. package/templates/standard/src/db/seed/index.ts +3 -3
  50. package/templates/standard/src/flows/main/route.ts +3 -2
  51. package/templates/standard/src/flows/notes/[id]/archive.ts +5 -8
  52. package/templates/standard/src/flows/notes/[id]/get.ts +4 -7
  53. package/templates/standard/src/flows/notes/create.ts +4 -6
  54. package/templates/standard/src/flows/notes/list.ts +4 -5
  55. package/templates/standard/src/flows/notes/shapes.ts +12 -2
  56. package/templates/standard/src/flows/notes/signals.ts +1 -2
  57. package/templates/standard/src/vault.ts +123 -0
  58. package/templates/standard/tests/standard.test.ts +3 -1
  59. package/templates/standard/web/src/client.ts +2 -2
  60. package/templates/standard/web/vite.config.ts +1 -0
  61. package/src/ai-setup/detect-ollama.ts +0 -228
  62. package/src/ai-setup/recommend.ts +0 -220
@@ -1,220 +0,0 @@
1
- /**
2
- * Machine fit helpers for local Ollama model picks.
3
- *
4
- * Catalog `ramGb` is the **recommended machine tier** for that model (not the
5
- * download size). Prefer picks that leave ~4GB for OS / IDE / browser.
6
- */
7
-
8
- import {
9
- CHAT_MODELS,
10
- MODEL_TIERS,
11
- type CatalogModel,
12
- type ModelTier,
13
- recommendForTier,
14
- } from "./catalog.ts";
15
-
16
- /** Reserved for OS + IDE + browser while the model runs. */
17
- export const OS_HEADROOM_GB = 4;
18
-
19
- /**
20
- * RAM left after reserving OS/IDE headroom.
21
- *
22
- * @param totalRamGb - Detected machine RAM
23
- */
24
- export function usableRamGb(totalRamGb: number): number {
25
- return Math.max(0, totalRamGb - OS_HEADROOM_GB);
26
- }
27
-
28
- /**
29
- * Whether the machine meets the model's recommended tier (`model.ramGb`).
30
- *
31
- * @param model - Catalog entry
32
- * @param totalRamGb - Machine RAM (null → only the catalog default recommended)
33
- */
34
- export function modelFitsOnMachine(model: CatalogModel, totalRamGb: number | null): boolean {
35
- if (totalRamGb === null || !Number.isFinite(totalRamGb)) {
36
- return Boolean(model.recommended);
37
- }
38
- return model.ramGb <= totalRamGb;
39
- }
40
-
41
- /**
42
- * Whether the model fits with comfortable headroom for OS/IDE.
43
- *
44
- * @param model - Catalog entry
45
- * @param totalRamGb - Machine RAM
46
- */
47
- export function modelFitsComfortably(model: CatalogModel, totalRamGb: number | null): boolean {
48
- if (totalRamGb === null || !Number.isFinite(totalRamGb)) {
49
- return Boolean(model.recommended);
50
- }
51
- const smallest = [...CHAT_MODELS].sort((a, b) => a.ramGb - b.ramGb)[0]!;
52
- if (model.id === smallest.id) return model.ramGb <= totalRamGb;
53
- return model.ramGb + OS_HEADROOM_GB <= totalRamGb;
54
- }
55
-
56
- /**
57
- * True when the model meets the tier but leaves little room for OS/IDE.
58
- *
59
- * @param model - Catalog entry
60
- * @param totalRamGb - Machine RAM
61
- */
62
- export function isTightFit(model: CatalogModel, totalRamGb: number | null): boolean {
63
- if (totalRamGb === null || !Number.isFinite(totalRamGb)) return false;
64
- return modelFitsOnMachine(model, totalRamGb) && !modelFitsComfortably(model, totalRamGb);
65
- }
66
-
67
- /**
68
- * Chat models that meet the machine tier, smallest → largest.
69
- *
70
- * @param totalRamGb - Machine RAM
71
- */
72
- export function fittingChatModels(totalRamGb: number | null): readonly CatalogModel[] {
73
- const fits = CHAT_MODELS.filter((m) => modelFitsOnMachine(m, totalRamGb));
74
- if (fits.length > 0) return [...fits].sort((a, b) => a.ramGb - b.ramGb);
75
- return [[...CHAT_MODELS].sort((a, b) => a.ramGb - b.ramGb)[0]!];
76
- }
77
-
78
- /**
79
- * Prefer comfortable fits; fall back to any tier-fit if needed.
80
- *
81
- * @param totalRamGb - Machine RAM
82
- */
83
- export function comfortableChatModels(totalRamGb: number | null): readonly CatalogModel[] {
84
- const comfortable = CHAT_MODELS.filter((m) => modelFitsComfortably(m, totalRamGb));
85
- if (comfortable.length > 0) {
86
- return [...comfortable].sort((a, b) => a.ramGb - b.ramGb);
87
- }
88
- return fittingChatModels(totalRamGb);
89
- }
90
-
91
- /**
92
- * Suggest a tier for the machine's fit RAM budget.
93
- *
94
- * @param totalRamGb - Machine RAM
95
- */
96
- export function suggestTierForRam(totalRamGb: number | null): ModelTier {
97
- if (totalRamGb === null || !Number.isFinite(totalRamGb)) return "fast";
98
- const budget = usableRamGb(totalRamGb);
99
- if (budget >= 24) return "smart";
100
- if (budget >= 8) return "balanced";
101
- if (budget >= 4) return "fast";
102
- return "ultra-fast";
103
- }
104
-
105
- /**
106
- * Recommend a chat model for host RAM (balanced default — no quiz).
107
- *
108
- * @param totalRamGb - Machine RAM
109
- */
110
- export function recommendChatForNeeds(totalRamGb: number | null): CatalogModel {
111
- return recommendForTier(suggestTierForRam(totalRamGb), totalRamGb);
112
- }
113
-
114
- /**
115
- * Shared hardware lines for local AI banners.
116
- *
117
- * @param machine - Detected hardware
118
- */
119
- function formatMachineBannerLines(machine: {
120
- readonly osName: string;
121
- readonly cpuCount: number | null;
122
- readonly ramGb: number | null;
123
- }): readonly string[] {
124
- const ram =
125
- machine.ramGb !== null && Number.isFinite(machine.ramGb)
126
- ? `~${machine.ramGb}GB RAM`
127
- : "RAM unknown";
128
- const cpu =
129
- machine.cpuCount !== null && Number.isFinite(machine.cpuCount) ? String(machine.cpuCount) : "?";
130
- const fit =
131
- machine.ramGb !== null && Number.isFinite(machine.ramGb)
132
- ? `~${usableRamGb(machine.ramGb)}GB RAM`
133
- : "unknown";
134
- const sep = " · ";
135
- return [[`OS ${machine.osName}`, `CPU ${cpu}`, `RAM ${ram}`].join(sep), `Fit RAM ${fit}`];
136
- }
137
-
138
- /**
139
- * Ollama banner lines — OS · CPU · RAM · fit · detected · tiers.
140
- *
141
- * @param machine - Detected hardware
142
- * @param detectedIds - Installed model ids
143
- */
144
- export function formatOllamaBanner(
145
- machine: {
146
- readonly osName: string;
147
- readonly cpuCount: number | null;
148
- readonly ramGb: number | null;
149
- },
150
- detectedIds: readonly string[],
151
- ): string {
152
- const sep = " · ";
153
- const lines = [
154
- ...formatMachineBannerLines(machine),
155
- "",
156
- "Detected local models",
157
- ...(detectedIds.length > 0 ? detectedIds.map((id) => id) : ["(none detected)"]),
158
- "",
159
- `Tiers${sep}${MODEL_TIERS.map((t) => t.label).join(sep)}`,
160
- ];
161
- return lines.join("\n");
162
- }
163
-
164
- /**
165
- * llama.cpp banner — OS · CPU · RAM · fit · Docker Hub `ai/` source · tiers.
166
- *
167
- * @param machine - Detected hardware
168
- */
169
- export function formatLlamaCppBanner(machine: {
170
- readonly osName: string;
171
- readonly cpuCount: number | null;
172
- readonly ramGb: number | null;
173
- }): string {
174
- const sep = " · ";
175
- const lines = [
176
- ...formatMachineBannerLines(machine),
177
- "",
178
- "Model source",
179
- "Docker Hub ai/ (curated) — pulled on first container start",
180
- "",
181
- `Tiers${sep}${MODEL_TIERS.map((t) => t.label).join(sep)}`,
182
- ];
183
- return lines.join("\n");
184
- }
185
-
186
- /** Model name column width (monospace CLI table). */
187
- const MODEL_COL_NAME = 26;
188
- /** RAM column width, right-aligned (`≈32GB`). */
189
- const MODEL_COL_RAM = 7;
190
-
191
- /**
192
- * Clip or pad a cell for aligned CLI columns.
193
- *
194
- * @param value - Cell text
195
- * @param width - Fixed width
196
- */
197
- function clipPad(value: string, width: number): string {
198
- if (value.length === width) return value;
199
- if (value.length < width) return value.padEnd(width);
200
- return `${value.slice(0, Math.max(0, width - 1))}…`;
201
- }
202
-
203
- /**
204
- * Column header for the model pick list (aligns with {@link formatModelRow}).
205
- */
206
- export function formatModelTableHeader(): string {
207
- return `${clipPad("Model", MODEL_COL_NAME)} ${"RAM".padStart(MODEL_COL_RAM)} Caps`;
208
- }
209
-
210
- /**
211
- * One model row as aligned columns: Model | RAM | Caps.
212
- *
213
- * @param model - Catalog entry
214
- */
215
- export function formatModelRow(model: CatalogModel): string {
216
- const name = clipPad(model.label, MODEL_COL_NAME);
217
- const ram = `≈${model.ramGb}GB`.padStart(MODEL_COL_RAM);
218
- const caps = model.modalities.join(" · ");
219
- return `${name} ${ram} ${caps}`;
220
- }