@promptbook/cli 0.114.0-23 → 0.114.0-25

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 (32) hide show
  1. package/README.md +2 -2
  2. package/esm/index.es.js +239 -51
  3. package/esm/index.es.js.map +1 -1
  4. package/esm/scripts/run-codex-prompts/runners/common/estimateUsageFromTextLength.d.ts +33 -0
  5. package/esm/scripts/run-codex-prompts/runners/common/modelPricing.d.ts +41 -0
  6. package/esm/scripts/run-codex-prompts/runners/gemini/gemini-pricing.d.ts +5 -18
  7. package/esm/scripts/run-codex-prompts/runners/qwen-code/QwenCodeRunner.d.ts +23 -0
  8. package/esm/scripts/run-codex-prompts/runners/qwen-code/buildQwenCodeScript.d.ts +8 -0
  9. package/esm/scripts/run-codex-prompts/runners/qwen-code/parseQwenCodeUsageFromOutput.d.ts +9 -0
  10. package/esm/scripts/run-codex-prompts/runners/qwen-code/qwen-code-pricing.d.ts +30 -0
  11. package/esm/src/book-3.0/cliAgentEnv.d.ts +3 -3
  12. package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +8 -2
  13. package/esm/src/version.d.ts +1 -1
  14. package/package.json +1 -1
  15. package/src/book-3.0/cliAgentEnv.ts +3 -2
  16. package/src/cli/cli-commands/common/harness/HarnessDefinition.ts +6 -0
  17. package/src/cli/cli-commands/common/promptRunnerCliOptions.ts +14 -8
  18. package/src/other/templates/getTemplatesPipelineCollection.ts +867 -872
  19. package/src/version.ts +2 -2
  20. package/src/versions.txt +2 -0
  21. package/umd/index.umd.js +239 -51
  22. package/umd/index.umd.js.map +1 -1
  23. package/umd/scripts/run-codex-prompts/runners/common/estimateUsageFromTextLength.d.ts +33 -0
  24. package/umd/scripts/run-codex-prompts/runners/common/modelPricing.d.ts +41 -0
  25. package/umd/scripts/run-codex-prompts/runners/gemini/gemini-pricing.d.ts +5 -18
  26. package/umd/scripts/run-codex-prompts/runners/qwen-code/QwenCodeRunner.d.ts +23 -0
  27. package/umd/scripts/run-codex-prompts/runners/qwen-code/buildQwenCodeScript.d.ts +8 -0
  28. package/umd/scripts/run-codex-prompts/runners/qwen-code/parseQwenCodeUsageFromOutput.d.ts +9 -0
  29. package/umd/scripts/run-codex-prompts/runners/qwen-code/qwen-code-pricing.d.ts +30 -0
  30. package/umd/src/book-3.0/cliAgentEnv.d.ts +3 -3
  31. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +8 -2
  32. 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-23';
19
+ export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.114.0-25';
20
20
 
21
21
  /**
22
22
  * Represents the version string of the Promptbook engine.
23
- * It follows semantic versioning (e.g., `0.114.0-22`).
23
+ * It follows semantic versioning (e.g., `0.114.0-24`).
24
24
  *
25
25
  * @generated
26
26
  */
package/src/versions.txt CHANGED
@@ -1199,3 +1199,5 @@
1199
1199
  0.114.0-21
1200
1200
  0.114.0-22
1201
1201
  0.114.0-23
1202
+ 0.114.0-24
1203
+ 0.114.0-25
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-23';
61
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-25';
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;
@@ -24143,6 +24152,12 @@
24143
24152
  commandName: 'gemini',
24144
24153
  npmPackageName: '@google/gemini-cli',
24145
24154
  },
24155
+ 'qwen-code': {
24156
+ harnessName: 'qwen-code',
24157
+ label: 'Qwen Code',
24158
+ commandName: 'qwen',
24159
+ npmPackageName: '@qwen-code/qwen-code',
24160
+ },
24146
24161
  };
24147
24162
  /**
24148
24163
  * Looks up the definition of one supported CLI coding harness.
@@ -26268,6 +26283,71 @@
26268
26283
  return { value };
26269
26284
  }
26270
26285
 
26286
+ /**
26287
+ * An estimation of how many characters are in one token.
26288
+ */
26289
+ const CHARS_PER_TOKEN = 4;
26290
+ /**
26291
+ * Estimates the usage of one harness run from the length of its prompt and its output.
26292
+ *
26293
+ * Harnesses which do not report their own token counts are billed per token anyway, so the
26294
+ * character counts are the only signal available for a price estimate.
26295
+ */
26296
+ function estimateUsageFromTextLength(options) {
26297
+ const { harnessLabel, prompt, output, resolvePricing } = options;
26298
+ try {
26299
+ const pricing = resolvePricing();
26300
+ const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN);
26301
+ const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN);
26302
+ const price = uncertainNumber((inputTokens / 1000000) * pricing.input + (outputTokens / 1000000) * pricing.output);
26303
+ return {
26304
+ ...UNCERTAIN_USAGE,
26305
+ price,
26306
+ input: {
26307
+ ...UNCERTAIN_USAGE.input,
26308
+ tokensCount: uncertainNumber(inputTokens),
26309
+ },
26310
+ output: {
26311
+ ...UNCERTAIN_USAGE.output,
26312
+ tokensCount: uncertainNumber(outputTokens),
26313
+ },
26314
+ };
26315
+ }
26316
+ catch (error) {
26317
+ console.error(colors__default["default"].bgRed(`Error parsing ${harnessLabel} usage output:`), error);
26318
+ return UNCERTAIN_USAGE;
26319
+ }
26320
+ }
26321
+
26322
+ /**
26323
+ * Resolves the pricing of one model of one harness.
26324
+ *
26325
+ * It first tries exact match, then prefix match, then falls back to the pricing of a stable
26326
+ * default model, because every harness names new models faster than the pricing tables grow.
26327
+ */
26328
+ function resolveModelPricing(options) {
26329
+ var _a;
26330
+ const { pricingTable, modelNameForEstimation, modelName } = options;
26331
+ const fallbackPricing = pricingTable[modelNameForEstimation];
26332
+ if (fallbackPricing === undefined) {
26333
+ throw new UnexpectedError(spaceTrim(`
26334
+ Missing pricing of the model \`${modelNameForEstimation}\` used for price estimation.
26335
+
26336
+ **The model used for estimation must always be listed in its own pricing table.**
26337
+ `));
26338
+ }
26339
+ if (!modelName) {
26340
+ return fallbackPricing;
26341
+ }
26342
+ const exactMatch = pricingTable[modelName];
26343
+ if (exactMatch) {
26344
+ return exactMatch;
26345
+ }
26346
+ const prefixMatch = (_a = Object.entries(pricingTable).find(([knownModelName]) => modelName.startsWith(knownModelName))) === null || _a === void 0 ? void 0 : _a[1];
26347
+ return prefixMatch !== null && prefixMatch !== void 0 ? prefixMatch : fallbackPricing;
26348
+ }
26349
+ // Note: [💞] Ignore a discrepancy between file name and entity name
26350
+
26271
26351
  /**
26272
26352
  * The pricing for Gemini models per 1 million tokens in USD.
26273
26353
  *
@@ -26287,27 +26367,14 @@
26287
26367
  const GEMINI_MODEL_FOR_ESTIMATION = 'gemini-1.5-flash';
26288
26368
  /**
26289
26369
  * 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
26370
  */
26294
26371
  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;
26372
+ return resolveModelPricing({
26373
+ pricingTable: GEMINI_PRICING,
26374
+ modelNameForEstimation: GEMINI_MODEL_FOR_ESTIMATION,
26375
+ modelName,
26376
+ });
26306
26377
  }
26307
- /**
26308
- * A an estimation of how many characters are in one token.
26309
- */
26310
- const CHARS_PER_TOKEN = 4;
26311
26378
 
26312
26379
  /**
26313
26380
  * Parses Gemini CLI output and extracts usage information.
@@ -26317,28 +26384,12 @@
26317
26384
  * @param modelName The Gemini model used for this run.
26318
26385
  */
26319
26386
  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
- }
26387
+ return estimateUsageFromTextLength({
26388
+ harnessLabel: 'Gemini',
26389
+ prompt,
26390
+ output,
26391
+ resolvePricing: () => resolveGeminiPricing(modelName),
26392
+ });
26342
26393
  }
26343
26394
 
26344
26395
  /**
@@ -27726,6 +27777,114 @@
27726
27777
  }
27727
27778
  }
27728
27779
 
27780
+ /**
27781
+ * Delimiter used for passing large prompts to the Qwen Code CLI.
27782
+ */
27783
+ const QWEN_CODE_PROMPT_DELIMITER = 'QWEN_CODE_PROMPT';
27784
+ /**
27785
+ * Builds the shell script that runs Qwen Code with the prompt and coding context.
27786
+ *
27787
+ * Note: `-y` runs the harness unattended, because `ptbk coder` approves the whole prompt
27788
+ * up front and there is nobody at the keyboard to confirm the single tool calls.
27789
+ */
27790
+ function buildQwenCodeScript(options) {
27791
+ return spaceTrim((block) => `
27792
+ qwen -y -m ${options.model} -p "$(cat <<'${QWEN_CODE_PROMPT_DELIMITER}'
27793
+
27794
+ ${block(options.prompt)}
27795
+
27796
+ ${QWEN_CODE_PROMPT_DELIMITER}
27797
+ )"
27798
+ `);
27799
+ }
27800
+
27801
+ /**
27802
+ * The pricing for Qwen Code models per 1 million tokens in USD.
27803
+ *
27804
+ * Note: This is an estimation.
27805
+ *
27806
+ * @see https://www.alibabacloud.com/help/en/model-studio/models
27807
+ */
27808
+ const QWEN_CODE_PRICING = {
27809
+ 'qwen3-coder-plus': {
27810
+ input: 1,
27811
+ output: 5,
27812
+ },
27813
+ 'qwen3-coder-flash': {
27814
+ input: 0.3,
27815
+ output: 1.5,
27816
+ },
27817
+ 'qwen3-max': {
27818
+ input: 1.2,
27819
+ output: 6,
27820
+ },
27821
+ };
27822
+ /**
27823
+ * The model to use for price estimation.
27824
+ */
27825
+ const QWEN_CODE_MODEL_FOR_ESTIMATION = 'qwen3-coder-plus';
27826
+ /**
27827
+ * Resolves Qwen Code pricing for the requested model.
27828
+ */
27829
+ function resolveQwenCodePricing(modelName) {
27830
+ return resolveModelPricing({
27831
+ pricingTable: QWEN_CODE_PRICING,
27832
+ modelNameForEstimation: QWEN_CODE_MODEL_FOR_ESTIMATION,
27833
+ modelName,
27834
+ });
27835
+ }
27836
+
27837
+ /**
27838
+ * Parses Qwen Code CLI output and extracts usage information.
27839
+ *
27840
+ * @param output The output from the Qwen Code CLI.
27841
+ * @param prompt The prompt that was sent to the Qwen Code CLI.
27842
+ * @param modelName The Qwen Code model used for this run.
27843
+ */
27844
+ function parseQwenCodeUsageFromOutput(output, prompt, modelName) {
27845
+ return estimateUsageFromTextLength({
27846
+ harnessLabel: 'Qwen Code',
27847
+ prompt,
27848
+ output,
27849
+ resolvePricing: () => resolveQwenCodePricing(modelName),
27850
+ });
27851
+ }
27852
+
27853
+ /**
27854
+ * Default Qwen Code model used by the coding runner.
27855
+ */
27856
+ const DEFAULT_QWEN_CODE_MODEL = 'qwen3.8-max';
27857
+ /**
27858
+ * Runs prompts via the Qwen Code CLI.
27859
+ */
27860
+ class QwenCodeRunner {
27861
+ /**
27862
+ * Creates a new Qwen Code runner.
27863
+ */
27864
+ constructor(options) {
27865
+ this.options = options;
27866
+ this.name = 'qwen-code';
27867
+ }
27868
+ /**
27869
+ * Runs the prompt using Qwen Code and parses usage output.
27870
+ */
27871
+ async runPrompt(options) {
27872
+ const scriptContent = buildQwenCodeScript({
27873
+ prompt: options.prompt,
27874
+ model: this.options.model,
27875
+ });
27876
+ const output = await $runGoScriptWithOutput({
27877
+ scriptPath: options.scriptPath,
27878
+ scriptContent,
27879
+ logPath: options.logPath,
27880
+ shouldPrintLiveOutput: options.shouldPrintLiveOutput,
27881
+ preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
27882
+ });
27883
+ const usage = parseQwenCodeUsageFromOutput(output, options.prompt, this.options.model);
27884
+ return { usage };
27885
+ }
27886
+ }
27887
+
27729
27888
  /**
27730
27889
  * Constant for default codex model.
27731
27890
  */
@@ -27734,6 +27893,11 @@
27734
27893
  * Constant for cline model.
27735
27894
  */
27736
27895
  const CLINE_MODEL = 'gemini:gemini-3-flash-preview';
27896
+ /**
27897
+ * Harnesses which refuse to run without an explicit `--model`, because they expose many models
27898
+ * of very different capability and price and never pick a sensible one on their own.
27899
+ */
27900
+ const MODEL_REQUIRING_HARNESS_NAMES = ['openai-codex', 'gemini', 'qwen-code'];
27737
27901
  /**
27738
27902
  * Resolves the configured prompt runner together with status-line metadata.
27739
27903
  *
@@ -27771,6 +27935,9 @@
27771
27935
  if (agentName === 'gemini') {
27772
27936
  return createGeminiRunnerResolution(options);
27773
27937
  }
27938
+ if (agentName === 'qwen-code') {
27939
+ return createQwenCodeRunnerResolution(options);
27940
+ }
27774
27941
  throw new Error(`Unknown harness: ${agentName}`);
27775
27942
  }
27776
27943
  /**
@@ -27812,6 +27979,23 @@
27812
27979
  model: actualRunnerModel,
27813
27980
  }), actualRunnerModel);
27814
27981
  }
27982
+ /**
27983
+ * Builds the Qwen Code CLI runner resolution, including required-model validation.
27984
+ */
27985
+ function createQwenCodeRunnerResolution(options) {
27986
+ const actualRunnerModel = resolveRequiredModel({
27987
+ agentName: 'qwen-code',
27988
+ providedModel: options.model,
27989
+ defaultModel: DEFAULT_QWEN_CODE_MODEL,
27990
+ exampleUsages: [
27991
+ `--harness qwen-code --model ${DEFAULT_QWEN_CODE_MODEL}`,
27992
+ '--harness qwen-code --model default',
27993
+ ],
27994
+ });
27995
+ return createRunnerResolution(options, new QwenCodeRunner({
27996
+ model: actualRunnerModel,
27997
+ }), actualRunnerModel);
27998
+ }
27815
27999
  /**
27816
28000
  * Combines the instantiated runner with prompt status metadata.
27817
28001
  */
@@ -27827,9 +28011,7 @@
27827
28011
  */
27828
28012
  function getRunnerMetadata(options, actualRunnerModel) {
27829
28013
  const runnerName = options.agentName ? getHarnessDefinition(options.agentName).label : 'unknown';
27830
- if (options.agentName === 'openai-codex' ||
27831
- options.agentName === 'github-copilot' ||
27832
- options.agentName === 'gemini') {
28014
+ if (options.agentName === 'github-copilot' || isModelRequiringHarnessName(options.agentName)) {
27833
28015
  return { runnerName, modelName: actualRunnerModel };
27834
28016
  }
27835
28017
  if (options.agentName === 'cline') {
@@ -27840,6 +28022,12 @@
27840
28022
  }
27841
28023
  return { runnerName };
27842
28024
  }
28025
+ /**
28026
+ * Checks whether one harness refuses to run without an explicit `--model`.
28027
+ */
28028
+ function isModelRequiringHarnessName(agentName) {
28029
+ return MODEL_REQUIRING_HARNESS_NAMES.includes(agentName);
28030
+ }
27843
28031
  /**
27844
28032
  * Resolves a runner model, allowing `default` but otherwise requiring an explicit value.
27845
28033
  */
@@ -39991,7 +40179,7 @@
39991
40179
  */
39992
40180
  function validateAgentRunOptions(options) {
39993
40181
  if (!options.agentName) {
39994
- throw new NotAllowed('You must choose a harness using --harness <openai-codex|github-copilot|cline|claude-code|opencode|gemini>.');
40182
+ throw new NotAllowed(`You must choose a harness using ${PROMPT_RUNNER_HARNESS_OPTION_HINT}.`);
39995
40183
  }
39996
40184
  if (options.autoPull && options.noCommit) {
39997
40185
  throw new NotAllowed(_spaceTrim.spaceTrim(`
@@ -74663,7 +74851,7 @@
74663
74851
  exitWithUsageError(error instanceof Error ? error.message : String(error));
74664
74852
  }
74665
74853
  if (!agentName && !dryRun) {
74666
- exitWithUsageError('You must choose a harness using --harness <openai-codex|github-copilot|cline|claude-code|opencode|gemini>');
74854
+ exitWithUsageError(`You must choose a harness using ${PROMPT_RUNNER_HARNESS_OPTION_HINT}`);
74667
74855
  }
74668
74856
  return {
74669
74857
  dryRun,