ucode-agent 1.49.0 → 1.51.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
@@ -2,7 +2,7 @@
2
2
 
3
3
  A coding agent that lives in your terminal. It reads your code, edits it, runs
4
4
  your commands, and keeps every conversation on disk. It runs on NVIDIA,
5
- Cohere and Nex AGI models, all of them free.
5
+ Cohere, Nex AGI, DeepSeek and Qwen models, all of them free.
6
6
 
7
7
  It opens on a quiet screen — the name, the place to type, and the version in the
8
8
  corner:
@@ -87,8 +87,8 @@ Needs Node 22 or newer.
87
87
 
88
88
  ## The models
89
89
 
90
- Six, and no picker full of names nobody recognises. NVIDIA, Cohere and Nex AGI
91
- all serve capable models free, and all handle tool calling
90
+ Eight, and no picker full of names nobody recognises. NVIDIA, Cohere, Nex AGI,
91
+ DeepSeek and Qwen all serve capable models free, and all handle tool calling
92
92
  properly, which is the thing an agent actually depends on.
93
93
 
94
94
  | Model | Context | For |
@@ -99,6 +99,8 @@ properly, which is the thing an agent actually depends on.
99
99
  | Nemotron 3 Nano Omni | 256k | small, fast, reasoning tuned |
100
100
  | **North Mini Code** ★ | 256k | the default — built for code and interface work, quick to answer |
101
101
  | Nex N2.5 Pro | 262k | new agentic coder, on trial — can stall on big builds |
102
+ | DeepSeek V4 Flash | 1M | fast DeepSeek coder, on trial |
103
+ | Qwen 3.8 | 262k | compact Qwen coder, on trial |
102
104
 
103
105
  `/model` shows them and switches. `ucode -m cohere/north-mini-code:free`
104
106
  starts on one.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ucode-agent",
3
- "version": "1.49.0",
4
- "description": "ucode - a terminal coding agent that reads, edits and runs your code, on NVIDIA, Cohere and Nex AGI models.",
3
+ "version": "1.51.0",
4
+ "description": "ucode - a terminal coding agent that reads, edits and runs your code, on NVIDIA, Cohere, Nex AGI, DeepSeek and Qwen models.",
5
5
  "type": "module",
6
6
  "main": "ucode.js",
7
7
  "bin": {
@@ -39,7 +39,9 @@
39
39
  "nvidia",
40
40
  "nemotron",
41
41
  "cohere",
42
- "nex-agi"
42
+ "nex-agi",
43
+ "deepseek",
44
+ "qwen"
43
45
  ],
44
46
  "author": "om dixit",
45
47
  "license": "ISC",
package/src/core/loop.js CHANGED
@@ -1911,6 +1911,31 @@ export class Agent {
1911
1911
  this.reads.set(key, seen + 1);
1912
1912
  }
1913
1913
 
1914
+ // create_app again for the app this turn already made. DeepSeek scaffolded
1915
+ // tasker with no files, then called create_app twice more — once with no
1916
+ // folder or name at all — and was refused both times while the empty
1917
+ // starter sat there. The folder and name are known, so fill them in; with
1918
+ // no files there is nothing to create, and the next step is batch_write.
1919
+ if (call.name === 'create_app' && this.apps?.length === 1) {
1920
+ const made = this.apps[0];
1921
+ const args = (call.args ??= {});
1922
+ if (!args.folder) args.folder = path.relative(this.cwd, made) || '.';
1923
+ if (!args.name) args.name = path.basename(made);
1924
+ const files = args.files;
1925
+ const none = files == null || files === ''
1926
+ || (Array.isArray(files) ? !files.length : typeof files === 'object' && !Object.keys(files).length);
1927
+ if (none && path.resolve(this.cwd, String(args.folder)) === made) {
1928
+ const show = path.relative(this.cwd, made) || '.';
1929
+ throw new ToolFailure({
1930
+ kind: 'already_made',
1931
+ attempted: `creating ${show}`,
1932
+ failed: `${show} was already created this turn, with the starter files in it.`,
1933
+ fix: `Do not call create_app again. Write the app into ${show} with one batch_write, `
1934
+ + 'replacing the starter files with the finished ones.',
1935
+ });
1936
+ }
1937
+ }
1938
+
1914
1939
  // Starting a second app instead of fixing the first.
1915
1940
  //
1916
1941
  // A traced build hit a problem in todo/, abandoned it and made todo-fixed/
@@ -2683,7 +2708,7 @@ ${out.content}` });
2683
2708
  this.ui.blank();
2684
2709
  }
2685
2710
 
2686
- /** The six models, and this session's spend. */
2711
+ /** The eight models, and this session's spend. */
2687
2712
  async cmdModel(arg) {
2688
2713
  if (arg) {
2689
2714
  try {
@@ -46,11 +46,11 @@ dotenv.config({ path: join(PACKAGE_ROOT, '.env'), quiet: true });
46
46
  /**
47
47
  * The whole model list. Not a starting point — the list.
48
48
  *
49
- * ucode runs on NVIDIA, Cohere and Nex AGI only. All three serve genuinely
50
- * capable models free through OpenRouter, all handle tool calling properly,
51
- * and keeping the set to six means every one of them has been used in anger
52
- * rather than listed on the strength of a benchmark. A picker offering sixty
53
- * models is a picker nobody reads.
49
+ * ucode runs on NVIDIA, Cohere, Nex AGI, DeepSeek and Qwen only. All of them
50
+ * serve genuinely capable models free through OpenRouter, all handle tool
51
+ * calling properly, and keeping the set to eight means every one of them has
52
+ * been used in anger rather than listed on the strength of a benchmark. A
53
+ * picker offering sixty models is a picker nobody reads.
54
54
  *
55
55
  * `name` is what the status bar shows. `note` is what the picker shows.
56
56
  */
@@ -89,6 +89,18 @@ export const MODELS = {
89
89
  context: 262_144,
90
90
  note: 'new agentic coder, on trial — can stall on big builds',
91
91
  },
92
+ // Both free on OpenRouter with tool calling, added untested: on trial, not
93
+ // the default and not in FALLBACKS until a real ucode build has run on them.
94
+ 'deepseek/deepseek-v4-flash-0731:free': {
95
+ name: 'DeepSeek V4 Flash',
96
+ context: 1_048_576,
97
+ note: 'fast DeepSeek coder, 1M context — on trial',
98
+ },
99
+ 'qwen/qwen3.8-27b:free': {
100
+ name: 'Qwen 3.8',
101
+ context: 262_144,
102
+ note: 'compact Qwen coder, 262k context — on trial',
103
+ },
92
104
  };
93
105
 
94
106
  /**
@@ -173,7 +185,7 @@ export function setModel(id) {
173
185
  throw new Failure({
174
186
  kind: 'bad_model',
175
187
  attempted: `switching to "${wanted}"`,
176
- failed: 'ucode only runs NVIDIA, Cohere and Nex AGI models, and that is not one of them.',
188
+ failed: 'ucode only runs NVIDIA, Cohere, Nex AGI, DeepSeek and Qwen models, and that is not one of them.',
177
189
  fix: `Run /model to choose from: ${Object.keys(MODELS).join(', ')}`,
178
190
  });
179
191
  }
@@ -581,6 +581,18 @@ function check(name, args) {
581
581
  return ['the arguments must be a JSON object'];
582
582
  }
583
583
 
584
+ // One file named as "path" where the tool takes a list called "paths".
585
+ // DeepSeek did it to four read_files at once, a whole round trip spent being
586
+ // told a plural it could simply have been given.
587
+ for (const key of schema.required ?? []) {
588
+ const one = key.endsWith('s') ? key.slice(0, -1) : '';
589
+ if (args[key] == null && one && !schema.properties[one] && args[one] != null
590
+ && schema.properties[key]?.type === 'array') {
591
+ args[key] = Array.isArray(args[one]) ? args[one] : [args[one]];
592
+ delete args[one];
593
+ }
594
+ }
595
+
584
596
  for (const key of schema.required ?? []) {
585
597
  if (args[key] === undefined || args[key] === null) problems.push(`"${key}" is required and missing`);
586
598
  }
@@ -709,7 +721,7 @@ export function describe(name, args = {}) {
709
721
  // untrue on screen while the opposite happens on disk.
710
722
  return `Creating ${clip(args.name || args.folder, 30)} from the ` +
711
723
  `${args.template === 'next-shadcn' ? 'Next.js' : 'HTML'} starter` +
712
- `${files ? ` with ${files} file${files === 1 ? '' : 's'}` : ''}`;
724
+ `${files ? ` with ${files} file${files === 1 ? '' : 's'}` : ''}`;
713
725
  }
714
726
  case 'look_at_app':
715
727
  return `Looking at ${clip(args.url, 40)} on a phone and a desktop`;