@promptbook/cli 0.112.0-104 → 0.112.0-106

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 (174) hide show
  1. package/apps/agents-server/src/app/admin/image-generator-test/ImageAttachmentsEditor.tsx +19 -3
  2. package/apps/agents-server/src/app/admin/limits/LimitsClient.tsx +11 -12
  3. package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +34 -2
  4. package/apps/agents-server/src/app/admin/servers/CreateServerDialog.tsx +6 -1
  5. package/apps/agents-server/src/app/admin/servers/useCreateServerWizard.ts +13 -1
  6. package/apps/agents-server/src/app/agents/[agentName]/AgentChatWrapper.tsx +11 -2
  7. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +11 -1
  8. package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +7 -1
  9. package/apps/agents-server/src/app/agents/[agentName]/chat/CanonicalAgentChatSurface.tsx +11 -1
  10. package/apps/agents-server/src/app/agents/[agentName]/images/default-avatar.png/route.ts +6 -2
  11. package/apps/agents-server/src/app/api/images/[filename]/route.ts +6 -2
  12. package/apps/agents-server/src/app/api/internal/agent-runner-limits/route.ts +51 -0
  13. package/apps/agents-server/src/app/api/upload/route.ts +48 -12
  14. package/apps/agents-server/src/app/layout.tsx +13 -0
  15. package/apps/agents-server/src/components/FileUploadAvailability/FileUploadAvailabilityContext.tsx +50 -0
  16. package/apps/agents-server/src/components/FileUploadAvailability/FileUploadUnavailableNotice.tsx +45 -0
  17. package/apps/agents-server/src/components/LayoutWrapper/LayoutWrapper.tsx +85 -76
  18. package/apps/agents-server/src/components/NewAgentDialog/NewAgentDialog.tsx +7 -3
  19. package/apps/agents-server/src/components/NewAgentDialog/NewAgentWizardKnowledgeStep.tsx +6 -0
  20. package/apps/agents-server/src/components/NewAgentDialog/useNewAgentWizardKnowledgeState.ts +8 -1
  21. package/apps/agents-server/src/constants/serverLimits.ts +22 -2
  22. package/apps/agents-server/src/database/seedDefaultAgents.ts +218 -0
  23. package/apps/agents-server/src/tools/$provideCdnForServer.ts +72 -8
  24. package/apps/agents-server/src/utils/defaultAgents/loadDefaultAgentBooks.ts +103 -0
  25. package/apps/agents-server/src/utils/knowledge/createInlineKnowledgeSourceUploader.ts +24 -5
  26. package/apps/agents-server/src/utils/serverLimits.ts +26 -1
  27. package/apps/agents-server/src/utils/serverManagement/createManagedServer/seedServerDefaultAgents.ts +1 -85
  28. package/apps/agents-server/src/utils/shareTargetPayloads.ts +20 -2
  29. package/apps/agents-server/src/utils/upload/fileUploadAvailability.ts +91 -0
  30. package/apps/agents-server/src/utils/upload/uploadFileToServer.ts +46 -2
  31. package/esm/apps/agents-server/src/constants/federatedAgentImport.d.ts +42 -0
  32. package/esm/apps/agents-server/src/constants/serverLimits.d.ts +207 -0
  33. package/esm/apps/agents-server/src/constants/toolUsageLimits.d.ts +55 -0
  34. package/esm/index.es.js +602 -39
  35. package/esm/index.es.js.map +1 -1
  36. package/esm/scripts/run-agent-messages/main/AgentMessageFailureTracker.d.ts +27 -0
  37. package/esm/scripts/run-agent-messages/main/handleAgentWatchError.d.ts +4 -0
  38. package/esm/scripts/run-agent-messages/main/runAgentMessages.d.ts +1 -0
  39. package/esm/scripts/run-agent-messages/messages/moveAgentMessageToFailed.d.ts +17 -0
  40. package/esm/src/book-components/BookEditor/BookEditor.d.ts +5 -4
  41. package/esm/src/book-components/BookEditor/BookEditorTheme.d.ts +24 -0
  42. package/esm/src/book-components/BookEditor/useBookEditorMonacoLanguage.d.ts +1 -6
  43. package/esm/src/book-components/BookEditor/useBookEditorMonacoLifecycle.d.ts +1 -4
  44. package/esm/src/book-components/BookEditor/useBookEditorMonacoStyles.d.ts +2 -1
  45. package/esm/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +6 -0
  46. package/esm/src/version.d.ts +1 -1
  47. package/package.json +1 -1
  48. package/src/avatars/visuals/octopus3d3AvatarVisual.ts +28 -29
  49. package/src/book-components/BookEditor/BookEditor.tsx +10 -7
  50. package/src/book-components/BookEditor/BookEditorMonaco.tsx +3 -1
  51. package/src/book-components/BookEditor/BookEditorTheme.ts +32 -0
  52. package/src/book-components/BookEditor/useBookEditorMonacoLanguage.ts +15 -15
  53. package/src/book-components/BookEditor/useBookEditorMonacoLifecycle.ts +1 -5
  54. package/src/book-components/BookEditor/useBookEditorMonacoStyles.ts +2 -1
  55. package/src/cli/cli-commands/agent-folder/agentProjectPaths.ts +7 -0
  56. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +109 -9
  57. package/src/cli/cli-commands/agents-server/startAgentsServer.ts +132 -4
  58. package/src/other/templates/getTemplatesPipelineCollection.ts +874 -760
  59. package/src/version.ts +2 -2
  60. package/src/versions.txt +2 -0
  61. package/umd/apps/agents-server/src/constants/federatedAgentImport.d.ts +42 -0
  62. package/umd/apps/agents-server/src/constants/serverLimits.d.ts +207 -0
  63. package/umd/apps/agents-server/src/constants/toolUsageLimits.d.ts +55 -0
  64. package/umd/index.umd.js +602 -39
  65. package/umd/index.umd.js.map +1 -1
  66. package/umd/scripts/run-agent-messages/main/AgentMessageFailureTracker.d.ts +27 -0
  67. package/umd/scripts/run-agent-messages/main/handleAgentWatchError.d.ts +4 -0
  68. package/umd/scripts/run-agent-messages/main/runAgentMessages.d.ts +1 -0
  69. package/umd/scripts/run-agent-messages/messages/moveAgentMessageToFailed.d.ts +17 -0
  70. package/umd/src/book-components/BookEditor/BookEditor.d.ts +5 -4
  71. package/umd/src/book-components/BookEditor/BookEditorTheme.d.ts +24 -0
  72. package/umd/src/book-components/BookEditor/useBookEditorMonacoLanguage.d.ts +1 -6
  73. package/umd/src/book-components/BookEditor/useBookEditorMonacoLifecycle.d.ts +1 -4
  74. package/umd/src/book-components/BookEditor/useBookEditorMonacoStyles.d.ts +2 -1
  75. package/umd/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +6 -0
  76. package/umd/src/version.d.ts +1 -1
  77. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddress.test.ts.todo +0 -108
  78. package/apps/agents-server/src/message-providers/email/_common/utils/parseEmailAddresses.test.ts.todo +0 -117
  79. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddress.test.ts.todo +0 -119
  80. package/apps/agents-server/src/message-providers/email/_common/utils/stringifyEmailAddresses.test.ts.todo +0 -74
  81. package/apps/agents-server/src/utils/defaultAgents/defaultAgents.ts +0 -168
  82. package/apps/agents-server/src/utils/defaultAgents/installDefaultAgents.ts +0 -139
  83. package/apps/agents-server/tests/e2e/authentication-and-navigation.spec.ts.todo +0 -178
  84. package/src/_packages/browser.index.ts +0 -31
  85. package/src/_packages/browser.readme.md +0 -43
  86. package/src/book-2.0/agent-source/parseAgentSourceWithCommitments.test.ts.todo +0 -265
  87. package/src/book-components/BookEditor/BookEditorMonaco.test.tsx.todo +0 -115
  88. package/src/book-components/Chat/utils/renderMarkdown.test.ts.tmp +0 -199
  89. package/src/collection/agent-collection/constructors/agent-collection-in-directory/AgentCollectionInDirectory.test.ts.todo +0 -131
  90. package/src/commands/_common/parseCommand.test.ts.todo +0 -48
  91. package/src/commitments/META_LINK/META_LINK.test.ts.todo +0 -75
  92. package/src/conversion/validation/pipelineStringToJson-errors.test.ts.todo +0 -33
  93. package/src/dialogs/simple-prompt/SimplePromptInterfaceTools.ts +0 -51
  94. package/src/executables/browsers/locateSafari.test.ts.tmp +0 -15
  95. package/src/execution/PromptbookFetch.test-type.ts +0 -14
  96. package/src/execution/createPipelineExecutor/00-createPipelineExecutor.test.ts.todo +0 -0
  97. package/src/execution/execution-report/executionReportJsonToString.test.ts.todo +0 -83
  98. package/src/execution/utils/usageToHuman.test.ts.todo +0 -80
  99. package/src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.ts +0 -76
  100. package/src/llm-providers/_common/utils/assertUniqueModels.ts +0 -27
  101. package/src/llm-providers/_multiple/playground/playground.ts +0 -141
  102. package/src/llm-providers/_multiple/playground/tsconfig.json +0 -19
  103. package/src/llm-providers/agent/playground/playground.ts +0 -190
  104. package/src/llm-providers/agent/playground/tsconfig.json +0 -19
  105. package/src/llm-providers/anthropic-claude/playground/playground.ts +0 -99
  106. package/src/llm-providers/anthropic-claude/playground/tsconfig.json +0 -19
  107. package/src/llm-providers/azure-openai/playground/playground.ts +0 -101
  108. package/src/llm-providers/azure-openai/playground/tsconfig.json +0 -19
  109. package/src/llm-providers/ollama/playground/playground.ts +0 -120
  110. package/src/llm-providers/ollama/playground/tsconfig.json +0 -19
  111. package/src/llm-providers/openai/playground/playground.ts +0 -406
  112. package/src/llm-providers/openai/playground/tsconfig.json +0 -19
  113. package/src/llm-providers/remote/playground/playground.ts +0 -144
  114. package/src/llm-providers/remote/playground/tsconfig.json +0 -19
  115. package/src/llm-providers/vercel/playground/playground.ts +0 -133
  116. package/src/llm-providers/vercel/playground/tsconfig.json +0 -19
  117. package/src/personas/preparePersona.test.ts.todo +0 -126
  118. package/src/playground/backup/_playground-boilerplate.ts.txt +0 -37
  119. package/src/playground/backup/playground-agent-os.txt +0 -62
  120. package/src/playground/backup/playground-brj-app.ts.txt +0 -302
  121. package/src/playground/backup/playground-browser-playwright.txt +0 -110
  122. package/src/playground/backup/playground-claude-mcp.txt +0 -43
  123. package/src/playground/backup/playground-document-conversion.txt +0 -84
  124. package/src/playground/backup/playground-glob.ts.txt +0 -42
  125. package/src/playground/backup/playground-mcp-server.txt +0 -1
  126. package/src/playground/backup/playground-openai-agent-kit.txt +0 -73
  127. package/src/playground/backup/playground-openai-function-calling.txt +0 -131
  128. package/src/playground/backup/playground-openai-streaming.ts.txt +0 -68
  129. package/src/playground/backup/playground-scrape-knowledge.txt +0 -65
  130. package/src/playground/backup/playground-scraperFetch.ts.txt +0 -44
  131. package/src/playground/backup/playground-using-openai-compatible-route-on-agents-server.ts.txt +0 -49
  132. package/src/playground/backup/playground-write-pavolhejny-bio.txt +0 -120
  133. package/src/playground/permanent/_boilerplate.ts +0 -54
  134. package/src/playground/permanent/agent-with-browser-playground.ts +0 -92
  135. package/src/playground/permanent/error-handling-playground.ts +0 -103
  136. package/src/playground/playground.ts +0 -36
  137. package/src/playground/tsconfig.json +0 -19
  138. package/src/scrapers/_boilerplate/BoilerplateScraper.test.ts.todo +0 -73
  139. package/src/scrapers/_boilerplate/playground/boilerplate-scraper-playground.ts +0 -79
  140. package/src/scrapers/_boilerplate/playground/tsconfig.json +0 -19
  141. package/src/scrapers/_common/utils/files/blobToDataurl.test.ts.todo +0 -17
  142. package/src/scrapers/_common/utils/files/dataurlToBlob.test.ts.todo +0 -52
  143. package/src/scrapers/_common/utils/files/isValidDataurl.test.ts.todo +0 -42
  144. package/src/scrapers/_common/utils/files/shorten.test.ts.todo +0 -13
  145. package/src/scrapers/document/playground/document-scraper-playground.ts +0 -80
  146. package/src/scrapers/document/playground/tsconfig.json +0 -19
  147. package/src/scrapers/document-legacy/playground/legacy-document-scraper-playground.ts +0 -80
  148. package/src/scrapers/document-legacy/playground/tsconfig.json +0 -19
  149. package/src/scrapers/markdown/playground/markdown-scraper-playground.ts +0 -74
  150. package/src/scrapers/markdown/playground/tsconfig.json +0 -19
  151. package/src/scrapers/markitdown/MarkitdownScraper.test.ts.todo +0 -132
  152. package/src/scrapers/markitdown/playground/markitdown-scraper-playground.ts +0 -91
  153. package/src/scrapers/markitdown/playground/tsconfig.json +0 -19
  154. package/src/scrapers/pdf/PdfScraper.test.ts.todo +0 -52
  155. package/src/scrapers/pdf/playground/pdf-scraper-playground.ts +0 -75
  156. package/src/scrapers/pdf/playground/tsconfig.json +0 -19
  157. package/src/scrapers/website/playground/tsconfig.json +0 -19
  158. package/src/scrapers/website/playground/website-scraper-playground.ts +0 -82
  159. package/src/storage/_common/PromptbookStorage.test-type.ts +0 -14
  160. package/src/storage/local-storage/getIndexedDbStorage.ts +0 -36
  161. package/src/storage/local-storage/getLocalStorage.ts +0 -33
  162. package/src/storage/local-storage/getSessionStorage.ts +0 -33
  163. package/src/storage/local-storage/utils/IndexedDbStorageOptions.ts +0 -16
  164. package/src/storage/local-storage/utils/makePromptbookStorageFromIndexedDb.ts +0 -58
  165. package/src/storage/local-storage/utils/makePromptbookStorageFromWebStorage.ts +0 -45
  166. package/src/transpilers/formatted-book-in-markdown/FormattedBookInMarkdownTranspiler.test.ts.todo +0 -35
  167. package/src/transpilers/openai-sdk/playground/playground.ts +0 -85
  168. package/src/transpilers/openai-sdk/playground/tmp/chatbot-openaisdk-1.js +0 -194
  169. package/src/transpilers/openai-sdk/playground/tmp/package.json +0 -3
  170. package/src/transpilers/openai-sdk/playground/tsconfig.json +0 -18
  171. package/src/utils/editable/utils/findUsableParameters.test.ts.todo +0 -43
  172. package/src/utils/editable/utils/stringifyPipelineJson.test.ts.todo +0 -38
  173. package/src/utils/markdown/prettifyMarkdown.test.ts.tmp +0 -42
  174. package/src/utils/serialization/serializeToPromptbookJavascript.test.ts.todo +0 -116
package/esm/index.es.js CHANGED
@@ -58,7 +58,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
58
58
  * @generated
59
59
  * @see https://github.com/webgptorg/promptbook
60
60
  */
61
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-104';
61
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-106';
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
@@ -1748,6 +1748,12 @@ const AGENT_QUEUED_MESSAGES_DIRECTORY_PATH = join(AGENT_MESSAGES_DIRECTORY_PATH,
1748
1748
  * @private internal utility of `ptbk agent-folder`
1749
1749
  */
1750
1750
  const AGENT_FINISHED_MESSAGES_DIRECTORY_PATH = join(AGENT_MESSAGES_DIRECTORY_PATH, 'finished');
1751
+ /**
1752
+ * Relative path to messages that the agent runner stopped retrying.
1753
+ *
1754
+ * @private internal utility of `ptbk agent-folder`
1755
+ */
1756
+ const AGENT_FAILED_MESSAGES_DIRECTORY_PATH = join(AGENT_MESSAGES_DIRECTORY_PATH, 'failed');
1751
1757
  /**
1752
1758
  * Relative path to generated local agent documentation initialized by `ptbk agent-folder init`.
1753
1759
  *
@@ -3158,12 +3164,38 @@ const AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES = new Set([
3158
3164
  'playwright-report',
3159
3165
  'test-results',
3160
3166
  ]);
3167
+ /**
3168
+ * Runtime source files excluded from the packaged Agents Server copy.
3169
+ *
3170
+ * @private internal constant of `ptbk agents-server`
3171
+ */
3172
+ const AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATHS = new Set([
3173
+ 'src/_packages/browser.index.ts',
3174
+ 'src/_packages/browser.readme.md',
3175
+ 'src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.ts',
3176
+ 'src/llm-providers/_common/utils/assertUniqueModels.ts',
3177
+ ]);
3178
+ /**
3179
+ * Runtime source folders excluded from the packaged Agents Server copy.
3180
+ *
3181
+ * @private internal constant of `ptbk agents-server`
3182
+ */
3183
+ const AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATH_PREFIXES = [
3184
+ 'src/dialogs/simple-prompt',
3185
+ 'src/storage/local-storage',
3186
+ ];
3161
3187
  /**
3162
3188
  * Test files copied out of packaged runtime input paths because Next does not build them.
3163
3189
  *
3164
3190
  * @private internal constant of `ptbk agents-server`
3165
3191
  */
3166
- const AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN = /\.(?:spec|test)\.[jt]sx?$/iu;
3192
+ const AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN = /\.(?:spec|test)(?:\.|$)/iu;
3193
+ /**
3194
+ * Type-only compile check files copied out of packaged runtime input paths.
3195
+ *
3196
+ * @private internal constant of `ptbk agents-server`
3197
+ */
3198
+ const AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN = /\.test-type\.[jt]sx?$/iu;
3167
3199
  /**
3168
3200
  * Ensures that the local Agents Server production build exists and matches its source fingerprint.
3169
3201
  *
@@ -3358,15 +3390,48 @@ async function copyAgentsServerRuntimePath(options) {
3358
3390
  */
3359
3391
  function shouldCopyAgentsServerRuntimePath(sourcePath, sourceRootPath) {
3360
3392
  const sourceRelativePath = relative(sourceRootPath, sourcePath).replace(/\\/gu, '/');
3393
+ const sourceRuntimeRelativePath = normalizeRuntimeSourceRelativePath(sourcePath, sourceRootPath);
3361
3394
  const sourcePathSegments = sourceRelativePath.split('/').filter(Boolean);
3362
3395
  const sourceBasename = basename(sourcePath);
3363
3396
  if (sourcePathSegments.some((sourcePathSegment) => AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES.has(sourcePathSegment))) {
3364
3397
  return false;
3365
3398
  }
3399
+ if (sourcePathSegments.includes('playground')) {
3400
+ return false;
3401
+ }
3402
+ if (isExcludedAgentsServerRuntimeSourcePath(sourceRuntimeRelativePath)) {
3403
+ return false;
3404
+ }
3366
3405
  if (sourceBasename.startsWith('.env')) {
3367
3406
  return false;
3368
3407
  }
3369
- return !AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(sourceBasename);
3408
+ return (!AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(sourceBasename) &&
3409
+ !AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN.test(sourceBasename));
3410
+ }
3411
+ /**
3412
+ * Normalizes a copied runtime path to the shape used inside the packaged runtime root.
3413
+ */
3414
+ function normalizeRuntimeSourceRelativePath(sourcePath, sourceRootPath) {
3415
+ const sourceRelativePath = relative(sourceRootPath, sourcePath).replace(/\\/gu, '/');
3416
+ const sourceRootBasename = basename(sourceRootPath);
3417
+ if (!sourceRelativePath) {
3418
+ return sourceRootBasename;
3419
+ }
3420
+ return `${sourceRootBasename}/${sourceRelativePath}`;
3421
+ }
3422
+ /**
3423
+ * Checks whether one normalized runtime path is equal to or nested below another path.
3424
+ */
3425
+ function isRuntimePathWithin(sourceRuntimeRelativePath, excludedSourcePathPrefix) {
3426
+ return (sourceRuntimeRelativePath === excludedSourcePathPrefix ||
3427
+ sourceRuntimeRelativePath.startsWith(`${excludedSourcePathPrefix}/`));
3428
+ }
3429
+ /**
3430
+ * Returns true for runtime source files and folders that are not needed by the Agents Server build.
3431
+ */
3432
+ function isExcludedAgentsServerRuntimeSourcePath(sourceRuntimeRelativePath) {
3433
+ return (AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATHS.has(sourceRuntimeRelativePath) ||
3434
+ AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATH_PREFIXES.some((excludedSourcePathPrefix) => isRuntimePathWithin(sourceRuntimeRelativePath, excludedSourcePathPrefix)));
3370
3435
  }
3371
3436
  /**
3372
3437
  * Links the materialized runtime back to the package dependency tree used by the installed CLI.
@@ -3484,6 +3549,9 @@ async function createAgentsServerBuildSourceFingerprint(appPath) {
3484
3549
  * Adds one runtime source file or directory subtree to the production build fingerprint.
3485
3550
  */
3486
3551
  async function addAgentsServerBuildInputToFingerprint(fingerprint, options) {
3552
+ if (isExcludedAgentsServerBuildInputPath(options.inputPath, options.runtimeRootPath)) {
3553
+ return;
3554
+ }
3487
3555
  let inputStats;
3488
3556
  try {
3489
3557
  inputStats = await stat(options.inputPath);
@@ -3493,9 +3561,6 @@ async function addAgentsServerBuildInputToFingerprint(fingerprint, options) {
3493
3561
  return;
3494
3562
  }
3495
3563
  if (inputStats.isFile()) {
3496
- if (isExcludedAgentsServerBuildInputFile(options.inputPath)) {
3497
- return;
3498
- }
3499
3564
  fingerprint.update(`file:${normalizeBuildInputPath(options.runtimeRootPath, options.inputPath)}\n`);
3500
3565
  fingerprint.update(await readFile(options.inputPath));
3501
3566
  fingerprint.update('\n');
@@ -3518,10 +3583,23 @@ async function addAgentsServerBuildInputToFingerprint(fingerprint, options) {
3518
3583
  }
3519
3584
  }
3520
3585
  /**
3521
- * Returns true for non-build test files inside shared runtime source paths.
3586
+ * Returns true for non-build files and folders inside shared runtime source paths.
3522
3587
  */
3523
- function isExcludedAgentsServerBuildInputFile(inputPath) {
3524
- return AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(basename(inputPath));
3588
+ function isExcludedAgentsServerBuildInputPath(inputPath, runtimeRootPath) {
3589
+ const inputRelativePath = normalizeBuildInputPath(runtimeRootPath, inputPath);
3590
+ const inputPathSegments = inputRelativePath.split('/').filter(Boolean);
3591
+ const inputBasename = basename(inputPath);
3592
+ if (inputPathSegments.some((inputPathSegment) => AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES.has(inputPathSegment))) {
3593
+ return true;
3594
+ }
3595
+ if (inputPathSegments.includes('playground')) {
3596
+ return true;
3597
+ }
3598
+ if (isExcludedAgentsServerRuntimeSourcePath(inputRelativePath)) {
3599
+ return true;
3600
+ }
3601
+ return (AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(inputBasename) ||
3602
+ AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN.test(inputBasename));
3525
3603
  }
3526
3604
  /**
3527
3605
  * Normalizes one absolute runtime path so cache fingerprints are stable across platforms.
@@ -4942,7 +5020,7 @@ async function listQueuedAgentMessages(projectPath) {
4942
5020
  .filter((entry) => entry.isFile() && isBookFileName(entry.name))
4943
5021
  .map((entry) => ({
4944
5022
  absolutePath: join(queuedMessagesDirectoryPath, entry.name),
4945
- relativePath: normalizeRelativePath$1(join(AGENT_QUEUED_MESSAGES_DIRECTORY_PATH, entry.name)),
5023
+ relativePath: normalizeRelativePath$2(join(AGENT_QUEUED_MESSAGES_DIRECTORY_PATH, entry.name)),
4946
5024
  fileName: entry.name,
4947
5025
  }))
4948
5026
  .sort((firstMessage, secondMessage) => firstMessage.fileName.localeCompare(secondMessage.fileName));
@@ -4970,7 +5048,7 @@ function isBookFileName(fileName) {
4970
5048
  /**
4971
5049
  * Normalizes a relative path for Markdown links and Git path matching.
4972
5050
  */
4973
- function normalizeRelativePath$1(relativePath) {
5051
+ function normalizeRelativePath$2(relativePath) {
4974
5052
  return relativePath.replace(/\\/gu, '/');
4975
5053
  }
4976
5054
  /**
@@ -13348,10 +13426,7 @@ function sampleContinuousOctopusSurfacePoint(options, latitude, longitude) {
13348
13426
  Math.max(0, Math.cos(effectiveLongitude)) * 0.1 +
13349
13427
  lowerBlend * tentacleInfluence.core * (0.1 + tentacleInfluence.depthScale * 0.06) -
13350
13428
  Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
13351
- const tentacleTubeRadius = lowerBlend *
13352
- tentacleInfluence.core *
13353
- (0.11 + tipBlend * 0.06 + tentacleInfluence.widthScale * 0.025) *
13354
- radiusX;
13429
+ const tentacleTubeRadius = lowerBlend * tentacleInfluence.core * (0.11 + tipBlend * 0.06 + tentacleInfluence.widthScale * 0.025) * radiusX;
13355
13430
  const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
13356
13431
  const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.72;
13357
13432
  const lowerDrop = lowerBlend *
@@ -13362,8 +13437,7 @@ function sampleContinuousOctopusSurfacePoint(options, latitude, longitude) {
13362
13437
  tentacleInfluence.lengthScale * 0.22 +
13363
13438
  (morphologyProfile.tentacles.flowLengthScale - 1) * 0.08));
13364
13439
  return {
13365
- x: Math.sin(effectiveLongitude) * planarRadiusX +
13366
- tentacleWave * radiusX * (0.052 + tipBlend * 0.05),
13440
+ x: Math.sin(effectiveLongitude) * planarRadiusX + tentacleWave * radiusX * (0.052 + tipBlend * 0.05),
13367
13441
  y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.12) -
13368
13442
  upperBlend * radiusY * 0.1 +
13369
13443
  lowerDrop +
@@ -13437,8 +13511,11 @@ function resolveContinuousTentacleInfluence(options, longitude) {
13437
13511
  */
13438
13512
  function resolveContinuousLobeWave(options, longitude) {
13439
13513
  const { morphologyProfile, animationPhase, timeMs } = options;
13440
- return (Math.cos(longitude * OCTOPUS_TENTACLE_COUNT + animationPhase + timeMs / (980 + morphologyProfile.body.lobeCount * 18)) +
13441
- 1) / 2;
13514
+ return ((Math.cos(longitude * OCTOPUS_TENTACLE_COUNT +
13515
+ animationPhase +
13516
+ timeMs / (980 + morphologyProfile.body.lobeCount * 18)) +
13517
+ 1) /
13518
+ 2);
13442
13519
  }
13443
13520
  /**
13444
13521
  * Resolves one base fill tone for a patch on the continuous octopus mesh.
@@ -13502,8 +13579,7 @@ function drawProjectedSurfaceCurrents(options) {
13502
13579
  for (let sampleIndex = 0; sampleIndex < 8; sampleIndex++) {
13503
13580
  const progress = sampleIndex / 7;
13504
13581
  const latitude = -0.46 + progress * 0.74;
13505
- const longitude = baseLongitude +
13506
- Math.sin(timeMs / 1160 + animationPhase + currentIndex * 0.7 + progress * 2) * 0.035;
13582
+ const longitude = baseLongitude + Math.sin(timeMs / 1160 + animationPhase + currentIndex * 0.7 + progress * 2) * 0.035;
13507
13583
  const scenePoint = transformScenePoint(sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude, longitude), center, rotationX, rotationY);
13508
13584
  if (scenePoint.z > center.z - size * 0.016) {
13509
13585
  projectedPoints.push(projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
@@ -35078,7 +35154,7 @@ function buildAgentMessageScriptPath(projectPath, messageFile) {
35078
35154
  async function moveAgentMessageToFinished(projectPath, messageFile) {
35079
35155
  const finishedDirectoryPath = join(projectPath, AGENT_FINISHED_MESSAGES_DIRECTORY_PATH);
35080
35156
  const finishedMessagePath = join(finishedDirectoryPath, messageFile.fileName);
35081
- const finishedMessageRelativePath = normalizeRelativePath(join(AGENT_FINISHED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
35157
+ const finishedMessageRelativePath = normalizeRelativePath$1(join(AGENT_FINISHED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
35082
35158
  await mkdir(finishedDirectoryPath, { recursive: true });
35083
35159
  if (await isExistingPath(finishedMessagePath)) {
35084
35160
  await rm(finishedMessagePath, { force: true });
@@ -35108,7 +35184,7 @@ async function isExistingPath(path) {
35108
35184
  /**
35109
35185
  * Normalizes a relative path for Git and display.
35110
35186
  */
35111
- function normalizeRelativePath(relativePath) {
35187
+ function normalizeRelativePath$1(relativePath) {
35112
35188
  return relativePath.replace(/\\/gu, '/');
35113
35189
  }
35114
35190
  /**
@@ -36127,6 +36203,177 @@ function validateAgentWatchOptions(commandDisplayName, options) {
36127
36203
  `));
36128
36204
  }
36129
36205
 
36206
+ /**
36207
+ * Moves one repeatedly failing queued message to `messages/failed` with a visible agent failure reply.
36208
+ */
36209
+ async function moveAgentMessageToFailed(options) {
36210
+ const { projectPath, messageFile, failureReason } = options;
36211
+ const failedDirectoryPath = join(projectPath, AGENT_FAILED_MESSAGES_DIRECTORY_PATH);
36212
+ const failedMessagePath = join(failedDirectoryPath, messageFile.fileName);
36213
+ const failedMessageRelativePath = normalizeRelativePath(join(AGENT_FAILED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
36214
+ const queuedMessageContent = await readFile(messageFile.absolutePath, 'utf-8');
36215
+ await mkdir(failedDirectoryPath, { recursive: true });
36216
+ await rm(failedMessagePath, { force: true });
36217
+ await rename(messageFile.absolutePath, failedMessagePath);
36218
+ await writeFile(failedMessagePath, appendFailureReply(queuedMessageContent, failureReason), 'utf-8');
36219
+ return {
36220
+ absolutePath: failedMessagePath,
36221
+ relativePath: failedMessageRelativePath,
36222
+ fileName: messageFile.fileName,
36223
+ };
36224
+ }
36225
+ /**
36226
+ * Appends a synthetic `@Agent` reply so the Agents Server can display the terminal failure reason.
36227
+ */
36228
+ function appendFailureReply(bookContent, failureReason) {
36229
+ const normalizedBookContent = bookContent.trimEnd();
36230
+ const normalizedFailureReason = failureReason.trim();
36231
+ return `${normalizedBookContent}\n\nMESSAGE @Agent\n${normalizedFailureReason}\n`;
36232
+ }
36233
+ /**
36234
+ * Normalizes a relative path for Git and display.
36235
+ */
36236
+ function normalizeRelativePath(relativePath) {
36237
+ return relativePath.replace(/\\/gu, '/');
36238
+ }
36239
+
36240
+ /**
36241
+ * Default number of failed queued-message attempts allowed before the watcher stops retrying that message.
36242
+ */
36243
+ const DEFAULT_MAX_MESSAGE_PROCESSING_FAILURES = 3;
36244
+ /**
36245
+ * Maximum number of characters copied from the final runner error into the failed chat message.
36246
+ */
36247
+ const MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH = 4000;
36248
+ /**
36249
+ * Tracks repeated watch-level failures for queued message files and stops retrying them after a configured cap.
36250
+ */
36251
+ class AgentMessageFailureTracker {
36252
+ constructor(options = {}) {
36253
+ this.failuresByMessageKey = new Map();
36254
+ this.maxMessageProcessingFailures = normalizeMaxMessageProcessingFailures(options.maxMessageProcessingFailures);
36255
+ }
36256
+ /**
36257
+ * Clears the failure counter after a queued message is processed successfully.
36258
+ */
36259
+ clearMessageFailure(projectPath, messageFile) {
36260
+ if (!messageFile) {
36261
+ return;
36262
+ }
36263
+ this.failuresByMessageKey.delete(createAgentMessageFailureKey(projectPath, messageFile.relativePath));
36264
+ }
36265
+ /**
36266
+ * Records one queued-message failure and moves the message into `messages/failed` when the retry cap is reached.
36267
+ */
36268
+ async recordFailure(error) {
36269
+ var _a, _b;
36270
+ const errorContext = getAgentWatchErrorContext(error);
36271
+ if (!(errorContext === null || errorContext === void 0 ? void 0 : errorContext.projectPath) || !errorContext.queuedMessageRelativePath) {
36272
+ return null;
36273
+ }
36274
+ const messageKey = createAgentMessageFailureKey(errorContext.projectPath, errorContext.queuedMessageRelativePath);
36275
+ const previousFailureCount = (_b = (_a = this.failuresByMessageKey.get(messageKey)) === null || _a === void 0 ? void 0 : _a.failureCount) !== null && _b !== void 0 ? _b : 0;
36276
+ const failureCount = previousFailureCount + 1;
36277
+ if (failureCount < this.maxMessageProcessingFailures) {
36278
+ this.failuresByMessageKey.set(messageKey, { failureCount });
36279
+ return {
36280
+ failureCount,
36281
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36282
+ isMessageMovedToFailed: false,
36283
+ };
36284
+ }
36285
+ try {
36286
+ await moveAgentMessageToFailed({
36287
+ projectPath: errorContext.projectPath,
36288
+ messageFile: createAgentMessageFileFromContext(errorContext.projectPath, errorContext.queuedMessageRelativePath),
36289
+ failureReason: buildFailedQueuedMessageReason({
36290
+ error,
36291
+ failureCount,
36292
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36293
+ }),
36294
+ });
36295
+ this.failuresByMessageKey.delete(messageKey);
36296
+ console.error(colors.yellow(`Moved ${errorContext.queuedMessageRelativePath} to messages/failed after ${failureCount} failed attempt(s).`));
36297
+ }
36298
+ catch (moveError) {
36299
+ this.failuresByMessageKey.set(messageKey, { failureCount });
36300
+ console.error(colors.yellow(`Failed to move ${errorContext.queuedMessageRelativePath} to messages/failed: ${formatUnknownErrorDetails(moveError)}`));
36301
+ return {
36302
+ failureCount,
36303
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36304
+ isMessageMovedToFailed: false,
36305
+ };
36306
+ }
36307
+ return {
36308
+ failureCount,
36309
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36310
+ isMessageMovedToFailed: true,
36311
+ };
36312
+ }
36313
+ }
36314
+ /**
36315
+ * Creates the stable in-memory key for one queued message.
36316
+ */
36317
+ function createAgentMessageFailureKey(projectPath, queuedMessageRelativePath) {
36318
+ return `${projectPath}\0${queuedMessageRelativePath}`;
36319
+ }
36320
+ /**
36321
+ * Recreates the selected queued message descriptor from watch-loop error context.
36322
+ */
36323
+ function createAgentMessageFileFromContext(projectPath, queuedMessageRelativePath) {
36324
+ return {
36325
+ absolutePath: join(projectPath, queuedMessageRelativePath),
36326
+ relativePath: queuedMessageRelativePath.replace(/\\/gu, '/'),
36327
+ fileName: getFileNameFromRelativePath(queuedMessageRelativePath),
36328
+ };
36329
+ }
36330
+ /**
36331
+ * Extracts the filename from a normalized or platform-specific relative path.
36332
+ */
36333
+ function getFileNameFromRelativePath(relativePath) {
36334
+ const pathParts = relativePath.replace(/\\/gu, '/').split('/');
36335
+ return pathParts[pathParts.length - 1] || 'message.book';
36336
+ }
36337
+ /**
36338
+ * Builds the message shown to the chat user when the local runner stops retrying.
36339
+ */
36340
+ function buildFailedQueuedMessageReason(options) {
36341
+ const errorDetails = limitFailureDetails(formatUnknownErrorDetails(options.error));
36342
+ return spaceTrim$1((block) => `
36343
+ Local agent runner failed after ${options.failureCount} attempt(s) and stopped retrying.
36344
+
36345
+ Fix the runner or API configuration before trying again. The maximum failed-attempt limit is currently ${options.maxMessageProcessingFailures}.
36346
+
36347
+ Last runner error:
36348
+ \`\`\`
36349
+ ${block(errorDetails)}
36350
+ \`\`\`
36351
+ `);
36352
+ }
36353
+ /**
36354
+ * Keeps the synthetic failed chat message bounded even when runner logs are long.
36355
+ */
36356
+ function limitFailureDetails(errorDetails) {
36357
+ const normalizedErrorDetails = errorDetails.trim();
36358
+ if (normalizedErrorDetails.length <= MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH) {
36359
+ return normalizedErrorDetails;
36360
+ }
36361
+ return spaceTrim$1(`
36362
+ [...runner error truncated to the last ${MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH} characters...]
36363
+ ${normalizedErrorDetails.slice(-MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH)}
36364
+ `);
36365
+ }
36366
+ /**
36367
+ * Normalizes the retry cap used by standalone CLI runs when no server-provided limit is available.
36368
+ */
36369
+ function normalizeMaxMessageProcessingFailures(rawValue) {
36370
+ const parsedValue = Number(rawValue);
36371
+ if (!Number.isFinite(parsedValue) || parsedValue <= 0) {
36372
+ return DEFAULT_MAX_MESSAGE_PROCESSING_FAILURES;
36373
+ }
36374
+ return Math.floor(parsedValue);
36375
+ }
36376
+
36130
36377
  /**
36131
36378
  * Delay between multi-agent watch iterations while all queues stay empty.
36132
36379
  */
@@ -36163,6 +36410,9 @@ async function runMultipleAgentMessages(options, controls = {}) {
36163
36410
  let lastObservedProjectCount = 0;
36164
36411
  let isWatchSessionInitialized = false;
36165
36412
  let uiHandle;
36413
+ const messageFailureTracker = new AgentMessageFailureTracker({
36414
+ maxMessageProcessingFailures: options.maxMessageProcessingFailures,
36415
+ });
36166
36416
  while (shouldContinue()) {
36167
36417
  try {
36168
36418
  if (!isWatchSessionInitialized) {
@@ -36211,7 +36461,7 @@ async function runMultipleAgentMessages(options, controls = {}) {
36211
36461
  const queuedProjects = projectSummaries.filter((projectSummary) => projectSummary.queuedMessageCount > 0);
36212
36462
  if (queuedProjects.length === 0) {
36213
36463
  updateMultipleAgentRunUiForWatching(uiHandle, options, rootPath, projectSummaries, ignoredAgentCount);
36214
- await wait$2(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36464
+ await wait$3(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36215
36465
  continue;
36216
36466
  }
36217
36467
  if (!uiHandle) {
@@ -36251,6 +36501,9 @@ async function runMultipleAgentMessages(options, controls = {}) {
36251
36501
  if (tickResult.value.tickResult.autoPullTimestamp !== undefined) {
36252
36502
  autoPullTimestampsByProjectPath.set(tickResult.value.projectPath, tickResult.value.tickResult.autoPullTimestamp);
36253
36503
  }
36504
+ if (tickResult.value.tickResult.isMessageProcessed) {
36505
+ messageFailureTracker.clearMessageFailure(tickResult.value.projectPath, tickResult.value.tickResult.queuedMessage);
36506
+ }
36254
36507
  continue;
36255
36508
  }
36256
36509
  await handleAgentWatchError({
@@ -36258,6 +36511,7 @@ async function runMultipleAgentMessages(options, controls = {}) {
36258
36511
  logDirectoryPath: controls.watchErrorLogDirectoryPath || rootPath,
36259
36512
  error: tickResult.reason,
36260
36513
  });
36514
+ await messageFailureTracker.recordFailure(tickResult.reason);
36261
36515
  }
36262
36516
  }
36263
36517
  catch (error) {
@@ -36266,7 +36520,8 @@ async function runMultipleAgentMessages(options, controls = {}) {
36266
36520
  logDirectoryPath: controls.watchErrorLogDirectoryPath || rootPath,
36267
36521
  error,
36268
36522
  });
36269
- await wait$2(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36523
+ await messageFailureTracker.recordFailure(error);
36524
+ await wait$3(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36270
36525
  }
36271
36526
  }
36272
36527
  }
@@ -36350,7 +36605,9 @@ async function pullLatestChangesForLocalAgentRunnerProjectsIfNeeded(options) {
36350
36605
  const autoPullTimestamp = await pullLatestChangesForAgentQueueIfEnabled({
36351
36606
  projectPath,
36352
36607
  runOptions,
36353
- logMessage: uiHandle ? undefined : `Pulling latest changes in ${formatProjectPath(rootPath, projectPath)}...`,
36608
+ logMessage: uiHandle
36609
+ ? undefined
36610
+ : `Pulling latest changes in ${formatProjectPath(rootPath, projectPath)}...`,
36354
36611
  });
36355
36612
  if (autoPullTimestamp !== undefined) {
36356
36613
  autoPullTimestampsByProjectPath.set(projectPath, autoPullTimestamp);
@@ -36564,9 +36821,7 @@ function buildMultiAgentUserMessageLines(projectSummaries, answeringProjectPaths
36564
36821
  const answeringMessageLines = projectSummaries
36565
36822
  .filter((projectSummary) => answeringProjectPaths.has(projectSummary.project.projectPath))
36566
36823
  .flatMap((projectSummary) => buildAnsweringAgentMessageLines(projectSummary));
36567
- return answeringMessageLines.length > 0
36568
- ? answeringMessageLines
36569
- : [WAITING_FOR_MESSAGE_LABEL];
36824
+ return answeringMessageLines.length > 0 ? answeringMessageLines : [WAITING_FOR_MESSAGE_LABEL];
36570
36825
  }
36571
36826
  /**
36572
36827
  * Builds one dedicated message-preview panel per answering agent.
@@ -36657,7 +36912,7 @@ function formatProjectPath(rootPath, projectPath) {
36657
36912
  /**
36658
36913
  * Waits for the next idle poll interval in multi-agent watch mode.
36659
36914
  */
36660
- async function wait$2(delayMs) {
36915
+ async function wait$3(delayMs) {
36661
36916
  await new Promise((resolve) => setTimeout(resolve, delayMs));
36662
36917
  }
36663
36918
 
@@ -36680,6 +36935,218 @@ async function withCurrentWorkingDirectory(directoryPath, callback) {
36680
36935
  }
36681
36936
  }
36682
36937
 
36938
+ /**
36939
+ * Metadata key storing the delay between retry attempts when importing federated agent books.
36940
+ *
36941
+ * @private internal Agents Server constant
36942
+ */
36943
+ const FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY = 'FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS';
36944
+ /**
36945
+ * Total number of attempts used when loading a federated imported agent before falling back.
36946
+ *
36947
+ * @private internal Agents Server constant
36948
+ */
36949
+ const FEDERATED_AGENT_IMPORT_MAX_ATTEMPTS = 3;
36950
+ /**
36951
+ * Default delay in milliseconds between federated imported-agent retry attempts.
36952
+ *
36953
+ * @private internal Agents Server constant
36954
+ */
36955
+ const DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS = 500;
36956
+ /**
36957
+ * Default retry configuration for federated imported-agent loading.
36958
+ *
36959
+ * @private internal Agents Server constant
36960
+ */
36961
+ Object.freeze({
36962
+ maxAttempts: FEDERATED_AGENT_IMPORT_MAX_ATTEMPTS,
36963
+ retryDelayMs: DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
36964
+ });
36965
+
36966
+ /**
36967
+ * Metadata key used to persist tool-usage limits.
36968
+ *
36969
+ * @private shared constant for Agents Server
36970
+ */
36971
+ const TOOL_USAGE_LIMITS_METADATA_KEY = 'TOOL_USAGE_LIMITS';
36972
+ /**
36973
+ * Default timeout limits applied when administrators do not override them.
36974
+ *
36975
+ * @private shared constant for Agents Server
36976
+ */
36977
+ const DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS = {
36978
+ maxActivePerChat: 5,
36979
+ maxFiredPerDayPerChat: 10,
36980
+ };
36981
+
36982
+ /**
36983
+ * Legacy metadata key storing the maximum accepted file upload size in megabytes.
36984
+ *
36985
+ * @private shared Agents Server constant
36986
+ */
36987
+ const MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY = 'MAX_FILE_UPLOAD_SIZE_MB';
36988
+ /**
36989
+ * Default maximum accepted spawn depth in one tool-runtime context.
36990
+ *
36991
+ * @private shared Agents Server constant
36992
+ */
36993
+ const DEFAULT_SPAWN_AGENT_MAX_DEPTH = 2;
36994
+ /**
36995
+ * Default maximum number of spawned agents allowed per actor in one time window.
36996
+ *
36997
+ * @private shared Agents Server constant
36998
+ */
36999
+ const DEFAULT_SPAWN_AGENT_RATE_LIMIT_MAX = 5;
37000
+ /**
37001
+ * Default spawn rate-limit window size in milliseconds.
37002
+ *
37003
+ * @private shared Agents Server constant
37004
+ */
37005
+ const DEFAULT_SPAWN_AGENT_RATE_LIMIT_WINDOW_MS = 10 * 60 * 1000;
37006
+ /**
37007
+ * Default maximum number of failed local runner attempts before a queued message is moved to `messages/failed`.
37008
+ *
37009
+ * @private shared Agents Server constant
37010
+ */
37011
+ const DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS = 3;
37012
+ /**
37013
+ * Stable keys used by the dedicated server-limits table.
37014
+ *
37015
+ * @private shared Agents Server constant
37016
+ */
37017
+ const SERVER_LIMIT_KEYS = {
37018
+ TIMEOUT_MAX_ACTIVE_PER_CHAT: 'TIMEOUT_MAX_ACTIVE_PER_CHAT',
37019
+ TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT: 'TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT',
37020
+ MAX_FILE_UPLOAD_SIZE_MB: MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY,
37021
+ FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS: FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY,
37022
+ SPAWN_AGENT_MAX_DEPTH: 'SPAWN_AGENT_MAX_DEPTH',
37023
+ SPAWN_AGENT_RATE_LIMIT_MAX: 'SPAWN_AGENT_RATE_LIMIT_MAX',
37024
+ SPAWN_AGENT_RATE_LIMIT_WINDOW_MS: 'SPAWN_AGENT_RATE_LIMIT_WINDOW_MS',
37025
+ LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS: 'LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS',
37026
+ };
37027
+ /**
37028
+ * Shared metadata for all server limits exposed in the admin UI and runtime loaders.
37029
+ *
37030
+ * @private shared Agents Server constant
37031
+ */
37032
+ const SERVER_LIMIT_DEFINITIONS = [
37033
+ {
37034
+ key: SERVER_LIMIT_KEYS.TIMEOUT_MAX_ACTIVE_PER_CHAT,
37035
+ category: 'Timeout tools',
37036
+ title: 'Max active timers per chat',
37037
+ description: 'Prevents one chat thread from scheduling too many timers at once.',
37038
+ unit: 'count',
37039
+ defaultValue: DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS.maxActivePerChat,
37040
+ minimumValue: 1,
37041
+ step: 1,
37042
+ legacyMetadataKeys: [TOOL_USAGE_LIMITS_METADATA_KEY],
37043
+ },
37044
+ {
37045
+ key: SERVER_LIMIT_KEYS.TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT,
37046
+ category: 'Timeout tools',
37047
+ title: 'Max timers fired per day per chat',
37048
+ description: 'Limits how many scheduled wake-ups can execute inside one chat within one UTC day.',
37049
+ unit: 'count',
37050
+ defaultValue: DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS.maxFiredPerDayPerChat,
37051
+ minimumValue: 1,
37052
+ step: 1,
37053
+ legacyMetadataKeys: [TOOL_USAGE_LIMITS_METADATA_KEY],
37054
+ },
37055
+ {
37056
+ key: SERVER_LIMIT_KEYS.MAX_FILE_UPLOAD_SIZE_MB,
37057
+ category: 'Files',
37058
+ title: 'Max file upload size',
37059
+ description: 'Caps the size of uploaded files accepted by chat uploads and Android share-target imports.',
37060
+ unit: 'MB',
37061
+ defaultValue: 50,
37062
+ minimumValue: 1,
37063
+ step: 1,
37064
+ legacyMetadataKeys: [MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY],
37065
+ },
37066
+ {
37067
+ key: SERVER_LIMIT_KEYS.FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
37068
+ category: 'Federation',
37069
+ title: 'Federated import retry delay',
37070
+ description: 'Wait time between retries when importing agent books from federated servers.',
37071
+ unit: 'ms',
37072
+ defaultValue: DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
37073
+ minimumValue: 0,
37074
+ step: 100,
37075
+ legacyMetadataKeys: [FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY],
37076
+ },
37077
+ {
37078
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_MAX_DEPTH,
37079
+ category: 'Agent spawning',
37080
+ title: 'Max spawn depth',
37081
+ description: 'Restricts how many nested `spawn_agent` hops can happen inside one tool runtime context.',
37082
+ unit: 'count',
37083
+ defaultValue: DEFAULT_SPAWN_AGENT_MAX_DEPTH,
37084
+ minimumValue: 1,
37085
+ step: 1,
37086
+ legacyMetadataKeys: [],
37087
+ },
37088
+ {
37089
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_RATE_LIMIT_MAX,
37090
+ category: 'Agent spawning',
37091
+ title: 'Max spawned agents per window',
37092
+ description: 'Limits how many persistent agents one actor can create through `spawn_agent` inside one rate-limit window.',
37093
+ unit: 'count',
37094
+ defaultValue: DEFAULT_SPAWN_AGENT_RATE_LIMIT_MAX,
37095
+ minimumValue: 1,
37096
+ step: 1,
37097
+ legacyMetadataKeys: [],
37098
+ },
37099
+ {
37100
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_RATE_LIMIT_WINDOW_MS,
37101
+ category: 'Agent spawning',
37102
+ title: 'Spawn rate-limit window',
37103
+ description: 'Time window used together with the spawn quota for `spawn_agent` abuse protection.',
37104
+ unit: 'ms',
37105
+ defaultValue: DEFAULT_SPAWN_AGENT_RATE_LIMIT_WINDOW_MS,
37106
+ minimumValue: 1000,
37107
+ step: 1000,
37108
+ legacyMetadataKeys: [],
37109
+ },
37110
+ {
37111
+ key: SERVER_LIMIT_KEYS.LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37112
+ category: 'Local agent runner',
37113
+ title: 'Max failed message attempts',
37114
+ description: 'Stops the local coding-agent watcher from retrying the same queued chat message forever.',
37115
+ unit: 'count',
37116
+ defaultValue: DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37117
+ minimumValue: 1,
37118
+ step: 1,
37119
+ legacyMetadataKeys: [],
37120
+ },
37121
+ ];
37122
+ /**
37123
+ * Fast lookup map used by server-limit validators and UI helpers.
37124
+ *
37125
+ * @private shared Agents Server constant
37126
+ */
37127
+ new Map(SERVER_LIMIT_DEFINITIONS.map((definition) => [definition.key, definition]));
37128
+ /**
37129
+ * Fully normalized default values keyed by dedicated server-limit ids.
37130
+ *
37131
+ * @private shared Agents Server constant
37132
+ */
37133
+ const defaultServerLimitValues = {};
37134
+ for (const definition of SERVER_LIMIT_DEFINITIONS) {
37135
+ defaultServerLimitValues[definition.key] = definition.defaultValue;
37136
+ }
37137
+ /**
37138
+ * Default values used whenever a server-limit row has not been persisted yet.
37139
+ *
37140
+ * @private shared Agents Server constant
37141
+ */
37142
+ Object.freeze(defaultServerLimitValues);
37143
+ /**
37144
+ * Deprecated metadata keys that now mirror dedicated server-limit rows for backward compatibility.
37145
+ *
37146
+ * @private shared Agents Server constant
37147
+ */
37148
+ Array.from(new Set(SERVER_LIMIT_DEFINITIONS.flatMap((definition) => definition.legacyMetadataKeys)));
37149
+
36683
37150
  /**
36684
37151
  * Local worker-pump delay while the Agents Server foreground process stays active.
36685
37152
  *
@@ -36698,6 +37165,18 @@ const USER_CHAT_JOB_WORKER_REPEATED_ERROR_LOG_INTERVAL = 10;
36698
37165
  * @private internal constant of `ptbk agents-server`
36699
37166
  */
36700
37167
  const USER_CHAT_JOB_WORKER_ERROR_BODY_MAX_LENGTH = 2000;
37168
+ /**
37169
+ * Delay between foreground CLI attempts to load internal Agents Server limits during startup.
37170
+ *
37171
+ * @private internal constant of `ptbk agents-server`
37172
+ */
37173
+ const INTERNAL_SERVER_LIMITS_RETRY_DELAY_MS = 1000;
37174
+ /**
37175
+ * Maximum time spent waiting for the internal limits route before startup fails.
37176
+ *
37177
+ * @private internal constant of `ptbk agents-server`
37178
+ */
37179
+ const INTERNAL_SERVER_LIMITS_STARTUP_TIMEOUT_MS = 60000;
36701
37180
  /**
36702
37181
  * HTTP status used by an idle internal worker tick with no job to process.
36703
37182
  *
@@ -36804,6 +37283,12 @@ async function startAgentsServer(options) {
36804
37283
  logStreams,
36805
37284
  state,
36806
37285
  });
37286
+ const localAgentRunnerLimits = await waitForLocalAgentRunnerLimits({
37287
+ port: options.port,
37288
+ environment: runtimeChildEnvironment,
37289
+ logStreams,
37290
+ state,
37291
+ });
36807
37292
  stopUserChatJobWorkerPump = startUserChatJobWorkerPump({
36808
37293
  port: options.port,
36809
37294
  environment: runtimeChildEnvironment,
@@ -36811,7 +37296,7 @@ async function startAgentsServer(options) {
36811
37296
  state,
36812
37297
  });
36813
37298
  await withCurrentWorkingDirectory(runtimePaths.agentRootPath, async () => {
36814
- await runMultipleAgentMessages(createLocalAgentRunOptions(options), {
37299
+ await runMultipleAgentMessages(createLocalAgentRunOptions(options, localAgentRunnerLimits), {
36815
37300
  shouldContinue: () => state.isContinuing,
36816
37301
  watchErrorLogDirectoryPath: runtimePaths.logDirectoryPath,
36817
37302
  onUiInitialized: (uiHandle) => {
@@ -36940,7 +37425,7 @@ function createAgentsServerChildEnvironment(port, agentRootPath) {
36940
37425
  /**
36941
37426
  * Creates local no-git agent runner options for folders managed by the Agents Server database.
36942
37427
  */
36943
- function createLocalAgentRunOptions(options) {
37428
+ function createLocalAgentRunOptions(options, localAgentRunnerLimits) {
36944
37429
  return {
36945
37430
  agentName: options.agentName,
36946
37431
  model: options.model,
@@ -36953,8 +37438,67 @@ function createLocalAgentRunOptions(options) {
36953
37438
  autoPush: false,
36954
37439
  autoPull: false,
36955
37440
  autoClone: false,
37441
+ maxMessageProcessingFailures: localAgentRunnerLimits.maxFailedAttempts,
36956
37442
  };
36957
37443
  }
37444
+ /**
37445
+ * Waits until the internal Next route can return current local runner limits.
37446
+ */
37447
+ async function waitForLocalAgentRunnerLimits(options) {
37448
+ const startedAt = Date.now();
37449
+ let lastError;
37450
+ while (options.state.isContinuing && Date.now() - startedAt < INTERNAL_SERVER_LIMITS_STARTUP_TIMEOUT_MS) {
37451
+ try {
37452
+ const limits = await fetchLocalAgentRunnerLimits(options);
37453
+ logRunnerEvent(options.logStreams.runner, `Local agent runner max failed attempts: ${limits.maxFailedAttempts}.`);
37454
+ return limits;
37455
+ }
37456
+ catch (error) {
37457
+ lastError = error;
37458
+ await wait$2(INTERNAL_SERVER_LIMITS_RETRY_DELAY_MS);
37459
+ }
37460
+ }
37461
+ if (!options.state.isContinuing) {
37462
+ return {
37463
+ maxFailedAttempts: DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37464
+ };
37465
+ }
37466
+ throw new NotAllowed(spaceTrim$1(`
37467
+ Failed to load local agent runner limits from the Agents Server.
37468
+
37469
+ ${lastError instanceof Error ? lastError.message : String(lastError)}
37470
+ `));
37471
+ }
37472
+ /**
37473
+ * Loads local runner limits through the token-protected internal Agents Server route.
37474
+ */
37475
+ async function fetchLocalAgentRunnerLimits(options) {
37476
+ const response = await fetch(`http://localhost:${options.port}/api/internal/agent-runner-limits`, {
37477
+ method: 'GET',
37478
+ cache: 'no-store',
37479
+ headers: {
37480
+ 'x-user-chat-worker-token': options.environment.PTBK_AGENTS_SERVER_USER_CHAT_WORKER_TOKEN,
37481
+ },
37482
+ });
37483
+ if (!response.ok) {
37484
+ const details = await readUserChatJobWorkerErrorDetails(response);
37485
+ throw new Error(createInternalRouteErrorMessage('agent runner limits', response, details));
37486
+ }
37487
+ const payload = (await response.json());
37488
+ return {
37489
+ maxFailedAttempts: normalizeLocalAgentRunnerMaxFailedAttempts(payload.maxFailedAttempts),
37490
+ };
37491
+ }
37492
+ /**
37493
+ * Normalizes the local runner retry cap returned by the internal server route.
37494
+ */
37495
+ function normalizeLocalAgentRunnerMaxFailedAttempts(rawValue) {
37496
+ const parsedValue = Number(rawValue);
37497
+ if (!Number.isFinite(parsedValue) || parsedValue <= 0) {
37498
+ return DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS;
37499
+ }
37500
+ return Math.floor(parsedValue);
37501
+ }
36958
37502
  /**
36959
37503
  * Starts periodic internal worker calls that queue and reconcile local message-folder jobs.
36960
37504
  */
@@ -37063,12 +37607,18 @@ function parseUserChatJobWorkerErrorMessage(body) {
37063
37607
  * Builds the foreground worker failure message from HTTP status and route details.
37064
37608
  */
37065
37609
  function createUserChatJobWorkerErrorMessage(response, details) {
37610
+ return createInternalRouteErrorMessage('user chat worker', response, details);
37611
+ }
37612
+ /**
37613
+ * Builds a foreground failure message for one internal Agents Server route.
37614
+ */
37615
+ function createInternalRouteErrorMessage(routeLabel, response, details) {
37066
37616
  const statusText = response.statusText ? ` ${response.statusText}` : '';
37067
37617
  const statusMessage = `${response.status}${statusText}`;
37068
37618
  if (!details) {
37069
- return `Internal user chat worker returned ${statusMessage}.`;
37619
+ return `Internal ${routeLabel} route returned ${statusMessage}.`;
37070
37620
  }
37071
- return `Internal user chat worker returned ${statusMessage}: ${details}`;
37621
+ return `Internal ${routeLabel} route returned ${statusMessage}: ${details}`;
37072
37622
  }
37073
37623
  /**
37074
37624
  * Keeps foreground worker diagnostics bounded when a route returns a large payload.
@@ -37138,6 +37688,12 @@ function stopChildProcess(commandProcess) {
37138
37688
  }
37139
37689
  commandProcess.kill();
37140
37690
  }
37691
+ /**
37692
+ * Waits for the given delay.
37693
+ */
37694
+ async function wait$2(delayMs) {
37695
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
37696
+ }
37141
37697
  // Note: [🟡] Code for CLI runtime [startAgentsServer](src/cli/cli-commands/agents-server/startAgentsServer.ts) should never be published outside of `@promptbook/cli`
37142
37698
 
37143
37699
  /**
@@ -61795,14 +62351,18 @@ const AGENT_IDLE_AUTO_PULL_INTERVAL_MS = 30000;
61795
62351
  * Watches the queued message directory and answers messages one by one.
61796
62352
  */
61797
62353
  async function runAgentMessages(options, controls = {}) {
61798
- var _a;
62354
+ var _a, _b;
61799
62355
  validateAgentRunOptions(options);
61800
62356
  validateAgentWatchOptions('ptbk agent-folder run-agent', options);
61801
62357
  const projectPath = process.cwd();
61802
62358
  let autoPullTimestamp = options.autoPull ? Date.now() : undefined;
61803
62359
  const shouldContinue = controls.shouldContinue || (() => just(true));
62360
+ const queuePollIntervalMs = (_a = controls.queuePollIntervalMs) !== null && _a !== void 0 ? _a : AGENT_QUEUE_POLL_INTERVAL_MS;
61804
62361
  let isWatchSessionInitialized = false;
61805
62362
  let uiHandle;
62363
+ const messageFailureTracker = new AgentMessageFailureTracker({
62364
+ maxMessageProcessingFailures: options.maxMessageProcessingFailures,
62365
+ });
61806
62366
  while (shouldContinue()) {
61807
62367
  try {
61808
62368
  if (!isWatchSessionInitialized) {
@@ -61814,8 +62374,9 @@ async function runAgentMessages(options, controls = {}) {
61814
62374
  }
61815
62375
  }
61816
62376
  const result = await tickAgentMessages(options, { isQuietWhenIdle: true, uiHandle });
61817
- autoPullTimestamp = (_a = result.autoPullTimestamp) !== null && _a !== void 0 ? _a : autoPullTimestamp;
62377
+ autoPullTimestamp = (_b = result.autoPullTimestamp) !== null && _b !== void 0 ? _b : autoPullTimestamp;
61818
62378
  if (result.isMessageProcessed) {
62379
+ messageFailureTracker.clearMessageFailure(projectPath, result.queuedMessage);
61819
62380
  continue;
61820
62381
  }
61821
62382
  autoPullTimestamp = await waitForQueuedAgentMessage({
@@ -61824,6 +62385,7 @@ async function runAgentMessages(options, controls = {}) {
61824
62385
  autoPullTimestamp,
61825
62386
  uiHandle,
61826
62387
  shouldContinue,
62388
+ queuePollIntervalMs,
61827
62389
  });
61828
62390
  }
61829
62391
  catch (error) {
@@ -61832,7 +62394,8 @@ async function runAgentMessages(options, controls = {}) {
61832
62394
  logDirectoryPath: projectPath,
61833
62395
  error,
61834
62396
  });
61835
- await wait(AGENT_QUEUE_POLL_INTERVAL_MS);
62397
+ await messageFailureTracker.recordFailure(error);
62398
+ await wait(queuePollIntervalMs);
61836
62399
  }
61837
62400
  }
61838
62401
  }
@@ -61840,14 +62403,14 @@ async function runAgentMessages(options, controls = {}) {
61840
62403
  * Polls until at least one queued `.book` message is available.
61841
62404
  */
61842
62405
  async function waitForQueuedAgentMessage(options) {
61843
- const { projectPath, options: runOptions, uiHandle, shouldContinue } = options;
62406
+ const { projectPath, options: runOptions, uiHandle, shouldContinue, queuePollIntervalMs } = options;
61844
62407
  let { autoPullTimestamp } = options;
61845
62408
  let queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
61846
62409
  if (uiHandle) {
61847
62410
  updateAgentRunUiForWatching(uiHandle, queueSnapshot);
61848
62411
  }
61849
62412
  while (shouldContinue()) {
61850
- await wait(AGENT_QUEUE_POLL_INTERVAL_MS);
62413
+ await wait(queuePollIntervalMs);
61851
62414
  queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
61852
62415
  if (queueSnapshot.queuedMessages.length > 0) {
61853
62416
  return autoPullTimestamp;