@promptbook/cli 0.113.0-5 → 0.113.0-8

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 (123) hide show
  1. package/apps/agents-server/src/app/admin/update/AdvancedOriginRepositoryPanel.tsx +76 -0
  2. package/apps/agents-server/src/app/admin/update/CurrentDeploymentCard.tsx +160 -0
  3. package/apps/agents-server/src/app/admin/update/PendingCommitsCard.tsx +86 -0
  4. package/apps/agents-server/src/app/admin/update/TargetEnvironmentCard.tsx +331 -0
  5. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +20 -873
  6. package/apps/agents-server/src/app/admin/update/UpdateJobCard.tsx +329 -0
  7. package/apps/agents-server/src/app/admin/update/UpdateOverview.ts +74 -0
  8. package/apps/agents-server/src/app/admin/update/buildDeploymentTimeBehindLabel.ts +29 -0
  9. package/apps/agents-server/src/app/admin/update/formatHumanReadableTimestamp.ts +18 -0
  10. package/apps/agents-server/src/app/admin/update/getUpdateJobFailureMessage.ts +13 -0
  11. package/apps/agents-server/src/app/admin/update/getUpdateJobSuccessMessage.ts +13 -0
  12. package/apps/agents-server/src/app/admin/update/useUpdateClientState.ts +441 -0
  13. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
  14. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageClient.tsx +14 -559
  15. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageHeader.tsx +84 -0
  16. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageSection.tsx +52 -0
  17. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedCodePreview.tsx +138 -0
  18. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedHarnessSection.tsx +98 -0
  19. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/SourceBookSection.tsx +66 -0
  20. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeErrorBanner.tsx +30 -0
  21. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeExportWarningBanner.tsx +62 -0
  22. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/Transpiler.ts +9 -0
  23. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/useAgentCodeExportState.ts +478 -0
  24. package/apps/agents-server/src/app/system/utilities/mocked-chats/cloneMockedChatPreset.ts +17 -0
  25. package/apps/agents-server/src/app/system/utilities/mocked-chats/confirmDeleteMockedChat.ts +16 -0
  26. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedMessage.ts +81 -0
  27. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedParticipant.ts +146 -0
  28. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedSettings.ts +19 -0
  29. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDuplicatedDraft.ts +66 -0
  30. package/apps/agents-server/src/app/system/utilities/mocked-chats/findMockedChatById.ts +51 -0
  31. package/apps/agents-server/src/app/system/utilities/mocked-chats/persistMockedChats.ts +51 -0
  32. package/apps/agents-server/src/app/system/utilities/mocked-chats/useMockedChatsEditorState.ts +16 -426
  33. package/apps/agents-server/src/components/Homepage/buildFreeGraphBoxLayout.ts +446 -0
  34. package/apps/agents-server/src/components/Homepage/buildGraphLayoutNodes.ts +415 -157
  35. package/apps/agents-server/src/components/Homepage/useAgentsGraphCanvasState.ts +2 -1
  36. package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +3 -1541
  37. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteQueryBuilder.ts +623 -0
  38. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteSupabaseClient.ts +64 -0
  39. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/ensureTable.ts +93 -0
  40. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteFilters.ts +202 -0
  41. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteMutationPayload.ts +131 -0
  42. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteRowOperations.ts +102 -0
  43. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteSql.ts +59 -0
  44. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTableSchema.ts +329 -0
  45. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTypes.ts +84 -0
  46. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteValueCodec.ts +63 -0
  47. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/normalizeSqliteError.ts +22 -0
  48. package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
  49. package/apps/agents-server/src/tools/send_email.ts +1 -2
  50. package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
  51. package/apps/agents-server/src/utils/backup/createServerBackupZipStream.ts +7 -1382
  52. package/apps/agents-server/src/utils/backup/serverBackup/appendAgentBackupEntriesToZip.ts +27 -0
  53. package/apps/agents-server/src/utils/backup/serverBackup/appendConversationBackupEntriesToZip.ts +140 -0
  54. package/apps/agents-server/src/utils/backup/serverBackup/appendFileBackupEntriesToZip.ts +147 -0
  55. package/apps/agents-server/src/utils/backup/serverBackup/appendMessageBackupEntriesToZip.ts +65 -0
  56. package/apps/agents-server/src/utils/backup/serverBackup/appendMetadataBackupEntriesToZip.ts +39 -0
  57. package/apps/agents-server/src/utils/backup/serverBackup/appendSectionEntriesToZip.ts +92 -0
  58. package/apps/agents-server/src/utils/backup/serverBackup/appendUserBackupEntriesToZip.ts +80 -0
  59. package/apps/agents-server/src/utils/backup/serverBackup/createRedactedWalletBackupRecord.ts +34 -0
  60. package/apps/agents-server/src/utils/backup/serverBackup/createServerBackupManifest.ts +82 -0
  61. package/apps/agents-server/src/utils/backup/serverBackup/downloadBackupBinaryContent.ts +39 -0
  62. package/apps/agents-server/src/utils/backup/serverBackup/resolveFeedbackThreadMessages.ts +53 -0
  63. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupAttachments.ts +151 -0
  64. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupContext.ts +167 -0
  65. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupFilenames.ts +161 -0
  66. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupPreviews.ts +97 -0
  67. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupRowUtilities.ts +158 -0
  68. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupTypes.ts +59 -0
  69. package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
  70. package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
  71. package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
  72. package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
  73. package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
  74. package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
  75. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
  76. package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
  77. package/apps/agents-server/src/utils/messages/sendMessage.ts +5 -3
  78. package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
  79. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
  80. package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
  81. package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
  82. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition/SpeechToTextFailoverRecognitionProviderRuntime.ts +0 -1
  83. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition.ts +34 -2
  84. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
  85. package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
  86. package/esm/index.es.js +96 -57
  87. package/esm/index.es.js.map +1 -1
  88. package/esm/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  89. package/esm/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  90. package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  91. package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  92. package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  93. package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  94. package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  95. package/esm/src/version.d.ts +1 -1
  96. package/package.json +1 -1
  97. package/src/avatars/avatarAnimationScheduler.ts +2 -1
  98. package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
  99. package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
  100. package/src/book-components/Chat/Chat/insertDictationChunk.ts +3 -3
  101. package/src/book-components/Chat/Chat/learnDictationDictionary.ts +1 -1
  102. package/src/book-components/Chat/Chat/useChatInputAreaDictation.ts +133 -26
  103. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
  104. package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
  105. package/src/cli/cli-commands/coder/find-refactor-candidates.ts +9 -2
  106. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
  107. package/src/cli/cli-commands/coder/run.ts +3 -27
  108. package/src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts +31 -0
  109. package/src/commitments/TEAM/TEAM.ts +5 -5
  110. package/src/other/templates/getTemplatesPipelineCollection.ts +727 -781
  111. package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +1 -4
  112. package/src/version.ts +2 -2
  113. package/src/versions.txt +1 -0
  114. package/umd/index.umd.js +96 -57
  115. package/umd/index.umd.js.map +1 -1
  116. package/umd/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  117. package/umd/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  118. package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  119. package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  120. package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  121. package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  122. package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  123. package/umd/src/version.d.ts +1 -1
@@ -231,8 +231,42 @@ type ResolveInheritedAgentSourceOptions = ImportAgentOptions & {
231
231
  * Retry configuration used for federated imported-agent loading.
232
232
  */
233
233
  readonly federatedAgentImportConfiguration?: FederatedAgentImportConfiguration;
234
+ /**
235
+ * Optional same-instance source importer used before falling back to HTTP import.
236
+ */
237
+ readonly agentSourceImporter?: AgentSourceImporter;
234
238
  };
235
239
 
240
+ /**
241
+ * Context passed to a custom agent source importer.
242
+ */
243
+ export type AgentSourceImporterContext = {
244
+ /**
245
+ * Commitment that requested the imported source.
246
+ */
247
+ readonly commitmentType: 'FROM' | 'IMPORT';
248
+
249
+ /**
250
+ * Import options propagated from the current resolution pass.
251
+ */
252
+ readonly importAgentOptions: ImportAgentOptions;
253
+
254
+ /**
255
+ * Retry configuration used by the default HTTP importer.
256
+ */
257
+ readonly federatedAgentImportConfiguration: FederatedAgentImportConfiguration;
258
+ };
259
+
260
+ /**
261
+ * Imports one agent source before the resolver falls back to the default HTTP importer.
262
+ *
263
+ * Return `null` when the importer does not own the given URL.
264
+ */
265
+ export type AgentSourceImporter = (
266
+ agentUrl: string_agent_url,
267
+ context: AgentSourceImporterContext,
268
+ ) => Promise<string_book | null>;
269
+
236
270
  /**
237
271
  * Parent inheritance state derived before rewriting the source body.
238
272
  */
@@ -277,6 +311,11 @@ type AgentImportContext = {
277
311
  */
278
312
  readonly importAgentOptions: ImportAgentOptions;
279
313
 
314
+ /**
315
+ * Optional importer for same-instance agent sources.
316
+ */
317
+ readonly agentSourceImporter?: AgentSourceImporter;
318
+
280
319
  /**
281
320
  * Original resolution options used for cycle detection.
282
321
  */
@@ -364,6 +403,7 @@ function createAgentImportContext(options?: ResolveInheritedAgentSourceOptions):
364
403
  recursionLevel: options?.recursionLevel || 0,
365
404
  inheritancePath: createResolutionLineage(options),
366
405
  },
406
+ agentSourceImporter: options?.agentSourceImporter,
367
407
  resolutionOptions: options,
368
408
  };
369
409
  }
@@ -427,11 +467,20 @@ async function importAgentCorpus(
427
467
  ): Promise<string> {
428
468
  assertNoResolutionCycle(agentUrl, commitmentType, context.resolutionOptions);
429
469
 
430
- const importedAgentSource = await importAgentWithFallback(
431
- agentUrl,
432
- context.importAgentOptions,
433
- context.federatedAgentImportConfiguration,
434
- );
470
+ const locallyImportedAgentSource = context.agentSourceImporter
471
+ ? await context.agentSourceImporter(agentUrl, {
472
+ commitmentType,
473
+ importAgentOptions: context.importAgentOptions,
474
+ federatedAgentImportConfiguration: context.federatedAgentImportConfiguration,
475
+ })
476
+ : null;
477
+ const importedAgentSource =
478
+ locallyImportedAgentSource ??
479
+ (await importAgentWithFallback(
480
+ agentUrl,
481
+ context.importAgentOptions,
482
+ context.federatedAgentImportConfiguration,
483
+ ));
435
484
 
436
485
  return getAgentSourceCorpus(importedAgentSource as string_book);
437
486
  }
@@ -1,6 +1,7 @@
1
1
  import type { AgentReferenceResolver } from '../../../../src/book-2.0/agent-source/AgentReferenceResolver';
2
2
  import type { AgentCollection } from '../../../../src/collection/agent-collection/AgentCollection';
3
3
  import { resolveBookScopedAgentContext, type ResolvedBookScopedAgentContext } from './agentReferenceResolver/bookScopedAgentReferences';
4
+ import { createLocalAgentSourceImporter } from './createLocalAgentSourceImporter';
4
5
  import { loadFederatedAgentImportConfiguration } from './federatedAgentImportConfiguration';
5
6
  import { getWellKnownAgentUrl } from './getWellKnownAgentUrl';
6
7
  import { resolveAgentStateFromSource, type ResolvedAgentState } from './resolveAgentStateFromSource';
@@ -46,12 +47,22 @@ export async function resolveServerAgentContext(
46
47
  ): Promise<ResolvedServerAgentContext> {
47
48
  const bookScopedAgentContext = await resolveBookScopedAgentContext(options);
48
49
  const federatedAgentImportConfiguration = await loadFederatedAgentImportConfiguration();
50
+ const adamAgentUrl = await getWellKnownAgentUrl('ADAM');
51
+ const agentSourceImporter = createLocalAgentSourceImporter({
52
+ collection: options.collection,
53
+ localServerUrls: [options.localServerUrl],
54
+ localAgentUrls: [adamAgentUrl],
55
+ adamAgentUrl,
56
+ fallbackResolver: options.fallbackResolver,
57
+ federatedAgentImportConfiguration,
58
+ });
49
59
  const resolvedAgentState = await resolveAgentStateFromSource(bookScopedAgentContext.unresolvedAgentSource, {
50
- adamAgentUrl: await getWellKnownAgentUrl('ADAM'),
60
+ adamAgentUrl,
51
61
  canonicalAgentUrl: bookScopedAgentContext.canonicalAgentUrl,
52
62
  currentAgentAliases: bookScopedAgentContext.currentAgentAliases,
53
63
  agentReferenceResolver: bookScopedAgentContext.scopedAgentReferenceResolver,
54
64
  federatedAgentImportConfiguration,
65
+ agentSourceImporter,
55
66
  });
56
67
 
57
68
  return {
@@ -30,7 +30,7 @@ export type ResolvedStoredAgentState<TAgent extends StoredAgentSourceRecord> = T
30
30
  */
31
31
  export type ResolveStoredAgentStateOptions = Pick<
32
32
  ResolveAgentStateFromSourceOptions,
33
- 'adamAgentUrl' | 'agentReferenceResolver' | 'federatedAgentImportConfiguration'
33
+ 'adamAgentUrl' | 'agentReferenceResolver' | 'federatedAgentImportConfiguration' | 'agentSourceImporter'
34
34
  > & {
35
35
  /**
36
36
  * Public/current server origin used to build canonical local agent URLs.
@@ -91,6 +91,7 @@ export async function resolveStoredAgentState<TAgent extends StoredAgentSourceRe
91
91
  currentAgentAliases: createCanonicalLocalAgentAliases(agent, options.localServerUrl),
92
92
  agentReferenceResolver: options.agentReferenceResolver,
93
93
  federatedAgentImportConfiguration,
94
+ agentSourceImporter: options.agentSourceImporter,
94
95
  });
95
96
 
96
97
  return {
@@ -172,7 +172,6 @@ export class SpeechToTextFailoverRecognitionProviderRuntime {
172
172
  }
173
173
  }
174
174
 
175
- this.options.onForceIdleStop();
176
175
  return false;
177
176
  }
178
177
 
@@ -302,13 +302,45 @@ export class SpeechToTextFailoverRecognition implements SpeechRecognition {
302
302
  * Handles stall watchdog restart/failover escalation.
303
303
  */
304
304
  private handleStallDetected(): void {
305
+ void this.handleStallDetectedAsync();
306
+ }
307
+
308
+ /**
309
+ * Handles stall watchdog restart/failover escalation.
310
+ */
311
+ private async handleStallDetectedAsync(): Promise<void> {
312
+ const providerId = this.providerRuntime.currentProviderId;
313
+
305
314
  if (!this.providerRuntime.hasRestartedCurrentProvider) {
306
315
  this.providerRuntime.markCurrentProviderRestarted();
307
- void this.providerRuntime.restartCurrentProvider('stall-detected');
316
+ this.telemetryReporter.emit({
317
+ type: 'provider-restart',
318
+ providerId,
319
+ elapsedMs: Date.now() - this.sessionStartedAtMs,
320
+ detail: 'stall-detected',
321
+ });
322
+
323
+ const restartSucceeded = await this.providerRuntime.restartCurrentProvider('stall-detected');
324
+ if (restartSucceeded) {
325
+ return;
326
+ }
327
+ }
328
+
329
+ const failoverSucceeded = await this.providerRuntime.failoverToNextProvider('stall-after-restart');
330
+ if (failoverSucceeded) {
308
331
  return;
309
332
  }
310
333
 
311
- void this.providerRuntime.failoverToNextProvider('stall-after-restart');
334
+ this._state = 'ERROR';
335
+ this.emit({
336
+ type: 'ERROR',
337
+ message: 'Speech recognition stalled while audio was detected. No fallback speech-to-text provider was available.',
338
+ code: 'unknown',
339
+ providerId,
340
+ canRetry: true,
341
+ canOpenBrowserSettings: false,
342
+ });
343
+ this.forceIdleStop();
312
344
  }
313
345
 
314
346
  /**
@@ -1,4 +1,6 @@
1
1
  import type { ChatMessage } from '../../../../../src/_packages/types.index';
2
+ import { appendChatAttachmentContextWithContent } from '../../../../../src/utils/chat/chatAttachments/appendChatAttachmentContextWithContent';
3
+
2
4
  /**
3
5
  * Lifecycle states rendered on canonical server-owned chat messages.
4
6
  */
@@ -99,11 +101,11 @@ export function resolvePromptThreadBeforeUserMessage(
99
101
  /**
100
102
  * Creates the complete chat thread mirrored to a runner before it writes the next answer.
101
103
  */
102
- export function createUserChatRunnerThreadMessages(options: {
104
+ export async function createUserChatRunnerThreadMessages(options: {
103
105
  messages: ReadonlyArray<ChatMessage>;
104
106
  userMessageId: string;
105
107
  resolveInitialAgentMessage: () => string | null | undefined;
106
- }): Array<UserChatRunnerThreadMessage> {
108
+ }): Promise<Array<UserChatRunnerThreadMessage>> {
107
109
  const userMessage = options.messages.find((message) => message.id === options.userMessageId);
108
110
  if (!userMessage) {
109
111
  return [];
@@ -111,19 +113,16 @@ export function createUserChatRunnerThreadMessages(options: {
111
113
 
112
114
  const previousThreadMessages = resolvePromptThreadBeforeUserMessage(options.messages, options.userMessageId);
113
115
 
114
- return [
116
+ const threadMessages = [
115
117
  ...createInitialUserChatRunnerThreadMessages({
116
118
  isFirstUserTurn: previousThreadMessages.length === 0,
117
119
  resolveInitialAgentMessage: options.resolveInitialAgentMessage,
118
120
  }),
119
121
  ...previousThreadMessages,
120
122
  userMessage,
121
- ]
122
- .filter(isUserChatRunnerThreadMessage)
123
- .map((message) => ({
124
- sender: message.sender,
125
- content: message.content,
126
- }));
123
+ ].filter(isUserChatRunnerThreadMessage);
124
+
125
+ return await Promise.all(threadMessages.map(createUserChatRunnerThreadMessage));
127
126
  }
128
127
 
129
128
  /**
@@ -176,3 +175,34 @@ function isUserChatRunnerThreadMessage(message: ChatMessage): message is ChatMes
176
175
  const isRunnerSender = message.sender === 'USER' || message.sender === 'AGENT';
177
176
  return message.isComplete !== false && isRunnerSender;
178
177
  }
178
+
179
+ /**
180
+ * Creates one runner-visible message with attachment context inlined into user-authored content.
181
+ *
182
+ * @private helper of `createUserChatRunnerThreadMessages`
183
+ */
184
+ async function createUserChatRunnerThreadMessage(
185
+ message: ChatMessage & UserChatRunnerThreadMessage,
186
+ ): Promise<UserChatRunnerThreadMessage> {
187
+ return {
188
+ sender: message.sender,
189
+ content: await createUserChatRunnerThreadMessageContent(message),
190
+ };
191
+ }
192
+
193
+ /**
194
+ * Adds attachment URLs and best-effort text previews to user messages mirrored into runner `.book` files.
195
+ *
196
+ * @private helper of `createUserChatRunnerThreadMessage`
197
+ */
198
+ async function createUserChatRunnerThreadMessageContent(
199
+ message: ChatMessage & UserChatRunnerThreadMessage,
200
+ ): Promise<string> {
201
+ if (message.sender !== 'USER' || !message.attachments || message.attachments.length === 0) {
202
+ return message.content;
203
+ }
204
+
205
+ return await appendChatAttachmentContextWithContent(message.content, message.attachments, {
206
+ allowLocalhost: true,
207
+ });
208
+ }
@@ -212,6 +212,7 @@ async function delayNextMatchingRequest(
212
212
  options: DelayNextMatchingRequestOptions,
213
213
  ): Promise<DelayedRequestControl> {
214
214
  let hasInterceptedTargetRequest = false;
215
+ let isReleased = false;
215
216
  let releaseRequest: (() => void) | null = null;
216
217
  let markStarted: (() => void) | null = null;
217
218
  let markFinished: (() => void) | null = null;
@@ -239,6 +240,9 @@ async function delayNextMatchingRequest(
239
240
 
240
241
  await new Promise<void>((resolve) => {
241
242
  releaseRequest = resolve;
243
+ if (isReleased) {
244
+ resolve();
245
+ }
242
246
  });
243
247
 
244
248
  try {
@@ -255,6 +259,7 @@ async function delayNextMatchingRequest(
255
259
  waitUntilStarted,
256
260
  waitUntilFinished,
257
261
  release() {
262
+ isReleased = true;
258
263
  releaseRequest?.();
259
264
  },
260
265
  async dispose() {
package/esm/index.es.js CHANGED
@@ -59,7 +59,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
59
59
  * @generated
60
60
  * @see https://github.com/webgptorg/promptbook
61
61
  */
62
- const PROMPTBOOK_ENGINE_VERSION = '0.113.0-5';
62
+ const PROMPTBOOK_ENGINE_VERSION = '0.113.0-8';
63
63
  /**
64
64
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
65
65
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -14664,7 +14664,7 @@ const octopus3d4AvatarVisual = {
14664
14664
  isAnimated: true,
14665
14665
  supportsPointerTracking: true,
14666
14666
  render({ context, size, palette, createRandom, timeMs, interaction }) {
14667
- const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots } = getOctopus3d4StableState(createRandom);
14667
+ const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots, } = getOctopus3d4StableState(createRandom);
14668
14668
  const sceneCenterX = size * 0.5;
14669
14669
  const sceneCenterY = size * 0.535;
14670
14670
  const bob = Math.sin(timeMs / 980 + animationPhase) * size * 0.013;
@@ -15012,10 +15012,7 @@ function sampleBlobbyContinuousSurfacePointWithLongitudeCache(options, latitude,
15012
15012
  Math.max(0, Math.cos(effectiveLongitude)) * 0.12 +
15013
15013
  lowerBlend * tentacleInfluence.core * (0.12 + tentacleInfluence.depthScale * 0.07) -
15014
15014
  Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
15015
- const tentacleTubeRadius = lowerBlend *
15016
- tentacleInfluence.core *
15017
- (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) *
15018
- radiusX;
15015
+ const tentacleTubeRadius = lowerBlend * tentacleInfluence.core * (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) * radiusX;
15019
15016
  const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
15020
15017
  const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.74;
15021
15018
  const lowerDrop = lowerBlend *
@@ -15027,9 +15024,7 @@ function sampleBlobbyContinuousSurfacePointWithLongitudeCache(options, latitude,
15027
15024
  (morphologyProfile.tentacles.flowLengthScale - 1) * 0.1));
15028
15025
  const combinedTentacleSway = (primaryTentacleWave + secondaryTentacleWave) * radiusX * (0.06 + tipBlend * 0.06);
15029
15026
  return {
15030
- x: Math.sin(effectiveLongitude) * planarRadiusX +
15031
- combinedTentacleSway +
15032
- tentacleCurl * radiusX * 0.18,
15027
+ x: Math.sin(effectiveLongitude) * planarRadiusX + combinedTentacleSway + tentacleCurl * radiusX * 0.18,
15033
15028
  y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
15034
15029
  upperBlend * radiusY * 0.12 +
15035
15030
  lowerDrop +
@@ -18288,10 +18283,10 @@ const teamToolTitles = {};
18288
18283
  *
18289
18284
  * @private
18290
18285
  */
18291
- const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
18292
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
18293
- '- Do not ask the user for information that a listed teammate can provide directly.',
18294
- ];
18286
+ const TEAM_SYSTEM_MESSAGE_GUIDANCE = spaceTrim$1(`
18287
+ - If a teammate is relevant to the request, consult that teammate using the matching tool.
18288
+ - Do not ask the user for information that a listed teammate can provide directly.
18289
+ `);
18295
18290
  /**
18296
18291
  * Constant for remote agents by Url.
18297
18292
  */
@@ -18473,7 +18468,7 @@ function buildTeamSystemMessageBody(teamEntries) {
18473
18468
  `);
18474
18469
  });
18475
18470
  return spaceTrim$1((block) => `
18476
- ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES.join('\n'))}
18471
+ ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE)}
18477
18472
 
18478
18473
  ${block(teammateSections.join('\n\n'))}
18479
18474
  `);
@@ -40291,6 +40286,30 @@ function createLineCountLimits(maxLineCount) {
40291
40286
  }
40292
40287
  // Note: [🟡] Code for repository script [RefactorCandidateLevel](scripts/find-refactor-candidates/RefactorCandidateLevel.ts) should never be published outside of `@promptbook/cli`
40293
40288
 
40289
+ /**
40290
+ * Creates a Commander argument parser that accepts only positive integers.
40291
+ *
40292
+ * The returned parser is meant to be passed as the coercion callback of `command.option(...)`.
40293
+ * It throws a branded `NotAllowed` error with a clear message referencing the given option name
40294
+ * when the provided value is not a positive integer.
40295
+ *
40296
+ * @private internal utility of `promptbookCli`
40297
+ */
40298
+ function createPositiveIntegerOptionParser(optionName) {
40299
+ return (value) => {
40300
+ const parsedValue = Number(value);
40301
+ if (!Number.isInteger(parsedValue) || parsedValue <= 0) {
40302
+ throw new NotAllowed(spaceTrim$1(`
40303
+ Invalid value for \`${optionName}\`: \`${value}\`.
40304
+
40305
+ Use a positive integer.
40306
+ `));
40307
+ }
40308
+ return parsedValue;
40309
+ };
40310
+ }
40311
+ // Note: [🟡] Code for CLI option parser [createPositiveIntegerOptionParser](src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts) should never be published outside of `@promptbook/cli`
40312
+
40294
40313
  /**
40295
40314
  * Initializes `coder find-refactor-candidates` command for Promptbook CLI utilities
40296
40315
  *
@@ -40311,12 +40330,13 @@ function $initializeCoderFindRefactorCandidatesCommand(program) {
40311
40330
  command.addOption(new Option('--level <level>', `Set scan aggressiveness (${REFACTOR_CANDIDATE_LEVEL_VALUES.join(', ')})`)
40312
40331
  .choices([...REFACTOR_CANDIDATE_LEVEL_VALUES])
40313
40332
  .default(DEFAULT_REFACTOR_CANDIDATE_LEVEL));
40333
+ command.option('--limit <candidate-count>', 'Create at most this many refactor prompts, keeping the most important candidates', createPositiveIntegerOptionParser('--limit'));
40314
40334
  command.action(handleActionErrors(async (cliOptions) => {
40315
- const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL } = cliOptions;
40335
+ const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = cliOptions;
40316
40336
  // Note: Import the function dynamically to avoid loading heavy dependencies until needed
40317
40337
  const { findRefactorCandidates } = await Promise.resolve().then(function () { return findRefactorCandidates$1; });
40318
40338
  try {
40319
- await findRefactorCandidates({ level });
40339
+ await findRefactorCandidates({ level, limit });
40320
40340
  }
40321
40341
  catch (error) {
40322
40342
  assertsError(error);
@@ -40400,26 +40420,26 @@ const DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS = [
40400
40420
  id: 'common',
40401
40421
  relativeFilePath: join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'common.md'),
40402
40422
  slugPrefix: null,
40403
- content: buildCoderPromptTemplateContent([
40404
- '- @@@',
40405
- "- Keep in mind the DRY _(don't repeat yourself)_ principle.",
40406
- '- Do a proper analysis of the current functionality before you start implementing.',
40407
- '- Add the changes into the [changelog](changelog/_current-preversion.md)',
40408
- ]),
40423
+ content: spaceTrim$1(`
40424
+ - @@@
40425
+ - Keep in mind the DRY _(don't repeat yourself)_ principle.
40426
+ - Do a proper analysis of the current functionality before you start implementing.
40427
+ - Add the changes into the [changelog](changelog/_current-preversion.md)
40428
+ `),
40409
40429
  isDefaultProjectTemplate: true,
40410
40430
  },
40411
40431
  {
40412
40432
  id: 'agents-server',
40413
40433
  relativeFilePath: join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'agents-server.md'),
40414
40434
  slugPrefix: 'agents-server',
40415
- content: buildCoderPromptTemplateContent([
40416
- '- @@@',
40417
- "- Keep in mind the DRY _(don't repeat yourself)_ principle.",
40418
- '- Do a proper analysis of the current functionality before you start implementing.',
40419
- '- You are working with the [Agents Server](apps/agents-server)',
40420
- '- If you need to do the database migration, do it',
40421
- '- Add the changes into the [changelog](changelog/_current-preversion.md)',
40422
- ]),
40435
+ content: spaceTrim$1(`
40436
+ - @@@
40437
+ - Keep in mind the DRY _(don't repeat yourself)_ principle.
40438
+ - Do a proper analysis of the current functionality before you start implementing.
40439
+ - You are working with the [Agents Server](apps/agents-server)
40440
+ - If you need to do the database migration, do it
40441
+ - Add the changes into the [changelog](changelog/_current-preversion.md)
40442
+ `),
40423
40443
  isDefaultProjectTemplate: false,
40424
40444
  },
40425
40445
  ];
@@ -40539,12 +40559,6 @@ function normalizeCoderPromptTemplateOption(templateOption) {
40539
40559
  function getDefaultCoderPromptTemplateDefinitionOrUndefined(template) {
40540
40560
  return DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS.find((definition) => definition.id === template);
40541
40561
  }
40542
- /**
40543
- * Builds stable markdown content for one coder prompt template without indentation drift.
40544
- */
40545
- function buildCoderPromptTemplateContent(lines) {
40546
- return lines.join('\n');
40547
- }
40548
40562
  /**
40549
40563
  * Creates a fully resolved template payload from one built-in definition.
40550
40564
  */
@@ -41471,7 +41485,7 @@ function $initializeCoderRunCommand(program) {
41471
41485
  command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
41472
41486
  addPromptRunnerExecutionOptions(command);
41473
41487
  command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption$1, 0);
41474
- command.option('--limit <run-count>', 'Stop after processing this many prompt runs', parsePositiveIntegerOption);
41488
+ command.option('--limit <run-count>', 'Stop after processing this many prompt runs', createPositiveIntegerOptionParser('--limit'));
41475
41489
  command.option('--wait-after-prompt <duration>', spaceTrim$1(`
41476
41490
  Wait this long after each prompt has been implemented, verified and committed before starting the next prompt.
41477
41491
  Accepts durations like 1h, 30m, 5s. Defaults to 0 (no wait).
@@ -41558,22 +41572,6 @@ function parseIntOption$1(value) {
41558
41572
  }
41559
41573
  return parsed;
41560
41574
  }
41561
- /**
41562
- * Parses a positive integer option value.
41563
- *
41564
- * @private internal utility of `coder run` command
41565
- */
41566
- function parsePositiveIntegerOption(value) {
41567
- const parsed = Number(value);
41568
- if (!Number.isInteger(parsed) || parsed <= 0) {
41569
- throw new NotAllowed(spaceTrim$1(`
41570
- Invalid value for \`--limit\`: \`${value}\`.
41571
-
41572
- Use a positive integer.
41573
- `));
41574
- }
41575
- return parsed;
41576
- }
41577
41575
  /**
41578
41576
  * Joins one Commander option that may be parsed either as a single string or a variadic token array.
41579
41577
  *
@@ -69846,23 +69844,28 @@ async function analyzeSourceFileForRefactorCandidate(options) {
69846
69844
  const extension = extname(filePath).toLowerCase();
69847
69845
  const relativePath = normalizeRefactorCandidatePath(relative(rootDir, filePath));
69848
69846
  const reasons = [];
69847
+ let severityScore = 0;
69849
69848
  if (!lineCountExemptPaths.has(normalizedAbsolutePath)) {
69850
69849
  const lineCount = countLines(content);
69851
69850
  const maxLines = getMaxLinesForExtension(extension, heuristics);
69852
69851
  if (lineCount > maxLines) {
69853
69852
  reasons.push(`lines ${lineCount}/${maxLines}`);
69853
+ severityScore += lineCount / maxLines;
69854
69854
  }
69855
69855
  }
69856
69856
  if (STRUCTURAL_ANALYSIS_EXTENSIONS.includes(extension)) {
69857
69857
  const structureSummary = summarizeSourceFileStructure(content, extension, filePath);
69858
69858
  if (structureSummary.entityCount > heuristics.maxEntityCountPerFile) {
69859
69859
  reasons.push(`entities ${structureSummary.entityCount}/${heuristics.maxEntityCountPerFile}`);
69860
+ severityScore += structureSummary.entityCount / heuristics.maxEntityCountPerFile;
69860
69861
  }
69861
69862
  if (structureSummary.functionCount > heuristics.maxFunctionCountPerFile) {
69862
69863
  reasons.push(`functions ${structureSummary.functionCount}/${heuristics.maxFunctionCountPerFile}`);
69864
+ severityScore += structureSummary.functionCount / heuristics.maxFunctionCountPerFile;
69863
69865
  }
69864
69866
  if (structureSummary.maxFunctionComplexity > heuristics.maxFunctionComplexity) {
69865
69867
  reasons.push(buildComplexityReason(structureSummary, heuristics.maxFunctionComplexity));
69868
+ severityScore += structureSummary.maxFunctionComplexity / heuristics.maxFunctionComplexity;
69866
69869
  }
69867
69870
  }
69868
69871
  if (reasons.length === 0) {
@@ -69872,6 +69875,7 @@ async function analyzeSourceFileForRefactorCandidate(options) {
69872
69875
  absolutePath: filePath,
69873
69876
  relativePath,
69874
69877
  reasons,
69878
+ severityScore,
69875
69879
  };
69876
69880
  }
69877
69881
  /**
@@ -70331,6 +70335,37 @@ async function isExistingFile(filePath) {
70331
70335
  }
70332
70336
  // Note: [🟡] Code for repository script [resolveRefactorCandidateProject](scripts/find-refactor-candidates/resolveRefactorCandidateProject.ts) should never be published outside of `@promptbook/cli`
70333
70337
 
70338
+ /**
70339
+ * Keeps at most `limit` refactor candidates, preferring the most important ones.
70340
+ *
70341
+ * When there are more candidates than `limit`, only the highest-severity candidates are kept
70342
+ * (ties broken by relative path for determinism). When `limit` is `undefined` or there are fewer
70343
+ * candidates than the limit, every candidate is returned. The original input order is preserved
70344
+ * among the kept candidates, so `limit` acts purely as a filter and never reorders prompts.
70345
+ *
70346
+ * @private function of findRefactorCandidates
70347
+ */
70348
+ function selectMostImportantRefactorCandidates(candidates, limit) {
70349
+ if (limit === undefined || candidates.length <= limit) {
70350
+ return candidates;
70351
+ }
70352
+ const candidatesRankedByImportance = [...candidates].sort(compareRefactorCandidatesByImportance);
70353
+ const keptRelativePaths = new Set(candidatesRankedByImportance.slice(0, limit).map((candidate) => candidate.relativePath));
70354
+ return candidates.filter((candidate) => keptRelativePaths.has(candidate.relativePath));
70355
+ }
70356
+ /**
70357
+ * Orders refactor candidates from most to least important.
70358
+ *
70359
+ * @private function of selectMostImportantRefactorCandidates
70360
+ */
70361
+ function compareRefactorCandidatesByImportance(candidateA, candidateB) {
70362
+ if (candidateB.severityScore !== candidateA.severityScore) {
70363
+ return candidateB.severityScore - candidateA.severityScore;
70364
+ }
70365
+ return candidateA.relativePath.localeCompare(candidateB.relativePath);
70366
+ }
70367
+ // Note: [🟡] Code for repository script [selectMostImportantRefactorCandidates](scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.ts) should never be published outside of `@promptbook/cli`
70368
+
70334
70369
  /**
70335
70370
  * Calculates the next available prompt numbering sequence for a month.
70336
70371
  */
@@ -70654,7 +70689,7 @@ function initializeFindRefactorCandidatesRun() {
70654
70689
  * @public exported from `@promptbook/cli`
70655
70690
  */
70656
70691
  async function findRefactorCandidates(options = {}) {
70657
- const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL } = options;
70692
+ const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = options;
70658
70693
  const heuristics = getRefactorCandidateLevelConfiguration(level);
70659
70694
  initializeFindRefactorCandidatesRun();
70660
70695
  console.info(colors.cyan('⚡🏭 Find refactor candidates'));
@@ -70678,8 +70713,10 @@ async function findRefactorCandidates(options = {}) {
70678
70713
  console.info(colors.green('All candidates already have prompts.'));
70679
70714
  return;
70680
70715
  }
70716
+ const selectedCandidatesToWrite = selectMostImportantRefactorCandidates(candidatesToWrite, limit);
70717
+ const skippedByLimit = candidatesToWrite.length - selectedCandidatesToWrite.length;
70681
70718
  const createdPrompts = await writeRefactorCandidatePrompts({
70682
- candidates: candidatesToWrite,
70719
+ candidates: selectedCandidatesToWrite,
70683
70720
  rootDir,
70684
70721
  promptsDir,
70685
70722
  });
@@ -70687,6 +70724,9 @@ async function findRefactorCandidates(options = {}) {
70687
70724
  if (alreadyTracked > 0) {
70688
70725
  console.info(colors.gray(`Skipped ${alreadyTracked} candidate(s) with existing prompts.`));
70689
70726
  }
70727
+ if (skippedByLimit > 0) {
70728
+ console.info(colors.gray(`Skipped ${skippedByLimit} lower-priority candidate(s) because of \`--limit ${limit}\`.`));
70729
+ }
70690
70730
  }
70691
70731
  /**
70692
70732
  * Prints discovered refactor candidates with their reasons.
@@ -71938,8 +71978,7 @@ function mapColorToAnsi256(color) {
71938
71978
  if (gray > ANSI_256_NEAR_WHITE_GRAY_LEVEL) {
71939
71979
  return ANSI_256_WHITE_INDEX; // <- Note: Pure white lives in the color cube
71940
71980
  }
71941
- return (232 +
71942
- Math.round(((gray - 8) / ANSI_256_GRAYSCALE_RAMP_MAX_LEVEL) * ANSI_256_GRAYSCALE_RAMP_INDEX_SPAN));
71981
+ return 232 + Math.round(((gray - 8) / ANSI_256_GRAYSCALE_RAMP_MAX_LEVEL) * ANSI_256_GRAYSCALE_RAMP_INDEX_SPAN);
71943
71982
  }
71944
71983
  const redIndex = Math.round((red / 255) * 5);
71945
71984
  const greenIndex = Math.round((green / 255) * 5);