@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/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-104';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-106';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -1750,6 +1750,12 @@
1750
1750
  * @private internal utility of `ptbk agent-folder`
1751
1751
  */
1752
1752
  const AGENT_FINISHED_MESSAGES_DIRECTORY_PATH = path.join(AGENT_MESSAGES_DIRECTORY_PATH, 'finished');
1753
+ /**
1754
+ * Relative path to messages that the agent runner stopped retrying.
1755
+ *
1756
+ * @private internal utility of `ptbk agent-folder`
1757
+ */
1758
+ const AGENT_FAILED_MESSAGES_DIRECTORY_PATH = path.join(AGENT_MESSAGES_DIRECTORY_PATH, 'failed');
1753
1759
  /**
1754
1760
  * Relative path to generated local agent documentation initialized by `ptbk agent-folder init`.
1755
1761
  *
@@ -3160,12 +3166,38 @@
3160
3166
  'playwright-report',
3161
3167
  'test-results',
3162
3168
  ]);
3169
+ /**
3170
+ * Runtime source files excluded from the packaged Agents Server copy.
3171
+ *
3172
+ * @private internal constant of `ptbk agents-server`
3173
+ */
3174
+ const AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATHS = new Set([
3175
+ 'src/_packages/browser.index.ts',
3176
+ 'src/_packages/browser.readme.md',
3177
+ 'src/llm-providers/_common/register/$provideLlmToolsForTestingAndScriptsAndPlayground.ts',
3178
+ 'src/llm-providers/_common/utils/assertUniqueModels.ts',
3179
+ ]);
3180
+ /**
3181
+ * Runtime source folders excluded from the packaged Agents Server copy.
3182
+ *
3183
+ * @private internal constant of `ptbk agents-server`
3184
+ */
3185
+ const AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATH_PREFIXES = [
3186
+ 'src/dialogs/simple-prompt',
3187
+ 'src/storage/local-storage',
3188
+ ];
3163
3189
  /**
3164
3190
  * Test files copied out of packaged runtime input paths because Next does not build them.
3165
3191
  *
3166
3192
  * @private internal constant of `ptbk agents-server`
3167
3193
  */
3168
- const AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN = /\.(?:spec|test)\.[jt]sx?$/iu;
3194
+ const AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN = /\.(?:spec|test)(?:\.|$)/iu;
3195
+ /**
3196
+ * Type-only compile check files copied out of packaged runtime input paths.
3197
+ *
3198
+ * @private internal constant of `ptbk agents-server`
3199
+ */
3200
+ const AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN = /\.test-type\.[jt]sx?$/iu;
3169
3201
  /**
3170
3202
  * Ensures that the local Agents Server production build exists and matches its source fingerprint.
3171
3203
  *
@@ -3360,15 +3392,48 @@
3360
3392
  */
3361
3393
  function shouldCopyAgentsServerRuntimePath(sourcePath, sourceRootPath) {
3362
3394
  const sourceRelativePath = path.relative(sourceRootPath, sourcePath).replace(/\\/gu, '/');
3395
+ const sourceRuntimeRelativePath = normalizeRuntimeSourceRelativePath(sourcePath, sourceRootPath);
3363
3396
  const sourcePathSegments = sourceRelativePath.split('/').filter(Boolean);
3364
3397
  const sourceBasename = path.basename(sourcePath);
3365
3398
  if (sourcePathSegments.some((sourcePathSegment) => AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES.has(sourcePathSegment))) {
3366
3399
  return false;
3367
3400
  }
3401
+ if (sourcePathSegments.includes('playground')) {
3402
+ return false;
3403
+ }
3404
+ if (isExcludedAgentsServerRuntimeSourcePath(sourceRuntimeRelativePath)) {
3405
+ return false;
3406
+ }
3368
3407
  if (sourceBasename.startsWith('.env')) {
3369
3408
  return false;
3370
3409
  }
3371
- return !AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(sourceBasename);
3410
+ return (!AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(sourceBasename) &&
3411
+ !AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN.test(sourceBasename));
3412
+ }
3413
+ /**
3414
+ * Normalizes a copied runtime path to the shape used inside the packaged runtime root.
3415
+ */
3416
+ function normalizeRuntimeSourceRelativePath(sourcePath, sourceRootPath) {
3417
+ const sourceRelativePath = path.relative(sourceRootPath, sourcePath).replace(/\\/gu, '/');
3418
+ const sourceRootBasename = path.basename(sourceRootPath);
3419
+ if (!sourceRelativePath) {
3420
+ return sourceRootBasename;
3421
+ }
3422
+ return `${sourceRootBasename}/${sourceRelativePath}`;
3423
+ }
3424
+ /**
3425
+ * Checks whether one normalized runtime path is equal to or nested below another path.
3426
+ */
3427
+ function isRuntimePathWithin(sourceRuntimeRelativePath, excludedSourcePathPrefix) {
3428
+ return (sourceRuntimeRelativePath === excludedSourcePathPrefix ||
3429
+ sourceRuntimeRelativePath.startsWith(`${excludedSourcePathPrefix}/`));
3430
+ }
3431
+ /**
3432
+ * Returns true for runtime source files and folders that are not needed by the Agents Server build.
3433
+ */
3434
+ function isExcludedAgentsServerRuntimeSourcePath(sourceRuntimeRelativePath) {
3435
+ return (AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATHS.has(sourceRuntimeRelativePath) ||
3436
+ AGENTS_SERVER_BUILD_INPUT_EXCLUDED_SOURCE_PATH_PREFIXES.some((excludedSourcePathPrefix) => isRuntimePathWithin(sourceRuntimeRelativePath, excludedSourcePathPrefix)));
3372
3437
  }
3373
3438
  /**
3374
3439
  * Links the materialized runtime back to the package dependency tree used by the installed CLI.
@@ -3486,6 +3551,9 @@
3486
3551
  * Adds one runtime source file or directory subtree to the production build fingerprint.
3487
3552
  */
3488
3553
  async function addAgentsServerBuildInputToFingerprint(fingerprint, options) {
3554
+ if (isExcludedAgentsServerBuildInputPath(options.inputPath, options.runtimeRootPath)) {
3555
+ return;
3556
+ }
3489
3557
  let inputStats;
3490
3558
  try {
3491
3559
  inputStats = await promises.stat(options.inputPath);
@@ -3495,9 +3563,6 @@
3495
3563
  return;
3496
3564
  }
3497
3565
  if (inputStats.isFile()) {
3498
- if (isExcludedAgentsServerBuildInputFile(options.inputPath)) {
3499
- return;
3500
- }
3501
3566
  fingerprint.update(`file:${normalizeBuildInputPath(options.runtimeRootPath, options.inputPath)}\n`);
3502
3567
  fingerprint.update(await promises.readFile(options.inputPath));
3503
3568
  fingerprint.update('\n');
@@ -3520,10 +3585,23 @@
3520
3585
  }
3521
3586
  }
3522
3587
  /**
3523
- * Returns true for non-build test files inside shared runtime source paths.
3588
+ * Returns true for non-build files and folders inside shared runtime source paths.
3524
3589
  */
3525
- function isExcludedAgentsServerBuildInputFile(inputPath) {
3526
- return AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(path.basename(inputPath));
3590
+ function isExcludedAgentsServerBuildInputPath(inputPath, runtimeRootPath) {
3591
+ const inputRelativePath = normalizeBuildInputPath(runtimeRootPath, inputPath);
3592
+ const inputPathSegments = inputRelativePath.split('/').filter(Boolean);
3593
+ const inputBasename = path.basename(inputPath);
3594
+ if (inputPathSegments.some((inputPathSegment) => AGENTS_SERVER_BUILD_INPUT_EXCLUDED_DIRECTORY_NAMES.has(inputPathSegment))) {
3595
+ return true;
3596
+ }
3597
+ if (inputPathSegments.includes('playground')) {
3598
+ return true;
3599
+ }
3600
+ if (isExcludedAgentsServerRuntimeSourcePath(inputRelativePath)) {
3601
+ return true;
3602
+ }
3603
+ return (AGENTS_SERVER_BUILD_INPUT_TEST_FILE_PATTERN.test(inputBasename) ||
3604
+ AGENTS_SERVER_BUILD_INPUT_TEST_TYPE_FILE_PATTERN.test(inputBasename));
3527
3605
  }
3528
3606
  /**
3529
3607
  * Normalizes one absolute runtime path so cache fingerprints are stable across platforms.
@@ -4944,7 +5022,7 @@
4944
5022
  .filter((entry) => entry.isFile() && isBookFileName(entry.name))
4945
5023
  .map((entry) => ({
4946
5024
  absolutePath: path.join(queuedMessagesDirectoryPath, entry.name),
4947
- relativePath: normalizeRelativePath$1(path.join(AGENT_QUEUED_MESSAGES_DIRECTORY_PATH, entry.name)),
5025
+ relativePath: normalizeRelativePath$2(path.join(AGENT_QUEUED_MESSAGES_DIRECTORY_PATH, entry.name)),
4948
5026
  fileName: entry.name,
4949
5027
  }))
4950
5028
  .sort((firstMessage, secondMessage) => firstMessage.fileName.localeCompare(secondMessage.fileName));
@@ -4972,7 +5050,7 @@
4972
5050
  /**
4973
5051
  * Normalizes a relative path for Markdown links and Git path matching.
4974
5052
  */
4975
- function normalizeRelativePath$1(relativePath) {
5053
+ function normalizeRelativePath$2(relativePath) {
4976
5054
  return relativePath.replace(/\\/gu, '/');
4977
5055
  }
4978
5056
  /**
@@ -13350,10 +13428,7 @@
13350
13428
  Math.max(0, Math.cos(effectiveLongitude)) * 0.1 +
13351
13429
  lowerBlend * tentacleInfluence.core * (0.1 + tentacleInfluence.depthScale * 0.06) -
13352
13430
  Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
13353
- const tentacleTubeRadius = lowerBlend *
13354
- tentacleInfluence.core *
13355
- (0.11 + tipBlend * 0.06 + tentacleInfluence.widthScale * 0.025) *
13356
- radiusX;
13431
+ const tentacleTubeRadius = lowerBlend * tentacleInfluence.core * (0.11 + tipBlend * 0.06 + tentacleInfluence.widthScale * 0.025) * radiusX;
13357
13432
  const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
13358
13433
  const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.72;
13359
13434
  const lowerDrop = lowerBlend *
@@ -13364,8 +13439,7 @@
13364
13439
  tentacleInfluence.lengthScale * 0.22 +
13365
13440
  (morphologyProfile.tentacles.flowLengthScale - 1) * 0.08));
13366
13441
  return {
13367
- x: Math.sin(effectiveLongitude) * planarRadiusX +
13368
- tentacleWave * radiusX * (0.052 + tipBlend * 0.05),
13442
+ x: Math.sin(effectiveLongitude) * planarRadiusX + tentacleWave * radiusX * (0.052 + tipBlend * 0.05),
13369
13443
  y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.12) -
13370
13444
  upperBlend * radiusY * 0.1 +
13371
13445
  lowerDrop +
@@ -13439,8 +13513,11 @@
13439
13513
  */
13440
13514
  function resolveContinuousLobeWave(options, longitude) {
13441
13515
  const { morphologyProfile, animationPhase, timeMs } = options;
13442
- return (Math.cos(longitude * OCTOPUS_TENTACLE_COUNT + animationPhase + timeMs / (980 + morphologyProfile.body.lobeCount * 18)) +
13443
- 1) / 2;
13516
+ return ((Math.cos(longitude * OCTOPUS_TENTACLE_COUNT +
13517
+ animationPhase +
13518
+ timeMs / (980 + morphologyProfile.body.lobeCount * 18)) +
13519
+ 1) /
13520
+ 2);
13444
13521
  }
13445
13522
  /**
13446
13523
  * Resolves one base fill tone for a patch on the continuous octopus mesh.
@@ -13504,8 +13581,7 @@
13504
13581
  for (let sampleIndex = 0; sampleIndex < 8; sampleIndex++) {
13505
13582
  const progress = sampleIndex / 7;
13506
13583
  const latitude = -0.46 + progress * 0.74;
13507
- const longitude = baseLongitude +
13508
- Math.sin(timeMs / 1160 + animationPhase + currentIndex * 0.7 + progress * 2) * 0.035;
13584
+ const longitude = baseLongitude + Math.sin(timeMs / 1160 + animationPhase + currentIndex * 0.7 + progress * 2) * 0.035;
13509
13585
  const scenePoint = transformScenePoint(sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude, longitude), center, rotationX, rotationY);
13510
13586
  if (scenePoint.z > center.z - size * 0.016) {
13511
13587
  projectedPoints.push(projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
@@ -35080,7 +35156,7 @@
35080
35156
  async function moveAgentMessageToFinished(projectPath, messageFile) {
35081
35157
  const finishedDirectoryPath = path.join(projectPath, AGENT_FINISHED_MESSAGES_DIRECTORY_PATH);
35082
35158
  const finishedMessagePath = path.join(finishedDirectoryPath, messageFile.fileName);
35083
- const finishedMessageRelativePath = normalizeRelativePath(path.join(AGENT_FINISHED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
35159
+ const finishedMessageRelativePath = normalizeRelativePath$1(path.join(AGENT_FINISHED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
35084
35160
  await promises.mkdir(finishedDirectoryPath, { recursive: true });
35085
35161
  if (await isExistingPath(finishedMessagePath)) {
35086
35162
  await promises.rm(finishedMessagePath, { force: true });
@@ -35110,7 +35186,7 @@
35110
35186
  /**
35111
35187
  * Normalizes a relative path for Git and display.
35112
35188
  */
35113
- function normalizeRelativePath(relativePath) {
35189
+ function normalizeRelativePath$1(relativePath) {
35114
35190
  return relativePath.replace(/\\/gu, '/');
35115
35191
  }
35116
35192
  /**
@@ -36129,6 +36205,177 @@
36129
36205
  `));
36130
36206
  }
36131
36207
 
36208
+ /**
36209
+ * Moves one repeatedly failing queued message to `messages/failed` with a visible agent failure reply.
36210
+ */
36211
+ async function moveAgentMessageToFailed(options) {
36212
+ const { projectPath, messageFile, failureReason } = options;
36213
+ const failedDirectoryPath = path.join(projectPath, AGENT_FAILED_MESSAGES_DIRECTORY_PATH);
36214
+ const failedMessagePath = path.join(failedDirectoryPath, messageFile.fileName);
36215
+ const failedMessageRelativePath = normalizeRelativePath(path.join(AGENT_FAILED_MESSAGES_DIRECTORY_PATH, messageFile.fileName));
36216
+ const queuedMessageContent = await promises.readFile(messageFile.absolutePath, 'utf-8');
36217
+ await promises.mkdir(failedDirectoryPath, { recursive: true });
36218
+ await promises.rm(failedMessagePath, { force: true });
36219
+ await promises.rename(messageFile.absolutePath, failedMessagePath);
36220
+ await promises.writeFile(failedMessagePath, appendFailureReply(queuedMessageContent, failureReason), 'utf-8');
36221
+ return {
36222
+ absolutePath: failedMessagePath,
36223
+ relativePath: failedMessageRelativePath,
36224
+ fileName: messageFile.fileName,
36225
+ };
36226
+ }
36227
+ /**
36228
+ * Appends a synthetic `@Agent` reply so the Agents Server can display the terminal failure reason.
36229
+ */
36230
+ function appendFailureReply(bookContent, failureReason) {
36231
+ const normalizedBookContent = bookContent.trimEnd();
36232
+ const normalizedFailureReason = failureReason.trim();
36233
+ return `${normalizedBookContent}\n\nMESSAGE @Agent\n${normalizedFailureReason}\n`;
36234
+ }
36235
+ /**
36236
+ * Normalizes a relative path for Git and display.
36237
+ */
36238
+ function normalizeRelativePath(relativePath) {
36239
+ return relativePath.replace(/\\/gu, '/');
36240
+ }
36241
+
36242
+ /**
36243
+ * Default number of failed queued-message attempts allowed before the watcher stops retrying that message.
36244
+ */
36245
+ const DEFAULT_MAX_MESSAGE_PROCESSING_FAILURES = 3;
36246
+ /**
36247
+ * Maximum number of characters copied from the final runner error into the failed chat message.
36248
+ */
36249
+ const MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH = 4000;
36250
+ /**
36251
+ * Tracks repeated watch-level failures for queued message files and stops retrying them after a configured cap.
36252
+ */
36253
+ class AgentMessageFailureTracker {
36254
+ constructor(options = {}) {
36255
+ this.failuresByMessageKey = new Map();
36256
+ this.maxMessageProcessingFailures = normalizeMaxMessageProcessingFailures(options.maxMessageProcessingFailures);
36257
+ }
36258
+ /**
36259
+ * Clears the failure counter after a queued message is processed successfully.
36260
+ */
36261
+ clearMessageFailure(projectPath, messageFile) {
36262
+ if (!messageFile) {
36263
+ return;
36264
+ }
36265
+ this.failuresByMessageKey.delete(createAgentMessageFailureKey(projectPath, messageFile.relativePath));
36266
+ }
36267
+ /**
36268
+ * Records one queued-message failure and moves the message into `messages/failed` when the retry cap is reached.
36269
+ */
36270
+ async recordFailure(error) {
36271
+ var _a, _b;
36272
+ const errorContext = getAgentWatchErrorContext(error);
36273
+ if (!(errorContext === null || errorContext === void 0 ? void 0 : errorContext.projectPath) || !errorContext.queuedMessageRelativePath) {
36274
+ return null;
36275
+ }
36276
+ const messageKey = createAgentMessageFailureKey(errorContext.projectPath, errorContext.queuedMessageRelativePath);
36277
+ const previousFailureCount = (_b = (_a = this.failuresByMessageKey.get(messageKey)) === null || _a === void 0 ? void 0 : _a.failureCount) !== null && _b !== void 0 ? _b : 0;
36278
+ const failureCount = previousFailureCount + 1;
36279
+ if (failureCount < this.maxMessageProcessingFailures) {
36280
+ this.failuresByMessageKey.set(messageKey, { failureCount });
36281
+ return {
36282
+ failureCount,
36283
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36284
+ isMessageMovedToFailed: false,
36285
+ };
36286
+ }
36287
+ try {
36288
+ await moveAgentMessageToFailed({
36289
+ projectPath: errorContext.projectPath,
36290
+ messageFile: createAgentMessageFileFromContext(errorContext.projectPath, errorContext.queuedMessageRelativePath),
36291
+ failureReason: buildFailedQueuedMessageReason({
36292
+ error,
36293
+ failureCount,
36294
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36295
+ }),
36296
+ });
36297
+ this.failuresByMessageKey.delete(messageKey);
36298
+ console.error(colors__default["default"].yellow(`Moved ${errorContext.queuedMessageRelativePath} to messages/failed after ${failureCount} failed attempt(s).`));
36299
+ }
36300
+ catch (moveError) {
36301
+ this.failuresByMessageKey.set(messageKey, { failureCount });
36302
+ console.error(colors__default["default"].yellow(`Failed to move ${errorContext.queuedMessageRelativePath} to messages/failed: ${formatUnknownErrorDetails(moveError)}`));
36303
+ return {
36304
+ failureCount,
36305
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36306
+ isMessageMovedToFailed: false,
36307
+ };
36308
+ }
36309
+ return {
36310
+ failureCount,
36311
+ maxMessageProcessingFailures: this.maxMessageProcessingFailures,
36312
+ isMessageMovedToFailed: true,
36313
+ };
36314
+ }
36315
+ }
36316
+ /**
36317
+ * Creates the stable in-memory key for one queued message.
36318
+ */
36319
+ function createAgentMessageFailureKey(projectPath, queuedMessageRelativePath) {
36320
+ return `${projectPath}\0${queuedMessageRelativePath}`;
36321
+ }
36322
+ /**
36323
+ * Recreates the selected queued message descriptor from watch-loop error context.
36324
+ */
36325
+ function createAgentMessageFileFromContext(projectPath, queuedMessageRelativePath) {
36326
+ return {
36327
+ absolutePath: path.join(projectPath, queuedMessageRelativePath),
36328
+ relativePath: queuedMessageRelativePath.replace(/\\/gu, '/'),
36329
+ fileName: getFileNameFromRelativePath(queuedMessageRelativePath),
36330
+ };
36331
+ }
36332
+ /**
36333
+ * Extracts the filename from a normalized or platform-specific relative path.
36334
+ */
36335
+ function getFileNameFromRelativePath(relativePath) {
36336
+ const pathParts = relativePath.replace(/\\/gu, '/').split('/');
36337
+ return pathParts[pathParts.length - 1] || 'message.book';
36338
+ }
36339
+ /**
36340
+ * Builds the message shown to the chat user when the local runner stops retrying.
36341
+ */
36342
+ function buildFailedQueuedMessageReason(options) {
36343
+ const errorDetails = limitFailureDetails(formatUnknownErrorDetails(options.error));
36344
+ return _spaceTrim.spaceTrim((block) => `
36345
+ Local agent runner failed after ${options.failureCount} attempt(s) and stopped retrying.
36346
+
36347
+ Fix the runner or API configuration before trying again. The maximum failed-attempt limit is currently ${options.maxMessageProcessingFailures}.
36348
+
36349
+ Last runner error:
36350
+ \`\`\`
36351
+ ${block(errorDetails)}
36352
+ \`\`\`
36353
+ `);
36354
+ }
36355
+ /**
36356
+ * Keeps the synthetic failed chat message bounded even when runner logs are long.
36357
+ */
36358
+ function limitFailureDetails(errorDetails) {
36359
+ const normalizedErrorDetails = errorDetails.trim();
36360
+ if (normalizedErrorDetails.length <= MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH) {
36361
+ return normalizedErrorDetails;
36362
+ }
36363
+ return _spaceTrim.spaceTrim(`
36364
+ [...runner error truncated to the last ${MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH} characters...]
36365
+ ${normalizedErrorDetails.slice(-MAX_FAILED_MESSAGE_ERROR_DETAILS_LENGTH)}
36366
+ `);
36367
+ }
36368
+ /**
36369
+ * Normalizes the retry cap used by standalone CLI runs when no server-provided limit is available.
36370
+ */
36371
+ function normalizeMaxMessageProcessingFailures(rawValue) {
36372
+ const parsedValue = Number(rawValue);
36373
+ if (!Number.isFinite(parsedValue) || parsedValue <= 0) {
36374
+ return DEFAULT_MAX_MESSAGE_PROCESSING_FAILURES;
36375
+ }
36376
+ return Math.floor(parsedValue);
36377
+ }
36378
+
36132
36379
  /**
36133
36380
  * Delay between multi-agent watch iterations while all queues stay empty.
36134
36381
  */
@@ -36165,6 +36412,9 @@
36165
36412
  let lastObservedProjectCount = 0;
36166
36413
  let isWatchSessionInitialized = false;
36167
36414
  let uiHandle;
36415
+ const messageFailureTracker = new AgentMessageFailureTracker({
36416
+ maxMessageProcessingFailures: options.maxMessageProcessingFailures,
36417
+ });
36168
36418
  while (shouldContinue()) {
36169
36419
  try {
36170
36420
  if (!isWatchSessionInitialized) {
@@ -36213,7 +36463,7 @@
36213
36463
  const queuedProjects = projectSummaries.filter((projectSummary) => projectSummary.queuedMessageCount > 0);
36214
36464
  if (queuedProjects.length === 0) {
36215
36465
  updateMultipleAgentRunUiForWatching(uiHandle, options, rootPath, projectSummaries, ignoredAgentCount);
36216
- await wait$2(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36466
+ await wait$3(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36217
36467
  continue;
36218
36468
  }
36219
36469
  if (!uiHandle) {
@@ -36253,6 +36503,9 @@
36253
36503
  if (tickResult.value.tickResult.autoPullTimestamp !== undefined) {
36254
36504
  autoPullTimestampsByProjectPath.set(tickResult.value.projectPath, tickResult.value.tickResult.autoPullTimestamp);
36255
36505
  }
36506
+ if (tickResult.value.tickResult.isMessageProcessed) {
36507
+ messageFailureTracker.clearMessageFailure(tickResult.value.projectPath, tickResult.value.tickResult.queuedMessage);
36508
+ }
36256
36509
  continue;
36257
36510
  }
36258
36511
  await handleAgentWatchError({
@@ -36260,6 +36513,7 @@
36260
36513
  logDirectoryPath: controls.watchErrorLogDirectoryPath || rootPath,
36261
36514
  error: tickResult.reason,
36262
36515
  });
36516
+ await messageFailureTracker.recordFailure(tickResult.reason);
36263
36517
  }
36264
36518
  }
36265
36519
  catch (error) {
@@ -36268,7 +36522,8 @@
36268
36522
  logDirectoryPath: controls.watchErrorLogDirectoryPath || rootPath,
36269
36523
  error,
36270
36524
  });
36271
- await wait$2(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36525
+ await messageFailureTracker.recordFailure(error);
36526
+ await wait$3(MULTI_AGENT_QUEUE_POLL_INTERVAL_MS);
36272
36527
  }
36273
36528
  }
36274
36529
  }
@@ -36352,7 +36607,9 @@
36352
36607
  const autoPullTimestamp = await pullLatestChangesForAgentQueueIfEnabled({
36353
36608
  projectPath,
36354
36609
  runOptions,
36355
- logMessage: uiHandle ? undefined : `Pulling latest changes in ${formatProjectPath(rootPath, projectPath)}...`,
36610
+ logMessage: uiHandle
36611
+ ? undefined
36612
+ : `Pulling latest changes in ${formatProjectPath(rootPath, projectPath)}...`,
36356
36613
  });
36357
36614
  if (autoPullTimestamp !== undefined) {
36358
36615
  autoPullTimestampsByProjectPath.set(projectPath, autoPullTimestamp);
@@ -36566,9 +36823,7 @@
36566
36823
  const answeringMessageLines = projectSummaries
36567
36824
  .filter((projectSummary) => answeringProjectPaths.has(projectSummary.project.projectPath))
36568
36825
  .flatMap((projectSummary) => buildAnsweringAgentMessageLines(projectSummary));
36569
- return answeringMessageLines.length > 0
36570
- ? answeringMessageLines
36571
- : [WAITING_FOR_MESSAGE_LABEL];
36826
+ return answeringMessageLines.length > 0 ? answeringMessageLines : [WAITING_FOR_MESSAGE_LABEL];
36572
36827
  }
36573
36828
  /**
36574
36829
  * Builds one dedicated message-preview panel per answering agent.
@@ -36659,7 +36914,7 @@
36659
36914
  /**
36660
36915
  * Waits for the next idle poll interval in multi-agent watch mode.
36661
36916
  */
36662
- async function wait$2(delayMs) {
36917
+ async function wait$3(delayMs) {
36663
36918
  await new Promise((resolve) => setTimeout(resolve, delayMs));
36664
36919
  }
36665
36920
 
@@ -36682,6 +36937,218 @@
36682
36937
  }
36683
36938
  }
36684
36939
 
36940
+ /**
36941
+ * Metadata key storing the delay between retry attempts when importing federated agent books.
36942
+ *
36943
+ * @private internal Agents Server constant
36944
+ */
36945
+ const FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY = 'FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS';
36946
+ /**
36947
+ * Total number of attempts used when loading a federated imported agent before falling back.
36948
+ *
36949
+ * @private internal Agents Server constant
36950
+ */
36951
+ const FEDERATED_AGENT_IMPORT_MAX_ATTEMPTS = 3;
36952
+ /**
36953
+ * Default delay in milliseconds between federated imported-agent retry attempts.
36954
+ *
36955
+ * @private internal Agents Server constant
36956
+ */
36957
+ const DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS = 500;
36958
+ /**
36959
+ * Default retry configuration for federated imported-agent loading.
36960
+ *
36961
+ * @private internal Agents Server constant
36962
+ */
36963
+ Object.freeze({
36964
+ maxAttempts: FEDERATED_AGENT_IMPORT_MAX_ATTEMPTS,
36965
+ retryDelayMs: DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
36966
+ });
36967
+
36968
+ /**
36969
+ * Metadata key used to persist tool-usage limits.
36970
+ *
36971
+ * @private shared constant for Agents Server
36972
+ */
36973
+ const TOOL_USAGE_LIMITS_METADATA_KEY = 'TOOL_USAGE_LIMITS';
36974
+ /**
36975
+ * Default timeout limits applied when administrators do not override them.
36976
+ *
36977
+ * @private shared constant for Agents Server
36978
+ */
36979
+ const DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS = {
36980
+ maxActivePerChat: 5,
36981
+ maxFiredPerDayPerChat: 10,
36982
+ };
36983
+
36984
+ /**
36985
+ * Legacy metadata key storing the maximum accepted file upload size in megabytes.
36986
+ *
36987
+ * @private shared Agents Server constant
36988
+ */
36989
+ const MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY = 'MAX_FILE_UPLOAD_SIZE_MB';
36990
+ /**
36991
+ * Default maximum accepted spawn depth in one tool-runtime context.
36992
+ *
36993
+ * @private shared Agents Server constant
36994
+ */
36995
+ const DEFAULT_SPAWN_AGENT_MAX_DEPTH = 2;
36996
+ /**
36997
+ * Default maximum number of spawned agents allowed per actor in one time window.
36998
+ *
36999
+ * @private shared Agents Server constant
37000
+ */
37001
+ const DEFAULT_SPAWN_AGENT_RATE_LIMIT_MAX = 5;
37002
+ /**
37003
+ * Default spawn rate-limit window size in milliseconds.
37004
+ *
37005
+ * @private shared Agents Server constant
37006
+ */
37007
+ const DEFAULT_SPAWN_AGENT_RATE_LIMIT_WINDOW_MS = 10 * 60 * 1000;
37008
+ /**
37009
+ * Default maximum number of failed local runner attempts before a queued message is moved to `messages/failed`.
37010
+ *
37011
+ * @private shared Agents Server constant
37012
+ */
37013
+ const DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS = 3;
37014
+ /**
37015
+ * Stable keys used by the dedicated server-limits table.
37016
+ *
37017
+ * @private shared Agents Server constant
37018
+ */
37019
+ const SERVER_LIMIT_KEYS = {
37020
+ TIMEOUT_MAX_ACTIVE_PER_CHAT: 'TIMEOUT_MAX_ACTIVE_PER_CHAT',
37021
+ TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT: 'TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT',
37022
+ MAX_FILE_UPLOAD_SIZE_MB: MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY,
37023
+ FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS: FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY,
37024
+ SPAWN_AGENT_MAX_DEPTH: 'SPAWN_AGENT_MAX_DEPTH',
37025
+ SPAWN_AGENT_RATE_LIMIT_MAX: 'SPAWN_AGENT_RATE_LIMIT_MAX',
37026
+ SPAWN_AGENT_RATE_LIMIT_WINDOW_MS: 'SPAWN_AGENT_RATE_LIMIT_WINDOW_MS',
37027
+ LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS: 'LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS',
37028
+ };
37029
+ /**
37030
+ * Shared metadata for all server limits exposed in the admin UI and runtime loaders.
37031
+ *
37032
+ * @private shared Agents Server constant
37033
+ */
37034
+ const SERVER_LIMIT_DEFINITIONS = [
37035
+ {
37036
+ key: SERVER_LIMIT_KEYS.TIMEOUT_MAX_ACTIVE_PER_CHAT,
37037
+ category: 'Timeout tools',
37038
+ title: 'Max active timers per chat',
37039
+ description: 'Prevents one chat thread from scheduling too many timers at once.',
37040
+ unit: 'count',
37041
+ defaultValue: DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS.maxActivePerChat,
37042
+ minimumValue: 1,
37043
+ step: 1,
37044
+ legacyMetadataKeys: [TOOL_USAGE_LIMITS_METADATA_KEY],
37045
+ },
37046
+ {
37047
+ key: SERVER_LIMIT_KEYS.TIMEOUT_MAX_FIRED_PER_DAY_PER_CHAT,
37048
+ category: 'Timeout tools',
37049
+ title: 'Max timers fired per day per chat',
37050
+ description: 'Limits how many scheduled wake-ups can execute inside one chat within one UTC day.',
37051
+ unit: 'count',
37052
+ defaultValue: DEFAULT_TIMEOUT_TOOL_USAGE_LIMITS.maxFiredPerDayPerChat,
37053
+ minimumValue: 1,
37054
+ step: 1,
37055
+ legacyMetadataKeys: [TOOL_USAGE_LIMITS_METADATA_KEY],
37056
+ },
37057
+ {
37058
+ key: SERVER_LIMIT_KEYS.MAX_FILE_UPLOAD_SIZE_MB,
37059
+ category: 'Files',
37060
+ title: 'Max file upload size',
37061
+ description: 'Caps the size of uploaded files accepted by chat uploads and Android share-target imports.',
37062
+ unit: 'MB',
37063
+ defaultValue: 50,
37064
+ minimumValue: 1,
37065
+ step: 1,
37066
+ legacyMetadataKeys: [MAX_FILE_UPLOAD_SIZE_MB_METADATA_KEY],
37067
+ },
37068
+ {
37069
+ key: SERVER_LIMIT_KEYS.FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
37070
+ category: 'Federation',
37071
+ title: 'Federated import retry delay',
37072
+ description: 'Wait time between retries when importing agent books from federated servers.',
37073
+ unit: 'ms',
37074
+ defaultValue: DEFAULT_FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS,
37075
+ minimumValue: 0,
37076
+ step: 100,
37077
+ legacyMetadataKeys: [FEDERATED_AGENT_IMPORT_RETRY_DELAY_MS_METADATA_KEY],
37078
+ },
37079
+ {
37080
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_MAX_DEPTH,
37081
+ category: 'Agent spawning',
37082
+ title: 'Max spawn depth',
37083
+ description: 'Restricts how many nested `spawn_agent` hops can happen inside one tool runtime context.',
37084
+ unit: 'count',
37085
+ defaultValue: DEFAULT_SPAWN_AGENT_MAX_DEPTH,
37086
+ minimumValue: 1,
37087
+ step: 1,
37088
+ legacyMetadataKeys: [],
37089
+ },
37090
+ {
37091
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_RATE_LIMIT_MAX,
37092
+ category: 'Agent spawning',
37093
+ title: 'Max spawned agents per window',
37094
+ description: 'Limits how many persistent agents one actor can create through `spawn_agent` inside one rate-limit window.',
37095
+ unit: 'count',
37096
+ defaultValue: DEFAULT_SPAWN_AGENT_RATE_LIMIT_MAX,
37097
+ minimumValue: 1,
37098
+ step: 1,
37099
+ legacyMetadataKeys: [],
37100
+ },
37101
+ {
37102
+ key: SERVER_LIMIT_KEYS.SPAWN_AGENT_RATE_LIMIT_WINDOW_MS,
37103
+ category: 'Agent spawning',
37104
+ title: 'Spawn rate-limit window',
37105
+ description: 'Time window used together with the spawn quota for `spawn_agent` abuse protection.',
37106
+ unit: 'ms',
37107
+ defaultValue: DEFAULT_SPAWN_AGENT_RATE_LIMIT_WINDOW_MS,
37108
+ minimumValue: 1000,
37109
+ step: 1000,
37110
+ legacyMetadataKeys: [],
37111
+ },
37112
+ {
37113
+ key: SERVER_LIMIT_KEYS.LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37114
+ category: 'Local agent runner',
37115
+ title: 'Max failed message attempts',
37116
+ description: 'Stops the local coding-agent watcher from retrying the same queued chat message forever.',
37117
+ unit: 'count',
37118
+ defaultValue: DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37119
+ minimumValue: 1,
37120
+ step: 1,
37121
+ legacyMetadataKeys: [],
37122
+ },
37123
+ ];
37124
+ /**
37125
+ * Fast lookup map used by server-limit validators and UI helpers.
37126
+ *
37127
+ * @private shared Agents Server constant
37128
+ */
37129
+ new Map(SERVER_LIMIT_DEFINITIONS.map((definition) => [definition.key, definition]));
37130
+ /**
37131
+ * Fully normalized default values keyed by dedicated server-limit ids.
37132
+ *
37133
+ * @private shared Agents Server constant
37134
+ */
37135
+ const defaultServerLimitValues = {};
37136
+ for (const definition of SERVER_LIMIT_DEFINITIONS) {
37137
+ defaultServerLimitValues[definition.key] = definition.defaultValue;
37138
+ }
37139
+ /**
37140
+ * Default values used whenever a server-limit row has not been persisted yet.
37141
+ *
37142
+ * @private shared Agents Server constant
37143
+ */
37144
+ Object.freeze(defaultServerLimitValues);
37145
+ /**
37146
+ * Deprecated metadata keys that now mirror dedicated server-limit rows for backward compatibility.
37147
+ *
37148
+ * @private shared Agents Server constant
37149
+ */
37150
+ Array.from(new Set(SERVER_LIMIT_DEFINITIONS.flatMap((definition) => definition.legacyMetadataKeys)));
37151
+
36685
37152
  /**
36686
37153
  * Local worker-pump delay while the Agents Server foreground process stays active.
36687
37154
  *
@@ -36700,6 +37167,18 @@
36700
37167
  * @private internal constant of `ptbk agents-server`
36701
37168
  */
36702
37169
  const USER_CHAT_JOB_WORKER_ERROR_BODY_MAX_LENGTH = 2000;
37170
+ /**
37171
+ * Delay between foreground CLI attempts to load internal Agents Server limits during startup.
37172
+ *
37173
+ * @private internal constant of `ptbk agents-server`
37174
+ */
37175
+ const INTERNAL_SERVER_LIMITS_RETRY_DELAY_MS = 1000;
37176
+ /**
37177
+ * Maximum time spent waiting for the internal limits route before startup fails.
37178
+ *
37179
+ * @private internal constant of `ptbk agents-server`
37180
+ */
37181
+ const INTERNAL_SERVER_LIMITS_STARTUP_TIMEOUT_MS = 60000;
36703
37182
  /**
36704
37183
  * HTTP status used by an idle internal worker tick with no job to process.
36705
37184
  *
@@ -36806,6 +37285,12 @@
36806
37285
  logStreams,
36807
37286
  state,
36808
37287
  });
37288
+ const localAgentRunnerLimits = await waitForLocalAgentRunnerLimits({
37289
+ port: options.port,
37290
+ environment: runtimeChildEnvironment,
37291
+ logStreams,
37292
+ state,
37293
+ });
36809
37294
  stopUserChatJobWorkerPump = startUserChatJobWorkerPump({
36810
37295
  port: options.port,
36811
37296
  environment: runtimeChildEnvironment,
@@ -36813,7 +37298,7 @@
36813
37298
  state,
36814
37299
  });
36815
37300
  await withCurrentWorkingDirectory(runtimePaths.agentRootPath, async () => {
36816
- await runMultipleAgentMessages(createLocalAgentRunOptions(options), {
37301
+ await runMultipleAgentMessages(createLocalAgentRunOptions(options, localAgentRunnerLimits), {
36817
37302
  shouldContinue: () => state.isContinuing,
36818
37303
  watchErrorLogDirectoryPath: runtimePaths.logDirectoryPath,
36819
37304
  onUiInitialized: (uiHandle) => {
@@ -36942,7 +37427,7 @@
36942
37427
  /**
36943
37428
  * Creates local no-git agent runner options for folders managed by the Agents Server database.
36944
37429
  */
36945
- function createLocalAgentRunOptions(options) {
37430
+ function createLocalAgentRunOptions(options, localAgentRunnerLimits) {
36946
37431
  return {
36947
37432
  agentName: options.agentName,
36948
37433
  model: options.model,
@@ -36955,8 +37440,67 @@
36955
37440
  autoPush: false,
36956
37441
  autoPull: false,
36957
37442
  autoClone: false,
37443
+ maxMessageProcessingFailures: localAgentRunnerLimits.maxFailedAttempts,
36958
37444
  };
36959
37445
  }
37446
+ /**
37447
+ * Waits until the internal Next route can return current local runner limits.
37448
+ */
37449
+ async function waitForLocalAgentRunnerLimits(options) {
37450
+ const startedAt = Date.now();
37451
+ let lastError;
37452
+ while (options.state.isContinuing && Date.now() - startedAt < INTERNAL_SERVER_LIMITS_STARTUP_TIMEOUT_MS) {
37453
+ try {
37454
+ const limits = await fetchLocalAgentRunnerLimits(options);
37455
+ logRunnerEvent(options.logStreams.runner, `Local agent runner max failed attempts: ${limits.maxFailedAttempts}.`);
37456
+ return limits;
37457
+ }
37458
+ catch (error) {
37459
+ lastError = error;
37460
+ await wait$2(INTERNAL_SERVER_LIMITS_RETRY_DELAY_MS);
37461
+ }
37462
+ }
37463
+ if (!options.state.isContinuing) {
37464
+ return {
37465
+ maxFailedAttempts: DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS,
37466
+ };
37467
+ }
37468
+ throw new NotAllowed(_spaceTrim.spaceTrim(`
37469
+ Failed to load local agent runner limits from the Agents Server.
37470
+
37471
+ ${lastError instanceof Error ? lastError.message : String(lastError)}
37472
+ `));
37473
+ }
37474
+ /**
37475
+ * Loads local runner limits through the token-protected internal Agents Server route.
37476
+ */
37477
+ async function fetchLocalAgentRunnerLimits(options) {
37478
+ const response = await fetch(`http://localhost:${options.port}/api/internal/agent-runner-limits`, {
37479
+ method: 'GET',
37480
+ cache: 'no-store',
37481
+ headers: {
37482
+ 'x-user-chat-worker-token': options.environment.PTBK_AGENTS_SERVER_USER_CHAT_WORKER_TOKEN,
37483
+ },
37484
+ });
37485
+ if (!response.ok) {
37486
+ const details = await readUserChatJobWorkerErrorDetails(response);
37487
+ throw new Error(createInternalRouteErrorMessage('agent runner limits', response, details));
37488
+ }
37489
+ const payload = (await response.json());
37490
+ return {
37491
+ maxFailedAttempts: normalizeLocalAgentRunnerMaxFailedAttempts(payload.maxFailedAttempts),
37492
+ };
37493
+ }
37494
+ /**
37495
+ * Normalizes the local runner retry cap returned by the internal server route.
37496
+ */
37497
+ function normalizeLocalAgentRunnerMaxFailedAttempts(rawValue) {
37498
+ const parsedValue = Number(rawValue);
37499
+ if (!Number.isFinite(parsedValue) || parsedValue <= 0) {
37500
+ return DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS;
37501
+ }
37502
+ return Math.floor(parsedValue);
37503
+ }
36960
37504
  /**
36961
37505
  * Starts periodic internal worker calls that queue and reconcile local message-folder jobs.
36962
37506
  */
@@ -37065,12 +37609,18 @@
37065
37609
  * Builds the foreground worker failure message from HTTP status and route details.
37066
37610
  */
37067
37611
  function createUserChatJobWorkerErrorMessage(response, details) {
37612
+ return createInternalRouteErrorMessage('user chat worker', response, details);
37613
+ }
37614
+ /**
37615
+ * Builds a foreground failure message for one internal Agents Server route.
37616
+ */
37617
+ function createInternalRouteErrorMessage(routeLabel, response, details) {
37068
37618
  const statusText = response.statusText ? ` ${response.statusText}` : '';
37069
37619
  const statusMessage = `${response.status}${statusText}`;
37070
37620
  if (!details) {
37071
- return `Internal user chat worker returned ${statusMessage}.`;
37621
+ return `Internal ${routeLabel} route returned ${statusMessage}.`;
37072
37622
  }
37073
- return `Internal user chat worker returned ${statusMessage}: ${details}`;
37623
+ return `Internal ${routeLabel} route returned ${statusMessage}: ${details}`;
37074
37624
  }
37075
37625
  /**
37076
37626
  * Keeps foreground worker diagnostics bounded when a route returns a large payload.
@@ -37140,6 +37690,12 @@
37140
37690
  }
37141
37691
  commandProcess.kill();
37142
37692
  }
37693
+ /**
37694
+ * Waits for the given delay.
37695
+ */
37696
+ async function wait$2(delayMs) {
37697
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
37698
+ }
37143
37699
  // Note: [🟡] Code for CLI runtime [startAgentsServer](src/cli/cli-commands/agents-server/startAgentsServer.ts) should never be published outside of `@promptbook/cli`
37144
37700
 
37145
37701
  /**
@@ -61797,14 +62353,18 @@
61797
62353
  * Watches the queued message directory and answers messages one by one.
61798
62354
  */
61799
62355
  async function runAgentMessages(options, controls = {}) {
61800
- var _a;
62356
+ var _a, _b;
61801
62357
  validateAgentRunOptions(options);
61802
62358
  validateAgentWatchOptions('ptbk agent-folder run-agent', options);
61803
62359
  const projectPath = process.cwd();
61804
62360
  let autoPullTimestamp = options.autoPull ? Date.now() : undefined;
61805
62361
  const shouldContinue = controls.shouldContinue || (() => just(true));
62362
+ const queuePollIntervalMs = (_a = controls.queuePollIntervalMs) !== null && _a !== void 0 ? _a : AGENT_QUEUE_POLL_INTERVAL_MS;
61806
62363
  let isWatchSessionInitialized = false;
61807
62364
  let uiHandle;
62365
+ const messageFailureTracker = new AgentMessageFailureTracker({
62366
+ maxMessageProcessingFailures: options.maxMessageProcessingFailures,
62367
+ });
61808
62368
  while (shouldContinue()) {
61809
62369
  try {
61810
62370
  if (!isWatchSessionInitialized) {
@@ -61816,8 +62376,9 @@
61816
62376
  }
61817
62377
  }
61818
62378
  const result = await tickAgentMessages(options, { isQuietWhenIdle: true, uiHandle });
61819
- autoPullTimestamp = (_a = result.autoPullTimestamp) !== null && _a !== void 0 ? _a : autoPullTimestamp;
62379
+ autoPullTimestamp = (_b = result.autoPullTimestamp) !== null && _b !== void 0 ? _b : autoPullTimestamp;
61820
62380
  if (result.isMessageProcessed) {
62381
+ messageFailureTracker.clearMessageFailure(projectPath, result.queuedMessage);
61821
62382
  continue;
61822
62383
  }
61823
62384
  autoPullTimestamp = await waitForQueuedAgentMessage({
@@ -61826,6 +62387,7 @@
61826
62387
  autoPullTimestamp,
61827
62388
  uiHandle,
61828
62389
  shouldContinue,
62390
+ queuePollIntervalMs,
61829
62391
  });
61830
62392
  }
61831
62393
  catch (error) {
@@ -61834,7 +62396,8 @@
61834
62396
  logDirectoryPath: projectPath,
61835
62397
  error,
61836
62398
  });
61837
- await wait(AGENT_QUEUE_POLL_INTERVAL_MS);
62399
+ await messageFailureTracker.recordFailure(error);
62400
+ await wait(queuePollIntervalMs);
61838
62401
  }
61839
62402
  }
61840
62403
  }
@@ -61842,14 +62405,14 @@
61842
62405
  * Polls until at least one queued `.book` message is available.
61843
62406
  */
61844
62407
  async function waitForQueuedAgentMessage(options) {
61845
- const { projectPath, options: runOptions, uiHandle, shouldContinue } = options;
62408
+ const { projectPath, options: runOptions, uiHandle, shouldContinue, queuePollIntervalMs } = options;
61846
62409
  let { autoPullTimestamp } = options;
61847
62410
  let queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
61848
62411
  if (uiHandle) {
61849
62412
  updateAgentRunUiForWatching(uiHandle, queueSnapshot);
61850
62413
  }
61851
62414
  while (shouldContinue()) {
61852
- await wait(AGENT_QUEUE_POLL_INTERVAL_MS);
62415
+ await wait(queuePollIntervalMs);
61853
62416
  queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
61854
62417
  if (queueSnapshot.queuedMessages.length > 0) {
61855
62418
  return autoPullTimestamp;