ucode-agent 1.62.6 → 1.62.7

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.62.6
30
+ v1.62.7
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.62.6",
3
+ "version": "1.62.7",
4
4
  "description": "ucode - a terminal coding agent that reads, edits and runs your code, on Google Gemini models.",
5
5
  "type": "module",
6
6
  "main": "ucode.js",
package/src/core/loop.js CHANGED
@@ -52,7 +52,7 @@ import { serversReadySince } from '../tools/shell.js';
52
52
  import { formatDuration } from '../ui/activity.js';
53
53
  import { MAX_FILE_OUTPUT } from '../tools/shared.js';
54
54
  import { openInBrowser } from './opener.js';
55
- import { withScope } from './scope.js';
55
+ import { withScope, isNoise } from './scope.js';
56
56
  import { chooseFile, projectFiles, loadAttachments } from './attach.js';
57
57
  import { runDoctor } from './doctor.js';
58
58
  import { JS_LOGIC } from './jslogic.js';
@@ -594,6 +594,11 @@ function systemPrompt({ cwd, skills, mode, check, map, memory }) {
594
594
  '',
595
595
  '## How to work',
596
596
  '',
597
+ 'BUILD ONLY WHEN ASKED. Make or change an app only when the message asks for one.',
598
+ 'A greeting, a question, a single word, or anything unclear gets a short plain',
599
+ 'answer - or one question back about what they would like - never an app. "What',
600
+ 'can you do?" is answered in words; "make a quiz app" is built.',
601
+ '',
597
602
  'AN APP THAT IS AWKWARD TO USE IS NOT FINISHED. Before you call it done, look at',
598
603
  'what you built as someone using it for the first time: is the button inside its',
599
604
  'field or sitting on top of it, is there room to breathe between things, does the',
@@ -1126,6 +1131,15 @@ export class Agent {
1126
1131
  continue;
1127
1132
  }
1128
1133
 
1134
+ // "+" on its own is the "+ file" button typed — the way to it on Windows,
1135
+ // where the terminal sends no clicks. Other symbols alone are not a request:
1136
+ // a live "+" was built into a calculator nobody asked for.
1137
+ if (input === '+' && this.ui.addAttachment) { await this.attachFile(); continue; }
1138
+ if (isNoise(input)) {
1139
+ this.ui.note('Say what you would like to build or ask. To add a picture or file, type + or press ctrl+o.');
1140
+ continue;
1141
+ }
1142
+
1129
1143
  try {
1130
1144
  await this.turn(input);
1131
1145
  } catch (err) {
@@ -1259,7 +1273,7 @@ export class Agent {
1259
1273
  // Nothing to look up in an empty folder, so those tools do not go out with
1260
1274
  // the request. Decided per turn: the moment there is code, they are back.
1261
1275
  this.fresh = !hasCode(this.map);
1262
- request.content = withScope(input, { fresh: this.fresh }) + added.text;
1276
+ request.content = withScope(input) + added.text;
1263
1277
  this.wantsWeb = WANTS_WEB.test(input);
1264
1278
  await this.persist();
1265
1279
 
package/src/core/scope.js CHANGED
@@ -13,11 +13,30 @@ export const SCOPE_NOTE =
13
13
  'for - no extra views or tools such as timers, calendars, kanban boards, analytics, stats or an ' +
14
14
  'editor for making your own, unless the request names them.)';
15
15
 
16
- /** A request that may be for a new app. Loose on purpose: the note it adds says "if". */
17
- export const BUILD_ASK =
18
- /\b(?:make|build|create|design|code|write|generate|develop)\b|\bi\s+(?:want|need)\b|\b(?:app|game|website|site|page|tracker|calculator|quiz)\b/i;
16
+ /**
17
+ * A request for something to be built: a making word, then a thing to make.
18
+ *
19
+ * It used to fire on any message in an empty folder, and on a bare "app" or
20
+ * "make". A user who typed "+" in their home folder got the note, and the
21
+ * model took it as a request and built a calculator nobody asked for.
22
+ */
23
+ const MAKE = String.raw`\b(?:make|build|create|design|generate|develop|code)\b`;
24
+ const THING = String.raw`\b(?:apps?|games?|website|site|page|tracker|calculator|quiz|tool|dashboard|list|timer|stopwatch|clock|form|portfolio|planner|converter|board|tic[- ]?tac[- ]?toe|snake|sudoku)\b`;
25
+ const BUILDS = [
26
+ new RegExp(`${MAKE}\\s+(?:me\\s+|us\\s+)?(?:an?|some|my|our)\\s`, 'i'), // make a stopwatch, build me a …
27
+ new RegExp(`${MAKE}[^.?!\\n]{0,60}?${THING}`, 'i'), // make tic tac toe, create the quiz page
28
+ /\bi\s+(?:want|need)\s+(?:a|an)\s+\S+/i, // i want a homework tracker
29
+ ];
30
+ /** Asking, not telling: "what can you make?", "how does it work". */
31
+ const QUESTION = /\?\s*$|^\s*(?:what|how|why|when|where|who|which|can|could|does|do|is|are|should|would)\b/i;
19
32
 
20
- /** The request as the model sees it: one in an empty folder, or shaped like a build, carries the note. */
21
- export function withScope(input, { fresh = false } = {}) {
22
- return fresh || BUILD_ASK.test(input) ? `${input}\n\n${SCOPE_NOTE}` : input;
33
+ /** Does this message ask for something to be built? Never for a question. */
34
+ export const asksToBuild = (input) => !QUESTION.test(input) && BUILDS.some((re) => re.test(input));
35
+
36
+ /** The request as the model sees it: one that asks for an app carries the note. */
37
+ export function withScope(input) {
38
+ return asksToBuild(input) ? `${input}\n\n${SCOPE_NOTE}` : input;
23
39
  }
40
+
41
+ /** A message with no letters or digits in it ("+", "?", "...") — nothing to answer or build. */
42
+ export const isNoise = (input) => !/[\p{L}\p{N}]/u.test(String(input ?? ''));