@promptbook/cli 0.113.0-4 → 0.113.0-8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/apps/agents-server/src/app/admin/update/AdvancedOriginRepositoryPanel.tsx +76 -0
  2. package/apps/agents-server/src/app/admin/update/CurrentDeploymentCard.tsx +160 -0
  3. package/apps/agents-server/src/app/admin/update/PendingCommitsCard.tsx +86 -0
  4. package/apps/agents-server/src/app/admin/update/TargetEnvironmentCard.tsx +331 -0
  5. package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +20 -873
  6. package/apps/agents-server/src/app/admin/update/UpdateJobCard.tsx +329 -0
  7. package/apps/agents-server/src/app/admin/update/UpdateOverview.ts +74 -0
  8. package/apps/agents-server/src/app/admin/update/buildDeploymentTimeBehindLabel.ts +29 -0
  9. package/apps/agents-server/src/app/admin/update/formatHumanReadableTimestamp.ts +18 -0
  10. package/apps/agents-server/src/app/admin/update/getUpdateJobFailureMessage.ts +13 -0
  11. package/apps/agents-server/src/app/admin/update/getUpdateJobSuccessMessage.ts +13 -0
  12. package/apps/agents-server/src/app/admin/update/useUpdateClientState.ts +441 -0
  13. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
  14. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageClient.tsx +14 -559
  15. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageHeader.tsx +84 -0
  16. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageSection.tsx +52 -0
  17. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedCodePreview.tsx +138 -0
  18. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedHarnessSection.tsx +98 -0
  19. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/SourceBookSection.tsx +66 -0
  20. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeErrorBanner.tsx +30 -0
  21. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeExportWarningBanner.tsx +62 -0
  22. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/Transpiler.ts +9 -0
  23. package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/useAgentCodeExportState.ts +478 -0
  24. package/apps/agents-server/src/app/system/utilities/mocked-chats/cloneMockedChatPreset.ts +17 -0
  25. package/apps/agents-server/src/app/system/utilities/mocked-chats/confirmDeleteMockedChat.ts +16 -0
  26. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedMessage.ts +81 -0
  27. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedParticipant.ts +146 -0
  28. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedSettings.ts +19 -0
  29. package/apps/agents-server/src/app/system/utilities/mocked-chats/createDuplicatedDraft.ts +66 -0
  30. package/apps/agents-server/src/app/system/utilities/mocked-chats/findMockedChatById.ts +51 -0
  31. package/apps/agents-server/src/app/system/utilities/mocked-chats/persistMockedChats.ts +51 -0
  32. package/apps/agents-server/src/app/system/utilities/mocked-chats/useMockedChatsEditorState.ts +16 -426
  33. package/apps/agents-server/src/components/Homepage/buildFreeGraphBoxLayout.ts +446 -0
  34. package/apps/agents-server/src/components/Homepage/buildGraphLayoutNodes.ts +415 -157
  35. package/apps/agents-server/src/components/Homepage/useAgentsGraphCanvasState.ts +2 -1
  36. package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +3 -1541
  37. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteQueryBuilder.ts +623 -0
  38. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteSupabaseClient.ts +64 -0
  39. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/ensureTable.ts +93 -0
  40. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteFilters.ts +202 -0
  41. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteMutationPayload.ts +131 -0
  42. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteRowOperations.ts +102 -0
  43. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteSql.ts +59 -0
  44. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTableSchema.ts +329 -0
  45. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTypes.ts +84 -0
  46. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteValueCodec.ts +63 -0
  47. package/apps/agents-server/src/database/sqlite/localSqliteSupabase/normalizeSqliteError.ts +22 -0
  48. package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
  49. package/apps/agents-server/src/tools/send_email.ts +1 -2
  50. package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
  51. package/apps/agents-server/src/utils/backup/createServerBackupZipStream.ts +7 -1382
  52. package/apps/agents-server/src/utils/backup/serverBackup/appendAgentBackupEntriesToZip.ts +27 -0
  53. package/apps/agents-server/src/utils/backup/serverBackup/appendConversationBackupEntriesToZip.ts +140 -0
  54. package/apps/agents-server/src/utils/backup/serverBackup/appendFileBackupEntriesToZip.ts +147 -0
  55. package/apps/agents-server/src/utils/backup/serverBackup/appendMessageBackupEntriesToZip.ts +65 -0
  56. package/apps/agents-server/src/utils/backup/serverBackup/appendMetadataBackupEntriesToZip.ts +39 -0
  57. package/apps/agents-server/src/utils/backup/serverBackup/appendSectionEntriesToZip.ts +92 -0
  58. package/apps/agents-server/src/utils/backup/serverBackup/appendUserBackupEntriesToZip.ts +80 -0
  59. package/apps/agents-server/src/utils/backup/serverBackup/createRedactedWalletBackupRecord.ts +34 -0
  60. package/apps/agents-server/src/utils/backup/serverBackup/createServerBackupManifest.ts +82 -0
  61. package/apps/agents-server/src/utils/backup/serverBackup/downloadBackupBinaryContent.ts +39 -0
  62. package/apps/agents-server/src/utils/backup/serverBackup/resolveFeedbackThreadMessages.ts +53 -0
  63. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupAttachments.ts +151 -0
  64. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupContext.ts +167 -0
  65. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupFilenames.ts +161 -0
  66. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupPreviews.ts +97 -0
  67. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupRowUtilities.ts +158 -0
  68. package/apps/agents-server/src/utils/backup/serverBackup/serverBackupTypes.ts +59 -0
  69. package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
  70. package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
  71. package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
  72. package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
  73. package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
  74. package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
  75. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
  76. package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
  77. package/apps/agents-server/src/utils/messages/sendMessage.ts +5 -3
  78. package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
  79. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
  80. package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
  81. package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
  82. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition/SpeechToTextFailoverRecognitionProviderRuntime.ts +0 -1
  83. package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition.ts +34 -2
  84. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
  85. package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
  86. package/esm/index.es.js +875 -60
  87. package/esm/index.es.js.map +1 -1
  88. package/esm/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  89. package/esm/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  90. package/esm/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
  91. package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
  92. package/esm/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
  93. package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
  94. package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
  95. package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  96. package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  97. package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  98. package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  99. package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  100. package/esm/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  101. package/esm/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  102. package/esm/src/version.d.ts +1 -1
  103. package/package.json +1 -1
  104. package/src/avatars/avatarAnimationScheduler.ts +2 -1
  105. package/src/avatars/renderAvatarVisualAsciiArt.ts +138 -0
  106. package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
  107. package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
  108. package/src/book-components/Chat/Chat/insertDictationChunk.ts +3 -3
  109. package/src/book-components/Chat/Chat/learnDictationDictionary.ts +1 -1
  110. package/src/book-components/Chat/Chat/useChatInputAreaDictation.ts +133 -26
  111. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
  112. package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
  113. package/src/cli/cli-commands/coder/find-refactor-candidates.ts +9 -2
  114. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
  115. package/src/cli/cli-commands/coder/run.ts +3 -27
  116. package/src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts +31 -0
  117. package/src/commitments/TEAM/TEAM.ts +5 -5
  118. package/src/other/templates/getTemplatesPipelineCollection.ts +770 -1169
  119. package/src/utils/ascii-art/$detectTerminalAnsiColorDepth.ts +45 -0
  120. package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +396 -0
  121. package/src/version.ts +2 -2
  122. package/src/versions.txt +2 -0
  123. package/umd/index.umd.js +875 -60
  124. package/umd/index.umd.js.map +1 -1
  125. package/umd/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
  126. package/umd/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
  127. package/umd/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
  128. package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
  129. package/umd/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
  130. package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
  131. package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
  132. package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
  133. package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
  134. package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
  135. package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
  136. package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
  137. package/umd/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  138. package/umd/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  139. package/umd/src/version.d.ts +1 -1
  140. package/esm/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
  141. package/umd/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
@@ -0,0 +1,446 @@
1
+ /**
2
+ * Default number of relaxation passes used by the free graph box layout.
3
+ *
4
+ * @private function of AgentsGraph
5
+ */
6
+ const DEFAULT_LAYOUT_ITERATION_COUNT = 96;
7
+
8
+ /**
9
+ * Minimum distance used when two layout boxes start at the same point.
10
+ *
11
+ * @private function of AgentsGraph
12
+ */
13
+ const MINIMUM_DISTANCE = 0.001;
14
+
15
+ /**
16
+ * Default weight for a graph relation when no explicit weight is provided.
17
+ *
18
+ * @private function of AgentsGraph
19
+ */
20
+ const DEFAULT_LINK_WEIGHT = 1;
21
+
22
+ /**
23
+ * Layout box used by the deterministic free graph layout.
24
+ *
25
+ * @private function of AgentsGraph
26
+ */
27
+ export type FreeGraphBoxLayoutItem = {
28
+ id: string;
29
+ width: number;
30
+ height: number;
31
+ orderIndex: number;
32
+ };
33
+
34
+ /**
35
+ * Weighted relationship between two layout boxes.
36
+ *
37
+ * @private function of AgentsGraph
38
+ */
39
+ export type FreeGraphBoxLayoutLink = {
40
+ sourceId: string;
41
+ targetId: string;
42
+ weight?: number;
43
+ };
44
+
45
+ /**
46
+ * Normalized top-left layout position for one box.
47
+ *
48
+ * @private function of AgentsGraph
49
+ */
50
+ export type FreeGraphBoxLayoutPosition = {
51
+ x: number;
52
+ y: number;
53
+ };
54
+
55
+ /**
56
+ * Options controlling the deterministic free graph layout.
57
+ *
58
+ * @private function of AgentsGraph
59
+ */
60
+ export type FreeGraphBoxLayoutOptions = {
61
+ paddingX: number;
62
+ paddingY: number;
63
+ gapX: number;
64
+ gapY: number;
65
+ relationshipDistance: number;
66
+ relationshipStrength: number;
67
+ centerPullStrength: number;
68
+ centerItemId?: string;
69
+ iterationCount?: number;
70
+ };
71
+
72
+ /**
73
+ * Result of laying out graph boxes inside one parent coordinate system.
74
+ *
75
+ * @private function of AgentsGraph
76
+ */
77
+ export type FreeGraphBoxLayoutResult = {
78
+ width: number;
79
+ height: number;
80
+ positionsById: Map<string, FreeGraphBoxLayoutPosition>;
81
+ };
82
+
83
+ /**
84
+ * Mutable item state used during layout relaxation.
85
+ *
86
+ * @private function of AgentsGraph
87
+ */
88
+ type FreeGraphBoxLayoutState = FreeGraphBoxLayoutItem & {
89
+ x: number;
90
+ y: number;
91
+ initialX: number;
92
+ initialY: number;
93
+ isCentered: boolean;
94
+ };
95
+
96
+ /**
97
+ * Integer center-out grid coordinate used for deterministic initial placement.
98
+ *
99
+ * @private function of AgentsGraph
100
+ */
101
+ type CenterOutCoordinate = {
102
+ column: number;
103
+ row: number;
104
+ };
105
+
106
+ /**
107
+ * Return the relationship weight attached to a layout item.
108
+ *
109
+ * @param links - Weighted graph links.
110
+ * @returns Relationship weight indexed by item id.
111
+ *
112
+ * @private function of AgentsGraph
113
+ */
114
+ function buildRelationshipWeightByItemId(links: ReadonlyArray<FreeGraphBoxLayoutLink>): Map<string, number> {
115
+ const relationshipWeightByItemId = new Map<string, number>();
116
+
117
+ links.forEach((link) => {
118
+ const weight = link.weight ?? DEFAULT_LINK_WEIGHT;
119
+ relationshipWeightByItemId.set(link.sourceId, (relationshipWeightByItemId.get(link.sourceId) ?? 0) + weight);
120
+ relationshipWeightByItemId.set(link.targetId, (relationshipWeightByItemId.get(link.targetId) ?? 0) + weight);
121
+ });
122
+
123
+ return relationshipWeightByItemId;
124
+ }
125
+
126
+ /**
127
+ * Sort layout boxes so the most structurally important item starts near the middle.
128
+ *
129
+ * @param items - Source layout boxes.
130
+ * @param links - Weighted graph links.
131
+ * @param centerItemId - Optional item that must remain in the visual center.
132
+ * @returns Ordered layout boxes.
133
+ *
134
+ * @private function of AgentsGraph
135
+ */
136
+ function sortLayoutItemsByImportance(
137
+ items: ReadonlyArray<FreeGraphBoxLayoutItem>,
138
+ links: ReadonlyArray<FreeGraphBoxLayoutLink>,
139
+ centerItemId: string | undefined,
140
+ ): FreeGraphBoxLayoutItem[] {
141
+ const relationshipWeightByItemId = buildRelationshipWeightByItemId(links);
142
+
143
+ return [...items].sort((left, right) => {
144
+ if (left.id === centerItemId) {
145
+ return -1;
146
+ }
147
+ if (right.id === centerItemId) {
148
+ return 1;
149
+ }
150
+
151
+ const rightWeight = relationshipWeightByItemId.get(right.id) ?? 0;
152
+ const leftWeight = relationshipWeightByItemId.get(left.id) ?? 0;
153
+ if (leftWeight !== rightWeight) {
154
+ return rightWeight - leftWeight;
155
+ }
156
+
157
+ return left.orderIndex - right.orderIndex;
158
+ });
159
+ }
160
+
161
+ /**
162
+ * Build deterministic center-out grid coordinates.
163
+ *
164
+ * @param count - Number of coordinates to build.
165
+ * @returns Center-first coordinate list.
166
+ *
167
+ * @private function of AgentsGraph
168
+ */
169
+ function buildCenterOutCoordinates(count: number): CenterOutCoordinate[] {
170
+ const coordinates: CenterOutCoordinate[] = [{ column: 0, row: 0 }];
171
+
172
+ for (let radius = 1; coordinates.length < count; radius += 1) {
173
+ for (let column = -radius; column <= radius && coordinates.length < count; column += 1) {
174
+ coordinates.push({ column, row: -radius });
175
+ }
176
+
177
+ for (let row = -radius + 1; row <= radius && coordinates.length < count; row += 1) {
178
+ coordinates.push({ column: radius, row });
179
+ }
180
+
181
+ for (let column = radius - 1; column >= -radius && coordinates.length < count; column -= 1) {
182
+ coordinates.push({ column, row: radius });
183
+ }
184
+
185
+ for (let row = radius - 1; row >= -radius + 1 && coordinates.length < count; row -= 1) {
186
+ coordinates.push({ column: -radius, row });
187
+ }
188
+ }
189
+
190
+ return coordinates.slice(0, count);
191
+ }
192
+
193
+ /**
194
+ * Create mutable layout state with deterministic center-out initial placement.
195
+ *
196
+ * @param items - Ordered layout boxes.
197
+ * @param options - Layout tuning options.
198
+ * @returns Mutable state objects for relaxation.
199
+ *
200
+ * @private function of AgentsGraph
201
+ */
202
+ function createInitialLayoutState(
203
+ items: ReadonlyArray<FreeGraphBoxLayoutItem>,
204
+ options: FreeGraphBoxLayoutOptions,
205
+ ): FreeGraphBoxLayoutState[] {
206
+ const coordinates = buildCenterOutCoordinates(items.length);
207
+ const widestItem = Math.max(...items.map((item) => item.width), 1);
208
+ const tallestItem = Math.max(...items.map((item) => item.height), 1);
209
+ const cellWidth = widestItem + options.gapX * 2;
210
+ const cellHeight = tallestItem + options.gapY * 2;
211
+
212
+ return items.map((item, index) => {
213
+ const coordinate = coordinates[index] ?? { column: 0, row: 0 };
214
+ const rowOffset = Math.abs(coordinate.row % 2) * cellWidth * 0.18;
215
+ const x = coordinate.column * cellWidth + rowOffset;
216
+ const y = coordinate.row * cellHeight;
217
+
218
+ return {
219
+ ...item,
220
+ x,
221
+ y,
222
+ initialX: x,
223
+ initialY: y,
224
+ isCentered: item.id === options.centerItemId,
225
+ };
226
+ });
227
+ }
228
+
229
+ /**
230
+ * Move one relaxed layout state unless it is fixed to the center.
231
+ *
232
+ * @param state - Mutable state to move.
233
+ * @param deltaX - Horizontal movement.
234
+ * @param deltaY - Vertical movement.
235
+ *
236
+ * @private function of AgentsGraph
237
+ */
238
+ function moveLayoutState(state: FreeGraphBoxLayoutState, deltaX: number, deltaY: number): void {
239
+ if (state.isCentered) {
240
+ return;
241
+ }
242
+
243
+ state.x += deltaX;
244
+ state.y += deltaY;
245
+ }
246
+
247
+ /**
248
+ * Relax relationship links so connected boxes stay in a shared neighborhood.
249
+ *
250
+ * @param stateById - Mutable layout state indexed by id.
251
+ * @param links - Weighted graph links.
252
+ * @param options - Layout tuning options.
253
+ *
254
+ * @private function of AgentsGraph
255
+ */
256
+ function relaxRelationshipLinks(
257
+ stateById: ReadonlyMap<string, FreeGraphBoxLayoutState>,
258
+ links: ReadonlyArray<FreeGraphBoxLayoutLink>,
259
+ options: FreeGraphBoxLayoutOptions,
260
+ ): void {
261
+ links.forEach((link) => {
262
+ const sourceState = stateById.get(link.sourceId);
263
+ const targetState = stateById.get(link.targetId);
264
+
265
+ if (!sourceState || !targetState || sourceState === targetState) {
266
+ return;
267
+ }
268
+
269
+ const deltaX = targetState.x - sourceState.x;
270
+ const deltaY = targetState.y - sourceState.y;
271
+ const distance = Math.max(MINIMUM_DISTANCE, Math.hypot(deltaX, deltaY));
272
+ const preferredDistance =
273
+ options.relationshipDistance + Math.max(sourceState.width, targetState.width) * 0.35;
274
+ const weight = Math.max(DEFAULT_LINK_WEIGHT, link.weight ?? DEFAULT_LINK_WEIGHT);
275
+ const movement = (distance - preferredDistance) * options.relationshipStrength * Math.min(weight, 4);
276
+ const moveX = (deltaX / distance) * movement;
277
+ const moveY = (deltaY / distance) * movement;
278
+
279
+ if (sourceState.isCentered && targetState.isCentered) {
280
+ return;
281
+ }
282
+
283
+ if (sourceState.isCentered) {
284
+ moveLayoutState(targetState, -moveX, -moveY);
285
+ return;
286
+ }
287
+
288
+ if (targetState.isCentered) {
289
+ moveLayoutState(sourceState, moveX, moveY);
290
+ return;
291
+ }
292
+
293
+ moveLayoutState(sourceState, moveX / 2, moveY / 2);
294
+ moveLayoutState(targetState, -moveX / 2, -moveY / 2);
295
+ });
296
+ }
297
+
298
+ /**
299
+ * Push overlapping boxes apart while preserving a deterministic direction for identical centers.
300
+ *
301
+ * @param states - Mutable layout states.
302
+ * @param options - Layout tuning options.
303
+ *
304
+ * @private function of AgentsGraph
305
+ */
306
+ function separateOverlappingBoxes(states: ReadonlyArray<FreeGraphBoxLayoutState>, options: FreeGraphBoxLayoutOptions): void {
307
+ for (let leftIndex = 0; leftIndex < states.length; leftIndex += 1) {
308
+ for (let rightIndex = leftIndex + 1; rightIndex < states.length; rightIndex += 1) {
309
+ const leftState = states[leftIndex];
310
+ const rightState = states[rightIndex];
311
+
312
+ if (!leftState || !rightState) {
313
+ continue;
314
+ }
315
+
316
+ const deltaX = rightState.x - leftState.x;
317
+ const deltaY = rightState.y - leftState.y;
318
+ const overlapX = (leftState.width + rightState.width) / 2 + options.gapX - Math.abs(deltaX);
319
+ const overlapY = (leftState.height + rightState.height) / 2 + options.gapY - Math.abs(deltaY);
320
+
321
+ if (overlapX <= 0 || overlapY <= 0) {
322
+ continue;
323
+ }
324
+
325
+ const isHorizontalSeparation = overlapX < overlapY;
326
+ const fallbackDirection = leftIndex % 2 === 0 ? 1 : -1;
327
+ const direction = isHorizontalSeparation
328
+ ? deltaX === 0
329
+ ? fallbackDirection
330
+ : Math.sign(deltaX)
331
+ : deltaY === 0
332
+ ? fallbackDirection
333
+ : Math.sign(deltaY);
334
+ const movement = (isHorizontalSeparation ? overlapX : overlapY) / 2;
335
+ const moveX = isHorizontalSeparation ? direction * movement : 0;
336
+ const moveY = isHorizontalSeparation ? 0 : direction * movement;
337
+
338
+ if (leftState.isCentered && rightState.isCentered) {
339
+ continue;
340
+ }
341
+
342
+ if (leftState.isCentered) {
343
+ moveLayoutState(rightState, moveX * 2, moveY * 2);
344
+ continue;
345
+ }
346
+
347
+ if (rightState.isCentered) {
348
+ moveLayoutState(leftState, -moveX * 2, -moveY * 2);
349
+ continue;
350
+ }
351
+
352
+ moveLayoutState(leftState, -moveX, -moveY);
353
+ moveLayoutState(rightState, moveX, moveY);
354
+ }
355
+ }
356
+ }
357
+
358
+ /**
359
+ * Pull boxes gently toward their seeded positions so unrelated nodes do not drift indefinitely.
360
+ *
361
+ * @param states - Mutable layout states.
362
+ * @param centerPullStrength - Strength of the center pull.
363
+ *
364
+ * @private function of AgentsGraph
365
+ */
366
+ function applyInitialPositionPull(states: ReadonlyArray<FreeGraphBoxLayoutState>, centerPullStrength: number): void {
367
+ states.forEach((state) => {
368
+ if (state.isCentered) {
369
+ state.x = 0;
370
+ state.y = 0;
371
+ return;
372
+ }
373
+
374
+ moveLayoutState(state, (state.initialX - state.x) * centerPullStrength, (state.initialY - state.y) * centerPullStrength);
375
+ });
376
+ }
377
+
378
+ /**
379
+ * Convert relaxed center coordinates to normalized top-left parent coordinates.
380
+ *
381
+ * @param states - Relaxed layout states.
382
+ * @param options - Layout tuning options.
383
+ * @returns Normalized layout result.
384
+ *
385
+ * @private function of AgentsGraph
386
+ */
387
+ function normalizeLayoutState(
388
+ states: ReadonlyArray<FreeGraphBoxLayoutState>,
389
+ options: FreeGraphBoxLayoutOptions,
390
+ ): FreeGraphBoxLayoutResult {
391
+ const minimumX = Math.min(...states.map((state) => state.x - state.width / 2));
392
+ const maximumX = Math.max(...states.map((state) => state.x + state.width / 2));
393
+ const minimumY = Math.min(...states.map((state) => state.y - state.height / 2));
394
+ const maximumY = Math.max(...states.map((state) => state.y + state.height / 2));
395
+ const positionsById = new Map<string, FreeGraphBoxLayoutPosition>();
396
+
397
+ states.forEach((state) => {
398
+ positionsById.set(state.id, {
399
+ x: state.x - state.width / 2 - minimumX + options.paddingX,
400
+ y: state.y - state.height / 2 - minimumY + options.paddingY,
401
+ });
402
+ });
403
+
404
+ return {
405
+ width: maximumX - minimumX + options.paddingX * 2,
406
+ height: maximumY - minimumY + options.paddingY * 2,
407
+ positionsById,
408
+ };
409
+ }
410
+
411
+ /**
412
+ * Build a deterministic free layout for differently sized boxes and their relationships.
413
+ *
414
+ * @param items - Boxes to place.
415
+ * @param links - Weighted graph relationships between boxes.
416
+ * @param options - Layout tuning options.
417
+ * @returns Normalized top-left positions and parent dimensions.
418
+ *
419
+ * @private function of AgentsGraph
420
+ */
421
+ export function buildFreeGraphBoxLayout(
422
+ items: ReadonlyArray<FreeGraphBoxLayoutItem>,
423
+ links: ReadonlyArray<FreeGraphBoxLayoutLink>,
424
+ options: FreeGraphBoxLayoutOptions,
425
+ ): FreeGraphBoxLayoutResult {
426
+ if (items.length === 0) {
427
+ return {
428
+ width: options.paddingX * 2,
429
+ height: options.paddingY * 2,
430
+ positionsById: new Map(),
431
+ };
432
+ }
433
+
434
+ const orderedItems = sortLayoutItemsByImportance(items, links, options.centerItemId);
435
+ const states = createInitialLayoutState(orderedItems, options);
436
+ const stateById = new Map(states.map((state) => [state.id, state]));
437
+ const iterationCount = options.iterationCount ?? DEFAULT_LAYOUT_ITERATION_COUNT;
438
+
439
+ for (let iterationIndex = 0; iterationIndex < iterationCount; iterationIndex += 1) {
440
+ relaxRelationshipLinks(stateById, links, options);
441
+ separateOverlappingBoxes(states, options);
442
+ applyInitialPositionPull(states, options.centerPullStrength);
443
+ }
444
+
445
+ return normalizeLayoutState(states, options);
446
+ }