Compare commits
3 Commits
0aab9a838b
...
e33ea62e35
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e33ea62e35 | ||
|
|
96d95a50fc | ||
|
|
c1ce804d14 |
1
App.tsx
1
App.tsx
@@ -4,6 +4,7 @@
|
|||||||
* Main application component with authentication routing.
|
* Main application component with authentication routing.
|
||||||
* Shows loading screen while restoring auth state.
|
* Shows loading screen while restoring auth state.
|
||||||
*/
|
*/
|
||||||
|
import './src/polyfills';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Buffer } from 'buffer';
|
import { Buffer } from 'buffer';
|
||||||
|
|||||||
BIN
assets/images/icon.png
Normal file
BIN
assets/images/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 B |
@@ -6,8 +6,10 @@ const config = getDefaultConfig(__dirname);
|
|||||||
config.resolver.extraNodeModules = {
|
config.resolver.extraNodeModules = {
|
||||||
...config.resolver.extraNodeModules,
|
...config.resolver.extraNodeModules,
|
||||||
crypto: path.resolve(__dirname, 'src/utils/crypto_polyfill.ts'),
|
crypto: path.resolve(__dirname, 'src/utils/crypto_polyfill.ts'),
|
||||||
stream: require.resolve('readable-stream'), // Just in case
|
stream: require.resolve('readable-stream'),
|
||||||
vm: require.resolve('vm-browserify'),
|
vm: require.resolve('vm-browserify'),
|
||||||
|
async_hooks: path.resolve(__dirname, 'src/utils/async_hooks_mock.ts'),
|
||||||
|
'node:async_hooks': path.resolve(__dirname, 'src/utils/async_hooks_mock.ts'),
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
||||||
|
|||||||
389
package-lock.json
generated
389
package-lock.json
generated
@@ -10,6 +10,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/metro-runtime": "~4.0.1",
|
"@expo/metro-runtime": "~4.0.1",
|
||||||
"@expo/vector-icons": "~14.0.4",
|
"@expo/vector-icons": "~14.0.4",
|
||||||
|
"@langchain/core": "^1.1.18",
|
||||||
|
"@langchain/langgraph": "^1.1.3",
|
||||||
"@noble/ciphers": "^1.3.0",
|
"@noble/ciphers": "^1.3.0",
|
||||||
"@noble/hashes": "^1.8.0",
|
"@noble/hashes": "^1.8.0",
|
||||||
"@react-native-async-storage/async-storage": "^2.2.0",
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
||||||
@@ -2203,6 +2205,12 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@cfworker/json-schema": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@cfworker/json-schema/-/json-schema-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@egjs/hammerjs": {
|
"node_modules/@egjs/hammerjs": {
|
||||||
"version": "2.0.17",
|
"version": "2.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
||||||
@@ -3216,6 +3224,204 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@langchain/core": {
|
||||||
|
"version": "1.1.18",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@langchain/core/-/core-1.1.18.tgz",
|
||||||
|
"integrity": "sha512-vwzbtHUSZaJONBA1n9uQedZPfyFFZ6XzTggTpR28n8tiIg7e1NC/5dvGW/lGtR1Du1VwV9DvDHA5/bOrLe6cVg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@cfworker/json-schema": "^4.0.2",
|
||||||
|
"ansi-styles": "^5.0.0",
|
||||||
|
"camelcase": "6",
|
||||||
|
"decamelize": "1.2.0",
|
||||||
|
"js-tiktoken": "^1.0.12",
|
||||||
|
"langsmith": ">=0.4.0 <1.0.0",
|
||||||
|
"mustache": "^4.2.0",
|
||||||
|
"p-queue": "^6.6.2",
|
||||||
|
"uuid": "^10.0.0",
|
||||||
|
"zod": "^3.25.76 || ^4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/core/node_modules/ansi-styles": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/core/node_modules/camelcase": {
|
||||||
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/core/node_modules/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@langchain/langgraph/-/langgraph-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-o/cEWeocDDSpyBI2MfX07LkNG4LzdRKxwcgUcbR4PyRzhxxCkeIZRCCYkXVQoDbdKqAczJa0D7+yjU9rmA5iHQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@langchain/langgraph-checkpoint": "^1.0.0",
|
||||||
|
"@langchain/langgraph-sdk": "~1.5.5",
|
||||||
|
"@standard-schema/spec": "1.1.0",
|
||||||
|
"uuid": "^10.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@langchain/core": "^1.0.1",
|
||||||
|
"zod": "^3.25.32 || ^4.2.0",
|
||||||
|
"zod-to-json-schema": "^3.x"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"zod-to-json-schema": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-checkpoint": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-xrclBGvNCXDmi0Nz28t3vjpxSH6UYx6w5XAXSiiB1WEdc2xD2iY/a913I3x3a31XpInUW/GGfXXfePfaghV54A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": "^10.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@langchain/core": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-checkpoint/node_modules/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-sdk": {
|
||||||
|
"version": "1.5.5",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@langchain/langgraph-sdk/-/langgraph-sdk-1.5.5.tgz",
|
||||||
|
"integrity": "sha512-SyiAs6TVXPWlt/8cI9pj/43nbIvclY3ytKqUFbL5MplCUnItetEyqvH87EncxyVF5D7iJKRZRfSVYBMmOZbjbQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"p-queue": "^9.0.1",
|
||||||
|
"p-retry": "^7.1.1",
|
||||||
|
"uuid": "^13.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@langchain/core": "^1.1.15",
|
||||||
|
"react": "^18 || ^19",
|
||||||
|
"react-dom": "^18 || ^19"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@langchain/core": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-sdk/node_modules/eventemitter3": {
|
||||||
|
"version": "5.0.4",
|
||||||
|
"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz",
|
||||||
|
"integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-sdk/node_modules/p-queue": {
|
||||||
|
"version": "9.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-9.1.0.tgz",
|
||||||
|
"integrity": "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eventemitter3": "^5.0.1",
|
||||||
|
"p-timeout": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-sdk/node_modules/p-timeout": {
|
||||||
|
"version": "7.0.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-7.0.1.tgz",
|
||||||
|
"integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph-sdk/node_modules/uuid": {
|
||||||
|
"version": "13.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-13.0.0.tgz",
|
||||||
|
"integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist-node/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@langchain/langgraph/node_modules/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@noble/ciphers": {
|
"node_modules/@noble/ciphers": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@noble/ciphers/-/ciphers-1.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@noble/ciphers/-/ciphers-1.3.0.tgz",
|
||||||
@@ -3818,6 +4024,12 @@
|
|||||||
"@sinonjs/commons": "^3.0.0"
|
"@sinonjs/commons": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@standard-schema/spec": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@standard-schema/spec/-/spec-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/babel__core": {
|
"node_modules/@types/babel__core": {
|
||||||
"version": "7.20.5",
|
"version": "7.20.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
|
||||||
@@ -3940,6 +4152,12 @@
|
|||||||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
|
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/@types/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/yargs": {
|
"node_modules/@types/yargs": {
|
||||||
"version": "17.0.35",
|
"version": "17.0.35",
|
||||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
|
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
|
||||||
@@ -5099,6 +5317,15 @@
|
|||||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/console-table-printer": {
|
||||||
|
"version": "2.15.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/console-table-printer/-/console-table-printer-2.15.0.tgz",
|
||||||
|
"integrity": "sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"simple-wcswidth": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/convert-source-map": {
|
"node_modules/convert-source-map": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||||
@@ -5238,6 +5465,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/decamelize": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/decode-uri-component": {
|
"node_modules/decode-uri-component": {
|
||||||
"version": "0.2.2",
|
"version": "0.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
|
||||||
@@ -5596,6 +5832,12 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/eventemitter3": {
|
||||||
|
"version": "4.0.7",
|
||||||
|
"resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||||
|
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/events": {
|
"node_modules/events": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
|
"resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz",
|
||||||
@@ -6813,6 +7055,18 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-network-error": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/is-network-error/-/is-network-error-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-number": {
|
"node_modules/is-number": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
@@ -7131,6 +7385,15 @@
|
|||||||
"integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==",
|
"integrity": "sha512-bF7vcQxbODoGK1imE2P9GS9aw4zD0Sd+Hni68IMZLj7zRnquH7dXUmMw9hDI5S/Jzt7q+IyTXN0rSg2GI0IKhQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/js-tiktoken": {
|
||||||
|
"version": "1.0.21",
|
||||||
|
"resolved": "https://registry.npmmirror.com/js-tiktoken/-/js-tiktoken-1.0.21.tgz",
|
||||||
|
"integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.5.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-tokens": {
|
"node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@@ -7251,6 +7514,65 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/langsmith": {
|
||||||
|
"version": "0.4.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/langsmith/-/langsmith-0.4.12.tgz",
|
||||||
|
"integrity": "sha512-YWt0jcGvKqjUgIvd78rd4QcdMss0lUkeUaqp0UpVRq7H2yNDx8H5jOUO/laWUmaPtWGgcip0qturykXe1g9Gqw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
|
"chalk": "^4.1.2",
|
||||||
|
"console-table-printer": "^2.12.1",
|
||||||
|
"p-queue": "^6.6.2",
|
||||||
|
"semver": "^7.6.3",
|
||||||
|
"uuid": "^10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@opentelemetry/api": "*",
|
||||||
|
"@opentelemetry/exporter-trace-otlp-proto": "*",
|
||||||
|
"@opentelemetry/sdk-trace-base": "*",
|
||||||
|
"openai": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@opentelemetry/api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@opentelemetry/exporter-trace-otlp-proto": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@opentelemetry/sdk-trace-base": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"openai": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/langsmith/node_modules/semver": {
|
||||||
|
"version": "7.7.3",
|
||||||
|
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.3.tgz",
|
||||||
|
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/langsmith/node_modules/uuid": {
|
||||||
|
"version": "10.0.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/uuid/-/uuid-10.0.0.tgz",
|
||||||
|
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/sponsors/broofa",
|
||||||
|
"https://github.com/sponsors/ctavan"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||||
@@ -8337,6 +8659,15 @@
|
|||||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/mustache": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/mustache/-/mustache-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"mustache": "bin/mustache"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mz": {
|
"node_modules/mz": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||||
@@ -8751,6 +9082,49 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/p-queue": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/p-queue/-/p-queue-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eventemitter3": "^4.0.4",
|
||||||
|
"p-timeout": "^3.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/p-retry": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmmirror.com/p-retry/-/p-retry-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-network-error": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/p-timeout": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmmirror.com/p-timeout/-/p-timeout-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"p-finally": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/p-try": {
|
"node_modules/p-try": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||||
@@ -10143,6 +10517,12 @@
|
|||||||
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
|
"integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/simple-wcswidth": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmmirror.com/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/sisteransi": {
|
"node_modules/sisteransi": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
|
||||||
@@ -11493,6 +11873,15 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/zod": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmmirror.com/zod/-/zod-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/metro-runtime": "~4.0.1",
|
"@expo/metro-runtime": "~4.0.1",
|
||||||
"@expo/vector-icons": "~14.0.4",
|
"@expo/vector-icons": "~14.0.4",
|
||||||
|
"@langchain/core": "^1.1.18",
|
||||||
|
"@langchain/langgraph": "^1.1.3",
|
||||||
"@noble/ciphers": "^1.3.0",
|
"@noble/ciphers": "^1.3.0",
|
||||||
"@noble/hashes": "^1.8.0",
|
"@noble/hashes": "^1.8.0",
|
||||||
"@react-native-async-storage/async-storage": "^2.2.0",
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
||||||
|
|||||||
45
src/polyfills.ts
Normal file
45
src/polyfills.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Polyfills that must run before any other app code (including LangChain/LangGraph).
|
||||||
|
* This file is imported as the very first line in App.tsx so that ReadableStream
|
||||||
|
* and crypto.getRandomValues exist before @langchain/core / uuid are loaded.
|
||||||
|
*/
|
||||||
|
import 'web-streams-polyfill';
|
||||||
|
|
||||||
|
// Ensure globalThis has ReadableStream (main polyfill may not patch in RN/Metro)
|
||||||
|
const g = typeof globalThis !== 'undefined' ? globalThis : (typeof global !== 'undefined' ? global : (typeof self !== 'undefined' ? self : {}));
|
||||||
|
if (typeof (g as any).ReadableStream === 'undefined') {
|
||||||
|
const ponyfill = require('web-streams-polyfill/dist/ponyfill.js');
|
||||||
|
(g as any).ReadableStream = ponyfill.ReadableStream;
|
||||||
|
(g as any).WritableStream = ponyfill.WritableStream;
|
||||||
|
(g as any).TransformStream = ponyfill.TransformStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polyfill crypto.getRandomValues for React Native/Expo (required by uuid, LangChain, etc.)
|
||||||
|
if (typeof g !== 'undefined') {
|
||||||
|
const cryptoObj = (g as any).crypto;
|
||||||
|
if (!cryptoObj || typeof (cryptoObj.getRandomValues) !== 'function') {
|
||||||
|
try {
|
||||||
|
const ExpoCrypto = require('expo-crypto');
|
||||||
|
const getRandomValues = (array: ArrayBufferView): ArrayBufferView => {
|
||||||
|
ExpoCrypto.getRandomValues(array);
|
||||||
|
return array;
|
||||||
|
};
|
||||||
|
if (!(g as any).crypto) (g as any).crypto = {};
|
||||||
|
(g as any).crypto.getRandomValues = getRandomValues;
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[polyfills] crypto.getRandomValues polyfill failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polyfill AbortSignal.prototype.throwIfAborted (required by fetch/LangChain in RN; not present in older runtimes)
|
||||||
|
const AbortSignalGlobal = (g as any).AbortSignal;
|
||||||
|
if (typeof AbortSignalGlobal === 'function' && AbortSignalGlobal.prototype && typeof AbortSignalGlobal.prototype.throwIfAborted !== 'function') {
|
||||||
|
AbortSignalGlobal.prototype.throwIfAborted = function (this: AbortSignal) {
|
||||||
|
if (this.aborted) {
|
||||||
|
const e = new Error('Aborted');
|
||||||
|
e.name = 'AbortError';
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -31,6 +31,8 @@ import * as ImagePicker from 'expo-image-picker';
|
|||||||
import { AIRole } from '../types';
|
import { AIRole } from '../types';
|
||||||
import { colors, typography, spacing, borderRadius, shadows } from '../theme/colors';
|
import { colors, typography, spacing, borderRadius, shadows } from '../theme/colors';
|
||||||
import { aiService, AIMessage } from '../services/ai.service';
|
import { aiService, AIMessage } from '../services/ai.service';
|
||||||
|
import { langGraphService } from '../services/langgraph.service';
|
||||||
|
import { HumanMessage, AIMessage as LangChainAIMessage, SystemMessage } from "@langchain/core/messages";
|
||||||
import { assetsService } from '../services/assets.service';
|
import { assetsService } from '../services/assets.service';
|
||||||
import { useAuth } from '../context/AuthContext';
|
import { useAuth } from '../context/AuthContext';
|
||||||
import { AI_CONFIG, getVaultStorageKeys } from '../config';
|
import { AI_CONFIG, getVaultStorageKeys } from '../config';
|
||||||
@@ -280,8 +282,23 @@ export default function FlowScreen() {
|
|||||||
setMessages(prev => [...prev, userMsg]);
|
setMessages(prev => [...prev, userMsg]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call AI proxy with selected role's system prompt
|
// 1. Convert current messages history to LangChain format
|
||||||
const aiResponse = await aiService.sendMessage(userMessage, token, selectedRole?.systemPrompt || '');
|
const history: (HumanMessage | LangChainAIMessage | SystemMessage)[] = messages.map(msg => {
|
||||||
|
if (msg.role === 'user') return new HumanMessage(msg.content);
|
||||||
|
return new LangChainAIMessage(msg.content);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. Add system prompt
|
||||||
|
const systemPrompt = new SystemMessage(selectedRole?.systemPrompt || '');
|
||||||
|
|
||||||
|
// 3. Add current new message
|
||||||
|
const currentMsg = new HumanMessage(userMessage);
|
||||||
|
|
||||||
|
// 4. Combine all messages for LangGraph processing
|
||||||
|
const fullMessages = [systemPrompt, ...history, currentMsg];
|
||||||
|
|
||||||
|
// 5. Execute via LangGraph service (handles token limits and context)
|
||||||
|
const aiResponse = await langGraphService.execute(fullMessages, token);
|
||||||
|
|
||||||
// Add AI response
|
// Add AI response
|
||||||
const aiMsg: ChatMessage = {
|
const aiMsg: ChatMessage = {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
logApiDebug,
|
logApiDebug,
|
||||||
} from '../config';
|
} from '../config';
|
||||||
import { AIRole } from '../types';
|
import { AIRole } from '../types';
|
||||||
|
import { trimInternalMessages } from '../utils/token_utils';
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Type Definitions
|
// Type Definitions
|
||||||
@@ -259,14 +260,17 @@ export const aiService = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const historicalMessages = messages.map(msg => ({
|
// Enforce token limit (10,000 tokens)
|
||||||
|
const trimmedMessages = trimInternalMessages(messages);
|
||||||
|
|
||||||
|
const historicalMessages = trimmedMessages.map(msg => ({
|
||||||
role: msg.role,
|
role: msg.role,
|
||||||
content: msg.content,
|
content: msg.content,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const summaryPrompt: AIMessage = {
|
const summaryPrompt: AIMessage = {
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: 'Please provide a concise summary of the conversation above in Chinese (since the user request was in Chinese). Focus on the main topics discussed and any key conclusions or actions mentioned.',
|
content: 'Please provide a concise summary of the conversation above in English. Focus on the main topics discussed and any key conclusions or actions mentioned.',
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await this.chat([...historicalMessages, summaryPrompt], token);
|
const response = await this.chat([...historicalMessages, summaryPrompt], token);
|
||||||
|
|||||||
96
src/services/langgraph.service.ts
Normal file
96
src/services/langgraph.service.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* LangGraph Service
|
||||||
|
*
|
||||||
|
* Implements AI chat logic using LangGraph.js for state management
|
||||||
|
* and context handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { StateGraph, START, END, Annotation } from "@langchain/langgraph";
|
||||||
|
import { BaseMessage, HumanMessage, AIMessage, SystemMessage } from "@langchain/core/messages";
|
||||||
|
import { aiService } from "./ai.service";
|
||||||
|
import { trimLangChainMessages } from "../utils/token_utils";
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Settings
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the State using Annotation (Standard for latest LangGraph.js)
|
||||||
|
*/
|
||||||
|
const GraphAnnotation = Annotation.Root({
|
||||||
|
messages: Annotation<BaseMessage[]>({
|
||||||
|
reducer: (x, y) => x.concat(y),
|
||||||
|
default: () => [],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Graph Definition
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main node that calls our existing AI API
|
||||||
|
*/
|
||||||
|
async function callModel(state: typeof GraphAnnotation.State, config: any) {
|
||||||
|
const { messages } = state;
|
||||||
|
const { token } = config.configurable || {};
|
||||||
|
|
||||||
|
// 1. Trim messages to stay under token limit
|
||||||
|
const trimmedMessages = trimLangChainMessages(messages);
|
||||||
|
|
||||||
|
// 2. Convert LangChain messages to our internal AIMessage format for the API
|
||||||
|
const apiMessages = trimmedMessages.map(m => {
|
||||||
|
let role: 'system' | 'user' | 'assistant' = 'user';
|
||||||
|
const type = (m as any)._getType?.() || (m instanceof SystemMessage ? 'system' : m instanceof HumanMessage ? 'human' : m instanceof AIMessage ? 'ai' : 'user');
|
||||||
|
|
||||||
|
if (type === 'system') role = 'system';
|
||||||
|
else if (type === 'human') role = 'user';
|
||||||
|
else if (type === 'ai') role = 'assistant';
|
||||||
|
|
||||||
|
return {
|
||||||
|
role,
|
||||||
|
content: m.content.toString()
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Call the proxy service
|
||||||
|
const response = await aiService.chat(apiMessages, token);
|
||||||
|
const content = response.choices[0]?.message?.content || "No response generated";
|
||||||
|
|
||||||
|
// 4. Return the new message to satisfy the Graph (it will be appended due to reducer)
|
||||||
|
return {
|
||||||
|
messages: [new AIMessage(content)]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Service Export
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
export const langGraphService = {
|
||||||
|
/**
|
||||||
|
* Run the chat graph with history
|
||||||
|
*/
|
||||||
|
async execute(
|
||||||
|
currentMessages: BaseMessage[],
|
||||||
|
userToken: string,
|
||||||
|
): Promise<string> {
|
||||||
|
// Define the graph
|
||||||
|
const workflow = new StateGraph(GraphAnnotation)
|
||||||
|
.addNode("agent", callModel)
|
||||||
|
.addEdge(START, "agent")
|
||||||
|
.addEdge("agent", END);
|
||||||
|
|
||||||
|
const app = workflow.compile();
|
||||||
|
|
||||||
|
// Execute the graph
|
||||||
|
const result = await app.invoke(
|
||||||
|
{ messages: currentMessages },
|
||||||
|
{ configurable: { token: userToken } }
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return the content of the last message (the AI response)
|
||||||
|
const lastMsg = result.messages[result.messages.length - 1];
|
||||||
|
return lastMsg.content.toString();
|
||||||
|
}
|
||||||
|
};
|
||||||
22
src/utils/async_hooks_mock.ts
Normal file
22
src/utils/async_hooks_mock.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Mock for Node.js async_hooks
|
||||||
|
* Used to fix LangGraph.js compatibility with React Native
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class AsyncLocalStorage {
|
||||||
|
disable() { }
|
||||||
|
getStore() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
run(store: any, callback: (...args: any[]) => any, ...args: any[]) {
|
||||||
|
return callback(...args);
|
||||||
|
}
|
||||||
|
exit(callback: (...args: any[]) => any, ...args: any[]) {
|
||||||
|
return callback(...args);
|
||||||
|
}
|
||||||
|
enterWith(store: any) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
AsyncLocalStorage,
|
||||||
|
};
|
||||||
76
src/utils/token_utils.ts
Normal file
76
src/utils/token_utils.ts
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* Token Utilities
|
||||||
|
*
|
||||||
|
* Shared logic for trimming messages to stay within token limits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BaseMessage, SystemMessage } from "@langchain/core/messages";
|
||||||
|
import { AIMessage as ServiceAIMessage } from "../services/ai.service";
|
||||||
|
|
||||||
|
export const TOKEN_LIMIT = 10000;
|
||||||
|
const CHARS_PER_TOKEN = 3; // Conservative estimate: 1 token ≈ 3 chars
|
||||||
|
export const MAX_CHARS = TOKEN_LIMIT * CHARS_PER_TOKEN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trims LangChain messages to fit within token limit
|
||||||
|
*/
|
||||||
|
export function trimLangChainMessages(messages: BaseMessage[]): BaseMessage[] {
|
||||||
|
let totalLength = 0;
|
||||||
|
const trimmed: BaseMessage[] = [];
|
||||||
|
|
||||||
|
// Always keep the system message if it's at the start
|
||||||
|
let systemMsg: BaseMessage | null = null;
|
||||||
|
if (messages.length > 0 && (messages[0] instanceof SystemMessage || (messages[0] as any)._getType?.() === 'system')) {
|
||||||
|
systemMsg = messages[0];
|
||||||
|
totalLength += systemMsg.content.toString().length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate backwards and add messages until we hit the char limit
|
||||||
|
for (let i = messages.length - 1; i >= (systemMsg ? 1 : 0); i--) {
|
||||||
|
const msg = messages[i];
|
||||||
|
const len = msg.content.toString().length;
|
||||||
|
|
||||||
|
if (totalLength + len > MAX_CHARS) break;
|
||||||
|
|
||||||
|
trimmed.unshift(msg);
|
||||||
|
totalLength += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemMsg) {
|
||||||
|
trimmed.unshift(systemMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trims internal AIMessage format messages to fit within token limit
|
||||||
|
*/
|
||||||
|
export function trimInternalMessages(messages: ServiceAIMessage[]): ServiceAIMessage[] {
|
||||||
|
let totalLength = 0;
|
||||||
|
const trimmed: ServiceAIMessage[] = [];
|
||||||
|
|
||||||
|
// Always keep the system message if it's at the start
|
||||||
|
let systemMsg: ServiceAIMessage | null = null;
|
||||||
|
if (messages.length > 0 && messages[0].role === 'system') {
|
||||||
|
systemMsg = messages[0];
|
||||||
|
totalLength += systemMsg.content.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate backwards and add messages until we hit the char limit
|
||||||
|
for (let i = messages.length - 1; i >= (systemMsg ? 1 : 0); i--) {
|
||||||
|
const msg = messages[i];
|
||||||
|
const len = msg.content.length;
|
||||||
|
|
||||||
|
if (totalLength + len > MAX_CHARS) break;
|
||||||
|
|
||||||
|
trimmed.unshift(msg);
|
||||||
|
totalLength += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemMsg) {
|
||||||
|
trimmed.unshift(systemMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trimmed;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user