@rubytech/create-realagent 1.0.869 → 1.0.871
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/package.json +1 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js +83 -91
- package/payload/platform/plugins/admin/mcp/dist/__tests__/public-hostname.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +7 -10
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.d.ts +5 -11
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js +66 -47
- package/payload/platform/plugins/admin/mcp/dist/lib/public-hostname.js.map +1 -1
- package/payload/platform/plugins/admin/skills/publish-site/SKILL.md +2 -2
- package/payload/platform/plugins/docs/references/internals.md +1 -1
- package/payload/platform/scripts/__tests__/admin-persist-audit.test.ts +182 -0
- package/payload/platform/scripts/admin-persist-audit.ts +43 -17
- package/payload/server/chunk-5U36PKG4.js +11326 -0
- package/payload/server/chunk-NDEQBCVI.js +1160 -0
- package/payload/server/client-pool-XAEDMS5D.js +34 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{Checkbox-B9hff9s8.js → Checkbox-CDffo5el.js} +1 -1
- package/payload/server/public/assets/{admin-Cpi6L_g7.js → admin-BSdV45P5.js} +2 -2
- package/payload/server/public/assets/data-vFVtOwuC.js +1 -0
- package/payload/server/public/assets/{graph-labels-ChinGFwI.js → graph-labels-C-KsUF_B.js} +1 -1
- package/payload/server/public/assets/graph-q802cxLY.js +1 -0
- package/payload/server/public/assets/{jsx-runtime-CVA1ZrPS.css → jsx-runtime-C1hGBzVx.css} +1 -1
- package/payload/server/public/assets/{page-OVrxtgOZ.js → page-B5b7tyz-.js} +1 -1
- package/payload/server/public/assets/{page-DqPf65sS.js → page-DsW7P98i.js} +1 -1
- package/payload/server/public/assets/{public-CJN5KAiK.js → public-BkNXx-3G.js} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-DyVx7e7a.js → useVoiceRecorder-DCVSlfUk.js} +1 -1
- package/payload/server/public/data.html +5 -5
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +8 -8
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +38 -18
- package/payload/server/public/assets/data-Da6iYRW1.js +0 -1
- package/payload/server/public/assets/graph-BHq-JYwV.js +0 -1
- /package/payload/server/public/assets/{jsx-runtime-nxP_2eNo.js → jsx-runtime-DFrHsKhm.js} +0 -0
package/package.json
CHANGED
|
@@ -1,106 +1,98 @@
|
|
|
1
|
-
// Task
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import { resolvePublicHostname, } from "../lib/public-hostname.js";
|
|
13
|
-
function assertMiss(r) {
|
|
14
|
-
if (r.hostname !== null)
|
|
15
|
-
throw new Error("expected miss, got hit");
|
|
1
|
+
// Task 971 — filesystem-only resolver tests (4th recurrence of
|
|
2
|
+
// llm-framing-deterministic). Each test seeds a temp configDir on disk and
|
|
3
|
+
// asserts the chosen hostname, source, and isApex flag — no driver, no graph.
|
|
4
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
5
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { resolvePublicHostname } from "../lib/public-hostname.js";
|
|
9
|
+
function writeConfigYml(configDir, body) {
|
|
10
|
+
mkdirSync(join(configDir, "cloudflared"), { recursive: true });
|
|
11
|
+
writeFileSync(join(configDir, "cloudflared", "config.yml"), body);
|
|
16
12
|
}
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
function mockSession(results) {
|
|
21
|
-
let i = 0;
|
|
22
|
-
const run = vi.fn((_cypher, _params) => {
|
|
23
|
-
if (i >= results.length)
|
|
24
|
-
throw new Error(`unexpected session.run call #${i + 1}`);
|
|
25
|
-
return Promise.resolve(results[i++]);
|
|
26
|
-
});
|
|
27
|
-
const close = vi.fn(() => Promise.resolve());
|
|
28
|
-
return { run, close };
|
|
13
|
+
function writeAliasDomains(configDir, list) {
|
|
14
|
+
writeFileSync(join(configDir, "alias-domains.json"), JSON.stringify(list));
|
|
29
15
|
}
|
|
30
16
|
describe("resolvePublicHostname", () => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
17
|
+
let configDir;
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
configDir = mkdtempSync(join(tmpdir(), "public-hostname-test-"));
|
|
20
|
+
});
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
rmSync(configDir, { recursive: true, force: true });
|
|
23
|
+
});
|
|
24
|
+
it("returns the single ingress hostname from cloudflared/config.yml", () => {
|
|
25
|
+
writeConfigYml(configDir, [
|
|
26
|
+
"tunnel: abc-123",
|
|
27
|
+
"ingress:",
|
|
28
|
+
" - hostname: realagent.app",
|
|
29
|
+
" service: http://localhost:3000",
|
|
30
|
+
" - service: http_status:404",
|
|
31
|
+
"",
|
|
32
|
+
].join("\n"));
|
|
33
|
+
expect(resolvePublicHostname(configDir)).toEqual({
|
|
34
|
+
hostname: "realagent.app",
|
|
35
|
+
isApex: true,
|
|
36
|
+
source: "cloudflared-config.yml",
|
|
44
37
|
});
|
|
45
|
-
expect(session.run).toHaveBeenCalledTimes(1);
|
|
46
|
-
const [cypher, params] = session.run.mock.calls[0];
|
|
47
|
-
expect(cypher).toContain("CloudflareHostname");
|
|
48
|
-
expect(cypher).toContain("h.hostnameValue");
|
|
49
|
-
expect(cypher).toContain("h.isApex");
|
|
50
|
-
expect(cypher).toContain("h.tunnelId");
|
|
51
|
-
expect(cypher).toContain("ORDER BY h.isApex DESC");
|
|
52
|
-
expect(cypher).toContain("LIMIT 1");
|
|
53
|
-
expect(params).toEqual({ accountId: "acc-1" });
|
|
54
38
|
});
|
|
55
|
-
it("
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
it("prefers apex over subdomain when both appear in config.yml", () => {
|
|
40
|
+
writeConfigYml(configDir, [
|
|
41
|
+
"ingress:",
|
|
42
|
+
" - hostname: public.realagent.app",
|
|
43
|
+
" service: http://localhost:3000",
|
|
44
|
+
" - hostname: realagent.app",
|
|
45
|
+
" service: http://localhost:3000",
|
|
46
|
+
"",
|
|
47
|
+
].join("\n"));
|
|
48
|
+
const r = resolvePublicHostname(configDir);
|
|
61
49
|
expect(r).toEqual({
|
|
62
|
-
hostname:
|
|
63
|
-
isApex:
|
|
64
|
-
|
|
65
|
-
reason: "no-hostname",
|
|
50
|
+
hostname: "realagent.app",
|
|
51
|
+
isApex: true,
|
|
52
|
+
source: "cloudflared-config.yml",
|
|
66
53
|
});
|
|
67
|
-
expect(session.run).toHaveBeenCalledTimes(2);
|
|
68
|
-
const [tunnelCypher] = session.run.mock.calls[1];
|
|
69
|
-
expect(tunnelCypher).toContain("CloudflareTunnel");
|
|
70
54
|
});
|
|
71
|
-
it("
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
55
|
+
it("filters localhost and *.local entries from config.yml ingress", () => {
|
|
56
|
+
writeConfigYml(configDir, [
|
|
57
|
+
"ingress:",
|
|
58
|
+
" - hostname: localhost",
|
|
59
|
+
" service: http://127.0.0.1:7474",
|
|
60
|
+
" - hostname: maxy.local",
|
|
61
|
+
" service: http://127.0.0.1:7475",
|
|
62
|
+
" - hostname: realagent.app",
|
|
63
|
+
" service: http://localhost:3000",
|
|
64
|
+
"",
|
|
65
|
+
].join("\n"));
|
|
66
|
+
expect(resolvePublicHostname(configDir).hostname).toBe("realagent.app");
|
|
67
|
+
});
|
|
68
|
+
it("treats www.<apex> as apex via prefix-strip tiebreak", () => {
|
|
69
|
+
writeConfigYml(configDir, [
|
|
70
|
+
"ingress:",
|
|
71
|
+
" - hostname: foo.realagent.app",
|
|
72
|
+
" service: http://localhost:3000",
|
|
73
|
+
" - hostname: www.realagent.app",
|
|
74
|
+
" service: http://localhost:3000",
|
|
75
|
+
"",
|
|
76
|
+
].join("\n"));
|
|
77
|
+
const r = resolvePublicHostname(configDir);
|
|
78
|
+
expect(r.hostname).toBe("www.realagent.app");
|
|
79
|
+
expect(r.isApex).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
it("falls back to alias-domains.json when config.yml is absent", () => {
|
|
82
|
+
writeAliasDomains(configDir, ["realagent.app"]);
|
|
83
|
+
expect(resolvePublicHostname(configDir)).toEqual({
|
|
84
|
+
hostname: "realagent.app",
|
|
85
|
+
isApex: true,
|
|
86
|
+
source: "alias-domains.json",
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it("returns reason=no-tunnel when neither file is populated", () => {
|
|
90
|
+
expect(resolvePublicHostname(configDir)).toEqual({
|
|
78
91
|
hostname: null,
|
|
79
92
|
isApex: null,
|
|
80
|
-
|
|
93
|
+
source: null,
|
|
81
94
|
reason: "no-tunnel",
|
|
82
95
|
});
|
|
83
96
|
});
|
|
84
|
-
it("handles Neo4j Integer return for the tunnel count", async () => {
|
|
85
|
-
// neo4j-driver returns count() as an Integer object with low/high fields
|
|
86
|
-
// and a toNumber() method. The resolver must unwrap it.
|
|
87
|
-
const integerLike = { low: 3, high: 0, toNumber: () => 3 };
|
|
88
|
-
const session = mockSession([
|
|
89
|
-
{ records: [] },
|
|
90
|
-
{ records: [record({ n: integerLike })] },
|
|
91
|
-
]);
|
|
92
|
-
const r = await resolvePublicHostname(session, "acc-1");
|
|
93
|
-
assertMiss(r);
|
|
94
|
-
expect(r.reason).toBe("no-hostname");
|
|
95
|
-
});
|
|
96
|
-
it("scopes the query to accountId — no cross-account leakage", async () => {
|
|
97
|
-
const session = mockSession([
|
|
98
|
-
{ records: [] },
|
|
99
|
-
{ records: [record({ n: 0 })] },
|
|
100
|
-
]);
|
|
101
|
-
await resolvePublicHostname(session, "acc-X");
|
|
102
|
-
expect(session.run.mock.calls[0][1]).toEqual({ accountId: "acc-X" });
|
|
103
|
-
expect(session.run.mock.calls[1][1]).toEqual({ accountId: "acc-X" });
|
|
104
|
-
});
|
|
105
97
|
});
|
|
106
98
|
//# sourceMappingURL=public-hostname.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-hostname.test.js","sourceRoot":"","sources":["../../src/__tests__/public-hostname.test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"public-hostname.test.js","sourceRoot":"","sources":["../../src/__tests__/public-hostname.test.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2EAA2E;AAC3E,8EAA8E;AAE9E,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAElE,SAAS,cAAc,CAAC,SAAiB,EAAE,IAAY;IACrD,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,YAAY,CAAC,EAAE,IAAI,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,iBAAiB,CAAC,SAAiB,EAAE,IAAa;IACzD,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,IAAI,SAAiB,CAAC;IAEtB,UAAU,CAAC,GAAG,EAAE;QACd,SAAS,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;QACzE,cAAc,CAAC,SAAS,EAAE;YACxB,iBAAiB;YACjB,UAAU;YACV,6BAA6B;YAC7B,oCAAoC;YACpC,8BAA8B;YAC9B,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/C,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,wBAAwB;SACjC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,cAAc,CAAC,SAAS,EAAE;YACxB,UAAU;YACV,oCAAoC;YACpC,oCAAoC;YACpC,6BAA6B;YAC7B,oCAAoC;YACpC,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAChB,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,wBAAwB;SACjC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,cAAc,CAAC,SAAS,EAAE;YACxB,UAAU;YACV,yBAAyB;YACzB,oCAAoC;YACpC,0BAA0B;YAC1B,oCAAoC;YACpC,6BAA6B;YAC7B,oCAAoC;YACpC,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,cAAc,CAAC,SAAS,EAAE;YACxB,UAAU;YACV,iCAAiC;YACjC,oCAAoC;YACpC,iCAAiC;YACjC,oCAAoC;YACpC,EAAE;SACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC7C,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,iBAAiB,CAAC,SAAS,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/C,QAAQ,EAAE,eAAe;YACzB,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,oBAAoB;SAC7B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,MAAM,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YAC/C,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,WAAW;SACpB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -403,27 +403,24 @@ server.tool("system-status", "Check health of all Maxy platform services: Neo4j,
|
|
|
403
403
|
.join("\n");
|
|
404
404
|
return { content: [{ type: "text", text: formatted }] };
|
|
405
405
|
});
|
|
406
|
-
server.tool("public-hostname", "Resolve this account's canonical public hostname
|
|
406
|
+
server.tool("public-hostname", "Resolve this account's canonical public hostname. Reads cloudflared ingress + alias-domains.json — the same files the platform server trusts to route. Returns a single deterministic answer; use this immediately after publish-site to construct the full URL.", {}, async () => {
|
|
407
407
|
const TAG = "[admin:public-hostname]";
|
|
408
|
-
const session = getSession();
|
|
409
408
|
try {
|
|
410
|
-
const result =
|
|
409
|
+
const result = resolvePublicHostname(CONFIG_DIR);
|
|
411
410
|
if (result.hostname !== null) {
|
|
412
|
-
console.error(`${TAG} resolved accountId=${ACCOUNT_ID} hostname=${result.hostname}
|
|
411
|
+
console.error(`${TAG} resolved accountId=${ACCOUNT_ID} hostname=${result.hostname} source=${result.source}`);
|
|
413
412
|
const body = `hostname: ${result.hostname}\n` +
|
|
414
413
|
`isApex: ${result.isApex}\n` +
|
|
415
|
-
`
|
|
414
|
+
`source: ${result.source}\n` +
|
|
416
415
|
`usage: paste \`https://${result.hostname}<path-slug>\` to the operator — the <path-slug> comes from publish-site.`;
|
|
417
416
|
return { content: [{ type: "text", text: body }] };
|
|
418
417
|
}
|
|
419
|
-
console.error(`${TAG} empty accountId=${ACCOUNT_ID} reason=${result.reason}`);
|
|
420
|
-
const remediation = result.reason === "no-tunnel"
|
|
421
|
-
? "No Cloudflare tunnel is configured for this account. Run the cloudflare setup-tunnel skill before publishing externally."
|
|
422
|
-
: "A Cloudflare tunnel exists but no public hostname is bound to it. Run the cloudflare setup-hostname skill before publishing externally.";
|
|
418
|
+
console.error(`${TAG} empty accountId=${ACCOUNT_ID} reason=${result.reason} files-checked=cloudflared-config.yml,alias-domains.json`);
|
|
423
419
|
return {
|
|
424
420
|
content: [{
|
|
425
421
|
type: "text",
|
|
426
|
-
text: `hostname: (none)\nreason: ${result.reason}\n
|
|
422
|
+
text: `hostname: (none)\nreason: ${result.reason}\n` +
|
|
423
|
+
`No Cloudflare tunnel is configured for this account. Run the cloudflare setup-tunnel skill before publishing externally.`,
|
|
427
424
|
}],
|
|
428
425
|
};
|
|
429
426
|
}
|