@promptbook/cli 0.112.0-132 → 0.112.0-134

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 (101) hide show
  1. package/apps/agents-server/src/app/admin/api-tokens/ApiTokensClient.tsx +4 -1
  2. package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +3 -0
  3. package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackTable.tsx +13 -8
  4. package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +3 -0
  5. package/apps/agents-server/src/app/admin/chat-history/ChatHistoryTable.tsx +13 -8
  6. package/apps/agents-server/src/app/admin/custom-css/CustomCssClient.tsx +4 -0
  7. package/apps/agents-server/src/app/admin/custom-css/CustomCssEditorPanel.tsx +7 -1
  8. package/apps/agents-server/src/app/admin/custom-css/CustomCssFilesPanel.tsx +7 -1
  9. package/apps/agents-server/src/app/admin/custom-js/CustomJsClient.tsx +4 -0
  10. package/apps/agents-server/src/app/admin/custom-js/CustomJsEditorPanel.tsx +7 -1
  11. package/apps/agents-server/src/app/admin/custom-js/CustomJsFilesPanel.tsx +7 -1
  12. package/apps/agents-server/src/app/admin/files/FilesGalleryClient.tsx +4 -0
  13. package/apps/agents-server/src/app/admin/files/FilesGalleryGrid.tsx +9 -11
  14. package/apps/agents-server/src/app/admin/files/FilesGalleryTable.tsx +9 -8
  15. package/apps/agents-server/src/app/admin/images/ImagesGalleryClient.tsx +4 -0
  16. package/apps/agents-server/src/app/admin/images/ImagesGalleryGrid.tsx +16 -11
  17. package/apps/agents-server/src/app/admin/images/ImagesGalleryTable.tsx +18 -9
  18. package/apps/agents-server/src/app/admin/login-methods/shibboleth/page.tsx +9 -9
  19. package/apps/agents-server/src/app/admin/messages/MessagesClient.tsx +7 -6
  20. package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +11 -10
  21. package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +4 -2
  22. package/apps/agents-server/src/app/admin/task-manager/TaskManagerTaskRow.tsx +14 -15
  23. package/apps/agents-server/src/app/admin/task-manager/TaskManagerTasksCard.tsx +4 -1
  24. package/apps/agents-server/src/app/admin/task-manager/useTaskManagerState.ts +6 -9
  25. package/apps/agents-server/src/app/admin/update/CustomCommitPicker.tsx +258 -0
  26. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +305 -108
  27. package/apps/agents-server/src/app/admin/usage/UsageClient.tsx +4 -2
  28. package/apps/agents-server/src/app/admin/usage/UsageClientAnalyticsPanels.tsx +6 -4
  29. package/apps/agents-server/src/app/admin/usage/UsageClientFormatting.ts +6 -12
  30. package/apps/agents-server/src/app/admin/usage/UsageClientTimelineChart.tsx +6 -3
  31. package/apps/agents-server/src/app/admin/usage/useUsageClientState.ts +12 -4
  32. package/apps/agents-server/src/app/admin/users/[userId]/UserDetailClient.tsx +8 -3
  33. package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +6 -20
  34. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +2 -0
  35. package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorHistory.ts +9 -2
  36. package/apps/agents-server/src/app/agents/[agentName]/chat/useAgentChatHistoryClientState.ts +2 -15
  37. package/apps/agents-server/src/app/agents/[agentName]/history/page.tsx +6 -1
  38. package/apps/agents-server/src/app/agents/[agentName]/integration/CalendarIntegrationSection.tsx +23 -5
  39. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsClient.tsx +4 -2
  40. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsFiltersCard.tsx +9 -4
  41. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableCard.tsx +4 -1
  42. package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableRow.tsx +10 -3
  43. package/apps/agents-server/src/app/api/admin/update/commits/route.ts +35 -0
  44. package/apps/agents-server/src/app/api/admin/update/route.ts +10 -2
  45. package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +5 -0
  46. package/apps/agents-server/src/app/api/internal/user-chat-jobs/run/route.ts +14 -2
  47. package/apps/agents-server/src/app/api/v1/agents/[agentId]/route.ts +4 -0
  48. package/apps/agents-server/src/app/api/v1/agents/route.ts +2 -0
  49. package/apps/agents-server/src/app/dashboard/page.tsx +11 -16
  50. package/apps/agents-server/src/app/recycle-bin/actions.ts +3 -0
  51. package/apps/agents-server/src/app/swagger/SwaggerApiKeysPanel.tsx +4 -1
  52. package/apps/agents-server/src/app/system/user-memory/UserMemoryClient.tsx +4 -2
  53. package/apps/agents-server/src/app/system/user-wallet/UserWalletClient.tsx +3 -0
  54. package/apps/agents-server/src/app/system/user-wallet/UserWalletRecordsTable.tsx +5 -1
  55. package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorClient.tsx +3 -0
  56. package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorSidebar.tsx +7 -8
  57. package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -2
  58. package/apps/agents-server/src/components/UsersList/UsersList.tsx +4 -2
  59. package/apps/agents-server/src/database/migrations/2026-06-2600-agent-directory-performance-indexes.sql +14 -0
  60. package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +92 -1
  61. package/apps/agents-server/src/tools/createAgentProgressTools.ts +8 -6
  62. package/apps/agents-server/src/utils/localization/formatServerLanguageHumanReadableDate.ts +70 -0
  63. package/apps/agents-server/src/utils/localization/getRequestServerLanguage.ts +32 -0
  64. package/apps/agents-server/src/utils/userChat/createRunUserChatJobExecutionContext.ts +17 -0
  65. package/apps/agents-server/src/utils/userChat/createRunUserChatJobPersistenceController.ts +0 -21
  66. package/apps/agents-server/src/utils/userChat/listUserChats.ts +5 -1
  67. package/apps/agents-server/src/utils/userChat/persistUserChatJobProgressCard.ts +31 -0
  68. package/apps/agents-server/src/utils/userChat/retryUserChatJob.ts +0 -4
  69. package/apps/agents-server/src/utils/userChat/runUserChatJob.ts +29 -0
  70. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +2 -2
  71. package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +99 -401
  72. package/apps/agents-server/src/utils/vpsSelfUpdate.ts +625 -51
  73. package/esm/index.es.js +252 -41
  74. package/esm/index.es.js.map +1 -1
  75. package/esm/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
  76. package/esm/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
  77. package/esm/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
  78. package/esm/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
  79. package/esm/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
  80. package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
  81. package/esm/src/book-3.0/cliAgentEnv.d.ts +1 -1
  82. package/esm/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
  83. package/esm/src/version.d.ts +1 -1
  84. package/package.json +1 -1
  85. package/src/book-3.0/cliAgentEnv.ts +1 -1
  86. package/src/cli/cli-commands/agents-server/startAgentsServer.ts +1 -1
  87. package/src/cli/cli-commands/coder/ThinkingLevel.ts +3 -1
  88. package/src/other/templates/getTemplatesPipelineCollection.ts +911 -741
  89. package/src/version.ts +2 -2
  90. package/src/versions.txt +2 -0
  91. package/umd/index.umd.js +254 -44
  92. package/umd/index.umd.js.map +1 -1
  93. package/umd/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
  94. package/umd/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
  95. package/umd/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
  96. package/umd/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
  97. package/umd/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
  98. package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
  99. package/umd/src/book-3.0/cliAgentEnv.d.ts +1 -1
  100. package/umd/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
  101. package/umd/src/version.d.ts +1 -1
@@ -0,0 +1,70 @@
1
+ import moment from 'moment';
2
+ import type { ServerLanguageCode } from '../../languages/ServerLanguageRegistry';
3
+ import { createServerLanguageMoment } from './createServerLanguageMoment';
4
+
5
+ /**
6
+ * Default fallback for missing date values.
7
+ *
8
+ * @private internal constant of `formatServerLanguageHumanReadableDate`
9
+ */
10
+ const DEFAULT_FALLBACK_LABEL = 'N/A';
11
+
12
+ /**
13
+ * Default localized exact-date format appended when requested.
14
+ *
15
+ * @private internal constant of `formatServerLanguageHumanReadableDate`
16
+ */
17
+ const DEFAULT_EXACT_DATE_FORMAT = 'L LT';
18
+
19
+ /**
20
+ * Options for localized human-readable date formatting.
21
+ *
22
+ * @private internal type of `formatServerLanguageHumanReadableDate`
23
+ */
24
+ type FormatServerLanguageHumanReadableDateOptions = {
25
+ /**
26
+ * Text returned when the date value is empty.
27
+ */
28
+ readonly fallbackLabel?: string;
29
+
30
+ /**
31
+ * Whether to append the localized exact timestamp after the relative label.
32
+ */
33
+ readonly isExactDateIncluded?: boolean;
34
+ };
35
+
36
+ /**
37
+ * Formats one timestamp for the active Agents Server language.
38
+ *
39
+ * @param value - Date-like value, usually an ISO timestamp from the database.
40
+ * @param language - Active Agents Server language code.
41
+ * @param options - Formatting options.
42
+ * @returns Localized relative date label, with optional exact timestamp.
43
+ * @private internal utility for Agents Server UI.
44
+ */
45
+ export function formatServerLanguageHumanReadableDate(
46
+ value: moment.MomentInput | null | undefined,
47
+ language: ServerLanguageCode,
48
+ options: FormatServerLanguageHumanReadableDateOptions = {},
49
+ ): string {
50
+ const fallbackLabel = options.fallbackLabel ?? DEFAULT_FALLBACK_LABEL;
51
+
52
+ if (value === null || value === undefined || value === '') {
53
+ return fallbackLabel;
54
+ }
55
+
56
+ const localizedMoment =
57
+ typeof value === 'string'
58
+ ? moment(value, moment.ISO_8601, true).locale(language)
59
+ : createServerLanguageMoment(value, language);
60
+ if (!localizedMoment.isValid()) {
61
+ return typeof value === 'string' ? value : fallbackLabel;
62
+ }
63
+
64
+ const relativeLabel = localizedMoment.fromNow();
65
+ if (!options.isExactDateIncluded) {
66
+ return relativeLabel;
67
+ }
68
+
69
+ return `${relativeLabel} (${localizedMoment.format(DEFAULT_EXACT_DATE_FORMAT)})`;
70
+ }
@@ -0,0 +1,32 @@
1
+ import { cookies } from 'next/headers';
2
+ import { getMetadataMap } from '../../database/getMetadata';
3
+ import {
4
+ IS_SERVER_LANGUAGE_ENFORCED_METADATA_KEY,
5
+ parseServerLanguageEnforcedMetadata,
6
+ resolveServerLanguageCode,
7
+ SERVER_LANGUAGE_COOKIE_NAME,
8
+ SERVER_LANGUAGE_METADATA_KEY,
9
+ type ServerLanguageCode,
10
+ } from '../../languages/ServerLanguageRegistry';
11
+
12
+ /**
13
+ * Resolves the active Agents Server UI language for the current server-rendered request.
14
+ *
15
+ * @returns Active server language code derived from metadata and the language override cookie.
16
+ * @private internal utility for server-rendered Agents Server UI.
17
+ */
18
+ export async function getRequestServerLanguage(): Promise<ServerLanguageCode> {
19
+ const [metadata, cookieStore] = await Promise.all([
20
+ getMetadataMap([SERVER_LANGUAGE_METADATA_KEY, IS_SERVER_LANGUAGE_ENFORCED_METADATA_KEY]),
21
+ cookies(),
22
+ ]);
23
+
24
+ const cookieLanguage = cookieStore.get(SERVER_LANGUAGE_COOKIE_NAME)?.value || null;
25
+ const rawServerLanguage = metadata[SERVER_LANGUAGE_METADATA_KEY];
26
+ const isServerLanguageEnforced = parseServerLanguageEnforcedMetadata(
27
+ metadata[IS_SERVER_LANGUAGE_ENFORCED_METADATA_KEY],
28
+ );
29
+ const preferredLanguageSource = isServerLanguageEnforced ? rawServerLanguage : cookieLanguage || rawServerLanguage;
30
+
31
+ return resolveServerLanguageCode(preferredLanguageSource);
32
+ }
@@ -27,6 +27,7 @@ import type { ChatMessage, ChatPrompt, LlmToolDefinition, ToolCall } from '@prom
27
27
  import { resolveTeamInternalAgentAccessToken } from '../../../../../src/commitments/_common/teamInternalAgentAccess';
28
28
  import type { ChatPromptResult } from '../../../../../src/execution/PromptResult';
29
29
  import { createUserChatMessagePrompt } from './createUserChatMessagePrompt';
30
+ import type { UserChatProgressPhase } from './userChatProgressCard';
30
31
  import type { UserChatJobRecord } from './UserChatJobRecord';
31
32
 
32
33
  /**
@@ -53,6 +54,11 @@ type RunUserChatJobPromptSnapshotFactory = (
53
54
  },
54
55
  ) => NonNullable<ChatMessage['prompt']>;
55
56
 
57
+ /**
58
+ * Reports one user-facing durable chat progress phase.
59
+ */
60
+ type RunUserChatJobProgressReporter = (phase: UserChatProgressPhase) => Promise<void>;
61
+
56
62
  /**
57
63
  * Prepares the full agent/runtime context required to execute one durable user chat job.
58
64
  *
@@ -67,12 +73,18 @@ export async function createRunUserChatJobExecutionContext(options: {
67
73
  userMessageAttachments: ChatMessage['attachments'];
68
74
  thread: NonNullable<ChatPrompt['thread']>;
69
75
  promptContent: ChatPrompt['content'];
76
+ reportProgress?: RunUserChatJobProgressReporter;
70
77
  }) {
78
+ await options.reportProgress?.('reading_context');
79
+
71
80
  const [localServerUrl, collection, baseAgentReferenceResolver] = await Promise.all([
72
81
  resolveCurrentOrInternalServerOrigin(),
73
82
  $provideAgentCollectionForServer(),
74
83
  $provideAgentReferenceResolver(),
75
84
  ]);
85
+
86
+ await options.reportProgress?.('preparing_agent');
87
+
76
88
  const resolvedAgentContext = await resolveCachedServerAgentContext({
77
89
  collection,
78
90
  agentIdentifier: options.job.agentPermanentId,
@@ -91,6 +103,9 @@ export async function createRunUserChatJobExecutionContext(options: {
91
103
  const projectRepositories = extractProjectRepositoriesFromAgentSource(agentSource);
92
104
  const calendarConnections = extractUseCalendarConnectionsFromAgentSource(agentSource);
93
105
  const useEmailConfiguration = extractUseEmailConfigurationFromAgentSource(agentSource);
106
+
107
+ await options.reportProgress?.('checking_capabilities');
108
+
94
109
  const { projectGithubToken, calendarGoogleAccessToken, emailSmtpCredential } =
95
110
  await resolveRunUserChatJobCredentials({
96
111
  userId: options.job.userId,
@@ -164,6 +179,8 @@ export async function createRunUserChatJobExecutionContext(options: {
164
179
  });
165
180
  }
166
181
 
182
+ await options.reportProgress?.('starting_response');
183
+
167
184
  const agentKitResult = await agentKitCacheManager.getOrCreateAgentKitAgent(
168
185
  agentSource,
169
186
  resolvedAgentName,
@@ -4,7 +4,6 @@ import type { ChatPromptResult } from '../../../../../src/execution/PromptResult
4
4
  import { mergeToolCalls } from '../../../../../src/utils/toolCalls/mergeToolCalls';
5
5
  import { persistUserChatJobTerminalState } from './persistUserChatJobTerminalState';
6
6
  import { updateUserChatAssistantMessage } from './updateUserChatAssistantMessage';
7
- import { createRunningUserChatProgressCard } from './userChatProgressCard';
8
7
  import { USER_CHAT_JOB_ASSISTANT_MESSAGE_PERSIST_INTERVAL_MS } from './userChatJobRuntimeConstants';
9
8
  import type { UserChatJobRecord } from './UserChatJobRecord';
10
9
 
@@ -45,14 +44,6 @@ export function createRunUserChatJobPersistenceController(options: {
45
44
  let hasPendingAssistantMessageUpdate = false;
46
45
  let assistantMessageUpdateTimeout: ReturnType<typeof setTimeout> | null = null;
47
46
 
48
- /**
49
- * Creates a typed ISO timestamp for progress-card updates.
50
- *
51
- * @private function of `createRunUserChatJobPersistenceController`
52
- */
53
- const createProgressUpdatedAt = (): NonNullable<ChatMessage['progressCard']>['updatedAt'] =>
54
- new Date().toISOString() as NonNullable<ChatMessage['progressCard']>['updatedAt'];
55
-
56
47
  /**
57
48
  * Queues one assistant-message mutation behind any earlier persistence work.
58
49
  *
@@ -141,12 +132,6 @@ export function createRunUserChatJobPersistenceController(options: {
141
132
  lifecycleState: 'running',
142
133
  lifecycleError: undefined,
143
134
  isComplete: false,
144
- progressCard: createRunningUserChatProgressCard({
145
- currentProgressCard: message.progressCard,
146
- content: latestContent,
147
- toolCalls: latestToolCalls,
148
- updatedAt: createProgressUpdatedAt(),
149
- }),
150
135
  prompt: options.createPromptSnapshot({
151
136
  toolCalls: latestToolCalls,
152
137
  }),
@@ -201,12 +186,6 @@ export function createRunUserChatJobPersistenceController(options: {
201
186
  lifecycleState: 'running',
202
187
  lifecycleError: undefined,
203
188
  isComplete: false,
204
- progressCard: createRunningUserChatProgressCard({
205
- currentProgressCard: message.progressCard,
206
- content: latestContent,
207
- toolCalls: latestToolCalls,
208
- updatedAt: createProgressUpdatedAt(),
209
- }),
210
189
  availableTools: options.availableTools,
211
190
  prompt: options.createPromptSnapshot(),
212
191
  }),
@@ -2,6 +2,7 @@ import { $getTableName } from '@/src/database/$getTableName';
2
2
  import { $provideClientSql } from '@/src/database/$provideClientSql';
3
3
  import { isAgentsServerSqliteMode } from '@/src/database/agentsServerDatabaseMode';
4
4
  import { $provideAgentsServerSqliteDatabase } from '@/src/database/sqlite/$provideAgentsServerSqliteDatabase';
5
+ import { ensureLocalSqliteTableReadIndexes } from '@/src/database/sqlite/$provideLocalSqliteSupabase';
5
6
  import type { ListUserChatsOptions, UserChatRecord } from './UserChatRecord';
6
7
  import type { UserChatSource } from './UserChatSource';
7
8
  import type { UserChatRow } from './UserChatRow';
@@ -168,7 +169,10 @@ export async function listUserChatSummarySeeds(options: ListUserChatsOptions): P
168
169
  * @private function of `userChat`
169
170
  */
170
171
  async function listUserChatSummarySeedsViaSqlite(options: ListUserChatsOptions): Promise<Array<UserChatSummarySeed>> {
171
- const userChatTableName = quoteIdentifier(await $getTableName('UserChat'));
172
+ const rawUserChatTableName = await $getTableName('UserChat');
173
+ ensureLocalSqliteTableReadIndexes(rawUserChatTableName);
174
+
175
+ const userChatTableName = quoteIdentifier(rawUserChatTableName);
172
176
  const shouldLoadExternalChats = options.viewerIsAdmin && options.includeExternalChats;
173
177
  const whereClause = shouldLoadExternalChats
174
178
  ? `
@@ -0,0 +1,31 @@
1
+ import { createUserChatProgressCard, type UserChatProgressPhase } from './userChatProgressCard';
2
+ import { updateUserChatAssistantMessage } from './updateUserChatAssistantMessage';
3
+
4
+ /**
5
+ * Persists one durable chat progress phase onto the active assistant placeholder.
6
+ */
7
+ export async function persistUserChatJobProgressCard(options: {
8
+ readonly userId: number;
9
+ readonly agentPermanentId: string;
10
+ readonly chatId: string;
11
+ readonly assistantMessageId: string;
12
+ readonly phase: UserChatProgressPhase;
13
+ }): Promise<void> {
14
+ await updateUserChatAssistantMessage({
15
+ userId: options.userId,
16
+ agentPermanentId: options.agentPermanentId,
17
+ chatId: options.chatId,
18
+ assistantMessageId: options.assistantMessageId,
19
+ mutateMessage: (message) => {
20
+ const lifecycleState = options.phase === 'queued' ? 'queued' : 'running';
21
+
22
+ return {
23
+ ...message,
24
+ lifecycleState,
25
+ lifecycleError: undefined,
26
+ isComplete: false,
27
+ progressCard: createUserChatProgressCard(options.phase),
28
+ };
29
+ },
30
+ });
31
+ }
@@ -1,13 +1,11 @@
1
1
  import type { UserChatJobRecord } from './UserChatJobRecord';
2
2
  import type { UserChatJobRow } from './UserChatJobRow';
3
3
  import type { Json } from '@/src/database/schema';
4
- import type { ChatMessage } from '@promptbook-local/types';
5
4
  import { withoutLocalUserChatJobMetadata } from '../localChatRunner/LocalUserChatJobMetadata';
6
5
  import { getUserChatJobById } from './getUserChatJobById';
7
6
  import { mapUserChatJobRow } from './mapUserChatJobRow';
8
7
  import { provideUserChatJobTable } from './provideUserChatJobTable';
9
8
  import { updateUserChatAssistantMessage } from './updateUserChatAssistantMessage';
10
- import { createQueuedUserChatProgressCard } from './userChatProgressCard';
11
9
 
12
10
  /**
13
11
  * Requeues one failed durable chat job and resets its assistant placeholder.
@@ -25,7 +23,6 @@ export async function retryUserChatJob(jobId: string): Promise<UserChatJobRecord
25
23
  }
26
24
 
27
25
  const nowIso = new Date().toISOString();
28
- const progressUpdatedAt = nowIso as NonNullable<ChatMessage['progressCard']>['updatedAt'];
29
26
  const userChatJobTable = await provideUserChatJobTable();
30
27
  const { data, error } = await userChatJobTable
31
28
  .update({
@@ -70,7 +67,6 @@ export async function retryUserChatJob(jobId: string): Promise<UserChatJobRecord
70
67
  completedToolCalls: undefined,
71
68
  prompt: undefined,
72
69
  generationDurationMs: undefined,
73
- progressCard: createQueuedUserChatProgressCard(progressUpdatedAt),
74
70
  }),
75
71
  });
76
72
 
@@ -20,7 +20,9 @@ import { finalizeUserChatJob } from './finalizeUserChatJob';
20
20
  import { getUserChat } from './getUserChat';
21
21
  import { heartbeatUserChatJob } from './heartbeatUserChatJob';
22
22
  import { persistUserChatJobTerminalState } from './persistUserChatJobTerminalState';
23
+ import { persistUserChatJobProgressCard } from './persistUserChatJobProgressCard';
23
24
  import type { UserChatJobRecord } from './UserChatJobRecord';
25
+ import type { UserChatProgressPhase } from './userChatProgressCard';
24
26
  import { createReplyAwareUserChatPromptContent, createReplyAwareUserChatPromptMessage } from './userChatReplies';
25
27
  import { resolvePromptThreadBeforeUserMessage } from './userChatMessageLifecycle';
26
28
  import { isUserChatNotFoundScopeError } from './UserChatScopeError';
@@ -107,6 +109,7 @@ export async function runUserChatJob(job: UserChatJobRecord): Promise<RunUserCha
107
109
  const executionContext = await createRunUserChatJobExecutionContext({
108
110
  job,
109
111
  ...startContext,
112
+ reportProgress: createRunUserChatJobProgressReporter(job),
110
113
  });
111
114
 
112
115
  return await executeRunUserChatJob({
@@ -122,6 +125,32 @@ export async function runUserChatJob(job: UserChatJobRecord): Promise<RunUserCha
122
125
  }
123
126
  }
124
127
 
128
+ /**
129
+ * Creates a non-critical progress reporter for one durable chat job.
130
+ *
131
+ * @private function of `runUserChatJob`
132
+ */
133
+ function createRunUserChatJobProgressReporter(
134
+ job: Pick<UserChatJobRecord, 'userId' | 'agentPermanentId' | 'chatId' | 'assistantMessageId' | 'id'>,
135
+ ): (phase: UserChatProgressPhase) => Promise<void> {
136
+ return async (phase) => {
137
+ await persistUserChatJobProgressCard({
138
+ userId: job.userId,
139
+ agentPermanentId: job.agentPermanentId,
140
+ chatId: job.chatId,
141
+ assistantMessageId: job.assistantMessageId,
142
+ phase,
143
+ }).catch((error) => {
144
+ console.warn('[user-chat-job] progress_update_failed', {
145
+ chatId: job.chatId,
146
+ jobId: job.id,
147
+ phase,
148
+ error,
149
+ });
150
+ });
151
+ };
152
+ }
153
+
125
154
  /**
126
155
  * Loads and validates the chat/user/message snapshot required before one job can start.
127
156
  *
@@ -1,5 +1,5 @@
1
1
  import type { ChatMessage } from '../../../../../src/_packages/types.index';
2
- import { createQueuedUserChatProgressCard } from './userChatProgressCard';
2
+ import { createUserChatProgressCard } from './userChatProgressCard';
3
3
 
4
4
  /**
5
5
  * Lifecycle states rendered on canonical server-owned chat messages.
@@ -46,7 +46,7 @@ export function createQueuedUserChatAssistantMessage(options: {
46
46
  isComplete: false,
47
47
  lifecycleState: 'queued',
48
48
  jobId: options.jobId,
49
- progressCard: createQueuedUserChatProgressCard(options.createdAt),
49
+ progressCard: createUserChatProgressCard('queued'),
50
50
  };
51
51
  }
52
52