@promptbook/cli 0.114.0-24 → 0.114.0-26

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 (41) hide show
  1. package/README.md +2 -2
  2. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimePm2.ts +56 -10
  3. package/apps/agents-server/src/utils/userChat/createImmediateUserChatAnswerModelRequirements.ts +1 -0
  4. package/esm/index.es.js +256 -59
  5. package/esm/index.es.js.map +1 -1
  6. package/esm/scripts/run-codex-prompts/runners/common/estimateUsageFromTextLength.d.ts +33 -0
  7. package/esm/scripts/run-codex-prompts/runners/common/modelPricing.d.ts +41 -0
  8. package/esm/scripts/run-codex-prompts/runners/gemini/gemini-pricing.d.ts +5 -18
  9. package/esm/scripts/run-codex-prompts/runners/qwen-code/QwenCodeRunner.d.ts +23 -0
  10. package/esm/scripts/run-codex-prompts/runners/qwen-code/buildQwenCodeScript.d.ts +8 -0
  11. package/esm/scripts/run-codex-prompts/runners/qwen-code/parseQwenCodeUsageFromOutput.d.ts +9 -0
  12. package/esm/scripts/run-codex-prompts/runners/qwen-code/qwen-code-pricing.d.ts +30 -0
  13. package/esm/src/book-3.0/cliAgentEnv.d.ts +3 -3
  14. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +8 -2
  15. package/esm/src/commitments/WRITING_RULES/WRITING_RULES.d.ts +14 -7
  16. package/esm/src/commitments/index.d.ts +1 -1
  17. package/esm/src/version.d.ts +1 -1
  18. package/package.json +1 -1
  19. package/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.ts +1 -0
  20. package/src/book-3.0/cliAgentEnv.ts +3 -2
  21. package/src/cli/cli-commands/common/harness/HarnessDefinition.ts +6 -0
  22. package/src/cli/cli-commands/common/promptRunnerCliOptions.ts +14 -8
  23. package/src/commitments/WRITING_RULES/WRITING_RULES.ts +16 -8
  24. package/src/commitments/index.ts +2 -1
  25. package/src/other/templates/getTemplatesPipelineCollection.ts +859 -739
  26. package/src/version.ts +2 -2
  27. package/src/versions.txt +2 -0
  28. package/umd/index.umd.js +256 -59
  29. package/umd/index.umd.js.map +1 -1
  30. package/umd/scripts/run-codex-prompts/runners/common/estimateUsageFromTextLength.d.ts +33 -0
  31. package/umd/scripts/run-codex-prompts/runners/common/modelPricing.d.ts +41 -0
  32. package/umd/scripts/run-codex-prompts/runners/gemini/gemini-pricing.d.ts +5 -18
  33. package/umd/scripts/run-codex-prompts/runners/qwen-code/QwenCodeRunner.d.ts +23 -0
  34. package/umd/scripts/run-codex-prompts/runners/qwen-code/buildQwenCodeScript.d.ts +8 -0
  35. package/umd/scripts/run-codex-prompts/runners/qwen-code/parseQwenCodeUsageFromOutput.d.ts +9 -0
  36. package/umd/scripts/run-codex-prompts/runners/qwen-code/qwen-code-pricing.d.ts +30 -0
  37. package/umd/src/book-3.0/cliAgentEnv.d.ts +3 -3
  38. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +8 -2
  39. package/umd/src/commitments/WRITING_RULES/WRITING_RULES.d.ts +14 -7
  40. package/umd/src/commitments/index.d.ts +1 -1
  41. package/umd/src/version.d.ts +1 -1
package/src/version.ts CHANGED
@@ -16,11 +16,11 @@ export const BOOK_LANGUAGE_VERSION: string_semantic_version = '2.0.0';
16
16
  * @generated
17
17
  * @see https://github.com/webgptorg/promptbook
18
18
  */
19
- export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.114.0-24';
19
+ export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.114.0-26';
20
20
 
21
21
  /**
22
22
  * Represents the version string of the Promptbook engine.
23
- * It follows semantic versioning (e.g., `0.114.0-23`).
23
+ * It follows semantic versioning (e.g., `0.114.0-25`).
24
24
  *
25
25
  * @generated
26
26
  */
package/src/versions.txt CHANGED
@@ -1200,3 +1200,5 @@
1200
1200
  0.114.0-22
1201
1201
  0.114.0-23
1202
1202
  0.114.0-24
1203
+ 0.114.0-25
1204
+ 0.114.0-26
package/umd/index.umd.js CHANGED
@@ -58,7 +58,7 @@
58
58
  * @generated
59
59
  * @see https://github.com/webgptorg/promptbook
60
60
  */
61
- const PROMPTBOOK_ENGINE_VERSION = '0.114.0-24';
61
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-26';
62
62
  /**
63
63
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
64
64
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1731,6 +1731,7 @@
1731
1731
  'claude-code',
1732
1732
  'opencode',
1733
1733
  'gemini',
1734
+ 'qwen-code',
1734
1735
  ];
1735
1736
  /**
1736
1737
  * All supported thinking-level values for CLI coding-agent runners.
@@ -1741,8 +1742,8 @@
1741
1742
  /**
1742
1743
  * Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
1743
1744
  *
1744
- * Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`)
1745
- * so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
1745
+ * Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`,
1746
+ * `qwen-code`) so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
1746
1747
  *
1747
1748
  * @public exported from `@promptbook/node`
1748
1749
  */
@@ -1827,23 +1828,31 @@
1827
1828
  - claude-code: Claude Code integration
1828
1829
  - opencode: Opencode integration
1829
1830
  - gemini: Google Gemini CLI integration (requires --model)
1831
+ - qwen-code: Qwen Code CLI integration (requires --model)
1830
1832
  `);
1831
1833
  /**
1832
1834
  * Commander description for the `--harness` option.
1833
1835
  *
1834
1836
  * @private internal utility of `promptbookCli`
1835
1837
  */
1836
- const PROMPT_RUNNER_HARNESS_OPTION_DESCRIPTION = 'Select runner: openai-codex, github-copilot, cline, claude-code, opencode, gemini (required for non-dry-run)';
1838
+ const PROMPT_RUNNER_HARNESS_OPTION_DESCRIPTION = `Select runner: ${PROMPT_RUNNER_HARNESS_NAMES.join(', ')} (required for non-dry-run)`;
1839
+ /**
1840
+ * Runner harness names listed as alternatives of the `--harness` option in error messages.
1841
+ *
1842
+ * @private internal utility of `promptbookCli`
1843
+ */
1844
+ const PROMPT_RUNNER_HARNESS_OPTION_HINT = `--harness <${PROMPT_RUNNER_HARNESS_NAMES.join('|')}>`;
1837
1845
  /**
1838
1846
  * Commander description for the `--model` option.
1839
1847
  *
1840
1848
  * @private internal utility of `promptbookCli`
1841
1849
  */
1842
1850
  const PROMPT_RUNNER_MODEL_OPTION_DESCRIPTION = _spaceTrim.spaceTrim(`
1843
- Model to use (required for openai-codex and gemini)
1851
+ Model to use (required for openai-codex, gemini and qwen-code)
1844
1852
 
1845
1853
  OpenAI examples: gpt-5.2-codex, default
1846
1854
  Gemini examples: gemini-3-flash-preview, default
1855
+ Qwen examples: qwen3.8-max, default
1847
1856
  `);
1848
1857
  /**
1849
1858
  * Commander description for the `--git-changes` option.
@@ -1931,7 +1940,7 @@
1931
1940
  if (!options.isAgentRequired) {
1932
1941
  return undefined;
1933
1942
  }
1934
- throw new Error(colors__default["default"].red('You must choose a harness using --harness <openai-codex|github-copilot|cline|claude-code|opencode|gemini>'));
1943
+ throw new Error(colors__default["default"].red(`You must choose a harness using ${PROMPT_RUNNER_HARNESS_OPTION_HINT}`));
1935
1944
  }
1936
1945
  if (isPromptRunnerHarnessName(harness)) {
1937
1946
  return harness;
@@ -20064,29 +20073,36 @@
20064
20073
  /**
20065
20074
  * `WRITING RULES` commitment definition.
20066
20075
  *
20067
- * It adds constraints that apply strictly to writing style and presentation
20068
- * rather than task-solving behavior.
20076
+ * The `WRITING RULES`/`WRITING RULE` commitment adds constraints that apply strictly to writing style
20077
+ * and presentation rather than task-solving behavior.
20078
+ *
20079
+ * Example usage in agent source:
20080
+ *
20081
+ * ```book
20082
+ * WRITING RULES Keep every response under 120 words
20083
+ * WRITING RULE Always end the message with an emoji
20084
+ * ```
20069
20085
  *
20070
20086
  * @private [🪔] Maybe export the commitments through some package
20071
20087
  */
20072
20088
  class WritingRulesCommitmentDefinition extends BaseCommitmentDefinition {
20073
- constructor() {
20074
- super('WRITING RULES');
20089
+ constructor(type = 'WRITING RULES') {
20090
+ super(type);
20075
20091
  }
20076
20092
  /**
20077
- * Short one-line description of `WRITING RULES`.
20093
+ * Short one-line description of `WRITING RULES`/`WRITING RULE`.
20078
20094
  */
20079
20095
  get description() {
20080
20096
  return 'Add writing-only constraints such as tone, length, formatting, or emoji usage.';
20081
20097
  }
20082
20098
  /**
20083
- * Icon for `WRITING RULES`.
20099
+ * Icon for `WRITING RULES`/`WRITING RULE`.
20084
20100
  */
20085
20101
  get icon() {
20086
20102
  return '📝';
20087
20103
  }
20088
20104
  /**
20089
- * Markdown documentation for `WRITING RULES`.
20105
+ * Markdown documentation for `WRITING RULES`/`WRITING RULE` commitment.
20090
20106
  */
20091
20107
  get documentation() {
20092
20108
  return _spaceTrim.spaceTrim(`
@@ -20096,6 +20112,7 @@
20096
20112
 
20097
20113
  ## Key aspects
20098
20114
 
20115
+ - All writing rules are treated equally regardless of singular/plural form.
20099
20116
  - Use it for writing-only constraints such as tone, formatting, length, emoji usage, punctuation, or reading level.
20100
20117
  - Do **not** use it for problem-solving behavior, policy, tool usage, or decision-making logic. Use \`RULE\` for that.
20101
20118
  - Newer writing-rules blocks override conflicting earlier writing-rules blocks.
@@ -20294,7 +20311,8 @@
20294
20311
  new LanguageCommitmentDefinition('LANGUAGE'),
20295
20312
  new LanguageCommitmentDefinition('LANGUAGES'),
20296
20313
  new WritingSampleCommitmentDefinition(),
20297
- new WritingRulesCommitmentDefinition(),
20314
+ new WritingRulesCommitmentDefinition('WRITING RULES'),
20315
+ new WritingRulesCommitmentDefinition('WRITING RULE'),
20298
20316
  new SampleCommitmentDefinition('SAMPLE'),
20299
20317
  new SampleCommitmentDefinition('EXAMPLE'),
20300
20318
  new FormatCommitmentDefinition('FORMAT'),
@@ -24143,6 +24161,12 @@
24143
24161
  commandName: 'gemini',
24144
24162
  npmPackageName: '@google/gemini-cli',
24145
24163
  },
24164
+ 'qwen-code': {
24165
+ harnessName: 'qwen-code',
24166
+ label: 'Qwen Code',
24167
+ commandName: 'qwen',
24168
+ npmPackageName: '@qwen-code/qwen-code',
24169
+ },
24146
24170
  };
24147
24171
  /**
24148
24172
  * Looks up the definition of one supported CLI coding harness.
@@ -26268,6 +26292,71 @@
26268
26292
  return { value };
26269
26293
  }
26270
26294
 
26295
+ /**
26296
+ * An estimation of how many characters are in one token.
26297
+ */
26298
+ const CHARS_PER_TOKEN = 4;
26299
+ /**
26300
+ * Estimates the usage of one harness run from the length of its prompt and its output.
26301
+ *
26302
+ * Harnesses which do not report their own token counts are billed per token anyway, so the
26303
+ * character counts are the only signal available for a price estimate.
26304
+ */
26305
+ function estimateUsageFromTextLength(options) {
26306
+ const { harnessLabel, prompt, output, resolvePricing } = options;
26307
+ try {
26308
+ const pricing = resolvePricing();
26309
+ const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN);
26310
+ const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN);
26311
+ const price = uncertainNumber((inputTokens / 1000000) * pricing.input + (outputTokens / 1000000) * pricing.output);
26312
+ return {
26313
+ ...UNCERTAIN_USAGE,
26314
+ price,
26315
+ input: {
26316
+ ...UNCERTAIN_USAGE.input,
26317
+ tokensCount: uncertainNumber(inputTokens),
26318
+ },
26319
+ output: {
26320
+ ...UNCERTAIN_USAGE.output,
26321
+ tokensCount: uncertainNumber(outputTokens),
26322
+ },
26323
+ };
26324
+ }
26325
+ catch (error) {
26326
+ console.error(colors__default["default"].bgRed(`Error parsing ${harnessLabel} usage output:`), error);
26327
+ return UNCERTAIN_USAGE;
26328
+ }
26329
+ }
26330
+
26331
+ /**
26332
+ * Resolves the pricing of one model of one harness.
26333
+ *
26334
+ * It first tries exact match, then prefix match, then falls back to the pricing of a stable
26335
+ * default model, because every harness names new models faster than the pricing tables grow.
26336
+ */
26337
+ function resolveModelPricing(options) {
26338
+ var _a;
26339
+ const { pricingTable, modelNameForEstimation, modelName } = options;
26340
+ const fallbackPricing = pricingTable[modelNameForEstimation];
26341
+ if (fallbackPricing === undefined) {
26342
+ throw new UnexpectedError(spaceTrim(`
26343
+ Missing pricing of the model \`${modelNameForEstimation}\` used for price estimation.
26344
+
26345
+ **The model used for estimation must always be listed in its own pricing table.**
26346
+ `));
26347
+ }
26348
+ if (!modelName) {
26349
+ return fallbackPricing;
26350
+ }
26351
+ const exactMatch = pricingTable[modelName];
26352
+ if (exactMatch) {
26353
+ return exactMatch;
26354
+ }
26355
+ const prefixMatch = (_a = Object.entries(pricingTable).find(([knownModelName]) => modelName.startsWith(knownModelName))) === null || _a === void 0 ? void 0 : _a[1];
26356
+ return prefixMatch !== null && prefixMatch !== void 0 ? prefixMatch : fallbackPricing;
26357
+ }
26358
+ // Note: [💞] Ignore a discrepancy between file name and entity name
26359
+
26271
26360
  /**
26272
26361
  * The pricing for Gemini models per 1 million tokens in USD.
26273
26362
  *
@@ -26287,27 +26376,14 @@
26287
26376
  const GEMINI_MODEL_FOR_ESTIMATION = 'gemini-1.5-flash';
26288
26377
  /**
26289
26378
  * Resolves Gemini pricing for the requested model.
26290
- *
26291
- * It first tries exact match, then prefix match, then falls back to a stable
26292
- * default pricing model.
26293
26379
  */
26294
26380
  function resolveGeminiPricing(modelName) {
26295
- var _a;
26296
- const fallbackPricing = GEMINI_PRICING[GEMINI_MODEL_FOR_ESTIMATION];
26297
- if (!modelName) {
26298
- return fallbackPricing;
26299
- }
26300
- const exactMatch = GEMINI_PRICING[modelName];
26301
- if (exactMatch) {
26302
- return exactMatch;
26303
- }
26304
- const prefixMatch = (_a = Object.entries(GEMINI_PRICING).find(([knownModel]) => modelName.startsWith(knownModel))) === null || _a === void 0 ? void 0 : _a[1];
26305
- return prefixMatch !== null && prefixMatch !== void 0 ? prefixMatch : fallbackPricing;
26381
+ return resolveModelPricing({
26382
+ pricingTable: GEMINI_PRICING,
26383
+ modelNameForEstimation: GEMINI_MODEL_FOR_ESTIMATION,
26384
+ modelName,
26385
+ });
26306
26386
  }
26307
- /**
26308
- * A an estimation of how many characters are in one token.
26309
- */
26310
- const CHARS_PER_TOKEN = 4;
26311
26387
 
26312
26388
  /**
26313
26389
  * Parses Gemini CLI output and extracts usage information.
@@ -26317,28 +26393,12 @@
26317
26393
  * @param modelName The Gemini model used for this run.
26318
26394
  */
26319
26395
  function parseGeminiUsageFromOutput(output, prompt, modelName) {
26320
- try {
26321
- const pricing = resolveGeminiPricing(modelName);
26322
- const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN);
26323
- const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN);
26324
- const price = uncertainNumber((inputTokens / 1000000) * pricing.input + (outputTokens / 1000000) * pricing.output);
26325
- return {
26326
- ...UNCERTAIN_USAGE,
26327
- price,
26328
- input: {
26329
- ...UNCERTAIN_USAGE.input,
26330
- tokensCount: uncertainNumber(inputTokens),
26331
- },
26332
- output: {
26333
- ...UNCERTAIN_USAGE.output,
26334
- tokensCount: uncertainNumber(outputTokens),
26335
- },
26336
- };
26337
- }
26338
- catch (error) {
26339
- console.error(colors__default["default"].bgRed('Error parsing Gemini usage output:'), error);
26340
- return UNCERTAIN_USAGE;
26341
- }
26396
+ return estimateUsageFromTextLength({
26397
+ harnessLabel: 'Gemini',
26398
+ prompt,
26399
+ output,
26400
+ resolvePricing: () => resolveGeminiPricing(modelName),
26401
+ });
26342
26402
  }
26343
26403
 
26344
26404
  /**
@@ -27726,6 +27786,114 @@
27726
27786
  }
27727
27787
  }
27728
27788
 
27789
+ /**
27790
+ * Delimiter used for passing large prompts to the Qwen Code CLI.
27791
+ */
27792
+ const QWEN_CODE_PROMPT_DELIMITER = 'QWEN_CODE_PROMPT';
27793
+ /**
27794
+ * Builds the shell script that runs Qwen Code with the prompt and coding context.
27795
+ *
27796
+ * Note: `-y` runs the harness unattended, because `ptbk coder` approves the whole prompt
27797
+ * up front and there is nobody at the keyboard to confirm the single tool calls.
27798
+ */
27799
+ function buildQwenCodeScript(options) {
27800
+ return spaceTrim((block) => `
27801
+ qwen -y -m ${options.model} -p "$(cat <<'${QWEN_CODE_PROMPT_DELIMITER}'
27802
+
27803
+ ${block(options.prompt)}
27804
+
27805
+ ${QWEN_CODE_PROMPT_DELIMITER}
27806
+ )"
27807
+ `);
27808
+ }
27809
+
27810
+ /**
27811
+ * The pricing for Qwen Code models per 1 million tokens in USD.
27812
+ *
27813
+ * Note: This is an estimation.
27814
+ *
27815
+ * @see https://www.alibabacloud.com/help/en/model-studio/models
27816
+ */
27817
+ const QWEN_CODE_PRICING = {
27818
+ 'qwen3-coder-plus': {
27819
+ input: 1,
27820
+ output: 5,
27821
+ },
27822
+ 'qwen3-coder-flash': {
27823
+ input: 0.3,
27824
+ output: 1.5,
27825
+ },
27826
+ 'qwen3-max': {
27827
+ input: 1.2,
27828
+ output: 6,
27829
+ },
27830
+ };
27831
+ /**
27832
+ * The model to use for price estimation.
27833
+ */
27834
+ const QWEN_CODE_MODEL_FOR_ESTIMATION = 'qwen3-coder-plus';
27835
+ /**
27836
+ * Resolves Qwen Code pricing for the requested model.
27837
+ */
27838
+ function resolveQwenCodePricing(modelName) {
27839
+ return resolveModelPricing({
27840
+ pricingTable: QWEN_CODE_PRICING,
27841
+ modelNameForEstimation: QWEN_CODE_MODEL_FOR_ESTIMATION,
27842
+ modelName,
27843
+ });
27844
+ }
27845
+
27846
+ /**
27847
+ * Parses Qwen Code CLI output and extracts usage information.
27848
+ *
27849
+ * @param output The output from the Qwen Code CLI.
27850
+ * @param prompt The prompt that was sent to the Qwen Code CLI.
27851
+ * @param modelName The Qwen Code model used for this run.
27852
+ */
27853
+ function parseQwenCodeUsageFromOutput(output, prompt, modelName) {
27854
+ return estimateUsageFromTextLength({
27855
+ harnessLabel: 'Qwen Code',
27856
+ prompt,
27857
+ output,
27858
+ resolvePricing: () => resolveQwenCodePricing(modelName),
27859
+ });
27860
+ }
27861
+
27862
+ /**
27863
+ * Default Qwen Code model used by the coding runner.
27864
+ */
27865
+ const DEFAULT_QWEN_CODE_MODEL = 'qwen3.8-max';
27866
+ /**
27867
+ * Runs prompts via the Qwen Code CLI.
27868
+ */
27869
+ class QwenCodeRunner {
27870
+ /**
27871
+ * Creates a new Qwen Code runner.
27872
+ */
27873
+ constructor(options) {
27874
+ this.options = options;
27875
+ this.name = 'qwen-code';
27876
+ }
27877
+ /**
27878
+ * Runs the prompt using Qwen Code and parses usage output.
27879
+ */
27880
+ async runPrompt(options) {
27881
+ const scriptContent = buildQwenCodeScript({
27882
+ prompt: options.prompt,
27883
+ model: this.options.model,
27884
+ });
27885
+ const output = await $runGoScriptWithOutput({
27886
+ scriptPath: options.scriptPath,
27887
+ scriptContent,
27888
+ logPath: options.logPath,
27889
+ shouldPrintLiveOutput: options.shouldPrintLiveOutput,
27890
+ preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
27891
+ });
27892
+ const usage = parseQwenCodeUsageFromOutput(output, options.prompt, this.options.model);
27893
+ return { usage };
27894
+ }
27895
+ }
27896
+
27729
27897
  /**
27730
27898
  * Constant for default codex model.
27731
27899
  */
@@ -27734,6 +27902,11 @@
27734
27902
  * Constant for cline model.
27735
27903
  */
27736
27904
  const CLINE_MODEL = 'gemini:gemini-3-flash-preview';
27905
+ /**
27906
+ * Harnesses which refuse to run without an explicit `--model`, because they expose many models
27907
+ * of very different capability and price and never pick a sensible one on their own.
27908
+ */
27909
+ const MODEL_REQUIRING_HARNESS_NAMES = ['openai-codex', 'gemini', 'qwen-code'];
27737
27910
  /**
27738
27911
  * Resolves the configured prompt runner together with status-line metadata.
27739
27912
  *
@@ -27771,6 +27944,9 @@
27771
27944
  if (agentName === 'gemini') {
27772
27945
  return createGeminiRunnerResolution(options);
27773
27946
  }
27947
+ if (agentName === 'qwen-code') {
27948
+ return createQwenCodeRunnerResolution(options);
27949
+ }
27774
27950
  throw new Error(`Unknown harness: ${agentName}`);
27775
27951
  }
27776
27952
  /**
@@ -27812,6 +27988,23 @@
27812
27988
  model: actualRunnerModel,
27813
27989
  }), actualRunnerModel);
27814
27990
  }
27991
+ /**
27992
+ * Builds the Qwen Code CLI runner resolution, including required-model validation.
27993
+ */
27994
+ function createQwenCodeRunnerResolution(options) {
27995
+ const actualRunnerModel = resolveRequiredModel({
27996
+ agentName: 'qwen-code',
27997
+ providedModel: options.model,
27998
+ defaultModel: DEFAULT_QWEN_CODE_MODEL,
27999
+ exampleUsages: [
28000
+ `--harness qwen-code --model ${DEFAULT_QWEN_CODE_MODEL}`,
28001
+ '--harness qwen-code --model default',
28002
+ ],
28003
+ });
28004
+ return createRunnerResolution(options, new QwenCodeRunner({
28005
+ model: actualRunnerModel,
28006
+ }), actualRunnerModel);
28007
+ }
27815
28008
  /**
27816
28009
  * Combines the instantiated runner with prompt status metadata.
27817
28010
  */
@@ -27827,9 +28020,7 @@
27827
28020
  */
27828
28021
  function getRunnerMetadata(options, actualRunnerModel) {
27829
28022
  const runnerName = options.agentName ? getHarnessDefinition(options.agentName).label : 'unknown';
27830
- if (options.agentName === 'openai-codex' ||
27831
- options.agentName === 'github-copilot' ||
27832
- options.agentName === 'gemini') {
28023
+ if (options.agentName === 'github-copilot' || isModelRequiringHarnessName(options.agentName)) {
27833
28024
  return { runnerName, modelName: actualRunnerModel };
27834
28025
  }
27835
28026
  if (options.agentName === 'cline') {
@@ -27840,6 +28031,12 @@
27840
28031
  }
27841
28032
  return { runnerName };
27842
28033
  }
28034
+ /**
28035
+ * Checks whether one harness refuses to run without an explicit `--model`.
28036
+ */
28037
+ function isModelRequiringHarnessName(agentName) {
28038
+ return MODEL_REQUIRING_HARNESS_NAMES.includes(agentName);
28039
+ }
27843
28040
  /**
27844
28041
  * Resolves a runner model, allowing `default` but otherwise requiring an explicit value.
27845
28042
  */
@@ -39991,7 +40188,7 @@
39991
40188
  */
39992
40189
  function validateAgentRunOptions(options) {
39993
40190
  if (!options.agentName) {
39994
- throw new NotAllowed('You must choose a harness using --harness <openai-codex|github-copilot|cline|claude-code|opencode|gemini>.');
40191
+ throw new NotAllowed(`You must choose a harness using ${PROMPT_RUNNER_HARNESS_OPTION_HINT}.`);
39995
40192
  }
39996
40193
  if (options.autoPull && options.noCommit) {
39997
40194
  throw new NotAllowed(_spaceTrim.spaceTrim(`
@@ -74663,7 +74860,7 @@
74663
74860
  exitWithUsageError(error instanceof Error ? error.message : String(error));
74664
74861
  }
74665
74862
  if (!agentName && !dryRun) {
74666
- exitWithUsageError('You must choose a harness using --harness <openai-codex|github-copilot|cline|claude-code|opencode|gemini>');
74863
+ exitWithUsageError(`You must choose a harness using ${PROMPT_RUNNER_HARNESS_OPTION_HINT}`);
74667
74864
  }
74668
74865
  return {
74669
74866
  dryRun,