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 +5 -3
- package/package.json +5 -3
- package/src/core/loop.js +26 -1
- package/src/core/provider.js +18 -6
- package/src/tools/index.js +13 -1
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
|
|
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
|
-
|
|
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.
|
|
4
|
-
"description": "ucode - a terminal coding agent that reads, edits and runs your code, on NVIDIA, Cohere
|
|
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
|
|
2711
|
+
/** The eight models, and this session's spend. */
|
|
2687
2712
|
async cmdModel(arg) {
|
|
2688
2713
|
if (arg) {
|
|
2689
2714
|
try {
|
package/src/core/provider.js
CHANGED
|
@@ -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
|
|
50
|
-
* capable models free through OpenRouter, all handle tool
|
|
51
|
-
* and keeping the set to
|
|
52
|
-
* rather than listed on the strength of a benchmark. A
|
|
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
|
|
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
|
}
|
package/src/tools/index.js
CHANGED
|
@@ -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`;
|