howtos:references :)

This commit is contained in:
lovebird 2025-03-28 06:01:51 +01:00
parent 28e3524297
commit bb65829605
9 changed files with 77 additions and 62 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-03-27T19:36:46.952Z"
"default": "2025-03-28T05:01:22.032Z"
},
"description": {
"type": "string",

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
"messages": [
{
"role": "user",
"content": "Extract the required tools, software hardware from the following tutorial. Return as Markdown chapters (H3) with very short bullet points (not bold), with links, max. 5.\n\nText to process:\nCreate an adaptable sorting system. If you have a larger quantity of a certain type of material, simply adjust the dividers to accommodate your needs.\n\n\nUser Location: Lisbon, Portugal\n\nIn this step, you may send the provided files for cutting on a CNC or laser cutting machine. Note that these files are designed for a material thickness of 25 mm (1 inch). If you alter this measurement, ensure the file is adjusted accordingly. We only cut the outline on the machine, but you may also use it for bevels and number engravings.\n\nAfter cutting all the panels, use the files with numbers to laser cut them. Ensure proper alignment as each divider panel is numbered on both sides. Align from the top highest corner for best results.\n\nIn this step, cut the front, bottom, and back panels. Additionally, begin finishing all parts and sanding them for a smooth surface.\n\nAfter sanding all parts, assemble them using screws. Begin by attaching the sides and the bottom, then fit the dividers according to your requirements.\n\nYou can now organize your plastic with greater ease."
"content": "Return a list of useful references (only with links), as Markdown, grouped : Articles, Books, Papers, Youtube, Opensource Designs, ... Dont comment !\n\nText to process:\nIn this tutorial, I will guide you through the process of cutting HDPE sheets using an X-Carve CNC.\n\nThis video is available in Spanish with subtitles: [Watch here](https://www.youtube.com/watch?v=4LrrFz802To).\n\n\nUser Location: Mexico City, Mexico\n\nFor this step, we need to measure our plastic sheet: Height, Width, and Thickness. Our X-Carve machine operates with the CAM Software EASEL, which is user-friendly software for CNC milling.\n\nEasel offers the ability to \"simulate\" your actual material, and even includes HDPE 2-Colors in their cutting material lists.\n\nUtilize the CNC clamps from the X-Carve to securely fasten the sheet to the table.\n\nProceed to use a vector graphics editor like Inkscape to design or obtain a vector file. \n\nDownload the SVG file and import it into Easel.\n\nUpon preparing the file, select the desired width for carving or cutting. Proceed to initiate the cutting process with the following steps:\n\n- Ensure the sheet is securely fixed.\n- Specify the cutting bit; in this case, use a 1/8 inch (3.18 mm) flat flute bit.\n- Set the machine's coordinate origin at the lower-left corner.\n- Raise the bit and activate the CNC Router.\n\nLet the process commence, and witness the craftsmanship unfold!\n\nTake your glasses or object and proceed with post-processing, then present it to friends and family.\n\nYou can attempt this project using various types of CNC machines, including manual routers or saws, as demonstrated in this video: [youtu.be/gxkcffQD3eQ](https://youtu.be/gxkcffQD3eQ). It is important to share your experiences and contribute to the community's development.\n\nShare your ideas and comments!"
},
{
"role": "user",

22
bom.md Normal file
View File

@ -0,0 +1,22 @@
Here's a comparative overview of open-source SBOM tools presented in a Markdown table format:
## Open Source SBOM Tools Comparison
| Tool Name | Supported Formats | Key Features | Source Link |
|----------------------------|-------------------------|-----------------------------------------------------------------------------|-----------------------------------------------------------------------------|
| **Syft** | SPDX, CycloneDX, Syft | CLI tool for container/image analysis, supports multiple Linux distros | [GitHub](https://github.com/anchore/syft) [6][14] |
| **Microsoft SBOM Tool** | SPDX 2.2 | Enterprise-ready, Docker image support, component detection library | [GitHub](https://github.com/microsoft/sbom-tool) [2][3][6] |
| **Dependency-Track** | CycloneDX | Vulnerability visualization, component analysis platform | [GitHub](https://github.com/DependencyTrack/dependency-track) [2] |
| **CycloneDX Generator** | CycloneDX | Multi-language support, API server integration, dependency tree analysis | [GitHub](https://github.com/CycloneDX/cdxgen) [6][12] |
| **SPDX SBOM Generator** | SPDX | Supports 15+ package managers, CLI interface | [GitHub](https://github.com/spdx/spdx-sbom-generator) [6] |
| **DISTRO2SBOM** | SPDX, CycloneDX | Linux package detection, OS-agnostic analysis | [GitHub](https://github.com/ossie-git/DISTRO2SBOM) [6] |
| **Tern** | SPDX, CycloneDX, YAML | Container layer analysis, license compliance focus | [GitHub](https://github.com/tern-tools/tern) [6] |
| **IBM SBOM Utility** | CycloneDX, SPDX | Validation against JSON schemas, license policy management | [GitHub](https://github.com/IBM/sbom-utility) [9][11] |
Key technical differentiators:
- **Format specialization**: Syft and cdxgen offer multi-format support[6][14][12], while Microsoft's tool focuses exclusively on SPDX[3][6]
- **Containerization**: Syft and Tern specialize in container/image analysis[6][14]
- **Language support**: CycloneDX Generator supports 30+ programming languages[6][12]
- **Enterprise features**: IBM's utility offers schema validation and policy management[9][11], Microsoft's tool integrates with build pipelines[6]
For developers working with TypeScript ecosystems, Syft and SPDX SBOM Generator offer native npm/yarn support[6][14], while the IBM utility provides API integration capabilities[11] that could complement CI/CD pipelines.

View File

@ -23,7 +23,9 @@ import {
HOWTO_COMPLETE_RESOURCES,
HOWTO_COMPLETE_SKILLS,
HOWTO_ADD_HARDWARE,
HOWTO_LOCAL_RESOURCES
HOWTO_LOCAL_RESOURCES,
HOWTO_ADD_RESOURCES,
HOWTO_ADD_REFERENCES,
} from "config/config.js";
import { filter } from "@/base/kbot.js";
@ -38,9 +40,12 @@ model_files = model_files.map((f) =>
forward_slash(`${howto.slug}/${path.relative(path.resolve(howto_abs), f)}`),
);
const content = async (str: string) => await translate(str,I18N_SOURCE_LANGUAGE, Astro.currentLocale)
const component = async (str: string) => await createMarkdownComponent(await content(str));
const componentHTML = async (str: string) => await createHTMLComponent(await content(str));
const content = async (str: string) =>
await translate(str, I18N_SOURCE_LANGUAGE, Astro.currentLocale);
const component = async (str: string) =>
await createMarkdownComponent(await content(str));
const componentHTML = async (str: string) =>
await createHTMLComponent(await content(str));
const stepsWithFilteredMarkdown = await pMap(
howto.steps,
@ -61,7 +66,7 @@ const authorLinks = (howto?.user?.data.urls || []).filter(
(l) => !l.url.includes("one_army") && !l.url.includes("bazar"),
);
//////////////////////////////////////////////////////////////
//
//
// Resources
//
//////////////////////////////////////////////////////////////
@ -72,28 +77,28 @@ let howto_resources = exists(howto_resources_path)
? read(howto_resources_path, "string") || howto_resources_default
: howto_resources_default;
const contentAll = `${howto.content}`;
if (HOWTO_COMPLETE_RESOURCES) {
const keywords = (await filter(contentAll,'keywords')) as string;
const references_extra = await filter(keywords,'references');
howto_resources = `${howto_resources}\n${references_extra}`;
}
const howto_references_default = `# References`;
const howto_references_path = path.join(howto_abs, "references.md");
let howto_references = exists(howto_resources_path)
? read(howto_references_path, "string") || howto_references_default
: howto_references_default;
const contentAll = `${howto.content}`;
if (HOWTO_ADD_HARDWARE) {
const references_extra = await filter(contentAll,'tools_and_hardware')
howto_resources = `${howto_resources}\n\n ${references_extra}`
}
if (HOWTO_COMPLETE_SKILLS) {
const references_extra = await filter(contentAll,'learned_skills')
howto_resources = `${howto_resources}\n\n ${references_extra}`
const references_extra = await filter(contentAll, "learned_skills");
howto_resources = `${howto_resources}\n\n ${references_extra}`;
}
if (HOWTO_LOCAL_RESOURCES && howto.user && howto.user.geo) {
const references_extra = await filter(`Location: ${authorGeo.countryName}`,'local')
howto_resources = `${howto_resources}\n\n ${references_extra}`
const references_extra = await filter(
`Location: ${authorGeo.countryName}`,
"local",
);
howto_resources = `${howto_resources}\n\n ${references_extra}`;
}
const Resources = component(howto_resources);
const References = component(howto_references);
---
<BaseLayout class="markdown-content bg-gray-100">
@ -239,7 +244,8 @@ const Resources = component(howto_resources);
</ol>
</section>
<section class="p-8 bg-white markdown-content"><Resources /></section>
<section class="p-8 bg-white markdown-content"><Resources /></section>
<section class="p-8 bg-white markdown-content"><References /></section>
<footer class="p-8 text-sm border-t bg-white text-gray-600">
<div class="flex justify-between">

View File

@ -26,7 +26,9 @@ export const HOWTO_FILTER_LLM = true
export const HOWTO_ANNOTATIONS = false
export const HOWTO_ANNOTATIONS_CACHE = false
export const HOWTO_COMPLETE_RESOURCES = true
export const HOWTO_ADD_HARDWARE = false
export const HOWTO_ADD_HARDWARE = true
export const HOWTO_ADD_RESOURCES = true
export const HOWTO_ADD_REFERENCES = true
export const HOWTO_COMPLETE_SKILLS = false
export const HOWTO_LOCAL_RESOURCES = false

View File

@ -43,27 +43,6 @@
"mode": "completion",
"prompt": "Markdown chapter (h4) with a list of local resources, services & suppliers, max. 5, with links,group by category. dont comment, just the list",
"filters": "code"
},
"difficulty": {
"router": "openai",
"model": "gpt-4o",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"timeEstimate": {
"router": "openai",
"model": "gpt-4o",
"mode": "completion",
"preferences": "none",
"filters": "code"
},
"prerequisites": {
"router": "openai",
"model": "gpt-4o",
"mode": "completion",
"preferences": "none",
"filters": "code"
}
},
"instructions": {

View File

@ -129,4 +129,6 @@ export interface IHowto {
skills?: string
// Added content field : resources
resources?: string
// Added content field : references
references?: string
}

View File

@ -27,7 +27,7 @@ import {
HOWTO_FILES_WEB,
HOWTO_FILES_ABS,
HOWTO_FILTER_LLM,
default_image,
HOWTO_ROOT,
HOWTO_GLOB,
@ -36,7 +36,9 @@ import {
HOWTO_COMPLETE_RESOURCES,
HOWTO_ADD_HARDWARE,
HOWTO_COMPLETE_SKILLS,
HOWTO_LOCAL_RESOURCES
HOWTO_LOCAL_RESOURCES,
HOWTO_ADD_RESOURCES,
HOWTO_ADD_REFERENCES
} from "config/config.js"
import { env, logger } from '@/base/index.js'
@ -136,8 +138,7 @@ export const raw = async () => {
howtos = howtos.filter((h: IHowto) => {
return h.steps.length > 0 && !blacklist.includes(h._createdBy);
});
howtos = howtos.slice(0, 10)
howtos = howtos.slice(0, 5)
return howtos
}
export const defaults = async (data: any, cwd: string, root: string) => {
@ -156,7 +157,7 @@ export const defaults = async (data: any, cwd: string, root: string) => {
}
return data;
}
const commons = async (text: string): Promise<string> => {
const commons = async (text: string): Promise<string> => {
return await template_filter(text, 'simple', TemplateContext.COMMONS);
}
const content = async (str: string, filters: FilterFunction[] = default_filters) => await applyFilters(str, filters)
@ -293,7 +294,7 @@ const complete = async (item: IHowto) => {
if (HOWTO_FILTER_LLM) {
item.description = await commons(item.description || '')
}
// default pass, links, words, formatting, ...
item.steps = await pMap(
item.steps,
@ -302,7 +303,7 @@ const complete = async (item: IHowto) => {
text: await content(step.text)
})
)
// commons: language, tone, bullshit filter, and a piece of love, just a bit, at least :)
if (HOWTO_FILTER_LLM) {
item.steps = await pMap(
@ -314,9 +315,7 @@ const complete = async (item: IHowto) => {
)
}
// Store final content as a single string with user location
const userLocation = item.user?.geo ?
`\nUser Location: ${item.user.geo.city ? `${item.user.geo.city}, ` : ''}${item.user.geo.countryName || ''}` : ''
const userLocation = item.user?.geo ? `\nUser Location: ${item.user.geo.city ? `${item.user.geo.city}, ` : ''}${item.user.geo.countryName || ''}` : ''
item.content = [
item.description,
userLocation,
@ -324,15 +323,20 @@ const complete = async (item: IHowto) => {
].filter(Boolean).join('\n\n')
// Generate keywords using the keywords template
if(HOWTO_COMPLETE_RESOURCES){
if (HOWTO_ADD_RESOURCES) {
item.keywords = await template_filter(item.content, 'keywords', TemplateContext.HOWTO);
item.resources = await template_filter(item.content, 'toolsAndHardware', TemplateContext.HOWTO);
write(path.join(item_path(item), 'resources.md'), item.resources as string)
}
if (HOWTO_ADD_REFERENCES) {
item.keywords = await template_filter(item.content, 'keywords', TemplateContext.HOWTO);
item.resources = await template_filter(item.content, 'references', TemplateContext.HOWTO);
write(path.join(item_path(item), 'references.md'), item.references as string)
}
await to_github(item)
await to_mdx(item)
await to_astro(item)
return item
}
@ -358,10 +362,10 @@ const onStoreItem = async (store: any, ctx: LoaderContext) => {
step.images = step.images.filter((image) => asset_local_abs(item, image))
})
item.files = await downloadFiles(item.slug, item)
await complete(item)
await complete(item)
const configPath = path.join(item_path(item), 'config.json')
write(configPath, JSON.stringify(item, null, 2))
logger.info(`Stored item ${item.slug} at ${configPath}`)
write(configPath, JSON.stringify(item, null, 2))
logger.info(`Stored item ${item.slug} at ${configPath}`)
return item
}