@openephemeris/mcp-server 3.23.1 → 4.0.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.
- package/CHANGELOG.md +105 -0
- package/LICENSE +21 -21
- package/README.md +52 -3
- package/dist/analytics.js +37 -5
- package/dist/backend/client.d.ts +7 -0
- package/dist/backend/client.js +39 -38
- package/dist/index.js +64 -2
- package/dist/oauth/session-utils.d.ts +42 -18
- package/dist/oauth/session-utils.js +79 -0
- package/dist/server-sse.js +114 -14
- package/dist/tools/apps/bazi-app.js +12 -26
- package/dist/tools/apps/bi-wheel-app.js +2 -2
- package/dist/tools/apps/bodygraph-app.d.ts +5 -5
- package/dist/tools/apps/bodygraph-app.js +187 -225
- package/dist/tools/apps/chart-wheel-app.js +5 -3
- package/dist/tools/apps/location-tools.js +167 -18
- package/dist/tools/apps/moon-phase-app.js +10 -3
- package/dist/tools/apps/transit-timeline-app.js +6 -4
- package/dist/tools/apps/vedic-chart-app.js +15 -49
- package/dist/tools/datetime.d.ts +65 -0
- package/dist/tools/datetime.js +153 -0
- package/dist/tools/index.d.ts +45 -2
- package/dist/tools/index.js +78 -2
- package/dist/tools/specialized/account.d.ts +1 -0
- package/dist/tools/specialized/account.js +100 -0
- package/dist/tools/specialized/acg.js +16 -14
- package/dist/tools/specialized/bazi.d.ts +7 -1
- package/dist/tools/specialized/bazi.js +86 -19
- package/dist/tools/specialized/bi_wheel.js +5 -4
- package/dist/tools/specialized/chart_wheel.js +5 -8
- package/dist/tools/specialized/comparative.js +13 -5
- package/dist/tools/specialized/electional.js +7 -7
- package/dist/tools/specialized/ephemeris_core.js +13 -8
- package/dist/tools/specialized/ephemeris_extended.js +27 -17
- package/dist/tools/specialized/hd_bodygraph.js +8 -10
- package/dist/tools/specialized/hd_cycles.js +7 -14
- package/dist/tools/specialized/hd_group.js +20 -13
- package/dist/tools/specialized/human_design.js +11 -17
- package/dist/tools/specialized/moon.js +8 -2
- package/dist/tools/specialized/natal.js +7 -9
- package/dist/tools/specialized/progressed.js +12 -8
- package/dist/tools/specialized/relocation.js +9 -3
- package/dist/tools/specialized/returns.js +23 -11
- package/dist/tools/specialized/synastry.js +17 -6
- package/dist/tools/specialized/transits.js +9 -5
- package/dist/tools/specialized/vedic.js +5 -3
- package/dist/tools/specialized/venus_star_points.js +14 -9
- package/dist/ui/bazi.html +1063 -1049
- package/dist/ui/bi-wheel.html +4197 -4120
- package/dist/ui/bodygraph.html +3855 -3720
- package/dist/ui/chart-wheel.html +3779 -3706
- package/dist/ui/moon-phase.html +3228 -3145
- package/dist/ui/transit-timeline.html +199 -170
- package/dist/ui/vedic-chart.html +1116 -1098
- package/package.json +6 -3
- package/smithery.yaml +1 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* bodygraph-app.ts
|
|
2
|
+
* bodygraph-app.ts — MCP App tool registration for the Human Design Bodygraph Explorer.
|
|
3
3
|
*
|
|
4
4
|
* Entry tools [model + app]:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* • explore_human_design — natal bodygraph, data + UI resource
|
|
6
|
+
* • explore_human_design_transit — natal + transit overlay (premium)
|
|
7
|
+
* • explore_human_design_connection — two-person connection/synastry overlay (premium)
|
|
8
8
|
* Click handlers [app-only]: hd_on_center_click, hd_on_gate_click,
|
|
9
9
|
* hd_on_channel_click, hd_on_planet_click, hd_on_variable_click,
|
|
10
10
|
* hd_on_connection_channel_click, hd_on_transit_channel_click (overlay, Phase 5).
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* overlay SVG is returned inline by /human-design/transit-chart and
|
|
13
13
|
* /human-design/composite (include_visual) rather than a separate render call.
|
|
14
14
|
*
|
|
15
|
-
* The bodygraph is rendered client-side from structured JSON
|
|
15
|
+
* The bodygraph is rendered client-side from structured JSON — no SVG endpoint
|
|
16
16
|
* is called, keeping latency at zero and the architecture consistent with
|
|
17
17
|
* the chart-wheel-app approach.
|
|
18
18
|
*
|
|
@@ -25,7 +25,8 @@ import { fileURLToPath } from "node:url";
|
|
|
25
25
|
import { registerTool, SERVER_VERSION } from "../index.js";
|
|
26
26
|
import { getActiveClient } from "../../backend/client.js";
|
|
27
27
|
import { OUTPUT_SCHEMA_JSON } from "../output-schemas.js";
|
|
28
|
-
|
|
28
|
+
import { localToUtcIso } from "../datetime.js";
|
|
29
|
+
// ── Constants ─────────────────────────────────────────────────────────────
|
|
29
30
|
export const BODYGRAPH_RESOURCE_URI = "ui://openephemeris/bodygraph";
|
|
30
31
|
// Appended to every model-visible HD tool description — trademark hygiene.
|
|
31
32
|
const HD_DISCLAIMER = " Human Design was originated by Ra Uru Hu; OpenEphemeris is an independent calculation service, not affiliated with Jovian Archive.";
|
|
@@ -61,31 +62,11 @@ export function getBodygraphBundle() {
|
|
|
61
62
|
export function clearBodygraphBundleCache() {
|
|
62
63
|
cachedBundle = null;
|
|
63
64
|
}
|
|
64
|
-
//
|
|
65
|
+
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
65
66
|
function capitalize(s) {
|
|
66
67
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
function ensureTimezone(dt) {
|
|
70
|
-
if (!dt)
|
|
71
|
-
return dt;
|
|
72
|
-
if (/[Zz]$/.test(dt) || /[+-]\d{2}:\d{2}$/.test(dt))
|
|
73
|
-
return dt;
|
|
74
|
-
return dt + "Z";
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Fetch the canonical bodygraph SVG from the Go renderer.
|
|
78
|
-
*
|
|
79
|
-
* The Go engine is the source of truth for bodygraph visuals (Phase 4 of the
|
|
80
|
-
* renderer unification). This SVG is inlined directly into the iframe and
|
|
81
|
-
* bound to interaction handlers via its data-* attributes (data-center,
|
|
82
|
-
* data-gate, data-channel, data-hanging, data-highlighted, etc.).
|
|
83
|
-
*
|
|
84
|
-
* Returns null on failure so the caller can fall back to the legacy client-side
|
|
85
|
-
* renderer in bodygraph-renderer.ts. Non-fatal: a missing SVG should never
|
|
86
|
-
* block the tool result.
|
|
87
|
-
*/
|
|
88
|
-
async function fetchGoBodygraphSVG(body, theme = "dark") {
|
|
69
|
+
async function fetchGoBodygraphSVG(body, theme = "dark", view) {
|
|
89
70
|
try {
|
|
90
71
|
const client = getActiveClient();
|
|
91
72
|
// /visualization/bodygraph is registered as binary in BINARY_ENDPOINT_PREFIXES.
|
|
@@ -96,7 +77,18 @@ async function fetchGoBodygraphSVG(body, theme = "dark") {
|
|
|
96
77
|
// to "light" when style is omitted, which mismatches dark MCP hosts — so we
|
|
97
78
|
// always pass an explicit theme (default "dark" to match the app shell; the
|
|
98
79
|
// iframe re-fetches with the host-detected theme on load / theme change).
|
|
99
|
-
|
|
80
|
+
//
|
|
81
|
+
// layout/rings/house_system are already validated + billed server-side
|
|
82
|
+
// (handler_bodygraph.go) — only appended when the caller (the in-iframe
|
|
83
|
+
// layout toggle) actually requests the mandala view.
|
|
84
|
+
let qs = `format=svg&size=800&style=${theme}`;
|
|
85
|
+
if (view?.layout)
|
|
86
|
+
qs += `&layout=${encodeURIComponent(view.layout)}`;
|
|
87
|
+
if (view?.rings !== undefined)
|
|
88
|
+
qs += `&rings=${encodeURIComponent(view.rings)}`;
|
|
89
|
+
if (view?.houseSystem)
|
|
90
|
+
qs += `&house_system=${encodeURIComponent(view.houseSystem)}`;
|
|
91
|
+
const resp = await client.post(`/visualization/bodygraph?${qs}`, body);
|
|
100
92
|
if (typeof resp === "string")
|
|
101
93
|
return resp;
|
|
102
94
|
if (resp && typeof resp === "object") {
|
|
@@ -112,54 +104,6 @@ async function fetchGoBodygraphSVG(body, theme = "dark") {
|
|
|
112
104
|
return null;
|
|
113
105
|
}
|
|
114
106
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Convert a local datetime string (no offset) to a UTC ISO 8601 string.
|
|
117
|
-
* Uses the IANA timezone to compute the correct UTC offset.
|
|
118
|
-
* Falls back to appending 'Z' (treating input as UTC) when no timezone is given
|
|
119
|
-
* or when the Intl API cannot resolve the zone.
|
|
120
|
-
*
|
|
121
|
-
* @param dt - "YYYY-MM-DDTHH:MM:SS" (no offset)
|
|
122
|
-
* @param tz - IANA timezone name, e.g. "America/New_York"
|
|
123
|
-
*/
|
|
124
|
-
function localToUtcIso(dt, tz) {
|
|
125
|
-
// Already has an offset / Z — pass through as-is
|
|
126
|
-
if (!dt || /[Zz]$/.test(dt) || /[+-]\d{2}:\d{2}$/.test(dt))
|
|
127
|
-
return ensureTimezone(dt);
|
|
128
|
-
if (!tz)
|
|
129
|
-
return dt + "Z"; // treat as UTC
|
|
130
|
-
try {
|
|
131
|
-
// Parse the local date components
|
|
132
|
-
const [datePart, timePart = "00:00:00"] = dt.split("T");
|
|
133
|
-
const [year, month, day] = datePart.split("-").map(Number);
|
|
134
|
-
const [hour, min, sec = 0] = timePart.split(":").map(Number);
|
|
135
|
-
// Build a Date assuming the inputs are LOCAL in the given timezone.
|
|
136
|
-
// Strategy: create a UTC candidate and shift by the Intl-reported offset.
|
|
137
|
-
// We iterate twice because DST can cause the offset to change at boundary datetimes.
|
|
138
|
-
const candidateUtcMs = Date.UTC(year, month - 1, day, hour, min, sec);
|
|
139
|
-
const getOffsetMs = (utcMs) => {
|
|
140
|
-
const fmtParts = new Intl.DateTimeFormat("en-US", {
|
|
141
|
-
timeZone: tz,
|
|
142
|
-
year: "numeric", month: "2-digit", day: "2-digit",
|
|
143
|
-
hour: "2-digit", minute: "2-digit", second: "2-digit",
|
|
144
|
-
hour12: false,
|
|
145
|
-
}).formatToParts(new Date(utcMs));
|
|
146
|
-
const get = (t) => Number(fmtParts.find(p => p.type === t)?.value ?? 0);
|
|
147
|
-
const localizedUtcMs = Date.UTC(get("year"), get("month") - 1, get("day"), get("hour") % 24, get("minute"), get("second"));
|
|
148
|
-
return utcMs - localizedUtcMs; // positive = timezone behind UTC
|
|
149
|
-
};
|
|
150
|
-
// First pass: rough offset
|
|
151
|
-
const offsetMs1 = getOffsetMs(candidateUtcMs);
|
|
152
|
-
const correctedUtcMs1 = candidateUtcMs + offsetMs1;
|
|
153
|
-
// Second pass: refine around DST boundary
|
|
154
|
-
const offsetMs2 = getOffsetMs(correctedUtcMs1);
|
|
155
|
-
const finalUtcMs = candidateUtcMs + offsetMs2;
|
|
156
|
-
return new Date(finalUtcMs).toISOString();
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
// Intl failed (bad timezone string etc.) — fall back to naive UTC
|
|
160
|
-
return dt + "Z";
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
107
|
const CENTER_ORDER = [
|
|
164
108
|
"Head", "Ajna", "Throat", "G", "Sacral",
|
|
165
109
|
"Heart", "Spleen", "Solar Plexus", "Root",
|
|
@@ -357,7 +301,7 @@ function buildHdSummary(payload, location) {
|
|
|
357
301
|
`Channels (${payload.active_channels.length}): ${channelList}\n\n` +
|
|
358
302
|
"Click any center, gate, or channel on the bodygraph for interpretation.");
|
|
359
303
|
}
|
|
360
|
-
//
|
|
304
|
+
// ── Tool: explore_human_design ────────────────────────────────────────────
|
|
361
305
|
registerTool({
|
|
362
306
|
name: "explore_human_design",
|
|
363
307
|
description: "Generate an interactive Human Design Bodygraph with clickable centers, gates, and channels.\n\n" +
|
|
@@ -377,12 +321,12 @@ registerTool({
|
|
|
377
321
|
datetime: {
|
|
378
322
|
type: "string",
|
|
379
323
|
description: "ISO 8601 birth datetime in UTC, e.g. '1990-04-15T19:30:00Z'. " +
|
|
380
|
-
"Human Design is time-sensitive
|
|
324
|
+
"Human Design is time-sensitive — accuracy to the minute matters. " +
|
|
381
325
|
"Include 'Z' or a timezone offset.",
|
|
382
326
|
},
|
|
383
327
|
latitude: {
|
|
384
328
|
type: "number",
|
|
385
|
-
description: "Birth latitude in decimal degrees (positive = North). Optional for HD charts.",
|
|
329
|
+
description: "Birth latitude in decimal degrees (positive = North). Optional for HD charts. Resolve from a place name with location_search; never recall coordinates from memory.",
|
|
386
330
|
},
|
|
387
331
|
longitude: {
|
|
388
332
|
type: "number",
|
|
@@ -390,7 +334,7 @@ registerTool({
|
|
|
390
334
|
},
|
|
391
335
|
location: {
|
|
392
336
|
type: "string",
|
|
393
|
-
description: "Location name for display only (e.g. 'New York, NY').",
|
|
337
|
+
description: "Location name for display only (e.g. 'New York, NY'). This is a caption, NOT a geocoder — it does not set the chart location. Supply latitude/longitude too (resolve them with location_search), or the chart is computed at 0N 0E.",
|
|
394
338
|
},
|
|
395
339
|
timezone: {
|
|
396
340
|
type: "string",
|
|
@@ -418,7 +362,7 @@ registerTool({
|
|
|
418
362
|
handler: async (args) => {
|
|
419
363
|
const client = getActiveClient();
|
|
420
364
|
const timezone = args.timezone;
|
|
421
|
-
const datetime = localToUtcIso(String(args.datetime), timezone);
|
|
365
|
+
const datetime = localToUtcIso("datetime", String(args.datetime), timezone);
|
|
422
366
|
const location = String(args.location ?? (args.latitude != null ? `${args.latitude}, ${args.longitude}` : "Unknown")).slice(0, 120);
|
|
423
367
|
const lat = args.latitude;
|
|
424
368
|
const lon = args.longitude;
|
|
@@ -495,6 +439,19 @@ registerTool({
|
|
|
495
439
|
enum: ["light", "dark"],
|
|
496
440
|
description: "Render palette for the bodygraph SVG. Mirrors the MCP host's light/dark color scheme.",
|
|
497
441
|
},
|
|
442
|
+
layout: {
|
|
443
|
+
type: "string",
|
|
444
|
+
enum: ["graph", "mandala"],
|
|
445
|
+
description: "Bodygraph composition. 'graph' (default) is the classic layout; 'mandala' nests the same diagram inside concentric rings. Set by the in-iframe layout toggle, never by the model.",
|
|
446
|
+
},
|
|
447
|
+
rings: {
|
|
448
|
+
type: "string",
|
|
449
|
+
description: "Comma-separated optional mandala rings (e.g. 'quarter,zodiac,planets'). Only used when layout=mandala. Omit for the server default; pass an empty string for none.",
|
|
450
|
+
},
|
|
451
|
+
house_system: {
|
|
452
|
+
type: "string",
|
|
453
|
+
description: "House system for the mandala house ring. Only used when layout=mandala and rings includes 'houses' with a birth location. Adds 1 credit when the house ring renders.",
|
|
454
|
+
},
|
|
498
455
|
},
|
|
499
456
|
required: ["datetime"],
|
|
500
457
|
},
|
|
@@ -505,10 +462,13 @@ registerTool({
|
|
|
505
462
|
const client = getActiveClient();
|
|
506
463
|
const timezone = args.timezone;
|
|
507
464
|
// Convert local-time input → UTC using IANA timezone when provided
|
|
508
|
-
const datetime = localToUtcIso(String(args.datetime), timezone);
|
|
465
|
+
const datetime = localToUtcIso("datetime", String(args.datetime), timezone);
|
|
509
466
|
const lat = args.latitude;
|
|
510
467
|
const lon = args.longitude;
|
|
511
468
|
const theme = args.theme === "light" ? "light" : "dark";
|
|
469
|
+
const layout = args.layout === "mandala" ? "mandala" : undefined;
|
|
470
|
+
const rings = typeof args.rings === "string" ? args.rings : undefined;
|
|
471
|
+
const houseSystem = typeof args.house_system === "string" ? args.house_system : undefined;
|
|
512
472
|
const body = {
|
|
513
473
|
birth_datetime_utc: datetime,
|
|
514
474
|
};
|
|
@@ -521,7 +481,7 @@ registerTool({
|
|
|
521
481
|
client.request("POST", "/human-design/chart", {
|
|
522
482
|
data: body,
|
|
523
483
|
}),
|
|
524
|
-
fetchGoBodygraphSVG(body, theme),
|
|
484
|
+
fetchGoBodygraphSVG(body, theme, { layout, rings, houseSystem }),
|
|
525
485
|
]);
|
|
526
486
|
const chart = chartData.chart ?? chartData;
|
|
527
487
|
const modelPayload = buildHdModelPayload(chart, {
|
|
@@ -538,7 +498,7 @@ registerTool({
|
|
|
538
498
|
};
|
|
539
499
|
},
|
|
540
500
|
});
|
|
541
|
-
//
|
|
501
|
+
// ── Tool: hd_on_center_click ──────────────────────────────────────────────
|
|
542
502
|
registerTool({
|
|
543
503
|
name: "hd_on_center_click",
|
|
544
504
|
description: "Event handler called when the user clicks a center in the Human Design Bodygraph. " +
|
|
@@ -572,12 +532,12 @@ registerTool({
|
|
|
572
532
|
};
|
|
573
533
|
}
|
|
574
534
|
const defLine = defined
|
|
575
|
-
? `**Defined**
|
|
576
|
-
: `**Undefined (Open)**
|
|
535
|
+
? `**Defined** — ${info.defined_theme}`
|
|
536
|
+
: `**Undefined (Open)** — ${info.undefined_theme}`;
|
|
577
537
|
return {
|
|
578
538
|
content: [{
|
|
579
539
|
type: "text",
|
|
580
|
-
text: `**${center} Center** ${defined ? "
|
|
540
|
+
text: `**${center} Center** ${defined ? "🔴" : "⬜"}\n\n` +
|
|
581
541
|
`${defLine}\n\n` +
|
|
582
542
|
`**Keynote:** ${info.keynote}\n\n` +
|
|
583
543
|
`**Biological Correlate:** ${info.biology}\n\n` +
|
|
@@ -589,7 +549,7 @@ registerTool({
|
|
|
589
549
|
};
|
|
590
550
|
},
|
|
591
551
|
});
|
|
592
|
-
//
|
|
552
|
+
// ── Tool: hd_on_gate_click ────────────────────────────────────────────────
|
|
593
553
|
registerTool({
|
|
594
554
|
name: "hd_on_gate_click",
|
|
595
555
|
description: "Event handler called when the user clicks an active gate in the Human Design Bodygraph. " +
|
|
@@ -600,11 +560,11 @@ registerTool({
|
|
|
600
560
|
properties: {
|
|
601
561
|
gate: {
|
|
602
562
|
type: "number",
|
|
603
|
-
description: "Gate number (1
|
|
563
|
+
description: "Gate number (1–64).",
|
|
604
564
|
},
|
|
605
565
|
line: {
|
|
606
566
|
type: "number",
|
|
607
|
-
description: "I Ching line number (1
|
|
567
|
+
description: "I Ching line number (1–6). Optional.",
|
|
608
568
|
},
|
|
609
569
|
planet: {
|
|
610
570
|
type: "string",
|
|
@@ -628,7 +588,7 @@ registerTool({
|
|
|
628
588
|
const info = HD_GATE_DATA[gate];
|
|
629
589
|
const lineRef = line ? `.${line}` : "";
|
|
630
590
|
const planetNote = planet ? ` (activated by ${capitalize(planet)})` : "";
|
|
631
|
-
const consciousNote = conscious === true ? "
|
|
591
|
+
const consciousNote = conscious === true ? " — **Personality** (conscious)" : conscious === false ? " — **Design** (unconscious)" : "";
|
|
632
592
|
if (!info) {
|
|
633
593
|
return {
|
|
634
594
|
content: [{ type: "text", text: `**Gate ${gate}${lineRef}**${planetNote}${consciousNote}\n\nGate data not available.` }],
|
|
@@ -637,7 +597,7 @@ registerTool({
|
|
|
637
597
|
return {
|
|
638
598
|
content: [{
|
|
639
599
|
type: "text",
|
|
640
|
-
text: `**Gate ${gate}${lineRef}
|
|
600
|
+
text: `**Gate ${gate}${lineRef} — ${info.name}**${planetNote}${consciousNote}\n\n` +
|
|
641
601
|
`**I Ching Hexagram:** ${info.hexagram}\n\n` +
|
|
642
602
|
`**Keynote:** ${info.keynote}\n\n` +
|
|
643
603
|
`**Gift:** ${info.gift}\n\n` +
|
|
@@ -648,7 +608,7 @@ registerTool({
|
|
|
648
608
|
};
|
|
649
609
|
},
|
|
650
610
|
});
|
|
651
|
-
//
|
|
611
|
+
// ── Tool: hd_on_channel_click ─────────────────────────────────────────────
|
|
652
612
|
registerTool({
|
|
653
613
|
name: "hd_on_channel_click",
|
|
654
614
|
description: "Event handler called when the user clicks an active channel in the Human Design Bodygraph. " +
|
|
@@ -679,7 +639,7 @@ registerTool({
|
|
|
679
639
|
const channelStr = String(args.channel);
|
|
680
640
|
const g1 = args.gate1 != null ? Number(args.gate1) : null;
|
|
681
641
|
const g2 = args.gate2 != null ? Number(args.gate2) : null;
|
|
682
|
-
// Normalise lookup key
|
|
642
|
+
// Normalise lookup key — try both gate orderings
|
|
683
643
|
const key = channelStr.includes("-") ? channelStr : g1 != null && g2 != null ? `${g1}-${g2}` : channelStr;
|
|
684
644
|
const info = HD_CHANNEL_DATA[key] ?? HD_CHANNEL_DATA[key.split("-").reverse().join("-")];
|
|
685
645
|
if (!info) {
|
|
@@ -694,17 +654,17 @@ registerTool({
|
|
|
694
654
|
};
|
|
695
655
|
}
|
|
696
656
|
const ENERGY_TYPE_DESCRIPTIONS = {
|
|
697
|
-
manifested: "This is a **Manifesting** channel
|
|
698
|
-
generated: "This is a **Generated** channel
|
|
699
|
-
projected: "This is a **Projected** channel
|
|
700
|
-
reflected: "This is a **Reflected** channel
|
|
657
|
+
manifested: "This is a **Manifesting** channel — it can initiate and impact the world directly.",
|
|
658
|
+
generated: "This is a **Generated** channel — powered by sacral life-force, it sustains and builds.",
|
|
659
|
+
projected: "This is a **Projected** channel — it guides and directs rather than generates energy.",
|
|
660
|
+
reflected: "This is a **Reflected** channel — it samples and mirrors the whole.",
|
|
701
661
|
};
|
|
702
662
|
const energyDesc = ENERGY_TYPE_DESCRIPTIONS[info.energy_type.toLowerCase()] ?? `Energy type: ${info.energy_type}`;
|
|
703
663
|
return {
|
|
704
664
|
content: [{
|
|
705
665
|
type: "text",
|
|
706
|
-
text: `**Channel ${channelStr}
|
|
707
|
-
`**Gates:** ${g1 ?? channelStr.split("-")[0]}
|
|
666
|
+
text: `**Channel ${channelStr} — ${info.name}**\n\n` +
|
|
667
|
+
`**Gates:** ${g1 ?? channelStr.split("-")[0]} ↔ ${g2 ?? channelStr.split("-")[1]}\n\n` +
|
|
708
668
|
`**Circuit:** ${info.circuit}\n\n` +
|
|
709
669
|
`${energyDesc}\n\n` +
|
|
710
670
|
`${info.description}`,
|
|
@@ -752,7 +712,7 @@ const TRANSIT_CLASS_DATA = {
|
|
|
752
712
|
body: "Both gates of this channel are defined in your own design. This is part of your fixed wiring, not transit weather — the passing sky does not change it. It reads here for context alongside the temporary activations.",
|
|
753
713
|
},
|
|
754
714
|
};
|
|
755
|
-
//
|
|
715
|
+
// ── Tool: hd_on_connection_channel_click [app-only] ────────────────────────
|
|
756
716
|
// Fired when the user clicks a connection (synastry) channel in the overlay
|
|
757
717
|
// bodygraph. Serves the connection-type dynamic for that specific channel.
|
|
758
718
|
registerTool({
|
|
@@ -786,12 +746,12 @@ registerTool({
|
|
|
786
746
|
const chan = HD_CHANNEL_DATA[key] ?? HD_CHANNEL_DATA[key.split("-").reverse().join("-")];
|
|
787
747
|
const conn = CONNECTION_TYPE_DATA[typeKey];
|
|
788
748
|
const chanName = chan?.name ?? "this channel";
|
|
789
|
-
const gatesLine = `**Gates:** ${g1 ?? channelStr.split("-")[0] ?? "?"}
|
|
749
|
+
const gatesLine = `**Gates:** ${g1 ?? channelStr.split("-")[0] ?? "?"} ↔ ${g2 ?? channelStr.split("-")[1] ?? "?"}`;
|
|
790
750
|
if (!conn) {
|
|
791
751
|
return {
|
|
792
752
|
content: [{
|
|
793
753
|
type: "text",
|
|
794
|
-
text: `**Channel ${channelStr}
|
|
754
|
+
text: `**Channel ${channelStr} — ${chanName}**\n\n${gatesLine}\n\n` +
|
|
795
755
|
`This channel is defined across both people. ${chan?.description ?? ""}`.trim(),
|
|
796
756
|
}],
|
|
797
757
|
};
|
|
@@ -799,7 +759,7 @@ registerTool({
|
|
|
799
759
|
return {
|
|
800
760
|
content: [{
|
|
801
761
|
type: "text",
|
|
802
|
-
text: `**${conn.label} Connection
|
|
762
|
+
text: `**${conn.label} Connection — Channel of ${chanName} (${channelStr})**\n\n` +
|
|
803
763
|
`${gatesLine}\n\n` +
|
|
804
764
|
`*${conn.tagline}*\n\n` +
|
|
805
765
|
`${conn.body}` +
|
|
@@ -808,7 +768,7 @@ registerTool({
|
|
|
808
768
|
};
|
|
809
769
|
},
|
|
810
770
|
});
|
|
811
|
-
//
|
|
771
|
+
// ── Tool: hd_on_transit_channel_click [app-only] ──────────────────────────
|
|
812
772
|
// Fired when the user clicks a channel in a transit overlay bodygraph. Serves
|
|
813
773
|
// the meaning of the channel's transit class (esp. transit_completed).
|
|
814
774
|
registerTool({
|
|
@@ -842,11 +802,11 @@ registerTool({
|
|
|
842
802
|
const chan = HD_CHANNEL_DATA[key] ?? HD_CHANNEL_DATA[key.split("-").reverse().join("-")];
|
|
843
803
|
const info = TRANSIT_CLASS_DATA[cls] ?? TRANSIT_CLASS_DATA.transit_completed;
|
|
844
804
|
const chanName = chan?.name ?? "this channel";
|
|
845
|
-
const gatesLine = `**Gates:** ${g1 ?? channelStr.split("-")[0] ?? "?"}
|
|
805
|
+
const gatesLine = `**Gates:** ${g1 ?? channelStr.split("-")[0] ?? "?"} ↔ ${g2 ?? channelStr.split("-")[1] ?? "?"}`;
|
|
846
806
|
return {
|
|
847
807
|
content: [{
|
|
848
808
|
type: "text",
|
|
849
|
-
text: `**Channel of ${chanName} (${channelStr})
|
|
809
|
+
text: `**Channel of ${chanName} (${channelStr}) — ${info.label}**\n\n` +
|
|
850
810
|
`${gatesLine}\n\n` +
|
|
851
811
|
`${info.body}` +
|
|
852
812
|
(chan?.description ? `\n\n**This channel:** ${chan.description}` : ""),
|
|
@@ -860,14 +820,14 @@ const HD_CENTER_DATA = {
|
|
|
860
820
|
biology: "Pineal gland, crown of skull",
|
|
861
821
|
circuit: "Knowing and Logic circuits",
|
|
862
822
|
defined_theme: "Consistent mental pressure to question, inspire, and seek answers. A fixed set of questions drives the mind.",
|
|
863
|
-
undefined_theme: "Amplifies others' mental pressure and questions. Wisdom comes from knowing which questions are worth answering
|
|
823
|
+
undefined_theme: "Amplifies others' mental pressure and questions. Wisdom comes from knowing which questions are worth answering — not every pressure needs resolution.",
|
|
864
824
|
},
|
|
865
825
|
Ajna: {
|
|
866
826
|
keynote: "Conceptualization, certainty/doubt, mental processing",
|
|
867
827
|
biology: "Pituitary/pineal gland complex, prefrontal cortex",
|
|
868
828
|
circuit: "Individual, Collective, and Tribal circuits",
|
|
869
829
|
defined_theme: "Consistent way of thinking and processing information. Opinionated and certain; thoughts have a reliable flavour.",
|
|
870
|
-
undefined_theme: "Open to many perspectives and ways of processing. The wisdom is in mental flexibility
|
|
830
|
+
undefined_theme: "Open to many perspectives and ways of processing. The wisdom is in mental flexibility — not needing to be certain.",
|
|
871
831
|
},
|
|
872
832
|
Throat: {
|
|
873
833
|
keynote: "Communication, manifestation, action",
|
|
@@ -881,28 +841,28 @@ const HD_CENTER_DATA = {
|
|
|
881
841
|
biology: "Liver, blood, immune system",
|
|
882
842
|
circuit: "Individual Knowing circuit",
|
|
883
843
|
defined_theme: "Fixed sense of direction and identity. Love, magnetic attraction, and life direction are reliable and self-directed.",
|
|
884
|
-
undefined_theme: "Identity and direction shift with environment and the people around. Sensitive to place
|
|
844
|
+
undefined_theme: "Identity and direction shift with environment and the people around. Sensitive to place — geography matters profoundly for finding the right people.",
|
|
885
845
|
},
|
|
886
846
|
Heart: {
|
|
887
847
|
keynote: "Willpower, ego, material world, value",
|
|
888
848
|
biology: "Heart, stomach, thymus, gallbladder",
|
|
889
849
|
circuit: "Tribal circuit",
|
|
890
850
|
defined_theme: "Consistent willpower and ability to make and keep promises. Strong sense of personal value and what is worth fighting for.",
|
|
891
|
-
undefined_theme: "Willpower is not consistent
|
|
851
|
+
undefined_theme: "Willpower is not consistent — rest after exertion is essential. May prove worth unnecessarily. Nothing to prove.",
|
|
892
852
|
},
|
|
893
853
|
Sacral: {
|
|
894
854
|
keynote: "Life-force, sexuality, work, response",
|
|
895
855
|
biology: "Reproductive system, ovaries, testes",
|
|
896
856
|
circuit: "Individual, Collective, and Tribal circuits",
|
|
897
857
|
defined_theme: "Consistent, powerful life-force energy that replenishes daily. Designed to work sustainably and respond gut-first. The motor of Generators and Manifesting Generators.",
|
|
898
|
-
undefined_theme: "No consistent life-force motor. Amplifies sacral energy of defined-sacral beings when around them. Must honour when energy is done
|
|
858
|
+
undefined_theme: "No consistent life-force motor. Amplifies sacral energy of defined-sacral beings when around them. Must honour when energy is done — sacral is not a reliable source.",
|
|
899
859
|
},
|
|
900
860
|
Spleen: {
|
|
901
861
|
keynote: "Intuition, instinct, fear, immune system, survival",
|
|
902
862
|
biology: "Spleen, lymphatic system, immune system, skin",
|
|
903
863
|
circuit: "Individual and Tribal circuits",
|
|
904
864
|
defined_theme: "Consistent intuition and immune awareness. Instincts are reliable; the body knows. Fear signals can be a guide rather than a trap.",
|
|
905
|
-
undefined_theme: "Splenic intuition is inconsistent
|
|
865
|
+
undefined_theme: "Splenic intuition is inconsistent — amplifies others' instincts. May hold on to things out of fear (relationships, jobs) rather than intuitive knowing.",
|
|
906
866
|
},
|
|
907
867
|
"Solar Plexus": {
|
|
908
868
|
keynote: "Emotions, feelings, desires, spirit, moods",
|
|
@@ -920,112 +880,112 @@ const HD_CENTER_DATA = {
|
|
|
920
880
|
},
|
|
921
881
|
};
|
|
922
882
|
const HD_GATE_DATA = {
|
|
923
|
-
1: { name: "The Creative", hexagram: "Hex 1
|
|
924
|
-
2: { name: "The Receptive", hexagram: "Hex 2
|
|
925
|
-
3: { name: "Ordering", hexagram: "Hex 3
|
|
926
|
-
4: { name: "Formulization", hexagram: "Hex 4
|
|
927
|
-
5: { name: "Fixed Rhythms", hexagram: "Hex 5
|
|
928
|
-
6: { name: "Friction", hexagram: "Hex 6
|
|
929
|
-
7: { name: "The Role of the Self", hexagram: "Hex 7
|
|
930
|
-
8: { name: "Contribution", hexagram: "Hex 8
|
|
931
|
-
9: { name: "Focus", hexagram: "Hex 9
|
|
932
|
-
10: { name: "Behaviour of the Self", hexagram: "Hex 10
|
|
933
|
-
11: { name: "Ideas", hexagram: "Hex 11
|
|
934
|
-
12: { name: "Caution", hexagram: "Hex 12
|
|
935
|
-
13: { name: "Fellowship of Man", hexagram: "Hex 13
|
|
936
|
-
14: { name: "Power Skills", hexagram: "Hex 14
|
|
937
|
-
15: { name: "Extremes", hexagram: "Hex 15
|
|
938
|
-
16: { name: "Skills", hexagram: "Hex 16
|
|
939
|
-
17: { name: "Opinions", hexagram: "Hex 17
|
|
940
|
-
18: { name: "Correction", hexagram: "Hex 18
|
|
941
|
-
19: { name: "Wanting", hexagram: "Hex 19
|
|
942
|
-
20: { name: "Contemplation", hexagram: "Hex 20
|
|
943
|
-
21: { name: "The Treasurer", hexagram: "Hex 21
|
|
944
|
-
22: { name: "Openness", hexagram: "Hex 22
|
|
945
|
-
23: { name: "Splitting Apart", hexagram: "Hex 23
|
|
946
|
-
24: { name: "Rationalisation", hexagram: "Hex 24
|
|
947
|
-
25: { name: "Innocence", hexagram: "Hex 25
|
|
948
|
-
26: { name: "The Taming Power of the Great", hexagram: "Hex 26
|
|
949
|
-
27: { name: "Caring", hexagram: "Hex 27
|
|
950
|
-
28: { name: "The Game Player", hexagram: "Hex 28
|
|
951
|
-
29: { name: "The Abysmal", hexagram: "Hex 29
|
|
952
|
-
30: { name: "Feelings", hexagram: "Hex 30
|
|
953
|
-
31: { name: "Influence", hexagram: "Hex 31
|
|
954
|
-
32: { name: "Continuity", hexagram: "Hex 32
|
|
955
|
-
33: { name: "Privacy", hexagram: "Hex 33
|
|
956
|
-
34: { name: "Power", hexagram: "Hex 34
|
|
957
|
-
35: { name: "Change", hexagram: "Hex 35
|
|
958
|
-
36: { name: "Crisis", hexagram: "Hex 36
|
|
959
|
-
37: { name: "Friendship", hexagram: "Hex 37
|
|
960
|
-
38: { name: "The Fighter", hexagram: "Hex 38
|
|
961
|
-
39: { name: "Provocation", hexagram: "Hex 39
|
|
962
|
-
40: { name: "Aloneness", hexagram: "Hex 40
|
|
963
|
-
41: { name: "Contraction", hexagram: "Hex 41
|
|
964
|
-
42: { name: "Growth", hexagram: "Hex 42
|
|
965
|
-
43: { name: "Insight", hexagram: "Hex 43
|
|
966
|
-
44: { name: "Alertness", hexagram: "Hex 44
|
|
967
|
-
45: { name: "The Gatherer", hexagram: "Hex 45
|
|
968
|
-
46: { name: "The Serendipitous", hexagram: "Hex 46
|
|
969
|
-
47: { name: "Realisation", hexagram: "Hex 47
|
|
970
|
-
48: { name: "Well", hexagram: "Hex 48
|
|
971
|
-
49: { name: "Revolution", hexagram: "Hex 49
|
|
972
|
-
50: { name: "Values", hexagram: "Hex 50
|
|
973
|
-
51: { name: "The Arousing", hexagram: "Hex 51
|
|
974
|
-
52: { name: "Concentration", hexagram: "Hex 52
|
|
975
|
-
53: { name: "Beginnings", hexagram: "Hex 53
|
|
976
|
-
54: { name: "Ambition", hexagram: "Hex 54
|
|
977
|
-
55: { name: "Abundance", hexagram: "Hex 55
|
|
978
|
-
56: { name: "Stimulation", hexagram: "Hex 56
|
|
979
|
-
57: { name: "Intuitive Insight", hexagram: "Hex 57
|
|
980
|
-
58: { name: "Vitality", hexagram: "Hex 58
|
|
981
|
-
59: { name: "Sexuality", hexagram: "Hex 59
|
|
982
|
-
60: { name: "Acceptance", hexagram: "Hex 60
|
|
983
|
-
61: { name: "Mystery", hexagram: "Hex 61
|
|
984
|
-
62: { name: "Detail", hexagram: "Hex 62
|
|
985
|
-
63: { name: "Doubt", hexagram: "Hex 63
|
|
986
|
-
64: { name: "Confusion", hexagram: "Hex 64
|
|
883
|
+
1: { name: "The Creative", hexagram: "Hex 1 — Creative Power", keynote: "Self-expression as a creative force", gift: "Freshness — original self-expression that inspires", shadow: "Entropy — creative block from fear of not being unique", circuit: "Individual (Centering)" },
|
|
884
|
+
2: { name: "The Receptive", hexagram: "Hex 2 — Receptive Power", keynote: "The direction of the self", gift: "Orientation — knowing where to go", shadow: "Dislocation — living without inner compass", circuit: "Individual (Centering)" },
|
|
885
|
+
3: { name: "Ordering", hexagram: "Hex 3 — Difficulty at the Beginning", keynote: "Innovation from chaos", gift: "Innovation — bringing order from initial confusion", shadow: "Chaos — stuck in mutation, unable to stabilise", circuit: "Individual (Centering)" },
|
|
886
|
+
4: { name: "Formulization", hexagram: "Hex 4 — Youthful Folly", keynote: "Mental solutions that benefit humanity", gift: "Understanding — solutions that help the collective", shadow: "Incompetence — mental answers that cause harm", circuit: "Collective (Logic)" },
|
|
887
|
+
5: { name: "Fixed Rhythms", hexagram: "Hex 5 — Waiting", keynote: "Universal patterns and timing", gift: "Patience — trusting the correct timing", shadow: "Impatience — forcing outcomes", circuit: "Collective (Logic)" },
|
|
888
|
+
6: { name: "Friction", hexagram: "Hex 6 — Conflict", keynote: "The role model through experience", gift: "Diplomacy — conflict resolved through right relationship", shadow: "Conflict — isolation and withdrawal", circuit: "Collective (Logic)" },
|
|
889
|
+
7: { name: "The Role of the Self", hexagram: "Hex 7 — The Army", keynote: "Leadership in the direction of the future", gift: "Guidance — leading through personal example", shadow: "Division — leadership without authority", circuit: "Collective (Logic)" },
|
|
890
|
+
8: { name: "Contribution", hexagram: "Hex 8 — Holding Together", keynote: "Contribution to the collective through individual creativity", gift: "Style — unique contribution that inspires others", shadow: "Mediocrity — hiding unique self to fit in", circuit: "Individual (Centering)" },
|
|
891
|
+
9: { name: "Focus", hexagram: "Hex 9 — The Taming Power of the Small", keynote: "Determination and focus on detail", gift: "Determination — laser focus on what matters", shadow: "Inertia — scattered, unable to concentrate", circuit: "Collective (Logic)" },
|
|
892
|
+
10: { name: "Behaviour of the Self", hexagram: "Hex 10 — Treading", keynote: "Love of self, self-empowerment", gift: "Naturalness — authentic behaviour without self-consciousness", shadow: "Self-obsession — behaviour driven by approval-seeking", circuit: "Individual (Centering)" },
|
|
893
|
+
11: { name: "Ideas", hexagram: "Hex 11 — Peace", keynote: "The harmony of ideas", gift: "Idealism — ideas that envision greater harmony", shadow: "Obscurity — inability to ground and communicate visions", circuit: "Collective (Abstract)" },
|
|
894
|
+
12: { name: "Caution", hexagram: "Hex 12 — Standstill", keynote: "Active caution in social interaction", gift: "Discrimination — grace in social engagement", shadow: "Vanity — withdrawing emotionally from genuine connection", circuit: "Individual (Centering)" },
|
|
895
|
+
13: { name: "Fellowship of Man", hexagram: "Hex 13 — The Fellowship", keynote: "Universal listening", gift: "Empathy — the ear that holds others' stories", shadow: "Discord — secrets and betrayal", circuit: "Individual (Centering)" },
|
|
896
|
+
14: { name: "Power Skills", hexagram: "Hex 14 — Possession in Great Measure", keynote: "Accumulation of resources for collective good", gift: "Competence — using resources masterfully", shadow: "Compromise — accumulating for the wrong reasons", circuit: "Individual (Centering)" },
|
|
897
|
+
15: { name: "Extremes", hexagram: "Hex 15 — Modesty", keynote: "Extremes flow into the universal", gift: "Magnetism — extreme rhythms that attract the right others", shadow: "Dullness — inability to embrace natural extremes", circuit: "Individual (Centering)" },
|
|
898
|
+
16: { name: "Skills", hexagram: "Hex 16 — Enthusiasm", keynote: "Expressing talent with zeal", gift: "Versatility — enthusiastic expression of many skills", shadow: "Indifference — talent wasted by lack of drive", circuit: "Collective (Logic)" },
|
|
899
|
+
17: { name: "Opinions", hexagram: "Hex 17 — Following", keynote: "Opinions that help the collective move forward", gift: "Far-sightedness — opinions that serve the future", shadow: "Opinion — opinionating without wisdom", circuit: "Collective (Logic)" },
|
|
900
|
+
18: { name: "Correction", hexagram: "Hex 18 — Work on What Has Been Spoilt", keynote: "Judgment to find perfection", gift: "Integrity — correction that restores wholeness", shadow: "Judgment — criticism that wounds rather than heals", circuit: "Collective (Logic)" },
|
|
901
|
+
19: { name: "Wanting", hexagram: "Hex 19 — Approach", keynote: "Sensitivity to spirit and material needs", gift: "Sensitivity — awareness of unspoken needs", shadow: "Co-dependence — needs driving all decisions", circuit: "Tribal (Defence)" },
|
|
902
|
+
20: { name: "Contemplation", hexagram: "Hex 20 — Contemplation", keynote: "Presence in the now", gift: "Self-assurance — expressing truth in the moment", shadow: "Superficiality — words without depth", circuit: "Individual (Centering)" },
|
|
903
|
+
21: { name: "The Treasurer", hexagram: "Hex 21 — Biting Through", keynote: "Self-regulation and control in the material world", gift: "Authority — control exercised with integrity", shadow: "Control — possessiveness and domination", circuit: "Tribal (Ego)" },
|
|
904
|
+
22: { name: "Openness", hexagram: "Hex 22 — Grace", keynote: "The quality of emotional grace", gift: "Graciousness — emotional openness that transforms", shadow: "Dishonour — emotional withdrawal and defence", circuit: "Individual (Centering)" },
|
|
905
|
+
23: { name: "Splitting Apart", hexagram: "Hex 23 — Splitting Apart", keynote: "Translating the unique into language others can receive", gift: "Simplicity — the gift of making the complex clear", shadow: "Complexity — information without context or timing", circuit: "Individual (Centering)" },
|
|
906
|
+
24: { name: "Rationalisation", hexagram: "Hex 24 — Return", keynote: "The blessings of mental return and review", gift: "Invention — turning contemplation into breakthrough", shadow: "Addiction — mental looping without resolution", circuit: "Individual (Knowing)" },
|
|
907
|
+
25: { name: "Innocence", hexagram: "Hex 25 — Innocence", keynote: "The wisdom of innocence and universalising love", gift: "Acceptance — love without conditions or agenda", shadow: "Cruelty — the pain of love withheld", circuit: "Individual (Centering)" },
|
|
908
|
+
26: { name: "The Taming Power of the Great", hexagram: "Hex 26 — Taming", keynote: "Skilful transmitting of information", gift: "Artfulness — the gift of efficient, compelling communication", shadow: "Covetousness — ego-driven manipulation", circuit: "Tribal (Ego)" },
|
|
909
|
+
27: { name: "Caring", hexagram: "Hex 27 — Nourishment", keynote: "Preservation and nurturing", gift: "Altruism — sustaining others from genuine care", shadow: "Selfishness — nurturing only what benefits the self", circuit: "Tribal (Defence)" },
|
|
910
|
+
28: { name: "The Game Player", hexagram: "Hex 28 — Preponderance of the Great", keynote: "Finding purpose in struggle", gift: "Totality — fully committing to what gives life meaning", shadow: "Purposelessness — gambling with life's purpose", circuit: "Individual (Knowing)" },
|
|
911
|
+
29: { name: "The Abysmal", hexagram: "Hex 29 — The Abysmal", keynote: "Commitment and perseverance", gift: "Commitment — deep yes to what the sacral confirms", shadow: "Half-heartedness — over-committed without response", circuit: "Collective (Abstract)" },
|
|
912
|
+
30: { name: "Feelings", hexagram: "Hex 30 — The Clinging", keynote: "Recognition and feeling of experience", gift: "Lightness — riding the wave without being swept away", shadow: "Desire — driven by emotional craving", circuit: "Collective (Abstract)" },
|
|
913
|
+
31: { name: "Influence", hexagram: "Hex 31 — Influence", keynote: "Leading through democratic means", gift: "Leadership — influence through example and invitation", shadow: "Arrogance — influence through position rather than merit", circuit: "Collective (Logic)" },
|
|
914
|
+
32: { name: "Continuity", hexagram: "Hex 32 — Duration", keynote: "Intuitive assessment of what endures", gift: "Preservation — knowing what is worth preserving", shadow: "Failure — fear of failure blocking right assessment", circuit: "Tribal (Defence)" },
|
|
915
|
+
33: { name: "Privacy", hexagram: "Hex 33 — Retreat", keynote: "Knowing when to retreat and share later wisdom", gift: "Revelation — wisdom shared at the right time", shadow: "Forgetting — retreat without integration", circuit: "Collective (Abstract)" },
|
|
916
|
+
34: { name: "Power", hexagram: "Hex 34 — The Power of the Great", keynote: "Manifestation of power through response", gift: "Strength — responsive power that transforms", shadow: "Force — power without direction or response", circuit: "Individual (Centering)" },
|
|
917
|
+
35: { name: "Change", hexagram: "Hex 35 — Progress", keynote: "The hunger for experience", gift: "Adventure — embracing change for collective growth", shadow: "Hunger — chasing experience to fill an inner void", circuit: "Collective (Abstract)" },
|
|
918
|
+
36: { name: "Crisis", hexagram: "Hex 36 — Darkening of the Light", keynote: "The need for emotional experience as teacher", gift: "Humanity — finding compassion through crisis survived", shadow: "Turbulence — emotionally driven chaos and drama", circuit: "Collective (Abstract)" },
|
|
919
|
+
37: { name: "Friendship", hexagram: "Hex 37 — The Family", keynote: "Harmony through clear agreements in relationship", gift: "Equality — friendship built on mutual respect", shadow: "Inequality — bargaining and conditional love", circuit: "Tribal (Ego)" },
|
|
920
|
+
38: { name: "The Fighter", hexagram: "Hex 38 — Opposition", keynote: "Struggle in the search for purpose", gift: "Perseverance — fighting for what is meaningful", shadow: "Struggle — fighting against everything without purpose", circuit: "Individual (Knowing)" },
|
|
921
|
+
39: { name: "Provocation", hexagram: "Hex 39 — Obstruction", keynote: "Freeing the spirit through provocation", gift: "Dynamism — provocateur that liberates", shadow: "Provocation — stirring trouble unconsciously", circuit: "Individual (Knowing)" },
|
|
922
|
+
40: { name: "Aloneness", hexagram: "Hex 40 — Deliverance", keynote: "The demand for aloneness as restoration", gift: "Resolve — willpower renewed in solitude", shadow: "Exhaustion — depleted by giving without replenishment", circuit: "Tribal (Ego)" },
|
|
923
|
+
41: { name: "Contraction", hexagram: "Hex 41 — Decrease", keynote: "The beginning of all experience — fantasy and desire", gift: "Fantasy — imagination that seeds new experience", shadow: "Escapism — escapism", circuit: "Collective (Abstract)" },
|
|
924
|
+
42: { name: "Growth", hexagram: "Hex 42 — Increase", keynote: "The ability to perpetuate and complete growth cycles", gift: "Detachment — completing cycles with grace", shadow: "Incompletion — abandoning cycles before they end", circuit: "Collective (Abstract)" },
|
|
925
|
+
43: { name: "Insight", hexagram: "Hex 43 — Breakthrough", keynote: "Breakthrough from within", gift: "Insight — inner knowing that arrives as genius", shadow: "Deafness — genius unrecognised or unheard", circuit: "Individual (Knowing)" },
|
|
926
|
+
44: { name: "Alertness", hexagram: "Hex 44 — Coming to Meet", keynote: "Instinctive memory and pattern recognition", gift: "Teamwork — bringing the right people together", shadow: "Interference — driven by karmic patterns from the past", circuit: "Tribal (Defence)" },
|
|
927
|
+
45: { name: "The Gatherer", hexagram: "Hex 45 — Gathering Together", keynote: "Ruling and gathering resources for the tribe", gift: "Synergy — the king/queen who gathers and empowers", shadow: "Dominance — ruling through control", circuit: "Tribal (Ego)" },
|
|
928
|
+
46: { name: "The Serendipitous", hexagram: "Hex 46 — Pushing Upward", keynote: "Love of the body and serendipity", gift: "Delight — inhabiting the body fully", shadow: "Seriousness — disconnected from physical joy", circuit: "Individual (Centering)" },
|
|
929
|
+
47: { name: "Realisation", hexagram: "Hex 47 — Oppression", keynote: "The realisation that transforms oppression", gift: "Realisation — finding the gem in difficult experience", shadow: "Oppression — trapped in mental suffering", circuit: "Collective (Abstract)" },
|
|
930
|
+
48: { name: "Well", hexagram: "Hex 48 — The Well", keynote: "The depth that provides solutions", gift: "Resourcefulness — drawing from a depth of wisdom", shadow: "Inadequacy — fear of not being deep enough", circuit: "Collective (Logic)" },
|
|
931
|
+
49: { name: "Revolution", hexagram: "Hex 49 — Revolution", keynote: "Sensitivity to right principles", gift: "Revolution — principled transformation", shadow: "Reaction — rejection driven by fear", circuit: "Tribal (Defence)" },
|
|
932
|
+
50: { name: "Values", hexagram: "Hex 50 — The Cauldron", keynote: "Values for humanity's nourishment", gift: "Responsibility — holding values that sustain the tribe", shadow: "Corruption — values compromised for survival", circuit: "Tribal (Defence)" },
|
|
933
|
+
51: { name: "The Arousing", hexagram: "Hex 51 — The Arousing", keynote: "The shock that awakens spirit", gift: "Initiative — shock as awakening force", shadow: "Agitation — disruption without purpose", circuit: "Individual (Centering)" },
|
|
934
|
+
52: { name: "Concentration", hexagram: "Hex 52 — Keeping Still", keynote: "Concentration and stillness as a power", gift: "Restraint — focused stillness that creates mastery", shadow: "Stress — adrenal pressure without direction", circuit: "Collective (Logic)" },
|
|
935
|
+
53: { name: "Beginnings", hexagram: "Hex 53 — Development", keynote: "Pressure to start new cycles", gift: "Expansion — initiating growth cycles", shadow: "Immaturity — starting without completing", circuit: "Collective (Abstract)" },
|
|
936
|
+
54: { name: "Ambition", hexagram: "Hex 54 — The Marrying Maiden", keynote: "The transformative fuel of ambition", gift: "Aspiration — ambition that elevates all", shadow: "Greed — reaching for position at others' expense", circuit: "Tribal (Defence)" },
|
|
937
|
+
55: { name: "Abundance", hexagram: "Hex 55 — Abundance", keynote: "Emotional abundance and spirit", gift: "Freedom — emotional richness surrendered to spirit", shadow: "Victimisation — emotional suffering without spirit", circuit: "Individual (Knowing)" },
|
|
938
|
+
56: { name: "Stimulation", hexagram: "Hex 56 — The Wanderer", keynote: "Stimulating stories and beliefs", gift: "Enrichment — stories that expand perspective", shadow: "Distraction — stories that mislead", circuit: "Collective (Abstract)" },
|
|
939
|
+
57: { name: "Intuitive Insight", hexagram: "Hex 57 — The Gentle", keynote: "Intuitive insight in the now", gift: "Clarity — penetrating intuition that clears confusion", shadow: "Unease — anxiety from ignoring the body's signals", circuit: "Individual (Knowing)" },
|
|
940
|
+
58: { name: "Vitality", hexagram: "Hex 58 — The Joyous", keynote: "Vitality and the joy of life", gift: "Vitality — life-force expressed as joy", shadow: "Dissatisfaction — criticism of what is imperfect", circuit: "Collective (Logic)" },
|
|
941
|
+
59: { name: "Sexuality", hexagram: "Hex 59 — Dispersion", keynote: "Intimacy and aura penetration", gift: "Intimacy — dissolving the aura safely into union", shadow: "Dishonesty — seduction without regard for truth", circuit: "Tribal (Defence)" },
|
|
942
|
+
60: { name: "Acceptance", hexagram: "Hex 60 — Limitation", keynote: "Acceptance of limitation as the basis for transcendence", gift: "Realism — working within constraints creatively", shadow: "Conservatism — clinging to limitation as identity", circuit: "Individual (Knowing)" },
|
|
943
|
+
61: { name: "Mystery", hexagram: "Hex 61 — Inner Truth", keynote: "The pressure to understand the unknowable", gift: "Inspiration — inner knowing beyond logic", shadow: "Psychosis — consumed by the search for unknowable truths", circuit: "Individual (Knowing)" },
|
|
944
|
+
62: { name: "Detail", hexagram: "Hex 62 — Preponderance of the Small", keynote: "The precision of detail and naming", gift: "Precision — detail that serves communication", shadow: "Intellectualism — detail without substance", circuit: "Collective (Logic)" },
|
|
945
|
+
63: { name: "Doubt", hexagram: "Hex 63 — After Completion", keynote: "Logical doubt as a mental pressure", gift: "Inquiry — questioning that leads to new solutions", shadow: "Doubt — anxiety about an unknowable future", circuit: "Collective (Logic)" },
|
|
946
|
+
64: { name: "Confusion", hexagram: "Hex 64 — Before Completion", keynote: "The inspiration pressure before clarity", gift: "Imagination — holding confusion long enough for illumination", shadow: "Confusion — overwhelmed by unresolved mental images", circuit: "Collective (Abstract)" },
|
|
987
947
|
};
|
|
988
948
|
const HD_CHANNEL_DATA = {
|
|
989
|
-
"1-8": { name: "Inspiration", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of creative inspiration
|
|
990
|
-
"2-14": { name: "The Beat", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of the keeper of keys
|
|
991
|
-
"3-60": { name: "Mutation", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of mutation
|
|
992
|
-
"4-63": { name: "Logic", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of mental logic
|
|
993
|
-
"5-15": { name: "Rhythm", circuit: "Collective (Logic)", energy_type: "generated", description: "The channel of fixed rhythms
|
|
994
|
-
"6-59": { name: "Intimacy", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of intimacy
|
|
995
|
-
"7-31": { name: "The Alpha", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of the leader
|
|
996
|
-
"9-52": { name: "Concentration", circuit: "Collective (Logic)", energy_type: "generated", description: "The channel of the focused mind
|
|
997
|
-
"10-20": { name: "Awakening", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of awakening
|
|
998
|
-
"10-34": { name: "Exploration", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of following one's convictions
|
|
999
|
-
"10-57": { name: "Perfected Form", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of perfected form
|
|
1000
|
-
"11-56": { name: "Curiosity", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of the storyteller
|
|
1001
|
-
"12-22": { name: "Openness", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of openness
|
|
1002
|
-
"13-33": { name: "The Prodigal", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of witness
|
|
1003
|
-
"16-48": { name: "The Wavelength", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of talent
|
|
1004
|
-
"17-62": { name: "Acceptance", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of organised activity
|
|
1005
|
-
"18-58": { name: "Judgement", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of judgement
|
|
1006
|
-
"19-49": { name: "Synthesis", circuit: "Tribal (Defence)", energy_type: "projected", description: "The channel of synthesis
|
|
1007
|
-
"20-34": { name: "Charisma", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of charisma
|
|
1008
|
-
"20-57": { name: "The Brain Wave", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of the brain wave
|
|
1009
|
-
"21-45": { name: "Money Line", circuit: "Tribal (Ego)", energy_type: "projected", description: "The channel of the money line
|
|
1010
|
-
"23-43": { name: "Structuring", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of structuring
|
|
1011
|
-
"24-61": { name: "Awareness", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of awareness
|
|
1012
|
-
"25-51": { name: "Initiation", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of initiation
|
|
1013
|
-
"26-44": { name: "Surrender", circuit: "Tribal (Defence)", energy_type: "projected", description: "The channel of surrender
|
|
1014
|
-
"27-50": { name: "Preservation", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of preservation
|
|
1015
|
-
"28-38": { name: "Struggle", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of struggle
|
|
1016
|
-
"29-46": { name: "Discovery", circuit: "Collective (Abstract)", energy_type: "generated", description: "The channel of discovery
|
|
1017
|
-
"30-41": { name: "Recognition", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of recognition
|
|
1018
|
-
"32-54": { name: "Transformation", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of transformation
|
|
1019
|
-
"34-57": { name: "Power", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of power
|
|
1020
|
-
"35-36": { name: "Transitoriness", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of transitoriness
|
|
1021
|
-
"37-40": { name: "Community", circuit: "Tribal (Ego)", energy_type: "projected", description: "The channel of community
|
|
1022
|
-
"39-55": { name: "Emoting", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of emoting
|
|
1023
|
-
"42-53": { name: "Maturation", circuit: "Collective (Abstract)", energy_type: "generated", description: "The channel of maturation
|
|
1024
|
-
"47-64": { name: "Abstraction", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of abstraction
|
|
1025
|
-
"57-20": { name: "The Brain Wave", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of the brain wave
|
|
1026
|
-
"58-18": { name: "Judgement", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of judgement
|
|
1027
|
-
"59-6": { name: "Intimacy", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of intimacy
|
|
1028
|
-
"60-3": { name: "Mutation", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of mutation
|
|
949
|
+
"1-8": { name: "Inspiration", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of creative inspiration — a unique individual frequency that inspires others through authentic self-expression. Not designed to broadcast; waits for recognition." },
|
|
950
|
+
"2-14": { name: "The Beat", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of the keeper of keys — a powerful sacral motor connected to the G center's direction. Attracts others magnetically toward purposeful resource accumulation." },
|
|
951
|
+
"3-60": { name: "Mutation", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of mutation — energy that transforms through accepted limitation. Initiates new patterns in a discontinuous, pulse-like fashion that disrupts the old." },
|
|
952
|
+
"4-63": { name: "Logic", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of mental logic — pressure and solutions meeting in a cycle of questioning and formulizing. Mental energy that must wait to be asked before offering answers." },
|
|
953
|
+
"5-15": { name: "Rhythm", circuit: "Collective (Logic)", energy_type: "generated", description: "The channel of fixed rhythms — humanity's flow and fixed patterns. Sacral motor powering universal timing; key to humanity's biological health rhythms." },
|
|
954
|
+
"6-59": { name: "Intimacy", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of intimacy — penetrating auras for mating and reproduction. Emotional authority governing who is let past one's auric boundaries." },
|
|
955
|
+
"7-31": { name: "The Alpha", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of the leader — democratic leadership providing direction to the collective. Recognition and invitation are essential; leadership must be elected, not seized." },
|
|
956
|
+
"9-52": { name: "Concentration", circuit: "Collective (Logic)", energy_type: "generated", description: "The channel of the focused mind — detail and concentration driving sacral response. Sustains attention on a single thread of logic until it resolves." },
|
|
957
|
+
"10-20": { name: "Awakening", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of awakening — the behaviour of the self expressed in the now. Presence and authenticity expressed without self-consciousness; a love of life in motion." },
|
|
958
|
+
"10-34": { name: "Exploration", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of following one's convictions — sacral power directed toward authentic self-expression and exploration. Highly independent." },
|
|
959
|
+
"10-57": { name: "Perfected Form", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of perfected form — survival instinct guided by intuition. Body awareness at its most refined; may produce physical beauty or extraordinary physical gifts." },
|
|
960
|
+
"11-56": { name: "Curiosity", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of the storyteller — abstract ideas turned into stimulating stories that expand others' perspectives. Conceptual awareness awaiting recognition." },
|
|
961
|
+
"12-22": { name: "Openness", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of openness — emotional grace in social engagement. When the wave is right, this channel opens conversations that can transform others profoundly." },
|
|
962
|
+
"13-33": { name: "The Prodigal", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of witness — listening to humanity's stories and retreating to share crystallised wisdom at the right time. The therapist channel." },
|
|
963
|
+
"16-48": { name: "The Wavelength", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of talent — depth of skill expressed as enthusiasm. Natural mastery that appears effortless; awakens when talents are recognised and invited." },
|
|
964
|
+
"17-62": { name: "Acceptance", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of organised activity — opinions formulated into detailed plans and frameworks. Facts and logic turned into workable systems." },
|
|
965
|
+
"18-58": { name: "Judgement", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of judgement — passionate criticism in service of joy and vitality. The desire to perfect what is alive; driven by love of life." },
|
|
966
|
+
"19-49": { name: "Synthesis", circuit: "Tribal (Defence)", energy_type: "projected", description: "The channel of synthesis — sensitivity to the tribe's emotional and material needs, combined with the power to revolutionise through principle. Resources and revolution." },
|
|
967
|
+
"20-34": { name: "Charisma", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of charisma — sacral response expressed in the now with extraordinary presence. Manifesting Generators often carry this channel; built for busy, impactful lives." },
|
|
968
|
+
"20-57": { name: "The Brain Wave", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of the brain wave — penetrating intuitive insight expressed without hesitation. A frequency that can inform the now with body-level knowing." },
|
|
969
|
+
"21-45": { name: "Money Line", circuit: "Tribal (Ego)", energy_type: "projected", description: "The channel of the money line — material world governance. Control over resources in the tribal hierarchy; the king/queen and the treasurer aligned." },
|
|
970
|
+
"23-43": { name: "Structuring", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of structuring — translating individual genius into language that others can hear. The key is timing; genius shared before recognition falls on deaf ears." },
|
|
971
|
+
"24-61": { name: "Awareness", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of awareness — mental pressure toward inner truth. Contemplative awareness cycling through questions until a genuine breakthrough arrives." },
|
|
972
|
+
"25-51": { name: "Initiation", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of initiation — innocence meeting the shock of the new. The shamanic channel; moves through crisis into universalising love." },
|
|
973
|
+
"26-44": { name: "Surrender", circuit: "Tribal (Defence)", energy_type: "projected", description: "The channel of surrender — ego memory and the transmission of the tribe's past patterns. Alert to what has and has not worked; a natural business channel." },
|
|
974
|
+
"27-50": { name: "Preservation", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of preservation — nurturing and values sustaining the tribe across generations. The channel of the mother/father archetype; keeping what is valuable alive." },
|
|
975
|
+
"28-38": { name: "Struggle", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of struggle — the game player meets the fighter in a search for purpose. Life is the game; the question is what is worth the fight." },
|
|
976
|
+
"29-46": { name: "Discovery", circuit: "Collective (Abstract)", energy_type: "generated", description: "The channel of discovery — sacral commitment to embodied experience. The body as the vehicle for serendipitous encounter; the great 'yes' to life." },
|
|
977
|
+
"30-41": { name: "Recognition", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of recognition — the beginning of all human experience. Emotional desire and fantasy that ignites new experiential cycles." },
|
|
978
|
+
"32-54": { name: "Transformation", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of transformation — instinct to transform ambition into material continuity. What endures; which ambitions serve the tribe's long-term survival." },
|
|
979
|
+
"34-57": { name: "Power", circuit: "Individual (Centering)", energy_type: "generated", description: "The channel of power — sacral life-force guided by intuition. Raw responsive power with in-the-moment instinctive awareness; self-sufficient and magnetic." },
|
|
980
|
+
"35-36": { name: "Transitoriness", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of transitoriness — the hunger for experience and the emotional crisis of each encounter. Rich emotional lessons through fully-felt experience." },
|
|
981
|
+
"37-40": { name: "Community", circuit: "Tribal (Ego)", energy_type: "projected", description: "The channel of community — bargain and agreement sustaining the family/tribe. Willpower renewed through rest; clear deals that make community sustainable." },
|
|
982
|
+
"39-55": { name: "Emoting", circuit: "Individual (Knowing)", energy_type: "projected", description: "The channel of emoting — the provocateur meeting the spirit of abundance. Gate 39 stirs the emotional wave; gate 55 determines whether spirit or suffering answers." },
|
|
983
|
+
"42-53": { name: "Maturation", circuit: "Collective (Abstract)", energy_type: "generated", description: "The channel of maturation — beginning and completing cycles of growth. The channel of sustainability; sacral energy that completes what it starts." },
|
|
984
|
+
"47-64": { name: "Abstraction", circuit: "Collective (Abstract)", energy_type: "projected", description: "The channel of abstraction — confusion ripening into realisation. Mental pressure from the past meeting images from the future; the alchemy of wisdom." },
|
|
985
|
+
"57-20": { name: "The Brain Wave", circuit: "Individual (Centering)", energy_type: "projected", description: "The channel of the brain wave — penetrating intuitive insight expressed without hesitation. A frequency that can inform the now with body-level knowing." },
|
|
986
|
+
"58-18": { name: "Judgement", circuit: "Collective (Logic)", energy_type: "projected", description: "The channel of judgement — vitality and correction. Joy arising from the pursuit of perfection in what is living and alive." },
|
|
987
|
+
"59-6": { name: "Intimacy", circuit: "Tribal (Defence)", energy_type: "generated", description: "The channel of intimacy — penetrating auras for mating and reproduction. Emotional authority governing who is let past one's auric boundaries." },
|
|
988
|
+
"60-3": { name: "Mutation", circuit: "Individual (Knowing)", energy_type: "generated", description: "The channel of mutation — energy that transforms through accepted limitation. Initiates new patterns in a discontinuous, pulse-like fashion." },
|
|
1029
989
|
};
|
|
1030
990
|
// ── Planet biographical themes (shared across tools) ─────────────────────────────
|
|
1031
991
|
const HD_PLANET_HD_THEMES = {
|
|
@@ -1349,7 +1309,7 @@ registerTool({
|
|
|
1349
1309
|
},
|
|
1350
1310
|
latitude: { type: "number", description: "Natal birth latitude (decimal degrees, +N). Optional." },
|
|
1351
1311
|
longitude: { type: "number", description: "Natal birth longitude (decimal degrees, +E). Optional." },
|
|
1352
|
-
location: { type: "string", description: "Natal location name, display only." },
|
|
1312
|
+
location: { type: "string", description: "Natal location name, display only. This is a caption, NOT a geocoder — it does not set the chart location. Supply latitude/longitude too (resolve them with location_search), or the chart is computed at 0N 0E." },
|
|
1353
1313
|
timezone: { type: "string", description: "IANA timezone for the birth location (e.g. 'America/New_York')." },
|
|
1354
1314
|
transit_datetime: {
|
|
1355
1315
|
type: "string",
|
|
@@ -1376,7 +1336,7 @@ registerTool({
|
|
|
1376
1336
|
handler: async (args) => {
|
|
1377
1337
|
const client = getActiveClient();
|
|
1378
1338
|
const timezone = args.timezone;
|
|
1379
|
-
const natalIso = localToUtcIso(String(args.datetime), timezone);
|
|
1339
|
+
const natalIso = localToUtcIso("datetime", String(args.datetime), timezone);
|
|
1380
1340
|
const lat = args.latitude ?? 0;
|
|
1381
1341
|
const lon = args.longitude ?? 0;
|
|
1382
1342
|
// SubjectRequest wire shape: name (required), birth_datetime.iso, and
|
|
@@ -1394,7 +1354,9 @@ registerTool({
|
|
|
1394
1354
|
},
|
|
1395
1355
|
};
|
|
1396
1356
|
if (args.transit_datetime) {
|
|
1397
|
-
body.transit_datetime = {
|
|
1357
|
+
body.transit_datetime = {
|
|
1358
|
+
iso: localToUtcIso("transit_datetime", String(args.transit_datetime), args.timezone),
|
|
1359
|
+
};
|
|
1398
1360
|
}
|
|
1399
1361
|
const bundleAvailable = Boolean(getBodygraphBundle());
|
|
1400
1362
|
// The Go endpoint defaults visual_config.theme to "light", which mismatches
|
|
@@ -1495,17 +1457,17 @@ registerTool({
|
|
|
1495
1457
|
_meta: { ui: { resourceUri: BODYGRAPH_RESOURCE_URI, visibility: ["model", "app"] } },
|
|
1496
1458
|
handler: async (args) => {
|
|
1497
1459
|
const client = getActiveClient();
|
|
1498
|
-
const toSubject = (p) => {
|
|
1460
|
+
const toSubject = (p, label) => {
|
|
1499
1461
|
const tz = p?.timezone;
|
|
1500
1462
|
return {
|
|
1501
|
-
birth_datetime_utc: localToUtcIso(String(p?.datetime), tz),
|
|
1463
|
+
birth_datetime_utc: localToUtcIso(`${label}.datetime`, String(p?.datetime), tz, `${label}.timezone`),
|
|
1502
1464
|
latitude: p?.latitude ?? 0,
|
|
1503
1465
|
longitude: p?.longitude ?? 0,
|
|
1504
1466
|
};
|
|
1505
1467
|
};
|
|
1506
1468
|
const body = {
|
|
1507
|
-
subject_1: toSubject(args.person_a),
|
|
1508
|
-
subject_2: toSubject(args.person_b),
|
|
1469
|
+
subject_1: toSubject(args.person_a, "person_a"),
|
|
1470
|
+
subject_2: toSubject(args.person_b, "person_b"),
|
|
1509
1471
|
};
|
|
1510
1472
|
const bundleAvailable = Boolean(getBodygraphBundle());
|
|
1511
1473
|
// Mirror the transit tool: explicit dark default, host-theme refetch.
|