@promptbook/cli 0.113.0-5 → 0.113.0-8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/agents-server/src/app/admin/update/AdvancedOriginRepositoryPanel.tsx +76 -0
- package/apps/agents-server/src/app/admin/update/CurrentDeploymentCard.tsx +160 -0
- package/apps/agents-server/src/app/admin/update/PendingCommitsCard.tsx +86 -0
- package/apps/agents-server/src/app/admin/update/TargetEnvironmentCard.tsx +331 -0
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +20 -873
- package/apps/agents-server/src/app/admin/update/UpdateJobCard.tsx +329 -0
- package/apps/agents-server/src/app/admin/update/UpdateOverview.ts +74 -0
- package/apps/agents-server/src/app/admin/update/buildDeploymentTimeBehindLabel.ts +29 -0
- package/apps/agents-server/src/app/admin/update/formatHumanReadableTimestamp.ts +18 -0
- package/apps/agents-server/src/app/admin/update/getUpdateJobFailureMessage.ts +13 -0
- package/apps/agents-server/src/app/admin/update/getUpdateJobSuccessMessage.ts +13 -0
- package/apps/agents-server/src/app/admin/update/useUpdateClientState.ts +441 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageClient.tsx +14 -559
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageHeader.tsx +84 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageSection.tsx +52 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedCodePreview.tsx +138 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedHarnessSection.tsx +98 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/SourceBookSection.tsx +66 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeErrorBanner.tsx +30 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeExportWarningBanner.tsx +62 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/Transpiler.ts +9 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/useAgentCodeExportState.ts +478 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/cloneMockedChatPreset.ts +17 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/confirmDeleteMockedChat.ts +16 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedMessage.ts +81 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedParticipant.ts +146 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedSettings.ts +19 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDuplicatedDraft.ts +66 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/findMockedChatById.ts +51 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/persistMockedChats.ts +51 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/useMockedChatsEditorState.ts +16 -426
- package/apps/agents-server/src/components/Homepage/buildFreeGraphBoxLayout.ts +446 -0
- package/apps/agents-server/src/components/Homepage/buildGraphLayoutNodes.ts +415 -157
- package/apps/agents-server/src/components/Homepage/useAgentsGraphCanvasState.ts +2 -1
- package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +3 -1541
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteQueryBuilder.ts +623 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteSupabaseClient.ts +64 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/ensureTable.ts +93 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteFilters.ts +202 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteMutationPayload.ts +131 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteRowOperations.ts +102 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteSql.ts +59 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTableSchema.ts +329 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTypes.ts +84 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteValueCodec.ts +63 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/normalizeSqliteError.ts +22 -0
- package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
- package/apps/agents-server/src/tools/send_email.ts +1 -2
- package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
- package/apps/agents-server/src/utils/backup/createServerBackupZipStream.ts +7 -1382
- package/apps/agents-server/src/utils/backup/serverBackup/appendAgentBackupEntriesToZip.ts +27 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendConversationBackupEntriesToZip.ts +140 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendFileBackupEntriesToZip.ts +147 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendMessageBackupEntriesToZip.ts +65 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendMetadataBackupEntriesToZip.ts +39 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendSectionEntriesToZip.ts +92 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendUserBackupEntriesToZip.ts +80 -0
- package/apps/agents-server/src/utils/backup/serverBackup/createRedactedWalletBackupRecord.ts +34 -0
- package/apps/agents-server/src/utils/backup/serverBackup/createServerBackupManifest.ts +82 -0
- package/apps/agents-server/src/utils/backup/serverBackup/downloadBackupBinaryContent.ts +39 -0
- package/apps/agents-server/src/utils/backup/serverBackup/resolveFeedbackThreadMessages.ts +53 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupAttachments.ts +151 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupContext.ts +167 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupFilenames.ts +161 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupPreviews.ts +97 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupRowUtilities.ts +158 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupTypes.ts +59 -0
- package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
- package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
- package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
- package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
- package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
- package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
- package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
- package/apps/agents-server/src/utils/messages/sendMessage.ts +5 -3
- package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
- package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
- package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
- package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
- package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition/SpeechToTextFailoverRecognitionProviderRuntime.ts +0 -1
- package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition.ts +34 -2
- package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
- package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
- package/esm/index.es.js +96 -57
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
- package/esm/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
- package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
- package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/avatars/avatarAnimationScheduler.ts +2 -1
- package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
- package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
- package/src/book-components/Chat/Chat/insertDictationChunk.ts +3 -3
- package/src/book-components/Chat/Chat/learnDictationDictionary.ts +1 -1
- package/src/book-components/Chat/Chat/useChatInputAreaDictation.ts +133 -26
- package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
- package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
- package/src/cli/cli-commands/coder/find-refactor-candidates.ts +9 -2
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
- package/src/cli/cli-commands/coder/run.ts +3 -27
- package/src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts +31 -0
- package/src/commitments/TEAM/TEAM.ts +5 -5
- package/src/other/templates/getTemplatesPipelineCollection.ts +727 -781
- package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +1 -4
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +96 -57
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
- package/umd/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
- package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
- package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -5,8 +5,13 @@ import { darken } from '../../../../../src/utils/color/operators/darken';
|
|
|
5
5
|
import { textColor } from '../../../../../src/utils/color/operators/furthest';
|
|
6
6
|
import { lighten } from '../../../../../src/utils/color/operators/lighten';
|
|
7
7
|
import type { Node } from 'reactflow';
|
|
8
|
-
import type { AgentWithVisibility, GraphNode, ServerGroup } from './
|
|
9
|
-
import {
|
|
8
|
+
import type { AgentWithVisibility, GraphLink, GraphNode, ServerGroup } from './buildGraphDataTypes';
|
|
9
|
+
import {
|
|
10
|
+
buildFreeGraphBoxLayout,
|
|
11
|
+
type FreeGraphBoxLayoutLink,
|
|
12
|
+
type FreeGraphBoxLayoutPosition,
|
|
13
|
+
} from './buildFreeGraphBoxLayout';
|
|
14
|
+
import { normalizeServerUrl } from './normalizeServerUrl';
|
|
10
15
|
|
|
11
16
|
/**
|
|
12
17
|
* Width of each rendered agent node.
|
|
@@ -44,67 +49,116 @@ const FOLDER_PADDING_X = 24;
|
|
|
44
49
|
const FOLDER_PADDING_Y = 20;
|
|
45
50
|
|
|
46
51
|
/**
|
|
47
|
-
* Horizontal
|
|
52
|
+
* Horizontal spacing between agent nodes.
|
|
48
53
|
*
|
|
49
54
|
* @private function of AgentsGraph
|
|
50
55
|
*/
|
|
51
|
-
const
|
|
56
|
+
const AGENT_HORIZONTAL_GAP = 16;
|
|
52
57
|
|
|
53
58
|
/**
|
|
54
|
-
* Vertical
|
|
59
|
+
* Vertical spacing between agent nodes.
|
|
55
60
|
*
|
|
56
61
|
* @private function of AgentsGraph
|
|
57
62
|
*/
|
|
58
|
-
const
|
|
63
|
+
const AGENT_VERTICAL_GAP = 16;
|
|
59
64
|
|
|
60
65
|
/**
|
|
61
|
-
*
|
|
66
|
+
* Server title strip height.
|
|
62
67
|
*
|
|
63
68
|
* @private function of AgentsGraph
|
|
64
69
|
*/
|
|
65
|
-
const
|
|
70
|
+
const SERVER_HEADER_HEIGHT = 28;
|
|
66
71
|
|
|
67
72
|
/**
|
|
68
|
-
* Horizontal
|
|
73
|
+
* Horizontal server padding.
|
|
69
74
|
*
|
|
70
75
|
* @private function of AgentsGraph
|
|
71
76
|
*/
|
|
72
|
-
const
|
|
77
|
+
const SERVER_PADDING_X = 32;
|
|
73
78
|
|
|
74
79
|
/**
|
|
75
|
-
* Vertical
|
|
80
|
+
* Vertical server padding.
|
|
76
81
|
*
|
|
77
82
|
* @private function of AgentsGraph
|
|
78
83
|
*/
|
|
79
|
-
const
|
|
84
|
+
const SERVER_PADDING_Y = 24;
|
|
80
85
|
|
|
81
86
|
/**
|
|
82
|
-
*
|
|
87
|
+
* Horizontal gap between server groups.
|
|
83
88
|
*
|
|
84
89
|
* @private function of AgentsGraph
|
|
85
90
|
*/
|
|
86
|
-
const
|
|
91
|
+
const SERVER_GAP_X = 96;
|
|
87
92
|
|
|
88
93
|
/**
|
|
89
|
-
*
|
|
94
|
+
* Vertical gap between server groups.
|
|
90
95
|
*
|
|
91
96
|
* @private function of AgentsGraph
|
|
92
97
|
*/
|
|
93
|
-
const
|
|
98
|
+
const SERVER_GAP_Y = 80;
|
|
94
99
|
|
|
95
100
|
/**
|
|
96
|
-
*
|
|
101
|
+
* Preferred distance between linked agent nodes during layout relaxation.
|
|
97
102
|
*
|
|
98
103
|
* @private function of AgentsGraph
|
|
99
104
|
*/
|
|
100
|
-
const
|
|
105
|
+
const AGENT_RELATIONSHIP_DISTANCE = 96;
|
|
101
106
|
|
|
102
107
|
/**
|
|
103
|
-
*
|
|
108
|
+
* Strength used to pull linked agent nodes together.
|
|
104
109
|
*
|
|
105
110
|
* @private function of AgentsGraph
|
|
106
111
|
*/
|
|
107
|
-
const
|
|
112
|
+
const AGENT_RELATIONSHIP_STRENGTH = 0.045;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Strength used to keep unrelated agent nodes near their seeded placement.
|
|
116
|
+
*
|
|
117
|
+
* @private function of AgentsGraph
|
|
118
|
+
*/
|
|
119
|
+
const AGENT_CENTER_PULL_STRENGTH = 0.014;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Preferred distance between linked folder groups during layout relaxation.
|
|
123
|
+
*
|
|
124
|
+
* @private function of AgentsGraph
|
|
125
|
+
*/
|
|
126
|
+
const FOLDER_RELATIONSHIP_DISTANCE = 180;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Strength used to pull linked folder groups together.
|
|
130
|
+
*
|
|
131
|
+
* @private function of AgentsGraph
|
|
132
|
+
*/
|
|
133
|
+
const FOLDER_RELATIONSHIP_STRENGTH = 0.035;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Strength used to keep unrelated folder groups near their seeded placement.
|
|
137
|
+
*
|
|
138
|
+
* @private function of AgentsGraph
|
|
139
|
+
*/
|
|
140
|
+
const FOLDER_CENTER_PULL_STRENGTH = 0.012;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Preferred distance between linked server groups during layout relaxation.
|
|
144
|
+
*
|
|
145
|
+
* @private function of AgentsGraph
|
|
146
|
+
*/
|
|
147
|
+
const SERVER_RELATIONSHIP_DISTANCE = 260;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Strength used to pull linked server groups together.
|
|
151
|
+
*
|
|
152
|
+
* @private function of AgentsGraph
|
|
153
|
+
*/
|
|
154
|
+
const SERVER_RELATIONSHIP_STRENGTH = 0.028;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Strength used to keep remote server groups around the current server.
|
|
158
|
+
*
|
|
159
|
+
* @private function of AgentsGraph
|
|
160
|
+
*/
|
|
161
|
+
const SERVER_CENTER_PULL_STRENGTH = 0.01;
|
|
108
162
|
|
|
109
163
|
/**
|
|
110
164
|
* Storage key prefix for persisted node positions.
|
|
@@ -132,15 +186,11 @@ type NodeVisualStyle = {
|
|
|
132
186
|
*/
|
|
133
187
|
type FolderLayout = {
|
|
134
188
|
folder: ServerGroup['folders'][number];
|
|
189
|
+
nodeId: string;
|
|
135
190
|
width: number;
|
|
136
191
|
height: number;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
contentHeight: number;
|
|
140
|
-
column?: number;
|
|
141
|
-
row?: number;
|
|
142
|
-
x?: number;
|
|
143
|
-
y?: number;
|
|
192
|
+
agentPositionsById: Map<string, FreeGraphBoxLayoutPosition>;
|
|
193
|
+
orderIndex: number;
|
|
144
194
|
};
|
|
145
195
|
|
|
146
196
|
/**
|
|
@@ -150,9 +200,33 @@ type FolderLayout = {
|
|
|
150
200
|
*/
|
|
151
201
|
type ServerLayout = {
|
|
152
202
|
serverGroup: ServerGroup;
|
|
203
|
+
nodeId: string;
|
|
153
204
|
folderLayouts: FolderLayout[];
|
|
205
|
+
folderPositionsById: Map<string, FreeGraphBoxLayoutPosition>;
|
|
154
206
|
width: number;
|
|
155
207
|
height: number;
|
|
208
|
+
orderIndex: number;
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Hierarchical placement metadata for one agent node.
|
|
213
|
+
*
|
|
214
|
+
* @private function of AgentsGraph
|
|
215
|
+
*/
|
|
216
|
+
type AgentLayoutLocation = {
|
|
217
|
+
serverNodeId: string;
|
|
218
|
+
folderNodeId: string;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Weighted layout link accumulator.
|
|
223
|
+
*
|
|
224
|
+
* @private function of AgentsGraph
|
|
225
|
+
*/
|
|
226
|
+
type AggregatedLayoutLink = {
|
|
227
|
+
sourceId: string;
|
|
228
|
+
targetId: string;
|
|
229
|
+
weight: number;
|
|
156
230
|
};
|
|
157
231
|
|
|
158
232
|
/**
|
|
@@ -299,139 +373,326 @@ export const saveStoredPositions = (storageKey: string, positions: StoredPositio
|
|
|
299
373
|
};
|
|
300
374
|
|
|
301
375
|
/**
|
|
302
|
-
* Build
|
|
303
|
-
*
|
|
304
|
-
* @private function of AgentsGraph
|
|
376
|
+
* Build the stable React Flow server group node id.
|
|
305
377
|
*/
|
|
306
|
-
|
|
307
|
-
serverGroups: ServerGroup[];
|
|
308
|
-
orderIndexByNodeId: Map<string, number>;
|
|
309
|
-
publicUrl: string;
|
|
310
|
-
storedPositions: StoredPositions;
|
|
311
|
-
onNodeOpen: (node: GraphNode) => void;
|
|
312
|
-
}): Node[] => {
|
|
313
|
-
const { serverGroups, orderIndexByNodeId, publicUrl, storedPositions, onNodeOpen } = params;
|
|
314
|
-
const nodes: Node[] = [];
|
|
378
|
+
const buildServerNodeId = (serverUrl: string): string => `server:${serverUrl}`;
|
|
315
379
|
|
|
316
|
-
|
|
317
|
-
|
|
380
|
+
/**
|
|
381
|
+
* Build the stable React Flow folder group node id.
|
|
382
|
+
*/
|
|
383
|
+
const buildFolderNodeId = (serverUrl: string, folderId: number | null): string =>
|
|
384
|
+
`folder:${serverUrl}:${folderId ?? 'root'}`;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Add or increment an undirected layout link.
|
|
388
|
+
*/
|
|
389
|
+
function addAggregatedLayoutLink(
|
|
390
|
+
linksByKey: Map<string, AggregatedLayoutLink>,
|
|
391
|
+
sourceId: string,
|
|
392
|
+
targetId: string,
|
|
393
|
+
): void {
|
|
394
|
+
if (sourceId === targetId) {
|
|
395
|
+
return;
|
|
318
396
|
}
|
|
319
397
|
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const contentWidth = agentColumns * NODE_WIDTH + Math.max(0, agentColumns - 1) * AGENT_HORIZONTAL_GAP;
|
|
326
|
-
const contentHeight = rows * NODE_HEIGHT + Math.max(0, rows - 1) * AGENT_VERTICAL_GAP;
|
|
327
|
-
const width = Math.max(contentWidth + FOLDER_PADDING_X * 2, NODE_WIDTH + FOLDER_PADDING_X * 2);
|
|
328
|
-
const height = Math.max(
|
|
329
|
-
contentHeight + FOLDER_PADDING_Y * 2 + FOLDER_HEADER_HEIGHT,
|
|
330
|
-
NODE_HEIGHT + FOLDER_PADDING_Y * 2 + FOLDER_HEADER_HEIGHT,
|
|
331
|
-
);
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
folder,
|
|
335
|
-
width,
|
|
336
|
-
height,
|
|
337
|
-
agentColumns,
|
|
338
|
-
contentWidth,
|
|
339
|
-
contentHeight,
|
|
340
|
-
};
|
|
341
|
-
});
|
|
398
|
+
const isSourceFirst = sourceId.localeCompare(targetId) <= 0;
|
|
399
|
+
const normalizedSourceId = isSourceFirst ? sourceId : targetId;
|
|
400
|
+
const normalizedTargetId = isSourceFirst ? targetId : sourceId;
|
|
401
|
+
const key = `${normalizedSourceId}->${normalizedTargetId}`;
|
|
402
|
+
const existingLink = linksByKey.get(key);
|
|
342
403
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
folderLayouts.forEach((layout, index) => {
|
|
349
|
-
const column = index % folderColumnCount;
|
|
350
|
-
const row = Math.floor(index / folderColumnCount);
|
|
351
|
-
layout.column = column;
|
|
352
|
-
layout.row = row;
|
|
353
|
-
columnWidths[column] = Math.max(columnWidths[column], layout.width);
|
|
354
|
-
rowHeights[row] = Math.max(rowHeights[row], layout.height);
|
|
355
|
-
});
|
|
404
|
+
if (existingLink) {
|
|
405
|
+
existingLink.weight += 1;
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
356
408
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
409
|
+
linksByKey.set(key, {
|
|
410
|
+
sourceId: normalizedSourceId,
|
|
411
|
+
targetId: normalizedTargetId,
|
|
412
|
+
weight: 1,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
364
415
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Convert aggregated layout links to the free-layout helper shape.
|
|
418
|
+
*/
|
|
419
|
+
function finalizeAggregatedLayoutLinks(linksByKey: ReadonlyMap<string, AggregatedLayoutLink>): FreeGraphBoxLayoutLink[] {
|
|
420
|
+
return Array.from(linksByKey.values()).map((link) => ({
|
|
421
|
+
sourceId: link.sourceId,
|
|
422
|
+
targetId: link.targetId,
|
|
423
|
+
weight: link.weight,
|
|
424
|
+
}));
|
|
425
|
+
}
|
|
372
426
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
427
|
+
/**
|
|
428
|
+
* Build server and folder lookup metadata for every agent node.
|
|
429
|
+
*/
|
|
430
|
+
function buildAgentLayoutLocationById(serverGroups: ReadonlyArray<ServerGroup>): Map<string, AgentLayoutLocation> {
|
|
431
|
+
const agentLayoutLocationById = new Map<string, AgentLayoutLocation>();
|
|
377
432
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
433
|
+
serverGroups.forEach((serverGroup) => {
|
|
434
|
+
const serverNodeId = buildServerNodeId(serverGroup.serverUrl);
|
|
435
|
+
|
|
436
|
+
serverGroup.folders.forEach((folder) => {
|
|
437
|
+
const folderNodeId = buildFolderNodeId(serverGroup.serverUrl, folder.id);
|
|
438
|
+
|
|
439
|
+
folder.agents.forEach((agent) => {
|
|
440
|
+
agentLayoutLocationById.set(agent.id, {
|
|
441
|
+
serverNodeId,
|
|
442
|
+
folderNodeId,
|
|
443
|
+
});
|
|
444
|
+
});
|
|
445
|
+
});
|
|
389
446
|
});
|
|
390
447
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
448
|
+
return agentLayoutLocationById;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Build weighted layout links between agents inside one folder.
|
|
453
|
+
*/
|
|
454
|
+
function buildAgentLayoutLinks(
|
|
455
|
+
folder: ServerGroup['folders'][number],
|
|
456
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
457
|
+
): FreeGraphBoxLayoutLink[] {
|
|
458
|
+
const agentIds = new Set(folder.agents.map((agent) => agent.id));
|
|
459
|
+
const linksByKey = new Map<string, AggregatedLayoutLink>();
|
|
460
|
+
|
|
461
|
+
graphLinks.forEach((link) => {
|
|
462
|
+
if (!agentIds.has(link.source) || !agentIds.has(link.target)) {
|
|
463
|
+
return;
|
|
404
464
|
}
|
|
405
|
-
}
|
|
406
465
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
466
|
+
addAggregatedLayoutLink(linksByKey, link.source, link.target);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
return finalizeAggregatedLayoutLinks(linksByKey);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Build weighted layout links between folders inside one server.
|
|
474
|
+
*/
|
|
475
|
+
function buildFolderLayoutLinks(
|
|
476
|
+
serverNodeId: string,
|
|
477
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
478
|
+
agentLayoutLocationById: ReadonlyMap<string, AgentLayoutLocation>,
|
|
479
|
+
): FreeGraphBoxLayoutLink[] {
|
|
480
|
+
const linksByKey = new Map<string, AggregatedLayoutLink>();
|
|
481
|
+
|
|
482
|
+
graphLinks.forEach((link) => {
|
|
483
|
+
const sourceLocation = agentLayoutLocationById.get(link.source);
|
|
484
|
+
const targetLocation = agentLayoutLocationById.get(link.target);
|
|
485
|
+
|
|
486
|
+
if (!sourceLocation || !targetLocation) {
|
|
487
|
+
return;
|
|
412
488
|
}
|
|
413
|
-
|
|
414
|
-
|
|
489
|
+
|
|
490
|
+
if (sourceLocation.serverNodeId !== serverNodeId || targetLocation.serverNodeId !== serverNodeId) {
|
|
491
|
+
return;
|
|
415
492
|
}
|
|
416
|
-
|
|
493
|
+
|
|
494
|
+
addAggregatedLayoutLink(linksByKey, sourceLocation.folderNodeId, targetLocation.folderNodeId);
|
|
417
495
|
});
|
|
418
496
|
|
|
419
|
-
|
|
420
|
-
|
|
497
|
+
return finalizeAggregatedLayoutLinks(linksByKey);
|
|
498
|
+
}
|
|
421
499
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
500
|
+
/**
|
|
501
|
+
* Build weighted layout links between server groups.
|
|
502
|
+
*/
|
|
503
|
+
function buildServerLayoutLinks(
|
|
504
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
505
|
+
agentLayoutLocationById: ReadonlyMap<string, AgentLayoutLocation>,
|
|
506
|
+
): FreeGraphBoxLayoutLink[] {
|
|
507
|
+
const linksByKey = new Map<string, AggregatedLayoutLink>();
|
|
508
|
+
|
|
509
|
+
graphLinks.forEach((link) => {
|
|
510
|
+
const sourceLocation = agentLayoutLocationById.get(link.source);
|
|
511
|
+
const targetLocation = agentLayoutLocationById.get(link.target);
|
|
512
|
+
|
|
513
|
+
if (!sourceLocation || !targetLocation) {
|
|
425
514
|
return;
|
|
426
515
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
516
|
+
|
|
517
|
+
addAggregatedLayoutLink(linksByKey, sourceLocation.serverNodeId, targetLocation.serverNodeId);
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
return finalizeAggregatedLayoutLinks(linksByKey);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Build the free-layout dimensions and node positions for one folder.
|
|
525
|
+
*/
|
|
526
|
+
function buildFolderLayout(
|
|
527
|
+
serverUrl: string,
|
|
528
|
+
folder: ServerGroup['folders'][number],
|
|
529
|
+
orderIndex: number,
|
|
530
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
531
|
+
): FolderLayout {
|
|
532
|
+
const nodeId = buildFolderNodeId(serverUrl, folder.id);
|
|
533
|
+
const agentLayout = buildFreeGraphBoxLayout(
|
|
534
|
+
folder.agents.map((agent, agentIndex) => ({
|
|
535
|
+
id: agent.id,
|
|
536
|
+
width: NODE_WIDTH,
|
|
537
|
+
height: NODE_HEIGHT,
|
|
538
|
+
orderIndex: agentIndex,
|
|
539
|
+
})),
|
|
540
|
+
buildAgentLayoutLinks(folder, graphLinks),
|
|
541
|
+
{
|
|
542
|
+
paddingX: FOLDER_PADDING_X,
|
|
543
|
+
paddingY: FOLDER_PADDING_Y,
|
|
544
|
+
gapX: AGENT_HORIZONTAL_GAP,
|
|
545
|
+
gapY: AGENT_VERTICAL_GAP,
|
|
546
|
+
relationshipDistance: AGENT_RELATIONSHIP_DISTANCE,
|
|
547
|
+
relationshipStrength: AGENT_RELATIONSHIP_STRENGTH,
|
|
548
|
+
centerPullStrength: AGENT_CENTER_PULL_STRENGTH,
|
|
549
|
+
},
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
return {
|
|
553
|
+
folder,
|
|
554
|
+
nodeId,
|
|
555
|
+
width: Math.max(agentLayout.width, NODE_WIDTH + FOLDER_PADDING_X * 2),
|
|
556
|
+
height: Math.max(agentLayout.height + FOLDER_HEADER_HEIGHT, NODE_HEIGHT + FOLDER_PADDING_Y * 2 + FOLDER_HEADER_HEIGHT),
|
|
557
|
+
agentPositionsById: agentLayout.positionsById,
|
|
558
|
+
orderIndex,
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Build the free-layout dimensions and folder positions for one server.
|
|
564
|
+
*/
|
|
565
|
+
function buildServerLayout(
|
|
566
|
+
serverGroup: ServerGroup,
|
|
567
|
+
orderIndex: number,
|
|
568
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
569
|
+
agentLayoutLocationById: ReadonlyMap<string, AgentLayoutLocation>,
|
|
570
|
+
): ServerLayout {
|
|
571
|
+
const nodeId = buildServerNodeId(serverGroup.serverUrl);
|
|
572
|
+
const folderLayouts = serverGroup.folders.map((folder, folderIndex) =>
|
|
573
|
+
buildFolderLayout(serverGroup.serverUrl, folder, folderIndex, graphLinks),
|
|
574
|
+
);
|
|
575
|
+
const rootFolder = folderLayouts.find((folderLayout) => folderLayout.folder.id === null);
|
|
576
|
+
const folderLayout = buildFreeGraphBoxLayout(
|
|
577
|
+
folderLayouts.map((layout) => ({
|
|
578
|
+
id: layout.nodeId,
|
|
579
|
+
width: layout.width,
|
|
580
|
+
height: layout.height,
|
|
581
|
+
orderIndex: layout.orderIndex,
|
|
582
|
+
})),
|
|
583
|
+
buildFolderLayoutLinks(nodeId, graphLinks, agentLayoutLocationById),
|
|
584
|
+
{
|
|
585
|
+
paddingX: SERVER_PADDING_X,
|
|
586
|
+
paddingY: SERVER_PADDING_Y,
|
|
587
|
+
gapX: FOLDER_PADDING_X * 2,
|
|
588
|
+
gapY: FOLDER_PADDING_Y * 2,
|
|
589
|
+
relationshipDistance: FOLDER_RELATIONSHIP_DISTANCE,
|
|
590
|
+
relationshipStrength: FOLDER_RELATIONSHIP_STRENGTH,
|
|
591
|
+
centerPullStrength: FOLDER_CENTER_PULL_STRENGTH,
|
|
592
|
+
centerItemId: rootFolder?.nodeId,
|
|
593
|
+
},
|
|
594
|
+
);
|
|
595
|
+
|
|
596
|
+
return {
|
|
597
|
+
serverGroup,
|
|
598
|
+
nodeId,
|
|
599
|
+
folderLayouts,
|
|
600
|
+
folderPositionsById: folderLayout.positionsById,
|
|
601
|
+
width: Math.max(folderLayout.width, NODE_WIDTH + SERVER_PADDING_X * 2),
|
|
602
|
+
height: Math.max(folderLayout.height + SERVER_HEADER_HEIGHT, NODE_HEIGHT + SERVER_PADDING_Y * 2 + SERVER_HEADER_HEIGHT),
|
|
603
|
+
orderIndex,
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Build free-layout server group positions while keeping the current server centered.
|
|
609
|
+
*/
|
|
610
|
+
function buildServerPositionsById(
|
|
611
|
+
serverLayouts: ReadonlyArray<ServerLayout>,
|
|
612
|
+
graphLinks: ReadonlyArray<GraphLink>,
|
|
613
|
+
agentLayoutLocationById: ReadonlyMap<string, AgentLayoutLocation>,
|
|
614
|
+
publicUrl: string,
|
|
615
|
+
): Map<string, FreeGraphBoxLayoutPosition> {
|
|
616
|
+
const normalizedPublicUrl = normalizeServerUrl(publicUrl);
|
|
617
|
+
const currentServerNodeId = buildServerNodeId(normalizedPublicUrl);
|
|
618
|
+
const centerServerLayout =
|
|
619
|
+
serverLayouts.find((layout) => layout.nodeId === currentServerNodeId) || serverLayouts[0] || null;
|
|
620
|
+
const serverLayout = buildFreeGraphBoxLayout(
|
|
621
|
+
serverLayouts.map((layout) => ({
|
|
622
|
+
id: layout.nodeId,
|
|
623
|
+
width: layout.width,
|
|
624
|
+
height: layout.height,
|
|
625
|
+
orderIndex: layout.orderIndex,
|
|
626
|
+
})),
|
|
627
|
+
buildServerLayoutLinks(graphLinks, agentLayoutLocationById),
|
|
628
|
+
{
|
|
629
|
+
paddingX: 0,
|
|
630
|
+
paddingY: 0,
|
|
631
|
+
gapX: SERVER_GAP_X,
|
|
632
|
+
gapY: SERVER_GAP_Y,
|
|
633
|
+
relationshipDistance: SERVER_RELATIONSHIP_DISTANCE,
|
|
634
|
+
relationshipStrength: SERVER_RELATIONSHIP_STRENGTH,
|
|
635
|
+
centerPullStrength: SERVER_CENTER_PULL_STRENGTH,
|
|
636
|
+
centerItemId: centerServerLayout?.nodeId,
|
|
637
|
+
},
|
|
638
|
+
);
|
|
639
|
+
|
|
640
|
+
if (!centerServerLayout) {
|
|
641
|
+
return serverLayout.positionsById;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
const centerServerPosition = serverLayout.positionsById.get(centerServerLayout.nodeId);
|
|
645
|
+
if (!centerServerPosition) {
|
|
646
|
+
return serverLayout.positionsById;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const centerX = centerServerPosition.x + centerServerLayout.width / 2;
|
|
650
|
+
const centerY = centerServerPosition.y + centerServerLayout.height / 2;
|
|
651
|
+
const centeredPositionsById = new Map<string, FreeGraphBoxLayoutPosition>();
|
|
652
|
+
|
|
653
|
+
serverLayout.positionsById.forEach((position, serverNodeId) => {
|
|
654
|
+
centeredPositionsById.set(serverNodeId, {
|
|
655
|
+
x: position.x - centerX,
|
|
656
|
+
y: position.y - centerY,
|
|
657
|
+
});
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
return centeredPositionsById;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/**
|
|
664
|
+
* Build nodes for servers, folders, and agents using a hierarchical free layout that keeps the current server centered.
|
|
665
|
+
*
|
|
666
|
+
* @private function of AgentsGraph
|
|
667
|
+
*/
|
|
668
|
+
export const buildGraphLayoutNodes = (params: {
|
|
669
|
+
serverGroups: ServerGroup[];
|
|
670
|
+
links: GraphLink[];
|
|
671
|
+
orderIndexByNodeId: Map<string, number>;
|
|
672
|
+
publicUrl: string;
|
|
673
|
+
storedPositions: StoredPositions;
|
|
674
|
+
onNodeOpen: (node: GraphNode) => void;
|
|
675
|
+
}): Node[] => {
|
|
676
|
+
const { serverGroups, links, orderIndexByNodeId, publicUrl, storedPositions, onNodeOpen } = params;
|
|
677
|
+
const nodes: Node[] = [];
|
|
678
|
+
|
|
679
|
+
if (serverGroups.length === 0) {
|
|
680
|
+
return nodes;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const agentLayoutLocationById = buildAgentLayoutLocationById(serverGroups);
|
|
684
|
+
const serverLayouts = serverGroups.map((serverGroup, serverIndex) =>
|
|
685
|
+
buildServerLayout(serverGroup, serverIndex, links, agentLayoutLocationById),
|
|
686
|
+
);
|
|
687
|
+
const serverPositionsById = buildServerPositionsById(serverLayouts, links, agentLayoutLocationById, publicUrl);
|
|
688
|
+
|
|
689
|
+
serverLayouts.forEach((layout) => {
|
|
690
|
+
const serverPosition = serverPositionsById.get(layout.nodeId) ?? { x: 0, y: 0 };
|
|
430
691
|
|
|
431
692
|
nodes.push({
|
|
432
|
-
id:
|
|
693
|
+
id: layout.nodeId,
|
|
433
694
|
type: 'serverGroup',
|
|
434
|
-
position:
|
|
695
|
+
position: serverPosition,
|
|
435
696
|
data: {
|
|
436
697
|
label: layout.serverGroup.label,
|
|
437
698
|
agentCount: layout.serverGroup.folders.reduce((sum, folder) => sum + folder.agents.length, 0),
|
|
@@ -447,15 +708,19 @@ export const buildGraphLayoutNodes = (params: {
|
|
|
447
708
|
});
|
|
448
709
|
|
|
449
710
|
layout.folderLayouts.forEach((folderLayout) => {
|
|
450
|
-
const
|
|
711
|
+
const folderPosition = layout.folderPositionsById.get(folderLayout.nodeId) ?? {
|
|
712
|
+
x: SERVER_PADDING_X,
|
|
713
|
+
y: SERVER_PADDING_Y,
|
|
714
|
+
};
|
|
715
|
+
|
|
451
716
|
nodes.push({
|
|
452
|
-
id:
|
|
717
|
+
id: folderLayout.nodeId,
|
|
453
718
|
type: 'folderGroup',
|
|
454
|
-
parentId:
|
|
719
|
+
parentId: layout.nodeId,
|
|
455
720
|
extent: 'parent',
|
|
456
721
|
position: {
|
|
457
|
-
x:
|
|
458
|
-
y:
|
|
722
|
+
x: folderPosition.x,
|
|
723
|
+
y: SERVER_HEADER_HEIGHT + folderPosition.y,
|
|
459
724
|
},
|
|
460
725
|
data: {
|
|
461
726
|
label: folderLayout.folder.label,
|
|
@@ -470,7 +735,7 @@ export const buildGraphLayoutNodes = (params: {
|
|
|
470
735
|
draggable: false,
|
|
471
736
|
});
|
|
472
737
|
|
|
473
|
-
folderLayout.folder.agents.forEach((agent
|
|
738
|
+
folderLayout.folder.agents.forEach((agent) => {
|
|
474
739
|
const { imageUrl, placeholderUrl } = getAgentImageUrls(agent.agent, publicUrl);
|
|
475
740
|
const style = buildAgentChipStyle(agent.agent);
|
|
476
741
|
const orderIndex = orderIndexByNodeId.get(agent.id) ?? null;
|
|
@@ -479,27 +744,20 @@ export const buildGraphLayoutNodes = (params: {
|
|
|
479
744
|
tooltipParts.push(`Folder: ${folderLayout.folder.label}`);
|
|
480
745
|
}
|
|
481
746
|
const tooltip = tooltipParts.filter(Boolean).join('\n');
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
const horizontalOffset = Math.max(0, (horizontalAvailable - folderLayout.contentWidth) / 2);
|
|
487
|
-
const agentX = FOLDER_PADDING_X + horizontalOffset + column * (NODE_WIDTH + AGENT_HORIZONTAL_GAP);
|
|
488
|
-
const verticalAvailable = folderLayout.height - FOLDER_PADDING_Y * 2 - FOLDER_HEADER_HEIGHT;
|
|
489
|
-
const verticalOffset = Math.max(0, (verticalAvailable - folderLayout.contentHeight) / 2);
|
|
490
|
-
const agentY =
|
|
491
|
-
FOLDER_HEADER_HEIGHT + FOLDER_PADDING_Y + verticalOffset + row * (NODE_HEIGHT + AGENT_VERTICAL_GAP);
|
|
492
|
-
|
|
747
|
+
const agentPosition = folderLayout.agentPositionsById.get(agent.id) ?? {
|
|
748
|
+
x: FOLDER_PADDING_X,
|
|
749
|
+
y: FOLDER_PADDING_Y,
|
|
750
|
+
};
|
|
493
751
|
const storedPosition = storedPositions[agent.id];
|
|
494
752
|
const finalPosition =
|
|
495
|
-
storedPosition && storedPosition.parentId ===
|
|
753
|
+
storedPosition && storedPosition.parentId === folderLayout.nodeId
|
|
496
754
|
? { x: storedPosition.x, y: storedPosition.y }
|
|
497
|
-
: { x:
|
|
755
|
+
: { x: agentPosition.x, y: FOLDER_HEADER_HEIGHT + agentPosition.y };
|
|
498
756
|
|
|
499
757
|
nodes.push({
|
|
500
758
|
id: agent.id,
|
|
501
759
|
type: 'agent',
|
|
502
|
-
parentId:
|
|
760
|
+
parentId: folderLayout.nodeId,
|
|
503
761
|
extent: 'parent',
|
|
504
762
|
position: finalPosition,
|
|
505
763
|
data: {
|