feat: add unit tests and redis caching for testing layer

old-agentic-v1^2
Travis Fischer 2023-05-31 23:03:27 -07:00
rodzic 02bf952659
commit b8db8d0a8a
8 zmienionych plików z 321 dodań i 13 usunięć

Wyświetl plik

@ -48,4 +48,6 @@ jobs:
run: pnpm install --frozen-lockfile
- name: Run test
env:
REDIS_URL_TEST: ${{ secrets.REDIS_URL_TEST }}
run: pnpm run test

Wyświetl plik

@ -32,6 +32,7 @@
"prepare": "husky install",
"pre-commit": "lint-staged",
"test": "run-p test:*",
"test:unit": "ava",
"test:prettier": "prettier '**/*.{js,jsx,ts,tsx}' --check"
},
"dependencies": {
@ -48,16 +49,23 @@
"zod-validation-error": "^1.3.0"
},
"devDependencies": {
"@keyv/redis": "^2.5.8",
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
"@types/node": "^20.2.5",
"@types/sinon": "^10.0.15",
"ava": "^5.3.0",
"del-cli": "^5.0.0",
"dotenv": "^16.1.3",
"expect-type": "^0.16.0",
"hash-obj": "^4.0.0",
"husky": "^8.0.3",
"ioredis": "^5.3.2",
"keyv": "^4.5.2",
"lint-staged": "^13.2.2",
"npm-run-all": "^4.1.5",
"p-memoize": "^7.1.1",
"prettier": "^2.8.8",
"sinon": "^15.1.0",
"tsup": "^6.7.0",
"tsx": "^3.12.7",
"type-fest": "^3.11.1",
@ -69,6 +77,7 @@
]
},
"ava": {
"snapshotDir": ".snapshots",
"extensions": {
"ts": "module"
},
@ -78,13 +87,14 @@
},
"keywords": [
"ai",
"openai",
"autonomous",
"agent",
"autogpt",
"agi",
"autogpt",
"babyagi",
"llms",
"chatgpt",
"openai",
"openapi",
"guardrails",
"plugins"

Wyświetl plik

@ -36,12 +36,18 @@ dependencies:
version: 1.3.0(zod@3.21.4)
devDependencies:
'@keyv/redis':
specifier: ^2.5.8
version: 2.5.8
'@trivago/prettier-plugin-sort-imports':
specifier: ^4.1.1
version: 4.1.1(prettier@2.8.8)
'@types/node':
specifier: ^20.2.5
version: 20.2.5
'@types/sinon':
specifier: ^10.0.15
version: 10.0.15
ava:
specifier: ^5.3.0
version: 5.3.0
@ -54,18 +60,33 @@ devDependencies:
expect-type:
specifier: ^0.16.0
version: 0.16.0
hash-obj:
specifier: ^4.0.0
version: 4.0.0
husky:
specifier: ^8.0.3
version: 8.0.3
ioredis:
specifier: ^5.3.2
version: 5.3.2
keyv:
specifier: ^4.5.2
version: 4.5.2
lint-staged:
specifier: ^13.2.2
version: 13.2.2
npm-run-all:
specifier: ^4.1.5
version: 4.1.5
p-memoize:
specifier: ^7.1.1
version: 7.1.1
prettier:
specifier: ^2.8.8
version: 2.8.8
sinon:
specifier: ^15.1.0
version: 15.1.0
tsup:
specifier: ^6.7.0
version: 6.7.0(typescript@5.0.4)
@ -414,6 +435,10 @@ packages:
dev: true
optional: true
/@ioredis/commands@1.2.0:
resolution: {integrity: sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==}
dev: true
/@jridgewell/gen-mapping@0.3.3:
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
engines: {node: '>=6.0.0'}
@ -448,6 +473,15 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@keyv/redis@2.5.8:
resolution: {integrity: sha512-WweuUZqZN2ETcseV6r1AEum1qG6eR5poNhkZ4CIpWBOjMasT2ArTKWyIPxxYllKUS2A8wKv1l8+AqH6Jpzk7Ug==}
engines: {node: '>= 12'}
dependencies:
ioredis: 5.3.2
transitivePeerDependencies:
- supports-color
dev: true
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@ -469,6 +503,36 @@ packages:
fastq: 1.15.0
dev: true
/@sinonjs/commons@2.0.0:
resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==}
dependencies:
type-detect: 4.0.8
dev: true
/@sinonjs/commons@3.0.0:
resolution: {integrity: sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==}
dependencies:
type-detect: 4.0.8
dev: true
/@sinonjs/fake-timers@10.2.0:
resolution: {integrity: sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==}
dependencies:
'@sinonjs/commons': 3.0.0
dev: true
/@sinonjs/samsam@8.0.0:
resolution: {integrity: sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==}
dependencies:
'@sinonjs/commons': 2.0.0
lodash.get: 4.4.2
type-detect: 4.0.8
dev: true
/@sinonjs/text-encoding@0.7.2:
resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==}
dev: true
/@trivago/prettier-plugin-sort-imports@4.1.1(prettier@2.8.8):
resolution: {integrity: sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw==}
peerDependencies:
@ -501,6 +565,16 @@ packages:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
dev: true
/@types/sinon@10.0.15:
resolution: {integrity: sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==}
dependencies:
'@types/sinonjs__fake-timers': 8.1.2
dev: true
/@types/sinonjs__fake-timers@8.1.2:
resolution: {integrity: sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==}
dev: true
/acorn-walk@8.2.0:
resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==}
engines: {node: '>=0.4.0'}
@ -856,6 +930,11 @@ packages:
wrap-ansi: 7.0.0
dev: true
/cluster-key-slot@1.1.2:
resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==}
engines: {node: '>=0.10.0'}
dev: true
/code-excerpt@4.0.0:
resolution: {integrity: sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -1020,6 +1099,16 @@ packages:
slash: 4.0.0
dev: true
/denque@2.1.0:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'}
dev: true
/diff@5.1.0:
resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==}
engines: {node: '>=0.3.1'}
dev: true
/dir-glob@3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
@ -1429,6 +1518,11 @@ packages:
engines: {node: '>=4'}
dev: true
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: true
/has-property-descriptors@1.0.0:
resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==}
dependencies:
@ -1459,6 +1553,15 @@ packages:
function-bind: 1.1.1
dev: true
/hash-obj@4.0.0:
resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==}
engines: {node: '>=12'}
dependencies:
is-obj: 3.0.0
sort-keys: 5.0.0
type-fest: 1.4.0
dev: true
/hosted-git-info@2.8.9:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
dev: true
@ -1531,6 +1634,23 @@ packages:
side-channel: 1.0.4
dev: true
/ioredis@5.3.2:
resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==}
engines: {node: '>=12.22.0'}
dependencies:
'@ioredis/commands': 1.2.0
cluster-key-slot: 1.1.2
debug: 4.3.4
denque: 2.1.0
lodash.defaults: 4.2.0
lodash.isarguments: 3.1.0
redis-errors: 1.2.0
redis-parser: 3.0.0
standard-as-callback: 2.1.0
transitivePeerDependencies:
- supports-color
dev: true
/irregular-plurals@3.5.0:
resolution: {integrity: sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==}
engines: {node: '>=8'}
@ -1630,6 +1750,11 @@ packages:
engines: {node: '>=0.12.0'}
dev: true
/is-obj@3.0.0:
resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==}
engines: {node: '>=12'}
dev: true
/is-path-cwd@3.0.0:
resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -1645,6 +1770,11 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/is-plain-obj@4.1.0:
resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
engines: {node: '>=12'}
dev: true
/is-plain-object@5.0.0:
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
engines: {node: '>=0.10.0'}
@ -1714,6 +1844,10 @@ packages:
call-bind: 1.0.2
dev: true
/isarray@0.0.1:
resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==}
dev: true
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
@ -1756,6 +1890,10 @@ packages:
hasBin: true
dev: true
/json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
dev: true
/json-parse-better-errors@1.0.2:
resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
dev: true
@ -1769,6 +1907,16 @@ packages:
hasBin: true
dev: false
/just-extend@4.2.1:
resolution: {integrity: sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==}
dev: true
/keyv@4.5.2:
resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==}
dependencies:
json-buffer: 3.0.1
dev: true
/kind-of@6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
@ -1864,6 +2012,18 @@ packages:
p-locate: 6.0.0
dev: true
/lodash.defaults@4.2.0:
resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
dev: true
/lodash.get@4.4.2:
resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
dev: true
/lodash.isarguments@3.1.0:
resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==}
dev: true
/lodash.sortby@4.7.0:
resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==}
dev: true
@ -2026,6 +2186,16 @@ packages:
resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==}
dev: true
/nise@5.1.4:
resolution: {integrity: sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==}
dependencies:
'@sinonjs/commons': 2.0.0
'@sinonjs/fake-timers': 10.2.0
'@sinonjs/text-encoding': 0.7.2
just-extend: 4.2.1
path-to-regexp: 1.8.0
dev: true
/nofilter@3.1.0:
resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==}
engines: {node: '>=12.19'}
@ -2195,6 +2365,14 @@ packages:
engines: {node: '>=16'}
dev: false
/p-memoize@7.1.1:
resolution: {integrity: sha512-DZ/bONJILHkQ721hSr/E9wMz5Am/OTJ9P6LhLFo2Tu+jL8044tgc9LwHO8g4PiaYePnlVVRAJcKmgy8J9MVFrA==}
engines: {node: '>=14.16'}
dependencies:
mimic-fn: 4.0.0
type-fest: 3.11.1
dev: true
/p-timeout@5.1.0:
resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==}
engines: {node: '>=12'}
@ -2257,6 +2435,12 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/path-to-regexp@1.8.0:
resolution: {integrity: sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==}
dependencies:
isarray: 0.0.1
dev: true
/path-type@3.0.0:
resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
engines: {node: '>=4'}
@ -2402,6 +2586,18 @@ packages:
strip-indent: 4.0.0
dev: true
/redis-errors@1.2.0:
resolution: {integrity: sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==}
engines: {node: '>=4'}
dev: true
/redis-parser@3.0.0:
resolution: {integrity: sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==}
engines: {node: '>=4'}
dependencies:
redis-errors: 1.2.0
dev: true
/regexp.prototype.flags@1.5.0:
resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==}
engines: {node: '>= 0.4'}
@ -2554,6 +2750,17 @@ packages:
engines: {node: '>=14'}
dev: true
/sinon@15.1.0:
resolution: {integrity: sha512-cS5FgpDdE9/zx7no8bxROHymSlPLZzq0ChbbLk1DrxBfc+eTeBK3y8nIL+nu/0QeYydhhbLIr7ecHJpywjQaoQ==}
dependencies:
'@sinonjs/commons': 3.0.0
'@sinonjs/fake-timers': 10.2.0
'@sinonjs/samsam': 8.0.0
diff: 5.1.0
nise: 5.1.4
supports-color: 7.2.0
dev: true
/slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@ -2590,6 +2797,13 @@ packages:
is-fullwidth-code-point: 4.0.0
dev: true
/sort-keys@5.0.0:
resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==}
engines: {node: '>=12'}
dependencies:
is-plain-obj: 4.1.0
dev: true
/source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
dependencies:
@ -2646,6 +2860,10 @@ packages:
escape-string-regexp: 2.0.0
dev: true
/standard-as-callback@2.1.0:
resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==}
dev: true
/string-argv@0.3.2:
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
engines: {node: '>=0.6.19'}
@ -2770,6 +2988,13 @@ packages:
has-flag: 3.0.0
dev: true
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
dev: true
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@ -2890,6 +3115,11 @@ packages:
fsevents: 2.3.2
dev: true
/type-detect@4.0.8:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
dev: true
/type-fest@0.13.1:
resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
engines: {node: '>=10'}

Wyświetl plik

@ -1,4 +1,4 @@
import { type SetRequired } from 'type-fest'
import { type SetOptional } from 'type-fest'
import { ZodTypeAny, z } from 'zod'
import * as types from './types'
@ -11,7 +11,7 @@ export class OpenAIChatModelBuilder<
> extends BaseChatModelBuilder<
TInput,
TOutput,
SetRequired<Omit<types.openai.ChatCompletionParams, 'messages'>, 'model'>,
SetOptional<Omit<types.openai.ChatCompletionParams, 'messages'>, 'model'>,
types.openai.ChatCompletionResponse
> {
_client: types.openai.OpenAIClient
@ -21,12 +21,12 @@ export class OpenAIChatModelBuilder<
options: types.ChatModelOptions<
TInput,
TOutput,
Omit<types.openai.ChatCompletionParams, 'messages'>
SetOptional<Omit<types.openai.ChatCompletionParams, 'messages'>, 'model'>
>
) {
super({
provider: 'openai',
model: defaultOpenAIModel,
model: options.modelParams?.model || defaultOpenAIModel,
...options
})

Wyświetl plik

@ -1,4 +1,3 @@
import { type SetRequired } from 'type-fest'
import { ZodRawShape, ZodTypeAny, z } from 'zod'
import * as types from './types'
@ -9,7 +8,7 @@ import * as types from './types'
* Examples of tasks include:
* - LLM calls with structured input and output
* - API calls
* - Native function execution
* - Native function calls
* - Invoking sub-agents
*/
export abstract class BaseTaskCallBuilder<
@ -19,7 +18,7 @@ export abstract class BaseTaskCallBuilder<
protected _timeoutMs: number | undefined
protected _retryConfig: types.RetryConfig | undefined
constructor(options: types.BaseTaskOptions) {
constructor(options: types.BaseTaskOptions = {}) {
this._timeoutMs = options.timeoutMs
this._retryConfig = options.retryConfig
}

1
test/_preload.ts 100644
Wyświetl plik

@ -0,0 +1 @@
import 'dotenv/config'

61
test/_utils.ts 100644
Wyświetl plik

@ -0,0 +1,61 @@
import KeyvRedis from '@keyv/redis'
import 'dotenv/config'
import hashObject from 'hash-obj'
import Redis from 'ioredis'
import Keyv from 'keyv'
import { OpenAIClient } from 'openai-fetch'
import pMemoize from 'p-memoize'
export const fakeOpenAIAPIKey = 'fake-openai-api-key'
export const env = process.env.NODE_ENV || 'development'
export const isTest = env === 'test'
export const isCI = process.env.CI === 'true'
export const refreshTestCache = process.env.REFRESH_TEST_CACHE === 'true'
if (isCI && refreshTestCache) {
throw new Error('REFRESH_TEST_CACHE must be disabled in CI')
}
const redis = new Redis(process.env.REDIS_URL_TEST!)
const keyvRedis = new KeyvRedis(redis)
const keyv = new Keyv({ store: keyvRedis, namespace: 'agentic-test' })
// TODO: this is pretty hacky
const keyvHas = (keyv.has as any).bind(keyv)
keyv.has = async (key, ...rest) => {
if (refreshTestCache) {
return undefined
}
const res = await keyvHas(key, ...rest)
return res
}
export class OpenAITestClient extends OpenAIClient {
createChatCompletion = pMemoize(super.createChatCompletion, {
cacheKey: (params) => getCacheKey('openai:chat', params),
cache: keyv
})
}
export function getCacheKey(label: string, params: any): string {
const hash = hashObject(params, { algorithm: 'sha256' })
return `${label}:${hash}`
}
export function createOpenAITestClient() {
const apiKey = isCI
? fakeOpenAIAPIKey
: process.env.OPENAI_API_KEY ?? fakeOpenAIAPIKey
if (refreshTestCache) {
if (!process.env.OPENAI_API_KEY) {
throw new Error(
'Cannot refresh test cache without OPENAI_API_KEY environment variable.'
)
}
}
const client = new OpenAITestClient({ apiKey })
return client
}

Wyświetl plik

@ -1,14 +1,19 @@
import test from 'ava'
// import 'dotenv/config'
import { expectTypeOf } from 'expect-type'
import { OpenAIClient } from 'openai-fetch'
import { z } from 'zod'
import { OpenAIChatModelBuilder } from './openai'
const client = new OpenAIClient({ apiKey: process.env.OPENAI_API_KEY! })
import { OpenAIChatModelBuilder } from '../src/openai'
import { createOpenAITestClient } from './_utils'
test('OpenAIChatModel ⇒ json output', async (t) => {
t.timeout(2 * 60 * 1000)
const client = createOpenAITestClient()
const builder = new OpenAIChatModelBuilder(client, {
modelParams: {
temperature: 0.5
},
messages: [
{
role: 'user',