@promptbook/node 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 (30) hide show
  1. package/README.md +2 -2
  2. package/esm/index.es.js +243 -54
  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/commitments/WRITING_RULES/WRITING_RULES.d.ts +14 -7
  14. package/esm/src/commitments/index.d.ts +1 -1
  15. package/esm/src/version.d.ts +1 -1
  16. package/package.json +2 -2
  17. package/umd/index.umd.js +243 -54
  18. package/umd/index.umd.js.map +1 -1
  19. package/umd/scripts/run-codex-prompts/runners/common/estimateUsageFromTextLength.d.ts +33 -0
  20. package/umd/scripts/run-codex-prompts/runners/common/modelPricing.d.ts +41 -0
  21. package/umd/scripts/run-codex-prompts/runners/gemini/gemini-pricing.d.ts +5 -18
  22. package/umd/scripts/run-codex-prompts/runners/qwen-code/QwenCodeRunner.d.ts +23 -0
  23. package/umd/scripts/run-codex-prompts/runners/qwen-code/buildQwenCodeScript.d.ts +8 -0
  24. package/umd/scripts/run-codex-prompts/runners/qwen-code/parseQwenCodeUsageFromOutput.d.ts +9 -0
  25. package/umd/scripts/run-codex-prompts/runners/qwen-code/qwen-code-pricing.d.ts +30 -0
  26. package/umd/src/book-3.0/cliAgentEnv.d.ts +3 -3
  27. package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +8 -2
  28. package/umd/src/commitments/WRITING_RULES/WRITING_RULES.d.ts +14 -7
  29. package/umd/src/commitments/index.d.ts +1 -1
  30. package/umd/src/version.d.ts +1 -1
package/umd/index.umd.js CHANGED
@@ -47,7 +47,7 @@
47
47
  * @generated
48
48
  * @see https://github.com/webgptorg/promptbook
49
49
  */
50
- const PROMPTBOOK_ENGINE_VERSION = '0.114.0-24';
50
+ const PROMPTBOOK_ENGINE_VERSION = '0.114.0-26';
51
51
  /**
52
52
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
53
53
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1837,6 +1837,12 @@
1837
1837
  commandName: 'gemini',
1838
1838
  npmPackageName: '@google/gemini-cli',
1839
1839
  },
1840
+ 'qwen-code': {
1841
+ harnessName: 'qwen-code',
1842
+ label: 'Qwen Code',
1843
+ commandName: 'qwen',
1844
+ npmPackageName: '@qwen-code/qwen-code',
1845
+ },
1840
1846
  };
1841
1847
  /**
1842
1848
  * Looks up the definition of one supported CLI coding harness.
@@ -4136,6 +4142,71 @@
4136
4142
  return { value };
4137
4143
  }
4138
4144
 
4145
+ /**
4146
+ * An estimation of how many characters are in one token.
4147
+ */
4148
+ const CHARS_PER_TOKEN = 4;
4149
+ /**
4150
+ * Estimates the usage of one harness run from the length of its prompt and its output.
4151
+ *
4152
+ * Harnesses which do not report their own token counts are billed per token anyway, so the
4153
+ * character counts are the only signal available for a price estimate.
4154
+ */
4155
+ function estimateUsageFromTextLength(options) {
4156
+ const { harnessLabel, prompt, output, resolvePricing } = options;
4157
+ try {
4158
+ const pricing = resolvePricing();
4159
+ const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN);
4160
+ const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN);
4161
+ const price = uncertainNumber((inputTokens / 1000000) * pricing.input + (outputTokens / 1000000) * pricing.output);
4162
+ return {
4163
+ ...UNCERTAIN_USAGE,
4164
+ price,
4165
+ input: {
4166
+ ...UNCERTAIN_USAGE.input,
4167
+ tokensCount: uncertainNumber(inputTokens),
4168
+ },
4169
+ output: {
4170
+ ...UNCERTAIN_USAGE.output,
4171
+ tokensCount: uncertainNumber(outputTokens),
4172
+ },
4173
+ };
4174
+ }
4175
+ catch (error) {
4176
+ console.error(colors__default["default"].bgRed(`Error parsing ${harnessLabel} usage output:`), error);
4177
+ return UNCERTAIN_USAGE;
4178
+ }
4179
+ }
4180
+
4181
+ /**
4182
+ * Resolves the pricing of one model of one harness.
4183
+ *
4184
+ * It first tries exact match, then prefix match, then falls back to the pricing of a stable
4185
+ * default model, because every harness names new models faster than the pricing tables grow.
4186
+ */
4187
+ function resolveModelPricing(options) {
4188
+ var _a;
4189
+ const { pricingTable, modelNameForEstimation, modelName } = options;
4190
+ const fallbackPricing = pricingTable[modelNameForEstimation];
4191
+ if (fallbackPricing === undefined) {
4192
+ throw new UnexpectedError(spaceTrim(`
4193
+ Missing pricing of the model \`${modelNameForEstimation}\` used for price estimation.
4194
+
4195
+ **The model used for estimation must always be listed in its own pricing table.**
4196
+ `));
4197
+ }
4198
+ if (!modelName) {
4199
+ return fallbackPricing;
4200
+ }
4201
+ const exactMatch = pricingTable[modelName];
4202
+ if (exactMatch) {
4203
+ return exactMatch;
4204
+ }
4205
+ const prefixMatch = (_a = Object.entries(pricingTable).find(([knownModelName]) => modelName.startsWith(knownModelName))) === null || _a === void 0 ? void 0 : _a[1];
4206
+ return prefixMatch !== null && prefixMatch !== void 0 ? prefixMatch : fallbackPricing;
4207
+ }
4208
+ // Note: [💞] Ignore a discrepancy between file name and entity name
4209
+
4139
4210
  /**
4140
4211
  * The pricing for Gemini models per 1 million tokens in USD.
4141
4212
  *
@@ -4155,27 +4226,14 @@
4155
4226
  const GEMINI_MODEL_FOR_ESTIMATION = 'gemini-1.5-flash';
4156
4227
  /**
4157
4228
  * Resolves Gemini pricing for the requested model.
4158
- *
4159
- * It first tries exact match, then prefix match, then falls back to a stable
4160
- * default pricing model.
4161
4229
  */
4162
4230
  function resolveGeminiPricing(modelName) {
4163
- var _a;
4164
- const fallbackPricing = GEMINI_PRICING[GEMINI_MODEL_FOR_ESTIMATION];
4165
- if (!modelName) {
4166
- return fallbackPricing;
4167
- }
4168
- const exactMatch = GEMINI_PRICING[modelName];
4169
- if (exactMatch) {
4170
- return exactMatch;
4171
- }
4172
- const prefixMatch = (_a = Object.entries(GEMINI_PRICING).find(([knownModel]) => modelName.startsWith(knownModel))) === null || _a === void 0 ? void 0 : _a[1];
4173
- return prefixMatch !== null && prefixMatch !== void 0 ? prefixMatch : fallbackPricing;
4231
+ return resolveModelPricing({
4232
+ pricingTable: GEMINI_PRICING,
4233
+ modelNameForEstimation: GEMINI_MODEL_FOR_ESTIMATION,
4234
+ modelName,
4235
+ });
4174
4236
  }
4175
- /**
4176
- * A an estimation of how many characters are in one token.
4177
- */
4178
- const CHARS_PER_TOKEN = 4;
4179
4237
 
4180
4238
  /**
4181
4239
  * Parses Gemini CLI output and extracts usage information.
@@ -4185,28 +4243,12 @@
4185
4243
  * @param modelName The Gemini model used for this run.
4186
4244
  */
4187
4245
  function parseGeminiUsageFromOutput(output, prompt, modelName) {
4188
- try {
4189
- const pricing = resolveGeminiPricing(modelName);
4190
- const inputTokens = Math.ceil(prompt.length / CHARS_PER_TOKEN);
4191
- const outputTokens = Math.ceil(output.length / CHARS_PER_TOKEN);
4192
- const price = uncertainNumber((inputTokens / 1000000) * pricing.input + (outputTokens / 1000000) * pricing.output);
4193
- return {
4194
- ...UNCERTAIN_USAGE,
4195
- price,
4196
- input: {
4197
- ...UNCERTAIN_USAGE.input,
4198
- tokensCount: uncertainNumber(inputTokens),
4199
- },
4200
- output: {
4201
- ...UNCERTAIN_USAGE.output,
4202
- tokensCount: uncertainNumber(outputTokens),
4203
- },
4204
- };
4205
- }
4206
- catch (error) {
4207
- console.error(colors__default["default"].bgRed('Error parsing Gemini usage output:'), error);
4208
- return UNCERTAIN_USAGE;
4209
- }
4246
+ return estimateUsageFromTextLength({
4247
+ harnessLabel: 'Gemini',
4248
+ prompt,
4249
+ output,
4250
+ resolvePricing: () => resolveGeminiPricing(modelName),
4251
+ });
4210
4252
  }
4211
4253
 
4212
4254
  /**
@@ -5653,6 +5695,114 @@
5653
5695
  }
5654
5696
  }
5655
5697
 
5698
+ /**
5699
+ * Delimiter used for passing large prompts to the Qwen Code CLI.
5700
+ */
5701
+ const QWEN_CODE_PROMPT_DELIMITER = 'QWEN_CODE_PROMPT';
5702
+ /**
5703
+ * Builds the shell script that runs Qwen Code with the prompt and coding context.
5704
+ *
5705
+ * Note: `-y` runs the harness unattended, because `ptbk coder` approves the whole prompt
5706
+ * up front and there is nobody at the keyboard to confirm the single tool calls.
5707
+ */
5708
+ function buildQwenCodeScript(options) {
5709
+ return spaceTrim((block) => `
5710
+ qwen -y -m ${options.model} -p "$(cat <<'${QWEN_CODE_PROMPT_DELIMITER}'
5711
+
5712
+ ${block(options.prompt)}
5713
+
5714
+ ${QWEN_CODE_PROMPT_DELIMITER}
5715
+ )"
5716
+ `);
5717
+ }
5718
+
5719
+ /**
5720
+ * The pricing for Qwen Code models per 1 million tokens in USD.
5721
+ *
5722
+ * Note: This is an estimation.
5723
+ *
5724
+ * @see https://www.alibabacloud.com/help/en/model-studio/models
5725
+ */
5726
+ const QWEN_CODE_PRICING = {
5727
+ 'qwen3-coder-plus': {
5728
+ input: 1,
5729
+ output: 5,
5730
+ },
5731
+ 'qwen3-coder-flash': {
5732
+ input: 0.3,
5733
+ output: 1.5,
5734
+ },
5735
+ 'qwen3-max': {
5736
+ input: 1.2,
5737
+ output: 6,
5738
+ },
5739
+ };
5740
+ /**
5741
+ * The model to use for price estimation.
5742
+ */
5743
+ const QWEN_CODE_MODEL_FOR_ESTIMATION = 'qwen3-coder-plus';
5744
+ /**
5745
+ * Resolves Qwen Code pricing for the requested model.
5746
+ */
5747
+ function resolveQwenCodePricing(modelName) {
5748
+ return resolveModelPricing({
5749
+ pricingTable: QWEN_CODE_PRICING,
5750
+ modelNameForEstimation: QWEN_CODE_MODEL_FOR_ESTIMATION,
5751
+ modelName,
5752
+ });
5753
+ }
5754
+
5755
+ /**
5756
+ * Parses Qwen Code CLI output and extracts usage information.
5757
+ *
5758
+ * @param output The output from the Qwen Code CLI.
5759
+ * @param prompt The prompt that was sent to the Qwen Code CLI.
5760
+ * @param modelName The Qwen Code model used for this run.
5761
+ */
5762
+ function parseQwenCodeUsageFromOutput(output, prompt, modelName) {
5763
+ return estimateUsageFromTextLength({
5764
+ harnessLabel: 'Qwen Code',
5765
+ prompt,
5766
+ output,
5767
+ resolvePricing: () => resolveQwenCodePricing(modelName),
5768
+ });
5769
+ }
5770
+
5771
+ /**
5772
+ * Default Qwen Code model used by the coding runner.
5773
+ */
5774
+ const DEFAULT_QWEN_CODE_MODEL = 'qwen3.8-max';
5775
+ /**
5776
+ * Runs prompts via the Qwen Code CLI.
5777
+ */
5778
+ class QwenCodeRunner {
5779
+ /**
5780
+ * Creates a new Qwen Code runner.
5781
+ */
5782
+ constructor(options) {
5783
+ this.options = options;
5784
+ this.name = 'qwen-code';
5785
+ }
5786
+ /**
5787
+ * Runs the prompt using Qwen Code and parses usage output.
5788
+ */
5789
+ async runPrompt(options) {
5790
+ const scriptContent = buildQwenCodeScript({
5791
+ prompt: options.prompt,
5792
+ model: this.options.model,
5793
+ });
5794
+ const output = await $runGoScriptWithOutput({
5795
+ scriptPath: options.scriptPath,
5796
+ scriptContent,
5797
+ logPath: options.logPath,
5798
+ shouldPrintLiveOutput: options.shouldPrintLiveOutput,
5799
+ preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
5800
+ });
5801
+ const usage = parseQwenCodeUsageFromOutput(output, options.prompt, this.options.model);
5802
+ return { usage };
5803
+ }
5804
+ }
5805
+
5656
5806
  /**
5657
5807
  * Constant for default codex model.
5658
5808
  */
@@ -5661,6 +5811,11 @@
5661
5811
  * Constant for cline model.
5662
5812
  */
5663
5813
  const CLINE_MODEL = 'gemini:gemini-3-flash-preview';
5814
+ /**
5815
+ * Harnesses which refuse to run without an explicit `--model`, because they expose many models
5816
+ * of very different capability and price and never pick a sensible one on their own.
5817
+ */
5818
+ const MODEL_REQUIRING_HARNESS_NAMES = ['openai-codex', 'gemini', 'qwen-code'];
5664
5819
  /**
5665
5820
  * Resolves the configured prompt runner together with status-line metadata.
5666
5821
  *
@@ -5698,6 +5853,9 @@
5698
5853
  if (agentName === 'gemini') {
5699
5854
  return createGeminiRunnerResolution(options);
5700
5855
  }
5856
+ if (agentName === 'qwen-code') {
5857
+ return createQwenCodeRunnerResolution(options);
5858
+ }
5701
5859
  throw new Error(`Unknown harness: ${agentName}`);
5702
5860
  }
5703
5861
  /**
@@ -5739,6 +5897,23 @@
5739
5897
  model: actualRunnerModel,
5740
5898
  }), actualRunnerModel);
5741
5899
  }
5900
+ /**
5901
+ * Builds the Qwen Code CLI runner resolution, including required-model validation.
5902
+ */
5903
+ function createQwenCodeRunnerResolution(options) {
5904
+ const actualRunnerModel = resolveRequiredModel({
5905
+ agentName: 'qwen-code',
5906
+ providedModel: options.model,
5907
+ defaultModel: DEFAULT_QWEN_CODE_MODEL,
5908
+ exampleUsages: [
5909
+ `--harness qwen-code --model ${DEFAULT_QWEN_CODE_MODEL}`,
5910
+ '--harness qwen-code --model default',
5911
+ ],
5912
+ });
5913
+ return createRunnerResolution(options, new QwenCodeRunner({
5914
+ model: actualRunnerModel,
5915
+ }), actualRunnerModel);
5916
+ }
5742
5917
  /**
5743
5918
  * Combines the instantiated runner with prompt status metadata.
5744
5919
  */
@@ -5754,9 +5929,7 @@
5754
5929
  */
5755
5930
  function getRunnerMetadata(options, actualRunnerModel) {
5756
5931
  const runnerName = options.agentName ? getHarnessDefinition(options.agentName).label : 'unknown';
5757
- if (options.agentName === 'openai-codex' ||
5758
- options.agentName === 'github-copilot' ||
5759
- options.agentName === 'gemini') {
5932
+ if (options.agentName === 'github-copilot' || isModelRequiringHarnessName(options.agentName)) {
5760
5933
  return { runnerName, modelName: actualRunnerModel };
5761
5934
  }
5762
5935
  if (options.agentName === 'cline') {
@@ -5767,6 +5940,12 @@
5767
5940
  }
5768
5941
  return { runnerName };
5769
5942
  }
5943
+ /**
5944
+ * Checks whether one harness refuses to run without an explicit `--model`.
5945
+ */
5946
+ function isModelRequiringHarnessName(agentName) {
5947
+ return MODEL_REQUIRING_HARNESS_NAMES.includes(agentName);
5948
+ }
5770
5949
  /**
5771
5950
  * Resolves a runner model, allowing `default` but otherwise requiring an explicit value.
5772
5951
  */
@@ -27769,29 +27948,36 @@
27769
27948
  /**
27770
27949
  * `WRITING RULES` commitment definition.
27771
27950
  *
27772
- * It adds constraints that apply strictly to writing style and presentation
27773
- * rather than task-solving behavior.
27951
+ * The `WRITING RULES`/`WRITING RULE` commitment adds constraints that apply strictly to writing style
27952
+ * and presentation rather than task-solving behavior.
27953
+ *
27954
+ * Example usage in agent source:
27955
+ *
27956
+ * ```book
27957
+ * WRITING RULES Keep every response under 120 words
27958
+ * WRITING RULE Always end the message with an emoji
27959
+ * ```
27774
27960
  *
27775
27961
  * @private [🪔] Maybe export the commitments through some package
27776
27962
  */
27777
27963
  class WritingRulesCommitmentDefinition extends BaseCommitmentDefinition {
27778
- constructor() {
27779
- super('WRITING RULES');
27964
+ constructor(type = 'WRITING RULES') {
27965
+ super(type);
27780
27966
  }
27781
27967
  /**
27782
- * Short one-line description of `WRITING RULES`.
27968
+ * Short one-line description of `WRITING RULES`/`WRITING RULE`.
27783
27969
  */
27784
27970
  get description() {
27785
27971
  return 'Add writing-only constraints such as tone, length, formatting, or emoji usage.';
27786
27972
  }
27787
27973
  /**
27788
- * Icon for `WRITING RULES`.
27974
+ * Icon for `WRITING RULES`/`WRITING RULE`.
27789
27975
  */
27790
27976
  get icon() {
27791
27977
  return '📝';
27792
27978
  }
27793
27979
  /**
27794
- * Markdown documentation for `WRITING RULES`.
27980
+ * Markdown documentation for `WRITING RULES`/`WRITING RULE` commitment.
27795
27981
  */
27796
27982
  get documentation() {
27797
27983
  return _spaceTrim.spaceTrim(`
@@ -27801,6 +27987,7 @@
27801
27987
 
27802
27988
  ## Key aspects
27803
27989
 
27990
+ - All writing rules are treated equally regardless of singular/plural form.
27804
27991
  - Use it for writing-only constraints such as tone, formatting, length, emoji usage, punctuation, or reading level.
27805
27992
  - Do **not** use it for problem-solving behavior, policy, tool usage, or decision-making logic. Use \`RULE\` for that.
27806
27993
  - Newer writing-rules blocks override conflicting earlier writing-rules blocks.
@@ -27999,7 +28186,8 @@
27999
28186
  new LanguageCommitmentDefinition('LANGUAGE'),
28000
28187
  new LanguageCommitmentDefinition('LANGUAGES'),
28001
28188
  new WritingSampleCommitmentDefinition(),
28002
- new WritingRulesCommitmentDefinition(),
28189
+ new WritingRulesCommitmentDefinition('WRITING RULES'),
28190
+ new WritingRulesCommitmentDefinition('WRITING RULE'),
28003
28191
  new SampleCommitmentDefinition('SAMPLE'),
28004
28192
  new SampleCommitmentDefinition('EXAMPLE'),
28005
28193
  new FormatCommitmentDefinition('FORMAT'),
@@ -30280,6 +30468,7 @@
30280
30468
  'claude-code',
30281
30469
  'opencode',
30282
30470
  'gemini',
30471
+ 'qwen-code',
30283
30472
  ];
30284
30473
  /**
30285
30474
  * All supported thinking-level values for CLI coding-agent runners.
@@ -30290,8 +30479,8 @@
30290
30479
  /**
30291
30480
  * Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
30292
30481
  *
30293
- * Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`)
30294
- * so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
30482
+ * Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`,
30483
+ * `qwen-code`) so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
30295
30484
  *
30296
30485
  * @public exported from `@promptbook/node`
30297
30486
  */