@far-world-labs/verblets 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +42 -0
- package/.husky/pre-commit +4 -0
- package/.release-it.json +9 -0
- package/.vite.config.examples.js +8 -0
- package/.vite.config.js +8 -0
- package/docker-compose.yml +7 -0
- package/docs/README.md +41 -0
- package/docs/babel.config.js +3 -0
- package/docs/blog/2019-05-28-first-blog-post.md +12 -0
- package/docs/blog/2019-05-29-long-blog-post.md +44 -0
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +20 -0
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.md +25 -0
- package/docs/blog/authors.yml +17 -0
- package/docs/docs/api/bool.md +74 -0
- package/docs/docs/api/search.md +51 -0
- package/docs/docs/intro.md +47 -0
- package/docs/docs/tutorial-basics/_category_.json +8 -0
- package/docs/docs/tutorial-basics/congratulations.md +23 -0
- package/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
- package/docs/docs/tutorial-basics/create-a-document.md +57 -0
- package/docs/docs/tutorial-basics/create-a-page.md +43 -0
- package/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
- package/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
- package/docs/docs/tutorial-extras/_category_.json +7 -0
- package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
- package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
- package/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
- package/docs/docs/tutorial-extras/translate-your-site.md +88 -0
- package/docs/docusaurus.config.js +120 -0
- package/docs/package.json +44 -0
- package/docs/sidebars.js +31 -0
- package/docs/src/components/HomepageFeatures/index.js +61 -0
- package/docs/src/components/HomepageFeatures/styles.module.css +11 -0
- package/docs/src/css/custom.css +30 -0
- package/docs/src/pages/index.js +43 -0
- package/docs/src/pages/index.module.css +23 -0
- package/docs/src/pages/markdown-page.md +7 -0
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +1 -0
- package/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
- package/docs/static/img/undraw_docusaurus_react.svg +170 -0
- package/docs/static/img/undraw_docusaurus_tree.svg +40 -0
- package/package.json +75 -0
- package/scripts/generate-chain/index.js +111 -0
- package/scripts/generate-lib/index.js +68 -0
- package/scripts/generate-test/index.js +111 -0
- package/scripts/generate-verblet/README.md +17 -0
- package/scripts/generate-verblet/index.js +110 -0
- package/scripts/run.sh +15 -0
- package/scripts/runner/index.js +30 -0
- package/scripts/simple-editor/README.md +34 -0
- package/scripts/simple-editor/index.js +68 -0
- package/scripts/summarize-files/index.js +46 -0
- package/src/chains/dismantle/dismantle.examples.js +0 -0
- package/src/chains/dismantle/index.examples.js +30 -0
- package/src/chains/dismantle/index.js +314 -0
- package/src/chains/dismantle/index.spec.js +33 -0
- package/src/chains/list/index.examples.js +72 -0
- package/src/chains/list/index.js +161 -0
- package/src/chains/list/index.spec.js +68 -0
- package/src/chains/list/schema.json +24 -0
- package/src/chains/questions/index.examples.js +68 -0
- package/src/chains/questions/index.js +136 -0
- package/src/chains/questions/index.spec.js +29 -0
- package/src/chains/scan-js/index.js +119 -0
- package/src/chains/sort/index.examples.js +40 -0
- package/src/chains/sort/index.js +113 -0
- package/src/chains/sort/index.spec.js +115 -0
- package/src/chains/summary-map/README.md +33 -0
- package/src/chains/summary-map/index.examples.js +57 -0
- package/src/chains/summary-map/index.js +208 -0
- package/src/chains/summary-map/index.spec.js +78 -0
- package/src/chains/test/index.js +118 -0
- package/src/chains/test-advice/index.js +36 -0
- package/src/constants/common.js +9 -0
- package/src/constants/messages.js +3 -0
- package/src/constants/openai.js +65 -0
- package/src/index.js +33 -0
- package/src/json-schemas/cars-test.json +11 -0
- package/src/json-schemas/index.js +18 -0
- package/src/json-schemas/intent.json +38 -0
- package/src/json-schemas/schema-dot-org-photograph.json +127 -0
- package/src/json-schemas/schema-dot-org-place.json +56 -0
- package/src/lib/any-signal/index.js +28 -0
- package/src/lib/chatgpt/index.js +143 -0
- package/src/lib/editor/index.js +31 -0
- package/src/lib/parse-js-parts/index.js +333 -0
- package/src/lib/parse-js-parts/index.spec.js +156 -0
- package/src/lib/path-aliases/index.js +39 -0
- package/src/lib/path-aliases/index.spec.js +70 -0
- package/src/lib/pave/index.js +34 -0
- package/src/lib/pave/index.spec.js +73 -0
- package/src/lib/prompt-cache/index.js +46 -0
- package/src/lib/retry/index.js +63 -0
- package/src/lib/retry/index.spec.js +86 -0
- package/src/lib/search-best-first/index.js +66 -0
- package/src/lib/search-js-files/code-features-property-definitions.json +123 -0
- package/src/lib/search-js-files/index.examples.js +22 -0
- package/src/lib/search-js-files/index.js +158 -0
- package/src/lib/search-js-files/index.spec.js +34 -0
- package/src/lib/search-js-files/scan-file.js +253 -0
- package/src/lib/shorten-text/index.js +30 -0
- package/src/lib/shorten-text/index.spec.js +68 -0
- package/src/lib/strip-numeric/index.js +5 -0
- package/src/lib/strip-response/index.js +35 -0
- package/src/lib/timed-abort-controller/index.js +41 -0
- package/src/lib/to-bool/index.js +8 -0
- package/src/lib/to-enum/index.js +14 -0
- package/src/lib/to-number/index.js +12 -0
- package/src/lib/to-number-with-units/index.js +51 -0
- package/src/lib/transcribe/index.js +61 -0
- package/src/prompts/README.md +15 -0
- package/src/prompts/as-enum.js +5 -0
- package/src/prompts/as-json-schema.js +9 -0
- package/src/prompts/as-object-with-schema.js +31 -0
- package/src/prompts/as-schema-org-text.js +17 -0
- package/src/prompts/as-schema-org-type.js +1 -0
- package/src/prompts/blog-post.js +7 -0
- package/src/prompts/code-features.js +28 -0
- package/src/prompts/constants.js +101 -0
- package/src/prompts/features-json-schema.js +27 -0
- package/src/prompts/generate-collection.js +26 -0
- package/src/prompts/generate-list.js +48 -0
- package/src/prompts/generate-questions.js +19 -0
- package/src/prompts/index.js +20 -0
- package/src/prompts/intent.js +66 -0
- package/src/prompts/output-succinct-names.js +3 -0
- package/src/prompts/select-from-threshold.js +18 -0
- package/src/prompts/sort.js +35 -0
- package/src/prompts/style.js +41 -0
- package/src/prompts/summarize.js +13 -0
- package/src/prompts/token-budget.js +3 -0
- package/src/prompts/wrap-list.js +14 -0
- package/src/prompts/wrap-variable.js +36 -0
- package/src/services/llm-model/index.js +114 -0
- package/src/services/llm-model/model.js +21 -0
- package/src/services/redis/index.js +84 -0
- package/src/verblets/auto/index.examples.js +28 -0
- package/src/verblets/auto/index.js +28 -0
- package/src/verblets/auto/index.spec.js +34 -0
- package/src/verblets/bool/index.examples.js +28 -0
- package/src/verblets/bool/index.js +28 -0
- package/src/verblets/bool/index.schema.json +14 -0
- package/src/verblets/bool/index.spec.js +35 -0
- package/src/verblets/enum/index.examples.js +33 -0
- package/src/verblets/enum/index.js +15 -0
- package/src/verblets/enum/index.spec.js +35 -0
- package/src/verblets/intent/index.examples.js +51 -0
- package/src/verblets/intent/index.js +72 -0
- package/src/verblets/intent/index.spec.js +31 -0
- package/src/verblets/number/index.examples.js +33 -0
- package/src/verblets/number/index.js +22 -0
- package/src/verblets/number/index.spec.js +35 -0
- package/src/verblets/number-with-units/index.examples.js +34 -0
- package/src/verblets/number-with-units/index.js +19 -0
- package/src/verblets/number-with-units/index.spec.js +46 -0
- package/src/verblets/schema-org/index.examples.js +56 -0
- package/src/verblets/schema-org/index.js +8 -0
- package/src/verblets/schema-org/index.spec.js +39 -0
- package/src/verblets/to-object/README.md +38 -0
- package/src/verblets/to-object/index.examples.js +29 -0
- package/src/verblets/to-object/index.js +136 -0
- package/src/verblets/to-object/index.spec.js +74 -0
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@far-world-labs/verblets",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "OpenAI Client",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Far-World-Labs/Verblets.git"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"start": "node scripts/runner/index.js",
|
|
13
|
+
"dev": "nodemon --no-warnings scripts/runner/index.js",
|
|
14
|
+
"editor": "node scripts/simple-editor/index.js",
|
|
15
|
+
"--": "npm run script -- generate-verblet foo",
|
|
16
|
+
"script": "./scripts/run.sh",
|
|
17
|
+
"test": "vitest",
|
|
18
|
+
"examples": "EXAMPLES=true vitest --config .vite.config.examples.js",
|
|
19
|
+
"lint": "eslint 'src/**/*.{js,jsx}'",
|
|
20
|
+
"lint:fix": "eslint 'src/**/*.{js,jsx}' --fix",
|
|
21
|
+
"husky:install": "husky install",
|
|
22
|
+
"husky:uninstall": "husky uninstall",
|
|
23
|
+
"prepare": "npx husky install"
|
|
24
|
+
},
|
|
25
|
+
"config": {
|
|
26
|
+
"gen-script": "./scripts/run.sh gen-$1"
|
|
27
|
+
},
|
|
28
|
+
"author": "Far World Labs",
|
|
29
|
+
"license": "All Rights Reserved",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"acorn": "^8.8.2",
|
|
32
|
+
"acorn-walk": "^8.2.0",
|
|
33
|
+
"ajv": "^8.12.0",
|
|
34
|
+
"chai": "^4.3.7",
|
|
35
|
+
"change-case": "^4.1.2",
|
|
36
|
+
"dependency-tree": "^10.0.1",
|
|
37
|
+
"dotenv": "^16.0.3",
|
|
38
|
+
"gpt-tokenizer": "^2.1.2",
|
|
39
|
+
"gpt4-tokenizer": "^1.3.0",
|
|
40
|
+
"mocha": "^10.2.0",
|
|
41
|
+
"node-fetch": "^3.3.0",
|
|
42
|
+
"nodemon": "^2.0.22",
|
|
43
|
+
"ramda": "^0.29.0",
|
|
44
|
+
"redis": "^4.6.5",
|
|
45
|
+
"uuid": "^9.0.0",
|
|
46
|
+
"vitest": "^0.30.1",
|
|
47
|
+
"yargs": "^17.7.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^18.16.3",
|
|
51
|
+
"eslint": "^8.39.0",
|
|
52
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
53
|
+
"eslint-config-prettier": "^8.8.0",
|
|
54
|
+
"eslint-plugin-import": "^2.27.5",
|
|
55
|
+
"eslint-plugin-jest": "^27.2.1",
|
|
56
|
+
"eslint-plugin-jsx-a11y": "^6.7.1",
|
|
57
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
58
|
+
"eslint-plugin-react": "^7.32.2",
|
|
59
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
60
|
+
"husky": "^8.0.3",
|
|
61
|
+
"install-peerdeps": "^3.0.3",
|
|
62
|
+
"lint-staged": "^13.2.2",
|
|
63
|
+
"node-record-lpcm16": "^1.0.1",
|
|
64
|
+
"npm-check": "^6.0.1",
|
|
65
|
+
"prettier": "^2.8.8",
|
|
66
|
+
"release-it": "^15.10.1",
|
|
67
|
+
"whisper-node": "^1.1.1",
|
|
68
|
+
"why-is-node-running": "^2.2.2"
|
|
69
|
+
},
|
|
70
|
+
"lint-staged": {
|
|
71
|
+
"**/*.js": [
|
|
72
|
+
"npm run lint:fix"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {
|
|
4
|
+
camelCase,
|
|
5
|
+
paramCase,
|
|
6
|
+
sentenceCase,
|
|
7
|
+
} from 'change-case';
|
|
8
|
+
|
|
9
|
+
const chainName = process.argv[2];
|
|
10
|
+
|
|
11
|
+
if (!chainName) {
|
|
12
|
+
console.error('Please specify a chain name.');
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const chainDir = `./src/chains/${paramCase(chainName)}`;
|
|
17
|
+
const indexFile = `${chainDir}/index.js`;
|
|
18
|
+
const testFile = `${chainDir}/index.spec.js`;
|
|
19
|
+
const exampleFile = `${chainDir}/index.examples.js`;
|
|
20
|
+
|
|
21
|
+
const createFileIfNotExists = (filePath, fileContent, fileType) => {
|
|
22
|
+
if (!fs.existsSync(filePath)) {
|
|
23
|
+
fs.writeFileSync(filePath, fileContent);
|
|
24
|
+
console.error(`Created new ${fileType} file: ${filePath}`);
|
|
25
|
+
} else {
|
|
26
|
+
console.error(`Creating ${fileType} file [skipped]: '${filePath}' exists`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check if the chain directory already exists
|
|
31
|
+
if (!fs.existsSync(chainDir)) {
|
|
32
|
+
// Create the chain directory
|
|
33
|
+
fs.mkdirSync(chainDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const indexContent = `
|
|
37
|
+
export default async (text) => {
|
|
38
|
+
// TODO: Implement ${paramCase(chainName)} chain
|
|
39
|
+
};
|
|
40
|
+
`;
|
|
41
|
+
createFileIfNotExists(indexFile, indexContent, 'module file');
|
|
42
|
+
|
|
43
|
+
const testContent = `import { describe, expect, it, vi } from 'vitest';
|
|
44
|
+
|
|
45
|
+
import ${camelCase(chainName)} from './index.js';
|
|
46
|
+
|
|
47
|
+
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
48
|
+
default: vi.fn().mockImplementation((text) => {
|
|
49
|
+
if (/prompt text to match/.test(text)) {
|
|
50
|
+
return 'True';
|
|
51
|
+
} else {
|
|
52
|
+
return 'undefined';
|
|
53
|
+
}
|
|
54
|
+
}),
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
const examples = [
|
|
58
|
+
{
|
|
59
|
+
name: 'Basic usage',
|
|
60
|
+
inputs: { text: 'test' },
|
|
61
|
+
want: { result: true }
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
describe('${sentenceCase(chainName)} chain', () => {
|
|
66
|
+
examples.forEach((example) => {
|
|
67
|
+
it(example.name, async () => {
|
|
68
|
+
const result = await ${camelCase(chainName)}(example.inputs.text);
|
|
69
|
+
|
|
70
|
+
if (example.want.typeOfResult) {
|
|
71
|
+
expect(typeof result)
|
|
72
|
+
.toStrictEqual(example.want.typeOfResult);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
`;
|
|
78
|
+
createFileIfNotExists(testFile, testContent, 'test');
|
|
79
|
+
|
|
80
|
+
const exampleContent = `import { describe, expect, it, vi } from 'vitest';
|
|
81
|
+
|
|
82
|
+
import ${camelCase(chainName)} from './index.js';
|
|
83
|
+
|
|
84
|
+
const examples = [
|
|
85
|
+
{
|
|
86
|
+
inputs: { text: 'test' },
|
|
87
|
+
want: { result: true }
|
|
88
|
+
}
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
describe('${sentenceCase(chainName)} chain', () => {
|
|
92
|
+
examples.forEach((example) => {
|
|
93
|
+
it(example.inputs.text, async () => {
|
|
94
|
+
const result = await ${camelCase(chainName)}(example.inputs.text)
|
|
95
|
+
|
|
96
|
+
if (example.want.typeOfResult) {
|
|
97
|
+
expect(typeof result)
|
|
98
|
+
.toStrictEqual(example.want.typeOfResult);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (example.want.result) {
|
|
102
|
+
expect(result)
|
|
103
|
+
.toStrictEqual(example.want.result);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
`;
|
|
109
|
+
createFileIfNotExists(exampleFile, exampleContent, 'example');
|
|
110
|
+
|
|
111
|
+
console.error(`Created new chain: ${chainName}`);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import {
|
|
3
|
+
camelCase,
|
|
4
|
+
paramCase,
|
|
5
|
+
sentenceCase,
|
|
6
|
+
} from 'change-case';
|
|
7
|
+
|
|
8
|
+
const libName = process.argv[2];
|
|
9
|
+
|
|
10
|
+
if (!libName) {
|
|
11
|
+
console.error('Please specify a library name.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const libDir = `./src/lib/${paramCase(libName)}`;
|
|
16
|
+
const indexFile = `${libDir}/index.js`;
|
|
17
|
+
const testFile = `${libDir}/index.spec.js`;
|
|
18
|
+
|
|
19
|
+
const createFileIfNotExists = (filePath, fileContent, fileType) => {
|
|
20
|
+
if (!fs.existsSync(filePath)) {
|
|
21
|
+
fs.writeFileSync(filePath, fileContent);
|
|
22
|
+
console.error(`Created new ${fileType} file: ${filePath}`);
|
|
23
|
+
} else {
|
|
24
|
+
console.error(`Creating ${fileType} file [skipped]: '${filePath}' exists`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Check if the lib directory already exists
|
|
29
|
+
if (!fs.existsSync(libDir)) {
|
|
30
|
+
// Create the lib directory
|
|
31
|
+
fs.mkdirSync(libDir, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const indexContent = `
|
|
35
|
+
export default async (text) => {
|
|
36
|
+
// TODO: Implement ${paramCase(libName)} lib
|
|
37
|
+
};
|
|
38
|
+
`;
|
|
39
|
+
createFileIfNotExists(indexFile, indexContent, 'module file');
|
|
40
|
+
|
|
41
|
+
const testContent = `import { describe, expect, it, vi } from 'vitest';
|
|
42
|
+
|
|
43
|
+
import ${camelCase(libName)} from './index.js';
|
|
44
|
+
|
|
45
|
+
const examples = [
|
|
46
|
+
{
|
|
47
|
+
name: 'Basic usage',
|
|
48
|
+
inputs: { text: 'test' },
|
|
49
|
+
want: { result: true }
|
|
50
|
+
}
|
|
51
|
+
];
|
|
52
|
+
|
|
53
|
+
describe('${sentenceCase(libName)} lib', () => {
|
|
54
|
+
examples.forEach((example) => {
|
|
55
|
+
it(example.name, async () => {
|
|
56
|
+
const result = await ${camelCase(libName)}(example.inputs.text);
|
|
57
|
+
|
|
58
|
+
if (example.want.typeOfResult) {
|
|
59
|
+
expect(typeof result)
|
|
60
|
+
.toStrictEqual(example.want.typeOfResult);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
`;
|
|
66
|
+
createFileIfNotExists(testFile, testContent, 'test');
|
|
67
|
+
|
|
68
|
+
console.error(`Created new lib: ${libName}`);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import parseJSParts from '../../src/lib/parse-js-parts/index.js';
|
|
5
|
+
import
|
|
6
|
+
chatGPT,
|
|
7
|
+
{
|
|
8
|
+
getRedis,
|
|
9
|
+
SummaryMap
|
|
10
|
+
} from '../../src/index.js';
|
|
11
|
+
|
|
12
|
+
const modulePath = process.argv[2];
|
|
13
|
+
const functionName = process.argv[3];
|
|
14
|
+
|
|
15
|
+
if (!modulePath) {
|
|
16
|
+
console.error('Please specify a module to test.');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
await fs.stat(modulePath);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error(`Module not found at: ${modulePath}`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const moduleDir = path.dirname(modulePath);
|
|
28
|
+
const moduleName = path.basename(moduleDir);
|
|
29
|
+
const testFile = path.join(moduleDir, `${moduleName}.spec.js`);
|
|
30
|
+
|
|
31
|
+
const examplePath1 = './src/lib/parse-js-parts/parse-js-parts.spec.js';
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await fs.stat(examplePath1);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error(`Generate test [error]: ${error.message}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const generatePrompt = ({ moduleFile, modulePath, examples=[] }) => {
|
|
41
|
+
const examplesJoined = examples.map((example) => `<example>${example}</example>`).join('\n');
|
|
42
|
+
|
|
43
|
+
let prompt = `Generate a test file for module shown below.
|
|
44
|
+
|
|
45
|
+
Examples to inform the results:
|
|
46
|
+
${examplesJoined}
|
|
47
|
+
|
|
48
|
+
<module-to-test>${moduleFile}</module-to-test>`;
|
|
49
|
+
|
|
50
|
+
return prompt;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function generateTestFile(modulePath) {
|
|
54
|
+
const moduleFile = await fs.readFile(modulePath, 'utf-8');
|
|
55
|
+
|
|
56
|
+
const example1 = (await fs.readFile(examplePath1, 'utf-8'));
|
|
57
|
+
// const example2 = await fs.readFile(examplePath2, 'utf-8');
|
|
58
|
+
|
|
59
|
+
const fixes = [];
|
|
60
|
+
if (functionName) {
|
|
61
|
+
fixes.push('For the function "${functionName}", keep as much of the code as you can.');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let functionNameDisplay = '';
|
|
65
|
+
if (functionName) {
|
|
66
|
+
functionNameDisplay = `, only for "${functionName}"`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
let moduleFileSliced = moduleFile;
|
|
70
|
+
if (functionName) {
|
|
71
|
+
const results = parseJSParts(modulePath, moduleFile);
|
|
72
|
+
|
|
73
|
+
const funcs = Object.keys(results.functionsMap);
|
|
74
|
+
const funcFound = funcs.find(f => (new RegExp(`${functionName}$`)).test(f));
|
|
75
|
+
const funcDefFound = results.functionsMap?.[funcFound];
|
|
76
|
+
if (funcDefFound) {
|
|
77
|
+
moduleFileSliced = moduleFile.slice(funcDefFound.start, funcDefFound.end);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const argsMap = new SummaryMap({ promptText: generatePrompt.toString() });
|
|
82
|
+
|
|
83
|
+
argsMap.set('functionName', { value: functionName });
|
|
84
|
+
argsMap.set('modulePath', { value: modulePath });
|
|
85
|
+
argsMap.set('moduleFile', {
|
|
86
|
+
value: moduleFileSliced,
|
|
87
|
+
weight: 1,
|
|
88
|
+
type: 'code',
|
|
89
|
+
fixes,
|
|
90
|
+
})
|
|
91
|
+
argsMap.set('examples.0', {
|
|
92
|
+
value: example1,
|
|
93
|
+
weight: 1,
|
|
94
|
+
type: 'code',
|
|
95
|
+
fixes: ['Keep at least one of the example definitions in the example array'],
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
const prompt = await generatePrompt(await argsMap.pavedSummaryResult());
|
|
99
|
+
|
|
100
|
+
console.error(prompt)
|
|
101
|
+
|
|
102
|
+
const response = await chatGPT(prompt);
|
|
103
|
+
|
|
104
|
+
// use standard shell IO to apply the generated code
|
|
105
|
+
console.error(response);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Example usage:
|
|
109
|
+
await generateTestFile(modulePath);
|
|
110
|
+
|
|
111
|
+
await (await getRedis()).disconnect();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Verblet Generator
|
|
2
|
+
|
|
3
|
+
This is a Node script that generates a new "verblet" module and test file in a specific directory structure.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
To use this script, run the following command:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
npm run script -- generate-verblet [verblet-name]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Replace `[verblet-name]` with the name of your new verblet. The script will create a new directory called `./src/verblets/[verblet-name]` and generate an `index.js` file and a test file inside that directory.
|
|
14
|
+
|
|
15
|
+
The generated `index.js` file exports a single default async function that you can implement to define the behavior of the verblet.
|
|
16
|
+
|
|
17
|
+
The generated test file is located at `./src/verblets/[verblet-name]/[verblet-name].spec.js`. It contains a sample test that you can modify to test your verblet implementation.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import {
|
|
3
|
+
camelCase,
|
|
4
|
+
paramCase,
|
|
5
|
+
sentenceCase,
|
|
6
|
+
} from 'change-case';
|
|
7
|
+
|
|
8
|
+
const verbletName = process.argv[2];
|
|
9
|
+
|
|
10
|
+
if (!verbletName) {
|
|
11
|
+
console.error('Please specify a verblet name.');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const verbletDir = `./src/verblets/${paramCase(verbletName)}`;
|
|
16
|
+
const indexFile = `${verbletDir}/index.js`;
|
|
17
|
+
const testFile = `${verbletDir}/index.spec.js`;
|
|
18
|
+
const exampleFile = `${verbletDir}/index.examples.js`;
|
|
19
|
+
|
|
20
|
+
const createFileIfNotExists = (filePath, fileContent, fileType) => {
|
|
21
|
+
if (!fs.existsSync(filePath)) {
|
|
22
|
+
fs.writeFileSync(filePath, fileContent);
|
|
23
|
+
console.error(`Created new ${fileType} file: ${filePath}`);
|
|
24
|
+
} else {
|
|
25
|
+
console.error(`Creating ${fileType} file [skipped]: '${filePath}' exists`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Check if the verblet directory already exists
|
|
30
|
+
if (!fs.existsSync(verbletDir)) {
|
|
31
|
+
// Create the verblet directory
|
|
32
|
+
fs.mkdirSync(verbletDir, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const indexContent = `
|
|
36
|
+
export default async (text) => {
|
|
37
|
+
// TODO: Implement ${paramCase(verbletName)} verblet
|
|
38
|
+
};
|
|
39
|
+
`;
|
|
40
|
+
createFileIfNotExists(indexFile, indexContent, 'module file');
|
|
41
|
+
|
|
42
|
+
const testContent = `import { describe, expect, it, vi } from 'vitest';
|
|
43
|
+
|
|
44
|
+
import ${camelCase(verbletName)} from './index.js';
|
|
45
|
+
|
|
46
|
+
vi.mock('../../lib/chatgpt/index.js', () => ({
|
|
47
|
+
default: vi.fn().mockImplementation((text) => {
|
|
48
|
+
if (/prompt text to match/.test(text)) {
|
|
49
|
+
return 'True';
|
|
50
|
+
} else {
|
|
51
|
+
return 'undefined';
|
|
52
|
+
}
|
|
53
|
+
}),
|
|
54
|
+
}));
|
|
55
|
+
|
|
56
|
+
const examples = [
|
|
57
|
+
{
|
|
58
|
+
name: 'Basic usage',
|
|
59
|
+
inputs: { text: 'test' },
|
|
60
|
+
want: { result: true }
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
describe('${sentenceCase(verbletName)} verblet', () => {
|
|
65
|
+
examples.forEach((example) => {
|
|
66
|
+
it(example.name, async () => {
|
|
67
|
+
const result = await ${camelCase(verbletName)}(example.inputs.text);
|
|
68
|
+
|
|
69
|
+
if (example.want.typeOfResult) {
|
|
70
|
+
expect(typeof result)
|
|
71
|
+
.toStrictEqual(example.want.typeOfResult);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
`;
|
|
77
|
+
createFileIfNotExists(testFile, testContent, 'test');
|
|
78
|
+
|
|
79
|
+
const exampleContent = `import { describe, expect, it, vi } from 'vitest';
|
|
80
|
+
|
|
81
|
+
import ${camelCase(verbletName)} from './index.js';
|
|
82
|
+
|
|
83
|
+
const examples = [
|
|
84
|
+
{
|
|
85
|
+
inputs: { text: 'test' },
|
|
86
|
+
want: { result: true }
|
|
87
|
+
}
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
describe('${sentenceCase(verbletName)} verblet', () => {
|
|
91
|
+
examples.forEach((example) => {
|
|
92
|
+
it(example.inputs.text, async () => {
|
|
93
|
+
const result = await ${camelCase(verbletName)}(example.inputs.text)
|
|
94
|
+
|
|
95
|
+
if (example.want.typeOfResult) {
|
|
96
|
+
expect(typeof result)
|
|
97
|
+
.toStrictEqual(example.want.typeOfResult);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (example.want.result) {
|
|
101
|
+
expect(result)
|
|
102
|
+
.toStrictEqual(example.want.result);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
`;
|
|
108
|
+
createFileIfNotExists(exampleFile, exampleContent, 'example');
|
|
109
|
+
|
|
110
|
+
console.error(`Created new verblet: ${verbletName}`);
|
package/scripts/run.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
script_name="$1"
|
|
4
|
+
if [[ "$script_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
|
5
|
+
script_path="./scripts/$script_name/index.js"
|
|
6
|
+
if [[ -f "$script_path" ]]; then
|
|
7
|
+
node "$script_path" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9" "$10"
|
|
8
|
+
else
|
|
9
|
+
echo "Script not found: $script_path"
|
|
10
|
+
exit 1
|
|
11
|
+
fi
|
|
12
|
+
else
|
|
13
|
+
echo "Invalid script name: $script_name"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
|
|
2
|
+
import chatGPT, {
|
|
3
|
+
getRedis,
|
|
4
|
+
list,
|
|
5
|
+
retry as run,
|
|
6
|
+
schemas,
|
|
7
|
+
} from '../../src/index.js';
|
|
8
|
+
|
|
9
|
+
await run(async () => {
|
|
10
|
+
const results = await chatGPT('make a list of nintendo games with a schema that includes a title, year, and maybe a couple others of your choice', {
|
|
11
|
+
forceQuery: true,
|
|
12
|
+
modelOptions: {
|
|
13
|
+
tools: schemas
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const functions = {
|
|
18
|
+
list: async (listName, options) => {
|
|
19
|
+
return await list(listName, options);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
if (typeof results === 'string') {
|
|
24
|
+
console.error(results);
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
console.error(await functions[results.name](results.arguments.name, results.arguments.options));
|
|
28
|
+
}, { maxRetries: 0 });
|
|
29
|
+
|
|
30
|
+
await (await getRedis()).disconnect();
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Simple Prompt Editor
|
|
2
|
+
|
|
3
|
+
This is a simple command-line tool that allows you to interact with the ChatGPT library using your system's default text editor or nano if none is defined.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
To run the simple ChatGPT editor, use the following command:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm run script -- simple-editor
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
It will open your system's default text editor or nano if none is defined. The editor allows you to enter your input text, which is then processed by the ChatGPT library. The script performs intent detection to match your request with one of the supported library commands. By default, it does ordinary ChatGPT completion.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## Adding Support for New Commands
|
|
17
|
+
|
|
18
|
+
To add support for new commands, you need to modify the operations array in the provided code. Each command should be an object with the following properties:
|
|
19
|
+
|
|
20
|
+
- name: A unique identifier for the command.
|
|
21
|
+
- parameters: An array of parameter names that the command accepts.
|
|
22
|
+
- operation: A function that takes an object with the parameters as keys and returns the result of the command.
|
|
23
|
+
|
|
24
|
+
To add a new command, simply append a new object to the operations array with the required properties. For example, to add a sum command that takes two numbers and returns their sum, you would add the following object:
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
{
|
|
28
|
+
name: 'sum',
|
|
29
|
+
parameters: ['number1', 'number2'],
|
|
30
|
+
operation: ({ number1, number2 }) => Number(number1) + Number(number2),
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
After adding the new command, the intent detection function will be able to match the user's input with the new command, and the script will execute the corresponding operation.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import dotenv from 'dotenv/config';
|
|
2
|
+
import yargs from 'yargs';
|
|
3
|
+
import { hideBin } from 'yargs/helpers';
|
|
4
|
+
|
|
5
|
+
import chatGPT, { getRedis, auto, bool } from '../../src/index.js';
|
|
6
|
+
import edit from '../../src/lib/editor/index.js';
|
|
7
|
+
import Transcriber from '../../src/lib/transcribe/index.js';
|
|
8
|
+
|
|
9
|
+
const argv = yargs(hideBin(process.argv))
|
|
10
|
+
.option('use-intent', {
|
|
11
|
+
alias: 'i',
|
|
12
|
+
default: 'true',
|
|
13
|
+
type: 'string',
|
|
14
|
+
description: '"false" to disable intent parsing and just use chatGPT',
|
|
15
|
+
})
|
|
16
|
+
.option('transcribe', {
|
|
17
|
+
alias: 't',
|
|
18
|
+
default: 'false',
|
|
19
|
+
type: 'string',
|
|
20
|
+
description: '"true" to enable audio transcription',
|
|
21
|
+
})
|
|
22
|
+
.argv;
|
|
23
|
+
|
|
24
|
+
const operations = [
|
|
25
|
+
{
|
|
26
|
+
name: 'bool',
|
|
27
|
+
fn: ({ text }) => {
|
|
28
|
+
return bool(text, { forceQuery: true });
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
let userInput;
|
|
35
|
+
const useTranscribe = ['true', '1'].includes(argv.transcribe)
|
|
36
|
+
if (useTranscribe) {
|
|
37
|
+
const transcriber = new Transcriber("stopword"); // Replace "stopword" with the word you want to trigger the stop
|
|
38
|
+
userInput = await transcriber.startRecording()
|
|
39
|
+
} else {
|
|
40
|
+
userInput = await edit();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const useIntent = !!['true', '1'].includes(argv.useIntent.toLowerCase())
|
|
44
|
+
|
|
45
|
+
const commandType = useIntent ? 'Tool selection' : 'Direct ChatGPT';
|
|
46
|
+
console.error(`Command: ${commandType}`);
|
|
47
|
+
const userInputDisplay = userInput.trim().split('\n')
|
|
48
|
+
.map(line => `| ${line}`)
|
|
49
|
+
.join('\n');
|
|
50
|
+
|
|
51
|
+
console.error(userInputDisplay);
|
|
52
|
+
|
|
53
|
+
let result;
|
|
54
|
+
if (!useIntent) {
|
|
55
|
+
result = await chatGPT(userInput);
|
|
56
|
+
} else {
|
|
57
|
+
const intentFound = await auto(userInput, { forceQuery: true });
|
|
58
|
+
|
|
59
|
+
const op = operations.find(option => {
|
|
60
|
+
return option.name === intentFound.name;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
result = await op.fn(...intentFound.functionArgsAsArray);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.error(result);
|
|
67
|
+
|
|
68
|
+
await (await getRedis()).disconnect();
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import glob from 'glob';
|
|
2
|
+
import { readFile } from 'fs/promises';
|
|
3
|
+
import SummaryMap from '../../src/chains/summary-map/index.js';
|
|
4
|
+
|
|
5
|
+
// Define your glob pattern here or pass it as a command line argument
|
|
6
|
+
const globPattern = process.argv[2] || './src/**/*.js';
|
|
7
|
+
|
|
8
|
+
// Define your target tokens here or pass it as a command line argument
|
|
9
|
+
const targetTokens = process.argv[3] || 4097;
|
|
10
|
+
|
|
11
|
+
// Initialize the SummaryMap with the target tokens
|
|
12
|
+
const map = new SummaryMap({
|
|
13
|
+
targetTokens: targetTokens
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
glob(globPattern, async (err, files) => {
|
|
17
|
+
if (err) {
|
|
18
|
+
console.error(err);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const filePromises = files.map(async (file) => {
|
|
23
|
+
try {
|
|
24
|
+
const content = await readFile(file, 'utf8');
|
|
25
|
+
// Set each file content with its respective filepath as a key
|
|
26
|
+
map.set(file, {
|
|
27
|
+
key: file,
|
|
28
|
+
value: content,
|
|
29
|
+
weight: 1,
|
|
30
|
+
type: 'code'
|
|
31
|
+
});
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error(`Error reading file ${file}:`, err);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// When all file read operations complete
|
|
38
|
+
await Promise.all(filePromises);
|
|
39
|
+
const entries = Array.from(await map.entries());
|
|
40
|
+
|
|
41
|
+
// Loop over each key/value and print it to stdout
|
|
42
|
+
for (const [key, value] of entries) {
|
|
43
|
+
console.log(`## ${key}\n`);
|
|
44
|
+
console.log(`\`\`\`js\n${value}\n\`\`\``);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
File without changes
|