Skip to content

Commit

Permalink
Merge pull request #32 from dcSpark/fix-is-local-message
Browse files Browse the repository at this point in the history
- fix: refactor isLocalMessage to generalize use cases
  • Loading branch information
nicarq authored Oct 5, 2023
2 parents c411682 + 1539c10 commit b670f11
Show file tree
Hide file tree
Showing 9 changed files with 562 additions and 23 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"react/react-in-jsx-scope": "off",
"react/jsx-uses-react": "off",
"simple-import-sort/imports": "error",
"react/jsx-sort-props": "warn"
"react/jsx-sort-props": "warn",
"react/prop-types": "off"
},
"overrides": [
{
Expand Down
45 changes: 45 additions & 0 deletions .github/workflows/pr-ci-healchecks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: PR CI Health checks

on:
pull_request:
branches: [ main ]

defaults:
run:
working-directory: ./

jobs:
health-checks:
runs-on: ubuntu-latest
strategy:
fail-fast: true
max-parallel: 1
matrix:
target: ['lint', 'build', 'test']

steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Use nx set shas
uses: nrwl/nx-set-shas@v3


- name: Setup Node version
uses: actions/setup-node@v3
with:
node-version: 18
check-latest: false
registry-url: https://registry.npmjs.org
cache: "npm"
cache-dependency-path: package-lock.json

- name: Install dependencies
run: |
npm cache verify
npm ci --no-audit --prefer-offline
- name: Run NX target ${{ matrix.target }} on affected projects
run: npx nx affected -t ${{ matrix.target }} --parallel=3 --skip-nx-cache --verbose
147 changes: 147 additions & 0 deletions libs/shinkai-message-ts/src/utils/shinkai_message_handler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { isLocalMessage } from './shinkai_message_handler';

describe('shinkai_messag_handler isLocalMessage', () => {
const messageSentByNode1MainDevice = `{
"body": {
"unencrypted": {
"message_data": {
"unencrypted": {
"message_raw_content": "hey!",
"message_content_schema": "TextContent"
}
},
"internal_metadata": {
"sender_subidentity": "main/device/main_device",
"recipient_subidentity": "",
"inbox": "inbox::@@node1.shinkai/main/device/main_device::@@node2.shinkai::false",
"signature": "",
"encryption": "None"
}
}
},
"external_metadata": {
"sender": "@@node1.shinkai",
"recipient": "@@node2.shinkai",
"scheduled_time": "2023-08-25T22:44:01.132Z",
"signature": "c6d0115c0878fbf2279f98aab67c0e9cb1af63825f49dca48d6e4420eba0ceb973e00488ba0905c9afd09254f0dac48c468fdcb1d6c5ab5ca4c5dd70a440b903",
"other": ""
},
"encryption": "None",
"version": "V1_0"
}`;

const messageSentByNode1SecondaryDevice = `{
"body": {
"unencrypted": {
"message_data": {
"unencrypted": {
"message_raw_content": "hey!",
"message_content_schema": "TextContent"
}
},
"internal_metadata": {
"sender_subidentity": "main/device/secondary_device",
"recipient_subidentity": "",
"inbox": "inbox::@@node1.shinkai/main/device/secondary_device::@@node2.shinkai::false",
"signature": "",
"encryption": "None"
}
}
},
"external_metadata": {
"sender": "@@node1.shinkai",
"recipient": "@@node2.shinkai",
"scheduled_time": "2023-08-25T22:44:01.132Z",
"signature": "c6d0115c0878fbf2279f98aab67c0e9cb1af63825f49dca48d6e4420eba0ceb973e00488ba0905c9afd09254f0dac48c468fdcb1d6c5ab5ca4c5dd70a440b903",
"other": ""
},
"encryption": "None",
"version": "V1_0"
}`;

const messageSentByNode1AgentGpt = `{
"body": {
"unencrypted": {
"message_data": {
"unencrypted": {
"message_raw_content": "hey!",
"message_content_schema": "TextContent"
}
},
"internal_metadata": {
"sender_subidentity": "main/agent/gpt",
"recipient_subidentity": "",
"inbox": "job_inbox::@@node1.shinkai/main/agent/gpt::@@node2.shinkai::false",
"signature": "",
"encryption": "None"
}
}
},
"external_metadata": {
"sender": "@@node1.shinkai",
"recipient": "@@node2.shinkai",
"scheduled_time": "2023-08-25T22:44:01.132Z",
"signature": "c6d0115c0878fbf2279f98aab67c0e9cb1af63825f49dca48d6e4420eba0ceb973e00488ba0905c9afd09254f0dac48c468fdcb1d6c5ab5ca4c5dd70a440b903",
"other": ""
},
"encryption": "None",
"version": "V1_0"
}`;

const messageSentByNode2MainDevice = `{
"body": {
"unencrypted": {
"message_data": {
"unencrypted": {
"message_raw_content": "hey!",
"message_content_schema": "TextContent"
}
},
"internal_metadata": {
"sender_subidentity": "main/device/main_device",
"recipient_subidentity": "",
"inbox": "inbox::@@node2.shinkai/main/device/main_device::@@node1.shinkai::false",
"signature": "",
"encryption": "None"
}
}
},
"external_metadata": {
"sender": "@@node2.shinkai",
"recipient": "@@node1.shinkai",
"scheduled_time": "2023-08-25T22:44:01.132Z",
"signature": "c6d0115c0878fbf2279f98aab67c0e9cb1af63825f49dca48d6e4420eba0ceb973e00488ba0905c9afd09254f0dac48c468fdcb1d6c5ab5ca4c5dd70a440b903",
"other": ""
},
"encryption": "None",
"version": "V1_0"
}`;

const myNodeSetup = {
myNodeIdentity: '@@node1.shinkai',
myProfile: 'main',
};
it('false when message was sent by agent', () => {
const message = JSON.parse(messageSentByNode1AgentGpt);
const isLocal = isLocalMessage(message, myNodeSetup.myNodeIdentity, myNodeSetup.myProfile);
expect(isLocal).toBe(false);
});

it('false when message was sent by a different node', () => {
const message = JSON.parse(messageSentByNode2MainDevice);
const isLocal = isLocalMessage(message, myNodeSetup.myNodeIdentity, myNodeSetup.myProfile);
expect(isLocal).toBe(false);
});

it('true when message was sent by same node', () => {
const message = JSON.parse(messageSentByNode1MainDevice);
const isLocal = isLocalMessage(message, myNodeSetup.myNodeIdentity, myNodeSetup.myProfile);
expect(isLocal).toBe(true);
});

it('true when message was sent by same node but different device', () => {
const message = JSON.parse(messageSentByNode1SecondaryDevice);
const isLocal = isLocalMessage(message, myNodeSetup.myNodeIdentity, myNodeSetup.myProfile);
expect(isLocal).toBe(true);
});
});
11 changes: 7 additions & 4 deletions libs/shinkai-message-ts/src/utils/shinkai_message_handler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MessageSchemaType } from '../models/SchemaTypes';
import { ShinkaiMessage } from '../models/ShinkaiMessage';
import { ShinkaiNameWrapper } from '../wasm';
import { ShinkaiMessageWrapper } from '../wasm/ShinkaiMessageWrapper';

export function calculateMessageHash(message: ShinkaiMessage): string {
Expand Down Expand Up @@ -51,8 +52,10 @@ export const getMessageContent = (message: ShinkaiMessage) => {

export const isLocalMessage = (
message: ShinkaiMessage,
identity: string,
profile: string,
) => {
return message.external_metadata?.sender === `${identity}/${profile}`;
myNodeIdentity: string,
myProfile: string,
): boolean => {
const messageNameWrapper = ShinkaiNameWrapper.from_shinkai_message_sender(message);
return (messageNameWrapper.get_subidentity_type === 'None' || messageNameWrapper.get_subidentity_type === 'device') &&
messageNameWrapper.get_node_name === myNodeIdentity && messageNameWrapper.get_profile_name === myProfile;
};
3 changes: 1 addition & 2 deletions libs/shinkai-message-ts/src/utils/wasm_helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { sha512 } from '@noble/hashes/sha512';
import { Crypto } from "@peculiar/webcrypto";

import { generateEncryptionKeys, generateSignatureKeys, test_util_generateKeys } from './wasm_helpers';
console.log('PATATATATATATA2');
console.log('PATATATATATATA');console.log('PATATATATATATA');console.log('PATATATATATATA');console.log('PATATATATATATA');console.log('PATATATATATATA');console.log('PATATATATATATA');

// Enable synchronous methods
ed.etc.sha512Sync = (...m) => sha512(ed.etc.concatBytes(...m));

Expand Down
60 changes: 60 additions & 0 deletions libs/shinkai-message-ts/src/wasm/ShinkaiNameWrapper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,63 @@ test("ShinkaiNameWrapper get_profile_name", () => {
expect(wrapper.extract_profile().get_full_name).toBe(profile.toLowerCase());
}
});

test("ShinkaiNameWrapper from_shinkai_message_sender", () => {
it('should fail when message is first level encrypted', () => {
const encryptedMessage = `{
"body": {
"encrypted": {
"content": "encrypted:de9a22018a78cb1977d72936145576a4e040a590c5da6ac9f60f334c5fddd773b53ca11c5a97110e4352a694fa55632e9e07346e60a579171aea11fcf17a8e9666fe8f3bfddadafe5b2ecef5b8d7759979536e8ae848c1976a5057892836d0a5806fdaf4a30220217da2f4930914aea7b1f0f4ae65175ca9d24db4408294ca4b7347048a295ef5eeac1f3a60112953edf3f78bd02103fc9ae866cbb223385781218f0c021e41c79f529b7fd8748d8339db1cc0e03ae7d3b27b6147639cc01f44e594401bea76743ddefff47e737df61710c30fc7e5f38da306336cf668c198dfa2f90506"
}
},
"external_metadata": {
"sender": "@@node1.shinkai/main",
"recipient": "@@node1.shinkai",
"scheduled_time": "2023-10-04T19:38:50.271Z",
"signature": "028810426c653e993deea94aa08b8fec14e82040ba73b09e533726eb769ea5de87ba095cc83cfe35035ca2db1ce996c963b7e7b12b1a28240706e4e0cbef6904",
"other": ""
},
"encryption": "DiffieHellmanChaChaPoly1305",
"version": "V1_0"
}`;
const message = JSON.parse(encryptedMessage);
expect(ShinkaiNameWrapper.from_shinkai_message_sender(message)).toThrowError();
});

it('should parse node_name, full_name, subidentity_name and subidentity_type when message is unepcrypted', () => {
const messageJson = `{
"body": {
"unencrypted": {
"message_data": {
"unencrypted": {
"message_raw_content": "hey!",
"message_content_schema": "TextContent"
}
},
"internal_metadata": {
"sender_subidentity": "main/device/main_device",
"recipient_subidentity": "",
"inbox": "inbox::@@node1.shinkai/main/device/main_device::@@node2.shinkai::false",
"signature": "",
"encryption": "None"
}
}
},
"external_metadata": {
"sender": "@@node1.shinkai",
"recipient": "@@node2.shinkai",
"scheduled_time": "2023-08-25T22:44:01.132Z",
"signature": "c6d0115c0878fbf2279f98aab67c0e9cb1af63825f49dca48d6e4420eba0ceb973e00488ba0905c9afd09254f0dac48c468fdcb1d6c5ab5ca4c5dd70a440b903",
"other": ""
},
"encryption": "None",
"version": "V1_0"
}`;
const message = JSON.parse(messageJson);
const messageNameWrapper = ShinkaiNameWrapper.from_shinkai_message_sender(message);
expect(messageNameWrapper.get_node_name).toBe('@@node1.shinkai');
expect(messageNameWrapper.get_full_name).toBe('@@node1.shinkai/main/device/main_device');
expect(messageNameWrapper.get_subidentity_name).toBe('main/device/main_device');
expect(messageNameWrapper.get_subidentity_type).toBe('device');
});
});
15 changes: 15 additions & 0 deletions libs/shinkai-message-ts/src/wasm/ShinkaiNameWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ShinkaiMessage } from "../models";
import { ShinkaiNameWrapper as ShinkaiNameWrapperWASM } from "../pkg/shinkai_message_wasm";

export class ShinkaiNameWrapper {
Expand All @@ -7,6 +8,20 @@ export class ShinkaiNameWrapper {
this.wasmWrapper = new ShinkaiNameWrapperWASM(shinkai_name_js);
}

static from_shinkai_message_sender(message: ShinkaiMessage): ShinkaiNameWrapper {
if (message.encryption !== 'None') {
throw new Error('shinkai message is encrypted');
}
if (!message.body || !('unencrypted' in message.body)) {
throw new Error('shinkai message body doesn\'t conestains unencrypted property');
}
let name = message.external_metadata?.sender;
if (message.body.unencrypted.internal_metadata.sender_subidentity) {
name += `/${message.body.unencrypted.internal_metadata.sender_subidentity}`;
}
return new ShinkaiNameWrapper(name);
}

to_jsvalue(): any {
return this.wasmWrapper.to_jsvalue();
}
Expand Down
Loading

0 comments on commit b670f11

Please sign in to comment.