@promptbook/cli 0.112.0-131 → 0.112.0-133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/agents-server/src/app/admin/api-tokens/ApiTokensClient.tsx +4 -1
- package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackClient.tsx +3 -0
- package/apps/agents-server/src/app/admin/chat-feedback/ChatFeedbackTable.tsx +13 -8
- package/apps/agents-server/src/app/admin/chat-history/ChatHistoryClient.tsx +3 -0
- package/apps/agents-server/src/app/admin/chat-history/ChatHistoryTable.tsx +13 -8
- package/apps/agents-server/src/app/admin/custom-css/CustomCssClient.tsx +4 -0
- package/apps/agents-server/src/app/admin/custom-css/CustomCssEditorPanel.tsx +7 -1
- package/apps/agents-server/src/app/admin/custom-css/CustomCssFilesPanel.tsx +7 -1
- package/apps/agents-server/src/app/admin/custom-js/CustomJsClient.tsx +11 -0
- package/apps/agents-server/src/app/admin/custom-js/CustomJsEditorPanel.tsx +7 -1
- package/apps/agents-server/src/app/admin/custom-js/CustomJsFilesPanel.tsx +7 -1
- package/apps/agents-server/src/app/admin/files/FilesGalleryClient.tsx +4 -0
- package/apps/agents-server/src/app/admin/files/FilesGalleryGrid.tsx +9 -11
- package/apps/agents-server/src/app/admin/files/FilesGalleryTable.tsx +9 -8
- package/apps/agents-server/src/app/admin/images/ImagesGalleryClient.tsx +4 -0
- package/apps/agents-server/src/app/admin/images/ImagesGalleryGrid.tsx +16 -11
- package/apps/agents-server/src/app/admin/images/ImagesGalleryTable.tsx +18 -9
- package/apps/agents-server/src/app/admin/login-methods/shibboleth/page.tsx +9 -9
- package/apps/agents-server/src/app/admin/messages/MessagesClient.tsx +7 -6
- package/apps/agents-server/src/app/admin/servers/ServersRegistryTable.tsx +11 -10
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +4 -2
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerTaskRow.tsx +14 -15
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerTasksCard.tsx +4 -1
- package/apps/agents-server/src/app/admin/task-manager/useTaskManagerState.ts +6 -9
- package/apps/agents-server/src/app/admin/update/CustomCommitPicker.tsx +258 -0
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +305 -108
- package/apps/agents-server/src/app/admin/usage/UsageClient.tsx +4 -2
- package/apps/agents-server/src/app/admin/usage/UsageClientAnalyticsPanels.tsx +6 -4
- package/apps/agents-server/src/app/admin/usage/UsageClientFormatting.ts +6 -12
- package/apps/agents-server/src/app/admin/usage/UsageClientTimelineChart.tsx +6 -3
- package/apps/agents-server/src/app/admin/usage/useUsageClientState.ts +12 -4
- package/apps/agents-server/src/app/admin/users/[userId]/UserDetailClient.tsx +8 -3
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +6 -20
- package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorHistory.ts +9 -2
- package/apps/agents-server/src/app/agents/[agentName]/chat/useAgentChatHistoryClientState.ts +2 -15
- package/apps/agents-server/src/app/agents/[agentName]/history/page.tsx +6 -1
- package/apps/agents-server/src/app/agents/[agentName]/integration/CalendarIntegrationSection.tsx +23 -5
- package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsClient.tsx +4 -2
- package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsFiltersCard.tsx +9 -4
- package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableCard.tsx +4 -1
- package/apps/agents-server/src/app/agents/[agentName]/timeouts/AgentTimeoutsTableRow.tsx +10 -3
- package/apps/agents-server/src/app/api/admin/update/commits/route.ts +35 -0
- package/apps/agents-server/src/app/api/admin/update/route.ts +10 -2
- package/apps/agents-server/src/app/api/internal/user-chat-jobs/run/route.ts +14 -2
- package/apps/agents-server/src/app/dashboard/page.tsx +11 -16
- package/apps/agents-server/src/app/layout.tsx +12 -3
- package/apps/agents-server/src/app/swagger/SwaggerApiKeysPanel.tsx +4 -1
- package/apps/agents-server/src/app/system/user-memory/UserMemoryClient.tsx +4 -2
- package/apps/agents-server/src/app/system/user-wallet/UserWalletClient.tsx +3 -0
- package/apps/agents-server/src/app/system/user-wallet/UserWalletRecordsTable.tsx +5 -1
- package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorClient.tsx +3 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/MockedChatsEditorSidebar.tsx +7 -8
- package/apps/agents-server/src/components/Footer/Footer.tsx +3 -2
- package/apps/agents-server/src/components/Footer/getCommitFooterEmoji.ts +112 -0
- package/apps/agents-server/src/components/PrintHeader/PrintHeader.tsx +4 -2
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +4 -2
- package/apps/agents-server/src/languages/translations/czech.yaml +1 -1
- package/apps/agents-server/src/languages/translations/english.yaml +1 -1
- package/apps/agents-server/src/middleware/applyEmbeddingHeader.ts +4 -2
- package/apps/agents-server/src/middleware/contentSecurityPolicy.ts +97 -0
- package/apps/agents-server/src/tools/createAgentProgressTools.ts +8 -6
- package/apps/agents-server/src/utils/localization/formatServerLanguageHumanReadableDate.ts +70 -0
- package/apps/agents-server/src/utils/localization/getRequestServerLanguage.ts +32 -0
- package/apps/agents-server/src/utils/userChat/createRunUserChatJobExecutionContext.ts +17 -0
- package/apps/agents-server/src/utils/userChat/createRunUserChatJobPersistenceController.ts +0 -21
- package/apps/agents-server/src/utils/userChat/persistUserChatJobProgressCard.ts +31 -0
- package/apps/agents-server/src/utils/userChat/retryUserChatJob.ts +0 -4
- package/apps/agents-server/src/utils/userChat/runUserChatJob.ts +29 -0
- package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +2 -2
- package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +99 -401
- package/apps/agents-server/src/utils/vpsSelfUpdate.ts +625 -51
- package/esm/index.es.js +252 -41
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
- package/esm/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
- package/esm/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
- package/esm/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
- package/esm/src/book-3.0/cliAgentEnv.d.ts +1 -1
- package/esm/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-3.0/cliAgentEnv.ts +1 -1
- package/src/cli/cli-commands/agents-server/startAgentsServer.ts +1 -1
- package/src/cli/cli-commands/coder/ThinkingLevel.ts +3 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +681 -766
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +254 -44
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +5 -1
- package/umd/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/common/coderRunEstimateCache.d.ts +31 -0
- package/umd/scripts/run-codex-prompts/common/progressFormatting.d.ts +2 -0
- package/umd/scripts/run-codex-prompts/runners/claude-code/ClaudeCodeRunner.d.ts +3 -1
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +7 -0
- package/umd/src/book-3.0/cliAgentEnv.d.ts +1 -1
- package/umd/src/cli/cli-commands/coder/ThinkingLevel.d.ts +1 -1
- package/umd/src/version.d.ts +1 -1
|
@@ -4,6 +4,8 @@ import type {
|
|
|
4
4
|
UsageCallType,
|
|
5
5
|
UsageMetricMode,
|
|
6
6
|
} from '@/src/utils/usageAdmin';
|
|
7
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
8
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Source shape with metric values used across usage widgets.
|
|
@@ -90,20 +92,12 @@ export const UsageClientFormatting = {
|
|
|
90
92
|
return usageCompactFormatter.format(value);
|
|
91
93
|
},
|
|
92
94
|
|
|
93
|
-
formatDateTime(iso: string): string {
|
|
94
|
-
|
|
95
|
-
if (Number.isNaN(date.getTime())) {
|
|
96
|
-
return iso;
|
|
97
|
-
}
|
|
98
|
-
return date.toLocaleString();
|
|
95
|
+
formatDateTime(iso: string, language: ServerLanguageCode): string {
|
|
96
|
+
return formatServerLanguageHumanReadableDate(iso, language);
|
|
99
97
|
},
|
|
100
98
|
|
|
101
|
-
formatShortDate(iso: string): string {
|
|
102
|
-
|
|
103
|
-
if (Number.isNaN(date.getTime())) {
|
|
104
|
-
return iso;
|
|
105
|
-
}
|
|
106
|
-
return date.toLocaleDateString();
|
|
99
|
+
formatShortDate(iso: string, language: ServerLanguageCode): string {
|
|
100
|
+
return formatServerLanguageHumanReadableDate(iso, language);
|
|
107
101
|
},
|
|
108
102
|
|
|
109
103
|
isIsoDateInputValue(value: string): boolean {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
1
2
|
import type { UsageAnalyticsResponse, UsageMetricMode } from '@/src/utils/usageAdmin';
|
|
2
3
|
import { useMemo } from 'react';
|
|
3
4
|
import { UsageClientFormatting } from './UsageClientFormatting';
|
|
@@ -24,6 +25,7 @@ type UsageClientTimelinePoint = {
|
|
|
24
25
|
* Props for `<UsageClientTimelineChart/>`.
|
|
25
26
|
*/
|
|
26
27
|
type UsageClientTimelineChartProps = {
|
|
28
|
+
language: ServerLanguageCode;
|
|
27
29
|
points: UsageAnalyticsResponse['timeline'];
|
|
28
30
|
metric: UsageMetricMode;
|
|
29
31
|
};
|
|
@@ -34,7 +36,7 @@ type UsageClientTimelineChartProps = {
|
|
|
34
36
|
* @private function of UsageClient
|
|
35
37
|
*/
|
|
36
38
|
export function UsageClientTimelineChart(props: UsageClientTimelineChartProps) {
|
|
37
|
-
const { points, metric } = props;
|
|
39
|
+
const { language, points, metric } = props;
|
|
38
40
|
|
|
39
41
|
const chartGeometry = useMemo(() => {
|
|
40
42
|
const paddedWidth = TIMELINE_WIDTH;
|
|
@@ -73,11 +75,12 @@ export function UsageClientTimelineChart(props: UsageClientTimelineChartProps) {
|
|
|
73
75
|
|
|
74
76
|
const linePath = toLinePath(chartGeometry.coordinates);
|
|
75
77
|
const areaPath = toAreaPath(chartGeometry.coordinates, chartGeometry.height - chartGeometry.paddingY);
|
|
76
|
-
const firstLabel = UsageClientFormatting.formatShortDate(points[0].bucketStart);
|
|
78
|
+
const firstLabel = UsageClientFormatting.formatShortDate(points[0].bucketStart, language);
|
|
77
79
|
const middleLabel = UsageClientFormatting.formatShortDate(
|
|
78
80
|
points[Math.floor(points.length / 2)]?.bucketStart || points[0].bucketStart,
|
|
81
|
+
language,
|
|
79
82
|
);
|
|
80
|
-
const lastLabel = UsageClientFormatting.formatShortDate(points[points.length - 1].bucketStart);
|
|
83
|
+
const lastLabel = UsageClientFormatting.formatShortDate(points[points.length - 1].bucketStart, language);
|
|
81
84
|
|
|
82
85
|
return (
|
|
83
86
|
<div>
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
type UsageMetricMode,
|
|
9
9
|
type UsageTimeframePreset,
|
|
10
10
|
} from '@/src/utils/usageAdmin';
|
|
11
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
11
12
|
import { usePathname, useRouter } from 'next/navigation';
|
|
12
13
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
13
14
|
import { UsageClientFormatting } from './UsageClientFormatting';
|
|
@@ -142,13 +143,17 @@ function resolveUsageClientSelectedScopeLabel(
|
|
|
142
143
|
/**
|
|
143
144
|
* Resolves the human-readable timeframe range chip label.
|
|
144
145
|
*/
|
|
145
|
-
function resolveUsageClientTimeframeRangeLabel(
|
|
146
|
+
function resolveUsageClientTimeframeRangeLabel(
|
|
147
|
+
data: UsageAnalyticsResponse | null,
|
|
148
|
+
language: ServerLanguageCode,
|
|
149
|
+
): string | null {
|
|
146
150
|
if (!data) {
|
|
147
151
|
return null;
|
|
148
152
|
}
|
|
149
153
|
|
|
150
|
-
return `${UsageClientFormatting.formatDateTime(data.timeframe.from)} - ${UsageClientFormatting.formatDateTime(
|
|
154
|
+
return `${UsageClientFormatting.formatDateTime(data.timeframe.from, language)} - ${UsageClientFormatting.formatDateTime(
|
|
151
155
|
data.timeframe.to,
|
|
156
|
+
language,
|
|
152
157
|
)}`;
|
|
153
158
|
}
|
|
154
159
|
|
|
@@ -164,7 +169,10 @@ function resolveUsageClientAnalyticsErrorMessage(fetchError: unknown): string {
|
|
|
164
169
|
*
|
|
165
170
|
* @private function of <UsageClient/>
|
|
166
171
|
*/
|
|
167
|
-
export function useUsageClientState(
|
|
172
|
+
export function useUsageClientState(
|
|
173
|
+
props: UseUsageClientStateProps,
|
|
174
|
+
language: ServerLanguageCode,
|
|
175
|
+
): UseUsageClientStateResult {
|
|
168
176
|
const { agents, folders } = props;
|
|
169
177
|
const router = useRouter();
|
|
170
178
|
const pathname = usePathname();
|
|
@@ -271,7 +279,7 @@ export function useUsageClientState(props: UseUsageClientStateProps): UseUsageCl
|
|
|
271
279
|
[agentName, agents, folderId, folders],
|
|
272
280
|
);
|
|
273
281
|
|
|
274
|
-
const timeframeRangeLabel = useMemo(() => resolveUsageClientTimeframeRangeLabel(data), [data]);
|
|
282
|
+
const timeframeRangeLabel = useMemo(() => resolveUsageClientTimeframeRangeLabel(data, language), [data, language]);
|
|
275
283
|
|
|
276
284
|
const handleAgentNameChange = useCallback((value: string) => {
|
|
277
285
|
setAgentName(value);
|
|
@@ -7,6 +7,7 @@ import { Card } from '../../../../components/Homepage/Card';
|
|
|
7
7
|
import { Section } from '../../../../components/Homepage/Section';
|
|
8
8
|
import { useServerLanguage } from '../../../../components/ServerLanguage/ServerLanguageProvider';
|
|
9
9
|
import { useUsersAdmin } from '../../../../components/UsersList/useUsersAdmin';
|
|
10
|
+
import { formatServerLanguageHumanReadableDate } from '../../../../utils/localization/formatServerLanguageHumanReadableDate';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Props for user detail client.
|
|
@@ -26,7 +27,7 @@ type UserDetailClientProps = {
|
|
|
26
27
|
*/
|
|
27
28
|
export function UserDetailClient({ userId }: UserDetailClientProps) {
|
|
28
29
|
const router = useRouter();
|
|
29
|
-
const { t } = useServerLanguage();
|
|
30
|
+
const { language, t } = useServerLanguage();
|
|
30
31
|
const { users, loading, error, deleteUser, toggleAdmin } = useUsersAdmin();
|
|
31
32
|
|
|
32
33
|
const user = useMemo(
|
|
@@ -108,11 +109,15 @@ export function UserDetailClient({ userId }: UserDetailClientProps) {
|
|
|
108
109
|
)}
|
|
109
110
|
<p className="text-gray-500 text-sm mt-1">
|
|
110
111
|
{t('users.createdAtLabel')}:{' '}
|
|
111
|
-
{
|
|
112
|
+
{formatServerLanguageHumanReadableDate(user.createdAt, language, {
|
|
113
|
+
fallbackLabel: t('users.unknownValue'),
|
|
114
|
+
})}
|
|
112
115
|
</p>
|
|
113
116
|
<p className="text-gray-500 text-sm mt-1">
|
|
114
117
|
{t('users.lastUpdatedLabel')}:{' '}
|
|
115
|
-
{
|
|
118
|
+
{formatServerLanguageHumanReadableDate(user.updatedAt, language, {
|
|
119
|
+
fallbackLabel: t('users.unknownValue'),
|
|
120
|
+
})}
|
|
116
121
|
</p>
|
|
117
122
|
</div>
|
|
118
123
|
<div className="space-x-2">
|
|
@@ -28,7 +28,7 @@ import type { ServerLanguageCode } from '../../../languages/ServerLanguageRegist
|
|
|
28
28
|
import { buildFreshAgentChatHref } from '../../../utils/agentRouting/agentRouteHrefs';
|
|
29
29
|
import { executeQuickActionButton } from '../../../utils/chat/executeQuickActionButton';
|
|
30
30
|
import { resolveChatMessageValidationIssue } from '../../../utils/chat/validateChatMessageContent';
|
|
31
|
-
import {
|
|
31
|
+
import { formatServerLanguageHumanReadableDate } from '../../../utils/localization/formatServerLanguageHumanReadableDate';
|
|
32
32
|
import { createDefaultSpeechRecognition } from '../../../utils/speech-to-text/createDefaultSpeechRecognition';
|
|
33
33
|
import { chatFileUploadHandler } from '../../../utils/upload/createBookEditorUploadHandler';
|
|
34
34
|
import { createUserChatClientMessageId, type UserChatSummary } from '../../../utils/userChatClient';
|
|
@@ -120,21 +120,6 @@ type OptimisticChatNavigationState = {
|
|
|
120
120
|
attachments?: ChatMessage['attachments'];
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
/**
|
|
124
|
-
* Parses one profile-chat timestamp using the active Agents Server language.
|
|
125
|
-
*
|
|
126
|
-
* @param timestamp - ISO string describing the chat update time.
|
|
127
|
-
* @param language - Active Agents Server language code.
|
|
128
|
-
* @returns Localized moment instance or `null` when the timestamp is invalid.
|
|
129
|
-
*/
|
|
130
|
-
function resolveProfileChatTimestampMoment(
|
|
131
|
-
timestamp: string,
|
|
132
|
-
language: ServerLanguageCode,
|
|
133
|
-
): ReturnType<typeof createServerLanguageMoment> | null {
|
|
134
|
-
const parsed = createServerLanguageMoment(timestamp, language);
|
|
135
|
-
return parsed.isValid() ? parsed : null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
123
|
/**
|
|
139
124
|
* Returns true when a message has non-whitespace content.
|
|
140
125
|
*/
|
|
@@ -643,9 +628,10 @@ function ExistingChatsPanel({
|
|
|
643
628
|
</div>
|
|
644
629
|
<div className="mt-4 space-y-3 overflow-y-auto pr-1" style={{ maxHeight: `${scrollViewportHeight}px` }}>
|
|
645
630
|
{chats.map((chat) => {
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
631
|
+
const fullTimeLabel = formatServerLanguageHumanReadableDate(chat.updatedAt, language, {
|
|
632
|
+
isExactDateIncluded: true,
|
|
633
|
+
});
|
|
634
|
+
const timeLabel = formatServerLanguageHumanReadableDate(chat.updatedAt, language);
|
|
649
635
|
const title = chat.title || formatText('Untitled chat');
|
|
650
636
|
const previewText = hasMessageContent(chat.preview)
|
|
651
637
|
? chat.preview
|
|
@@ -678,7 +664,7 @@ function ExistingChatsPanel({
|
|
|
678
664
|
</span>
|
|
679
665
|
</div>
|
|
680
666
|
<time
|
|
681
|
-
dateTime={
|
|
667
|
+
dateTime={chat.updatedAt}
|
|
682
668
|
title={fullTimeLabel}
|
|
683
669
|
className="text-[0.65rem] font-semibold text-slate-400 dark:text-slate-500"
|
|
684
670
|
>
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { string_book } from '@promptbook-local/types';
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { showAlert, showConfirm, showPrompt } from '@/src/components/AsyncDialogs/asyncDialogs';
|
|
4
|
+
import { useServerLanguage } from '@/src/components/ServerLanguage/ServerLanguageProvider';
|
|
5
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
6
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
4
7
|
import type { BookEditorHistoryVersionItem } from './BookEditorHistoryPanel';
|
|
5
8
|
import { resolveBookEditorApiErrorMessage } from './resolveBookEditorApiErrorMessage';
|
|
6
9
|
|
|
@@ -340,6 +343,7 @@ function resolveSelectedHistoryId<HistoryItem extends { readonly id: number }>(
|
|
|
340
343
|
*/
|
|
341
344
|
function buildHistoryVersionItems(
|
|
342
345
|
historyEntries: ReadonlyArray<AgentHistoryEntry>,
|
|
346
|
+
language: ServerLanguageCode,
|
|
343
347
|
): Array<BookEditorHistoryVersionItem> {
|
|
344
348
|
const totalVersions = historyEntries.length;
|
|
345
349
|
|
|
@@ -347,7 +351,9 @@ function buildHistoryVersionItems(
|
|
|
347
351
|
id: entry.id,
|
|
348
352
|
versionName: normalizeHistoryVersionName(entry.versionName),
|
|
349
353
|
versionLabel: `Version ${totalVersions - index}`,
|
|
350
|
-
createdAtLabel:
|
|
354
|
+
createdAtLabel: formatServerLanguageHumanReadableDate(entry.createdAt, language, {
|
|
355
|
+
isExactDateIncluded: true,
|
|
356
|
+
}),
|
|
351
357
|
hash: entry.agentHash,
|
|
352
358
|
hashPreview: entry.agentHash.slice(0, 8),
|
|
353
359
|
source: entry.agentSource,
|
|
@@ -800,6 +806,7 @@ export function useBookEditorHistory({
|
|
|
800
806
|
replaceWithRestoredSource,
|
|
801
807
|
requestDiagnostics,
|
|
802
808
|
}: UseBookEditorHistoryProps) {
|
|
809
|
+
const { language } = useServerLanguage();
|
|
803
810
|
const [isHistoryOpen, setIsHistoryOpen] = useState(false);
|
|
804
811
|
const [historyNameQuery, setHistoryNameQuery] = useState('');
|
|
805
812
|
const [isNamedHistoryOnly, setIsNamedHistoryOnly] = useState(false);
|
|
@@ -840,7 +847,7 @@ export function useBookEditorHistory({
|
|
|
840
847
|
*
|
|
841
848
|
* @private function of useBookEditorHistory
|
|
842
849
|
*/
|
|
843
|
-
const historyVersions = useMemo(() => buildHistoryVersionItems(historyEntries), [historyEntries]);
|
|
850
|
+
const historyVersions = useMemo(() => buildHistoryVersionItems(historyEntries, language), [historyEntries, language]);
|
|
844
851
|
|
|
845
852
|
/**
|
|
846
853
|
* Filtered history items matching the current panel controls.
|
package/apps/agents-server/src/app/agents/[agentName]/chat/useAgentChatHistoryClientState.ts
CHANGED
|
@@ -9,9 +9,8 @@ import { usePrivateModePreferences } from '../../../../components/PrivateModePre
|
|
|
9
9
|
import { useBrowserPushNotifications } from '../../../../components/PushNotifications/BrowserPushNotificationsProvider';
|
|
10
10
|
import { useServerLanguage } from '../../../../components/ServerLanguage/ServerLanguageProvider';
|
|
11
11
|
import { useActiveBrowserTab } from '../../../../hooks/useActiveBrowserTab';
|
|
12
|
-
import type { ServerLanguageCode } from '../../../../languages/ServerLanguageRegistry';
|
|
13
12
|
import type { ChatFeedbackMode } from '../../../../utils/chatFeedbackMode';
|
|
14
|
-
import {
|
|
13
|
+
import { formatServerLanguageHumanReadableDate } from '../../../../utils/localization/formatServerLanguageHumanReadableDate';
|
|
15
14
|
import { consumeShareTargetPayloadFromBrowser } from '../../../../utils/shareTargetClient';
|
|
16
15
|
import type { UserChatJob, UserChatSummary, UserChatTimeout } from '../../../../utils/userChatClient';
|
|
17
16
|
import { FORCE_NEW_CHAT_QUERY_VALUE } from '../agentChatNavigationUtils';
|
|
@@ -309,7 +308,7 @@ export function useAgentChatHistoryClientState(
|
|
|
309
308
|
useHoistedMobileMenuItems(hoistedMobileMenuItems);
|
|
310
309
|
|
|
311
310
|
const formatChatTimestamp = useCallback(
|
|
312
|
-
(timestamp: string): string =>
|
|
311
|
+
(timestamp: string): string => formatServerLanguageHumanReadableDate(timestamp, language),
|
|
313
312
|
[language],
|
|
314
313
|
);
|
|
315
314
|
|
|
@@ -359,15 +358,3 @@ function hasAutoExecutePayload(
|
|
|
359
358
|
): boolean {
|
|
360
359
|
return Boolean(message) || Boolean(attachments?.length);
|
|
361
360
|
}
|
|
362
|
-
|
|
363
|
-
/**
|
|
364
|
-
* Formats one chat timestamp into relative text using the active server language.
|
|
365
|
-
*/
|
|
366
|
-
function formatRelativeChatTimestamp(timestamp: string, language: ServerLanguageCode): string {
|
|
367
|
-
const parsed = createServerLanguageMoment(timestamp, language);
|
|
368
|
-
if (!parsed.isValid()) {
|
|
369
|
-
return timestamp;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return parsed.fromNow();
|
|
373
|
-
}
|
|
@@ -3,6 +3,8 @@ import { $provideAgentCollectionForServer } from '@/src/tools/$provideAgentColle
|
|
|
3
3
|
import { formatAgentNamingText } from '@/src/utils/agentNaming';
|
|
4
4
|
import { getCurrentUser } from '@/src/utils/getCurrentUser';
|
|
5
5
|
import { getAgentNaming } from '@/src/utils/getAgentNaming';
|
|
6
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
7
|
+
import { getRequestServerLanguage } from '@/src/utils/localization/getRequestServerLanguage';
|
|
6
8
|
import { HistoryIcon } from 'lucide-react';
|
|
7
9
|
import { RestoreVersionButton } from './RestoreVersionButton';
|
|
8
10
|
import { enforceCanonicalLocalAgentId, getAgentName } from '../_utils';
|
|
@@ -39,6 +41,7 @@ export default async function AgentHistoryPage({ params }: { params: Promise<{ a
|
|
|
39
41
|
const collection = await $provideAgentCollectionForServer();
|
|
40
42
|
const history = await collection.listAgentHistory(agentName);
|
|
41
43
|
const agentNaming = await getAgentNaming();
|
|
44
|
+
const language = await getRequestServerLanguage();
|
|
42
45
|
|
|
43
46
|
return (
|
|
44
47
|
<div className="container mx-auto p-6 max-w-4xl">
|
|
@@ -69,7 +72,9 @@ export default async function AgentHistoryPage({ params }: { params: Promise<{ a
|
|
|
69
72
|
<div className="flex justify-between items-start mb-2">
|
|
70
73
|
<div>
|
|
71
74
|
<time className="block mb-1 text-sm font-normal leading-none text-gray-400">
|
|
72
|
-
{
|
|
75
|
+
{formatServerLanguageHumanReadableDate(item.createdAt, language, {
|
|
76
|
+
isExactDateIncluded: true,
|
|
77
|
+
})}
|
|
73
78
|
</time>
|
|
74
79
|
<h3 className="text-lg font-semibold text-gray-900">
|
|
75
80
|
{item.versionName || `Version ${history.length - index}`}
|
package/apps/agents-server/src/app/agents/[agentName]/integration/CalendarIntegrationSection.tsx
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { showConfirm } from '@/src/components/AsyncDialogs/asyncDialogs';
|
|
4
|
+
import { useServerLanguage } from '@/src/components/ServerLanguage/ServerLanguageProvider';
|
|
5
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
4
6
|
import { buildCalendarOAuthConnectUrl } from '@/src/utils/calendarOAuthClient';
|
|
7
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
5
8
|
import { Calendar, Link2, RefreshCw, Unlink } from 'lucide-react';
|
|
6
9
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
10
|
|
|
@@ -71,6 +74,7 @@ type CalendarIntegrationSectionProps = {
|
|
|
71
74
|
* Renders connected-calendar settings for one agent, including re-auth/disconnect and activity timeline.
|
|
72
75
|
*/
|
|
73
76
|
export function CalendarIntegrationSection({ agentName, agentPermanentId }: CalendarIntegrationSectionProps) {
|
|
77
|
+
const { language } = useServerLanguage();
|
|
74
78
|
const {
|
|
75
79
|
activeConnections,
|
|
76
80
|
disconnectConnection,
|
|
@@ -124,7 +128,7 @@ export function CalendarIntegrationSection({ agentName, agentPermanentId }: Cale
|
|
|
124
128
|
onDisconnect={(connection) => void disconnectConnection(connection)}
|
|
125
129
|
/>
|
|
126
130
|
|
|
127
|
-
<CalendarActivitySection activity={payload?.activity || []} />
|
|
131
|
+
<CalendarActivitySection activity={payload?.activity || []} language={language} />
|
|
128
132
|
</>
|
|
129
133
|
)}
|
|
130
134
|
</div>
|
|
@@ -497,7 +501,13 @@ function CalendarConnectionCard({
|
|
|
497
501
|
/**
|
|
498
502
|
* Renders the recent calendar activity section.
|
|
499
503
|
*/
|
|
500
|
-
function CalendarActivitySection({
|
|
504
|
+
function CalendarActivitySection({
|
|
505
|
+
activity,
|
|
506
|
+
language,
|
|
507
|
+
}: {
|
|
508
|
+
activity: ReadonlyArray<CalendarActivityItem>;
|
|
509
|
+
language: ServerLanguageCode;
|
|
510
|
+
}) {
|
|
501
511
|
return (
|
|
502
512
|
<div className="mt-6 space-y-3">
|
|
503
513
|
<h3 className="text-sm font-semibold uppercase tracking-wide text-gray-700">Recent activity</h3>
|
|
@@ -506,7 +516,7 @@ function CalendarActivitySection({ activity }: { activity: ReadonlyArray<Calenda
|
|
|
506
516
|
) : (
|
|
507
517
|
<div className="space-y-2">
|
|
508
518
|
{activity.map((item) => (
|
|
509
|
-
<CalendarActivityCard key={item.id} activity={item} />
|
|
519
|
+
<CalendarActivityCard key={item.id} activity={item} language={language} />
|
|
510
520
|
))}
|
|
511
521
|
</div>
|
|
512
522
|
)}
|
|
@@ -517,7 +527,13 @@ function CalendarActivitySection({ activity }: { activity: ReadonlyArray<Calenda
|
|
|
517
527
|
/**
|
|
518
528
|
* Renders one recent calendar activity row.
|
|
519
529
|
*/
|
|
520
|
-
function CalendarActivityCard({
|
|
530
|
+
function CalendarActivityCard({
|
|
531
|
+
activity,
|
|
532
|
+
language,
|
|
533
|
+
}: {
|
|
534
|
+
activity: CalendarActivityItem;
|
|
535
|
+
language: ServerLanguageCode;
|
|
536
|
+
}) {
|
|
521
537
|
return (
|
|
522
538
|
<div className="rounded-lg border border-blue-100 bg-white/90 px-3 py-2">
|
|
523
539
|
<div className="flex flex-wrap items-center gap-2 text-xs">
|
|
@@ -529,7 +545,9 @@ function CalendarActivityCard({ activity }: { activity: CalendarActivityItem })
|
|
|
529
545
|
>
|
|
530
546
|
{activity.status}
|
|
531
547
|
</span>
|
|
532
|
-
<span className="text-gray-500">
|
|
548
|
+
<span className="text-gray-500">
|
|
549
|
+
{formatServerLanguageHumanReadableDate(activity.createdAt, language)}
|
|
550
|
+
</span>
|
|
533
551
|
</div>
|
|
534
552
|
{activity.calendarUrl && (
|
|
535
553
|
<p className="mt-1 text-[11px] text-gray-600 break-all font-mono">{activity.calendarUrl}</p>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
+
import { useServerLanguage } from '@/src/components/ServerLanguage/ServerLanguageProvider';
|
|
3
4
|
import { AgentTimeoutsEditDialog } from './AgentTimeoutsEditDialog';
|
|
4
5
|
import { AgentTimeoutsFiltersCard } from './AgentTimeoutsFiltersCard';
|
|
5
6
|
import { AgentTimeoutsHeader } from './AgentTimeoutsHeader';
|
|
@@ -20,13 +21,14 @@ type AgentTimeoutsClientProps = {
|
|
|
20
21
|
* @private route component of AgentTimeoutsPage
|
|
21
22
|
*/
|
|
22
23
|
export function AgentTimeoutsClient({ agentName }: AgentTimeoutsClientProps) {
|
|
24
|
+
const { language } = useServerLanguage();
|
|
23
25
|
const state = useAgentTimeoutsClientState({ agentName });
|
|
24
26
|
|
|
25
27
|
return (
|
|
26
28
|
<div className="container mx-auto mt-20 space-y-6 px-4 py-8">
|
|
27
29
|
<AgentTimeoutsHeader state={state} />
|
|
28
30
|
<AgentTimeoutsSummaryMetrics state={state} />
|
|
29
|
-
<AgentTimeoutsFiltersCard state={state} />
|
|
31
|
+
<AgentTimeoutsFiltersCard language={language} state={state} />
|
|
30
32
|
|
|
31
33
|
{state.errorMessage ? (
|
|
32
34
|
<div className="rounded-2xl border border-red-200 bg-red-50 p-4 text-sm text-red-700">
|
|
@@ -34,7 +36,7 @@ export function AgentTimeoutsClient({ agentName }: AgentTimeoutsClientProps) {
|
|
|
34
36
|
</div>
|
|
35
37
|
) : null}
|
|
36
38
|
|
|
37
|
-
<AgentTimeoutsTableCard agentName={agentName} state={state} />
|
|
39
|
+
<AgentTimeoutsTableCard agentName={agentName} language={language} state={state} />
|
|
38
40
|
<AgentTimeoutsEditDialog state={state} />
|
|
39
41
|
</div>
|
|
40
42
|
);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
2
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
1
3
|
import type { useAgentTimeoutsClientState } from './useAgentTimeoutsClientState';
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -6,6 +8,7 @@ import type { useAgentTimeoutsClientState } from './useAgentTimeoutsClientState'
|
|
|
6
8
|
* @private function of AgentTimeoutsClient
|
|
7
9
|
*/
|
|
8
10
|
type AgentTimeoutsFiltersCardProps = {
|
|
11
|
+
language: ServerLanguageCode;
|
|
9
12
|
state: ReturnType<typeof useAgentTimeoutsClientState>;
|
|
10
13
|
};
|
|
11
14
|
|
|
@@ -36,8 +39,10 @@ const TIMEOUT_MANAGER_FILTER_OPTIONS: ReadonlyArray<TimeoutManagerFilterOption>
|
|
|
36
39
|
*
|
|
37
40
|
* @private function of AgentTimeoutsFiltersCard
|
|
38
41
|
*/
|
|
39
|
-
function resolveLastRefreshedLabel(generatedAt: string | null): string {
|
|
40
|
-
return generatedAt
|
|
42
|
+
function resolveLastRefreshedLabel(generatedAt: string | null, language: ServerLanguageCode): string {
|
|
43
|
+
return generatedAt
|
|
44
|
+
? `Last refreshed ${formatServerLanguageHumanReadableDate(generatedAt, language)}`
|
|
45
|
+
: 'Waiting for first refresh...';
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
/**
|
|
@@ -45,7 +50,7 @@ function resolveLastRefreshedLabel(generatedAt: string | null): string {
|
|
|
45
50
|
*
|
|
46
51
|
* @private function of AgentTimeoutsClient
|
|
47
52
|
*/
|
|
48
|
-
export function AgentTimeoutsFiltersCard({ state }: AgentTimeoutsFiltersCardProps) {
|
|
53
|
+
export function AgentTimeoutsFiltersCard({ language, state }: AgentTimeoutsFiltersCardProps) {
|
|
49
54
|
return (
|
|
50
55
|
<div className="rounded-2xl border border-gray-200 bg-white p-4 shadow-sm">
|
|
51
56
|
<div className="flex flex-wrap gap-2">
|
|
@@ -64,7 +69,7 @@ export function AgentTimeoutsFiltersCard({ state }: AgentTimeoutsFiltersCardProp
|
|
|
64
69
|
</button>
|
|
65
70
|
))}
|
|
66
71
|
</div>
|
|
67
|
-
<div className="mt-3 text-xs text-gray-500">{resolveLastRefreshedLabel(state.generatedAt)}</div>
|
|
72
|
+
<div className="mt-3 text-xs text-gray-500">{resolveLastRefreshedLabel(state.generatedAt, language)}</div>
|
|
68
73
|
</div>
|
|
69
74
|
);
|
|
70
75
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
1
2
|
import type { useAgentTimeoutsClientState } from './useAgentTimeoutsClientState';
|
|
2
3
|
import { AgentTimeoutsTableRow } from './AgentTimeoutsTableRow';
|
|
3
4
|
|
|
@@ -8,6 +9,7 @@ import { AgentTimeoutsTableRow } from './AgentTimeoutsTableRow';
|
|
|
8
9
|
*/
|
|
9
10
|
type AgentTimeoutsTableCardProps = {
|
|
10
11
|
agentName: string;
|
|
12
|
+
language: ServerLanguageCode;
|
|
11
13
|
state: ReturnType<typeof useAgentTimeoutsClientState>;
|
|
12
14
|
};
|
|
13
15
|
|
|
@@ -16,7 +18,7 @@ type AgentTimeoutsTableCardProps = {
|
|
|
16
18
|
*
|
|
17
19
|
* @private function of AgentTimeoutsClient
|
|
18
20
|
*/
|
|
19
|
-
export function AgentTimeoutsTableCard({ agentName, state }: AgentTimeoutsTableCardProps) {
|
|
21
|
+
export function AgentTimeoutsTableCard({ agentName, language, state }: AgentTimeoutsTableCardProps) {
|
|
20
22
|
return (
|
|
21
23
|
<div className="rounded-2xl border border-gray-200 bg-white shadow-sm">
|
|
22
24
|
{state.isLoading ? (
|
|
@@ -42,6 +44,7 @@ export function AgentTimeoutsTableCard({ agentName, state }: AgentTimeoutsTableC
|
|
|
42
44
|
<AgentTimeoutsTableRow
|
|
43
45
|
key={timeout.timeoutId}
|
|
44
46
|
agentName={agentName}
|
|
47
|
+
language={language}
|
|
45
48
|
state={state}
|
|
46
49
|
timeout={timeout}
|
|
47
50
|
/>
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { UserChatTimeout } from '@/src/utils/userChatClient';
|
|
2
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
3
|
+
import { formatServerLanguageHumanReadableDate } from '@/src/utils/localization/formatServerLanguageHumanReadableDate';
|
|
2
4
|
import Link from 'next/link';
|
|
3
5
|
import type { useAgentTimeoutsClientState } from './useAgentTimeoutsClientState';
|
|
4
6
|
|
|
@@ -9,6 +11,7 @@ import type { useAgentTimeoutsClientState } from './useAgentTimeoutsClientState'
|
|
|
9
11
|
*/
|
|
10
12
|
type AgentTimeoutsTableRowProps = {
|
|
11
13
|
agentName: string;
|
|
14
|
+
language: ServerLanguageCode;
|
|
12
15
|
state: ReturnType<typeof useAgentTimeoutsClientState>;
|
|
13
16
|
timeout: UserChatTimeout;
|
|
14
17
|
};
|
|
@@ -141,7 +144,7 @@ function truncateText(value: string, maxLength: number): string {
|
|
|
141
144
|
*
|
|
142
145
|
* @private function of AgentTimeoutsClient
|
|
143
146
|
*/
|
|
144
|
-
export function AgentTimeoutsTableRow({ agentName, state, timeout }: AgentTimeoutsTableRowProps) {
|
|
147
|
+
export function AgentTimeoutsTableRow({ agentName, language, state, timeout }: AgentTimeoutsTableRowProps) {
|
|
145
148
|
const isBusy = state.busyTimeoutId === timeout.timeoutId;
|
|
146
149
|
const isPaused = isTimeoutPaused(timeout);
|
|
147
150
|
const isEditable = isTimeoutEditable(timeout);
|
|
@@ -152,7 +155,9 @@ export function AgentTimeoutsTableRow({ agentName, state, timeout }: AgentTimeou
|
|
|
152
155
|
<tr>
|
|
153
156
|
<td className="px-4 py-3 align-top">
|
|
154
157
|
<div className="font-mono text-[11px] font-semibold text-gray-900">{timeout.timeoutId}</div>
|
|
155
|
-
<div className="mt-1 text-[11px] text-gray-500">
|
|
158
|
+
<div className="mt-1 text-[11px] text-gray-500">
|
|
159
|
+
Updated {formatServerLanguageHumanReadableDate(timeout.updatedAt, language)}
|
|
160
|
+
</div>
|
|
156
161
|
</td>
|
|
157
162
|
<td className="px-4 py-3 align-top">
|
|
158
163
|
<Link
|
|
@@ -167,7 +172,9 @@ export function AgentTimeoutsTableRow({ agentName, state, timeout }: AgentTimeou
|
|
|
167
172
|
{statusPresentation.label}
|
|
168
173
|
</span>
|
|
169
174
|
</td>
|
|
170
|
-
<td className="px-4 py-3 align-top">
|
|
175
|
+
<td className="px-4 py-3 align-top">
|
|
176
|
+
{formatServerLanguageHumanReadableDate(timeout.dueAt, language, { isExactDateIncluded: true })}
|
|
177
|
+
</td>
|
|
171
178
|
<td className="px-4 py-3 align-top">
|
|
172
179
|
{timeout.recurrenceIntervalMs ? `Every ${formatDuration(timeout.recurrenceIntervalMs)}` : 'One-shot'}
|
|
173
180
|
</td>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { isUserGlobalAdmin } from '@/src/utils/isUserGlobalAdmin';
|
|
3
|
+
import { listVpsSelfUpdateCandidateCommits } from '@/src/utils/vpsSelfUpdate';
|
|
4
|
+
|
|
5
|
+
export const runtime = 'nodejs';
|
|
6
|
+
export const dynamic = 'force-dynamic';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Lists candidate commits for the standalone VPS self-update custom-target picker.
|
|
10
|
+
*/
|
|
11
|
+
export async function GET(request: Request) {
|
|
12
|
+
if (!(await isUserGlobalAdmin())) {
|
|
13
|
+
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const requestUrl = new URL(request.url);
|
|
18
|
+
const limitParameter = requestUrl.searchParams.get('limit');
|
|
19
|
+
const parsedLimit = limitParameter ? Number.parseInt(limitParameter, 10) : null;
|
|
20
|
+
|
|
21
|
+
const commits = await listVpsSelfUpdateCandidateCommits({
|
|
22
|
+
searchText: requestUrl.searchParams.get('search'),
|
|
23
|
+
authoredAfter: requestUrl.searchParams.get('after'),
|
|
24
|
+
authoredBefore: requestUrl.searchParams.get('before'),
|
|
25
|
+
limit: Number.isFinite(parsedLimit) ? parsedLimit : null,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return NextResponse.json({ commits });
|
|
29
|
+
} catch (error) {
|
|
30
|
+
return NextResponse.json(
|
|
31
|
+
{ error: error instanceof Error ? error.message : 'Failed to load candidate commits.' },
|
|
32
|
+
{ status: 500 },
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -24,7 +24,7 @@ export async function GET() {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
|
-
* Starts a detached standalone VPS self-update for the selected environment.
|
|
27
|
+
* Starts a detached standalone VPS self-update for the selected environment or arbitrary ref.
|
|
28
28
|
*/
|
|
29
29
|
export async function POST(request: Request) {
|
|
30
30
|
if (!(await isUserGlobalAdmin())) {
|
|
@@ -35,6 +35,8 @@ export async function POST(request: Request) {
|
|
|
35
35
|
const body = (await request.json().catch(() => null)) as
|
|
36
36
|
| {
|
|
37
37
|
readonly environment?: string;
|
|
38
|
+
readonly customRef?: string | null;
|
|
39
|
+
readonly originRepositoryUrl?: string | null;
|
|
38
40
|
}
|
|
39
41
|
| null;
|
|
40
42
|
|
|
@@ -42,7 +44,13 @@ export async function POST(request: Request) {
|
|
|
42
44
|
return NextResponse.json({ error: 'Update environment is required.' }, { status: 400 });
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
const overview = await startVpsSelfUpdate({
|
|
48
|
+
environmentId: body.environment,
|
|
49
|
+
customRef: body.customRef ?? null,
|
|
50
|
+
originRepositoryUrl: body.originRepositoryUrl ?? null,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return NextResponse.json(overview, { status: 202 });
|
|
46
54
|
} catch (error) {
|
|
47
55
|
return NextResponse.json(
|
|
48
56
|
{ error: error instanceof Error ? error.message : 'Failed to start the update.' },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { processNextLocalUserChatJob } from '@/src/utils/localChatRunner';
|
|
1
|
+
import { processNextLocalUserChatJob, type ProcessLocalUserChatJobResult } from '@/src/utils/localChatRunner';
|
|
2
2
|
import {
|
|
3
3
|
recoverExpiredRunningUserChatJobs,
|
|
4
4
|
resolveUserChatWorkerInternalToken,
|
|
@@ -51,7 +51,7 @@ async function handleUserChatJobWorkerRequest(request: Request) {
|
|
|
51
51
|
await recoverExpiredRunningUserChatJobs();
|
|
52
52
|
|
|
53
53
|
const processedJob = await processNextLocalUserChatJob({ preferredJobId });
|
|
54
|
-
if (!processedJob) {
|
|
54
|
+
if (!processedJob || !shouldRequeueUserChatJobWorker(processedJob)) {
|
|
55
55
|
return new Response(null, { status: 204 });
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -73,6 +73,18 @@ async function handleUserChatJobWorkerRequest(request: Request) {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Decides whether one worker outcome should immediately schedule another worker tick.
|
|
78
|
+
*
|
|
79
|
+
* Mutating outcomes may have exposed more queued work, while non-mutating `waiting`
|
|
80
|
+
* outcomes need the foreground fallback poll instead of a tight self-requeue loop.
|
|
81
|
+
*
|
|
82
|
+
* @private route helper
|
|
83
|
+
*/
|
|
84
|
+
function shouldRequeueUserChatJobWorker(processedJob: ProcessLocalUserChatJobResult): boolean {
|
|
85
|
+
return processedJob.didMutate;
|
|
86
|
+
}
|
|
87
|
+
|
|
76
88
|
/**
|
|
77
89
|
* Validates the internal worker token.
|
|
78
90
|
*
|