From 77c4cc11aa2eccef82ca4c287cd7114bf946b6af Mon Sep 17 00:00:00 2001 From: Nico Arqueros <1622112+nicarq@users.noreply.github.com> Date: Tue, 6 Feb 2024 00:33:23 -0600 Subject: [PATCH] fix and tests --- src/schemas/shinkai_name.ts | 19 ++-- tests/shinkai_name.test.ts | 182 ++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 tests/shinkai_name.test.ts diff --git a/src/schemas/shinkai_name.ts b/src/schemas/shinkai_name.ts index aa7038e..f72a713 100644 --- a/src/schemas/shinkai_name.ts +++ b/src/schemas/shinkai_name.ts @@ -21,7 +21,7 @@ export class ShinkaiName { subidentityName: string | null; constructor(rawName: string) { - const correctedName = ShinkaiName.correctNodeName(rawName); + const correctedName = ShinkaiName.correctNodeName(rawName).toLowerCase(); const parts = correctedName.split("/"); this.nodeName = parts[0]; @@ -29,9 +29,7 @@ export class ShinkaiName { this.subidentityType = parts.length > 2 ? parts[2] : null; this.subidentityName = parts.length > 3 ? parts[3] : null; - this.fullName = correctedName.toLowerCase(); - if (this.nodeName) this.nodeName = this.nodeName.toLowerCase(); - if (this.profileName) this.profileName = this.profileName.toLowerCase(); + this.fullName = correctedName; } static isFullyValid(shinkaiName: string): boolean { @@ -303,7 +301,7 @@ export class ShinkaiName { } hasNoSubidentities(): boolean { - return this.profileName === undefined && this.subidentityType === undefined; + return this.profileName == null && this.subidentityType == null; } getProfileName(): string | null { @@ -335,18 +333,21 @@ export class ShinkaiName { } static correctNodeName(rawName: string): string { - let parts = rawName.split("/", 2); - let nodeName = parts[0]; + // Split without limiting the parts, to include all sections of the name + let parts = rawName.toLowerCase().split("/"); + // Correct the node name part + let nodeName = parts[0]; if (!nodeName.startsWith("@@")) { nodeName = "@@" + nodeName; } - if (!nodeName.endsWith(".shinkai")) { nodeName = nodeName + ".shinkai"; } + parts[0] = nodeName; // Update the node name part with corrections - let correctedName = parts.length > 1 ? nodeName + "/" + parts[1] : nodeName; + // Reconstruct the corrected name including all parts + let correctedName = parts.join("/"); return correctedName; } diff --git a/tests/shinkai_name.test.ts b/tests/shinkai_name.test.ts new file mode 100644 index 0000000..9a7fa01 --- /dev/null +++ b/tests/shinkai_name.test.ts @@ -0,0 +1,182 @@ +import { ShinkaiName } from "../src/schemas/shinkai_name"; + +describe("ShinkaiName", () => { + describe("Validation and Parsing", () => { + it.each([ + // Include expected outcomes in the test cases + [ + "@@alice.shinkai", + { + nodeName: "@@alice.shinkai", + profileName: null, + subidentityType: null, + subidentityName: null, + fullName: "@@alice.shinkai", + }, + ], + [ + "@@ALICE.SHINKAI", + { + nodeName: "@@alice.shinkai", + profileName: null, + subidentityType: null, + subidentityName: null, + fullName: "@@alice.shinkai", + }, + ], + [ + "@@alice_in_chains.shinkai", + { + nodeName: "@@alice_in_chains.shinkai", + profileName: null, + subidentityType: null, + subidentityName: null, + fullName: "@@alice_in_chains.shinkai", + }, + ], + [ + "@@alice.shinkai/profileName", + { + nodeName: "@@alice.shinkai", + profileName: "profilename", + subidentityType: null, + subidentityName: null, + fullName: "@@alice.shinkai/profilename", + }, + ], + [ + "@@alice.shinkai/profileName/agent/myChatGPTAgent", + { + nodeName: "@@alice.shinkai", + profileName: "profilename", + subidentityType: "agent", + subidentityName: "mychatgptagent", + fullName: "@@alice.shinkai/profilename/agent/mychatgptagent", + }, + ], + [ + "@@alice.shinkai/profileName/device/myPhone", + { + nodeName: "@@alice.shinkai", + profileName: "profilename", + subidentityType: "device", + subidentityName: "myphone", + fullName: "@@alice.shinkai/profilename/device/myphone", + }, + ], + [ + "@@localhost.shinkai/profileName/agent/STANDARD_TEXT", + { + nodeName: "@@localhost.shinkai", + profileName: "profilename", + subidentityType: "agent", + subidentityName: "standard_text", + fullName: "@@localhost.shinkai/profilename/agent/standard_text", + }, + ], + ])( + "should validate and parse valid Shinkai names: %s", + (name, expected) => { + const shinkaiName = new ShinkaiName(name); + console.log(`Creating new ShinkaiName for ${name} with: `, shinkaiName); + // Check that no error is thrown + expect(() => new ShinkaiName(name)).not.toThrow(); + // Check each property against the expected values + expect(shinkaiName.nodeName).toBe(expected.nodeName); + expect(shinkaiName.profileName).toBe(expected.profileName); + expect(shinkaiName.subidentityType).toBe(expected.subidentityType); + expect(shinkaiName.subidentityName).toBe(expected.subidentityName); + expect(shinkaiName.getValue()).toBe(expected.fullName); + } + ); + + it.each([ + // Invalid because it includes an unexpected segment 'myPhone' without a subidentity type + "@@alice.shinkai/profileName/myPhone", + // Invalid because it contains illegal characters '!'. + "@@al!ce.shinkai", + // Invalid because 'subidentity' is used without a profile name or subidentity type. + "@@alice/subidentity", + // Invalid because it ends with '//', indicating an incomplete subidentity part. + "@@alice.shinkai//", + // Invalid because it contains '//subidentity' without a proper subidentity type. + "@@alice.shinkai//subidentity", + // Invalid because 'profile_1.shinkai' is not a valid profile name. + "@@node1.shinkai/profile_1.shinkai", + ])( + "should return false for isFullyValid with invalid names: %s", + (name) => { + expect(ShinkaiName.isFullyValid(name)).toBe(false); + } + ); + + it.each([ + "@@alice.shinkai/profileName/myPhone", + "@@al!ce.shinkai", + "@@alice/subidentity", + "@@alice.shinkai//", + "@@alice.shinkai//subidentity", + "@@node1.shinkai/profile_1.shinkai", + ])( + "should return false for isFullyValid with invalid names: %s", + (name) => { + expect(ShinkaiName.isFullyValid(name)).toBe(false); + } + ); + + it("should correct and format name without Shinkai suffix", () => { + const name = "@@alice"; + const shinkaiName = new ShinkaiName(name); + expect(shinkaiName.getValue()).toBe("@@alice.shinkai"); + }); + + it("should correct and format name without Shinkai prefix", () => { + const name = "alice.shinkai"; + const shinkaiName = new ShinkaiName(name); + expect(shinkaiName.getValue()).toBe("@@alice.shinkai"); + }); + + it("should handle profile inclusion correctly", () => { + const shinkaiName = new ShinkaiName("@@charlie.shinkai/profileCharlie"); + expect(shinkaiName.hasProfile()).toBe(true); + }); + + it("should handle device inclusion correctly", () => { + const shinkaiName = new ShinkaiName( + "@@dave.shinkai/profileDave/device/myDevice" + ); + expect(shinkaiName.hasDevice()).toBe(true); + }); + + it("should identify names without subidentities correctly", () => { + const shinkaiName = new ShinkaiName("@@eve.shinkai"); + console.log(shinkaiName); + expect(shinkaiName.hasNoSubidentities()).toBe(true); + }); + + it("should extract profile name correctly", () => { + const shinkaiName = new ShinkaiName("@@frank.shinkai/profileFrank"); + expect(shinkaiName.getProfileName()).toBe("profilefrank"); + }); + + it("should extract node correctly", () => { + const shinkaiName = new ShinkaiName( + "@@henry.shinkai/profileHenry/device/myDevice" + ); + const node = shinkaiName.extractNode(); + expect(node.getValue()).toBe("@@henry.shinkai"); + }); + + it("should correctly determine containment relationships", () => { + const alice = new ShinkaiName("@@alice.shinkai"); + const aliceProfile = new ShinkaiName("@@alice.shinkai/profileName"); + expect(alice.contains(aliceProfile)).toBe(true); + }); + + it("should correctly identify non-containment relationships", () => { + const alice = new ShinkaiName("@@alice.shinkai"); + const bob = new ShinkaiName("@@bob.shinkai"); + expect(alice.contains(bob)).toBe(false); + }); + }); +});