@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.
- 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 +875 -60
- 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/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
- package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -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/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
- package/esm/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/avatars/avatarAnimationScheduler.ts +2 -1
- package/src/avatars/renderAvatarVisualAsciiArt.ts +138 -0
- 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 +770 -1169
- package/src/utils/ascii-art/$detectTerminalAnsiColorDepth.ts +45 -0
- package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +396 -0
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +875 -60
- 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/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
- package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -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/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
- package/umd/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
- package/umd/src/version.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
- 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
|
+
}
|