@laitszkin/apollo-toolkit 3.9.7 → 3.11.0

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 (55) hide show
  1. package/AGENTS.md +2 -0
  2. package/CHANGELOG.md +37 -0
  3. package/README.md +6 -0
  4. package/analyse-app-logs/scripts/__pycache__/filter_logs_by_time.cpython-312.pyc +0 -0
  5. package/analyse-app-logs/scripts/__pycache__/log_cli_utils.cpython-312.pyc +0 -0
  6. package/analyse-app-logs/scripts/__pycache__/search_logs.cpython-312.pyc +0 -0
  7. package/cjk-pdf/agents/openai.yaml +5 -0
  8. package/docs-to-voice/scripts/__pycache__/docs_to_voice.cpython-312.pyc +0 -0
  9. package/generate-spec/SKILL.md +26 -4
  10. package/generate-spec/agents/openai.yaml +1 -0
  11. package/generate-spec/references/TEMPLATE_SPEC.md +117 -0
  12. package/generate-spec/scripts/__pycache__/create-specscpython-312.pyc +0 -0
  13. package/init-project-html/SKILL.md +137 -0
  14. package/init-project-html/agents/openai.yaml +22 -0
  15. package/init-project-html/lib/atlas/assets/architecture.css +140 -0
  16. package/init-project-html/lib/atlas/assets/viewer.client.js +93 -0
  17. package/init-project-html/lib/atlas/cli.js +995 -0
  18. package/init-project-html/lib/atlas/layout.js +229 -0
  19. package/init-project-html/lib/atlas/render.js +485 -0
  20. package/init-project-html/lib/atlas/schema.js +310 -0
  21. package/init-project-html/lib/atlas/state.js +402 -0
  22. package/init-project-html/references/TEMPLATE_SPEC.md +137 -0
  23. package/init-project-html/references/architecture-page.template.html +35 -0
  24. package/init-project-html/references/architecture.css +1059 -0
  25. package/init-project-html/sample-demo/resources/project-architecture/assets/architecture.css +140 -0
  26. package/init-project-html/sample-demo/resources/project-architecture/assets/viewer.client.js +93 -0
  27. package/init-project-html/sample-demo/resources/project-architecture/atlas/atlas.index.yaml +34 -0
  28. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/get-invite-codes.yaml +159 -0
  29. package/init-project-html/sample-demo/resources/project-architecture/atlas/features/invite-code-registration.yaml +160 -0
  30. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/index.html +69 -0
  31. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-code-generator.html +50 -0
  32. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/invite-issuance-service.html +72 -0
  33. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/postgresql.html +66 -0
  34. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/public-api.html +70 -0
  35. package/init-project-html/sample-demo/resources/project-architecture/features/get-invite-codes/web-get-invite-ui.html +67 -0
  36. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/index.html +63 -0
  37. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/postgresql.html +68 -0
  38. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/public-api.html +65 -0
  39. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/registration-service.html +79 -0
  40. package/init-project-html/sample-demo/resources/project-architecture/features/invite-code-registration/web-register-ui.html +67 -0
  41. package/init-project-html/sample-demo/resources/project-architecture/index.html +234 -0
  42. package/init-project-html/scripts/architecture.js +314 -0
  43. package/katex/scripts/__pycache__/render_katex.cpython-312.pyc +0 -0
  44. package/lib/cli.js +2 -0
  45. package/lib/tool-runner.js +7 -0
  46. package/merge-conflict-resolver/agents/openai.yaml +5 -0
  47. package/open-github-issue/scripts/__pycache__/open_github_issue.cpython-312.pyc +0 -0
  48. package/package.json +6 -2
  49. package/read-github-issue/scripts/__pycache__/find_issues.cpython-312.pyc +0 -0
  50. package/read-github-issue/scripts/__pycache__/read_issue.cpython-312.pyc +0 -0
  51. package/resolve-review-comments/scripts/__pycache__/review_threads.cpython-312.pyc +0 -0
  52. package/spec-to-project-html/SKILL.md +114 -0
  53. package/spec-to-project-html/agents/openai.yaml +18 -0
  54. package/spec-to-project-html/references/TEMPLATE_SPEC.md +111 -0
  55. package/text-to-short-video/scripts/__pycache__/enforce_video_aspect_ratio.cpython-312.pyc +0 -0
@@ -0,0 +1,229 @@
1
+ 'use strict';
2
+
3
+ // layout.js — wraps elkjs to lay out the macro atlas. Features are
4
+ // nested compound nodes; submodules are leaf nodes inside them.
5
+ // hierarchyHandling=INCLUDE_CHILDREN lets cross-cluster edges route
6
+ // past intermediate nodes. The flatten step rebases every node and
7
+ // edge section into absolute (root-relative) coordinates so render.js
8
+ // can emit SVG without further math.
9
+ //
10
+ // Layout is async because elkjs returns a Promise even in Node.
11
+
12
+ const ELK = require('elkjs');
13
+
14
+ const SUB_WIDTH = 240;
15
+ const SUB_HEIGHT = 92;
16
+ const CLUSTER_PAD_TOP = 60;
17
+ const CLUSTER_PAD_SIDE = 24;
18
+ const CLUSTER_PAD_BOTTOM = 28;
19
+ const EDGE_LABEL_HEIGHT = 18;
20
+
21
+ function estimateLabelWidth(text) {
22
+ if (!text) return 0;
23
+ return Math.min(220, Math.max(40, String(text).length * 7 + 16));
24
+ }
25
+
26
+ function endpointId(endpoint, ownerFeature) {
27
+ if (typeof endpoint === 'string') {
28
+ return `submodule::${ownerFeature}::${endpoint}`;
29
+ }
30
+ if (endpoint && endpoint.submodule) {
31
+ return `submodule::${endpoint.feature}::${endpoint.submodule}`;
32
+ }
33
+ if (endpoint && endpoint.feature) {
34
+ return `feature::${endpoint.feature}`;
35
+ }
36
+ return null;
37
+ }
38
+
39
+ function buildGraph(state) {
40
+ const children = (state.features || []).map((feature) => ({
41
+ id: `feature::${feature.slug}`,
42
+ labels: [{
43
+ id: `feature::${feature.slug}::label`,
44
+ text: feature.title || feature.slug,
45
+ width: estimateLabelWidth(feature.title || feature.slug),
46
+ height: 24,
47
+ }],
48
+ layoutOptions: {
49
+ 'elk.padding': `[top=${CLUSTER_PAD_TOP},left=${CLUSTER_PAD_SIDE},bottom=${CLUSTER_PAD_BOTTOM},right=${CLUSTER_PAD_SIDE}]`,
50
+ 'elk.spacing.nodeNode': '24',
51
+ 'elk.algorithm': 'layered',
52
+ 'elk.direction': 'DOWN',
53
+ 'elk.layered.spacing.nodeNodeBetweenLayers': '36',
54
+ 'elk.nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]',
55
+ },
56
+ children: (feature.submodules || []).map((sub) => ({
57
+ id: `submodule::${feature.slug}::${sub.slug}`,
58
+ width: SUB_WIDTH,
59
+ height: SUB_HEIGHT,
60
+ labels: [{
61
+ id: `submodule::${feature.slug}::${sub.slug}::label`,
62
+ text: sub.slug,
63
+ width: estimateLabelWidth(sub.slug),
64
+ height: 18,
65
+ }],
66
+ })),
67
+ }));
68
+
69
+ let nextEdgeId = 0;
70
+ const rootEdges = [];
71
+ const nestedEdges = new Map(); // feature slug → edges[]
72
+
73
+ function pushEdge(list, raw, sourceId, targetId) {
74
+ if (!sourceId || !targetId) return;
75
+ list.push({
76
+ id: raw.id || `e-${nextEdgeId++}`,
77
+ sources: [sourceId],
78
+ targets: [targetId],
79
+ labels: raw.label ? [{
80
+ id: `${raw.id || `e-${nextEdgeId}`}::label`,
81
+ text: raw.label,
82
+ width: estimateLabelWidth(raw.label),
83
+ height: EDGE_LABEL_HEIGHT,
84
+ }] : [],
85
+ });
86
+ }
87
+
88
+ for (const feature of state.features || []) {
89
+ const list = [];
90
+ for (const edge of feature.edges || []) {
91
+ pushEdge(list, edge, endpointId(edge.from, feature.slug), endpointId(edge.to, feature.slug));
92
+ }
93
+ if (list.length > 0) nestedEdges.set(feature.slug, list);
94
+ }
95
+ for (const edge of state.edges || []) {
96
+ pushEdge(rootEdges, edge, endpointId(edge.from), endpointId(edge.to));
97
+ }
98
+
99
+ for (const child of children) {
100
+ const slug = child.id.replace(/^feature::/, '');
101
+ if (nestedEdges.has(slug)) child.edges = nestedEdges.get(slug);
102
+ }
103
+
104
+ return {
105
+ id: 'root',
106
+ layoutOptions: {
107
+ 'elk.algorithm': 'layered',
108
+ 'elk.direction': 'RIGHT',
109
+ 'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
110
+ 'elk.spacing.nodeNode': '60',
111
+ 'elk.layered.spacing.nodeNodeBetweenLayers': '100',
112
+ 'elk.padding': '[top=40,left=40,bottom=40,right=40]',
113
+ 'elk.edgeRouting': 'ORTHOGONAL',
114
+ 'elk.edgeLabels.inline': 'false',
115
+ 'elk.edgeLabels.placement': 'CENTER',
116
+ },
117
+ children,
118
+ edges: rootEdges,
119
+ };
120
+ }
121
+
122
+ function collectAbsolute(node, offsetX, offsetY, acc) {
123
+ // node may be root, a cluster, or a leaf.
124
+ const absX = offsetX + (node.x || 0);
125
+ const absY = offsetY + (node.y || 0);
126
+
127
+ if (node.id && node.id.startsWith('feature::')) {
128
+ acc.features.push({
129
+ id: node.id,
130
+ slug: node.id.replace(/^feature::/, ''),
131
+ x: absX,
132
+ y: absY,
133
+ width: node.width || 0,
134
+ height: node.height || 0,
135
+ labels: (node.labels || []).map((l) => ({
136
+ text: l.text,
137
+ x: absX + (l.x || 0),
138
+ y: absY + (l.y || 0),
139
+ width: l.width || 0,
140
+ height: l.height || 0,
141
+ })),
142
+ });
143
+ } else if (node.id && node.id.startsWith('submodule::')) {
144
+ const parts = node.id.split('::');
145
+ acc.submodules.push({
146
+ id: node.id,
147
+ featureSlug: parts[1],
148
+ slug: parts[2],
149
+ x: absX,
150
+ y: absY,
151
+ width: node.width || SUB_WIDTH,
152
+ height: node.height || SUB_HEIGHT,
153
+ labels: (node.labels || []).map((l) => ({
154
+ text: l.text,
155
+ x: absX + (l.x || 0),
156
+ y: absY + (l.y || 0),
157
+ width: l.width || 0,
158
+ height: l.height || 0,
159
+ })),
160
+ });
161
+ }
162
+
163
+ for (const edge of node.edges || []) {
164
+ const sections = (edge.sections || []).map((section) => ({
165
+ startPoint: { x: section.startPoint.x + absX, y: section.startPoint.y + absY },
166
+ endPoint: { x: section.endPoint.x + absX, y: section.endPoint.y + absY },
167
+ bendPoints: (section.bendPoints || []).map((p) => ({ x: p.x + absX, y: p.y + absY })),
168
+ }));
169
+ const labels = (edge.labels || []).map((label) => ({
170
+ text: label.text,
171
+ x: absX + (label.x || 0),
172
+ y: absY + (label.y || 0),
173
+ width: label.width || 0,
174
+ height: label.height || 0,
175
+ }));
176
+ acc.edges.push({ id: edge.id, sections, labels });
177
+ }
178
+
179
+ for (const child of node.children || []) {
180
+ collectAbsolute(child, absX, absY, acc);
181
+ }
182
+ }
183
+
184
+ function assertNoOverlap(layout) {
185
+ const boxes = [];
186
+ for (const sub of layout.submodules) {
187
+ boxes.push({ id: sub.id, x: sub.x, y: sub.y, w: sub.width, h: sub.height });
188
+ }
189
+ for (let i = 0; i < boxes.length; i += 1) {
190
+ for (let j = i + 1; j < boxes.length; j += 1) {
191
+ const a = boxes[i];
192
+ const b = boxes[j];
193
+ const overlapX = a.x < b.x + b.w && b.x < a.x + a.w;
194
+ const overlapY = a.y < b.y + b.h && b.y < a.y + a.h;
195
+ if (overlapX && overlapY) {
196
+ throw new Error(`atlas layout: submodule rectangles overlap: ${a.id} vs ${b.id}`);
197
+ }
198
+ }
199
+ }
200
+ }
201
+
202
+ async function layoutMacro(state) {
203
+ if (!state.features || state.features.length === 0) {
204
+ return { width: 320, height: 160, features: [], submodules: [], edges: [], empty: true };
205
+ }
206
+ const elk = new ELK();
207
+ const graph = buildGraph(state);
208
+ const laidOut = await elk.layout(graph);
209
+ const acc = { features: [], submodules: [], edges: [] };
210
+ collectAbsolute(laidOut, 0, 0, acc);
211
+ const layout = {
212
+ width: laidOut.width || 0,
213
+ height: laidOut.height || 0,
214
+ features: acc.features,
215
+ submodules: acc.submodules,
216
+ edges: acc.edges,
217
+ empty: false,
218
+ };
219
+ assertNoOverlap(layout);
220
+ return layout;
221
+ }
222
+
223
+ module.exports = {
224
+ SUB_WIDTH,
225
+ SUB_HEIGHT,
226
+ layoutMacro,
227
+ assertNoOverlap,
228
+ buildGraph,
229
+ };