@nodetool-ai/node-sdk 0.8.4-a24.3 → 0.8.4
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/dist/.nodetool-build-stamp +1 -1
- package/dist/_sandbox/README.md +176 -0
- package/dist/_sandbox/sandbox-aws/SKILL.md +98 -0
- package/dist/_sandbox/sandbox-aws/package.json +40 -0
- package/dist/_sandbox/sandbox-chrono/SKILL.md +39 -0
- package/dist/_sandbox/sandbox-chrono/package.json +40 -0
- package/dist/_sandbox/sandbox-color/SKILL.md +35 -0
- package/dist/_sandbox/sandbox-color/package.json +43 -0
- package/dist/_sandbox/sandbox-csv/SKILL.md +50 -0
- package/dist/_sandbox/sandbox-csv/package.json +39 -0
- package/dist/_sandbox/sandbox-dates/SKILL.md +47 -0
- package/dist/_sandbox/sandbox-dates/package.json +41 -0
- package/dist/_sandbox/sandbox-decimal/SKILL.md +36 -0
- package/dist/_sandbox/sandbox-decimal/package.json +43 -0
- package/dist/_sandbox/sandbox-diff/SKILL.md +36 -0
- package/dist/_sandbox/sandbox-diff/package.json +39 -0
- package/dist/_sandbox/sandbox-docx/SKILL.md +53 -0
- package/dist/_sandbox/sandbox-docx/package.json +40 -0
- package/dist/_sandbox/sandbox-dsl/SKILL.md +137 -0
- package/dist/_sandbox/sandbox-dsl/package.json +413 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/authoring.js +382 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/core.js +382 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.audio.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.image.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.text.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/gemini.video.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/index.js +149 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/kie.dynamic_schema.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.audio.js +68 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.browser.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.charts.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.comfy.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.grid.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.channel.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.color.js +32 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.color_grading.js +44 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.draw.js +36 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.effects.js +24 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.enhance.js +28 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.filter.js +64 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.keyer.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.mask.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.image.warp.js +36 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.pdf.js +32 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.sqlite.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.stable_diffusion_cpp.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.svg.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/lib.video.download.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/messaging.discord.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/messaging.telegram.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.embeddings.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.text.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/mistral.vision.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.agents.js +32 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.js +104 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.realtime.js +28 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.audio.synth.js +40 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.blender.js +28 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.code.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.compare.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.constant.js +132 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.control.js +96 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.creative.js +24 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.data.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.document.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.entity.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.fake.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.game.js +36 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.generators.js +24 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.image.js +120 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.input.js +140 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.manimgx.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.model3d.js +76 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.output.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.script.js +28 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.sketch.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.storyboard.js +32 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.text.js +56 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.timeline.js +24 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.triggers.js +24 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.variable.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.video.js +136 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.app_node.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.base_node.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.subgraph.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/nodetool.workflows.workflow_node.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.agents.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.audio.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.image.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/openai.text.js +16 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/vector.js +56 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/whisper_cpp.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.image.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.text.js +12 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/generated/xai.vision.js +8 -0
- package/dist/_sandbox/sandbox-dsl/sandbox/index.js +13 -0
- package/dist/_sandbox/sandbox-dsl/scripts/build.mjs +116 -0
- package/dist/_sandbox/sandbox-epub/SKILL.md +61 -0
- package/dist/_sandbox/sandbox-epub/package.json +40 -0
- package/dist/_sandbox/sandbox-exif/SKILL.md +30 -0
- package/dist/_sandbox/sandbox-exif/package.json +40 -0
- package/dist/_sandbox/sandbox-expr/SKILL.md +28 -0
- package/dist/_sandbox/sandbox-expr/package.json +40 -0
- package/dist/_sandbox/sandbox-fabric/SKILL.md +113 -0
- package/dist/_sandbox/sandbox-fabric/package.json +40 -0
- package/dist/_sandbox/sandbox-flow/SKILL.md +131 -0
- package/dist/_sandbox/sandbox-flow/package.json +411 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.audio.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.image.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.text.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/gemini.video.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/kie.dynamic_schema.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.audio.js +68 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.browser.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.charts.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.comfy.js +25 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.grid.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.channel.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.color.js +32 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.color_grading.js +44 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.draw.js +36 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.effects.js +24 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.enhance.js +28 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.filter.js +64 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.keyer.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.mask.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.image.warp.js +36 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.pdf.js +32 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.sqlite.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.stable_diffusion_cpp.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.svg.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/lib.video.download.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/messaging.discord.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/messaging.telegram.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.embeddings.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.text.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/mistral.vision.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.agents.js +41 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.js +110 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.realtime.js +46 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.audio.synth.js +67 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.blender.js +28 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.code.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.compare.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.constant.js +132 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.control.js +165 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.creative.js +27 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.data.js +18 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.document.js +19 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.entity.js +19 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.fake.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.game.js +39 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.generators.js +30 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.image.js +126 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.input.js +143 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.manimgx.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.model3d.js +76 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.output.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.script.js +28 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.sketch.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.storyboard.js +35 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.text.js +68 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.timeline.js +24 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.triggers.js +33 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.variable.js +15 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.video.js +145 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.app_node.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.base_node.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.subgraph.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/nodetool.workflows.workflow_node.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.agents.js +25 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.audio.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.image.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/openai.text.js +16 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/vector.js +56 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/whisper_cpp.js +11 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.image.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.text.js +12 -0
- package/dist/_sandbox/sandbox-flow/sandbox/generated/xai.vision.js +8 -0
- package/dist/_sandbox/sandbox-flow/sandbox/guest-core.js +35 -0
- package/dist/_sandbox/sandbox-flow/sandbox/index.js +10 -0
- package/dist/_sandbox/sandbox-flow/scripts/build.mjs +120 -0
- package/dist/_sandbox/sandbox-game/SKILL.md +116 -0
- package/dist/_sandbox/sandbox-game/package.json +36 -0
- package/dist/_sandbox/sandbox-game/sandbox/index.js +208 -0
- package/dist/_sandbox/sandbox-gif/SKILL.md +36 -0
- package/dist/_sandbox/sandbox-gif/package.json +43 -0
- package/dist/_sandbox/sandbox-html/SKILL.md +107 -0
- package/dist/_sandbox/sandbox-html/package.json +40 -0
- package/dist/_sandbox/sandbox-ics/SKILL.md +41 -0
- package/dist/_sandbox/sandbox-ics/package.json +40 -0
- package/dist/_sandbox/sandbox-jmespath/SKILL.md +26 -0
- package/dist/_sandbox/sandbox-jmespath/package.json +43 -0
- package/dist/_sandbox/sandbox-mammoth/SKILL.md +46 -0
- package/dist/_sandbox/sandbox-mammoth/package.json +41 -0
- package/dist/_sandbox/sandbox-markdown/SKILL.md +123 -0
- package/dist/_sandbox/sandbox-markdown/package.json +41 -0
- package/dist/_sandbox/sandbox-notion/SKILL.md +101 -0
- package/dist/_sandbox/sandbox-notion/package.json +38 -0
- package/dist/_sandbox/sandbox-ocr/SKILL.md +47 -0
- package/dist/_sandbox/sandbox-ocr/package.json +40 -0
- package/dist/_sandbox/sandbox-pdf/SKILL.md +47 -0
- package/dist/_sandbox/sandbox-pdf/package.json +39 -0
- package/dist/_sandbox/sandbox-pdflib/SKILL.md +56 -0
- package/dist/_sandbox/sandbox-pdflib/package.json +38 -0
- package/dist/_sandbox/sandbox-pptx/SKILL.md +42 -0
- package/dist/_sandbox/sandbox-pptx/package.json +40 -0
- package/dist/_sandbox/sandbox-pptxgen/SKILL.md +49 -0
- package/dist/_sandbox/sandbox-pptxgen/package.json +38 -0
- package/dist/_sandbox/sandbox-qr/SKILL.md +43 -0
- package/dist/_sandbox/sandbox-qr/package.json +42 -0
- package/dist/_sandbox/sandbox-rrule/SKILL.md +37 -0
- package/dist/_sandbox/sandbox-rrule/package.json +43 -0
- package/dist/_sandbox/sandbox-stats/SKILL.md +42 -0
- package/dist/_sandbox/sandbox-stats/package.json +43 -0
- package/dist/_sandbox/sandbox-subtitle/SKILL.md +38 -0
- package/dist/_sandbox/sandbox-subtitle/package.json +41 -0
- package/dist/_sandbox/sandbox-supabase/SKILL.md +108 -0
- package/dist/_sandbox/sandbox-supabase/package.json +39 -0
- package/dist/_sandbox/sandbox-tfjs/SKILL.md +76 -0
- package/dist/_sandbox/sandbox-tfjs/package.json +42 -0
- package/dist/_sandbox/sandbox-timeline/SKILL.md +647 -0
- package/dist/_sandbox/sandbox-timeline/package.json +46 -0
- package/dist/_sandbox/sandbox-timeline/sandbox/charts.js +356 -0
- package/dist/_sandbox/sandbox-timeline/sandbox/components.js +171 -0
- package/dist/_sandbox/sandbox-timeline/sandbox/index.d.ts +700 -0
- package/dist/_sandbox/sandbox-timeline/sandbox/index.js +1658 -0
- package/dist/_sandbox/sandbox-tokens/SKILL.md +46 -0
- package/dist/_sandbox/sandbox-tokens/package.json +40 -0
- package/dist/_sandbox/sandbox-twilio/SKILL.md +93 -0
- package/dist/_sandbox/sandbox-twilio/package.json +39 -0
- package/dist/_sandbox/sandbox-xlsx/SKILL.md +74 -0
- package/dist/_sandbox/sandbox-xlsx/package.json +40 -0
- package/dist/_sandbox/sandbox-xml/SKILL.md +36 -0
- package/dist/_sandbox/sandbox-xml/package.json +40 -0
- package/dist/_sandbox/sandbox-yaml/SKILL.md +48 -0
- package/dist/_sandbox/sandbox-yaml/package.json +41 -0
- package/dist/_sandbox/sandbox-zip/SKILL.md +54 -0
- package/dist/_sandbox/sandbox-zip/package.json +40 -0
- package/dist/code-node-validation.d.ts +2 -0
- package/dist/code-node-validation.d.ts.map +1 -1
- package/dist/code-node-validation.js +1 -1
- package/dist/code-node-validation.js.map +1 -1
- package/dist/pack-loader.d.ts +1 -0
- package/dist/pack-loader.d.ts.map +1 -1
- package/dist/pack-loader.js +1 -0
- package/dist/pack-loader.js.map +1 -1
- package/dist/sandbox-catalog-host.js +1 -1
- package/dist/sandbox-catalog-host.js.map +1 -1
- package/dist/sandbox-pack-discovery.d.ts +3 -0
- package/dist/sandbox-pack-discovery.d.ts.map +1 -1
- package/dist/sandbox-pack-discovery.js +7 -3
- package/dist/sandbox-pack-discovery.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-10-
|
|
1
|
+
2026-10-17T11:16:09.598Z
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Sandbox library packs
|
|
2
|
+
|
|
3
|
+
One npm package per library the sandbox offers. Library bridge packs contain
|
|
4
|
+
a config-only `nodetool.sandboxModules` manifest and a SKILL.md. Authoring packs
|
|
5
|
+
such as sandbox-game and sandbox-timeline also ship guest JavaScript.
|
|
6
|
+
|
|
7
|
+
There is one import surface and no second route: a library is reached with
|
|
8
|
+
`import`, from a pack that is installed and declared on the node. The `data.*`
|
|
9
|
+
guest globals are gone.
|
|
10
|
+
|
|
11
|
+
## The packs
|
|
12
|
+
|
|
13
|
+
| Pack | Library | Runs | Why |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| `@nodetool-ai/sandbox-dates` | date-fns | guest | compiler admits it |
|
|
16
|
+
| `@nodetool-ai/sandbox-yaml` | js-yaml | guest | compiler admits it |
|
|
17
|
+
| `@nodetool-ai/sandbox-markdown` | marked | guest | compiler admits it |
|
|
18
|
+
| `@nodetool-ai/sandbox-qr` | uqr | guest | compiler admits it |
|
|
19
|
+
| `@nodetool-ai/sandbox-subtitle` | subtitle | host | stream internals |
|
|
20
|
+
| `@nodetool-ai/sandbox-tokens` | js-tiktoken | host | megabytes of BPE ranks |
|
|
21
|
+
| `@nodetool-ai/sandbox-color` | culori | guest | compiler admits it |
|
|
22
|
+
| `@nodetool-ai/sandbox-decimal` | decimal.js | guest | compiler admits it |
|
|
23
|
+
| `@nodetool-ai/sandbox-expr` | expr-eval | host | bundle uses Function |
|
|
24
|
+
| `@nodetool-ai/sandbox-jmespath` | jmespath | guest | compiler admits it |
|
|
25
|
+
| `@nodetool-ai/sandbox-chrono` | chrono-node | host | locale tables / Date internals |
|
|
26
|
+
| `@nodetool-ai/sandbox-exif` | exifr | host | workers / DOM-shaped globals |
|
|
27
|
+
| `@nodetool-ai/sandbox-stats` | simple-statistics | guest | compiler admits it |
|
|
28
|
+
| `@nodetool-ai/sandbox-rrule` | rrule | guest | compiler admits it |
|
|
29
|
+
| `@nodetool-ai/sandbox-ics` | ics | host | Node-shaped helpers |
|
|
30
|
+
| `@nodetool-ai/sandbox-gif` | gifenc | guest | compiler admits it |
|
|
31
|
+
| `@nodetool-ai/sandbox-game` | NodeTool's game builder | guest | creates complete game documents and saves drafts atomically |
|
|
32
|
+
| `@nodetool-ai/sandbox-csv` | papaparse | host | imports `node:stream` |
|
|
33
|
+
| `@nodetool-ai/sandbox-html` | cheerio + turndown | host | 25 Node builtins; turndown wants a DOM |
|
|
34
|
+
| `@nodetool-ai/sandbox-xml` | fast-xml-parser | host | reads a bare `window` |
|
|
35
|
+
| `@nodetool-ai/sandbox-xlsx` | exceljs | host | Node streams |
|
|
36
|
+
| `@nodetool-ai/sandbox-diff` | diff | host | schedules with `setTimeout` |
|
|
37
|
+
| `@nodetool-ai/sandbox-zip` | fflate | host | the 50 MB inflation cap (below) |
|
|
38
|
+
| `@nodetool-ai/sandbox-ocr` | tesseract.js | host | WASM engine, workers, downloads its language data |
|
|
39
|
+
| `@nodetool-ai/sandbox-tfjs` | TensorFlow.js + model zoo | host | model weights outlive a run and outsize the guest heap |
|
|
40
|
+
| `@nodetool-ai/sandbox-docx` | docx | host | builds from class instances, not data |
|
|
41
|
+
| `@nodetool-ai/sandbox-mammoth` | mammoth | host | Node's own zip/XML stack |
|
|
42
|
+
| `@nodetool-ai/sandbox-epub` | epub2 | host | reads from a file path, not a buffer |
|
|
43
|
+
| `@nodetool-ai/sandbox-fabric` | fabric | host | DOM/Canvas APIs, rasterization |
|
|
44
|
+
| `@nodetool-ai/sandbox-pdflib` | pdf-lib | host | builds from class instances, not data |
|
|
45
|
+
| `@nodetool-ai/sandbox-pptxgen` | pptxgenjs | host | builds from class instances, not data |
|
|
46
|
+
| `@nodetool-ai/sandbox-pptx` | office-text-extractor | host | Node's own zip/XML stack |
|
|
47
|
+
| `@nodetool-ai/sandbox-pdf` | pdf-parse | host | pdf.js wants Node builtins and a canvas |
|
|
48
|
+
| `@nodetool-ai/sandbox-aws` | NodeTool's SigV4 signer | host | signing chain the guest has no library for |
|
|
49
|
+
| `@nodetool-ai/sandbox-notion` | NodeTool's Notion helper | host | first-party, so a pack cannot bring it |
|
|
50
|
+
| `@nodetool-ai/sandbox-supabase` | NodeTool's PostgREST helper | host | first-party |
|
|
51
|
+
| `@nodetool-ai/sandbox-twilio` | NodeTool's Twilio helper | host | first-party |
|
|
52
|
+
|
|
53
|
+
**Guest** means the M3 compiler bundles the library into the QuickJS guest and
|
|
54
|
+
the pack ships that manifest entry (`{"kind": "js", "npm": "…"}`). **Host**
|
|
55
|
+
means the library runs where the sandbox itself runs and the guest reaches it
|
|
56
|
+
through a generated ESM facade over a per-run dispatcher; the pack's manifest
|
|
57
|
+
entry is `{"kind": "host", "host": "<id>"}` and the implementation lives in
|
|
58
|
+
`packages/agents/src/host-modules/`.
|
|
59
|
+
|
|
60
|
+
An authored guest pack declares `{"kind": "js", "file": "sandbox/index.js"}`.
|
|
61
|
+
Discovery reads that file directly. The game builder uses this form and runs
|
|
62
|
+
inside QuickJS with the same module admission rules as other guest code.
|
|
63
|
+
|
|
64
|
+
### The service packs build requests; they never send one
|
|
65
|
+
|
|
66
|
+
The last four packs replace the S3, Notion, Supabase and Twilio nodes.
|
|
67
|
+
They are not libraries: each is a pure function that turns a description of a
|
|
68
|
+
request into `{url, method, headers, body}`, or in `-aws`'s case into signed
|
|
69
|
+
headers. The guest passes that to its own `fetch`, so the run's fetch cap, its
|
|
70
|
+
SSRF guard and its body limit still apply — moving the header math to the host
|
|
71
|
+
must not move the network call with it.
|
|
72
|
+
|
|
73
|
+
They run through the host registry of NodeTool's service helpers. SigV4 uses
|
|
74
|
+
an HMAC-SHA256 chain over the canonical request, which the guest cannot
|
|
75
|
+
compute with its own globals.
|
|
76
|
+
|
|
77
|
+
### Why zip is a host pack
|
|
78
|
+
|
|
79
|
+
fflate is pure JavaScript and the compiler admits it — it shipped as a guest
|
|
80
|
+
pack once. It does not now, because of `MAX_UNZIP_TOTAL_BYTES`. A zip bomb is a
|
|
81
|
+
policy question, and a policy enforced inside the guest is enforced by code the
|
|
82
|
+
guest can decline to call; the 64 MB guest heap does not replicate it either,
|
|
83
|
+
because fflate inflates into host memory first. The library therefore runs on
|
|
84
|
+
the host, where the cap sits between the archive and the guest with nothing
|
|
85
|
+
around it.
|
|
86
|
+
|
|
87
|
+
## A pack cannot bring a host module
|
|
88
|
+
|
|
89
|
+
`kind: "host"` carries an **id**, never an implementation. Discovery admits the
|
|
90
|
+
entry only when the id is in `SANDBOX_HOST_MODULES`
|
|
91
|
+
(`packages/protocol/src/sandbox-host.ts`) *and* the declaring package is the one
|
|
92
|
+
that table pins to the id — so `@evil/x` declaring `{"host": "csv"}` is refused,
|
|
93
|
+
and an unknown id is refused outright. The per-run dispatcher repeats both
|
|
94
|
+
checks on every call, because the boundary is enforcement, not declaration.
|
|
95
|
+
|
|
96
|
+
Adding a host module is a NodeTool change: a row in the protocol table and an
|
|
97
|
+
implementation in `packages/agents/src/host-modules/registry.ts`. A third-party
|
|
98
|
+
pack cannot reach host execution through this path.
|
|
99
|
+
|
|
100
|
+
## Not workspaces, on purpose
|
|
101
|
+
|
|
102
|
+
The root `workspaces` array names every workspace by path — there is no
|
|
103
|
+
`packages/*` glob — and these directories are deliberately absent from it. A
|
|
104
|
+
pack is consumed the way any third-party pack is: discovered from disk and
|
|
105
|
+
mounted into the guest by the loader. Nothing in the repo may
|
|
106
|
+
`import "@nodetool-ai/sandbox-yaml"` in host code, and leaving them out of the
|
|
107
|
+
workspace list is what makes that impossible rather than merely discouraged —
|
|
108
|
+
npm links no symlink into `node_modules`, so the specifier does not resolve for
|
|
109
|
+
the host at all.
|
|
110
|
+
|
|
111
|
+
The compiler still finds a guest pack's dependency in this tree: esbuild
|
|
112
|
+
resolves from the pack directory upward, and js-yaml and date-fns are hoisted to
|
|
113
|
+
the repo root by the workspaces that already depend on them. A host pack has no
|
|
114
|
+
dependency of its own at all — the library is a dependency of
|
|
115
|
+
`@nodetool-ai/agents`, where the implementation lives.
|
|
116
|
+
|
|
117
|
+
## Shipped, not installed
|
|
118
|
+
|
|
119
|
+
Being outside `node_modules` once meant being absent: a checkout, the desktop
|
|
120
|
+
app and the server image all discovered zero of these packs, so every library
|
|
121
|
+
NodeTool documents failed a Code node with "Sandbox module … is not installed".
|
|
122
|
+
Discovery now reads this directory directly. `shippedPackSearchPaths()` in
|
|
123
|
+
`packages/node-sdk/src/pack-loader.ts` returns it — found by walking up from the
|
|
124
|
+
loader module in a checkout, and read from `_sandbox/` beside `server.mjs` in
|
|
125
|
+
the packaged app and the Docker image, where `scripts/bundle-backend.mjs` stages
|
|
126
|
+
every pack here (manifest, declared files, SKILL.md) and
|
|
127
|
+
`scripts/verify-backend-bundle.mjs` fails a build that misses one. Both are
|
|
128
|
+
scans, so a pack added to this directory ships with no list to update.
|
|
129
|
+
`NODETOOL_SHIPPED_PACKS_DIR` overrides the root for a host that stages them
|
|
130
|
+
elsewhere.
|
|
131
|
+
|
|
132
|
+
The shipped root comes last in the search order. A pack installed from npm
|
|
133
|
+
through the Package Manager therefore shadows the copy that ships with the app,
|
|
134
|
+
with no duplicate-pack diagnostic: that name has an owner, and it is the one the
|
|
135
|
+
user installed.
|
|
136
|
+
|
|
137
|
+
Availability is not new authority. These packs declare modules; they register no
|
|
138
|
+
nodes and run no code at load, so the pack allowlist that gates node packs has
|
|
139
|
+
nothing to gate here. A host module still resolves only through
|
|
140
|
+
`SANDBOX_HOST_MODULES`, a Code node still has to declare the specifier, and the
|
|
141
|
+
credentials the service packs use still come from `nodetool.secrets.get`,
|
|
142
|
+
narrowed to the names that node declares.
|
|
143
|
+
|
|
144
|
+
## Registry metadata
|
|
145
|
+
|
|
146
|
+
The package index lives in the external `nodetool-ai/nodetool-registry`
|
|
147
|
+
repository, so nothing in this repo writes an index entry. What the index reads
|
|
148
|
+
is here, in each pack's package.json: `name`, `description`, the
|
|
149
|
+
`nodetool-sandbox-pack` keyword, `nodetool.sandboxModules` (the specifier
|
|
150
|
+
summary the design asks index entries to carry), and `nodetool.recommended`.
|
|
151
|
+
Discovery ignores every key but `apiVersion`, `sandboxModules`, and `internal`,
|
|
152
|
+
so the extra metadata costs the host nothing.
|
|
153
|
+
|
|
154
|
+
## Adding a pack
|
|
155
|
+
|
|
156
|
+
**Guest pack.** Compile the candidate first — a pack for a library the compiler
|
|
157
|
+
skips is a pack nobody can import; `nodetool packs compile --json` reports the
|
|
158
|
+
named skip. Then write the package.json with `{"kind": "js", "npm": "<dep>"}`
|
|
159
|
+
and the dependency pinned to a range this tree already resolves.
|
|
160
|
+
|
|
161
|
+
**Authored guest pack.** Write browser-safe JavaScript and declare it with
|
|
162
|
+
`{"kind": "js", "file": "sandbox/index.js"}`. Mark its bridge table row
|
|
163
|
+
`source: "authored"` and test importing it in QuickJS through discovery and
|
|
164
|
+
the module catalog. It needs no npm compilation.
|
|
165
|
+
|
|
166
|
+
**Host pack.** Add the row to `SANDBOX_HOST_MODULES` and the loader to
|
|
167
|
+
`packages/agents/src/host-modules/registry.ts`, with the implementation beside
|
|
168
|
+
it and every limit inside it. Then write the package.json with
|
|
169
|
+
`{"kind": "host", "host": "<id>"}`.
|
|
170
|
+
|
|
171
|
+
Either way: a `SKILL.md` with the specifier, each export with one example
|
|
172
|
+
written for the guest, and the gotchas that bite there; a row in
|
|
173
|
+
`packages/node-sdk/src/sandbox-bridge-packs.ts` so an uninstalled specifier gets
|
|
174
|
+
an "Install …" hint; and the pack directory added to
|
|
175
|
+
`packages/sandbox-compiler/tests/packs.test.ts`, which discovers, compiles, and
|
|
176
|
+
runs every pack in this directory.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-aws
|
|
3
|
+
description: Sign AWS requests (S3 and every other SigV4 service) in a Code node or CodeAct action, with NodeTool's signer running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# AWS SigV4 in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-aws`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
S3 is an HTTP API, so `fetch` already reaches it. What the guest cannot do is
|
|
11
|
+
sign the request: SigV4 is an HMAC-SHA256 chain over a canonical form of the
|
|
12
|
+
request, and one wrong byte gives a signature mismatch that names nothing.
|
|
13
|
+
This pack is a **host module**: the chain runs on the host and hands back
|
|
14
|
+
headers.
|
|
15
|
+
|
|
16
|
+
**Nothing here sends a request.** Both exports are pure — they take a request
|
|
17
|
+
and return a signed one. The call goes out through the guest's own `fetch`, so
|
|
18
|
+
the run's fetch cap and its SSRF guard still apply.
|
|
19
|
+
|
|
20
|
+
## sigv4 — sign a request
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { sigv4 } from "@nodetool-ai/sandbox-aws";
|
|
24
|
+
|
|
25
|
+
const accessKeyId = await nodetool.secrets.get("AWS_ACCESS_KEY_ID");
|
|
26
|
+
const secretAccessKey = await nodetool.secrets.get("AWS_SECRET_ACCESS_KEY");
|
|
27
|
+
|
|
28
|
+
const signed = await sigv4({
|
|
29
|
+
method: "GET",
|
|
30
|
+
url: "https://my-bucket.s3.us-east-1.amazonaws.com/?list-type=2&max-keys=100",
|
|
31
|
+
region: "us-east-1",
|
|
32
|
+
service: "s3",
|
|
33
|
+
accessKeyId,
|
|
34
|
+
secretAccessKey
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const res = await fetch(signed.url, { method: signed.method, headers: signed.headers });
|
|
38
|
+
return { xml: await res.text() };
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Options: `method` (default `GET`), `url` (required, absolute), `region`
|
|
42
|
+
(default `us-east-1`), `service` (default `s3`), `accessKeyId` and
|
|
43
|
+
`secretAccessKey` (required), `sessionToken` (for temporary STS credentials),
|
|
44
|
+
`headers`, `body`, `payloadHash`.
|
|
45
|
+
|
|
46
|
+
Returns `{url, method, headers}` — never the body. Pass the same body value to
|
|
47
|
+
`fetch` yourself, so bytes make one trip, not two.
|
|
48
|
+
|
|
49
|
+
### Writing an object
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
const body = JSON.stringify(inputs.record);
|
|
53
|
+
const signed = await sigv4({
|
|
54
|
+
method: "PUT",
|
|
55
|
+
url: `https://my-bucket.s3.us-east-1.amazonaws.com/${inputs.key}`,
|
|
56
|
+
region: "us-east-1", service: "s3",
|
|
57
|
+
accessKeyId, secretAccessKey,
|
|
58
|
+
headers: { "content-type": "application/json" },
|
|
59
|
+
body
|
|
60
|
+
});
|
|
61
|
+
await fetch(signed.url, { method: "PUT", headers: signed.headers, body });
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
A `Uint8Array` body works the same way — from `workspace.readBytes` or a
|
|
65
|
+
previous `response.bytes()`.
|
|
66
|
+
|
|
67
|
+
## presign — a URL that authorizes itself
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import { presign } from "@nodetool-ai/sandbox-aws";
|
|
71
|
+
|
|
72
|
+
const url = await presign({
|
|
73
|
+
method: "GET",
|
|
74
|
+
url: "https://my-bucket.s3.us-east-1.amazonaws.com/report.pdf",
|
|
75
|
+
region: "us-east-1", service: "s3",
|
|
76
|
+
expiresIn: 3600,
|
|
77
|
+
accessKeyId, secretAccessKey
|
|
78
|
+
});
|
|
79
|
+
return { url };
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Returns the URL as a string. `expiresIn` is seconds, clamped to a week. The
|
|
83
|
+
payload is unsigned, which is what makes a presigned `PUT` usable — whoever
|
|
84
|
+
holds the URL supplies the body.
|
|
85
|
+
|
|
86
|
+
## Gotchas
|
|
87
|
+
|
|
88
|
+
- **Every export is async.** A host call is a round trip.
|
|
89
|
+
- **It signs; it does not send.** Nothing reaches the network until you call
|
|
90
|
+
`fetch`.
|
|
91
|
+
- **The signature is time-bound.** It is stamped when you call `sigv4`, and AWS
|
|
92
|
+
rejects one more than 15 minutes old. Sign immediately before fetching, not
|
|
93
|
+
at the top of a long function.
|
|
94
|
+
- **Other services work too.** Set `service` and `region` — `dynamodb`,
|
|
95
|
+
`sqs`, `lambda`, `bedrock`. Only `s3` skips path normalization, because an
|
|
96
|
+
object key is a key.
|
|
97
|
+
- **10 MB of body per signature.** Hash a bigger upload yourself and pass
|
|
98
|
+
`payloadHash`, or use a presigned `PUT`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-aws",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Sign AWS requests with Signature V4 inside the NodeTool sandbox, from NodeTool's signer running on the host",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"nodetool": {
|
|
7
|
+
"apiVersion": 1,
|
|
8
|
+
"recommended": true,
|
|
9
|
+
"sandboxModules": [
|
|
10
|
+
{
|
|
11
|
+
"name": ".",
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"host": "aws"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-aws"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://nodetool.ai",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/nodetool-ai/nodetool/issues"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"SKILL.md"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"nodetool",
|
|
34
|
+
"nodetool-sandbox-pack",
|
|
35
|
+
"sandbox",
|
|
36
|
+
"aws",
|
|
37
|
+
"s3",
|
|
38
|
+
"sigv4"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-chrono
|
|
3
|
+
description: Parse English dates such as next Tuesday in a Code node or CodeAct action, with chrono-node running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Natural-language dates in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-chrono`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
chrono-node does not compile into QuickJS, so this pack is a **host module**.
|
|
11
|
+
You pass text; you get ISO strings back.
|
|
12
|
+
|
|
13
|
+
## parseDate — first match
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import { parseDate } from "@nodetool-ai/sandbox-chrono";
|
|
17
|
+
|
|
18
|
+
const iso = await parseDate(inputs.text, inputs.now);
|
|
19
|
+
return { iso };
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`inputs.now` is an optional reference timestamp (ISO string or epoch ms).
|
|
23
|
+
|
|
24
|
+
## parse — every match
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { parse } from "@nodetool-ai/sandbox-chrono";
|
|
28
|
+
|
|
29
|
+
const hits = await parse(inputs.text, inputs.now);
|
|
30
|
+
return { hits };
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Each hit is `{ text, start, end }` with ISO strings (`end` may be `null`).
|
|
34
|
+
|
|
35
|
+
## Gotchas
|
|
36
|
+
|
|
37
|
+
- **Async host calls.** Always `await`.
|
|
38
|
+
- **UTC.** The guest still has no time-zone database.
|
|
39
|
+
- **Pair with `@nodetool-ai/sandbox-dates`** to format the Date you parse.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-chrono",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Parse natural-language dates inside the NodeTool sandbox, from chrono-node",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"nodetool": {
|
|
7
|
+
"apiVersion": 1,
|
|
8
|
+
"recommended": true,
|
|
9
|
+
"sandboxModules": [
|
|
10
|
+
{
|
|
11
|
+
"name": ".",
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"host": "chrono"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-chrono"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://nodetool.ai",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/nodetool-ai/nodetool/issues"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"SKILL.md"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"nodetool",
|
|
34
|
+
"nodetool-sandbox-pack",
|
|
35
|
+
"sandbox",
|
|
36
|
+
"chrono",
|
|
37
|
+
"date",
|
|
38
|
+
"nlp"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-color
|
|
3
|
+
description: Convert, mix, and measure colors inside a Code node or CodeAct action, with culori running in the guest
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Color in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-color`. One module, culori's root export.
|
|
9
|
+
Import it at the top of the body.
|
|
10
|
+
|
|
11
|
+
## Parse and convert
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { parse, formatHex, converter } from "@nodetool-ai/sandbox-color";
|
|
15
|
+
|
|
16
|
+
const color = parse(inputs.hex);
|
|
17
|
+
const rgb = converter("rgb")(color);
|
|
18
|
+
return { hex: formatHex(color), rgb };
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Mix and difference
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import { interpolate, formatHex, differenceCiede2000 } from "@nodetool-ai/sandbox-color";
|
|
25
|
+
|
|
26
|
+
const mix = interpolate(["#2563eb", "#f97316"]);
|
|
27
|
+
const mid = formatHex(mix(0.5));
|
|
28
|
+
const delta = differenceCiede2000()("#2563eb", "#f97316");
|
|
29
|
+
return { mid, delta };
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Gotchas
|
|
33
|
+
|
|
34
|
+
- **Objects, not CSS strings, after parse.** A parsed color is `{ mode, ...channels }`.
|
|
35
|
+
- **Named imports.** There is no useful default export.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-color",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Color conversion, mixing, and difference (deltaE) inside the NodeTool sandbox, from culori",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"culori": "^4.0.2"
|
|
8
|
+
},
|
|
9
|
+
"nodetool": {
|
|
10
|
+
"apiVersion": 1,
|
|
11
|
+
"recommended": true,
|
|
12
|
+
"sandboxModules": [
|
|
13
|
+
{
|
|
14
|
+
"name": ".",
|
|
15
|
+
"kind": "js",
|
|
16
|
+
"npm": "culori"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
23
|
+
"directory": "packages/sandbox-packs/sandbox-color"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://nodetool.ai",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/nodetool-ai/nodetool/issues"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"SKILL.md"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"nodetool",
|
|
37
|
+
"nodetool-sandbox-pack",
|
|
38
|
+
"sandbox",
|
|
39
|
+
"color",
|
|
40
|
+
"culori",
|
|
41
|
+
"deltae"
|
|
42
|
+
]
|
|
43
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-csv
|
|
3
|
+
description: Parse and write CSV in a Code node or CodeAct action, with papaparse running on the host behind a generated facade
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CSV in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-csv`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
papaparse imports `node:stream`, so it cannot be compiled into the guest. This
|
|
11
|
+
pack is a **host module**: the import resolves to a generated facade whose two
|
|
12
|
+
exports call NodeTool's own implementation. Both are `async` — a host call is a
|
|
13
|
+
round trip.
|
|
14
|
+
|
|
15
|
+
## parse — CSV text to records
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
import { parse } from "@nodetool-ai/sandbox-csv";
|
|
19
|
+
|
|
20
|
+
const rows = await parse(inputs.csv); // records keyed by the header row
|
|
21
|
+
const raw = await parse(inputs.csv, { header: false }); // string[][]
|
|
22
|
+
return { count: rows.length, first: rows[0] ?? null };
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Options: `header` (default `true`), `delimiter` (one character; omit to
|
|
26
|
+
auto-detect).
|
|
27
|
+
|
|
28
|
+
Values stay **strings**. There is no `dynamicTyping`, so a column never changes
|
|
29
|
+
shape between runs — convert what you need with `Number()` or `new Date()`.
|
|
30
|
+
|
|
31
|
+
## stringify — records back to CSV
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { stringify } from "@nodetool-ai/sandbox-csv";
|
|
35
|
+
|
|
36
|
+
const csv = await stringify(inputs.rows, { delimiter: ";" });
|
|
37
|
+
return { csv };
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Takes records or row arrays. Options: `header` (default `true`), `delimiter`
|
|
41
|
+
(exactly one character).
|
|
42
|
+
|
|
43
|
+
## Gotchas
|
|
44
|
+
|
|
45
|
+
- **Every export is async.** `parse(...)` without `await` gives you a Promise.
|
|
46
|
+
- **5 MB of text per call.** Input over that is refused by name. Split a bigger
|
|
47
|
+
file, or read it in slices with `workspace.read`.
|
|
48
|
+
- **Bounded concurrency still helps.** Host calls start when invoked, so
|
|
49
|
+
`Promise.all` over several `parse` calls runs them together; `parallelMap`
|
|
50
|
+
is the bounded form.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-csv",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Parse and write CSV inside the NodeTool sandbox, from papaparse running on the host",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"nodetool": {
|
|
7
|
+
"apiVersion": 1,
|
|
8
|
+
"recommended": true,
|
|
9
|
+
"sandboxModules": [
|
|
10
|
+
{
|
|
11
|
+
"name": ".",
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"host": "csv"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-csv"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://nodetool.ai",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/nodetool-ai/nodetool/issues"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"SKILL.md"
|
|
31
|
+
],
|
|
32
|
+
"keywords": [
|
|
33
|
+
"nodetool",
|
|
34
|
+
"nodetool-sandbox-pack",
|
|
35
|
+
"sandbox",
|
|
36
|
+
"csv",
|
|
37
|
+
"parse"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-dates
|
|
3
|
+
description: Date arithmetic, parsing and formatting inside a Code node or CodeAct action, with date-fns running in the guest
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Dates in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-dates`. One module, date-fns's root export —
|
|
9
|
+
around 250 named functions. There is no default export, so import the names you
|
|
10
|
+
use.
|
|
11
|
+
|
|
12
|
+
## Arithmetic and comparison
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import { addDays, differenceInCalendarDays, isBefore } from "@nodetool-ai/sandbox-dates";
|
|
16
|
+
|
|
17
|
+
const due = addDays(new Date(inputs.startedAt), 30);
|
|
18
|
+
return { due: due.toISOString(), overdue: isBefore(due, new Date()), days: differenceInCalendarDays(due, new Date()) };
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Parsing and formatting
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
import { parseISO, format, isValid } from "@nodetool-ai/sandbox-dates";
|
|
25
|
+
|
|
26
|
+
const when = parseISO(inputs.timestamp);
|
|
27
|
+
if (!isValid(when)) return { label: "unknown" };
|
|
28
|
+
return { label: format(when, "EEEE, d MMMM yyyy") };
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`format` uses date-fns's own English locale tables, not `Intl` — which the
|
|
32
|
+
guest does not have. That is why formatting works here at all, and it is also
|
|
33
|
+
the limit: another language means another locale, and locales live at
|
|
34
|
+
`date-fns/locale`, a subpath this pack does not publish.
|
|
35
|
+
|
|
36
|
+
## Gotchas
|
|
37
|
+
|
|
38
|
+
- **UTC only.** The guest runs with no time-zone database, so `new Date()` and
|
|
39
|
+
every conversion behave as UTC. Anything zone-aware — "9 am in Berlin" —
|
|
40
|
+
belongs on the host, not here.
|
|
41
|
+
- **Named imports only.** `import dates from "@nodetool-ai/sandbox-dates"` gets
|
|
42
|
+
you nothing; date-fns is pure ESM with no default export.
|
|
43
|
+
- **Import what you use.** The bundle is about 176 KB and loads as one module
|
|
44
|
+
per invocation, so a node that needs one comparison pays for all of it. For a
|
|
45
|
+
single `Date` subtraction, plain arithmetic is cheaper.
|
|
46
|
+
- **No timers.** `setTimeout` does not exist in the guest. date-fns needs none,
|
|
47
|
+
but code around it must not either.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-dates",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Date arithmetic, parsing and formatting inside the NodeTool sandbox, from date-fns",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"date-fns": "^4.4.0"
|
|
8
|
+
},
|
|
9
|
+
"nodetool": {
|
|
10
|
+
"apiVersion": 1,
|
|
11
|
+
"recommended": true,
|
|
12
|
+
"sandboxModules": [
|
|
13
|
+
{
|
|
14
|
+
"name": ".",
|
|
15
|
+
"kind": "js",
|
|
16
|
+
"npm": "date-fns"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
23
|
+
"directory": "packages/sandbox-packs/sandbox-dates"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://nodetool.ai",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/nodetool-ai/nodetool/issues"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"SKILL.md"
|
|
34
|
+
],
|
|
35
|
+
"keywords": [
|
|
36
|
+
"nodetool",
|
|
37
|
+
"nodetool-sandbox-pack",
|
|
38
|
+
"sandbox",
|
|
39
|
+
"date"
|
|
40
|
+
]
|
|
41
|
+
}
|