@promptbook/cli 0.112.0 → 0.113.0-1

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 (109) hide show
  1. package/README.md +45 -29
  2. package/agents/default/developer.book +2 -1
  3. package/apps/agents-server/next.config.ts +21 -0
  4. package/apps/agents-server/src/app/admin/limits/LimitsClient.tsx +1 -1
  5. package/apps/agents-server/src/app/admin/task-manager/TaskManagerTaskRow.tsx +7 -2
  6. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +52 -33
  7. package/apps/agents-server/src/app/api/agent-folders/[folderId]/visibility/route.ts +19 -7
  8. package/apps/agents-server/src/app/api/agents/[agentName]/route.ts +8 -18
  9. package/apps/agents-server/src/app/api/internal/agent-runner-limits/route.ts +1 -1
  10. package/apps/agents-server/src/app/api/page-preview/check/route.ts +5 -20
  11. package/apps/agents-server/src/app/api/page-preview/interact/route.ts +179 -0
  12. package/apps/agents-server/src/app/api/page-preview/live/route.ts +67 -0
  13. package/apps/agents-server/src/app/api/page-preview/screenshot/route.ts +13 -21
  14. package/apps/agents-server/src/app/api/v1/agents/[agentId]/route.ts +13 -8
  15. package/apps/agents-server/src/components/AgentProfile/AgentCapabilityChips.tsx +39 -5
  16. package/apps/agents-server/src/components/Homepage/AgentCard.tsx +7 -1
  17. package/apps/agents-server/src/components/Homepage/AgentsList.tsx +3 -0
  18. package/apps/agents-server/src/components/Homepage/AgentsListHeader.tsx +41 -0
  19. package/apps/agents-server/src/components/Homepage/hiddenFolders.ts +104 -0
  20. package/apps/agents-server/src/components/Homepage/useAgentsListQueryState.ts +35 -0
  21. package/apps/agents-server/src/components/Homepage/useAgentsListState.ts +24 -4
  22. package/apps/agents-server/src/constants/chatVisualMode.ts +1 -1
  23. package/apps/agents-server/src/constants/serverLimits.ts +19 -0
  24. package/apps/agents-server/src/constants/themeMode.ts +1 -1
  25. package/apps/agents-server/src/database/migrations/2026-05-2600-default-theme.sql +2 -2
  26. package/apps/agents-server/src/database/seedCoreAgents.ts +0 -2
  27. package/apps/agents-server/src/database/seedDefaultAgents.ts +0 -2
  28. package/apps/agents-server/src/tools/agent_progress.ts +4 -10
  29. package/apps/agents-server/src/utils/agentVisibility.ts +25 -62
  30. package/apps/agents-server/src/utils/chatTasksAdmin.ts +3 -1
  31. package/apps/agents-server/src/utils/createAgentWithDefaultVisibility.ts +3 -1
  32. package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +9 -17
  33. package/apps/agents-server/src/utils/getAdminChatTasksResponse/mapVpsSelfUpdateJobToAdminChatTask.ts +84 -0
  34. package/apps/agents-server/src/utils/getAdminChatTasksResponse.ts +195 -5
  35. package/apps/agents-server/src/utils/localChatRunner/LocalUserChatJobMetadata.ts +15 -5
  36. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +17 -26
  37. package/apps/agents-server/src/utils/pagePreview/livePagePreviewSessions.ts +365 -0
  38. package/apps/agents-server/src/utils/pagePreview/resolvePagePreviewRequestUrl.ts +74 -0
  39. package/apps/agents-server/src/utils/serverLimits.ts +2 -0
  40. package/apps/agents-server/src/utils/serverManagement/createManagedServer/seedServerCoreAgents.ts +2 -2
  41. package/apps/agents-server/src/utils/serverManagement/createManagedServer/seedServerDefaultAgents.ts +1 -1
  42. package/apps/agents-server/src/utils/userChat/createUserChatHarnessProgressCard.ts +0 -6
  43. package/apps/agents-server/src/utils/userChat/createUserChatRunnerProgressCard.ts +0 -6
  44. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +69 -0
  45. package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +0 -6
  46. package/apps/agents-server/src/utils/vpsSelfUpdate.ts +150 -24
  47. package/esm/apps/agents-server/src/constants/serverLimits.d.ts +17 -0
  48. package/esm/index.es.js +581 -93
  49. package/esm/index.es.js.map +1 -1
  50. package/esm/scripts/run-agent-messages/main/runMultipleAgentMessages.d.ts +1 -0
  51. package/esm/scripts/run-agent-messages/main/tickAgentMessages.d.ts +1 -0
  52. package/esm/src/_packages/core.index.d.ts +22 -0
  53. package/esm/src/_packages/types.index.d.ts +2 -0
  54. package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -0
  55. package/esm/src/book-2.0/agent-source/agentSourceVisibility.d.ts +97 -0
  56. package/esm/src/book-2.0/agent-source/agentSourceVisibility.test.d.ts +1 -0
  57. package/esm/src/book-components/BookEditor/BookEditorMonacoTokenization.d.ts +1 -0
  58. package/esm/src/book-components/Chat/Chat/CitationIframePreview.d.ts +2 -2
  59. package/esm/src/book-components/Chat/utils/livePagePreviewConstants.d.ts +12 -0
  60. package/esm/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +6 -0
  61. package/esm/src/collection/agent-collection/CreateAgentInput.d.ts +2 -1
  62. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +21 -1
  63. package/esm/src/commitments/META_VISIBILITY/META_VISIBILITY.d.ts +27 -0
  64. package/esm/src/commitments/index.d.ts +2 -1
  65. package/esm/src/version.d.ts +1 -1
  66. package/package.json +1 -1
  67. package/src/_packages/core.index.ts +22 -0
  68. package/src/_packages/types.index.ts +2 -0
  69. package/src/book-2.0/agent-source/AgentBasicInformation.ts +2 -0
  70. package/src/book-2.0/agent-source/agentSourceVisibility.ts +214 -0
  71. package/src/book-2.0/agent-source/parseAgentSource/applyMetaCommitment.ts +17 -0
  72. package/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.ts +1 -0
  73. package/src/book-components/BookEditor/BookEditorMonacoTokenization.ts +11 -0
  74. package/src/book-components/BookEditor/useBookEditorMonacoLanguage.ts +7 -3
  75. package/src/book-components/Chat/Chat/Chat.module.css +14 -5
  76. package/src/book-components/Chat/Chat/CitationIframePreview.tsx +197 -22
  77. package/src/book-components/Chat/utils/livePagePreviewConstants.ts +17 -0
  78. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +144 -16
  79. package/src/cli/cli-commands/agents-server/startAgentsServer.ts +22 -2
  80. package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
  81. package/src/cli/cli-commands/coder/run.ts +30 -0
  82. package/src/collection/agent-collection/CreateAgentInput.ts +10 -5
  83. package/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.ts +7 -3
  84. package/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.ts +7 -4
  85. package/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.ts +44 -8
  86. package/src/commitments/META_VISIBILITY/META_VISIBILITY.ts +78 -0
  87. package/src/commitments/index.ts +2 -0
  88. package/src/other/templates/getTemplatesPipelineCollection.ts +826 -650
  89. package/src/version.ts +2 -2
  90. package/src/versions.txt +2 -0
  91. package/umd/apps/agents-server/src/constants/serverLimits.d.ts +17 -0
  92. package/umd/index.umd.js +581 -93
  93. package/umd/index.umd.js.map +1 -1
  94. package/umd/scripts/run-agent-messages/main/runMultipleAgentMessages.d.ts +1 -0
  95. package/umd/scripts/run-agent-messages/main/tickAgentMessages.d.ts +1 -0
  96. package/umd/src/_packages/core.index.d.ts +22 -0
  97. package/umd/src/_packages/types.index.d.ts +2 -0
  98. package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -0
  99. package/umd/src/book-2.0/agent-source/agentSourceVisibility.d.ts +97 -0
  100. package/umd/src/book-2.0/agent-source/agentSourceVisibility.test.d.ts +1 -0
  101. package/umd/src/book-components/BookEditor/BookEditorMonacoTokenization.d.ts +1 -0
  102. package/umd/src/book-components/Chat/Chat/CitationIframePreview.d.ts +2 -2
  103. package/umd/src/book-components/Chat/utils/livePagePreviewConstants.d.ts +12 -0
  104. package/umd/src/cli/cli-commands/agents-server/buildAgentsServer.d.ts +6 -0
  105. package/umd/src/collection/agent-collection/CreateAgentInput.d.ts +2 -1
  106. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/prepareAgentSourceForPersistence.d.ts +21 -1
  107. package/umd/src/commitments/META_VISIBILITY/META_VISIBILITY.d.ts +27 -0
  108. package/umd/src/commitments/index.d.ts +2 -1
  109. package/umd/src/version.d.ts +1 -1
@@ -0,0 +1,104 @@
1
+ import type { AgentOrganizationAgent, AgentOrganizationFolder } from '../../utils/agentOrganization/types';
2
+ import { buildFolderMaps, collectDescendantFolderIds } from './agentOrganizationUtils';
3
+
4
+ /**
5
+ * Prefix that marks a folder as hidden from default homepage listings.
6
+ *
7
+ * Folders whose name starts with this prefix (for example `.core`) are excluded
8
+ * from the agents list, graph, and office views unless the user explicitly toggles
9
+ * hidden-folder visibility on.
10
+ *
11
+ * @private function of AgentsList
12
+ */
13
+ export const HIDDEN_FOLDER_NAME_PREFIX = '.';
14
+
15
+ /**
16
+ * Determines whether one folder name represents a hidden folder.
17
+ *
18
+ * @param folderName - Folder name persisted in the database.
19
+ * @returns True when the folder should be hidden by default.
20
+ *
21
+ * @private function of AgentsList
22
+ */
23
+ export function isHiddenFolderName(folderName: string): boolean {
24
+ return folderName.startsWith(HIDDEN_FOLDER_NAME_PREFIX);
25
+ }
26
+
27
+ /**
28
+ * Collects identifiers of all hidden folders together with their descendant folders.
29
+ *
30
+ * A folder is hidden when its own name starts with the hidden-folder prefix, or when
31
+ * it lives under another hidden folder. Descendants are included so that nested
32
+ * content is hidden together with the marker folder.
33
+ *
34
+ * @param folders - All folders in the organization.
35
+ * @returns Set of folder identifiers that should be excluded from default views.
36
+ *
37
+ * @private function of AgentsList
38
+ */
39
+ export function collectHiddenFolderIds(folders: ReadonlyArray<AgentOrganizationFolder>): Set<number> {
40
+ const folderMaps = buildFolderMaps(folders);
41
+ const hiddenFolderIds = new Set<number>();
42
+
43
+ for (const folder of folders) {
44
+ if (!isHiddenFolderName(folder.name)) {
45
+ continue;
46
+ }
47
+
48
+ for (const descendantId of collectDescendantFolderIds(folder.id, folderMaps.childrenByParentId)) {
49
+ hiddenFolderIds.add(descendantId);
50
+ }
51
+ }
52
+
53
+ return hiddenFolderIds;
54
+ }
55
+
56
+ /**
57
+ * Result of removing hidden folders and their agents from one organization snapshot.
58
+ *
59
+ * @private function of AgentsList
60
+ */
61
+ type FilterHiddenFolderTreeResult = {
62
+ readonly folders: AgentOrganizationFolder[];
63
+ readonly agents: AgentOrganizationAgent[];
64
+ readonly hasHiddenFolders: boolean;
65
+ };
66
+
67
+ /**
68
+ * Removes hidden folders and their agents from one organization snapshot.
69
+ *
70
+ * When `isHiddenFoldersVisible` is true the snapshot passes through unchanged so the
71
+ * caller can render every folder. When false, all hidden folders (including their
72
+ * descendants and the agents inside them) are removed in one pass — keeping the
73
+ * single filtering rule in one place across list, graph, and office views.
74
+ *
75
+ * @param folders - All folders in the organization.
76
+ * @param agents - All agents in the organization.
77
+ * @param isHiddenFoldersVisible - Whether the user has opted to display hidden folders.
78
+ * @returns Filtered organization snapshot together with the unfiltered detection flag.
79
+ *
80
+ * @private function of AgentsList
81
+ */
82
+ export function filterHiddenFolderTree(
83
+ folders: ReadonlyArray<AgentOrganizationFolder>,
84
+ agents: ReadonlyArray<AgentOrganizationAgent>,
85
+ isHiddenFoldersVisible: boolean,
86
+ ): FilterHiddenFolderTreeResult {
87
+ const hasHiddenFolders = folders.some((folder) => isHiddenFolderName(folder.name));
88
+
89
+ if (isHiddenFoldersVisible || !hasHiddenFolders) {
90
+ return {
91
+ folders: Array.from(folders),
92
+ agents: Array.from(agents),
93
+ hasHiddenFolders,
94
+ };
95
+ }
96
+
97
+ const hiddenFolderIds = collectHiddenFolderIds(folders);
98
+
99
+ return {
100
+ folders: folders.filter((folder) => !hiddenFolderIds.has(folder.id)),
101
+ agents: agents.filter((agent) => agent.folderId === null || !hiddenFolderIds.has(agent.folderId)),
102
+ hasHiddenFolders,
103
+ };
104
+ }
@@ -6,6 +6,20 @@ import { useCurrentPathQueryNavigation } from '../_utils/useCurrentPathQueryNavi
6
6
  import type { HomeViewMode } from './homeViewMode';
7
7
  import { getHomeViewQueryValue, resolveHomeViewMode } from './homeViewMode';
8
8
 
9
+ /**
10
+ * Query parameter name used to opt into showing hidden folders.
11
+ *
12
+ * @private function of AgentsList
13
+ */
14
+ const HIDDEN_FOLDERS_QUERY_PARAM = 'hidden';
15
+
16
+ /**
17
+ * Query value that opts the agents list into showing hidden folders.
18
+ *
19
+ * @private function of AgentsList
20
+ */
21
+ const HIDDEN_FOLDERS_VISIBLE_QUERY_VALUE = 'show';
22
+
9
23
  /**
10
24
  * Route/query state returned to the private `useAgentsListState` facade.
11
25
  *
@@ -13,8 +27,10 @@ import { getHomeViewQueryValue, resolveHomeViewMode } from './homeViewMode';
13
27
  */
14
28
  type UseAgentsListQueryStateResult = {
15
29
  readonly folderQuery: string | null;
30
+ readonly isHiddenFoldersVisible: boolean;
16
31
  readonly routeSyncKey: string;
17
32
  readonly searchParamsSnapshot: string;
33
+ readonly setHiddenFoldersVisible: (isVisible: boolean) => void;
18
34
  readonly setViewMode: (mode: HomeViewMode) => void;
19
35
  readonly viewMode: HomeViewMode;
20
36
  readonly updateCurrentPathQuery: ReturnType<typeof useCurrentPathQueryNavigation>;
@@ -34,6 +50,8 @@ export function useAgentsListQueryState(): UseAgentsListQueryStateResult {
34
50
  const routeSyncKey = `?${searchParamsSnapshot}`;
35
51
  const folderQuery = searchParams?.get('folder') || null;
36
52
  const viewMode = resolveHomeViewMode(searchParams?.get('view'));
53
+ const isHiddenFoldersVisible =
54
+ searchParams?.get(HIDDEN_FOLDERS_QUERY_PARAM) === HIDDEN_FOLDERS_VISIBLE_QUERY_VALUE;
37
55
 
38
56
  const setViewMode = useCallback(
39
57
  (mode: HomeViewMode) => {
@@ -51,10 +69,27 @@ export function useAgentsListQueryState(): UseAgentsListQueryStateResult {
51
69
  [searchParams, updateCurrentPathQuery],
52
70
  );
53
71
 
72
+ const setHiddenFoldersVisible = useCallback(
73
+ (isVisible: boolean) => {
74
+ const nextSearchParams = new URLSearchParams(searchParams?.toString() || '');
75
+
76
+ if (isVisible) {
77
+ nextSearchParams.set(HIDDEN_FOLDERS_QUERY_PARAM, HIDDEN_FOLDERS_VISIBLE_QUERY_VALUE);
78
+ } else {
79
+ nextSearchParams.delete(HIDDEN_FOLDERS_QUERY_PARAM);
80
+ }
81
+
82
+ updateCurrentPathQuery(nextSearchParams, 'replace');
83
+ },
84
+ [searchParams, updateCurrentPathQuery],
85
+ );
86
+
54
87
  return {
55
88
  folderQuery,
89
+ isHiddenFoldersVisible,
56
90
  routeSyncKey,
57
91
  searchParamsSnapshot,
92
+ setHiddenFoldersVisible,
58
93
  setViewMode,
59
94
  viewMode,
60
95
  updateCurrentPathQuery,
@@ -5,6 +5,7 @@ import { useMemo } from 'react';
5
5
  import type { AgentOrganizationAgent, AgentOrganizationFolder } from '../../utils/agentOrganization/types';
6
6
  import { useAgentNaming } from '../AgentNaming/AgentNamingContext';
7
7
  import { getAgentIdentifier } from './agentOrganizationUtils';
8
+ import { filterHiddenFolderTree } from './hiddenFolders';
8
9
  import { useAgentsListAgentState } from './useAgentsListAgentState';
9
10
  import { useAgentsListDerivedState } from './useAgentsListDerivedState';
10
11
  import {
@@ -82,14 +83,22 @@ export function useAgentsListState(props: UseAgentsListStateProps) {
82
83
  showFederatedAgents,
83
84
  externalAgents: initialExternalAgents,
84
85
  } = props;
85
- const { folderQuery, routeSyncKey, searchParamsSnapshot, setViewMode, updateCurrentPathQuery, viewMode } =
86
- useAgentsListQueryState();
86
+ const {
87
+ folderQuery,
88
+ isHiddenFoldersVisible,
89
+ routeSyncKey,
90
+ searchParamsSnapshot,
91
+ setHiddenFoldersVisible,
92
+ setViewMode,
93
+ updateCurrentPathQuery,
94
+ viewMode,
95
+ } = useAgentsListQueryState();
87
96
  const { formatText } = useAgentNaming();
88
97
  const isTouchInput = useIsTouchInput();
89
98
  const allowFullCardDrag = canOrganize && viewMode === 'LIST' && !isTouchInput;
90
99
  const {
91
- agents,
92
- folders,
100
+ agents: agentsBeforeHiddenFilter,
101
+ folders: foldersBeforeHiddenFilter,
93
102
  lastSyncedRouteKey,
94
103
  persistQueuedOrganizationMutation,
95
104
  setAgents,
@@ -100,6 +109,14 @@ export function useAgentsListState(props: UseAgentsListStateProps) {
100
109
  initialFolders,
101
110
  routeSyncKey,
102
111
  });
112
+ const {
113
+ agents,
114
+ folders,
115
+ hasHiddenFolders,
116
+ } = useMemo(
117
+ () => filterHiddenFolderTree(foldersBeforeHiddenFilter, agentsBeforeHiddenFilter, isHiddenFoldersVisible),
118
+ [foldersBeforeHiddenFilter, agentsBeforeHiddenFilter, isHiddenFoldersVisible],
119
+ );
103
120
  const {
104
121
  agentCount,
105
122
  allAgentsLabel,
@@ -272,11 +289,13 @@ export function useAgentsListState(props: UseAgentsListStateProps) {
272
289
  handleRequestFolderVisibilityUpdate: folderState.handleRequestFolderVisibilityUpdate,
273
290
  handleShowQrCode: overlayState.handleShowQrCode,
274
291
  handleSubmitFolderEdit: folderState.handleSubmitFolderEdit,
292
+ hasHiddenFolders,
275
293
  headingTitle,
276
294
  isAgentsExporting: importExportState.isAgentsExporting,
277
295
  isAgentsImportDragActive: importExportState.isAgentsImportDragActive,
278
296
  isAgentsImporting: importExportState.isAgentsImporting,
279
297
  isFolderEditSubmitting: folderState.isFolderEditSubmitting,
298
+ isHiddenFoldersVisible,
280
299
  navigateToFolder,
281
300
  mazeAgents,
282
301
  officeAgents,
@@ -286,6 +305,7 @@ export function useAgentsListState(props: UseAgentsListStateProps) {
286
305
  qrCodeAgentEmail,
287
306
  qrCodeAgentUrl,
288
307
  sensors,
308
+ setHiddenFoldersVisible,
289
309
  setViewMode,
290
310
  viewMode,
291
311
  visibleAgentDragIds,
@@ -46,7 +46,7 @@ export const CHAT_VISUAL_MODE_COOKIE_NAME = 'promptbook_agents_chat_visual_mode'
46
46
  /**
47
47
  * Fallback visual mode when metadata/browser values are missing or invalid.
48
48
  */
49
- export const DEFAULT_CHAT_VISUAL_MODE: ChatVisualMode = CHAT_VISUAL_MODES.BUBBLE_MODE;
49
+ export const DEFAULT_CHAT_VISUAL_MODE: ChatVisualMode = CHAT_VISUAL_MODES.ARTICLE_MODE;
50
50
 
51
51
  /**
52
52
  * Resolves one raw visual mode value to a supported mode.
@@ -39,6 +39,13 @@ export const DEFAULT_SPAWN_AGENT_RATE_LIMIT_WINDOW_MS = 10 * 60 * 1000;
39
39
  */
40
40
  export const DEFAULT_LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS = 3;
41
41
 
42
+ /**
43
+ * Default maximum number of local runner harness instances allowed to answer queued messages at once.
44
+ *
45
+ * @private shared Agents Server constant
46
+ */
47
+ export const DEFAULT_LOCAL_AGENT_RUNNER_MAX_PARALLEL_MESSAGES = 3;
48
+
42
49
  /**
43
50
  * Stable keys used by the dedicated server-limits table.
44
51
  *
@@ -53,6 +60,7 @@ export const SERVER_LIMIT_KEYS = {
53
60
  SPAWN_AGENT_RATE_LIMIT_MAX: 'SPAWN_AGENT_RATE_LIMIT_MAX',
54
61
  SPAWN_AGENT_RATE_LIMIT_WINDOW_MS: 'SPAWN_AGENT_RATE_LIMIT_WINDOW_MS',
55
62
  LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS: 'LOCAL_AGENT_RUNNER_MAX_FAILED_ATTEMPTS',
63
+ LOCAL_AGENT_RUNNER_MAX_PARALLEL_MESSAGES: 'LOCAL_AGENT_RUNNER_MAX_PARALLEL_MESSAGES',
56
64
  } as const;
57
65
 
58
66
  /**
@@ -181,6 +189,17 @@ export const SERVER_LIMIT_DEFINITIONS = [
181
189
  step: 1,
182
190
  legacyMetadataKeys: [],
183
191
  },
192
+ {
193
+ key: SERVER_LIMIT_KEYS.LOCAL_AGENT_RUNNER_MAX_PARALLEL_MESSAGES,
194
+ category: 'Local agent runner',
195
+ title: 'Max parallel harness instances',
196
+ description: 'Caps how many queued chat messages the local coding-agent harness may answer at the same time.',
197
+ unit: 'count',
198
+ defaultValue: DEFAULT_LOCAL_AGENT_RUNNER_MAX_PARALLEL_MESSAGES,
199
+ minimumValue: 1,
200
+ step: 1,
201
+ legacyMetadataKeys: [],
202
+ },
184
203
  ] satisfies ReadonlyArray<ServerLimitDefinition>;
185
204
 
186
205
  /**
@@ -46,7 +46,7 @@ export const THEME_MODE_OPTIONS: ReadonlyArray<{
46
46
  /**
47
47
  * Built-in fallback theme mode applied when metadata/browser values are missing or invalid.
48
48
  */
49
- export const DEFAULT_THEME_MODE: ThemeMode = THEME_MODES.SYSTEM;
49
+ export const DEFAULT_THEME_MODE: ThemeMode = THEME_MODES.LIGHT;
50
50
 
51
51
  /**
52
52
  * Local storage key used to keep the latest browser theme mode in sync.
@@ -1,6 +1,6 @@
1
1
  INSERT INTO "prefix_Metadata" ("key", "value", "note", "createdAt", "updatedAt")
2
2
  SELECT 'DEFAULT_THEME',
3
- 'SYSTEM',
3
+ 'LIGHT',
4
4
  'Default theme mode for browsers without a saved preference. Allowed values: SYSTEM, LIGHT, DARK.',
5
5
  NOW(),
6
6
  NOW()
@@ -9,7 +9,7 @@ WHERE NOT EXISTS (SELECT 1 FROM "prefix_Metadata" WHERE "key" = 'DEFAULT_THEME')
9
9
  UPDATE "prefix_Metadata"
10
10
  SET "value" = CASE
11
11
  WHEN UPPER(COALESCE("value", '')) IN ('SYSTEM', 'LIGHT', 'DARK') THEN UPPER("value")
12
- ELSE 'SYSTEM'
12
+ ELSE 'LIGHT'
13
13
  END,
14
14
  "note" = 'Default theme mode for browsers without a saved preference. Allowed values: SYSTEM, LIGHT, DARK.',
15
15
  "updatedAt" = NOW()
@@ -6,7 +6,6 @@ import { parseAgentSource } from '../../../../src/book-2.0/agent-source/parseAge
6
6
  import type { string_book } from '../../../../src/book-2.0/agent-source/string_book';
7
7
  import { DatabaseError } from '../../../../src/errors/DatabaseError';
8
8
  import { CORE_AGENT_DIRECTORY_NAME, loadCoreAgentBooks } from '../utils/defaultAgents/loadDefaultAgentBooks';
9
- import { DEFAULT_AGENT_VISIBILITY } from '../utils/agentVisibility';
10
9
  import { $provideSupabaseForServer } from './$provideSupabaseForServer';
11
10
 
12
11
  /**
@@ -100,7 +99,6 @@ export async function seedCoreAgents(options: SeedCoreAgentsOptions = {}): Promi
100
99
  const createdAgent = await collection.createAgent(coreAgentBook, {
101
100
  folderId: coreFolderId,
102
101
  sortOrder: index,
103
- visibility: DEFAULT_AGENT_VISIBILITY,
104
102
  });
105
103
  createdAgentNames.push(createdAgent.agentName);
106
104
  logger.info(`Created \`.core\` agent: ${createdAgent.agentName}`);
@@ -2,7 +2,6 @@ import type { SupabaseClient } from '@supabase/supabase-js';
2
2
  import { AgentCollectionInSupabase } from '../../../../src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase';
3
3
  import type { AgentsDatabaseSchema } from '../../../../src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentsDatabaseSchema';
4
4
  import { $provideSupabaseForServer } from './$provideSupabaseForServer';
5
- import { DEFAULT_AGENT_VISIBILITY } from '../utils/agentVisibility';
6
5
  import { loadDefaultAgentBooks } from '../utils/defaultAgents/loadDefaultAgentBooks';
7
6
  import { loadAgentsServerEnvFile } from './loadAgentsServerEnvFile';
8
7
  import { seedCoreAgents } from './seedCoreAgents';
@@ -161,7 +160,6 @@ async function seedDefaultAgentBooks(
161
160
  for (const [index, defaultAgentBook] of defaultAgentBooks.entries()) {
162
161
  const createdAgent = await collection.createAgent(defaultAgentBook, {
163
162
  sortOrder: index,
164
- visibility: DEFAULT_AGENT_VISIBILITY,
165
163
  });
166
164
  createdAgentNames.push(createdAgent.agentName);
167
165
  logger.info(`Created default agent: ${createdAgent.agentName}`);
@@ -8,11 +8,6 @@ import type { ChatMessage } from '@promptbook-local/types';
8
8
  import type { ChatProgressCard, ChatProgressItem } from '../../../../src/book-components/Chat/types/ChatMessage';
9
9
  import { updateUserChatAssistantMessage } from '../utils/userChat/updateUserChatAssistantMessage';
10
10
 
11
- /**
12
- * Internal default title used when the progress card is initialized without explicit heading.
13
- */
14
- const DEFAULT_PROGRESS_TITLE = 'Working on your request';
15
-
16
11
  /**
17
12
  * Maximum markdown length accepted for one progress-card text field.
18
13
  */
@@ -227,7 +222,6 @@ function applyAgentProgressPayloadToMessage(
227
222
  function normalizeStoredProgressCard(rawCard: ChatMessage['progressCard']): ChatProgressCard {
228
223
  if (!rawCard) {
229
224
  return {
230
- title: DEFAULT_PROGRESS_TITLE,
231
225
  items: [],
232
226
  isVisible: true,
233
227
  };
@@ -244,8 +238,10 @@ function normalizeStoredProgressCard(rawCard: ChatMessage['progressCard']): Chat
244
238
  .filter((item) => item.text.length > 0)
245
239
  : [];
246
240
 
241
+ const normalizedTitle = normalizeOptionalText(rawCard.title);
242
+
247
243
  return {
248
- title: normalizeOptionalText(rawCard.title) || DEFAULT_PROGRESS_TITLE,
244
+ ...(normalizedTitle ? { title: normalizedTitle } : {}),
249
245
  now: normalizeOptionalText(rawCard.now) || undefined,
250
246
  next: normalizeOptionalText(rawCard.next) || undefined,
251
247
  items: normalizedItems,
@@ -264,7 +260,7 @@ function applyAgentProgressPayloadToCard(
264
260
  ): ChatProgressCard {
265
261
  if (payload.action === 'initialize') {
266
262
  return {
267
- title: payload.title || DEFAULT_PROGRESS_TITLE,
263
+ ...(payload.title ? { title: payload.title } : {}),
268
264
  ...(payload.now !== undefined ? { now: payload.now } : {}),
269
265
  ...(payload.next !== undefined ? { next: payload.next } : {}),
270
266
  items: payload.items || [],
@@ -290,7 +286,6 @@ function applyAgentProgressPayloadToCard(
290
286
 
291
287
  return {
292
288
  ...currentCard,
293
- title: currentCard.title || DEFAULT_PROGRESS_TITLE,
294
289
  items: existingItems,
295
290
  updatedAt,
296
291
  isVisible: true,
@@ -303,7 +298,6 @@ function applyAgentProgressPayloadToCard(
303
298
  ...(payload.now !== undefined ? { now: payload.now } : {}),
304
299
  ...(payload.next !== undefined ? { next: payload.next } : {}),
305
300
  ...(payload.items !== undefined ? { items: payload.items } : {}),
306
- title: payload.title || currentCard.title || DEFAULT_PROGRESS_TITLE,
307
301
  updatedAt,
308
302
  isVisible: true,
309
303
  };
@@ -1,12 +1,25 @@
1
+ import {
2
+ AGENT_VISIBILITY_VALUES,
3
+ DEFAULT_AGENT_VISIBILITY,
4
+ getNextAgentVisibility,
5
+ isAgentVisibility,
6
+ isPublicAgentVisibility,
7
+ normalizeAgentVisibility,
8
+ parseAgentVisibility,
9
+ parseAgentSourceVisibility,
10
+ setAgentSourceVisibility,
11
+ type AgentVisibility,
12
+ } from '../../../../src/book-2.0/agent-source/agentSourceVisibility';
13
+
1
14
  /**
2
15
  * Supported visibility states for Agents Server agents.
3
16
  */
4
- export const AGENT_VISIBILITY_VALUES = ['PRIVATE', 'UNLISTED', 'PUBLIC'] as const;
17
+ export { AGENT_VISIBILITY_VALUES };
5
18
 
6
19
  /**
7
20
  * Canonical visibility union for agents.
8
21
  */
9
- export type AgentVisibility = (typeof AGENT_VISIBILITY_VALUES)[number];
22
+ export type { AgentVisibility };
10
23
 
11
24
  /**
12
25
  * Shared select options for agent-visibility pickers.
@@ -42,63 +55,13 @@ export const LEGACY_DEFAULT_VISIBILITY_METADATA_KEY = 'DEFAULT_AGENT_VISIBILITY'
42
55
  /**
43
56
  * Fallback visibility used when metadata is missing or invalid.
44
57
  */
45
- export const DEFAULT_AGENT_VISIBILITY: AgentVisibility = 'UNLISTED';
46
-
47
- /**
48
- * Returns `true` when the value is one of supported visibility states.
49
- *
50
- * @param value - Raw value to validate.
51
- * @returns Whether the value is a valid `AgentVisibility`.
52
- */
53
- export function isAgentVisibility(value: unknown): value is AgentVisibility {
54
- return typeof value === 'string' && AGENT_VISIBILITY_VALUES.includes(value as AgentVisibility);
55
- }
56
-
57
- /**
58
- * Parses visibility from an unknown value with a safe fallback.
59
- *
60
- * @param value - Raw visibility value.
61
- * @param fallback - Fallback when the value is invalid.
62
- * @returns Parsed visibility.
63
- */
64
- export function parseAgentVisibility(
65
- value: unknown,
66
- fallback: AgentVisibility = DEFAULT_AGENT_VISIBILITY,
67
- ): AgentVisibility {
68
- if (typeof value !== 'string') {
69
- return fallback;
70
- }
71
-
72
- const normalized = value.trim().toUpperCase();
73
- return isAgentVisibility(normalized) ? normalized : fallback;
74
- }
75
-
76
- /**
77
- * Returns whether an agent should be listed publicly in anonymous views.
78
- *
79
- * @param visibility - Agent visibility to evaluate.
80
- * @returns `true` for publicly listed agents.
81
- */
82
- export function isPublicAgentVisibility(visibility: AgentVisibility | null | undefined): boolean {
83
- return visibility === 'PUBLIC';
84
- }
85
-
86
- /**
87
- * Returns the next visibility in UI rotation order.
88
- *
89
- * @param visibility - Current visibility.
90
- * @returns Next visibility value.
91
- */
92
- export function getNextAgentVisibility(
93
- visibility: AgentVisibility | null | undefined,
94
- ): AgentVisibility {
95
- switch (visibility) {
96
- case 'PRIVATE':
97
- return 'UNLISTED';
98
- case 'UNLISTED':
99
- return 'PUBLIC';
100
- case 'PUBLIC':
101
- default:
102
- return 'PRIVATE';
103
- }
104
- }
58
+ export {
59
+ DEFAULT_AGENT_VISIBILITY,
60
+ getNextAgentVisibility,
61
+ isAgentVisibility,
62
+ isPublicAgentVisibility,
63
+ normalizeAgentVisibility,
64
+ parseAgentVisibility,
65
+ parseAgentSourceVisibility,
66
+ setAgentSourceVisibility,
67
+ };
@@ -10,9 +10,11 @@ export type AdminChatTaskView = 'active' | 'running' | 'queued' | 'failed' | 'al
10
10
  /**
11
11
  * Durable task kinds currently surfaced by the admin task manager.
12
12
  *
13
+ * `VPS_SELF_UPDATE` represents the standalone VPS self-update session triggered from `/admin/update`.
14
+ *
13
15
  * @private internal admin utility of Agents Server
14
16
  */
15
- export type AdminChatTaskKind = 'CHAT_COMPLETION' | 'CHAT_TIMEOUT';
17
+ export type AdminChatTaskKind = 'CHAT_COMPLETION' | 'CHAT_TIMEOUT' | 'VPS_SELF_UPDATE';
16
18
 
17
19
  /**
18
20
  * One row shown in the admin task-manager table.
@@ -1,6 +1,7 @@
1
1
  import type { AgentBasicInformation, AgentCollection, string_book } from '@promptbook-local/types';
2
2
  import type { CreateAgentInput } from '../../../../src/collection/agent-collection/CreateAgentInput';
3
3
  import { assignAgentOwner } from './agentOwnership';
4
+ import { parseAgentSourceVisibility } from './agentVisibility';
4
5
  import { getDefaultAgentVisibility } from './getDefaultAgentVisibility';
5
6
 
6
7
  /**
@@ -27,7 +28,8 @@ export async function createAgentWithDefaultVisibility(
27
28
  options: CreateAgentWithDefaultVisibilityOptions = {},
28
29
  ): Promise<AgentBasicInformation & Required<Pick<AgentBasicInformation, 'permanentId'>>> {
29
30
  const { userId, ...createOptions } = options;
30
- const visibility = options.visibility ?? (await getDefaultAgentVisibility());
31
+ const sourceVisibility = parseAgentSourceVisibility(agentSource, { isStrict: true });
32
+ const visibility = options.visibility ?? sourceVisibility ?? (await getDefaultAgentVisibility());
31
33
 
32
34
  const createdAgent = await collection.createAgent(agentSource, {
33
35
  ...createOptions,
@@ -11,7 +11,10 @@ import { createUserChatRunnerProgressCard } from '../userChat/createUserChatRunn
11
11
  import { updateUserChatAssistantMessage } from '../userChat/updateUserChatAssistantMessage';
12
12
  import type { UserChatJobRecord } from '../userChat/UserChatJobRecord';
13
13
  import type { UserChatJobRow } from '../userChat/UserChatJobRow';
14
- import { resolvePromptThreadBeforeUserMessage } from '../userChat/userChatMessageLifecycle';
14
+ import {
15
+ createUserChatRunnerThreadMessages,
16
+ resolvePromptThreadBeforeUserMessage,
17
+ } from '../userChat/userChatMessageLifecycle';
15
18
  import {
16
19
  EXTERNAL_USER_CHAT_JOB_ANSWER_TIMEOUT_MS,
17
20
  EXTERNAL_USER_CHAT_JOB_PROVIDER,
@@ -150,22 +153,11 @@ async function enqueueExternalUserChatJob(job: UserChatJobRecord): Promise<Proce
150
153
  return { didMutate: false, outcome: 'waiting' };
151
154
  }
152
155
 
153
- const agentInitialMessage = previousThreadMessages.length === 0
154
- ? parseAgentSource(agentSourceSnapshot.agentSource).initialMessage
155
- : null;
156
- const initialAgentThreadMessages = agentInitialMessage
157
- ? [{ sender: 'AGENT' as const, content: agentInitialMessage }]
158
- : [];
159
-
160
- const threadMessages = [
161
- ...initialAgentThreadMessages,
162
- ...[...previousThreadMessages, userMessage]
163
- .filter((message) => message.isComplete !== false)
164
- .filter((message) => message.sender === 'USER' || message.sender === 'AGENT'),
165
- ].map((message) => ({
166
- sender: String(message.sender),
167
- content: message.content,
168
- }));
156
+ const threadMessages = createUserChatRunnerThreadMessages({
157
+ messages: chat.messages,
158
+ userMessageId: job.userMessageId,
159
+ resolveInitialAgentMessage: () => parseAgentSource(agentSourceSnapshot.agentSource).initialMessage,
160
+ });
169
161
 
170
162
  const repository = await ensureExternalAgentRepository(agentSourceSnapshot);
171
163
  const queuedAt = new Date().toISOString();
@@ -0,0 +1,84 @@
1
+ import type { AdminChatTaskRecord } from '../chatTasksAdmin';
2
+ import type { UserChatJobStatus } from '../userChat/UserChatJobRecord';
3
+ import type { VpsSelfUpdateJobSnapshot } from '../vpsSelfUpdate';
4
+
5
+ /**
6
+ * Stable synthetic task id used for the singleton standalone VPS self-update task row.
7
+ *
8
+ * @private internal admin utility of Agents Server
9
+ */
10
+ export const VPS_SELF_UPDATE_ADMIN_CHAT_TASK_ID = 'vps-self-update';
11
+
12
+ /**
13
+ * Synthetic queue name used for the standalone VPS self-update task row.
14
+ *
15
+ * @private internal admin utility of Agents Server
16
+ */
17
+ export const VPS_SELF_UPDATE_ADMIN_CHAT_TASK_QUEUE_NAME = 'vps-self-update';
18
+
19
+ /**
20
+ * Maps a persisted VPS self-update job snapshot to the admin task manager row shape.
21
+ *
22
+ * @param job - Latest persisted self-update job snapshot.
23
+ * @returns Task manager row or `null` when no self-update has ever been triggered on this server.
24
+ */
25
+ export function mapVpsSelfUpdateJobToAdminChatTask(job: VpsSelfUpdateJobSnapshot): AdminChatTaskRecord | null {
26
+ const status = toAdminChatTaskStatus(job);
27
+ if (!status) {
28
+ return null;
29
+ }
30
+
31
+ const isTerminalStatus = status === 'COMPLETED' || status === 'FAILED';
32
+ const startedAt = job.startedAt;
33
+ const finishedAt = isTerminalStatus ? job.finishedAt || startedAt : null;
34
+ const updatedAt = finishedAt || startedAt || new Date().toISOString();
35
+ const errorSummary = job.errorMessage || null;
36
+ const currentStepDetails = job.currentStep || null;
37
+
38
+ return {
39
+ id: VPS_SELF_UPDATE_ADMIN_CHAT_TASK_ID,
40
+ kind: 'VPS_SELF_UPDATE',
41
+ status,
42
+ createdAt: startedAt || updatedAt,
43
+ queuedAt: startedAt || updatedAt,
44
+ startedAt,
45
+ updatedAt,
46
+ finishedAt,
47
+ cancelRequestedAt: null,
48
+ pausedAt: null,
49
+ lastHeartbeatAt: null,
50
+ leaseExpiresAt: null,
51
+ recurrenceIntervalMs: null,
52
+ priority: null,
53
+ attemptCount: 1,
54
+ retryCount: 0,
55
+ lastErrorSummary: errorSummary,
56
+ lastErrorDetails: currentStepDetails,
57
+ userId: 0,
58
+ username: null,
59
+ agentPermanentId: VPS_SELF_UPDATE_ADMIN_CHAT_TASK_ID,
60
+ agentName: job.targetEnvironment.label,
61
+ chatId: job.targetBranch || job.targetEnvironment.branch || VPS_SELF_UPDATE_ADMIN_CHAT_TASK_ID,
62
+ workerId: job.pid !== null ? String(job.pid) : null,
63
+ queueName: VPS_SELF_UPDATE_ADMIN_CHAT_TASK_QUEUE_NAME,
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Maps the shell-owned self-update status to the durable chat-task status enum used by the admin task manager.
69
+ *
70
+ * @param job - Persisted self-update job snapshot.
71
+ * @returns Equivalent durable chat-job status, or `null` when the job is idle (no run has been triggered yet).
72
+ */
73
+ function toAdminChatTaskStatus(job: VpsSelfUpdateJobSnapshot): UserChatJobStatus | null {
74
+ switch (job.status) {
75
+ case 'running':
76
+ return 'RUNNING';
77
+ case 'succeeded':
78
+ return 'COMPLETED';
79
+ case 'failed':
80
+ return 'FAILED';
81
+ case 'idle':
82
+ return null;
83
+ }
84
+ }