@rubytech/create-realagent 1.0.771 → 1.0.772
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/PLUGIN.md +2 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +88 -16
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js +21 -6
- package/payload/platform/plugins/memory/mcp/dist/tools/profile-read.js.map +1 -1
- package/payload/platform/templates/agents/admin/IDENTITY.md +3 -2
- package/payload/server/chunk-57S5JC7G.js +9563 -0
- package/payload/server/chunk-XHFMXKXI.js +3179 -0
- package/payload/server/client-pool-J4ZHJ6Z3.js +28 -0
- package/payload/server/maxy-edge.js +2 -2
- package/payload/server/public/assets/{admin-CaXX8wc3.js → admin-CFttroHB.js} +6 -6
- package/payload/server/public/index.html +1 -1
- package/payload/server/server.js +60 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: admin
|
|
3
|
-
description: "Platform administration plugin. Provides system-status, brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, agent-list, agent-config-read, logs-read, plugin-read, render-component, session-reset, session-resume, file-attach, wifi, review-cadence tools (review-rules-list, review-rules-suppress, review-rules-unsuppress, review-rules-add, review-rules-remove, review-alerts-recent), adherence-read (attention-weighted adherence ledger), and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform."
|
|
3
|
+
description: "Platform administration plugin. Provides system-status, brand-settings, account-manage, account-update, admin-add, admin-remove, admin-list, admin-update-pin, agent-list, agent-config-read, logs-read, plugin-read, render-component, session-reset, session-resume, file-attach, wifi, review-cadence tools (review-rules-list, review-rules-suppress, review-rules-unsuppress, review-rules-add, review-rules-remove, review-alerts-recent), adherence-read (attention-weighted adherence ledger), and action-approval tools (action-pending, action-approve, action-reject, action-edit) for managing the Maxy platform."
|
|
4
4
|
tools:
|
|
5
5
|
- system-status
|
|
6
6
|
- brand-settings
|
|
@@ -9,6 +9,7 @@ tools:
|
|
|
9
9
|
- admin-add
|
|
10
10
|
- admin-remove
|
|
11
11
|
- admin-list
|
|
12
|
+
- admin-update-pin
|
|
12
13
|
- agent-list
|
|
13
14
|
- agent-config-read
|
|
14
15
|
- logs-read
|
|
@@ -545,9 +545,9 @@ server.tool("account-update", "Update a user-configurable setting in account.jso
|
|
|
545
545
|
// ===================================================================
|
|
546
546
|
// Admin user management tools
|
|
547
547
|
// ===================================================================
|
|
548
|
-
server.tool("admin-add", "Add a new admin user to this account. Creates a device-level user entry (users.json) and adds them to this account's admins list (account.json).
|
|
549
|
-
name: z.string().describe("Display name for the new admin"),
|
|
550
|
-
pin: z.string().optional().describe("Optional 4
|
|
548
|
+
server.tool("admin-add", "Add a new admin user to this account. Creates a device-level user entry (users.json) and adds them to this account's admins list (account.json). PIN must be at least 4 digits. If no PIN is provided, a unique 4-digit PIN is generated. Returns the userId and PIN to share with the new admin.", {
|
|
549
|
+
name: z.string().describe("Display name for the new admin (stored on the AdminUser node in Neo4j)."),
|
|
550
|
+
pin: z.string().optional().describe("Optional PIN (minimum 4 digits). If omitted, a unique 4-digit PIN is generated."),
|
|
551
551
|
}, async ({ name, pin: rawPin }) => {
|
|
552
552
|
const TAG = "[admin]";
|
|
553
553
|
if (!name.trim()) {
|
|
@@ -577,7 +577,7 @@ server.tool("admin-add", "Add a new admin user to this account. Creates a device
|
|
|
577
577
|
}
|
|
578
578
|
// Resolve the calling user's identity from the session environment
|
|
579
579
|
const callerUserId = process.env.USER_ID;
|
|
580
|
-
// PIN: use provided or generate
|
|
580
|
+
// PIN: use provided or generate. Constraint: minimum 4 digits, no upper bound.
|
|
581
581
|
let plaintextPin;
|
|
582
582
|
if (rawPin) {
|
|
583
583
|
if (rawPin.length < 4) {
|
|
@@ -599,8 +599,9 @@ server.tool("admin-add", "Add a new admin user to this account. Creates a device
|
|
|
599
599
|
}
|
|
600
600
|
const pinHash = hashPin(plaintextPin);
|
|
601
601
|
const userId = crypto.randomUUID();
|
|
602
|
-
// 1. Write to users.json (device-level)
|
|
603
|
-
|
|
602
|
+
// 1. Write to users.json (device-level). Auth fields only — `name` lives
|
|
603
|
+
// on the AdminUser node in Neo4j (Task 829).
|
|
604
|
+
users.push({ userId, pin: pinHash });
|
|
604
605
|
try {
|
|
605
606
|
writeUsersJson(users);
|
|
606
607
|
}
|
|
@@ -676,13 +677,22 @@ server.tool("admin-remove", "Remove an admin from this account. Removes them fro
|
|
|
676
677
|
if (admins.length <= 1) {
|
|
677
678
|
return { content: [{ type: "text", text: `${TAG} Cannot remove the last admin. At least one admin must remain on the account.` }], isError: true };
|
|
678
679
|
}
|
|
679
|
-
// Resolve the admin's name for the confirmation
|
|
680
|
+
// Resolve the admin's name from Neo4j (canonical) for the confirmation
|
|
681
|
+
// message. Best-effort — fall back to userId if the graph is unreachable.
|
|
680
682
|
let removedName = userId;
|
|
681
683
|
try {
|
|
682
|
-
const
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
684
|
+
const session = getSession();
|
|
685
|
+
try {
|
|
686
|
+
const result = await session.run(`MATCH (au:AdminUser {userId: $userId}) RETURN au.name AS name LIMIT 1`, { userId });
|
|
687
|
+
if (result.records.length > 0) {
|
|
688
|
+
const name = result.records[0].get("name");
|
|
689
|
+
if (name && name.trim())
|
|
690
|
+
removedName = name.trim();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
finally {
|
|
694
|
+
await session.close();
|
|
695
|
+
}
|
|
686
696
|
}
|
|
687
697
|
catch { /* name lookup is best-effort */ }
|
|
688
698
|
// 1. Remove from account.json
|
|
@@ -733,13 +743,27 @@ server.tool("admin-list", "List all admins for this account with their names and
|
|
|
733
743
|
if (admins.length === 0) {
|
|
734
744
|
return { content: [{ type: "text", text: `${TAG} No admins configured for this account.` }] };
|
|
735
745
|
}
|
|
736
|
-
// Enrich with names from
|
|
737
|
-
|
|
746
|
+
// Enrich with names from Neo4j AdminUser (canonical, Task 829). Best
|
|
747
|
+
// effort — render "(unknown)" for any userId without a graph entry.
|
|
748
|
+
const userMap = new Map();
|
|
738
749
|
try {
|
|
739
|
-
|
|
750
|
+
const session = getSession();
|
|
751
|
+
try {
|
|
752
|
+
const result = await session.run(`UNWIND $userIds AS uid
|
|
753
|
+
MATCH (au:AdminUser {userId: uid})
|
|
754
|
+
RETURN au.userId AS userId, au.name AS name`, { userIds: admins.map(a => a.userId) });
|
|
755
|
+
for (const record of result.records) {
|
|
756
|
+
const uid = record.get("userId");
|
|
757
|
+
const name = record.get("name");
|
|
758
|
+
if (name && name.trim())
|
|
759
|
+
userMap.set(uid, name.trim());
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
finally {
|
|
763
|
+
await session.close();
|
|
764
|
+
}
|
|
740
765
|
}
|
|
741
|
-
catch { /* name lookup is best-effort —
|
|
742
|
-
const userMap = new Map(users.map(u => [u.userId, u.name]));
|
|
766
|
+
catch { /* name lookup is best-effort — userIds shown when graph is unreachable */ }
|
|
743
767
|
const lines = admins.map(a => {
|
|
744
768
|
const name = userMap.get(a.userId) ?? "(unknown)";
|
|
745
769
|
return `- **${name}** — role: ${a.role}, userId: ${a.userId}`;
|
|
@@ -748,6 +772,54 @@ server.tool("admin-list", "List all admins for this account with their names and
|
|
|
748
772
|
content: [{ type: "text", text: `Admins for this account:\n\n${lines.join("\n")}` }],
|
|
749
773
|
};
|
|
750
774
|
});
|
|
775
|
+
server.tool("admin-update-pin", "Update an existing admin user's PIN. Defaults to the calling admin if no userId is given. PIN must be at least 4 digits and unique across all users on the device. PINs are device-level: updating another admin's PIN does not require shared account membership — any admin on the device can rotate any other admin's PIN, matching the existing trust model used by admin-remove.", {
|
|
776
|
+
userId: z.string().optional().describe("The userId of the admin whose PIN to update. Defaults to the caller (the admin invoking this tool)."),
|
|
777
|
+
newPin: z.string().describe("The new PIN. Minimum 4 digits, no upper bound."),
|
|
778
|
+
}, async ({ userId: targetUserId, newPin }) => {
|
|
779
|
+
const TAG = "[admin-update-pin]";
|
|
780
|
+
const callerUserId = process.env.USER_ID;
|
|
781
|
+
const userId = targetUserId ?? callerUserId;
|
|
782
|
+
const userIdLabel = userId ? userId.slice(0, 8) : "unknown";
|
|
783
|
+
if (!userId) {
|
|
784
|
+
console.error(`${TAG} userId=${userIdLabel} result=user-not-found reason=no-caller-context`);
|
|
785
|
+
return { content: [{ type: "text", text: `${TAG} No userId supplied and no caller context — cannot update.` }], isError: true };
|
|
786
|
+
}
|
|
787
|
+
if (newPin.length < 4) {
|
|
788
|
+
console.error(`${TAG} userId=${userIdLabel} result=too-short`);
|
|
789
|
+
return { content: [{ type: "text", text: `${TAG} PIN must be at least 4 digits.` }], isError: true };
|
|
790
|
+
}
|
|
791
|
+
let users;
|
|
792
|
+
try {
|
|
793
|
+
users = readUsersJson();
|
|
794
|
+
}
|
|
795
|
+
catch (err) {
|
|
796
|
+
console.error(`${TAG} userId=${userIdLabel} result=user-not-found reason=users-json-read-failed`);
|
|
797
|
+
return { content: [{ type: "text", text: `${TAG} ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
798
|
+
}
|
|
799
|
+
const targetIndex = users.findIndex(u => u.userId === userId);
|
|
800
|
+
if (targetIndex === -1) {
|
|
801
|
+
console.error(`${TAG} userId=${userIdLabel} result=user-not-found`);
|
|
802
|
+
return { content: [{ type: "text", text: `${TAG} User ${userId} not found in users.json.` }], isError: true };
|
|
803
|
+
}
|
|
804
|
+
const newHash = hashPin(newPin);
|
|
805
|
+
const collidesWithOther = users.some((u, i) => i !== targetIndex && u.pin === newHash);
|
|
806
|
+
if (collidesWithOther) {
|
|
807
|
+
console.error(`${TAG} userId=${userIdLabel} result=collision`);
|
|
808
|
+
return { content: [{ type: "text", text: `${TAG} That PIN is already in use by another user. Choose a different PIN.` }], isError: true };
|
|
809
|
+
}
|
|
810
|
+
users[targetIndex].pin = newHash;
|
|
811
|
+
try {
|
|
812
|
+
writeUsersJson(users);
|
|
813
|
+
}
|
|
814
|
+
catch (err) {
|
|
815
|
+
return { content: [{ type: "text", text: `${TAG} Failed to write users.json: ${err instanceof Error ? err.message : String(err)}` }], isError: true };
|
|
816
|
+
}
|
|
817
|
+
console.error(`${TAG} userId=${userIdLabel} result=ok`);
|
|
818
|
+
const self = userId === callerUserId;
|
|
819
|
+
return {
|
|
820
|
+
content: [{ type: "text", text: `PIN updated${self ? "" : ` for userId ${userId}`}. The new PIN takes effect on the next login.` }],
|
|
821
|
+
};
|
|
822
|
+
});
|
|
751
823
|
server.tool("agent-image", "Upload, update, or remove an agent's image. action=set: copy the file at filePath to the agent's assets directory and update config.json with image URL and shape. action=remove: delete the image file and clear the image fields from config.json. imageShape: 'circle' for avatars/icons, 'rounded' for logos.", {
|
|
752
824
|
agentSlug: z.string().describe("Agent slug (e.g. 'coaching', 'sales')"),
|
|
753
825
|
action: z.enum(["set", "remove"]),
|