@nodetool-ai/node-sdk 0.8.4-a24.2 → 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
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-tokens
|
|
3
|
+
description: Count, encode, and decode LLM tokens in a Code node or CodeAct action, with js-tiktoken running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Token counting in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-tokens`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
One encoding's BPE ranks are several megabytes, well past the 1 MB cap on a
|
|
11
|
+
compiled guest module, so this pack is a **host module**: the import resolves to
|
|
12
|
+
a generated facade over NodeTool's own implementation. The ranks load once per
|
|
13
|
+
process per encoding.
|
|
14
|
+
|
|
15
|
+
This is what the removed `nodetool.text.CountTokens` node did.
|
|
16
|
+
|
|
17
|
+
## count — how many tokens a text costs
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { count } from "@nodetool-ai/sandbox-tokens";
|
|
21
|
+
|
|
22
|
+
const tokens = await count(inputs.text, "cl100k_base");
|
|
23
|
+
return { tokens, fitsContext: tokens < 8000 };
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Encodings: `cl100k_base` (default — GPT-4, GPT-3.5), `o200k_base` (GPT-4o),
|
|
27
|
+
`p50k_base`, `r50k_base`. Empty text is 0 without loading anything.
|
|
28
|
+
|
|
29
|
+
## encode / decode — the token ids themselves
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
import { encode, decode } from "@nodetool-ai/sandbox-tokens";
|
|
33
|
+
|
|
34
|
+
const ids = await encode(inputs.text);
|
|
35
|
+
// Truncate on a token boundary rather than a character one.
|
|
36
|
+
return { head: await decode(ids.slice(0, 500)) };
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Gotchas
|
|
40
|
+
|
|
41
|
+
- **All three are async.**
|
|
42
|
+
- **5 MB per call**, the shared host-module text cap.
|
|
43
|
+
- **tiktoken is OpenAI's tokenizer.** Anthropic, Gemini, and local models count
|
|
44
|
+
differently — treat the number as an estimate for anything else.
|
|
45
|
+
- **Round-tripping is not free.** `decode(encode(t))` allocates the ranks and
|
|
46
|
+
two passes; use `count` when you only need the number.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-tokens",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "LLM token counting inside the NodeTool sandbox, from js-tiktoken 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": "tokens"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-tokens"
|
|
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
|
+
"tokens",
|
|
37
|
+
"tiktoken",
|
|
38
|
+
"count"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-twilio
|
|
3
|
+
description: Send SMS and WhatsApp messages and look up numbers from a Code node or CodeAct action, with NodeTool's Twilio request builder running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Twilio in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-twilio`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
Twilio is HTTP Basic auth over form-encoded bodies, on a URL that buries the
|
|
11
|
+
account SID in the path. None of that is hard; all of it is easy to get wrong
|
|
12
|
+
once, and the failure is a 401 that names nothing.
|
|
13
|
+
|
|
14
|
+
**Nothing here sends a request.** `request` builds one; the guest's own `fetch`
|
|
15
|
+
sends it, under the run's fetch cap and SSRF guard.
|
|
16
|
+
|
|
17
|
+
## request
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { request } from "@nodetool-ai/sandbox-twilio";
|
|
21
|
+
|
|
22
|
+
const accountSid = await nodetool.secrets.get("TWILIO_ACCOUNT_SID");
|
|
23
|
+
const authToken = await nodetool.secrets.get("TWILIO_AUTH_TOKEN");
|
|
24
|
+
|
|
25
|
+
const req = await request({
|
|
26
|
+
accountSid, authToken,
|
|
27
|
+
path: "Messages.json",
|
|
28
|
+
method: "POST",
|
|
29
|
+
params: { To: inputs.to, From: inputs.from, Body: inputs.text }
|
|
30
|
+
});
|
|
31
|
+
const res = await fetch(req.url, req);
|
|
32
|
+
if (!res.ok) throw new Error(`Twilio: ${res.json.message ?? res.status}`);
|
|
33
|
+
return { sid: res.json.sid, status: res.json.status };
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Options: `accountSid` and `authToken` (required), `path` (required), `method`
|
|
37
|
+
(default `GET`), `params`, `host` (default `api.twilio.com`), `query`.
|
|
38
|
+
|
|
39
|
+
`params` become the form body on a write and the query string on a read.
|
|
40
|
+
|
|
41
|
+
A `path` **without** a leading slash is an Account resource and lands under
|
|
42
|
+
`/2010-04-01/Accounts/<sid>/`. One **with** a leading slash is used as written,
|
|
43
|
+
which is how the other products are reached.
|
|
44
|
+
|
|
45
|
+
## WhatsApp
|
|
46
|
+
|
|
47
|
+
Same endpoint; the numbers carry a `whatsapp:` prefix.
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const req = await request({
|
|
51
|
+
accountSid, authToken, path: "Messages.json", method: "POST",
|
|
52
|
+
params: {
|
|
53
|
+
To: `whatsapp:${inputs.to}`,
|
|
54
|
+
From: `whatsapp:${inputs.from}`,
|
|
55
|
+
Body: inputs.text
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Reading messages
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
const req = await request({
|
|
64
|
+
accountSid, authToken, path: "Messages.json",
|
|
65
|
+
params: { To: inputs.to, PageSize: 50 }
|
|
66
|
+
});
|
|
67
|
+
const { messages } = (await fetch(req.url, req)).json;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Number lookup
|
|
71
|
+
|
|
72
|
+
Lookup lives on its own host, so pass an absolute path:
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
const req = await request({
|
|
76
|
+
accountSid, authToken,
|
|
77
|
+
host: "lookups.twilio.com",
|
|
78
|
+
path: `/v2/PhoneNumbers/${encodeURIComponent(inputs.phone)}`,
|
|
79
|
+
params: { Fields: "line_type_intelligence" }
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Gotchas
|
|
84
|
+
|
|
85
|
+
- **`request` is async.** A host call is a round trip.
|
|
86
|
+
- **Parameter names are PascalCase.** `To`, `From`, `Body`, `MediaUrl` —
|
|
87
|
+
Twilio ignores what it does not recognize, so a lowercase `body` sends an
|
|
88
|
+
empty message rather than an error.
|
|
89
|
+
- **Numbers are E.164.** `+15551234567`, country code and all.
|
|
90
|
+
- **Only `*.twilio.com` hosts are accepted**, so a mistyped `host` fails here
|
|
91
|
+
rather than mailing credentials somewhere else.
|
|
92
|
+
- **An error is a non-2xx with JSON.** Read `res.json.message` and
|
|
93
|
+
`res.json.code`; the code maps to Twilio's error reference.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-twilio",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Build authenticated Twilio API requests inside the NodeTool sandbox, from NodeTool's helper 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": "twilio"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-twilio"
|
|
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
|
+
"twilio",
|
|
37
|
+
"sms"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-xlsx
|
|
3
|
+
description: Read and write Excel workbooks in a Code node or CodeAct action, with exceljs running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Excel workbooks in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-xlsx`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
exceljs is built on Node streams and ships its own zip layer; it will never be a
|
|
11
|
+
guest module. This pack is a **host module**: the import resolves to a generated
|
|
12
|
+
facade over NodeTool's own implementation.
|
|
13
|
+
|
|
14
|
+
## parse — workbook bytes to records
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
import { parse } from "@nodetool-ai/sandbox-xlsx";
|
|
18
|
+
|
|
19
|
+
const bytes = await workspace.readBytes("report.xlsx");
|
|
20
|
+
const sheets = await parse(bytes); // { "Sheet1": [...], "Costs": [...] }
|
|
21
|
+
const rows = await parse(bytes, { sheet: "Costs" }); // one sheet's rows
|
|
22
|
+
return { sheetNames: Object.keys(sheets), rows };
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Options: `sheet` (name — returns that sheet's rows directly) and `header`
|
|
26
|
+
(default `true`; `false` gives raw cell arrays). Formula cells yield their
|
|
27
|
+
computed result, dates come back as ISO strings, and rich text is flattened.
|
|
28
|
+
|
|
29
|
+
Get the bytes from `workspace.readBytes`, or from a fetched body with
|
|
30
|
+
`await response.bytes()`.
|
|
31
|
+
|
|
32
|
+
## write — records to workbook bytes
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { write } from "@nodetool-ai/sandbox-xlsx";
|
|
36
|
+
|
|
37
|
+
const bytes = await write({ Costs: inputs.rows, Notes: [{ note: "draft" }] });
|
|
38
|
+
await workspace.writeBytes("report.xlsx", bytes);
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`{sheetName: rows}` is the short form. The long form is an array, one entry per
|
|
42
|
+
sheet, which is where per-sheet options live:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
const bytes = await write([
|
|
46
|
+
{
|
|
47
|
+
name: "Costs",
|
|
48
|
+
rows: inputs.rows,
|
|
49
|
+
columns: ["item", "usd"], // pin the column order
|
|
50
|
+
styles: [
|
|
51
|
+
{ range: "A1:B1", bold: true, background: "FFE9A8" },
|
|
52
|
+
{ range: "B2:B999", numberFormat: "$#,##0.00" }
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
]);
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Rows are records by default, and the header is the union of their keys in
|
|
59
|
+
first-seen order unless `columns` pins it. `header: false` takes arrays of
|
|
60
|
+
cells instead and writes no header row. Column widths are fitted to the
|
|
61
|
+
content; pass `{ autoFitColumns: false }` to leave them alone. A style's
|
|
62
|
+
`range` is `A1` or `A1:C20`, and it takes `bold`, `italic`, `size`, `color`,
|
|
63
|
+
`background` (hex, with or without `#`) and `numberFormat`.
|
|
64
|
+
|
|
65
|
+
## Gotchas
|
|
66
|
+
|
|
67
|
+
- **Both exports are async.**
|
|
68
|
+
- **10 MB per workbook read.** Larger input is refused by name.
|
|
69
|
+
- **A missing sheet name throws**, and the error lists the sheets that exist.
|
|
70
|
+
- **`write` caps a workbook at 64 sheets and 250 000 cells.**
|
|
71
|
+
- **Values that are not a number, string, boolean or date are stored as JSON
|
|
72
|
+
text.** A cell cannot hold bytes.
|
|
73
|
+
- **Nothing is saved for you.** `write` returns bytes; `workspace.writeBytes`
|
|
74
|
+
(or `sandboxToAsset`) is what puts them somewhere.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-xlsx",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Read Excel workbooks inside the NodeTool sandbox, from exceljs 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": "xlsx"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-xlsx"
|
|
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
|
+
"xlsx",
|
|
37
|
+
"excel",
|
|
38
|
+
"spreadsheet"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-xml
|
|
3
|
+
description: Parse XML feeds and sitemaps in a Code node or CodeAct action, with fast-xml-parser running on the host
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XML in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-xml`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
fast-xml-parser reads a bare `window`, which the guest does not have, so it
|
|
11
|
+
cannot be compiled in. This pack is a **host module**: the import resolves to a
|
|
12
|
+
generated facade over NodeTool's own implementation.
|
|
13
|
+
|
|
14
|
+
## parse — XML to a plain object
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
import { parse } from "@nodetool-ai/sandbox-xml";
|
|
18
|
+
|
|
19
|
+
const feed = await parse(inputs.xml);
|
|
20
|
+
const items = feed?.rss?.channel?.item ?? [];
|
|
21
|
+
return { titles: items.map((i) => i.title) };
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Attributes ride along prefixed `@_` so they never collide with child-element
|
|
25
|
+
keys; pass `{ attributes: false }` to drop them. Text values stay text — a
|
|
26
|
+
numeric-looking id must not change shape between runs.
|
|
27
|
+
|
|
28
|
+
Invalid XML throws with the parser's own reason rather than returning a partial
|
|
29
|
+
tree.
|
|
30
|
+
|
|
31
|
+
## Gotchas
|
|
32
|
+
|
|
33
|
+
- **`parse` is async.**
|
|
34
|
+
- **5 MB of text per call.**
|
|
35
|
+
- **A single child is not an array.** `channel.item` is one object when the feed
|
|
36
|
+
has one item; normalize with `[].concat(x ?? [])`.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-xml",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Parse XML feeds and sitemaps inside the NodeTool sandbox, from fast-xml-parser 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": "xml"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-xml"
|
|
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
|
+
"xml",
|
|
37
|
+
"rss",
|
|
38
|
+
"sitemap"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-yaml
|
|
3
|
+
description: Read and write YAML inside a Code node or CodeAct action, with js-yaml running in the guest
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# YAML in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-yaml`. One module, the js-yaml root export.
|
|
9
|
+
Import it at the top of the body.
|
|
10
|
+
|
|
11
|
+
## load — YAML text to a value
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import yaml from "@nodetool-ai/sandbox-yaml";
|
|
15
|
+
|
|
16
|
+
const config = yaml.load(inputs.text);
|
|
17
|
+
return { name: config.name, replicas: config.replicas };
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`load` reads one document and throws a `YAMLException` with a line and column
|
|
21
|
+
on malformed input. Multi-document files go through `loadAll`, which returns an
|
|
22
|
+
array.
|
|
23
|
+
|
|
24
|
+
## dump — a value to YAML text
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import yaml from "@nodetool-ai/sandbox-yaml";
|
|
28
|
+
|
|
29
|
+
return { text: yaml.dump({ name: inputs.name, tags: inputs.tags }, { indent: 2 }) };
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`dump` throws on a cyclic structure unless you pass `{ noRefs: false }`, and on
|
|
33
|
+
a value it cannot represent (a function, a symbol).
|
|
34
|
+
|
|
35
|
+
## Gotchas
|
|
36
|
+
|
|
37
|
+
- **Everything runs in the guest.** The 64 MB guest heap holds your input text,
|
|
38
|
+
the parse tree, and the returned value at once. A file of a few megabytes is
|
|
39
|
+
fine; a hundred megabytes is not.
|
|
40
|
+
- **No timers, no I/O.** The guest has no `setTimeout`, no filesystem, and no
|
|
41
|
+
Node builtins. js-yaml needs none of them — that is why it is admitted — but
|
|
42
|
+
code you write around it must not reach for them either.
|
|
43
|
+
- **The safe schema is not the default.** `yaml.load` uses `DEFAULT_SCHEMA`,
|
|
44
|
+
which resolves tags such as `!!timestamp`. For input from a stranger, pass
|
|
45
|
+
`{ schema: yaml.FAILSAFE_SCHEMA }` and get strings, arrays, and objects only.
|
|
46
|
+
- **This pack is the only route to YAML.** There is no `data.parseYaml` global
|
|
47
|
+
any more; every library the sandbox offers is an importable module, and this
|
|
48
|
+
is the one for YAML. A node that needs it declares it.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-yaml",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "YAML parsing and dumping inside the NodeTool sandbox, from js-yaml",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"js-yaml": "^4.3.0"
|
|
8
|
+
},
|
|
9
|
+
"nodetool": {
|
|
10
|
+
"apiVersion": 1,
|
|
11
|
+
"recommended": true,
|
|
12
|
+
"sandboxModules": [
|
|
13
|
+
{
|
|
14
|
+
"name": ".",
|
|
15
|
+
"kind": "js",
|
|
16
|
+
"npm": "js-yaml"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
23
|
+
"directory": "packages/sandbox-packs/sandbox-yaml"
|
|
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
|
+
"yaml"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sandbox-zip
|
|
3
|
+
description: Read and write zip archives in a Code node or CodeAct action, with fflate running on the host under a 50 MB inflation cap
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Zip archives in the sandbox
|
|
7
|
+
|
|
8
|
+
Specifier: `@nodetool-ai/sandbox-zip`. Import it at the top of the body.
|
|
9
|
+
|
|
10
|
+
## Why this one runs on the host
|
|
11
|
+
|
|
12
|
+
fflate is pure JavaScript and the sandbox compiler admits it, so this pack
|
|
13
|
+
*could* have shipped as a guest module — and an earlier version did. It does
|
|
14
|
+
not, because of the cap: a zip bomb is a policy question, and a policy enforced
|
|
15
|
+
inside the guest is enforced by code the guest can simply not call. The guest's
|
|
16
|
+
64 MB heap does not replicate it either — fflate inflates into host memory
|
|
17
|
+
first. So the library stays on the host, with `unzip` refusing anything that
|
|
18
|
+
inflates past **50 MB**, and there is no second route around that number.
|
|
19
|
+
|
|
20
|
+
## unzip — extract an archive
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { unzip } from "@nodetool-ai/sandbox-zip";
|
|
24
|
+
|
|
25
|
+
const files = await unzip(inputs.archive); // { "a/b.txt": Uint8Array }
|
|
26
|
+
const readme = new TextDecoder().decode(files["README.md"]);
|
|
27
|
+
return { names: Object.keys(files), readme };
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Entry values arrive as real `Uint8Array`s. Decode text with `TextDecoder`.
|
|
31
|
+
|
|
32
|
+
## zip — build one
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { zip } from "@nodetool-ai/sandbox-zip";
|
|
36
|
+
|
|
37
|
+
const archive = await zip({
|
|
38
|
+
"report.md": inputs.markdown, // strings are UTF-8 encoded
|
|
39
|
+
"data.json": JSON.stringify(inputs.rows)
|
|
40
|
+
});
|
|
41
|
+
await workspace.writeBytes("out.zip", archive);
|
|
42
|
+
return { bytes: archive.length };
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Entry values are `Uint8Array` or `string`.
|
|
46
|
+
|
|
47
|
+
## Gotchas
|
|
48
|
+
|
|
49
|
+
- **Both exports are async.**
|
|
50
|
+
- **10 MB in, 50 MB out.** The archive itself is capped at 10 MB; the sum of the
|
|
51
|
+
entries `unzip` produces — and the sum of what `zip` is handed — is capped at
|
|
52
|
+
50 MB, checked as the entries are walked so a bomb stops part way.
|
|
53
|
+
- **No streaming.** The whole archive is materialized. For a payload near the
|
|
54
|
+
cap, write entries to the workspace as you go instead.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nodetool-ai/sandbox-zip",
|
|
3
|
+
"version": "0.8.4",
|
|
4
|
+
"description": "Read and write zip archives inside the NodeTool sandbox, from fflate running on the host with a 50 MB inflation cap",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"nodetool": {
|
|
7
|
+
"apiVersion": 1,
|
|
8
|
+
"recommended": true,
|
|
9
|
+
"sandboxModules": [
|
|
10
|
+
{
|
|
11
|
+
"name": ".",
|
|
12
|
+
"kind": "host",
|
|
13
|
+
"host": "zip"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/nodetool-ai/nodetool.git",
|
|
20
|
+
"directory": "packages/sandbox-packs/sandbox-zip"
|
|
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
|
+
"zip",
|
|
37
|
+
"archive",
|
|
38
|
+
"compression"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
@@ -46,6 +46,8 @@ export interface CodeNodeValidationInput {
|
|
|
46
46
|
connectedInputs?: readonly string[];
|
|
47
47
|
/** Output handles the node declares (`dynamic_outputs` keys). */
|
|
48
48
|
declaredOutputs: readonly string[];
|
|
49
|
+
/** Scripts always send outputs through emit/output, including non-streaming bodies. */
|
|
50
|
+
outputContract?: "emit";
|
|
49
51
|
/** Output handles other nodes are wired to. A superset check on `keys`. */
|
|
50
52
|
connectedOutputs?: readonly string[];
|
|
51
53
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"code-node-validation.d.ts","sourceRoot":"","sources":["../src/code-node-validation.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAwBjE,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAEjD,CAAC;AAEH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAuC9C,CAAC;AAkBH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,iEAAiE;IACjE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACpD;AAiCD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,GAC7B,aAAa,EAAE,CAsXjB"}
|
|
1
|
+
{"version":3,"file":"code-node-validation.d.ts","sourceRoot":"","sources":["../src/code-node-validation.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAwBjE,qEAAqE;AACrE,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,MAAM,CAEjD,CAAC;AAEH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAuC9C,CAAC;AAkBH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B;;;;;;;;;OASG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd;;;OAGG;IACH,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,iEAAiE;IACjE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;CACpD;AAiCD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,uBAAuB,GAC7B,aAAa,EAAE,CAsXjB"}
|
|
@@ -359,7 +359,7 @@ export function validateCodeNodeBody(input) {
|
|
|
359
359
|
// A body that calls `emit`/`output` names its handles, so the return-path
|
|
360
360
|
// analysis below does not apply to it at all — its returns are control flow
|
|
361
361
|
// and carry nothing.
|
|
362
|
-
if (usesEmitOutputContract(code)) {
|
|
362
|
+
if (input.outputContract === "emit" || usesEmitOutputContract(code)) {
|
|
363
363
|
issues.push(...emitContractIssues(parsed.statements, declared, connected));
|
|
364
364
|
return withUnusedInputs(issues, declaredInputsUnused);
|
|
365
365
|
}
|