@far-world-labs/verblets 0.1.1 → 0.1.3
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/.cursor/launch.json +30 -0
- package/.cursor/settings.json +20 -0
- package/.github/workflows/branch-protection.yml +22 -0
- package/.github/workflows/ci.yml +120 -0
- package/.prettierrc +6 -0
- package/.release-it.json +4 -1
- package/.vscode/launch.json +31 -0
- package/AGENTS.md +220 -0
- package/DEVELOPING.md +105 -0
- package/README.md +254 -0
- package/eslint.config.js +80 -0
- package/package.json +29 -17
- package/scripts/generate-test/index.js +29 -3
- package/scripts/runner/index.js +26 -0
- package/scripts/simple-editor/index.js +29 -18
- package/scripts/summarize-files/index.js +28 -4
- package/src/chains/README.md +30 -0
- package/src/chains/anonymize/README.md +21 -0
- package/src/chains/anonymize/index.examples.js +75 -0
- package/src/chains/anonymize/index.js +121 -0
- package/src/chains/anonymize/index.spec.js +78 -0
- package/src/chains/bulk-central-tendency/index.examples.js +138 -0
- package/src/chains/bulk-central-tendency/index.js +91 -0
- package/src/chains/bulk-filter/README.md +21 -0
- package/src/chains/bulk-filter/index.examples.js +22 -0
- package/src/chains/bulk-filter/index.js +58 -0
- package/src/chains/bulk-filter/index.spec.js +38 -0
- package/src/chains/bulk-find/README.md +16 -0
- package/src/chains/bulk-find/index.examples.js +20 -0
- package/src/chains/bulk-find/index.js +30 -0
- package/src/chains/bulk-find/index.spec.js +26 -0
- package/src/chains/bulk-group/README.md +23 -0
- package/src/chains/bulk-group/index.examples.js +18 -0
- package/src/chains/bulk-group/index.js +34 -0
- package/src/chains/bulk-group/index.spec.js +41 -0
- package/src/chains/bulk-map/README.md +43 -0
- package/src/chains/bulk-map/index.examples.js +17 -0
- package/src/chains/bulk-map/index.js +86 -0
- package/src/chains/bulk-map/index.spec.js +44 -0
- package/src/chains/bulk-reduce/README.md +12 -0
- package/src/chains/bulk-reduce/index.examples.js +15 -0
- package/src/chains/bulk-reduce/index.js +13 -0
- package/src/chains/bulk-reduce/index.spec.js +25 -0
- package/src/chains/bulk-score/README.md +16 -0
- package/src/chains/bulk-score/bulk-score-result.json +18 -0
- package/src/chains/bulk-score/index.examples.js +22 -0
- package/src/chains/bulk-score/index.js +133 -0
- package/src/chains/bulk-score/index.spec.js +30 -0
- package/src/chains/category-samples/README.md +61 -0
- package/src/chains/category-samples/index.examples.js +103 -0
- package/src/chains/category-samples/index.js +134 -0
- package/src/chains/collect-terms/README.md +12 -0
- package/src/chains/collect-terms/index.examples.js +16 -0
- package/src/chains/collect-terms/index.js +44 -0
- package/src/chains/collect-terms/index.spec.js +25 -0
- package/src/chains/date/README.md +12 -0
- package/src/chains/date/index.examples.js +47 -0
- package/src/chains/date/index.js +74 -0
- package/src/chains/date/index.spec.js +62 -0
- package/src/chains/disambiguate/README.md +22 -0
- package/src/chains/disambiguate/disambiguate-meanings-result.json +16 -0
- package/src/chains/disambiguate/index.examples.js +18 -0
- package/src/chains/disambiguate/index.js +92 -0
- package/src/chains/disambiguate/index.spec.js +25 -0
- package/src/chains/dismantle/README.md +67 -0
- package/src/chains/dismantle/dismantle.examples.js +27 -0
- package/src/chains/dismantle/index.js +6 -17
- package/src/chains/dismantle/index.spec.js +1 -2
- package/src/chains/expect/README.md +171 -0
- package/src/chains/expect/index.examples.js +146 -0
- package/src/chains/expect/index.js +173 -0
- package/src/chains/expect/index.spec.js +324 -0
- package/src/chains/filter-ambiguous/README.md +11 -0
- package/src/chains/filter-ambiguous/index.examples.js +20 -0
- package/src/chains/filter-ambiguous/index.js +49 -0
- package/src/chains/filter-ambiguous/index.spec.js +31 -0
- package/src/chains/glossary/README.md +19 -0
- package/src/chains/glossary/index.examples.js +386 -0
- package/src/chains/glossary/index.js +75 -0
- package/src/chains/glossary/index.spec.js +19 -0
- package/src/chains/intersections/README.md +152 -0
- package/src/chains/intersections/index.examples.js +279 -0
- package/src/chains/intersections/index.js +366 -0
- package/src/chains/intersections/intersection-result.json +38 -0
- package/src/chains/list/index.examples.js +12 -16
- package/src/chains/list/index.js +106 -53
- package/src/chains/list/index.spec.js +8 -9
- package/src/chains/list/list-result.json +16 -0
- package/src/chains/llm-logger/README.md +208 -0
- package/src/chains/llm-logger/index.js +205 -0
- package/src/chains/llm-logger/index.spec.js +330 -0
- package/src/chains/questions/index.examples.js +2 -1
- package/src/chains/questions/index.js +14 -15
- package/src/chains/scan-js/index.js +6 -9
- package/src/chains/set-interval/README.md +81 -0
- package/src/chains/set-interval/index.examples.js +36 -0
- package/src/chains/set-interval/index.js +131 -0
- package/src/chains/set-interval/index.spec.js +70 -0
- package/src/chains/socratic/README.md +17 -0
- package/src/chains/socratic/index.js +64 -0
- package/src/chains/socratic/index.spec.js +24 -0
- package/src/chains/sort/index.examples.js +3 -7
- package/src/chains/sort/index.js +65 -15
- package/src/chains/sort/index.spec.js +5 -8
- package/src/chains/sort/sort-result.json +16 -0
- package/src/chains/summary-map/README.md +9 -1
- package/src/chains/summary-map/index.examples.js +9 -2
- package/src/chains/summary-map/index.js +43 -25
- package/src/chains/summary-map/index.spec.js +78 -3
- package/src/chains/test/index.js +9 -13
- package/src/chains/test-advice/index.js +4 -5
- package/src/chains/themes/README.md +20 -0
- package/src/chains/themes/index.examples.js +17 -0
- package/src/chains/themes/index.js +28 -0
- package/src/chains/themes/index.spec.js +19 -0
- package/src/chains/veiled-variants/index.examples.js +18 -0
- package/src/chains/veiled-variants/index.js +107 -0
- package/src/chains/veiled-variants/index.spec.js +40 -0
- package/src/constants/common.js +0 -2
- package/src/constants/models.js +172 -0
- package/src/index.js +178 -18
- package/src/json-schemas/README.md +13 -0
- package/src/json-schemas/index.js +8 -14
- package/src/json-schemas/schema-dot-org-photograph.json +11 -5
- package/src/json-schemas/schema-dot-org-place.json +78 -5
- package/src/lib/README.md +26 -0
- package/src/lib/bulk-filter/README.md +22 -0
- package/src/lib/bulk-filter/index.examples.js +27 -0
- package/src/lib/bulk-filter/index.js +63 -0
- package/src/lib/bulk-filter/index.spec.js +38 -0
- package/src/lib/bulk-find/README.md +18 -0
- package/src/lib/bulk-find/index.examples.js +19 -0
- package/src/lib/bulk-find/index.js +30 -0
- package/src/lib/bulk-find/index.spec.js +41 -0
- package/src/lib/chatgpt/index.js +63 -43
- package/src/lib/combinations/index.js +30 -0
- package/src/lib/combinations/index.spec.js +23 -0
- package/src/lib/functional/index.js +28 -0
- package/src/lib/logger-service/index.js +32 -0
- package/src/lib/parse-js-parts/index.js +9 -21
- package/src/lib/parse-llm-list/README.md +39 -0
- package/src/lib/parse-llm-list/index.js +54 -0
- package/src/lib/parse-llm-list/index.spec.js +59 -0
- package/src/lib/path-aliases/index.js +1 -3
- package/src/lib/path-aliases/index.spec.js +2 -8
- package/src/lib/pave/index.js +4 -4
- package/src/lib/pave/index.spec.js +6 -3
- package/src/lib/prompt-cache/index.js +14 -10
- package/src/lib/retry/index.js +11 -8
- package/src/lib/ring-buffer/README.md +460 -0
- package/src/lib/ring-buffer/index.js +1074 -0
- package/src/lib/search-best-first/city-walk.spec.js +37 -0
- package/src/lib/search-best-first/index.js +42 -11
- package/src/lib/search-best-first/index.spec.js +35 -0
- package/src/lib/search-js-files/index.js +44 -47
- package/src/lib/search-js-files/scan-file.js +10 -21
- package/src/lib/shorten-text/index.js +2 -7
- package/src/lib/shorten-text/index.spec.js +3 -3
- package/src/lib/strip-response/index.js +2 -7
- package/src/lib/template-replace/index.js +23 -0
- package/src/lib/template-replace/index.spec.js +60 -0
- package/src/lib/to-date/index.js +11 -0
- package/src/lib/to-number/index.js +1 -1
- package/src/lib/transcribe/index.js +26 -9
- package/src/prompts/README.md +3 -1
- package/src/prompts/as-object-with-schema.js +3 -8
- package/src/prompts/as-schema-org-text.js +10 -2
- package/src/prompts/code-features.js +1 -5
- package/src/prompts/constants.js +27 -27
- package/src/prompts/generate-collection.js +1 -1
- package/src/prompts/intent.js +16 -22
- package/src/prompts/select-from-threshold.js +1 -2
- package/src/prompts/sort.js +4 -8
- package/src/prompts/style.js +4 -7
- package/src/prompts/wrap-list.js +1 -4
- package/src/services/llm-model/global-overrides.spec.js +432 -0
- package/src/services/llm-model/index.js +234 -40
- package/src/services/llm-model/model.js +2 -2
- package/src/services/llm-model/negotiate.spec.js +447 -0
- package/src/services/redis/index.js +70 -7
- package/src/test/setup.js +20 -0
- package/src/verblets/README.md +26 -0
- package/src/verblets/auto/index.examples.js +12 -9
- package/src/verblets/auto/index.js +10 -10
- package/src/verblets/auto/index.spec.js +4 -6
- package/src/verblets/bool/README.md +36 -0
- package/src/verblets/bool/index.examples.js +53 -1
- package/src/verblets/bool/index.js +6 -9
- package/src/verblets/bool/index.spec.js +1 -3
- package/src/verblets/central-tendency/README.md +166 -0
- package/src/verblets/central-tendency/central-tendency-result.json +24 -0
- package/src/verblets/central-tendency/index.examples.js +196 -0
- package/src/verblets/central-tendency/index.js +171 -0
- package/src/verblets/central-tendency/index.spec.js +148 -0
- package/src/verblets/enum/index.examples.js +1 -4
- package/src/verblets/enum/index.js +7 -4
- package/src/verblets/expect/README.md +64 -0
- package/src/verblets/expect/index.examples.js +109 -0
- package/src/verblets/expect/index.js +75 -0
- package/src/verblets/expect/index.spec.js +127 -0
- package/src/verblets/intent/index.examples.js +95 -7
- package/src/verblets/intent/index.js +56 -68
- package/src/verblets/intersection/README.md +16 -0
- package/src/verblets/intersection/index.examples.js +89 -0
- package/src/verblets/intersection/index.js +84 -0
- package/src/verblets/intersection/index.spec.js +60 -0
- package/src/verblets/intersection/intersection-result.json +16 -0
- package/src/verblets/list-expand/README.md +10 -0
- package/src/verblets/list-expand/index.examples.js +14 -0
- package/src/verblets/list-expand/index.js +104 -0
- package/src/verblets/list-expand/index.spec.js +18 -0
- package/src/verblets/list-expand/list-expand-result.json +16 -0
- package/src/verblets/list-filter/README.md +22 -0
- package/src/verblets/list-filter/index.examples.js +26 -0
- package/src/verblets/list-filter/index.js +18 -0
- package/src/verblets/list-filter/index.spec.js +19 -0
- package/src/verblets/list-find/README.md +11 -0
- package/src/verblets/list-find/index.examples.js +15 -0
- package/src/verblets/list-find/index.js +17 -0
- package/src/verblets/list-find/index.spec.js +19 -0
- package/src/verblets/list-group/README.md +16 -0
- package/src/verblets/list-group/index.examples.js +16 -0
- package/src/verblets/list-group/index.js +112 -0
- package/src/verblets/list-group/index.spec.js +35 -0
- package/src/verblets/list-group/list-group-result.json +16 -0
- package/src/verblets/list-map/README.md +11 -0
- package/src/verblets/list-map/index.examples.js +15 -0
- package/src/verblets/list-map/index.js +26 -0
- package/src/verblets/list-map/index.spec.js +17 -0
- package/src/verblets/list-reduce/README.md +10 -0
- package/src/verblets/list-reduce/index.examples.js +14 -0
- package/src/verblets/list-reduce/index.js +21 -0
- package/src/verblets/list-reduce/index.spec.js +27 -0
- package/src/verblets/list-reduce/index.spec.jsx +27 -0
- package/src/verblets/name/README.md +15 -0
- package/src/verblets/name/index.examples.js +28 -0
- package/src/verblets/name/index.js +19 -0
- package/src/verblets/name/index.spec.js +33 -0
- package/src/verblets/name-similar-to/README.md +26 -0
- package/src/verblets/name-similar-to/index.examples.js +18 -0
- package/src/verblets/name-similar-to/index.js +20 -0
- package/src/verblets/name-similar-to/index.spec.js +13 -0
- package/src/verblets/number/index.examples.js +173 -7
- package/src/verblets/number/index.js +5 -2
- package/src/verblets/number/index.spec.js +1 -3
- package/src/verblets/number-with-units/index.examples.js +5 -1
- package/src/verblets/number-with-units/index.js +74 -9
- package/src/verblets/number-with-units/number-with-units-result.json +23 -0
- package/src/verblets/schema-org/index.examples.js +2 -7
- package/src/verblets/schema-org/index.js +32 -3
- package/src/verblets/sentiment/README.md +10 -0
- package/src/verblets/sentiment/index.examples.js +20 -0
- package/src/verblets/sentiment/index.js +9 -0
- package/src/verblets/sentiment/index.spec.js +20 -0
- package/src/verblets/to-object/index.js +10 -15
- package/src/verblets/to-object/index.spec.js +1 -4
- package/.eslintrc.json +0 -42
- package/docs/README.md +0 -41
- package/docs/babel.config.js +0 -3
- package/docs/blog/2019-05-28-first-blog-post.md +0 -12
- package/docs/blog/2019-05-29-long-blog-post.md +0 -44
- package/docs/blog/2021-08-01-mdx-blog-post.mdx +0 -20
- package/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs/blog/2021-08-26-welcome/index.md +0 -25
- package/docs/blog/authors.yml +0 -17
- package/docs/docs/api/bool.md +0 -74
- package/docs/docs/api/search.md +0 -51
- package/docs/docs/intro.md +0 -47
- package/docs/docs/tutorial-basics/_category_.json +0 -8
- package/docs/docs/tutorial-basics/congratulations.md +0 -23
- package/docs/docs/tutorial-basics/create-a-blog-post.md +0 -34
- package/docs/docs/tutorial-basics/create-a-document.md +0 -57
- package/docs/docs/tutorial-basics/create-a-page.md +0 -43
- package/docs/docs/tutorial-basics/deploy-your-site.md +0 -31
- package/docs/docs/tutorial-basics/markdown-features.mdx +0 -152
- package/docs/docs/tutorial-extras/_category_.json +0 -7
- 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 +0 -55
- package/docs/docs/tutorial-extras/translate-your-site.md +0 -88
- package/docs/docusaurus.config.js +0 -120
- package/docs/package.json +0 -44
- package/docs/sidebars.js +0 -31
- package/docs/src/components/HomepageFeatures/index.js +0 -61
- package/docs/src/components/HomepageFeatures/styles.module.css +0 -11
- package/docs/src/css/custom.css +0 -30
- package/docs/src/pages/index.js +0 -43
- package/docs/src/pages/index.module.css +0 -23
- package/docs/src/pages/markdown-page.md +0 -7
- 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 +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -171
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/src/constants/openai.js +0 -65
- /package/{.vite.config.examples.js → .vitest.config.examples.js} +0 -0
- /package/{.vite.config.js → .vitest.config.js} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import searchBestFirst from './index.js';
|
|
3
|
+
|
|
4
|
+
describe('searchBestFirst city walk example', () => {
|
|
5
|
+
it('plans a path across the city', async () => {
|
|
6
|
+
const graph = {
|
|
7
|
+
start: ['museum', 'park'],
|
|
8
|
+
museum: ['cafe', 'gallery'],
|
|
9
|
+
park: ['cafe', 'river'],
|
|
10
|
+
cafe: ['theater'],
|
|
11
|
+
gallery: ['theater'],
|
|
12
|
+
river: ['theater'],
|
|
13
|
+
theater: ['finish'],
|
|
14
|
+
finish: [],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const next = ({ node }) => graph[node] || [];
|
|
18
|
+
|
|
19
|
+
const rank = ({ nodes }) => [...nodes].sort(() => 0.5 - Math.random());
|
|
20
|
+
|
|
21
|
+
const visit = ({ node, state }) => ({ ...state, path: [...(state.path || []), node] });
|
|
22
|
+
|
|
23
|
+
const { path } = await searchBestFirst({
|
|
24
|
+
node: 'start',
|
|
25
|
+
next,
|
|
26
|
+
rank,
|
|
27
|
+
visit,
|
|
28
|
+
goal: ({ node }) => node === 'finish',
|
|
29
|
+
state: {},
|
|
30
|
+
returnPath: true,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(path.length).toBeGreaterThan(2);
|
|
34
|
+
expect(path[0]).toBe('start');
|
|
35
|
+
expect(path[path.length - 1]).toBe('finish');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -4,6 +4,10 @@ const hasOwnToString = (obj) => {
|
|
|
4
4
|
return obj.toString !== Object.prototype.toString;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
+
const keyFor = (obj) => {
|
|
8
|
+
return hasOwnToString(obj) ? obj.toString() : obj;
|
|
9
|
+
};
|
|
10
|
+
|
|
7
11
|
const visitDefault = () => {
|
|
8
12
|
return Promise.reject(new Error('Not Implemented'));
|
|
9
13
|
};
|
|
@@ -17,9 +21,7 @@ const rankDefault = () => {
|
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
const filterWith = (state) => (nextNode) => {
|
|
20
|
-
return !state.visited.has(
|
|
21
|
-
hasOwnToString(nextNode) ? nextNode.toString() : nextNode
|
|
22
|
-
);
|
|
24
|
+
return !state.visited.has(keyFor(nextNode));
|
|
23
25
|
};
|
|
24
26
|
|
|
25
27
|
export default async ({
|
|
@@ -28,39 +30,68 @@ export default async ({
|
|
|
28
30
|
rank = rankDefault,
|
|
29
31
|
state: stateInitial = {},
|
|
30
32
|
visit = visitDefault,
|
|
33
|
+
goal = () => false,
|
|
34
|
+
returnPath = false,
|
|
31
35
|
}) => {
|
|
32
36
|
let nodesTodo = [rootNode];
|
|
37
|
+
const parents = new Map();
|
|
33
38
|
let state = stateInitial;
|
|
34
39
|
if (!state.visited) {
|
|
35
40
|
state.visited = new Set();
|
|
36
41
|
}
|
|
42
|
+
parents.set(keyFor(rootNode), null);
|
|
43
|
+
let lastNode = rootNode;
|
|
37
44
|
|
|
38
45
|
while (nodesTodo.length > 0) {
|
|
39
46
|
// eslint-disable-next-line no-await-in-loop
|
|
40
47
|
const nodesRanked = await rank({ nodes: nodesTodo, state });
|
|
41
48
|
const node = nodesRanked.shift();
|
|
49
|
+
lastNode = node;
|
|
42
50
|
|
|
43
|
-
const nodesTodoNext = nodesTodo.filter((el) =>
|
|
44
|
-
hasOwnToString(node) ? el.toString() !== node.toString() : el !== node
|
|
45
|
-
);
|
|
51
|
+
const nodesTodoNext = nodesTodo.filter((el) => keyFor(el) !== keyFor(node));
|
|
46
52
|
|
|
47
|
-
state.visited.add(
|
|
53
|
+
state.visited.add(keyFor(node));
|
|
48
54
|
|
|
49
55
|
// eslint-disable-next-line no-await-in-loop
|
|
50
56
|
state = await visit({ node, state });
|
|
51
57
|
|
|
58
|
+
if (goal({ node, state })) {
|
|
59
|
+
if (returnPath) {
|
|
60
|
+
const path = [];
|
|
61
|
+
for (let cur = node; cur !== null; ) {
|
|
62
|
+
path.unshift(cur);
|
|
63
|
+
cur = parents.get(keyFor(cur));
|
|
64
|
+
}
|
|
65
|
+
return { state, path };
|
|
66
|
+
}
|
|
67
|
+
return state;
|
|
68
|
+
}
|
|
69
|
+
|
|
52
70
|
// eslint-disable-next-line no-await-in-loop
|
|
53
71
|
const nextNodes = await next({ node, state });
|
|
54
72
|
|
|
73
|
+
nextNodes.filter(filterWith(state)).forEach((nextNode) => {
|
|
74
|
+
const key = keyFor(nextNode);
|
|
75
|
+
if (!parents.has(key)) {
|
|
76
|
+
parents.set(key, node);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
55
80
|
nodesTodo = R.unionWith(
|
|
56
|
-
(nodeA, nodeB) =>
|
|
57
|
-
hasOwnToString(nodeA)
|
|
58
|
-
? nodeA.toString() === nodeB.toString()
|
|
59
|
-
: nodeA === nodeB,
|
|
81
|
+
(nodeA, nodeB) => keyFor(nodeA) === keyFor(nodeB),
|
|
60
82
|
nodesTodoNext,
|
|
61
83
|
nextNodes.filter(filterWith(state))
|
|
62
84
|
);
|
|
63
85
|
}
|
|
64
86
|
|
|
87
|
+
if (returnPath) {
|
|
88
|
+
const path = [];
|
|
89
|
+
for (let cur = lastNode; cur !== null; ) {
|
|
90
|
+
path.unshift(cur);
|
|
91
|
+
cur = parents.get(keyFor(cur));
|
|
92
|
+
}
|
|
93
|
+
return { state, path: path.length ? path : null };
|
|
94
|
+
}
|
|
95
|
+
|
|
65
96
|
return state;
|
|
66
97
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import search from './index.js';
|
|
3
|
+
|
|
4
|
+
describe('search-best-first', () => {
|
|
5
|
+
it('returns path to goal', async () => {
|
|
6
|
+
const result = await search({
|
|
7
|
+
node: 0,
|
|
8
|
+
next: ({ node }) => [node + 1],
|
|
9
|
+
rank: ({ nodes }) => nodes,
|
|
10
|
+
visit: ({ node, state }) => ({ ...state, sum: (state.sum || 0) + node }),
|
|
11
|
+
goal: ({ node }) => node >= 3,
|
|
12
|
+
state: {},
|
|
13
|
+
returnPath: true,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(result.state.sum).toBe(6); // 0 + 1 + 2 + 3
|
|
17
|
+
expect(result.path).toEqual([0, 1, 2, 3]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('handles missing goal', async () => {
|
|
21
|
+
const result = await search({
|
|
22
|
+
node: 0,
|
|
23
|
+
next: ({ node }) => (node < 2 ? [node + 1] : []),
|
|
24
|
+
rank: ({ nodes }) => nodes,
|
|
25
|
+
// eslint-disable-next-line no-unused-vars
|
|
26
|
+
visit: ({ node, state }) => ({ ...state, count: (state.count || 0) + 1 }),
|
|
27
|
+
goal: ({ node }) => node === 5,
|
|
28
|
+
state: {},
|
|
29
|
+
returnPath: true,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
expect(result.state.count).toBe(3);
|
|
33
|
+
expect(result.path).toEqual([0, 1, 2]);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import path from 'node:path';
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
4
3
|
|
|
5
4
|
import parseJSParts from '../parse-js-parts/index.js';
|
|
6
5
|
import search from '../search-best-first/index.js';
|
|
@@ -11,54 +10,59 @@ export class Node {
|
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
toString() {
|
|
14
|
-
return `${this.filename}
|
|
13
|
+
return `${this.filename}:${this.functionName}`;
|
|
15
14
|
}
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
const processLocalImport = async (source) => {
|
|
19
|
-
const importedFile = await fs.readFile(source, '
|
|
18
|
+
const importedFile = await fs.readFile(source, 'utf-8');
|
|
20
19
|
const parsedImport = parseJSParts(source, importedFile);
|
|
21
|
-
return Object.entries(parsedImport.functionsMap).map(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
})
|
|
27
|
-
);
|
|
20
|
+
return Object.entries(parsedImport.functionsMap).map(([importKey, importValue]) => ({
|
|
21
|
+
filename: source,
|
|
22
|
+
functionName: importValue?.functionName ?? importKey,
|
|
23
|
+
functionData: importValue,
|
|
24
|
+
}));
|
|
28
25
|
};
|
|
29
26
|
|
|
30
27
|
const processNpmImport = async (source, includeNodeModules = false) => {
|
|
31
28
|
if (!includeNodeModules) return [];
|
|
32
29
|
|
|
33
30
|
try {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
31
|
+
// Find the project root by looking for package.json
|
|
32
|
+
let currentDir = process.cwd();
|
|
33
|
+
let packageJsonPath = path.join(currentDir, 'package.json');
|
|
34
|
+
|
|
35
|
+
// If not found in current directory, try to find it in parent directories
|
|
36
|
+
while (
|
|
37
|
+
!(await fs
|
|
38
|
+
.access(packageJsonPath)
|
|
39
|
+
.then(() => true)
|
|
40
|
+
.catch(() => false))
|
|
38
41
|
) {
|
|
39
|
-
const
|
|
42
|
+
const parentDir = path.dirname(currentDir);
|
|
43
|
+
if (parentDir === currentDir) break; // Reached filesystem root
|
|
44
|
+
currentDir = parentDir;
|
|
45
|
+
packageJsonPath = path.join(currentDir, 'package.json');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
49
|
+
if (packageJson.dependencies[source] || packageJson.devDependencies[source]) {
|
|
50
|
+
const nodeModulePath = path.join(currentDir, 'node_modules', source);
|
|
40
51
|
const npmPackageJson = JSON.parse(
|
|
41
|
-
await fs.readFile(
|
|
52
|
+
await fs.readFile(path.join(nodeModulePath, 'package.json'), 'utf8')
|
|
42
53
|
);
|
|
43
54
|
const mainFilePath = npmPackageJson.main || 'index.js';
|
|
44
|
-
const importedFile = await fs.readFile(
|
|
45
|
-
`${nodeModulePath}/${mainFilePath}`,
|
|
46
|
-
'utf-8'
|
|
47
|
-
);
|
|
55
|
+
const importedFile = await fs.readFile(path.join(nodeModulePath, mainFilePath), 'utf-8');
|
|
48
56
|
const parsedImport = parseJSParts(mainFilePath, importedFile);
|
|
49
57
|
|
|
50
|
-
return Object.entries(parsedImport.functionsMap).map(
|
|
51
|
-
(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
})
|
|
56
|
-
);
|
|
58
|
+
return Object.entries(parsedImport.functionsMap).map(([importKey, importValue]) => ({
|
|
59
|
+
filename: path.join(nodeModulePath, mainFilePath),
|
|
60
|
+
functionName: importKey,
|
|
61
|
+
functionData: importValue,
|
|
62
|
+
}));
|
|
57
63
|
}
|
|
58
64
|
} catch (error) {
|
|
59
|
-
console.error(
|
|
60
|
-
`Process npm import [error]: ${error.message} (source: ${source})`
|
|
61
|
-
);
|
|
65
|
+
console.error(`Process npm import [error]: ${error.message} (source: ${source})`);
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
return [];
|
|
@@ -74,9 +78,7 @@ const visitDefault = ({ state }) => {
|
|
|
74
78
|
const rank = ({ nodes }) => {
|
|
75
79
|
// Example: Rank by the length of the function name
|
|
76
80
|
return nodes.sort(
|
|
77
|
-
(a, b) =>
|
|
78
|
-
(a.functionName ?? a.filename).length -
|
|
79
|
-
(b.functionName ?? b.filename).length
|
|
81
|
+
(a, b) => (a.functionName ?? a.filename).length - (b.functionName ?? b.filename).length
|
|
80
82
|
);
|
|
81
83
|
};
|
|
82
84
|
|
|
@@ -84,14 +86,12 @@ const prepareNext = async ({ node, includeNodeModules }) => {
|
|
|
84
86
|
const code = await fs.readFile(node.filename, 'utf-8');
|
|
85
87
|
const parsed = parseJSParts(node.filename, code);
|
|
86
88
|
|
|
87
|
-
const functionsFound = Object.entries(parsed.functionsMap).map(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
);
|
|
89
|
+
const functionsFound = Object.entries(parsed.functionsMap).map(([, value]) => {
|
|
90
|
+
return new Node({
|
|
91
|
+
...value,
|
|
92
|
+
filename: node.filename,
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
95
|
|
|
96
96
|
const importPromises = Object.values(parsed.importsMap).map((importData) => {
|
|
97
97
|
if (
|
|
@@ -99,10 +99,7 @@ const prepareNext = async ({ node, includeNodeModules }) => {
|
|
|
99
99
|
importData.source.startsWith('../') ||
|
|
100
100
|
importData.source.startsWith('/')
|
|
101
101
|
) {
|
|
102
|
-
const resolvedPath = path.resolve(
|
|
103
|
-
path.dirname(node.filename),
|
|
104
|
-
importData.source
|
|
105
|
-
);
|
|
102
|
+
const resolvedPath = path.resolve(path.dirname(node.filename), importData.source);
|
|
106
103
|
|
|
107
104
|
return processLocalImport(resolvedPath);
|
|
108
105
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-await-in-loop */
|
|
2
|
-
|
|
3
1
|
import path from 'path';
|
|
4
2
|
import fs from 'fs';
|
|
5
3
|
import { parse } from 'acorn';
|
|
@@ -26,15 +24,12 @@ const flatten = (obj) => {
|
|
|
26
24
|
result = Object.keys(obj).reduce((acc, key) => {
|
|
27
25
|
if (typeof obj[key] === 'object') {
|
|
28
26
|
const flattenedValue = flatten(obj[key]);
|
|
29
|
-
return Object.entries(flattenedValue).reduce(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
acc
|
|
37
|
-
);
|
|
27
|
+
return Object.entries(flattenedValue).reduce((innerAcc, [innerKey, innerVal]) => {
|
|
28
|
+
return {
|
|
29
|
+
...innerAcc,
|
|
30
|
+
[innerKey]: (innerAcc[innerKey] ?? 0) + innerVal,
|
|
31
|
+
};
|
|
32
|
+
}, acc);
|
|
38
33
|
}
|
|
39
34
|
return acc;
|
|
40
35
|
}, result);
|
|
@@ -96,9 +91,7 @@ const parseFiles = (files) => {
|
|
|
96
91
|
return { ...s.imported }.name; // also has local name
|
|
97
92
|
});
|
|
98
93
|
const source = node.source.value;
|
|
99
|
-
const importKey = source.startsWith('.')
|
|
100
|
-
? convertImport(file, source)
|
|
101
|
-
: source;
|
|
94
|
+
const importKey = source.startsWith('.') ? convertImport(file, source) : source;
|
|
102
95
|
importsMap[importKey] = {
|
|
103
96
|
start: node.start,
|
|
104
97
|
end: node.end,
|
|
@@ -207,16 +200,12 @@ const parseFiles = (files) => {
|
|
|
207
200
|
const className = node.id.name;
|
|
208
201
|
node.body.body.forEach((classElement) => {
|
|
209
202
|
if (classElement.type === 'MethodDefinition') {
|
|
210
|
-
functionsSeen[
|
|
211
|
-
`${classElement.value.start}:${classElement.value.end}`
|
|
212
|
-
] = true;
|
|
203
|
+
functionsSeen[`${classElement.value.start}:${classElement.value.end}`] = true;
|
|
213
204
|
|
|
214
|
-
functionsMap[
|
|
215
|
-
`MethodDefinition:${className}.${classElement.key.name}`
|
|
216
|
-
] = {
|
|
205
|
+
functionsMap[`MethodDefinition:${className}.${classElement.key.name}`] = {
|
|
217
206
|
start: node.start,
|
|
218
207
|
end: node.end,
|
|
219
|
-
className
|
|
208
|
+
className,
|
|
220
209
|
name: classElement.key.name,
|
|
221
210
|
async: classElement.value.async,
|
|
222
211
|
generator: classElement.value.generator,
|
|
@@ -2,11 +2,7 @@ import modelService from '../../services/llm-model/index.js';
|
|
|
2
2
|
|
|
3
3
|
export default (
|
|
4
4
|
text,
|
|
5
|
-
{
|
|
6
|
-
minCharsToRemove = 10,
|
|
7
|
-
model = modelService.getBestAvailableModel(),
|
|
8
|
-
targetTokenCount,
|
|
9
|
-
}
|
|
5
|
+
{ minCharsToRemove = 10, model = modelService.getBestPublicModel(), targetTokenCount }
|
|
10
6
|
) => {
|
|
11
7
|
const ellipsis = '...';
|
|
12
8
|
const textToTokenRatio = text.length / model.toTokens(text).length;
|
|
@@ -21,8 +17,7 @@ export default (
|
|
|
21
17
|
const middleIndex = Math.floor(trimmedText.length / 2);
|
|
22
18
|
const startIndex = middleIndex - Math.ceil(charsToRemove / 2);
|
|
23
19
|
const endIndex = middleIndex + Math.floor(charsToRemove / 2);
|
|
24
|
-
trimmedText =
|
|
25
|
-
trimmedText.slice(0, startIndex) + ellipsis + trimmedText.slice(endIndex);
|
|
20
|
+
trimmedText = trimmedText.slice(0, startIndex) + ellipsis + trimmedText.slice(endIndex);
|
|
26
21
|
tokenCount = model.toTokens(trimmedText).length;
|
|
27
22
|
}
|
|
28
23
|
|
|
@@ -59,9 +59,9 @@ describe('Shorten text', () => {
|
|
|
59
59
|
expect(example.want.end.test(got)).toBe(true);
|
|
60
60
|
}
|
|
61
61
|
if (example.want.maxLength) {
|
|
62
|
-
expect(
|
|
63
|
-
|
|
64
|
-
)
|
|
62
|
+
expect(modelService.getBestPublicModel().toTokens(got).length).toBeLessThanOrEqual(
|
|
63
|
+
example.want.maxLength
|
|
64
|
+
);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
67
|
});
|
|
@@ -11,18 +11,13 @@ export default (val) => {
|
|
|
11
11
|
|
|
12
12
|
const answerPartTrimmed = answerPart.trim() ?? '';
|
|
13
13
|
|
|
14
|
-
const answerSection = answerPartTrimmed.length
|
|
15
|
-
? answerPart.trim()
|
|
16
|
-
: questionPart.trim();
|
|
14
|
+
const answerSection = answerPartTrimmed.length ? answerPart.trim() : questionPart.trim();
|
|
17
15
|
|
|
18
16
|
const answerNoPrefix = answerSection.replace(/[aA]nswer:?/, '').trim();
|
|
19
17
|
|
|
20
18
|
const answerNoPunctuation = answerNoPrefix.replace(/[., ]+$/g, '').trim();
|
|
21
19
|
|
|
22
|
-
const answerNoQuotes = answerNoPunctuation
|
|
23
|
-
.replace(/^['"]/, '')
|
|
24
|
-
.replace(/['"]$/, '')
|
|
25
|
-
.trim();
|
|
20
|
+
const answerNoQuotes = answerNoPunctuation.replace(/^['"]/, '').replace(/['"]$/, '').trim();
|
|
26
21
|
|
|
27
22
|
if (answerNoQuotes.startsWith('{') || answerNoQuotes.startsWith('[')) {
|
|
28
23
|
return answerNoQuotes;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple template replacement utility
|
|
3
|
+
* Replaces {key} placeholders with values from data object
|
|
4
|
+
*
|
|
5
|
+
* @param {string} template - Template string with {key} placeholders
|
|
6
|
+
* @param {object} data - Data object with key-value pairs
|
|
7
|
+
* @returns {string} - Template with placeholders replaced
|
|
8
|
+
*/
|
|
9
|
+
export default function templateReplace(template, data) {
|
|
10
|
+
if (!template || typeof template !== 'string') {
|
|
11
|
+
return template || '';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (data === undefined || data === null || typeof data !== 'object') {
|
|
15
|
+
return template;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Replace all {key} placeholders
|
|
19
|
+
return template.replace(/\{([^}]+)\}/g, (match, key) => {
|
|
20
|
+
const value = data[key];
|
|
21
|
+
return String(value != null ? value : '');
|
|
22
|
+
});
|
|
23
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import templateReplace from './index.js';
|
|
3
|
+
|
|
4
|
+
describe('templateReplace', () => {
|
|
5
|
+
it('replaces single placeholder', () => {
|
|
6
|
+
const result = templateReplace('Hello {name}!', { name: 'World' });
|
|
7
|
+
expect(result).toBe('Hello World!');
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('replaces multiple placeholders', () => {
|
|
11
|
+
const result = templateReplace('Hello {name}, you are {age} years old', {
|
|
12
|
+
name: 'John',
|
|
13
|
+
age: 30,
|
|
14
|
+
});
|
|
15
|
+
expect(result).toBe('Hello John, you are 30 years old');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('replaces multiple instances of same placeholder', () => {
|
|
19
|
+
const result = templateReplace('{name} said "{name} is great"', { name: 'Alice' });
|
|
20
|
+
expect(result).toBe('Alice said "Alice is great"');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('handles missing data gracefully', () => {
|
|
24
|
+
const result = templateReplace('Hello {name}!', {});
|
|
25
|
+
expect(result).toBe('Hello !');
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('handles null/undefined values', () => {
|
|
29
|
+
const result = templateReplace('Value: {value}', { value: null });
|
|
30
|
+
expect(result).toBe('Value: ');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('handles non-string values', () => {
|
|
34
|
+
const result = templateReplace('Count: {count}, Active: {active}', {
|
|
35
|
+
count: 42,
|
|
36
|
+
active: true,
|
|
37
|
+
});
|
|
38
|
+
expect(result).toBe('Count: 42, Active: true');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('returns original template when no data provided', () => {
|
|
42
|
+
const result = templateReplace('Hello {name}!');
|
|
43
|
+
expect(result).toBe('Hello {name}!');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('returns original template when data is not an object', () => {
|
|
47
|
+
const result = templateReplace('Hello {name}!', 'not an object');
|
|
48
|
+
expect(result).toBe('Hello {name}!');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('handles empty template', () => {
|
|
52
|
+
const result = templateReplace('', { name: 'test' });
|
|
53
|
+
expect(result).toBe('');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('handles template with no placeholders', () => {
|
|
57
|
+
const result = templateReplace('Just plain text', { name: 'test' });
|
|
58
|
+
expect(result).toBe('Just plain text');
|
|
59
|
+
});
|
|
60
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import stripResponse from '../strip-response/index.js';
|
|
2
|
+
|
|
3
|
+
export default (val) => {
|
|
4
|
+
const clean = stripResponse(String(val)).trim();
|
|
5
|
+
if (clean.toLowerCase() === 'undefined') return undefined;
|
|
6
|
+
const parsed = new Date(clean);
|
|
7
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
8
|
+
throw new Error('ChatGPT output [error]');
|
|
9
|
+
}
|
|
10
|
+
return parsed;
|
|
11
|
+
};
|
|
@@ -6,7 +6,7 @@ export default (val) => {
|
|
|
6
6
|
if (valLower === 'undefined') return undefined;
|
|
7
7
|
const valParsed = +stripNumeric(val);
|
|
8
8
|
if (Number.isNaN(valParsed)) {
|
|
9
|
-
throw new Error(
|
|
9
|
+
throw new Error('ChatGPT output [error]');
|
|
10
10
|
}
|
|
11
11
|
return valParsed;
|
|
12
12
|
};
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
import whisper
|
|
2
|
-
|
|
1
|
+
// Lazy import whisper to avoid initialization issues
|
|
2
|
+
let whisper;
|
|
3
|
+
let record;
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
async function getWhisper() {
|
|
6
|
+
if (!whisper) {
|
|
7
|
+
whisper = (await import('whisper-node')).default;
|
|
8
|
+
}
|
|
9
|
+
return whisper;
|
|
10
|
+
}
|
|
5
11
|
|
|
12
|
+
async function getRecord() {
|
|
13
|
+
if (!record) {
|
|
14
|
+
record = (await import('node-record-lpcm16')).default;
|
|
15
|
+
}
|
|
16
|
+
return record;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default class Transcriber {
|
|
6
20
|
constructor(targetWord, silenceDuration = 5000, wordPauseDuration = 2000) {
|
|
7
21
|
this.targetWord = targetWord;
|
|
8
22
|
this.silenceDuration = silenceDuration;
|
|
@@ -12,8 +26,9 @@ export default class Transcriber {
|
|
|
12
26
|
this.recording = null;
|
|
13
27
|
}
|
|
14
28
|
|
|
15
|
-
startRecording() {
|
|
16
|
-
|
|
29
|
+
async startRecording() {
|
|
30
|
+
const recordModule = await getRecord();
|
|
31
|
+
this.recording = recordModule.record({
|
|
17
32
|
sampleRateHertz: 16000,
|
|
18
33
|
threshold: 0,
|
|
19
34
|
recordProgram: 'rec',
|
|
@@ -30,12 +45,14 @@ export default class Transcriber {
|
|
|
30
45
|
}
|
|
31
46
|
}
|
|
32
47
|
|
|
33
|
-
transcribe(stream) {
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
async transcribe(stream) {
|
|
49
|
+
const whisperModule = await getWhisper();
|
|
50
|
+
whisperModule
|
|
51
|
+
.transcribeStream(stream, { streaming: true })
|
|
52
|
+
.then((transcription) => {
|
|
36
53
|
this.handleTranscription(transcription);
|
|
37
54
|
})
|
|
38
|
-
.catch(error => {
|
|
55
|
+
.catch((error) => {
|
|
39
56
|
console.error(error);
|
|
40
57
|
});
|
|
41
58
|
}
|
package/src/prompts/README.md
CHANGED
|
@@ -12,4 +12,6 @@ The functions can generate HTML from their inputs and this structure can be tran
|
|
|
12
12
|
|
|
13
13
|
# Constants
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
The text snippets used by many prompt functions are collected in
|
|
16
|
+
[`constants.js`](./constants.js). As the set of fragments grows it may make sense
|
|
17
|
+
to manage them with a CMS such as Strapi.
|
|
@@ -13,15 +13,10 @@ export default (jsonSchema = jsonSchemaDefault) => {
|
|
|
13
13
|
const propertiesJoined = Object.entries(jsonSchema.properties)
|
|
14
14
|
.map(([key, val]) => {
|
|
15
15
|
const annotations = Object.entries(val).filter(
|
|
16
|
-
([annKey, annVal]) =>
|
|
17
|
-
['format', 'description'].includes(annKey) && !!annVal
|
|
16
|
+
([annKey, annVal]) => ['format', 'description'].includes(annKey) && !!annVal
|
|
18
17
|
);
|
|
19
|
-
const annotationsFormatted = annotations
|
|
20
|
-
|
|
21
|
-
.join(', ');
|
|
22
|
-
const annotationsWrapped = annotations.length
|
|
23
|
-
? ` (${annotationsFormatted})`
|
|
24
|
-
: '';
|
|
18
|
+
const annotationsFormatted = annotations.map(([k, v]) => `${k}: ${v}`).join(', ');
|
|
19
|
+
const annotationsWrapped = annotations.length ? ` (${annotationsFormatted})` : '';
|
|
25
20
|
return `"${key}": "<${val.type ?? ''}${annotationsWrapped}>"`;
|
|
26
21
|
})
|
|
27
22
|
.join(', ');
|
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
import { onlyJSON } from './constants.js';
|
|
1
|
+
import { contentIsSchema, onlyJSON } from './constants.js';
|
|
2
2
|
import asSchemaOrgType from './as-schema-org-type.js';
|
|
3
|
+
import wrapVariable from './wrap-variable.js';
|
|
3
4
|
|
|
4
5
|
const ensureNumbers = 'ensure values meant to be numbers are numbers';
|
|
5
6
|
const ensureSchemaOrgType = 'ensure the type is a real schema.org type';
|
|
6
7
|
const ensureProperties = 'ensure the returned object has @context, name';
|
|
7
8
|
|
|
8
|
-
export default (object, type) => {
|
|
9
|
+
export default (object, type, schema) => {
|
|
9
10
|
const typeText = `${asSchemaOrgType(type)}`;
|
|
11
|
+
const schemaText = schema
|
|
12
|
+
? `\n${contentIsSchema} ${wrapVariable(JSON.stringify(schema), {
|
|
13
|
+
tag: 'schema',
|
|
14
|
+
})}`
|
|
15
|
+
: '';
|
|
16
|
+
|
|
10
17
|
return `Give me "${object}" in schema.org JSON format with a full set of properties. ${
|
|
11
18
|
typeText ? `${typeText}.` : ''
|
|
12
19
|
}
|
|
13
20
|
- ${ensureNumbers}
|
|
14
21
|
- ${ensureSchemaOrgType}
|
|
15
22
|
- ${ensureProperties}
|
|
23
|
+
${schemaText}
|
|
16
24
|
${onlyJSON}`;
|
|
17
25
|
};
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
asJSON,
|
|
3
|
-
explainAndSeparate,
|
|
4
|
-
explainAndSeparateJSON,
|
|
5
|
-
} from './constants.js';
|
|
1
|
+
import { asJSON, explainAndSeparate, explainAndSeparateJSON } from './constants.js';
|
|
6
2
|
|
|
7
3
|
export default ({ text, schema }) => {
|
|
8
4
|
return `Analyze the following code to provide scores for each of the features described below.
|