Making completion utilities available in AI package (#39190)
Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
722922191e
commit
7cb5cfed69
|
@ -40,6 +40,7 @@ npm-debug.log
|
|||
build/
|
||||
build-module/
|
||||
build-style/
|
||||
build-style.js
|
||||
build-types/
|
||||
dist/
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ],
|
||||
root: true,
|
||||
overrides: [
|
||||
{
|
||||
files: [ '**/*.js', '**/*.jsx', '**/*.tsx' ],
|
||||
rules: {
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
package-lock=false
|
|
@ -0,0 +1,11 @@
|
|||
# Artificial Intelligence tools
|
||||
|
||||
A collection of WooCommerce tools and utilities to implement ai features.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the module
|
||||
|
||||
```bash
|
||||
pnpm install @woocommerce/ai --save
|
||||
```
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
extends: '../internal-js-tests/babel.config.js',
|
||||
};
|
|
@ -0,0 +1,3 @@
|
|||
# Changelog
|
||||
|
||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Moving text completion hooks into @woocommerce/ai package for reuse.
|
|
@ -0,0 +1,32 @@
|
|||
{
|
||||
"name": "woocommerce/ai",
|
||||
"description": "WooCommerce AI library",
|
||||
"type": "library",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"minimum-stability": "dev",
|
||||
"require-dev": {
|
||||
"automattic/jetpack-changelogger": "3.3.0"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"changelogger": {
|
||||
"formatter": {
|
||||
"filename": "../../../tools/changelogger/class-package-formatter.php"
|
||||
},
|
||||
"types": {
|
||||
"fix": "Fixes an existing bug",
|
||||
"add": "Adds functionality",
|
||||
"update": "Update existing functionality",
|
||||
"dev": "Development related task",
|
||||
"tweak": "A minor adjustment to the codebase",
|
||||
"performance": "Address performance issues",
|
||||
"enhancement": "Improve existing functionality"
|
||||
},
|
||||
"changelog": "CHANGELOG.md"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,483 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c8190a953aa0a440f30a24c71e0fef6d",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "automattic/jetpack-changelogger",
|
||||
"version": "v3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Automattic/jetpack-changelogger.git",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Automattic/jetpack-changelogger/zipball/8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"reference": "8f63c829b8d1b0d7b1d5de93510d78523ed18959",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"symfony/console": "^3.4 || ^5.2 || ^6.0",
|
||||
"symfony/process": "^3.4 || ^5.2 || ^6.0",
|
||||
"wikimedia/at-ease": "^1.2 || ^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"wikimedia/testing-access-wrapper": "^1.0 || ^2.0",
|
||||
"yoast/phpunit-polyfills": "1.0.4"
|
||||
},
|
||||
"bin": [
|
||||
"bin/changelogger"
|
||||
],
|
||||
"type": "project",
|
||||
"extra": {
|
||||
"autotagger": true,
|
||||
"branch-alias": {
|
||||
"dev-trunk": "3.3.x-dev"
|
||||
},
|
||||
"mirror-repo": "Automattic/jetpack-changelogger",
|
||||
"version-constants": {
|
||||
"::VERSION": "src/Application.php"
|
||||
},
|
||||
"changelogger": {
|
||||
"link-template": "https://github.com/Automattic/jetpack-changelogger/compare/${old}...${new}"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Automattic\\Jetpack\\Changelog\\": "lib",
|
||||
"Automattic\\Jetpack\\Changelogger\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"description": "Jetpack Changelogger tool. Allows for managing changelogs by dropping change files into a changelog directory with each PR.",
|
||||
"support": {
|
||||
"source": "https://github.com/Automattic/jetpack-changelogger/tree/v3.3.0"
|
||||
},
|
||||
"time": "2022-12-26T13:49:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
"version": "1.1.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/log.git",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"reference": "d49695b909c3b7628b6289db5479a1c204601f11",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Log\\": "Psr/Log/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for logging libraries",
|
||||
"homepage": "https://github.com/php-fig/log",
|
||||
"keywords": [
|
||||
"log",
|
||||
"psr",
|
||||
"psr-3"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/log/tree/1.1.4"
|
||||
},
|
||||
"time": "2021-05-03T11:20:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8",
|
||||
"symfony/debug": "~2.8|~3.0|~4.0",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/dependency-injection": "<3.4",
|
||||
"symfony/process": "<3.3"
|
||||
},
|
||||
"provide": {
|
||||
"psr/log-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"psr/log": "~1.0",
|
||||
"symfony/config": "~3.3|~4.0",
|
||||
"symfony/dependency-injection": "~3.4|~4.0",
|
||||
"symfony/event-dispatcher": "~2.8|~3.0|~4.0",
|
||||
"symfony/lock": "~3.4|~4.0",
|
||||
"symfony/process": "~3.3|~4.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "For using the console logger",
|
||||
"symfony/event-dispatcher": "",
|
||||
"symfony/lock": "",
|
||||
"symfony/process": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Console\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/debug",
|
||||
"version": "4.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/debug.git",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/debug/zipball/1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"reference": "1a692492190773c5310bc7877cb590c04c2f05be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1.3",
|
||||
"psr/log": "^1|^2|^3"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/http-kernel": "<3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/http-kernel": "^3.4|^4.0|^5.0"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Debug\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Provides tools to ease debugging PHP code",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/debug/tree/v4.4.44"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"abandoned": "symfony/error-handler",
|
||||
"time": "2022-07-28T16:29:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "dev-main",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "f9c7affe77a00ae32ca127ca6833d034e6d33f25"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f9c7affe77a00ae32ca127ca6833d034e6d33f25",
|
||||
"reference": "f9c7affe77a00ae32ca127ca6833d034e6d33f25",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"provide": {
|
||||
"ext-mbstring": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "For best performance"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.28-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
"url": "https://github.com/symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Mbstring\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill for the Mbstring extension",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"mbstring",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-mbstring/tree/main"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-01-30T17:25:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "3.4.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.5.9|>=7.0.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Process\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "wikimedia/at-ease",
|
||||
"version": "v2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wikimedia/at-ease.git",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/wikimedia/at-ease/zipball/013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"reference": "013ac61929797839c80a111a3f1a4710d8248e7a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6.99"
|
||||
},
|
||||
"require-dev": {
|
||||
"jakub-onderka/php-console-highlighter": "0.3.2",
|
||||
"jakub-onderka/php-parallel-lint": "1.0.0",
|
||||
"mediawiki/mediawiki-codesniffer": "22.0.0",
|
||||
"mediawiki/minus-x": "0.3.1",
|
||||
"ockcyp/covers-validator": "0.5.1 || 0.6.1",
|
||||
"phpunit/phpunit": "4.8.36 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Wikimedia/Functions.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Wikimedia\\AtEase\\": "src/Wikimedia/AtEase/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-2.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tim Starling",
|
||||
"email": "tstarling@wikimedia.org"
|
||||
},
|
||||
{
|
||||
"name": "MediaWiki developers",
|
||||
"email": "wikitech-l@lists.wikimedia.org"
|
||||
}
|
||||
],
|
||||
"description": "Safe replacement to @ for suppressing warnings.",
|
||||
"homepage": "https://www.mediawiki.org/wiki/at-ease",
|
||||
"support": {
|
||||
"source": "https://github.com/wikimedia/at-ease/tree/master"
|
||||
},
|
||||
"time": "2018-10-10T15:39:06+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": [],
|
||||
"platform-dev": [],
|
||||
"platform-overrides": {
|
||||
"php": "7.2"
|
||||
},
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rootDir": "./src",
|
||||
"preset": "../node_modules/@woocommerce/internal-js-tests/jest-preset.js"
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"name": "@woocommerce/ai",
|
||||
"version": "0.1.0-beta.0",
|
||||
"description": "Utilities for usage in AI features across WooCommerce.",
|
||||
"author": "Automattic",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
"woocommerce"
|
||||
],
|
||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/packages/js/ai/README.md",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/woocommerce/woocommerce/issues"
|
||||
},
|
||||
"main": "build/index.js",
|
||||
"module": "build-module/index.js",
|
||||
"types": "build-types",
|
||||
"react-native": "src/index",
|
||||
"sideEffects": [
|
||||
"build-style/**",
|
||||
"src/**/*.scss"
|
||||
],
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@wordpress/api-fetch": "wp-6.0",
|
||||
"@wordpress/compose": "wp-6.0",
|
||||
"@wordpress/core-data": "wp-6.0",
|
||||
"@wordpress/element": "wp-6.0",
|
||||
"classnames": "^2.3.1",
|
||||
"debug": "^4.3.3",
|
||||
"dompurify": "^2.3.6",
|
||||
"prop-types": "^15.8.1",
|
||||
"react-router-dom": "^6.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@babel/runtime": "^7.17.2",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/dompurify": "^2.3.3",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/testing-library__jest-dom": "^5.14.3",
|
||||
"@types/wordpress__core-data": "^2.4.5",
|
||||
"@woocommerce/eslint-plugin": "workspace:*",
|
||||
"@woocommerce/internal-js-tests": "workspace:*",
|
||||
"@woocommerce/internal-style-build": "workspace:*",
|
||||
"@wordpress/browserslist-config": "wp-6.0",
|
||||
"concurrently": "^7.0.0",
|
||||
"copy-webpack-plugin": "^9.1.0",
|
||||
"css-loader": "^3.6.0",
|
||||
"eslint": "^8.32.0",
|
||||
"jest": "^27.5.1",
|
||||
"jest-cli": "^27.5.1",
|
||||
"postcss": "^8.4.7",
|
||||
"postcss-loader": "^4.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-hooks^8.0.1": "link:@testing-library/react-hooks^8.0.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass-loader": "^10.2.1",
|
||||
"ts-jest": "^27.1.3",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "^5.70.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
},
|
||||
"scripts": {
|
||||
"turbo:build": "pnpm run build:js && pnpm run build:css",
|
||||
"turbo:test": "jest --config ./jest.config.json",
|
||||
"prepare": "composer install",
|
||||
"changelog": "composer exec -- changelogger",
|
||||
"clean": "pnpm exec rimraf tsconfig.tsbuildinfo build build-*",
|
||||
"build": "pnpm -w exec turbo run turbo:build --filter=$npm_package_name",
|
||||
"test": "pnpm -w exec turbo run turbo:test --filter=$npm_package_name",
|
||||
"lint": "eslint src",
|
||||
"build:js": "tsc --project tsconfig.json && tsc --project tsconfig-cjs.json",
|
||||
"build:css": "webpack",
|
||||
"start": "concurrently \"tsc --project tsconfig.json --watch\" \"tsc --project tsconfig-cjs.json --watch\" \"webpack --watch\"",
|
||||
"prepack": "pnpm run clean && pnpm run build",
|
||||
"lint:fix": "eslint src --fix"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.2",
|
||||
"@wordpress/data": "wp-6.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './useCompletion';
|
|
@ -6,23 +6,27 @@ import { useRef, useState } from '@wordpress/element';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCompletion } from '../utils';
|
||||
import { getCompletion, createExtendedError } from '../utils/';
|
||||
|
||||
type StopReason = 'abort' | 'finished' | 'error' | 'interrupted';
|
||||
|
||||
export type UseCompletionError = Error & { code?: string; cause?: Error };
|
||||
|
||||
type UseCompletionProps = {
|
||||
onStreamMessage?: ( message: string, chunk: string ) => void;
|
||||
onCompletionFinished?: (
|
||||
reason: StopReason,
|
||||
previousContent: string
|
||||
) => void;
|
||||
onStreamError?: ( error: string ) => void;
|
||||
onStreamError?: ( error: UseCompletionError ) => void;
|
||||
feature?: string;
|
||||
};
|
||||
|
||||
export const useCompletion = ( {
|
||||
onStreamMessage = () => {},
|
||||
onCompletionFinished = () => {},
|
||||
onStreamError = () => {},
|
||||
feature,
|
||||
}: UseCompletionProps ) => {
|
||||
const completionSource = useRef< EventSource | null >( null );
|
||||
const previousContent = useRef< string >( '' );
|
||||
|
@ -51,47 +55,68 @@ export const useCompletion = ( {
|
|||
}
|
||||
};
|
||||
|
||||
const onCompletionError = ( error: string ) => {
|
||||
const onCompletionError = ( error: string | Error ) => {
|
||||
stopCompletion( 'error' );
|
||||
onStreamError( error );
|
||||
onStreamError( typeof error === 'object' ? error : new Error( error ) );
|
||||
};
|
||||
|
||||
const requestCompletion = async ( prompt: string ) => {
|
||||
const requestCompletion = async (
|
||||
prompt: string,
|
||||
featureOverride?: string
|
||||
) => {
|
||||
if (
|
||||
! window.JP_CONNECTION_INITIAL_STATE?.connectionStatus?.isActive
|
||||
) {
|
||||
throw createExtendedError(
|
||||
'You must be connected to Jetpack for text completion',
|
||||
'no_jetpack_connection'
|
||||
);
|
||||
}
|
||||
|
||||
const completionFeature = featureOverride ?? feature;
|
||||
if ( completionSource.current ) {
|
||||
stopCompletion( 'interrupted' );
|
||||
}
|
||||
previousContent.current = '';
|
||||
|
||||
let suggestionsSource;
|
||||
|
||||
try {
|
||||
suggestionsSource = await getCompletion( prompt );
|
||||
} catch ( e ) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug( 'Completion connection error encountered', e );
|
||||
onCompletionError( 'connection_error' );
|
||||
return;
|
||||
if ( typeof completionFeature !== 'string' ) {
|
||||
throw createExtendedError(
|
||||
'You must provide a feature when requesting a completion',
|
||||
'missing_feature'
|
||||
);
|
||||
}
|
||||
|
||||
setCompletionActive( true );
|
||||
try {
|
||||
const suggestionsSource = await getCompletion(
|
||||
prompt,
|
||||
completionFeature
|
||||
);
|
||||
|
||||
suggestionsSource.addEventListener( 'message', ( e ) => {
|
||||
onMessage( e );
|
||||
} );
|
||||
suggestionsSource.addEventListener(
|
||||
'error',
|
||||
( event: MessageEvent ) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug( 'Streaming error encountered', event );
|
||||
onCompletionError(
|
||||
typeof event === 'string' ? event : event.data
|
||||
);
|
||||
}
|
||||
);
|
||||
setCompletionActive( true );
|
||||
|
||||
completionSource.current = suggestionsSource;
|
||||
suggestionsSource.addEventListener( 'message', ( e ) => {
|
||||
onMessage( e );
|
||||
} );
|
||||
|
||||
return suggestionsSource;
|
||||
suggestionsSource.addEventListener(
|
||||
'error',
|
||||
( event: MessageEvent ) => {
|
||||
onCompletionError(
|
||||
typeof event === 'string' ? event : event.data
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
completionSource.current = suggestionsSource;
|
||||
|
||||
return suggestionsSource;
|
||||
} catch ( e ) {
|
||||
throw createExtendedError(
|
||||
'An error occurred while connecting to the completion service',
|
||||
'connection_error',
|
||||
e as Error
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* Hooks
|
||||
*/
|
||||
export {
|
||||
useCompletion as __experimentalUseCompletion,
|
||||
UseCompletionError,
|
||||
} from './hooks';
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
export {
|
||||
requestJetpackToken as __experimentalRequestJetpackToken,
|
||||
getCompletion as __experimentalgetCompletion,
|
||||
createExtendedError,
|
||||
} from './utils';
|
|
@ -0,0 +1,11 @@
|
|||
export type UseCompletionError = Error & { code?: string; cause?: Error };
|
||||
|
||||
export const createExtendedError = (
|
||||
msg: string,
|
||||
code?: string,
|
||||
cause?: Error
|
||||
) =>
|
||||
Object.assign( new Error( msg ), {
|
||||
code,
|
||||
cause,
|
||||
} );
|
|
@ -0,0 +1,2 @@
|
|||
export * from './text-completion';
|
||||
export * from './create-extended-error';
|
|
@ -7,7 +7,7 @@ import debugFactory from 'debug';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { WOO_AI_PLUGIN_FEATURE_NAME } from '../constants';
|
||||
import { createExtendedError } from './create-extended-error';
|
||||
|
||||
const debugToken = debugFactory( 'jetpack-ai-assistant:token' );
|
||||
|
||||
|
@ -19,6 +19,7 @@ declare global {
|
|||
JP_CONNECTION_INITIAL_STATE: {
|
||||
apiNonce: string;
|
||||
siteSuffix: string;
|
||||
connectionStatus: { isActive: boolean };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +38,10 @@ export async function requestJetpackToken() {
|
|||
tokenData = JSON.parse( token );
|
||||
} catch ( err ) {
|
||||
debugToken( 'Error parsing token', err );
|
||||
throw new Error( 'Error parsing cached token' );
|
||||
throw createExtendedError(
|
||||
'Error parsing cached token',
|
||||
'token_parse_error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,7 +68,7 @@ export async function requestJetpackToken() {
|
|||
blogId: siteSuffix,
|
||||
|
||||
/**
|
||||
* Let's expire the token in 5 minutes
|
||||
* Let's expire the token in 2 minutes
|
||||
*/
|
||||
expire: Date.now() + JWT_TOKEN_EXPIRATION_TIME,
|
||||
};
|
||||
|
@ -74,7 +78,10 @@ export async function requestJetpackToken() {
|
|||
|
||||
return newTokenData;
|
||||
} catch ( e ) {
|
||||
throw new Error( 'Error fetching new token' );
|
||||
throw createExtendedError(
|
||||
'Error fetching new token',
|
||||
'token_fetch_error'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,7 +90,7 @@ export async function requestJetpackToken() {
|
|||
*
|
||||
* @param {string} prompt - The query to send to the API
|
||||
*/
|
||||
export async function getCompletion( prompt: string ) {
|
||||
export async function getCompletion( prompt: string, feature: string ) {
|
||||
const { token } = await requestJetpackToken();
|
||||
|
||||
const url = new URL(
|
||||
|
@ -92,7 +99,7 @@ export async function getCompletion( prompt: string ) {
|
|||
|
||||
url.searchParams.append( 'prompt', prompt );
|
||||
url.searchParams.append( 'token', token );
|
||||
url.searchParams.append( 'feature', WOO_AI_PLUGIN_FEATURE_NAME );
|
||||
url.searchParams.append( 'feature', feature );
|
||||
|
||||
return new EventSource( url.toString() );
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../tsconfig-cjs",
|
||||
"include": [
|
||||
"**/*.d.ts",
|
||||
"src/**/*",
|
||||
"src/**/*.json"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "build",
|
||||
"resolveJsonModule": true,
|
||||
"typeRoots": [
|
||||
"./typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../tsconfig",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "build-module",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"declarationDir": "./build-types",
|
||||
"resolveJsonModule": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.d.ts",
|
||||
"src/**/*",
|
||||
"src/**/*.json"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const WebpackRTLPlugin = require( 'webpack-rtl-plugin' );
|
||||
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' );
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { webpackConfig } = require( '@woocommerce/internal-style-build' );
|
||||
|
||||
const NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
|
||||
module.exports = {
|
||||
mode: process.env.NODE_ENV || 'development',
|
||||
entry: {
|
||||
'build-style': __dirname + '/src/style.scss',
|
||||
},
|
||||
output: {
|
||||
path: __dirname,
|
||||
},
|
||||
module: {
|
||||
parser: webpackConfig.parser,
|
||||
rules: webpackConfig.rules,
|
||||
},
|
||||
plugins: [
|
||||
new MiniCssExtractPlugin( {
|
||||
filename: ( data ) => {
|
||||
return data.chunk.name.startsWith( '/build/blocks' )
|
||||
? `[name].css`
|
||||
: `[name]/style.css`;
|
||||
},
|
||||
chunkFilename: 'chunks/[id].style.css',
|
||||
} ),
|
||||
new WebpackRTLPlugin( {
|
||||
test: /(?<!style)\.css$/,
|
||||
filename: '[name]-rtl.css',
|
||||
minify: NODE_ENV === 'development' ? false : { safe: true },
|
||||
} ),
|
||||
new WebpackRTLPlugin( {
|
||||
test: /style\.css$/,
|
||||
filename: '[name]/style-rtl.css',
|
||||
minify: NODE_ENV === 'development' ? false : { safe: true },
|
||||
} ),
|
||||
],
|
||||
};
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: update
|
||||
|
||||
Moving text completion hooks into @woocommerce/ai package for reuse.
|
|
@ -30,6 +30,7 @@
|
|||
"@emotion/react": "^11.10.4",
|
||||
"@types/prop-types": "^15.7.4",
|
||||
"@types/react-outside-click-handler": "^1.3.1",
|
||||
"@woocommerce/ai": "workspace:0.1.0-beta.0",
|
||||
"@woocommerce/components": "workspace:*",
|
||||
"@woocommerce/tracks": "workspace:*",
|
||||
"@wordpress/api-fetch": "wp-6.0",
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
export * from './useTinyEditor';
|
||||
export * from './useCompletion';
|
||||
export * from './useFeedbackSnackbar';
|
||||
export * from './useProductSlug';
|
||||
export * from './useProductDataSuggestions';
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
ProductDataSuggestion,
|
||||
ProductDataSuggestionRequest,
|
||||
ApiErrorResponse,
|
||||
} from '../utils/types';
|
||||
import { requestJetpackToken } from '../utils';
|
||||
|
||||
type ProductDataSuggestionSuccessResponse = {
|
||||
suggestions: ProductDataSuggestion[];
|
||||
};
|
||||
|
||||
type ProductDataSuggestionErrorResponse = ApiErrorResponse;
|
||||
|
||||
export const useProductDataSuggestions = () => {
|
||||
const fetchSuggestions = async (
|
||||
request: ProductDataSuggestionRequest
|
||||
): Promise< ProductDataSuggestion[] > => {
|
||||
try {
|
||||
const token = await requestJetpackToken();
|
||||
const { suggestions } =
|
||||
await apiFetch< ProductDataSuggestionSuccessResponse >( {
|
||||
path: '/wooai/product-data-suggestions',
|
||||
method: 'POST',
|
||||
data: { ...request, token },
|
||||
} );
|
||||
|
||||
return suggestions;
|
||||
} catch ( error ) {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.error( error );
|
||||
|
||||
const errorResponse = error as ProductDataSuggestionErrorResponse;
|
||||
const hasStatus = errorResponse?.data?.status;
|
||||
const hasMessage = errorResponse?.message;
|
||||
|
||||
// Check if the status is 500 or greater.
|
||||
const isStatusGte500 =
|
||||
errorResponse?.data?.status && errorResponse.data.status >= 500;
|
||||
|
||||
// If the error response doesn't have a status or message, or if the status is 500 or greater, throw a generic error.
|
||||
if ( ! hasStatus || ! hasMessage || isStatusGte500 ) {
|
||||
throw new Error(
|
||||
__(
|
||||
`Apologies, this is an experimental feature and there was an error with this service. Please try again.`,
|
||||
'woocommerce'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
throw new Error( errorResponse.message );
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
fetchSuggestions,
|
||||
} as const;
|
||||
};
|
|
@ -1,9 +1,12 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useEffect, useRef } from '@wordpress/element';
|
||||
import {
|
||||
__experimentalUseCompletion as useCompletion,
|
||||
UseCompletionError,
|
||||
} from '@woocommerce/ai';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -11,9 +14,10 @@ import { useState, useEffect, useRef } from '@wordpress/element';
|
|||
import {
|
||||
MAX_TITLE_LENGTH,
|
||||
MIN_TITLE_LENGTH_FOR_DESCRIPTION,
|
||||
WOO_AI_PLUGIN_FEATURE_NAME,
|
||||
} from '../constants';
|
||||
import { StopCompletionBtn, WriteItForMeBtn } from '../components';
|
||||
import { useCompletion, useFeedbackSnackbar, useTinyEditor } from '../hooks';
|
||||
import { useFeedbackSnackbar, useTinyEditor } from '../hooks';
|
||||
import {
|
||||
getProductName,
|
||||
getPostId,
|
||||
|
@ -57,9 +61,14 @@ export function WriteItForMeButtonContainer() {
|
|||
titleEl.current?.value || ''
|
||||
);
|
||||
const tinyEditor = useTinyEditor();
|
||||
|
||||
const handleCompletionError = ( error: UseCompletionError ) =>
|
||||
tinyEditor.setContent( getApiError( error.code ?? '' ) );
|
||||
|
||||
const { showSnackbar, removeSnackbar } = useFeedbackSnackbar();
|
||||
const { requestCompletion, completionActive, stopCompletion } =
|
||||
useCompletion( {
|
||||
feature: WOO_AI_PLUGIN_FEATURE_NAME,
|
||||
onStreamMessage: ( content ) => {
|
||||
// This prevents printing out incomplete HTML tags.
|
||||
const ignoreRegex = new RegExp( /<\/?\w*[^>]*$/g );
|
||||
|
@ -67,12 +76,7 @@ export function WriteItForMeButtonContainer() {
|
|||
tinyEditor.setContent( content );
|
||||
}
|
||||
},
|
||||
onStreamError: ( error ) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug( 'Streaming error encountered', error );
|
||||
|
||||
tinyEditor.setContent( getApiError( error ) );
|
||||
},
|
||||
onStreamError: handleCompletionError,
|
||||
onCompletionFinished: ( reason, content ) => {
|
||||
recordDescriptionTracks( 'stop', {
|
||||
reason,
|
||||
|
@ -174,7 +178,7 @@ export function WriteItForMeButtonContainer() {
|
|||
].join( ' ' );
|
||||
};
|
||||
|
||||
const onWriteItForMeClick = () => {
|
||||
const onWriteItForMeClick = async () => {
|
||||
setFetching( true );
|
||||
removeSnackbar();
|
||||
|
||||
|
@ -182,7 +186,12 @@ export function WriteItForMeButtonContainer() {
|
|||
recordDescriptionTracks( 'start', {
|
||||
prompt,
|
||||
} );
|
||||
requestCompletion( prompt );
|
||||
|
||||
try {
|
||||
await requestCompletion( prompt );
|
||||
} catch ( err ) {
|
||||
handleCompletionError( err as UseCompletionError );
|
||||
}
|
||||
};
|
||||
|
||||
return completionActive ? (
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import React from 'react';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
|
||||
import { __experimentalUseCompletion as useCompletion } from '@woocommerce/ai';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -20,10 +21,11 @@ import {
|
|||
getTags,
|
||||
getAttributes,
|
||||
} from '../utils';
|
||||
import { useCompletion, useProductSlug } from '../hooks';
|
||||
import { useProductSlug } from '../hooks';
|
||||
import { ProductDataSuggestion } from '../utils/types';
|
||||
import { SuggestionItem, PoweredByLink, recordNameTracks } from './index';
|
||||
import { RandomLoadingMessage } from '../components';
|
||||
import { WOO_AI_PLUGIN_FEATURE_NAME } from '../constants';
|
||||
|
||||
const MIN_TITLE_LENGTH = 10;
|
||||
|
||||
|
@ -64,12 +66,13 @@ export const ProductNameSuggestions = () => {
|
|||
);
|
||||
const { updateProductSlug } = useProductSlug();
|
||||
const { requestCompletion } = useCompletion( {
|
||||
feature: WOO_AI_PLUGIN_FEATURE_NAME,
|
||||
onStreamError: ( error ) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug( 'Streaming error encountered', error );
|
||||
recordNameTracks( 'stop', {
|
||||
reason: 'error',
|
||||
error: ( error as { message?: string } )?.message || '',
|
||||
error: error.code ?? error.message,
|
||||
} );
|
||||
setSuggestionsState( SuggestionsState.Failed );
|
||||
},
|
||||
|
@ -127,14 +130,13 @@ export const ProductNameSuggestions = () => {
|
|||
|
||||
const onBodyClick = ( e: MouseEvent ) => {
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
if (
|
||||
! (
|
||||
nameInput?.ownerDocument.activeElement === nameInput ||
|
||||
// Need to capture errant handlediv click that happens on load as well
|
||||
Boolean( target.querySelector( ':scope > .handlediv' ) ) ||
|
||||
target?.matches(
|
||||
'#woocommerce-ai-app-product-name-suggestions *, #title'
|
||||
'#woocommerce-ai-app-product-name-suggestions *, #title, .woo-ai-get-suggestions-btn__content'
|
||||
)
|
||||
)
|
||||
) {
|
||||
|
@ -259,7 +261,11 @@ export const ProductNameSuggestions = () => {
|
|||
current_title: getProductName(),
|
||||
} );
|
||||
|
||||
requestCompletion( buildPrompt() );
|
||||
try {
|
||||
await requestCompletion( buildPrompt() );
|
||||
} catch ( e ) {
|
||||
setSuggestionsState( SuggestionsState.Failed );
|
||||
}
|
||||
};
|
||||
|
||||
const shouldRenderSuggestionsButton = useCallback( () => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
export * from './productData';
|
||||
export * from './shuffleArray';
|
||||
export * from './text-completion';
|
||||
export * from './recordTracksFactory';
|
||||
export * from './get-post-id';
|
||||
export * from './tiny-tools';
|
||||
|
|
|
@ -7,24 +7,3 @@ export type ProductDataSuggestion = {
|
|||
reason: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type ProductDataSuggestionRequest = {
|
||||
requested_data: string;
|
||||
name: string;
|
||||
description: string;
|
||||
categories: string[];
|
||||
tags: string[];
|
||||
attributes: Attribute[];
|
||||
};
|
||||
|
||||
// This is the standard API response data when an error is returned.
|
||||
export type ApiErrorResponse = {
|
||||
code: string;
|
||||
message: string;
|
||||
data?: ApiErrorResponseData | undefined;
|
||||
};
|
||||
|
||||
// API errors contain data with the status, and more in-depth error details. This may be null.
|
||||
export type ApiErrorResponseData = {
|
||||
status: number;
|
||||
} | null;
|
||||
|
|
2916
pnpm-lock.yaml
2916
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue