@promptbook/cli 0.112.0-131 → 0.112.0-133

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 (100) hide show
  1. package/apps/agents-server/src/app/admin/api-tokens/ApiTokensClient.tsx +4 -1
  2. package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +3 -0
  3. package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackTable.tsx +13 -8
  4. package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +3 -0
  5. package/apps/agents-server/src/app/admin/chat-history/ChatHistoryTable.tsx +13 -8
  6. package/apps/agents-server/src/app/admin/custom-css/CustomCssClient.tsx +4 -0
  7. package/apps/agents-server/src/app/admin/custom-css/CustomCssEditorPanel.tsx +7 -1
  8. package/apps/agents-server/src/app/admin/custom-css/CustomCssFilesPanel.tsx +7 -1
  9. package/apps/agents-server/src/app/admin/custom-js/CustomJsClient.tsx +11 -0
  10. package/apps/agents-server/src/app/admin/custom-js/CustomJsEditorPanel.tsx +7 -1
  11. package/apps/agents-server/src/app/admin/custom-js/CustomJsFilesPanel.tsx +7 -1
  12. package/apps/agents-server/src/app/admin/files/FilesGalleryClient.tsx +4 -0
  13. package/apps/agents-server/src/app/admin/files/FilesGalleryGrid.tsx +9 -11
  14. package/apps/agents-server/src/app/admin/files/FilesGalleryTable.tsx +9 -8
  15. package/apps/agents-server/src/app/admin/images/ImagesGalleryClient.tsx +4 -0
  16. package/apps/agents-server/src/app/admin/images/ImagesGalleryGrid.tsx +16 -11
  17. package/apps/agents-server/src/app/admin/images/ImagesGalleryTable.tsx +18 -9
  18. package/apps/agents-server/src/app/admin/login-methods/shibboleth/page.tsx +9 -9
  19. package/apps/agents-server/src/app/admin/messages/MessagesClient.tsx +7 -6
  20. package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +11 -10
  21. package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +4 -2
  22. package/apps/agents-server/src/app/admin/task-manager/TaskManagerTaskRow.tsx +14 -15
  23. package/apps/agents-server/src/app/admin/task-manager/TaskManagerTasksCard.tsx +4 -1
  24. package/apps/agents-server/src/app/admin/task-manager/useTaskManagerState.ts +6 -9
  25. package/apps/agents-server/src/app/admin/update/CustomCommitPicker.tsx +258 -0
  26. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +305 -108
  27. package/apps/agents-server/src/app/admin/usage/UsageClient.tsx +4 -2
  28. package/apps/agents-server/src/app/admin/usage/UsageClientAnalyticsPanels.tsx +6 -4
  29. package/apps/agents-server/src/app/admin/usage/UsageClientFormatting.ts +6 -12
  30. package/apps/agents-server/src/app/admin/usage/UsageClientTimelineChart.tsx +6 -3
  31. package/apps/agents-server/src/app/admin/usage/useUsageClientState.ts +12 -4
  32. package/apps/agents-server/src/app/admin/users/[userId]/UserDetailClient.tsx +8 -3
  33. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +6 -20
  34. package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorHistory.ts +9 -2
  35. package/apps/agents-server/src/app/agents/[agentName]/chat/useAgentChatHistoryClientState.ts +2 -15
  36. package/apps/agents-server/src/app/agents/[agentName]/history/page.tsx +6 -1
  37. package/apps/agents-server/src/app/agents/[agentName]/integration/CalendarIntegrationSection.tsx +23 -5
  38. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsClient.tsx +4 -2
  39. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsFiltersCard.tsx +9 -4
  40. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableCard.tsx +4 -1
  41. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableRow.tsx +10 -3
  42. package/apps/agents-server/src/app/api/admin/update/commits/route.ts +35 -0
  43. package/apps/agents-server/src/app/api/admin/update/route.ts +10 -2
  44. package/apps/agents-server/src/app/api/internal/user-chat-jobs/run/route.ts +14 -2
  45. package/apps/agents-server/src/app/dashboard/page.tsx +11 -16
  46. package/apps/agents-server/src/app/layout.tsx +12 -3
  47. package/apps/agents-server/src/app/swagger/SwaggerApiKeysPanel.tsx +4 -1
  48. package/apps/agents-server/src/app/system/user-memory/UserMemoryClient.tsx +4 -2
  49. package/apps/agents-server/src/app/system/user-wallet/UserWalletClient.tsx +3 -0
  50. package/apps/agents-server/src/app/system/user-wallet/UserWalletRecordsTable.tsx +5 -1
  51. package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorClient.tsx +3 -0
  52. package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorSidebar.tsx +7 -8
  53. package/apps/agents-server/src/components/Footer/Footer.tsx +3 -2
  54. package/apps/agents-server/src/components/Footer/getCommitFooterEmoji.ts +112 -0
  55. package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -2
  56. package/apps/agents-server/src/components/UsersList/UsersList.tsx +4 -2
  57. package/apps/agents-server/src/languages/translations/czech.yaml +1 -1
  58. package/apps/agents-server/src/languages/translations/english.yaml +1 -1
  59. package/apps/agents-server/src/middleware/applyEmbeddingHeader.ts +4 -2
  60. package/apps/agents-server/src/middleware/contentSecurityPolicy.ts +97 -0
  61. package/apps/agents-server/src/tools/createAgentProgressTools.ts +8 -6
  62. package/apps/agents-server/src/utils/localization/formatServerLanguageHumanReadableDate.ts +70 -0
  63. package/apps/agents-server/src/utils/localization/getRequestServerLanguage.ts +32 -0
  64. package/apps/agents-server/src/utils/userChat/createRunUserChatJobExecutionContext.ts +17 -0
  65. package/apps/agents-server/src/utils/userChat/createRunUserChatJobPersistenceController.ts +0 -21
  66. package/apps/agents-server/src/utils/userChat/persistUserChatJobProgressCard.ts +31 -0
  67. package/apps/agents-server/src/utils/userChat/retryUserChatJob.ts +0 -4
  68. package/apps/agents-server/src/utils/userChat/runUserChatJob.ts +29 -0
  69. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +2 -2
  70. package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +99 -401
  71. package/apps/agents-server/src/utils/vpsSelfUpdate.ts +625 -51
  72. package/esm/index.es.js +252 -41
  73. package/esm/index.es.js.map +1 -1
  74. package/esm/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
  75. package/esm/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
  76. package/esm/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
  77. package/esm/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
  78. package/esm/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
  79. package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
  80. package/esm/src/book-3.0/cliAgentEnv.d.ts +1 -1
  81. package/esm/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
  82. package/esm/src/version.d.ts +1 -1
  83. package/package.json +1 -1
  84. package/src/book-3.0/cliAgentEnv.ts +1 -1
  85. package/src/cli/cli-commands/agents-server/startAgentsServer.ts +1 -1
  86. package/src/cli/cli-commands/coder/ThinkingLevel.ts +3 -1
  87. package/src/other/templates/getTemplatesPipelineCollection.ts +681 -766
  88. package/src/version.ts +2 -2
  89. package/src/versions.txt +2 -0
  90. package/umd/index.umd.js +254 -44
  91. package/umd/index.umd.js.map +1 -1
  92. package/umd/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
  93. package/umd/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
  94. package/umd/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
  95. package/umd/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
  96. package/umd/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
  97. package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
  98. package/umd/src/book-3.0/cliAgentEnv.d.ts +1 -1
  99. package/umd/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
  100. 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.112.0-131';
19
+ export const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version = '0.112.0-133';
20
20
 
21
21
  /**
22
22
  * Represents the version string of the Promptbook engine.
23
- * It follows semantic versioning (e.g., `0.112.0-128`).
23
+ * It follows semantic versioning (e.g., `0.112.0-132`).
24
24
  *
25
25
  * @generated
26
26
  */
package/src/versions.txt CHANGED
@@ -1158,3 +1158,5 @@
1158
1158
  0.112.0-126
1159
1159
  0.112.0-128
1160
1160
  0.112.0-131
1161
+ 0.112.0-132
1162
+ 0.112.0-133
package/umd/index.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('fs/promises'), require('path'), require('child_process'), require('crypto'), require('fs'), require('dotenv'), require('moment'), require('waitasecond'), require('prompts'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('socket.io-client'), require('jszip'), require('@mozilla/readability'), require('jsdom'), require('crypto-js'), require('showdown'), require('glob-promise'), require('http'), require('express'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('react'), require('react-dom/server'), require('@anthropic-ai/sdk'), require('bottleneck'), require('@azure/openai'), require('rxjs'), require('@openai/agents'), require('openai'), require('typescript'), require('ignore'), require('readline'), require('events'), require('mime-types'), require('papaparse'), require('url'), require('pg'), require('@supabase/supabase-js')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'fs/promises', 'path', 'child_process', 'crypto', 'fs', 'dotenv', 'moment', 'waitasecond', 'prompts', 'crypto-js/enc-hex', 'crypto-js/sha256', 'socket.io-client', 'jszip', '@mozilla/readability', 'jsdom', 'crypto-js', 'showdown', 'glob-promise', 'http', 'express', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', 'react', 'react-dom/server', '@anthropic-ai/sdk', 'bottleneck', '@azure/openai', 'rxjs', '@openai/agents', 'openai', 'typescript', 'ignore', 'readline', 'events', 'mime-types', 'papaparse', 'url', 'pg', '@supabase/supabase-js'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global._spaceTrim, global.promises, global.path, global.child_process, global.crypto, global.fs, global.dotenv, global.moment, global.waitasecond, global.prompts, global.hexEncoder, global.sha256, global.socket_ioClient, global.JSZip, global.readability, global.jsdom, global.CryptoJS, global.showdown, global.glob, global.http, global.express, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.react, global.server, global.Anthropic, global.Bottleneck, global.openai, global.rxjs, global.agents, global.OpenAI, global.ts, global.ignore, global.readline, global.events, global.mimeTypes, global.papaparse, global.url, global.pg));
5
- })(this, (function (exports, colors, commander, _spaceTrim, promises, path, child_process, crypto, fs, dotenv, moment, waitasecond, prompts, hexEncoder, sha256, socket_ioClient, JSZip, readability, jsdom, CryptoJS, showdown, glob, http, express, socket_io, OpenApiValidator, swaggerUi, react, server, Anthropic, Bottleneck, openai, rxjs, agents, OpenAI, ts, ignore, readline, events, mimeTypes, papaparse, url, pg) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('fs/promises'), require('path'), require('child_process'), require('crypto'), require('fs'), require('dotenv'), require('moment'), require('waitasecond'), require('prompts'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('socket.io-client'), require('jszip'), require('@mozilla/readability'), require('jsdom'), require('crypto-js'), require('showdown'), require('glob-promise'), require('http'), require('express'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('react'), require('react-dom/server'), require('@anthropic-ai/sdk'), require('bottleneck'), require('@azure/openai'), require('rxjs'), require('@openai/agents'), require('openai'), require('typescript'), require('ignore'), require('readline'), require('events'), require('os'), require('mime-types'), require('papaparse'), require('url'), require('pg'), require('@supabase/supabase-js')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'fs/promises', 'path', 'child_process', 'crypto', 'fs', 'dotenv', 'moment', 'waitasecond', 'prompts', 'crypto-js/enc-hex', 'crypto-js/sha256', 'socket.io-client', 'jszip', '@mozilla/readability', 'jsdom', 'crypto-js', 'showdown', 'glob-promise', 'http', 'express', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', 'react', 'react-dom/server', '@anthropic-ai/sdk', 'bottleneck', '@azure/openai', 'rxjs', '@openai/agents', 'openai', 'typescript', 'ignore', 'readline', 'events', 'os', 'mime-types', 'papaparse', 'url', 'pg', '@supabase/supabase-js'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global._spaceTrim, global.promises, global.path, global.child_process, global.crypto, global.fs, global.dotenv, global.moment, global.waitasecond, global.prompts, global.hexEncoder, global.sha256, global.socket_ioClient, global.JSZip, global.readability, global.jsdom, global.CryptoJS, global.showdown, global.glob, global.http, global.express, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.react, global.server, global.Anthropic, global.Bottleneck, global.openai, global.rxjs, global.agents, global.OpenAI, global.ts, global.ignore, global.readline, global.events, global.os, global.mimeTypes, global.papaparse, global.url, global.pg));
5
+ })(this, (function (exports, colors, commander, _spaceTrim, promises, path, child_process, crypto, fs, dotenv, moment, waitasecond, prompts, hexEncoder, sha256, socket_ioClient, JSZip, readability, jsdom, CryptoJS, showdown, glob, http, express, socket_io, OpenApiValidator, swaggerUi, react, server, Anthropic, Bottleneck, openai, rxjs, agents, OpenAI, ts, ignore, readline, events, os, mimeTypes, papaparse, url, pg) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
@@ -63,7 +63,7 @@
63
63
  * @generated
64
64
  * @see https://github.com/webgptorg/promptbook
65
65
  */
66
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-131';
66
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-133';
67
67
  /**
68
68
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
69
69
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1723,28 +1723,6 @@
1723
1723
  // TODO: [🗽] Unite branding and make single place for it
1724
1724
  // Note: [💞] Ignore a discrepancy between file name and entity name
1725
1725
 
1726
- /**
1727
- * Supported thinking-level CLI values for coding-agent runners with configurable reasoning effort.
1728
- *
1729
- * @private internal shared utility of `ptbk coder run`
1730
- */
1731
- const THINKING_LEVEL_VALUES = ['low', 'medium', 'high', 'xhigh'];
1732
- /**
1733
- * Parses and validates an optional thinking-level option value.
1734
- *
1735
- * @private internal shared utility of `ptbk coder run`
1736
- */
1737
- function parseThinkingLevel(thinkingLevelValue) {
1738
- if (thinkingLevelValue === undefined) {
1739
- return undefined;
1740
- }
1741
- if (THINKING_LEVEL_VALUES.includes(thinkingLevelValue)) {
1742
- return thinkingLevelValue;
1743
- }
1744
- throw new Error(`Invalid thinking level "${thinkingLevelValue}". Use one of: ${THINKING_LEVEL_VALUES.join(', ')}.`);
1745
- }
1746
- // Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
1747
-
1748
1726
  // Note: [💞] Ignore a discrepancy between file name and entity name
1749
1727
  /**
1750
1728
  * All CLI harness names supported by `CliAgent` and `ptbk agent exec`.
@@ -1759,6 +1737,12 @@
1759
1737
  'opencode',
1760
1738
  'gemini',
1761
1739
  ];
1740
+ /**
1741
+ * All supported thinking-level values for CLI coding-agent runners.
1742
+ *
1743
+ * @public exported from `@promptbook/node`
1744
+ */
1745
+ const CLI_AGENT_THINKING_LEVEL_VALUES = ['low', 'medium', 'high', 'xhigh', 'max'];
1762
1746
  /**
1763
1747
  * Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
1764
1748
  *
@@ -1781,6 +1765,28 @@
1781
1765
  */
1782
1766
  const PTBK_THINKING_LEVEL_ENV = 'PTBK_THINKING_LEVEL';
1783
1767
 
1768
+ /**
1769
+ * Supported thinking-level CLI values for coding-agent runners with configurable reasoning effort.
1770
+ *
1771
+ * @private internal shared utility of `ptbk coder run`
1772
+ */
1773
+ const THINKING_LEVEL_VALUES = CLI_AGENT_THINKING_LEVEL_VALUES;
1774
+ /**
1775
+ * Parses and validates an optional thinking-level option value.
1776
+ *
1777
+ * @private internal shared utility of `ptbk coder run`
1778
+ */
1779
+ function parseThinkingLevel(thinkingLevelValue) {
1780
+ if (thinkingLevelValue === undefined) {
1781
+ return undefined;
1782
+ }
1783
+ if (THINKING_LEVEL_VALUES.includes(thinkingLevelValue)) {
1784
+ return thinkingLevelValue;
1785
+ }
1786
+ throw new Error(`Invalid thinking level "${thinkingLevelValue}". Use one of: ${THINKING_LEVEL_VALUES.join(', ')}.`);
1787
+ }
1788
+ // Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
1789
+
1784
1790
  /**
1785
1791
  * Runner identifiers supported by Promptbook CLI agent orchestration commands.
1786
1792
  *
@@ -4566,14 +4572,16 @@
4566
4572
 
4567
4573
  /**
4568
4574
  * Calendar formats used when displaying the estimated completion time.
4575
+ *
4576
+ * Uses 24-hour format (`HH:mm`) so estimates are unambiguous (for example `17:30` instead of `5:30`).
4569
4577
  */
4570
4578
  const ESTIMATED_DONE_CALENDAR_FORMATS = {
4571
- sameDay: '[Today] h:mm',
4572
- nextDay: '[Tomorrow] h:mm',
4573
- nextWeek: 'dddd h:mm',
4574
- lastDay: '[Yesterday] h:mm',
4575
- lastWeek: 'dddd h:mm',
4576
- sameElse: 'MMM D h:mm',
4579
+ sameDay: '[Today] HH:mm',
4580
+ nextDay: '[Tomorrow] HH:mm',
4581
+ nextWeek: 'dddd HH:mm',
4582
+ lastDay: '[Yesterday] HH:mm',
4583
+ lastWeek: 'dddd HH:mm',
4584
+ sameElse: 'MMM D HH:mm',
4577
4585
  };
4578
4586
  /**
4579
4587
  * Formats a duration into a compact string such as "3h 12m" or "45s".
@@ -4601,8 +4609,12 @@
4601
4609
 
4602
4610
  /**
4603
4611
  * Builds a session-scoped progress snapshot from prompt stats and elapsed active time.
4612
+ *
4613
+ * When the current session has not finished any prompt yet but a `cachedAveragePromptDurationMs` is
4614
+ * provided (loaded from the per-config estimate cache stored in the temp folder), the snapshot uses
4615
+ * that historical average to project the remaining work instead of waiting for the first completion.
4604
4616
  */
4605
- function buildCoderRunProgressSnapshot(stats, elapsedDuration, initialDone) {
4617
+ function buildCoderRunProgressSnapshot(stats, elapsedDuration, initialDone, cachedAveragePromptDurationMs) {
4606
4618
  const totalPrompts = stats.done + stats.forAgent + stats.toBeWritten;
4607
4619
  const sessionDone = Math.max(0, stats.done - initialDone);
4608
4620
  const sessionRemaining = stats.forAgent;
@@ -4610,12 +4622,22 @@
4610
4622
  const currentPromptIndex = sessionTotal > 0 ? Math.min(sessionDone + 1, sessionTotal) : 0;
4611
4623
  const percentage = sessionTotal > 0 ? Math.round((sessionDone / sessionTotal) * 100) : 0;
4612
4624
  const elapsedText = formatDurationBrief(elapsedDuration);
4625
+ const elapsedMs = elapsedDuration.asMilliseconds();
4613
4626
  let estimatedTotalText = 'estimating...';
4614
4627
  let estimatedLabel = 'after first completion';
4615
4628
  let isEstimatedTotalKnown = false;
4629
+ let estimatedTotalMs;
4616
4630
  if (sessionTotal > 0 && sessionDone > 0) {
4617
- const estimatedTotalMs = (elapsedDuration.asMilliseconds() * sessionTotal) / sessionDone;
4618
- const estimatedRemainingMs = Math.max(0, estimatedTotalMs - elapsedDuration.asMilliseconds());
4631
+ estimatedTotalMs = (elapsedMs * sessionTotal) / sessionDone;
4632
+ }
4633
+ else if (sessionTotal > 0 &&
4634
+ cachedAveragePromptDurationMs !== undefined &&
4635
+ cachedAveragePromptDurationMs > 0) {
4636
+ const projectedRemainingMs = sessionRemaining * cachedAveragePromptDurationMs;
4637
+ estimatedTotalMs = elapsedMs + projectedRemainingMs;
4638
+ }
4639
+ if (estimatedTotalMs !== undefined) {
4640
+ const estimatedRemainingMs = Math.max(0, estimatedTotalMs - elapsedMs);
4619
4641
  const estimatedTotalDuration = moment__default["default"].duration(estimatedTotalMs);
4620
4642
  const estimatedCompletion = moment__default["default"]().add(estimatedRemainingMs, 'milliseconds');
4621
4643
  estimatedTotalText = formatDurationBrief(estimatedTotalDuration);
@@ -4749,12 +4771,21 @@
4749
4771
  this.stats = stats;
4750
4772
  this.emitChange();
4751
4773
  }
4774
+ /**
4775
+ * Sets the cached average prompt duration (in milliseconds) loaded from the temp-folder estimate cache.
4776
+ *
4777
+ * Used to project completion estimates before the first prompt of the current session finishes.
4778
+ */
4779
+ setCachedAveragePromptDurationMs(cachedAveragePromptDurationMs) {
4780
+ this.cachedAveragePromptDurationMs = cachedAveragePromptDurationMs;
4781
+ this.emitChange();
4782
+ }
4752
4783
  /**
4753
4784
  * Computes a progress snapshot on demand so elapsed time ticks with periodic re-renders.
4754
4785
  */
4755
4786
  getProgress() {
4756
4787
  var _a;
4757
- return buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done);
4788
+ return buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done, this.cachedAveragePromptDurationMs);
4758
4789
  }
4759
4790
  /**
4760
4791
  * Sets the label of the prompt currently being processed and resets per-prompt state.
@@ -27461,17 +27492,21 @@
27461
27492
  });
27462
27493
  }
27463
27494
 
27495
+ /**
27496
+ * Base delimiter used for passing large prompts through stdin.
27497
+ */
27498
+ const CLAUDE_PROMPT_DELIMITER = 'CLAUDE_PROMPT';
27464
27499
  /**
27465
27500
  * Builds the shell script that runs Claude Code with the prompt and coding context.
27466
27501
  */
27467
27502
  function buildClaudeScript(options) {
27468
- const delimiter = 'CLAUDE_PROMPT';
27503
+ const THINKING_LEVEL_ARGUMENT = options.thinkingLevel ? ` --effort ${options.thinkingLevel}` : '';
27469
27504
  return spaceTrim((block) => `
27470
- claude --allowedTools "Bash,Read,Edit,Write" --output-format json --print <<'${delimiter}'
27505
+ claude --allowedTools "Bash,Read,Edit,Write"${THINKING_LEVEL_ARGUMENT} --output-format json --print <<'${CLAUDE_PROMPT_DELIMITER}'
27471
27506
 
27472
27507
  ${block(options.prompt)}
27473
27508
 
27474
- ${delimiter}
27509
+ ${CLAUDE_PROMPT_DELIMITER}
27475
27510
  `);
27476
27511
  }
27477
27512
 
@@ -27607,7 +27642,8 @@
27607
27642
  /**
27608
27643
  * Creates a new Claude Code runner.
27609
27644
  */
27610
- constructor() {
27645
+ constructor(options = {}) {
27646
+ this.options = options;
27611
27647
  this.name = 'claude-code';
27612
27648
  }
27613
27649
  /**
@@ -27616,6 +27652,7 @@
27616
27652
  async runPrompt(options) {
27617
27653
  const scriptContent = buildClaudeScript({
27618
27654
  prompt: options.prompt,
27655
+ thinkingLevel: this.options.thinkingLevel,
27619
27656
  });
27620
27657
  const output = await $runGoScriptWithOutput({
27621
27658
  scriptPath: options.scriptPath,
@@ -28788,7 +28825,9 @@
28788
28825
  }), actualRunnerModel);
28789
28826
  }
28790
28827
  if (agentName === 'claude-code') {
28791
- return createRunnerResolution(options, new ClaudeCodeRunner());
28828
+ return createRunnerResolution(options, new ClaudeCodeRunner({
28829
+ thinkingLevel: options.thinkingLevel,
28830
+ }));
28792
28831
  }
28793
28832
  if (agentName === 'opencode') {
28794
28833
  return createRunnerResolution(options, new OpencodeRunner({
@@ -37862,7 +37901,7 @@
37862
37901
  *
37863
37902
  * @private internal constant of `ptbk agents-server`
37864
37903
  */
37865
- const USER_CHAT_JOB_WORKER_POLL_INTERVAL_MS = 2000;
37904
+ const USER_CHAT_JOB_WORKER_POLL_INTERVAL_MS = 10000;
37866
37905
  /**
37867
37906
  * Number of identical worker failures suppressed before logging a repeated summary.
37868
37907
  *
@@ -69687,6 +69726,15 @@
69687
69726
  this.render();
69688
69727
  this.interval = setInterval(() => this.render(), PROGRESS_REFRESH_INTERVAL_MS);
69689
69728
  }
69729
+ /**
69730
+ * Sets the cached average prompt duration (in milliseconds) loaded from the temp-folder estimate cache.
69731
+ *
69732
+ * Used to project completion estimates before the first prompt of the current session finishes.
69733
+ */
69734
+ setCachedAveragePromptDurationMs(cachedAveragePromptDurationMs) {
69735
+ this.cachedAveragePromptDurationMs = cachedAveragePromptDurationMs;
69736
+ this.render();
69737
+ }
69690
69738
  /**
69691
69739
  * Updates the progress statistics shown in the header.
69692
69740
  */
@@ -69757,7 +69805,7 @@
69757
69805
  */
69758
69806
  buildProgressLines() {
69759
69807
  var _a, _b;
69760
- const snapshot = buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done);
69808
+ const snapshot = buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done, this.cachedAveragePromptDurationMs);
69761
69809
  const columns = Math.max(40, (_b = process.stdout.columns) !== null && _b !== void 0 ? _b : 80);
69762
69810
  const workingLine = snapshot.sessionTotal > 0
69763
69811
  ? [
@@ -69815,6 +69863,118 @@
69815
69863
  return `${count} prompt${count === 1 ? '' : 's'}`;
69816
69864
  }
69817
69865
 
69866
+ /**
69867
+ * Sub-directory of the OS temp folder where per-config estimate caches are stored.
69868
+ *
69869
+ * @private internal constant of `coderRunEstimateCache`
69870
+ */
69871
+ const ESTIMATE_CACHE_DIRECTORY_NAME = 'ptbk-coder-estimates';
69872
+ /**
69873
+ * Absolute path to the directory where estimate caches are persisted.
69874
+ *
69875
+ * @private internal utility of `coderRunEstimateCache`
69876
+ */
69877
+ function getEstimateCacheDirectory() {
69878
+ return path.join(os.tmpdir(), ESTIMATE_CACHE_DIRECTORY_NAME);
69879
+ }
69880
+ /**
69881
+ * Sanitizes a single identifier component so that it is safe to use as a filename segment.
69882
+ *
69883
+ * @private internal utility of `coderRunEstimateCache`
69884
+ */
69885
+ function sanitizeFileNameSegment(value) {
69886
+ return value.replace(/[^a-zA-Z0-9._-]/g, '_');
69887
+ }
69888
+ /**
69889
+ * Builds the cache filename for a given runner configuration.
69890
+ *
69891
+ * @private internal utility of `coderRunEstimateCache`
69892
+ */
69893
+ function buildEstimateCacheFileName(key) {
69894
+ var _a, _b;
69895
+ const harnessSegment = sanitizeFileNameSegment(key.harness);
69896
+ const modelSegment = sanitizeFileNameSegment((_a = key.model) !== null && _a !== void 0 ? _a : 'default');
69897
+ const thinkingLevelSegment = sanitizeFileNameSegment((_b = key.thinkingLevel) !== null && _b !== void 0 ? _b : 'default');
69898
+ return `${harnessSegment}__${modelSegment}__${thinkingLevelSegment}.json`;
69899
+ }
69900
+ /**
69901
+ * Reads the previously persisted cache entry for a configuration if available.
69902
+ *
69903
+ * @private internal utility of `coderRunEstimateCache`
69904
+ */
69905
+ async function readEstimateCacheEntry(filePath) {
69906
+ try {
69907
+ const content = await fs.promises.readFile(filePath, 'utf-8');
69908
+ const parsed = JSON.parse(content);
69909
+ if (typeof parsed.averagePromptDurationMs !== 'number' ||
69910
+ !Number.isFinite(parsed.averagePromptDurationMs) ||
69911
+ parsed.averagePromptDurationMs <= 0 ||
69912
+ typeof parsed.sampleCount !== 'number' ||
69913
+ !Number.isFinite(parsed.sampleCount) ||
69914
+ parsed.sampleCount <= 0) {
69915
+ return undefined;
69916
+ }
69917
+ return {
69918
+ averagePromptDurationMs: parsed.averagePromptDurationMs,
69919
+ sampleCount: parsed.sampleCount,
69920
+ updatedAt: typeof parsed.updatedAt === 'string' ? parsed.updatedAt : new Date().toISOString(),
69921
+ };
69922
+ }
69923
+ catch (_a) {
69924
+ return undefined;
69925
+ }
69926
+ }
69927
+ /**
69928
+ * Loads the cached average prompt duration for the given runner configuration.
69929
+ *
69930
+ * Returns `undefined` when no usable cache entry exists. Cache failures must never break the run, so this
69931
+ * function swallows IO and parsing errors instead of throwing.
69932
+ *
69933
+ * @public exported for use by the coder run progress displays
69934
+ */
69935
+ async function loadCachedAveragePromptDurationMs(key) {
69936
+ const filePath = path.join(getEstimateCacheDirectory(), buildEstimateCacheFileName(key));
69937
+ const entry = await readEstimateCacheEntry(filePath);
69938
+ return entry === null || entry === void 0 ? void 0 : entry.averagePromptDurationMs;
69939
+ }
69940
+ /**
69941
+ * Records a new prompt-duration sample for the given runner configuration into the temp folder cache.
69942
+ *
69943
+ * Updates a running average so future `ptbk coder run` / `ptbk coder server` invocations can show
69944
+ * meaningful estimates immediately, before the first prompt of the new session has completed.
69945
+ *
69946
+ * Cache failures are swallowed because the next-run estimate is best-effort and must not affect the
69947
+ * current run.
69948
+ *
69949
+ * @public exported for use by the prompt round finalizer
69950
+ */
69951
+ async function recordPromptDurationSample(key, promptDurationMs) {
69952
+ var _a, _b;
69953
+ if (!Number.isFinite(promptDurationMs) || promptDurationMs <= 0) {
69954
+ return;
69955
+ }
69956
+ try {
69957
+ const cacheDirectory = getEstimateCacheDirectory();
69958
+ await fs.promises.mkdir(cacheDirectory, { recursive: true });
69959
+ const filePath = path.join(cacheDirectory, buildEstimateCacheFileName(key));
69960
+ const previousEntry = await readEstimateCacheEntry(filePath);
69961
+ const previousSampleCount = (_a = previousEntry === null || previousEntry === void 0 ? void 0 : previousEntry.sampleCount) !== null && _a !== void 0 ? _a : 0;
69962
+ const previousTotalMs = ((_b = previousEntry === null || previousEntry === void 0 ? void 0 : previousEntry.averagePromptDurationMs) !== null && _b !== void 0 ? _b : 0) * previousSampleCount;
69963
+ const nextSampleCount = previousSampleCount + 1;
69964
+ const nextAveragePromptDurationMs = (previousTotalMs + promptDurationMs) / nextSampleCount;
69965
+ const nextEntry = {
69966
+ averagePromptDurationMs: nextAveragePromptDurationMs,
69967
+ sampleCount: nextSampleCount,
69968
+ updatedAt: new Date().toISOString(),
69969
+ };
69970
+ await fs.promises.writeFile(filePath, JSON.stringify(nextEntry, null, 4), 'utf-8');
69971
+ }
69972
+ catch (_c) {
69973
+ // Note: Persisting the estimate cache is best-effort. Failures must not affect the current run.
69974
+ }
69975
+ }
69976
+ // Note: [🟡] Code in this file is only used from `@promptbook/cli` orchestration scripts and is not shipped to other consumers.
69977
+
69818
69978
  /**
69819
69979
  * Reads an optional agent `.book` file and compiles its system message for injection into coder prompts.
69820
69980
  *
@@ -71782,6 +71942,11 @@
71782
71942
  markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
71783
71943
  await writePromptFile(nextPrompt.file);
71784
71944
  await normalizeLineEndingsForCurrentRound(runOptions, roundChangedFilesSnapshot);
71945
+ await recordPromptDurationInEstimateCache({
71946
+ options: runOptions,
71947
+ runnerMetadata,
71948
+ promptExecutionStartedDate,
71949
+ });
71785
71950
  if (!runOptions.noCommit) {
71786
71951
  await waitForCommitConfirmationIfNeeded({
71787
71952
  options: runOptions,
@@ -71883,6 +72048,24 @@
71883
72048
  logger: console,
71884
72049
  });
71885
72050
  }
72051
+ /**
72052
+ * Persists the duration of one successful prompt round into the per-config estimate cache so the
72053
+ * next `ptbk coder run` / `ptbk coder server` invocation can show a meaningful completion estimate
72054
+ * before its own first prompt has finished.
72055
+ */
72056
+ async function recordPromptDurationInEstimateCache(options) {
72057
+ var _a;
72058
+ const { options: runOptions, runnerMetadata, promptExecutionStartedDate } = options;
72059
+ if (!runOptions.agentName) {
72060
+ return;
72061
+ }
72062
+ const promptDurationMs = moment__default["default"]().diff(promptExecutionStartedDate);
72063
+ await recordPromptDurationSample({
72064
+ harness: runOptions.agentName,
72065
+ model: (_a = runnerMetadata.modelName) !== null && _a !== void 0 ? _a : runOptions.model,
72066
+ thinkingLevel: runOptions.thinkingLevel,
72067
+ }, promptDurationMs);
72068
+ }
71886
72069
  /**
71887
72070
  * Normalizes line endings in files modified during the current coding round.
71888
72071
  */
@@ -71932,6 +72115,12 @@
71932
72115
  const { runner, actualRunnerModel, runnerMetadata } = resolvePromptRunner(options);
71933
72116
  console.info(colors__default["default"].green(`Running prompts with ${runner.name}`));
71934
72117
  initializeRunUi(uiHandle, runner.name, actualRunnerModel, options);
72118
+ await seedCachedAveragePromptDuration({
72119
+ options,
72120
+ actualRunnerModel,
72121
+ progressDisplay,
72122
+ uiHandle,
72123
+ });
71935
72124
  let hasShownUpcomingTasks = false;
71936
72125
  let hasWaitedForStart = false;
71937
72126
  let previousRoundStartTime;
@@ -72293,6 +72482,27 @@
72293
72482
  progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
72294
72483
  uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
72295
72484
  }
72485
+ /**
72486
+ * Loads the cached average prompt duration for the current runner configuration and seeds both
72487
+ * progress displays with it so estimates are shown immediately, even before the first prompt of
72488
+ * the current session completes.
72489
+ */
72490
+ async function seedCachedAveragePromptDuration(options) {
72491
+ const { options: runOptions, actualRunnerModel, progressDisplay, uiHandle } = options;
72492
+ if (!runOptions.agentName) {
72493
+ return;
72494
+ }
72495
+ const cachedAveragePromptDurationMs = await loadCachedAveragePromptDurationMs({
72496
+ harness: runOptions.agentName,
72497
+ model: actualRunnerModel !== null && actualRunnerModel !== void 0 ? actualRunnerModel : runOptions.model,
72498
+ thinkingLevel: runOptions.thinkingLevel,
72499
+ });
72500
+ if (cachedAveragePromptDurationMs === undefined) {
72501
+ return;
72502
+ }
72503
+ progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.setCachedAveragePromptDurationMs(cachedAveragePromptDurationMs);
72504
+ uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCachedAveragePromptDurationMs(cachedAveragePromptDurationMs);
72505
+ }
72296
72506
  /**
72297
72507
  * Stops active displays and prints the git identity tip for real runs.
72298
72508
  */