@qwen-code/qwen-code 0.18.0 → 0.18.1-nightly.20260616.a68b2e1e7

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.
Files changed (113) hide show
  1. package/bundled/loop/SKILL.md +2 -1
  2. package/bundled/qc-helper/docs/common-workflow.md +4 -4
  3. package/bundled/qc-helper/docs/configuration/auth.md +1 -1
  4. package/bundled/qc-helper/docs/configuration/model-providers.md +13 -6
  5. package/bundled/qc-helper/docs/configuration/settings.md +90 -87
  6. package/bundled/qc-helper/docs/features/dual-output.md +37 -3
  7. package/bundled/qc-helper/docs/features/skills.md +29 -3
  8. package/bundled/qc-helper/docs/features/sub-agents.md +2 -1
  9. package/bundled/qc-helper/docs/qwen-serve.md +32 -23
  10. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +30 -30
  11. package/chunks/{agent-LOTJK6AH.js → agent-PXMT2XR5.js} +21 -20
  12. package/chunks/{agent-headless-TU3EPMYU.js → agent-headless-SY7VJUHV.js} +21 -20
  13. package/chunks/{anthropicContentGenerator-2HBRNQ3B.js → anthropicContentGenerator-DCI26OQF.js} +4 -4
  14. package/chunks/{askUserQuestion-OGCMIBQM.js → askUserQuestion-NDNFGC35.js} +2 -2
  15. package/chunks/{ca-BARBRL6N.js → ca-RK4QPLIX.js} +18 -1
  16. package/chunks/{chunk-BIVG75CP.js → chunk-26QELEL2.js} +1 -1
  17. package/chunks/{chunk-ZTZ4DDQE.js → chunk-3NRO6NHX.js} +2 -2
  18. package/chunks/{chunk-XV4HCEVI.js → chunk-6WPY6ES3.js} +41 -22
  19. package/chunks/{chunk-6YIUGZTC.js → chunk-A3OEZT2F.js} +281 -132
  20. package/chunks/{chunk-LBP46COL.js → chunk-ABRZC6FA.js} +83 -15
  21. package/chunks/{chunk-A7B4ISQP.js → chunk-B4ZF2KSI.js} +1 -1
  22. package/chunks/chunk-BJ5HQ23U.js +178 -0
  23. package/chunks/{chunk-OHEGWO4L.js → chunk-CPVI5J2L.js} +1 -1
  24. package/chunks/{chunk-SEGYWKIH.js → chunk-FIQECJTQ.js} +1 -1
  25. package/chunks/{chunk-IWAYOW5Q.js → chunk-H4ZDM3N6.js} +6588 -4196
  26. package/chunks/{chunk-HR7SV7AY.js → chunk-HA2UEYZP.js} +6 -2
  27. package/chunks/{chunk-2Y5SYSD3.js → chunk-IDYDPBBN.js} +3 -3
  28. package/chunks/{chunk-3HTIVKZE.js → chunk-IQHSD7K5.js} +1 -1
  29. package/chunks/{chunk-MFBBBTNY.js → chunk-JZFEL3RB.js} +1 -1
  30. package/chunks/{chunk-B7HXHOHU.js → chunk-LXYWINWF.js} +1 -1
  31. package/chunks/{chunk-IDX6COTE.js → chunk-LYRSMKLS.js} +2 -2
  32. package/chunks/{chunk-M6VTDSVR.js → chunk-LYSND7KR.js} +9 -4
  33. package/chunks/{chunk-7BCMOPIM.js → chunk-M5PJ5QAF.js} +31 -12
  34. package/chunks/{chunk-EYENRK4D.js → chunk-NNIYWQIS.js} +1 -1
  35. package/chunks/chunk-OMX7CUOE.js +356 -0
  36. package/chunks/{chunk-R7ODSGTK.js → chunk-OT6JA3KQ.js} +2 -2
  37. package/chunks/{chunk-72LDN5PP.js → chunk-QP4R5FTG.js} +1 -1
  38. package/chunks/{chunk-3DHXZ6EV.js → chunk-SFRV6BGY.js} +6 -4
  39. package/chunks/{chunk-LEJ42GNY.js → chunk-TSBXGR73.js} +6 -6
  40. package/chunks/{chunk-PL3MVCWD.js → chunk-UOB6KPGG.js} +11 -11
  41. package/chunks/{chunk-JTQAQBTV.js → chunk-VU6A2OBJ.js} +20 -6
  42. package/chunks/{chunk-HLPLOD42.js → chunk-VXHYMZXW.js} +1 -1
  43. package/chunks/{chunk-J5MDQKJL.js → chunk-WPTCDQN6.js} +2 -347
  44. package/chunks/{chunk-SNGELLWX.js → chunk-ZMIBJS45.js} +1 -1
  45. package/chunks/{chunk-XBY7E2FX.js → chunk-ZOFNJQNJ.js} +6 -4
  46. package/chunks/computer-use-7SEQDSHB.js +2052 -0
  47. package/chunks/{contextCommand-K347QT6O.js → contextCommand-KM5OWV65.js} +23 -22
  48. package/chunks/cron-create-7CXEAJ2K.js +184 -0
  49. package/chunks/{cron-delete-WKWSJZQA.js → cron-delete-2FQYYNQ6.js} +27 -4
  50. package/chunks/{cron-list-B52XEXAZ.js → cron-list-QCAJ73XE.js} +39 -6
  51. package/chunks/{de-YGKK2BC4.js → de-FGPM4KW5.js} +18 -1
  52. package/chunks/{dist-4LXD6L6X.js → dist-2UCAYOX7.js} +2 -2
  53. package/chunks/{dist-H6ONXVLG.js → dist-33LHH26D.js} +1 -1
  54. package/chunks/{dist-PK7DFCAW.js → dist-KF43SZZV.js} +1 -1
  55. package/chunks/{dist-KAZ3SEBX.js → dist-PF2IYSMD.js} +1 -1
  56. package/chunks/{edit-KU4PJGEX.js → edit-BMUKPLA7.js} +23 -24
  57. package/chunks/{en-DHGYHIHX.js → en-VP6XPGEC.js} +5 -2
  58. package/chunks/{enter-worktree-PPYIDCWI.js → enter-worktree-LXJ5WJ5A.js} +21 -20
  59. package/chunks/{enterPlanMode-5CZDMCB4.js → enterPlanMode-QWRZ54ZF.js} +21 -20
  60. package/chunks/{exit-worktree-UY3CGHKC.js → exit-worktree-5HTQPNZO.js} +21 -20
  61. package/chunks/{exitPlanMode-3DN4QNSG.js → exitPlanMode-5WQAXNDA.js} +71 -31
  62. package/chunks/{fr-JXBKPJKQ.js → fr-ATYBVCLT.js} +18 -1
  63. package/chunks/{geminiContentGenerator-7A6I2RWB.js → geminiContentGenerator-CAKHT5YE.js} +4 -4
  64. package/chunks/{glob-OFNQSS52.js → glob-5DN6NSCD.js} +21 -20
  65. package/chunks/{grep-6J2MSUM5.js → grep-BJILOLCD.js} +30 -26
  66. package/chunks/{ja-TGPZSP2B.js → ja-W2QEA2OI.js} +18 -1
  67. package/chunks/{keychain-token-storage-6IU6ORQN.js → keychain-token-storage-QSTRHKKL.js} +2 -2
  68. package/chunks/{ls-V3O6A5PT.js → ls-XVGXRYWD.js} +3 -3
  69. package/chunks/{lsp-G2OCIFUA.js → lsp-S6SHPULC.js} +2 -2
  70. package/chunks/{monitor-FKLHV423.js → monitor-SUEMSRN3.js} +21 -20
  71. package/chunks/{notebook-edit-KTBYFKWG.js → notebook-edit-6F6Z5P6U.js} +22 -21
  72. package/chunks/{openaiContentGenerator-L5KSWQY7.js → openaiContentGenerator-DO27LL6O.js} +11 -11
  73. package/chunks/{pt-TIBG6BIO.js → pt-ZKEWJFBW.js} +18 -1
  74. package/chunks/{qwenContentGenerator-PYOXLMBW.js → qwenContentGenerator-DQLGLQSH.js} +23 -22
  75. package/chunks/{qwenOAuth2-2KCKWDCF.js → qwenOAuth2-KK433U33.js} +4 -4
  76. package/chunks/{read-file-JQVRK4NU.js → read-file-3TBLYTOQ.js} +8 -8
  77. package/chunks/{ripGrep-2L4LPNAJ.js → ripGrep-3INYT3QV.js} +21 -20
  78. package/chunks/{ru-JBCHCK4L.js → ru-VEKTPJ74.js} +18 -1
  79. package/chunks/{scheduler-FGNXY4JQ.js → scheduler-23KQW6CX.js} +21 -20
  80. package/chunks/{send-message-SZFWNOCL.js → send-message-SMNR5DBG.js} +2 -2
  81. package/chunks/{serve-N2IBLA3G.js → serve-Y5E4LKUI.js} +998 -278
  82. package/chunks/{shell-PTEG6UX4.js → shell-4H6XQXVY.js} +21 -20
  83. package/chunks/{skill-X4NTK4NH.js → skill-SE6FECZR.js} +10 -10
  84. package/chunks/{src-GLLQ3R5W.js → src-76DUBH3A.js} +42 -26
  85. package/chunks/{syntheticOutput-IKAY5F6X.js → syntheticOutput-KMNF7YG6.js} +3 -3
  86. package/chunks/{task-create-MQICOJFV.js → task-create-LIJHK75G.js} +7 -6
  87. package/chunks/{task-list-RIHJCH32.js → task-list-S4GNSILM.js} +6 -5
  88. package/chunks/{task-stop-FWZRFANS.js → task-stop-3GBRYJHM.js} +2 -2
  89. package/chunks/{task-update-2LHPXOYM.js → task-update-F3UTVJMS.js} +7 -6
  90. package/chunks/{team-create-2E4PF4KN.js → team-create-Q5DTDDH4.js} +21 -20
  91. package/chunks/{team-delete-DAUDQS4J.js → team-delete-54434EB7.js} +6 -5
  92. package/chunks/{todoWrite-HTUACZES.js → todoWrite-4ENGSBUX.js} +4 -4
  93. package/chunks/{tool-search-KTVULRES.js → tool-search-ABZMSDTU.js} +8 -8
  94. package/chunks/{web-fetch-CZ7LLKPE.js → web-fetch-RHZMF3MP.js} +4 -4
  95. package/chunks/{workflow-L2ZUUDT2.js → workflow-NEMDQB75.js} +503 -49
  96. package/chunks/{write-file-ZEB2JDYH.js → write-file-VAEHZPSL.js} +22 -21
  97. package/chunks/{zh-7H5OQC4I.js → zh-OIXDDQHB.js} +5 -2
  98. package/chunks/{zh-TW-P4IDHD3M.js → zh-TW-6YFNCKTA.js} +5 -2
  99. package/cli-entry.js +19 -0
  100. package/cli.js +6643 -4971
  101. package/locales/ca.js +20 -2
  102. package/locales/de.js +21 -2
  103. package/locales/en.js +7 -4
  104. package/locales/fr.js +22 -2
  105. package/locales/ja.js +22 -2
  106. package/locales/pt.js +21 -2
  107. package/locales/ru.js +20 -2
  108. package/locales/zh-TW.js +6 -4
  109. package/locales/zh.js +6 -4
  110. package/package.json +4 -3
  111. package/chunks/chunk-SKBPNJEW.js +0 -45
  112. package/chunks/computer-use-3RH2DOM6.js +0 -825
  113. package/chunks/cron-create-YJL3KFWI.js +0 -140
@@ -2,21 +2,21 @@
2
2
  "use strict";
3
3
  import {
4
4
  runSideQuery
5
- } from "./chunk-HLPLOD42.js";
5
+ } from "./chunk-VXHYMZXW.js";
6
6
  import "./chunk-OFEVLU4C.js";
7
7
  import {
8
8
  BaseDeclarativeTool,
9
9
  BaseToolInvocation,
10
10
  ToolDisplayNames,
11
11
  ToolNames
12
- } from "./chunk-XV4HCEVI.js";
12
+ } from "./chunk-6WPY6ES3.js";
13
13
  import {
14
14
  fetchWithTimeout,
15
15
  isPrivateIp
16
- } from "./chunk-SEGYWKIH.js";
16
+ } from "./chunk-FIQECJTQ.js";
17
17
  import {
18
18
  createDebugLogger
19
- } from "./chunk-HR7SV7AY.js";
19
+ } from "./chunk-HA2UEYZP.js";
20
20
  import "./chunk-Z2Z3GUXZ.js";
21
21
  import {
22
22
  init_esbuild_shims
@@ -1,18 +1,61 @@
1
1
  // Force strict mode and setup for ESM
2
2
  "use strict";
3
- import "./chunk-SKBPNJEW.js";
3
+ import {
4
+ AgentEventEmitter,
5
+ FileDiscoveryService,
6
+ GitWorktreeService,
7
+ WorkspaceContext,
8
+ generateAgentWorktreeSlug,
9
+ rebuildToolRegistryOnOverride,
10
+ writeWorktreeSessionMarker
11
+ } from "./chunk-H4ZDM3N6.js";
12
+ import "./chunk-K5PGHDBN.js";
13
+ import "./chunk-VXHYMZXW.js";
14
+ import "./chunk-O4PICXES.js";
15
+ import "./chunk-TW522KN6.js";
16
+ import "./chunk-BJ5HQ23U.js";
17
+ import "./chunk-SFRV6BGY.js";
18
+ import "./chunk-ZOFNJQNJ.js";
19
+ import "./chunk-WPTCDQN6.js";
20
+ import "./chunk-OMX7CUOE.js";
21
+ import "./chunk-MLZQVCF3.js";
22
+ import "./chunk-LD2XBG6Z.js";
23
+ import "./chunk-CPVI5J2L.js";
24
+ import "./chunk-ZMIBJS45.js";
25
+ import "./chunk-77WXWU44.js";
26
+ import "./chunk-B4ZF2KSI.js";
27
+ import "./chunk-A3OEZT2F.js";
28
+ import "./chunk-3PJXIDKI.js";
29
+ import "./chunk-UWCTAVOD.js";
30
+ import "./chunk-OFEVLU4C.js";
31
+ import "./chunk-IQHSD7K5.js";
32
+ import "./chunk-LYRSMKLS.js";
33
+ import {
34
+ SyntheticOutputTool
35
+ } from "./chunk-26QELEL2.js";
4
36
  import {
5
37
  BaseDeclarativeTool,
6
38
  BaseToolInvocation,
7
39
  ToolDisplayNames,
8
40
  ToolNames
9
- } from "./chunk-XV4HCEVI.js";
41
+ } from "./chunk-6WPY6ES3.js";
42
+ import "./chunk-IDYDPBBN.js";
43
+ import "./chunk-FIQECJTQ.js";
10
44
  import {
11
45
  createChildAbortController
12
46
  } from "./chunk-64WXLC72.js";
47
+ import "./chunk-LXYWINWF.js";
48
+ import "./chunk-NNIYWQIS.js";
49
+ import "./chunk-LYSND7KR.js";
50
+ import "./chunk-55ZMG67I.js";
51
+ import "./chunk-H6BD2ELD.js";
52
+ import "./chunk-5IFG2VC4.js";
13
53
  import {
14
54
  createDebugLogger
15
- } from "./chunk-HR7SV7AY.js";
55
+ } from "./chunk-HA2UEYZP.js";
56
+ import "./chunk-ZERZSAZL.js";
57
+ import "./chunk-QN5NZ3UQ.js";
58
+ import "./chunk-BR4QREVK.js";
16
59
  import "./chunk-Z2Z3GUXZ.js";
17
60
  import {
18
61
  init_esbuild_shims
@@ -317,32 +360,85 @@ function createWorkflowSandbox(opts) {
317
360
  );
318
361
  }
319
362
  }
320
- if (agentOpts.schema !== undefined) {
321
- throw new Error(
322
- 'agent({schema}) is not supported in P1. ' +
323
- 'Schema enforcement / StructuredOutput contract is scheduled for P3.'
324
- );
325
- }
326
- if (agentOpts.isolation !== undefined) {
363
+ // P3: schema + model + agentType + isolation are all wired through
364
+ // createProductionDispatch \u2192 SubagentManager.createAgentHeadless.
365
+ // The dispatch surfaces descriptive errors for "agent type not found",
366
+ // "isolation:'remote' is not available in this build", parent-dirty
367
+ // refuse, worktree creation failures, and StructuredOutput contract
368
+ // violations ("completed without calling StructuredOutput after 2
369
+ // in-conversation nudges").
370
+ if (
371
+ agentOpts.isolation !== undefined &&
372
+ agentOpts.isolation !== 'worktree' &&
373
+ agentOpts.isolation !== 'remote'
374
+ ) {
327
375
  throw new Error(
328
- "agent({isolation: '" + agentOpts.isolation + "'}) is not supported in P1. " +
329
- 'Worktree / remote isolation is scheduled for a later phase.'
376
+ "agent({isolation: '" + agentOpts.isolation + "'}): unknown isolation mode. " +
377
+ "Known modes are: 'worktree', 'remote'."
330
378
  );
331
379
  }
332
- if (agentOpts.model !== undefined) {
333
- throw new Error(
334
- 'agent({model}) is not supported in P1. Model override is scheduled for a later phase.'
335
- );
336
- }
337
- if (agentOpts.agentType !== undefined) {
338
- throw new Error('agent({agentType}) is not supported in P1.');
339
- }
340
380
  if (typeof agentOpts.phase === 'string' && agentOpts.phase.length > 0) {
341
381
  if (__b.lastPhase() !== agentOpts.phase) {
342
382
  __b.pushPhase(agentOpts.phase);
343
383
  }
344
384
  }
345
- return __b.hostAgent(prompt, agentOpts);
385
+ // SECURITY (P3 R2 self-review): user-script-controlled agentOpts
386
+ // cross the vm/host boundary verbatim via vmAsync's hostFn.apply.
387
+ // A Proxy / inherited-getter / non-plain object in agentOpts.schema
388
+ // would let host-side code (SyntheticOutputTool constructor + AJV
389
+ // compile) trigger user-controlled trap handlers that execute with
390
+ // the host realm's full surface. Revive agentOpts through JSON
391
+ // round-trip BEFORE crossing so the host only ever sees vm-realm
392
+ // plain objects with vm-realm prototypes. Same mechanism that
393
+ // makes args + parallel/pipeline results safe.
394
+ var safeOpts;
395
+ try {
396
+ safeOpts = JSON.parse(JSON.stringify(agentOpts));
397
+ } catch (e) {
398
+ throw new Error(
399
+ "agent() opts contain a non-JSON-serializable value: " +
400
+ String(e && e.message != null ? e.message : e)
401
+ );
402
+ }
403
+ // SECURITY (PR #4947 R1 wenshao, extended for P3): vmAsync's resolve
404
+ // path is verbatim (no re-wrap of resolved values). Host-realm
405
+ // strings cross the boundary harmlessly because primitives have no
406
+ // prototype identity. But P3's schema-mode dispatch returns the
407
+ // validated structured_output args as a host-realm OBJECT --
408
+ // handing that to the script reopens the T1/T8/T14 escape:
409
+ // result.constructor.constructor("return process")() would walk
410
+ // the host Object.prototype chain to the host Function
411
+ // constructor. Per-call JSON revival inside this vm runInContext
412
+ // block makes the returned object carry vm-realm prototypes (same
413
+ // mechanism as parallel/pipeline reviveInRealm and the args
414
+ // global revival). The fallback to null on a non-serializable
415
+ // resolve mirrors the errors-as-data convention parallel/pipeline
416
+ // already use for individual slot failures.
417
+ // R3 review (wenshao T3 [Suggestion]): the null fallback below is
418
+ // a SECURITY backstop, not a contract path. In schema mode the
419
+ // host return is the validated args of a structured_output tool
420
+ // call -- LLM tool_call payloads are always JSON-serializable
421
+ // (the model sends them through the OpenAI tool-call protocol
422
+ // which serializes through JSON itself) and SyntheticOutputTool's
423
+ // AJV validation runs over the parsed JSON, so a non-serializable
424
+ // host return is unreachable in production schema mode. The
425
+ // sentinel preserves the errors-as-data convention parallel /
426
+ // pipeline already use for individual slot failures, and stays as
427
+ // residual defense for any future dispatch path whose return
428
+ // value isn't a tool_call payload. logRevivalFailure surfaces
429
+ // the actionable detail (slot 0 + the error string) to operators
430
+ // so a real trigger in production isn't silent.
431
+ return __b.hostAgent(prompt, safeOpts).then(function (value) {
432
+ if (value === null || typeof value !== 'object') {
433
+ return value;
434
+ }
435
+ try {
436
+ return JSON.parse(JSON.stringify(value));
437
+ } catch (e) {
438
+ __b.logRevivalFailure(0, String(e && e.message != null ? e.message : e));
439
+ return null;
440
+ }
441
+ });
346
442
  });
347
443
 
348
444
  // --- parallel / pipeline ---
@@ -513,6 +609,7 @@ __name(createWorkflowSandbox, "createWorkflowSandbox");
513
609
  // packages/core/src/agents/runtime/workflow-prompts.ts
514
610
  init_esbuild_shims();
515
611
  var WORKFLOW_SUBAGENT_SYSTEM_PROMPT = 'You are a subagent spawned by a workflow orchestration script. Use the tools available to complete the task.\nCRITICAL: Your final text response is returned **verbatim** as a string to the calling script \u2014 it is your return value, not a message to a human.\n- Output the literal result (data, JSON, text). Do NOT output confirmations like "Done." or "Sent."\n- If asked for JSON, return ONLY the raw JSON \u2014 no code fences, no prose, no markdown.\n- Do NOT use SendUserMessage to deliver your answer. Put your answer in your final text response.\n- Be concise. The script will parse your output.';
612
+ var WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA = "You are a subagent spawned by a workflow orchestration script. Use the tools available to complete the task.\nCRITICAL: You MUST deliver your final answer by calling the `structured_output` tool with arguments that conform to its parameter schema. Plain-text final answers are DISCARDED \u2014 only a valid `structured_output` call returns a result to the calling script.\n- Use other tools (Read, Grep, etc.) to gather information first.\n- When ready, call `structured_output` ONCE with the conforming JSON object.\n- If validation fails, the error tells you what to fix. Try again with corrected fields.\n- After two failed attempts, the run terminates \u2014 get the arguments right.\n- Do NOT use SendUserMessage to deliver your answer.\n- Be concise; the script reads only the structured payload, not your prose.";
516
613
 
517
614
  // packages/core/src/utils/concurrencyLimiter.ts
518
615
  init_esbuild_shims();
@@ -635,43 +732,400 @@ function generateRunId() {
635
732
  return `wf_${randomBytes(8).toString("hex")}`;
636
733
  }
637
734
  __name(generateRunId, "generateRunId");
735
+ function sanitizeForErrorMessage(value) {
736
+ return value.replace(/[\u0000-\u001f\u007f]+/g, " ");
737
+ }
738
+ __name(sanitizeForErrorMessage, "sanitizeForErrorMessage");
638
739
  function createProductionDispatch(config, signal) {
639
740
  return async (prompt, opts) => {
640
- const { AgentHeadless, ContextState } = await import("./agent-headless-TU3EPMYU.js");
741
+ const { AgentHeadless, ContextState } = await import("./agent-headless-SY7VJUHV.js");
641
742
  const ctx = new ContextState();
642
743
  ctx.set("task_prompt", prompt);
643
- const subagent = await AgentHeadless.create(
644
- opts.label ?? "workflow-agent",
744
+ if (opts.agentType === void 0 && opts.model === void 0 && opts.isolation === void 0 && opts.schema === void 0) {
745
+ const subagent = await AgentHeadless.create(
746
+ opts.label ?? "workflow-agent",
747
+ config,
748
+ {
749
+ systemPrompt: WORKFLOW_SUBAGENT_SYSTEM_PROMPT,
750
+ initialMessages: []
751
+ },
752
+ {},
753
+ // T11 (PR #4732 R1): bound resource ceiling so a single agent() call
754
+ // cannot loop the model indefinitely. Without this, runConfig was {}
755
+ // and the loop guards never tripped — combined with the cancellation
756
+ // bug below, workflows were effectively unkillable.
757
+ {
758
+ max_turns: WORKFLOW_SUBAGENT_MAX_TURNS,
759
+ max_time_minutes: WORKFLOW_SUBAGENT_MAX_TIME_MINUTES
760
+ },
761
+ // T11 (PR #4732 R1): disallow SendMessage / ExitPlanMode to align with
762
+ // upstream Tg8 — closes the back-channel that would let a subagent
763
+ // deliver its answer via user message instead of the script's read.
764
+ { tools: ["*"], disallowedTools: WORKFLOW_SUBAGENT_DISALLOWED_TOOLS }
765
+ );
766
+ await subagent.execute(ctx, signal);
767
+ const mode = subagent.getTerminateMode();
768
+ if (mode !== "GOAL" /* GOAL */) {
769
+ throw new Error(
770
+ `Workflow subagent did not complete (terminate mode: ${mode}).`
771
+ );
772
+ }
773
+ return subagent.getFinalText();
774
+ }
775
+ return runOverridePath(config, ctx, opts, signal);
776
+ };
777
+ }
778
+ __name(createProductionDispatch, "createProductionDispatch");
779
+ async function runOverridePath(config, ctx, opts, signal) {
780
+ if (opts.isolation === "remote") {
781
+ throw new Error(
782
+ "agent({isolation:'remote'}) is not available in this build."
783
+ );
784
+ }
785
+ const subagentMgr = config.getSubagentManager();
786
+ let baseConfig;
787
+ if (opts.agentType !== void 0) {
788
+ const resolved = await subagentMgr.findSubagentByName(opts.agentType);
789
+ if (!resolved) {
790
+ const safeAgentType = sanitizeForErrorMessage(opts.agentType);
791
+ throw new Error(
792
+ `agent({agentType}): agent type '${safeAgentType}' not found.`
793
+ );
794
+ }
795
+ baseConfig = resolved;
796
+ } else {
797
+ baseConfig = {
798
+ name: opts.label ?? "workflow-agent",
799
+ description: "Default workflow subagent (per-call overrides).",
800
+ systemPrompt: WORKFLOW_SUBAGENT_SYSTEM_PROMPT,
801
+ level: "session",
802
+ isBuiltin: false
803
+ };
804
+ }
805
+ let schemaSystemPrompt;
806
+ if (opts.schema !== void 0) {
807
+ schemaSystemPrompt = opts.agentType !== void 0 && baseConfig.systemPrompt ? `${baseConfig.systemPrompt}
808
+
809
+ ${WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA}` : WORKFLOW_SUBAGENT_SYSTEM_PROMPT_WITH_SCHEMA;
810
+ }
811
+ let schemaTools;
812
+ if (opts.schema !== void 0 && baseConfig.tools && baseConfig.tools.length > 0 && !baseConfig.tools.includes("*") && !baseConfig.tools.includes(ToolNames.STRUCTURED_OUTPUT)) {
813
+ schemaTools = [...baseConfig.tools, ToolNames.STRUCTURED_OUTPUT];
814
+ }
815
+ const augmented = {
816
+ ...baseConfig,
817
+ ...opts.model !== void 0 ? { model: opts.model } : {},
818
+ ...schemaSystemPrompt !== void 0 ? { systemPrompt: schemaSystemPrompt } : {},
819
+ ...schemaTools !== void 0 ? { tools: schemaTools } : {},
820
+ disallowedTools: Array.from(
821
+ /* @__PURE__ */ new Set([
822
+ ...baseConfig.disallowedTools ?? [],
823
+ ...WORKFLOW_SUBAGENT_DISALLOWED_TOOLS
824
+ ])
825
+ )
826
+ };
827
+ let worktreeIsolation = null;
828
+ let effectiveContext = config;
829
+ if (opts.isolation === "worktree") {
830
+ worktreeIsolation = await provisionWorkflowWorktree(config);
831
+ effectiveContext = createWorktreeConfigOverride(
645
832
  config,
833
+ worktreeIsolation.path
834
+ );
835
+ }
836
+ let onParentAbort;
837
+ try {
838
+ let schemaState = null;
839
+ if (opts.schema !== void 0) {
840
+ effectiveContext = await createSchemaConfigOverride(
841
+ effectiveContext,
842
+ opts.schema
843
+ );
844
+ schemaState = createSchemaModeState();
845
+ }
846
+ let dispatchSignal = signal;
847
+ if (schemaState) {
848
+ const child = new AbortController();
849
+ if (signal) {
850
+ if (signal.aborted) {
851
+ child.abort(signal.reason);
852
+ } else {
853
+ onParentAbort = /* @__PURE__ */ __name(() => child.abort(signal.reason), "onParentAbort");
854
+ signal.addEventListener("abort", onParentAbort);
855
+ }
856
+ }
857
+ schemaState.abortController = child;
858
+ dispatchSignal = child.signal;
859
+ }
860
+ const eventEmitter = schemaState ? createSchemaEventEmitter(schemaState) : void 0;
861
+ const { subagent, dispose } = await subagentMgr.createAgentHeadless(
862
+ augmented,
863
+ effectiveContext,
646
864
  {
647
- systemPrompt: WORKFLOW_SUBAGENT_SYSTEM_PROMPT,
648
- initialMessages: []
649
- },
650
- {},
651
- // T11 (PR #4732 R1): bound resource ceiling so a single agent() call
652
- // cannot loop the model indefinitely. Without this, runConfig was {}
653
- // and the loop guards never tripped — combined with the cancellation
654
- // bug below, workflows were effectively unkillable.
655
- {
656
- max_turns: WORKFLOW_SUBAGENT_MAX_TURNS,
657
- max_time_minutes: WORKFLOW_SUBAGENT_MAX_TIME_MINUTES
658
- },
659
- // T11 (PR #4732 R1): disallow SendMessage / ExitPlanMode to align with
660
- // upstream Tg8 — closes the back-channel that would let a subagent
661
- // deliver its answer via user message instead of the script's read.
662
- { tools: ["*"], disallowedTools: WORKFLOW_SUBAGENT_DISALLOWED_TOOLS }
865
+ // Workflow always bounds resource ceiling regardless of agentType's
866
+ // own runConfig / maxTurns — these are workflow-level safety bounds,
867
+ // not subagent-level preferences. P5 will refine via budget.
868
+ runConfigOverrides: {
869
+ max_turns: WORKFLOW_SUBAGENT_MAX_TURNS,
870
+ max_time_minutes: WORKFLOW_SUBAGENT_MAX_TIME_MINUTES
871
+ },
872
+ eventEmitter
873
+ }
663
874
  );
664
- await subagent.execute(ctx, signal);
665
- const mode = subagent.getTerminateMode();
666
- if (mode !== "GOAL" /* GOAL */) {
667
- throw new Error(
668
- `Workflow subagent did not complete (terminate mode: ${mode}).`
875
+ try {
876
+ await subagent.execute(ctx, dispatchSignal);
877
+ if (schemaState) {
878
+ if (schemaState.result !== null) {
879
+ if (worktreeIsolation) {
880
+ const isolation = worktreeIsolation;
881
+ worktreeIsolation = null;
882
+ const preserved = await cleanupWorkflowWorktree(isolation);
883
+ if (preserved) {
884
+ debugLogger.info(
885
+ `[Workflow] Schema-mode subagent preserved worktree at ${preserved.path ?? "(directory removed)"} on branch ${preserved.branch}. The structured payload is returned verbatim; recover the work from the preserved path / branch.`
886
+ );
887
+ }
888
+ }
889
+ return schemaState.result;
890
+ }
891
+ if (signal?.aborted) {
892
+ throw new DOMException("Workflow aborted.", "AbortError");
893
+ }
894
+ const mode2 = subagent.getTerminateMode();
895
+ if (mode2 !== "GOAL" /* GOAL */ && mode2 !== "CANCELLED" /* CANCELLED */) {
896
+ throw new Error(
897
+ `Workflow subagent did not complete (terminate mode: ${mode2}).`
898
+ );
899
+ }
900
+ if (schemaState.attempts > 2) {
901
+ throw new Error(
902
+ "subagent completed without calling StructuredOutput (after 2 in-conversation nudges)."
903
+ );
904
+ }
905
+ throw new Error(
906
+ "subagent completed without calling structured_output (no validation attempt \u2014 model produced plain-text content)."
907
+ );
908
+ }
909
+ const mode = subagent.getTerminateMode();
910
+ if (mode !== "GOAL" /* GOAL */) {
911
+ throw new Error(
912
+ `Workflow subagent did not complete (terminate mode: ${mode}).`
913
+ );
914
+ }
915
+ let finalText = subagent.getFinalText();
916
+ if (worktreeIsolation) {
917
+ const isolation = worktreeIsolation;
918
+ worktreeIsolation = null;
919
+ const preserved = await cleanupWorkflowWorktree(isolation);
920
+ if (preserved && typeof finalText === "string") {
921
+ finalText = appendWorktreePreservedSuffix(finalText, preserved);
922
+ }
923
+ }
924
+ return finalText;
925
+ } finally {
926
+ await dispose();
927
+ }
928
+ } finally {
929
+ if (onParentAbort && signal) {
930
+ signal.removeEventListener("abort", onParentAbort);
931
+ }
932
+ if (worktreeIsolation) {
933
+ try {
934
+ await cleanupWorkflowWorktree(worktreeIsolation);
935
+ } catch (error) {
936
+ debugLogger.warn(
937
+ `Workflow worktree cleanup in fallback finally failed for ${worktreeIsolation.path}: ${error instanceof Error ? error.message : String(error)}`
938
+ );
939
+ }
940
+ }
941
+ }
942
+ }
943
+ __name(runOverridePath, "runOverridePath");
944
+ async function provisionWorkflowWorktree(config) {
945
+ const cwd = config.getTargetDir();
946
+ if (/\.qwen[\\/]worktrees[\\/]/.test(cwd)) {
947
+ throw new Error(
948
+ `agent({isolation:'worktree'}): parent is already inside a worktree (${cwd}). Nested isolation worktrees are not supported \u2014 the subagent's inherited paths would still reference the outer worktree.`
949
+ );
950
+ }
951
+ const probe = new GitWorktreeService(cwd);
952
+ const gitCheck = await probe.checkGitAvailable();
953
+ if (!gitCheck.available) {
954
+ throw new Error(
955
+ `agent({isolation:'worktree'}): ${gitCheck.error ?? "git is not available"}.`
956
+ );
957
+ }
958
+ if (!await probe.isGitRepository()) {
959
+ throw new Error(
960
+ `agent({isolation:'worktree'}): ${cwd} is not a git repository.`
961
+ );
962
+ }
963
+ const projectRoot = await probe.getRepoTopLevel() ?? cwd;
964
+ const wtService = projectRoot === cwd ? probe : new GitWorktreeService(projectRoot);
965
+ let parentDirty = false;
966
+ try {
967
+ parentDirty = await wtService.hasWorktreeChanges(projectRoot);
968
+ } catch (error) {
969
+ debugLogger.warn(
970
+ `[Workflow] hasWorktreeChanges failed at ${projectRoot}: ${error}`
971
+ );
972
+ parentDirty = true;
973
+ }
974
+ if (parentDirty) {
975
+ throw new Error(
976
+ `agent({isolation:'worktree'}): parent working tree at ${projectRoot} has uncommitted changes that would not propagate into the isolated worktree. The subagent would see the prior HEAD instead of the current state. Commit or stash the changes, then re-run.`
977
+ );
978
+ }
979
+ const slug = generateAgentWorktreeSlug();
980
+ let parentBranch;
981
+ try {
982
+ parentBranch = await wtService.getCurrentBranch();
983
+ } catch (error) {
984
+ debugLogger.warn(
985
+ `[Workflow] getCurrentBranch failed at ${projectRoot}: ${error}`
986
+ );
987
+ }
988
+ const created = await wtService.createUserWorktree(slug, parentBranch, {
989
+ symlinkDirectories: config.getWorktreeSymlinkDirectories()
990
+ });
991
+ if (!created.success || !created.worktree) {
992
+ throw new Error(
993
+ `agent({isolation:'worktree'}): failed to create worktree: ${created.error ?? "unknown error"}.`
994
+ );
995
+ }
996
+ try {
997
+ await writeWorktreeSessionMarker(
998
+ created.worktree.path,
999
+ config.getSessionId()
1000
+ );
1001
+ } catch (error) {
1002
+ debugLogger.warn(
1003
+ `[Workflow] failed to write session marker at ${created.worktree.path}: ${error}`
1004
+ );
1005
+ }
1006
+ return {
1007
+ slug,
1008
+ path: created.worktree.path,
1009
+ branch: created.worktree.branch,
1010
+ repoRoot: projectRoot
1011
+ };
1012
+ }
1013
+ __name(provisionWorkflowWorktree, "provisionWorkflowWorktree");
1014
+ function createWorktreeConfigOverride(base, wtPath) {
1015
+ const ov = Object.create(base);
1016
+ ov.targetDir = wtPath;
1017
+ ov.cwd = wtPath;
1018
+ ov.getTargetDir = () => wtPath;
1019
+ ov.getCwd = () => wtPath;
1020
+ ov.getWorkingDir = () => wtPath;
1021
+ ov.getProjectRoot = () => wtPath;
1022
+ const wtFileService = new FileDiscoveryService(wtPath);
1023
+ ov.fileDiscoveryService = wtFileService;
1024
+ ov.getFileService = () => wtFileService;
1025
+ const wtWorkspace = new WorkspaceContext(wtPath);
1026
+ ov.workspaceContext = wtWorkspace;
1027
+ ov.getWorkspaceContext = () => wtWorkspace;
1028
+ return ov;
1029
+ }
1030
+ __name(createWorktreeConfigOverride, "createWorktreeConfigOverride");
1031
+ async function cleanupWorkflowWorktree(isolation) {
1032
+ const wtService = new GitWorktreeService(isolation.repoRoot);
1033
+ const [hasChanges, hasUnmerged] = await Promise.all([
1034
+ wtService.hasWorktreeChanges(isolation.path).catch((error) => {
1035
+ debugLogger.warn(
1036
+ `[Workflow] hasWorktreeChanges failed for ${isolation.path}: ${error}`
1037
+ );
1038
+ return true;
1039
+ }),
1040
+ wtService.hasUnmergedWorktreeCommits(isolation.slug).catch((error) => {
1041
+ debugLogger.warn(
1042
+ `[Workflow] hasUnmergedWorktreeCommits failed for ${isolation.slug}: ${error}`
1043
+ );
1044
+ return true;
1045
+ })
1046
+ ]);
1047
+ if (hasChanges || hasUnmerged) {
1048
+ debugLogger.info(
1049
+ `[Workflow] Preserving isolation worktree ${isolation.path} (branch ${isolation.branch}, hasChanges=${hasChanges}, hasUnmerged=${hasUnmerged})`
1050
+ );
1051
+ return { path: isolation.path, branch: isolation.branch };
1052
+ }
1053
+ try {
1054
+ const result = await wtService.removeUserWorktree(isolation.slug, {
1055
+ deleteBranch: true
1056
+ });
1057
+ if (!result.success) {
1058
+ debugLogger.warn(
1059
+ `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${result.error}`
1060
+ );
1061
+ return { path: isolation.path, branch: isolation.branch };
1062
+ }
1063
+ if (result.branchPreserved) {
1064
+ debugLogger.warn(
1065
+ `[Workflow] Removed worktree directory ${isolation.path} but kept branch ${isolation.branch} (unmerged commits at delete time)`
669
1066
  );
1067
+ return { branch: isolation.branch };
670
1068
  }
671
- return subagent.getFinalText();
1069
+ } catch (error) {
1070
+ debugLogger.warn(
1071
+ `[Workflow] Failed to remove ephemeral worktree ${isolation.path}: ${error}`
1072
+ );
1073
+ return { path: isolation.path, branch: isolation.branch };
1074
+ }
1075
+ return null;
1076
+ }
1077
+ __name(cleanupWorkflowWorktree, "cleanupWorkflowWorktree");
1078
+ function appendWorktreePreservedSuffix(finalText, preserved) {
1079
+ const sep = finalText.endsWith("\n") ? "\n" : "\n\n";
1080
+ if (preserved.path) {
1081
+ return `${finalText}${sep}[worktree preserved: ${preserved.path} (branch ${preserved.branch})]`;
1082
+ }
1083
+ return `${finalText}${sep}[worktree directory removed; branch ${preserved.branch} preserved \u2014 recover with \`git worktree add <path> ${preserved.branch}\`]`;
1084
+ }
1085
+ __name(appendWorktreePreservedSuffix, "appendWorktreePreservedSuffix");
1086
+ function createSchemaModeState() {
1087
+ return {
1088
+ result: null,
1089
+ attempts: 0,
1090
+ pendingArgs: /* @__PURE__ */ new Map(),
1091
+ abortController: new AbortController()
672
1092
  };
673
1093
  }
674
- __name(createProductionDispatch, "createProductionDispatch");
1094
+ __name(createSchemaModeState, "createSchemaModeState");
1095
+ function createSchemaEventEmitter(state) {
1096
+ const emitter = new AgentEventEmitter();
1097
+ const targetTool = ToolNames.STRUCTURED_OUTPUT;
1098
+ emitter.on("tool_call" /* TOOL_CALL */, (evt) => {
1099
+ if (evt.name !== targetTool) return;
1100
+ state.pendingArgs.set(evt.callId, evt.args);
1101
+ });
1102
+ emitter.on("tool_result" /* TOOL_RESULT */, (evt) => {
1103
+ if (evt.name !== targetTool) return;
1104
+ const args = state.pendingArgs.get(evt.callId);
1105
+ state.pendingArgs.delete(evt.callId);
1106
+ if (evt.success) {
1107
+ if (args !== void 0 && state.result === null) {
1108
+ state.result = args;
1109
+ state.abortController.abort();
1110
+ }
1111
+ return;
1112
+ }
1113
+ state.attempts += 1;
1114
+ if (state.attempts > 2 && state.result === null) {
1115
+ state.abortController.abort();
1116
+ }
1117
+ });
1118
+ return emitter;
1119
+ }
1120
+ __name(createSchemaEventEmitter, "createSchemaEventEmitter");
1121
+ async function createSchemaConfigOverride(base, schema) {
1122
+ const override = Object.create(base);
1123
+ await rebuildToolRegistryOnOverride(override, base);
1124
+ const registry = override.getToolRegistry();
1125
+ registry.registerTool(new SyntheticOutputTool(schema));
1126
+ return override;
1127
+ }
1128
+ __name(createSchemaConfigOverride, "createSchemaConfigOverride");
675
1129
  var WorkflowOrchestrator = class {
676
1130
  constructor(dispatch) {
677
1131
  this.dispatch = dispatch;
@@ -809,7 +1263,7 @@ var WORKFLOW_PARAM_SCHEMA = {
809
1263
  properties: {
810
1264
  script: {
811
1265
  type: "string",
812
- description: "JavaScript source of the workflow. Wrapped as an async IIFE. May call the injected globals `phase(title)`, `log(msg)`, `agent(prompt, { label? })`, and read `args`. Concurrency: `parallel([() => agent(...), ...])` runs thunks through a shared per-run window (default `max(1, min(16, cpus-2))` agents in flight; override via `QWEN_CODE_MAX_WORKFLOW_CONCURRENCY`) and resolves to a position-aligned array \u2014 a thunk that throws, or resolves to a non-JSON-serializable value, becomes `null` at its index (errors-as-data); parallel() itself rejects only on invalid arguments or abort. `pipeline(items, ...stages)` runs each item through the stages (staggered, no inter-stage barrier); a stage that throws, returns `null`, or returns a non-JSON-serializable value drops that item to `null`. Pass THUNKS to parallel, not eager calls: `parallel([() => agent(...)])`, not `parallel([agent(...)])`. At most 1000 agent() calls per run (override via `QWEN_CODE_MAX_WORKFLOW_AGENTS`). `Date.now()` and `Math.random()` both throw \u2014 workflow scripts must be deterministic for resume. `export const meta = {...}` declarations are stripped before execution."
1266
+ description: "JavaScript source of the workflow. Wrapped as an async IIFE. May call the injected globals `phase(title)`, `log(msg)`, `agent(prompt, opts?)`, and read `args`. agent() opts: `{ label?, phase?, schema?, model?, agentType?, isolation? }`. `schema` (JSON Schema object): the subagent must deliver its result by calling `structured_output` with arguments matching the schema; agent() resolves to the validated object. Two failed attempts produce a terminal error \"subagent completed without calling StructuredOutput (after 2 in-conversation nudges)\". `agentType` (string): resolves against the declarative-agents registry (`.qwen/agents/<name>.md`, project then user then built-in). Unresolved names throw \"agent({agentType}): agent type 'X' not found\". `model` (string): per-call model override; routes provider correctly via the subagent runtime view. `isolation`: `'worktree'` provisions a fresh git worktree under `<projectRoot>/.qwen/worktrees/agent-<7hex>`; the worktree is auto-removed if no changes, otherwise the path and branch are returned alongside the result. `'remote'` throws \"agent({isolation:'remote'}) is not available in this build\" (parity with upstream). isolation=worktree refuses to run when the parent working tree has uncommitted changes (the subagent would see a stale HEAD). Workflow subagents always have SendMessage / ExitPlanMode in their disallowed-tool floor regardless of agentType. Concurrency: `parallel([() => agent(...), ...])` runs thunks through a shared per-run window (default `max(1, min(16, cpus-2))` agents in flight; override via `QWEN_CODE_MAX_WORKFLOW_CONCURRENCY`) and resolves to a position-aligned array \u2014 a thunk that throws, or resolves to a non-JSON-serializable value, becomes `null` at its index (errors-as-data); parallel() itself rejects only on invalid arguments or abort. `pipeline(items, ...stages)` runs each item through the stages (staggered, no inter-stage barrier); a stage that throws, returns `null`, or returns a non-JSON-serializable value drops that item to `null`. Pass THUNKS to parallel, not eager calls: `parallel([() => agent(...)])`, not `parallel([agent(...)])`. At most 1000 agent() calls per run (override via `QWEN_CODE_MAX_WORKFLOW_AGENTS`). `Date.now()` and `Math.random()` both throw \u2014 workflow scripts must be deterministic for resume. `export const meta = {...}` declarations are stripped before execution."
813
1267
  },
814
1268
  args: {
815
1269
  description: "Optional structured value bound to the `args` global. Pass actual JSON, not a stringified value."
@@ -926,7 +1380,7 @@ var WorkflowTool = class extends BaseDeclarativeTool {
926
1380
  super(
927
1381
  ToolNames.WORKFLOW,
928
1382
  ToolDisplayNames.WORKFLOW,
929
- "Execute a workflow script that orchestrates subagents. Supports `phase`, `log`, sequential `agent`, and concurrent fan-out via `parallel(thunks)` / `pipeline(items, ...stages)` (default `max(1, min(16, cpus-2))` agents in flight per run, up to 1000 agents total; both env-overridable). No schema, no resume, no background execution yet. Scripts run in a node:vm sandbox without access to the filesystem or shell; all I/O happens through the spawned agents.",
1383
+ "Execute a workflow script that orchestrates subagents. Supports `phase`, `log`, sequential `agent`, concurrent fan-out via `parallel(thunks)` / `pipeline(items, ...stages)` (default `max(1, min(16, cpus-2))` agents in flight per run, up to 1000 agents total; both env-overridable), per-call `agent({ schema, agentType, model, isolation: 'worktree' })` for structured-output contracts, declarative-agent selection, model override, and git-worktree-isolated subagents. No resume and no background execution yet (scheduled for later phases). Scripts run in a node:vm sandbox without access to the filesystem or shell; all I/O happens through the spawned agents.",
930
1384
  "other" /* Other */,
931
1385
  WORKFLOW_PARAM_SCHEMA,
932
1386
  /* isOutputMarkdown */