@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.
Files changed (167) hide show
  1. package/.eslintrc.json +42 -0
  2. package/.husky/pre-commit +4 -0
  3. package/.release-it.json +9 -0
  4. package/.vite.config.examples.js +8 -0
  5. package/.vite.config.js +8 -0
  6. package/docker-compose.yml +7 -0
  7. package/docs/README.md +41 -0
  8. package/docs/babel.config.js +3 -0
  9. package/docs/blog/2019-05-28-first-blog-post.md +12 -0
  10. package/docs/blog/2019-05-29-long-blog-post.md +44 -0
  11. package/docs/blog/2021-08-01-mdx-blog-post.mdx +20 -0
  12. package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  13. package/docs/blog/2021-08-26-welcome/index.md +25 -0
  14. package/docs/blog/authors.yml +17 -0
  15. package/docs/docs/api/bool.md +74 -0
  16. package/docs/docs/api/search.md +51 -0
  17. package/docs/docs/intro.md +47 -0
  18. package/docs/docs/tutorial-basics/_category_.json +8 -0
  19. package/docs/docs/tutorial-basics/congratulations.md +23 -0
  20. package/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
  21. package/docs/docs/tutorial-basics/create-a-document.md +57 -0
  22. package/docs/docs/tutorial-basics/create-a-page.md +43 -0
  23. package/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
  24. package/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
  25. package/docs/docs/tutorial-extras/_category_.json +7 -0
  26. package/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
  27. package/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
  28. package/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
  29. package/docs/docs/tutorial-extras/translate-your-site.md +88 -0
  30. package/docs/docusaurus.config.js +120 -0
  31. package/docs/package.json +44 -0
  32. package/docs/sidebars.js +31 -0
  33. package/docs/src/components/HomepageFeatures/index.js +61 -0
  34. package/docs/src/components/HomepageFeatures/styles.module.css +11 -0
  35. package/docs/src/css/custom.css +30 -0
  36. package/docs/src/pages/index.js +43 -0
  37. package/docs/src/pages/index.module.css +23 -0
  38. package/docs/src/pages/markdown-page.md +7 -0
  39. package/docs/static/.nojekyll +0 -0
  40. package/docs/static/img/docusaurus-social-card.jpg +0 -0
  41. package/docs/static/img/docusaurus.png +0 -0
  42. package/docs/static/img/favicon.ico +0 -0
  43. package/docs/static/img/logo.svg +1 -0
  44. package/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  45. package/docs/static/img/undraw_docusaurus_react.svg +170 -0
  46. package/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  47. package/package.json +75 -0
  48. package/scripts/generate-chain/index.js +111 -0
  49. package/scripts/generate-lib/index.js +68 -0
  50. package/scripts/generate-test/index.js +111 -0
  51. package/scripts/generate-verblet/README.md +17 -0
  52. package/scripts/generate-verblet/index.js +110 -0
  53. package/scripts/run.sh +15 -0
  54. package/scripts/runner/index.js +30 -0
  55. package/scripts/simple-editor/README.md +34 -0
  56. package/scripts/simple-editor/index.js +68 -0
  57. package/scripts/summarize-files/index.js +46 -0
  58. package/src/chains/dismantle/dismantle.examples.js +0 -0
  59. package/src/chains/dismantle/index.examples.js +30 -0
  60. package/src/chains/dismantle/index.js +314 -0
  61. package/src/chains/dismantle/index.spec.js +33 -0
  62. package/src/chains/list/index.examples.js +72 -0
  63. package/src/chains/list/index.js +161 -0
  64. package/src/chains/list/index.spec.js +68 -0
  65. package/src/chains/list/schema.json +24 -0
  66. package/src/chains/questions/index.examples.js +68 -0
  67. package/src/chains/questions/index.js +136 -0
  68. package/src/chains/questions/index.spec.js +29 -0
  69. package/src/chains/scan-js/index.js +119 -0
  70. package/src/chains/sort/index.examples.js +40 -0
  71. package/src/chains/sort/index.js +113 -0
  72. package/src/chains/sort/index.spec.js +115 -0
  73. package/src/chains/summary-map/README.md +33 -0
  74. package/src/chains/summary-map/index.examples.js +57 -0
  75. package/src/chains/summary-map/index.js +208 -0
  76. package/src/chains/summary-map/index.spec.js +78 -0
  77. package/src/chains/test/index.js +118 -0
  78. package/src/chains/test-advice/index.js +36 -0
  79. package/src/constants/common.js +9 -0
  80. package/src/constants/messages.js +3 -0
  81. package/src/constants/openai.js +65 -0
  82. package/src/index.js +33 -0
  83. package/src/json-schemas/cars-test.json +11 -0
  84. package/src/json-schemas/index.js +18 -0
  85. package/src/json-schemas/intent.json +38 -0
  86. package/src/json-schemas/schema-dot-org-photograph.json +127 -0
  87. package/src/json-schemas/schema-dot-org-place.json +56 -0
  88. package/src/lib/any-signal/index.js +28 -0
  89. package/src/lib/chatgpt/index.js +143 -0
  90. package/src/lib/editor/index.js +31 -0
  91. package/src/lib/parse-js-parts/index.js +333 -0
  92. package/src/lib/parse-js-parts/index.spec.js +156 -0
  93. package/src/lib/path-aliases/index.js +39 -0
  94. package/src/lib/path-aliases/index.spec.js +70 -0
  95. package/src/lib/pave/index.js +34 -0
  96. package/src/lib/pave/index.spec.js +73 -0
  97. package/src/lib/prompt-cache/index.js +46 -0
  98. package/src/lib/retry/index.js +63 -0
  99. package/src/lib/retry/index.spec.js +86 -0
  100. package/src/lib/search-best-first/index.js +66 -0
  101. package/src/lib/search-js-files/code-features-property-definitions.json +123 -0
  102. package/src/lib/search-js-files/index.examples.js +22 -0
  103. package/src/lib/search-js-files/index.js +158 -0
  104. package/src/lib/search-js-files/index.spec.js +34 -0
  105. package/src/lib/search-js-files/scan-file.js +253 -0
  106. package/src/lib/shorten-text/index.js +30 -0
  107. package/src/lib/shorten-text/index.spec.js +68 -0
  108. package/src/lib/strip-numeric/index.js +5 -0
  109. package/src/lib/strip-response/index.js +35 -0
  110. package/src/lib/timed-abort-controller/index.js +41 -0
  111. package/src/lib/to-bool/index.js +8 -0
  112. package/src/lib/to-enum/index.js +14 -0
  113. package/src/lib/to-number/index.js +12 -0
  114. package/src/lib/to-number-with-units/index.js +51 -0
  115. package/src/lib/transcribe/index.js +61 -0
  116. package/src/prompts/README.md +15 -0
  117. package/src/prompts/as-enum.js +5 -0
  118. package/src/prompts/as-json-schema.js +9 -0
  119. package/src/prompts/as-object-with-schema.js +31 -0
  120. package/src/prompts/as-schema-org-text.js +17 -0
  121. package/src/prompts/as-schema-org-type.js +1 -0
  122. package/src/prompts/blog-post.js +7 -0
  123. package/src/prompts/code-features.js +28 -0
  124. package/src/prompts/constants.js +101 -0
  125. package/src/prompts/features-json-schema.js +27 -0
  126. package/src/prompts/generate-collection.js +26 -0
  127. package/src/prompts/generate-list.js +48 -0
  128. package/src/prompts/generate-questions.js +19 -0
  129. package/src/prompts/index.js +20 -0
  130. package/src/prompts/intent.js +66 -0
  131. package/src/prompts/output-succinct-names.js +3 -0
  132. package/src/prompts/select-from-threshold.js +18 -0
  133. package/src/prompts/sort.js +35 -0
  134. package/src/prompts/style.js +41 -0
  135. package/src/prompts/summarize.js +13 -0
  136. package/src/prompts/token-budget.js +3 -0
  137. package/src/prompts/wrap-list.js +14 -0
  138. package/src/prompts/wrap-variable.js +36 -0
  139. package/src/services/llm-model/index.js +114 -0
  140. package/src/services/llm-model/model.js +21 -0
  141. package/src/services/redis/index.js +84 -0
  142. package/src/verblets/auto/index.examples.js +28 -0
  143. package/src/verblets/auto/index.js +28 -0
  144. package/src/verblets/auto/index.spec.js +34 -0
  145. package/src/verblets/bool/index.examples.js +28 -0
  146. package/src/verblets/bool/index.js +28 -0
  147. package/src/verblets/bool/index.schema.json +14 -0
  148. package/src/verblets/bool/index.spec.js +35 -0
  149. package/src/verblets/enum/index.examples.js +33 -0
  150. package/src/verblets/enum/index.js +15 -0
  151. package/src/verblets/enum/index.spec.js +35 -0
  152. package/src/verblets/intent/index.examples.js +51 -0
  153. package/src/verblets/intent/index.js +72 -0
  154. package/src/verblets/intent/index.spec.js +31 -0
  155. package/src/verblets/number/index.examples.js +33 -0
  156. package/src/verblets/number/index.js +22 -0
  157. package/src/verblets/number/index.spec.js +35 -0
  158. package/src/verblets/number-with-units/index.examples.js +34 -0
  159. package/src/verblets/number-with-units/index.js +19 -0
  160. package/src/verblets/number-with-units/index.spec.js +46 -0
  161. package/src/verblets/schema-org/index.examples.js +56 -0
  162. package/src/verblets/schema-org/index.js +8 -0
  163. package/src/verblets/schema-org/index.spec.js +39 -0
  164. package/src/verblets/to-object/README.md +38 -0
  165. package/src/verblets/to-object/index.examples.js +29 -0
  166. package/src/verblets/to-object/index.js +136 -0
  167. 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