ucode-agent 1.43.0 → 1.44.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.
package/README.md CHANGED
@@ -27,7 +27,7 @@ corner:
27
27
  add a dark mode toggle that remembers the choice
28
28
 
29
29
 
30
- v1.43.0
30
+ v1.44.0
31
31
  ```
32
32
 
33
33
  A light crosses the wordmark once as it opens, and the three lines under the box
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ucode-agent",
3
- "version": "1.43.0",
3
+ "version": "1.44.0",
4
4
  "description": "ucode - a terminal coding agent that reads, edits and runs your code, on NVIDIA and Cohere models.",
5
5
  "type": "module",
6
6
  "main": "ucode.js",
@@ -95,7 +95,11 @@ export const tools = [
95
95
  'toy, a game, a visualisation, a calculator, a timer. "next-shadcn": Next.js 16, ' +
96
96
  'TypeScript, Tailwind 4 and shadcn with 33 components — only when the app genuinely ' +
97
97
  'needs routes, a database or many screens, because it costs an install and a build. ' +
98
- 'This is how every Next.js app begins - never run create-next-app or shadcn init.',
98
+ 'This is how every Next.js app begins - never run create-next-app or shadcn init. ' +
99
+ 'In "next-shadcn" every path in "files" goes under src/: a page is a route only at ' +
100
+ '<app>/src/app/page.tsx or <app>/src/app/<segment>/page.tsx, an API handler only at ' +
101
+ '<app>/src/app/api/<name>/route.ts, and components at <app>/src/components/<feature>/. ' +
102
+ 'A page.tsx written anywhere else is an ordinary file the router never serves.',
99
103
  parameters: {
100
104
  type: 'object',
101
105
  properties: {
@@ -173,6 +173,60 @@ async function unprefixOwnFolder(appDir, written) {
173
173
  return fixed;
174
174
  }
175
175
 
176
+ /**
177
+ * Files that legitimately sit at the root of a Next.js project.
178
+ *
179
+ * Everything else a model writes there is app code that has missed src/.
180
+ */
181
+ const NEXT_ROOT = /^(?:package(?:-lock)?\.json|next\.config\.[mc]?[jt]s|tsconfig\.json|postcss\.config\.[mc]?js|eslint\.config\.[mc]?js|components\.json|README\.md|TEMPLATE\.md|\.gitignore|next-env\.d\.ts)$/i;
182
+
183
+ /**
184
+ * Put Next.js files where Next.js looks for them.
185
+ *
186
+ * Routing is folder-based and unforgiving: a page is a route only at
187
+ * src/app/<segment>/page.tsx. A traced build wrote page.tsx at the project
188
+ * root and api/expenses/route.ts beside it — the build passed, every route
189
+ * 404ed, and nothing said why.
190
+ *
191
+ * The guide has the tree in it, and the guide cannot help: it comes back
192
+ * inside the create_app result, and the model chooses these paths in the call
193
+ * that produces that result. It is reading the map after it has parked. So the
194
+ * paths are corrected on the way in, and the result says what moved and why,
195
+ * which is the copy that arrives in time to matter for the next file.
196
+ *
197
+ * Only for next-shadcn, only for files under the app folder, and never for the
198
+ * config files that genuinely belong at the root.
199
+ */
200
+ function placeForNext(files, folder) {
201
+ const moved = [];
202
+
203
+ const out = files.map((f) => {
204
+ const rel = String(f.path ?? '').split('\\').join('/');
205
+ const prefix = `${folder}/`;
206
+ if (!rel.startsWith(prefix)) return f;
207
+
208
+ const inside = rel.slice(prefix.length);
209
+ if (!inside || inside.startsWith('src/') || inside.startsWith('public/')) return f;
210
+ if (NEXT_ROOT.test(inside)) return f;
211
+
212
+ // app/... is the right tree written one level too high; everything else
213
+ // that is app code belongs under src/ as it stands.
214
+ const under = inside.startsWith('app/') ? `src/${inside}` : `src/app/${inside}`;
215
+ const isRoute = /(?:^|\/)(?:page|layout|loading|error|not-found)\.[jt]sx?$/.test(inside)
216
+ || /(?:^|\/)route\.[jt]s$/.test(inside);
217
+ const isCode = /^(?:components|lib|hooks|styles|utils)\//.test(inside);
218
+
219
+ if (!isRoute && !isCode) return f;
220
+ const to = isCode ? `${prefix}src/${inside}` : `${prefix}${under}`;
221
+ if (to === rel) return f;
222
+
223
+ moved.push(`${inside} -> ${to.slice(prefix.length)}`);
224
+ return { ...f, path: to };
225
+ });
226
+
227
+ return { files: out, moved };
228
+ }
229
+
176
230
  async function keepDesignTokens(appDir, template, written, starterCss) {
177
231
  const rel = TOKEN_FILE[template];
178
232
  if (!rel || !starterCss) return null;
@@ -366,7 +420,9 @@ export async function createApp({ folder, name, description, template = 'plain-h
366
420
 
367
421
  // The app's own files, written in this same call. Two round trips become
368
422
  // one, and round trips are nearly all of the time a build takes.
369
- const mine = given;
423
+ // Next.js only: paths that have missed src/ are corrected before they land.
424
+ const placed = template === 'next-shadcn' ? placeForNext(given, path.basename(target.abs)) : { files: given, moved: [] };
425
+ const mine = placed.files;
370
426
  const wrote = mine.length ? await batchWrite({ files: mine }) : null;
371
427
  const written = new Set(mine.map((f) => resolveIn(f.path, 'create_app', 'files').abs));
372
428
  const keptTokens = await keepDesignTokens(target.abs, template, written, starterCss);
@@ -387,6 +443,13 @@ export async function createApp({ folder, name, description, template = 'plain-h
387
443
  `Created ${target.show} from the ${template} starter — ${copied.length} files, already known to build.\n` +
388
444
  (look ? `Design: the ${look.name} preset (${look.summary}), font ${look.fonts?.sans ?? 'Geist'}.\n` : '') +
389
445
  (wrote ? `\nYour ${mine.length} file${mine.length === 1 ? '' : 's'}:\n${wrote.content}\n` : '') +
446
+ (placed.moved.length
447
+ ? `\nMoved into place: ${placed.moved.join(', ')}. In Next.js a page is only a route at `
448
+ + 'src/app/<segment>/page.tsx, an API handler only at src/app/api/<name>/route.ts, and '
449
+ + 'components and libraries live under src/. A file written outside src/ builds fine and '
450
+ + 'is never served, which is the hardest kind of wrong to notice. Write the rest there '
451
+ + 'directly.\n'
452
+ : '') +
390
453
  (relinked.length
391
454
  ? `\nFixed in ${relinked.join(', ')}: links that began with "${path.basename(target.abs)}/". ` +
392
455
  'Paths in "files" are relative to the project root, but a link inside a page is ' +