nox-qwen-agent-cli 1.1.4 → 1.1.5

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.
@@ -47,6 +47,13 @@ Editing rules:
47
47
  Planning rules:
48
48
  Use a plan when the task has multiple steps, affects several files, requires investigation, or requires tests.
49
49
 
50
+ Clarification rules:
51
+ - If a request is broad, ambiguous, risky, destructive, or missing acceptance criteria, ask concise clarifying questions before changing files or running commands with side effects.
52
+ - Ask only for details that materially affect the implementation, validation, or safety of the task.
53
+ - Keep clarification questions numbered, specific, and limited to five unless the user explicitly asks for a deeper requirements interview.
54
+ - When a reasonable default is safe, state the assumption and continue instead of blocking.
55
+ - If the user explicitly asks for clarification mode, do not execute the task yet; return the questions and the proposed assumptions only.
56
+
50
57
  Progress rules:
51
58
  For longer operations, provide brief progress updates after meaningful milestones. Do not narrate every low-level command.
52
59
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nox-qwen-agent-cli",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "Cross-platform OpenAI-compatible Qwen coding agent CLI",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
package/qwen.js CHANGED
@@ -19,6 +19,14 @@ const MAX_FILE_BYTES = 20 * 1024 * 1024;
19
19
  const MAX_COMMAND_OUTPUT = 128 * 1024;
20
20
  const MAX_API_RETRIES = 2;
21
21
  const MAX_SHELL_TIMEOUT_MS = 10 * 60 * 1000;
22
+ const CLARIFY_REQUEST_PROMPT = `Clarify this request before execution.
23
+ Do not modify files, run commands with side effects, or implement the task yet.
24
+ Ask the minimum set of precise questions needed to remove ambiguity, identify acceptance criteria, and confirm risky choices.
25
+ Use no more than five numbered questions unless the user explicitly asks for a deeper requirements interview.
26
+ If the request is already clear enough, say so and list the assumptions you would use before execution.
27
+
28
+ Request:
29
+ `;
22
30
  const SYSTEM_PROMPT_RULES = `The tools attached to the request are authoritative. Use their exact names and JSON schemas.
23
31
  Use tools for every local operation. Never claim a command ran or a file changed without a tool result.
24
32
  Perform one coherent tool action at a time, inspect its result, and continue until the task is complete.
@@ -226,6 +234,7 @@ function parseArgs(argv) {
226
234
  prompt: "",
227
235
  stream: true,
228
236
  yes: false,
237
+ clarify: false,
229
238
  approvalMode: "ask",
230
239
  history: true,
231
240
  resume: "",
@@ -238,6 +247,7 @@ function parseArgs(argv) {
238
247
  else if (value === "-p" || value === "--prompt") options.prompt = argv[++index] || "";
239
248
  else if (value === "--base-url") options.baseUrl = argv[++index] || options.baseUrl;
240
249
  else if (value === "-C" || value === "--workspace") options.workspace = argv[++index] || options.workspace;
250
+ else if (value === "--clarify") options.clarify = true;
241
251
  else if (value === "--no-stream") options.stream = false;
242
252
  else if (value === "--stream") options.stream = true;
243
253
  else if (value === "--request-timeout") options.requestTimeoutMs = Number.parseInt(argv[++index] || "", 10) * 1000;
@@ -262,11 +272,13 @@ Usage:
262
272
  qwen
263
273
  qwen install ext
264
274
  qwen -m gpt-5.5 -p "inspect this project"
275
+ qwen --clarify -p "add auth"
265
276
  qwen --yes --no-stream
266
277
 
267
278
  Options:
268
279
  -m, --model MODEL Select model without the menu
269
280
  -p, --prompt TEXT Run one task and exit
281
+ --clarify Ask precise clarification questions for --prompt before execution
270
282
  -C, --workspace PATH Active workspace
271
283
  --base-url URL OpenAI-compatible base URL
272
284
  --stream / --no-stream Streaming mode; streaming is default
@@ -287,10 +299,15 @@ Interactive commands:
287
299
  /resume SESSION Resume a saved chat
288
300
  /approval ask|auto Change approval mode for this session
289
301
  /plan TASK Require a visible plan before execution
302
+ /clarify TASK Ask precise questions and assumptions before execution
290
303
  /clear Alias for /new
291
304
  /exit Exit`;
292
305
  }
293
306
 
307
+ function clarifyPrompt(request) {
308
+ return `${CLARIFY_REQUEST_PROMPT}${String(request || "").trim()}`;
309
+ }
310
+
294
311
  function configuredApiKey() {
295
312
  return String(
296
313
  process.env.NOX_API_KEY
@@ -764,6 +781,44 @@ function shellQuote(value) {
764
781
  return `'${String(value).replace(/'/g, `'\\''`)}'`;
765
782
  }
766
783
 
784
+ function parseTextToolCall(content) {
785
+ const text = typeof content === "string" ? content.trim() : "";
786
+ const match = text.match(/^<NOX_TOOL_CALL>([\s\S]+)<\/NOX_TOOL_CALL>$/);
787
+ if (!match) return null;
788
+ let payload;
789
+ try {
790
+ payload = JSON.parse(match[1]);
791
+ } catch {
792
+ return null;
793
+ }
794
+ const name = String(payload?.tool || "");
795
+ if (!name) return null;
796
+ const id = String(payload?.id || `text_tool_${crypto.randomUUID().slice(0, 8)}`);
797
+ const args = payload?.args && typeof payload.args === "object" && !Array.isArray(payload.args)
798
+ ? payload.args
799
+ : {};
800
+ return {
801
+ id,
802
+ type: "function",
803
+ function: {
804
+ name,
805
+ arguments: JSON.stringify(args),
806
+ },
807
+ };
808
+ }
809
+
810
+ function normalizeAssistantToolTransport(assistant) {
811
+ const nativeCalls = Array.isArray(assistant.tool_calls) ? assistant.tool_calls : [];
812
+ if (nativeCalls.length) return assistant;
813
+ const textCall = parseTextToolCall(assistant.content);
814
+ if (!textCall) return assistant;
815
+ return {
816
+ ...assistant,
817
+ content: null,
818
+ tool_calls: [textCall],
819
+ };
820
+ }
821
+
767
822
  async function runShell(command, cwd, timeoutValue) {
768
823
  const timeoutMs = Math.max(1, Math.min(MAX_SHELL_TIMEOUT_MS, Number(timeoutValue || 120000)));
769
824
  return await new Promise((resolvePromise) => {