@nodetool-ai/agents 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/_skills/LICENSE-iart-motion-design-skills +21 -0
- package/dist/_skills/README.md +211 -0
- package/dist/_skills/api-agents/SKILL.md +58 -0
- package/dist/_skills/api-apps/SKILL.md +54 -0
- package/dist/_skills/api-assets/SKILL.md +66 -0
- package/dist/_skills/api-collections/SKILL.md +33 -0
- package/dist/_skills/api-games/SKILL.md +81 -0
- package/dist/_skills/api-media/SKILL.md +131 -0
- package/dist/_skills/api-memory/SKILL.md +72 -0
- package/dist/_skills/api-models/SKILL.md +78 -0
- package/dist/_skills/api-scripts/SKILL.md +79 -0
- package/dist/_skills/api-settings/SKILL.md +49 -0
- package/dist/_skills/api-sketches/SKILL.md +61 -0
- package/dist/_skills/api-storyboards/SKILL.md +94 -0
- package/dist/_skills/api-timelines/SKILL.md +151 -0
- package/dist/_skills/api-web/SKILL.md +57 -0
- package/dist/_skills/api-workflows/SKILL.md +123 -0
- package/dist/_skills/beat-sync-editing/SKILL.md +208 -0
- package/dist/_skills/caption-titles/SKILL.md +94 -0
- package/dist/_skills/color-motion/SKILL.md +185 -0
- package/dist/_skills/commercial-beat-sheet/SKILL.md +338 -0
- package/dist/_skills/elevenlabs-audio-prompting/SKILL.md +163 -0
- package/dist/_skills/explainer-storyboard/SKILL.md +63 -0
- package/dist/_skills/flux-2-klein-prompting/SKILL.md +107 -0
- package/dist/_skills/frame-composition/SKILL.md +291 -0
- package/dist/_skills/game-direction/SKILL.md +99 -0
- package/dist/_skills/gpt-image-2-prompting/SKILL.md +161 -0
- package/dist/_skills/hailuo-prompting/SKILL.md +107 -0
- package/dist/_skills/kling-video-prompting/SKILL.md +188 -0
- package/dist/_skills/launch-commercial/SKILL.md +267 -0
- package/dist/_skills/launch-kit/SKILL.md +120 -0
- package/dist/_skills/logo-reveal/SKILL.md +225 -0
- package/dist/_skills/manimgx/SKILL.md +123 -0
- package/dist/_skills/minimax-h3-prompting/SKILL.md +134 -0
- package/dist/_skills/motion-ad/SKILL.md +281 -0
- package/dist/_skills/motion-background/SKILL.md +145 -0
- package/dist/_skills/motion-curves/SKILL.md +302 -0
- package/dist/_skills/motion-direction/SKILL.md +259 -0
- package/dist/_skills/motion-graphics/SKILL.md +217 -0
- package/dist/_skills/motion-principles/SKILL.md +255 -0
- package/dist/_skills/music-video-treatment/SKILL.md +40 -0
- package/dist/_skills/nano-banana-pro-prompting/SKILL.md +133 -0
- package/dist/_skills/native-game/SKILL.md +310 -0
- package/dist/_skills/native-game-reference/SKILL.md +879 -0
- package/dist/_skills/nodetool-3d-scene/SKILL.md +110 -0
- package/dist/_skills/nodetool-api-reference/SKILL.md +338 -0
- package/dist/_skills/nodetool-app-builder/SKILL.md +291 -0
- package/dist/_skills/nodetool-browser-agent/SKILL.md +119 -0
- package/dist/_skills/nodetool-chat-cli/SKILL.md +184 -0
- package/dist/_skills/nodetool-custom-node-developer/SKILL.md +294 -0
- package/dist/_skills/nodetool-deployment/SKILL.md +195 -0
- package/dist/_skills/nodetool-js-scripting/SKILL.md +223 -0
- package/dist/_skills/nodetool-model-provider-config/SKILL.md +348 -0
- package/dist/_skills/nodetool-rag-indexing/SKILL.md +153 -0
- package/dist/_skills/nodetool-sketch/SKILL.md +138 -0
- package/dist/_skills/nodetool-skill-author/SKILL.md +125 -0
- package/dist/_skills/nodetool-troubleshooter/SKILL.md +370 -0
- package/dist/_skills/nodetool-video-post/SKILL.md +149 -0
- package/dist/_skills/nodetool-workflow-builder/SKILL.md +295 -0
- package/dist/_skills/product-commercial/SKILL.md +132 -0
- package/dist/_skills/qwen-image-prompting/SKILL.md +122 -0
- package/dist/_skills/script-video/SKILL.md +106 -0
- package/dist/_skills/seedance-2-prompting/SKILL.md +194 -0
- package/dist/_skills/seedream-prompting/SKILL.md +117 -0
- package/dist/_skills/short-film/SKILL.md +123 -0
- package/dist/_skills/stable-audio-prompting/SKILL.md +130 -0
- package/dist/_skills/storyboard-core/SKILL.md +716 -0
- package/dist/_skills/timeline-edit-ops/SKILL.md +736 -0
- package/dist/_skills/trailer-template/SKILL.md +291 -0
- package/dist/_skills/ugc-video/SKILL.md +186 -0
- package/dist/_skills/veo-3-prompting/SKILL.md +140 -0
- package/dist/_skills/video-audio-continuity/SKILL.md +90 -0
- package/dist/_skills/video-clone/SKILL.md +96 -0
- package/dist/_skills/video-workflow/SKILL.md +119 -0
- package/dist/_skills/wan-2-6-prompting/SKILL.md +107 -0
- package/dist/app-build/bridge.d.ts.map +1 -1
- package/dist/app-build/bridge.js +44 -17
- package/dist/app-build/bridge.js.map +1 -1
- package/dist/capabilities/apps.d.ts.map +1 -1
- package/dist/capabilities/apps.js +55 -13
- package/dist/capabilities/apps.js.map +1 -1
- package/dist/capabilities/apps.specs.d.ts.map +1 -1
- package/dist/capabilities/apps.specs.js +5 -3
- package/dist/capabilities/apps.specs.js.map +1 -1
- package/dist/capabilities/game-asset-browser.d.ts.map +1 -1
- package/dist/capabilities/game-asset-browser.js +6 -1
- package/dist/capabilities/game-asset-browser.js.map +1 -1
- package/dist/capabilities/game.d.ts +1 -1
- package/dist/capabilities/game.d.ts.map +1 -1
- package/dist/capabilities/game.js +71 -56
- package/dist/capabilities/game.js.map +1 -1
- package/dist/capabilities/game.specs.js +1 -1
- package/dist/capabilities/game.specs.js.map +1 -1
- package/dist/capabilities/game3d.d.ts.map +1 -1
- package/dist/capabilities/game3d.js +14 -19
- package/dist/capabilities/game3d.js.map +1 -1
- package/dist/capabilities/gameAssertions.d.ts +52 -0
- package/dist/capabilities/gameAssertions.d.ts.map +1 -0
- package/dist/capabilities/gameAssertions.js +32 -0
- package/dist/capabilities/gameAssertions.js.map +1 -0
- package/dist/capabilities/models.d.ts.map +1 -1
- package/dist/capabilities/models.js +9 -0
- package/dist/capabilities/models.js.map +1 -1
- package/dist/capabilities/storyboards.d.ts.map +1 -1
- package/dist/capabilities/storyboards.js +36 -11
- package/dist/capabilities/storyboards.js.map +1 -1
- package/dist/capabilities/storyboards.specs.d.ts.map +1 -1
- package/dist/capabilities/storyboards.specs.js +11 -1
- package/dist/capabilities/storyboards.specs.js.map +1 -1
- package/dist/capabilities/workflows.d.ts.map +1 -1
- package/dist/capabilities/workflows.js +1 -0
- package/dist/capabilities/workflows.js.map +1 -1
- package/dist/capabilities/workflows.specs.d.ts.map +1 -1
- package/dist/capabilities/workflows.specs.js +4 -3
- package/dist/capabilities/workflows.specs.js.map +1 -1
- package/dist/evals/surfaces/game.d.ts.map +1 -1
- package/dist/evals/surfaces/game.js +29 -1
- package/dist/evals/surfaces/game.js.map +1 -1
- package/dist/game-authoring.d.ts +120 -0
- package/dist/game-authoring.d.ts.map +1 -1
- package/dist/game-build-integrity.d.ts +12 -0
- package/dist/game-build-integrity.d.ts.map +1 -0
- package/dist/game-build-integrity.js +78 -0
- package/dist/game-build-integrity.js.map +1 -0
- package/dist/game-examples.d.ts +44 -3
- package/dist/game-examples.d.ts.map +1 -1
- package/dist/game-examples.js +60 -10
- package/dist/game-examples.js.map +1 -1
- package/dist/system-skills.d.ts +1 -1
- package/dist/system-skills.js +1 -1
- package/dist/tools/builtin-tools.d.ts.map +1 -1
- package/dist/tools/builtin-tools.js +2 -0
- package/dist/tools/builtin-tools.js.map +1 -1
- package/package.json +19 -19
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodetool-3d-scene
|
|
3
|
+
description: "Build, edit, validate or render a NodeTool 3D model: glTF primitives, transforms, lights, material colors, generated meshes, and headless Blender renders. For a playable 3D game, use native-game."
|
|
4
|
+
featured: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Work a NodeTool 3D model
|
|
8
|
+
|
|
9
|
+
A 3D model is a `.glb` or `.gltf` **asset**, addressed by its asset id. The
|
|
10
|
+
capabilities edit the stored glTF in place and save it back over the same asset,
|
|
11
|
+
so the id stays valid and an open editor reloads it.
|
|
12
|
+
|
|
13
|
+
For a playable game, 2D or 3D, use `native-game`: it authors 3D games with
|
|
14
|
+
`dimension: "3d"`. For a 3D clip inside a cut, build the model here and place it
|
|
15
|
+
on a timeline.
|
|
16
|
+
|
|
17
|
+
## The loop
|
|
18
|
+
|
|
19
|
+
1. **Find it.** `list_model3ds` returns asset id, name, content type and size.
|
|
20
|
+
Nothing to start from: `create_model3d {name, ops?}` makes an empty glTF
|
|
21
|
+
scene and can apply the whole scene in the same call.
|
|
22
|
+
2. **Read it.** `get_model3d {model_id}` lists every object with its uuid, name,
|
|
23
|
+
type, visibility, transform and material color, plus the scene's world-space
|
|
24
|
+
bounds. Call this before editing, for the uuids.
|
|
25
|
+
3. **Edit.** `edit_model3d {model_id, ops: [...]}`. Operations run in order.
|
|
26
|
+
Anything they do not name — meshes, textures, skins, animations — is kept, so
|
|
27
|
+
an imported model survives an edit.
|
|
28
|
+
4. **Validate.** `validate_model3d {model_id | document}`.
|
|
29
|
+
5. **Render**, when a picture is asked for. `render_model3d {model_id}` goes
|
|
30
|
+
through headless Blender, honors scene cameras and lights, and stores a PNG
|
|
31
|
+
asset. It needs Blender on the server and is not offered on the cloud
|
|
32
|
+
profile. `engine` is `eevee` (default, fast) or `cycles` (slower);
|
|
33
|
+
`camera_mode` is `auto`, `scene` or `orbit`. A Cycles render blocks the call,
|
|
34
|
+
so pass `background: true` to get a `generation_id` at once and collect the
|
|
35
|
+
PNG with `await_generation`.
|
|
36
|
+
|
|
37
|
+
## A real mesh
|
|
38
|
+
|
|
39
|
+
The ops add primitives only. For an object with real geometry, generate one:
|
|
40
|
+
`run_node` with `nodetool.model3d.TextTo3D {model, prompt}` or
|
|
41
|
+
`nodetool.model3d.ImageTo3D {model, image}` returns a `model_3d` output. Read
|
|
42
|
+
`get_node_info` first for the `model` field's shape. These call a paid
|
|
43
|
+
provider, so confirm with the user before generating. The other
|
|
44
|
+
`nodetool.model3d.*` nodes (`Decimate`, `RepairMesh`, `FormatConverter`,
|
|
45
|
+
`Transform3D`, …) and the `nodetool.blender.*` nodes process a mesh inside a
|
|
46
|
+
workflow.
|
|
47
|
+
|
|
48
|
+
## `edit_model3d` ops
|
|
49
|
+
|
|
50
|
+
| Op | Fields |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `add_object` | `kind`: `box`, `sphere`, `plane`, `cylinder`, `torus`, `directionalLight`, `pointLight`. Optional `name` |
|
|
53
|
+
| `delete_object` | `target` |
|
|
54
|
+
| `set_transform` | `position`, `rotation` (Euler **degrees**), `scale`, each `[x, y, z]` |
|
|
55
|
+
| `set_visibility` | `visible` |
|
|
56
|
+
| `rename_object` | `target`, `name` |
|
|
57
|
+
| `set_material_color` | `color` as a CSS hex string, meshes only |
|
|
58
|
+
| `select_object` | `target`, or `null` to clear |
|
|
59
|
+
|
|
60
|
+
`target` is a uuid or a name. Object ids are stamped into
|
|
61
|
+
`node.extras.nodetool_id`, because glTF addresses nodes by array index and a
|
|
62
|
+
delete renumbers them. Duplicate names make addressing ambiguous, which
|
|
63
|
+
`validate_model3d` warns about.
|
|
64
|
+
|
|
65
|
+
`delete_object` keeps the file valid: an animation left with no channels is
|
|
66
|
+
removed, and so is a skin that lost a joint, which leaves its mesh in the bind
|
|
67
|
+
pose. `set_material_color` recolors only the named object, copying a material
|
|
68
|
+
or mesh it shares with another object first.
|
|
69
|
+
|
|
70
|
+
These are the `ui_3d_*` verbs with no editor open. The operations, the units and
|
|
71
|
+
the addressing live in `@nodetool-ai/model3d`, shared with the browser editor, so
|
|
72
|
+
a model built headlessly opens there unchanged. Headlessly, a light is a
|
|
73
|
+
`directionalLight` or `pointLight` and a material can only be recolored.
|
|
74
|
+
Light settings, other material fields and parenting need the open editor:
|
|
75
|
+
`ui_3d_set_light`, `ui_3d_set_material`, `ui_3d_set_parent`.
|
|
76
|
+
|
|
77
|
+
## No camera headlessly
|
|
78
|
+
|
|
79
|
+
`ui_3d_frame_scene` and `ui_3d_capture_view` need a WebGL context. Without one,
|
|
80
|
+
`get_model3d`'s world-space bounds are what answer "how big is this and where is
|
|
81
|
+
it". Use `render_model3d` when an actual picture is required.
|
|
82
|
+
|
|
83
|
+
## What `validate_model3d` catches
|
|
84
|
+
|
|
85
|
+
The glTF version, references that resolve to nothing (node, mesh, accessor,
|
|
86
|
+
material, buffer, skin, camera, skin joint, animation target and sampler), a
|
|
87
|
+
node with two parents, a cycle in the node hierarchy, a node carrying both a
|
|
88
|
+
matrix and TRS fields, an accessor with an unknown type or reading past its
|
|
89
|
+
buffer view, a buffer view reading past its buffer, an undeclared light, and an
|
|
90
|
+
extension this build cannot honor. It warns on an empty scene, geometry with no
|
|
91
|
+
light, and duplicate names. It only reads the document, and it handles
|
|
92
|
+
hierarchies of any depth.
|
|
93
|
+
|
|
94
|
+
## On a timeline
|
|
95
|
+
|
|
96
|
+
A `model3d` layer is the one kind `preview_timeline_frame` cannot draw on its
|
|
97
|
+
own canvas. The preview pass collects every 3D layer across the requested
|
|
98
|
+
instants, groups them by glTF plus the options that fix a renderer, and hands
|
|
99
|
+
each group to one headless Chromium page. Two fields on the layer's report say
|
|
100
|
+
what the pixels do not: `camera` (the pose it was drawn with, authored camera
|
|
101
|
+
folded with the animated channels) and `animation_time_sec` (the glTF
|
|
102
|
+
animation's own clock, not timeline time). With no Chrome on the host the group
|
|
103
|
+
is left out and reported as a `model3d_unavailable` degradation.
|
|
104
|
+
|
|
105
|
+
## Reference
|
|
106
|
+
|
|
107
|
+
In a NodeTool checkout, these repository sources go further:
|
|
108
|
+
|
|
109
|
+
- `docs/harnesses.md` § 3D scene tools
|
|
110
|
+
- `docs/harnesses.md` § 3D clips in preview_timeline_frame
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nodetool-api-reference
|
|
3
|
+
description: "Integrate with NodeTool over REST, tRPC, MsgPack WebSocket, MCP, or the OpenAI-compatible Chat API, including the document surfaces and workflow execution."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You help users integrate with NodeTool's HTTP + WebSocket server (default `http://localhost:7777`). Start it with `nodetool serve` (flags: `--host`, `--port`).
|
|
7
|
+
|
|
8
|
+
# Surfaces
|
|
9
|
+
|
|
10
|
+
| Surface | Path prefix | Use case |
|
|
11
|
+
|---------|-------------|----------|
|
|
12
|
+
| **REST** | `/api/...` | Workflows, assets, collections, models, bundles, health |
|
|
13
|
+
| **tRPC** | `/trpc/...` | The document surfaces: timelines, storyboards, sketches, scripts, applications, JS scripts, projects, skills, settings |
|
|
14
|
+
| **OpenAI-compatible** | `/v1/...` | Chat completions + model list |
|
|
15
|
+
| **WebSocket** | `/ws` | Run/cancel/stream jobs, live chat, live editor tools |
|
|
16
|
+
| **MCP** | `/mcp` | Agent tools over streamable HTTP, for Claude Desktop and CLI agents |
|
|
17
|
+
|
|
18
|
+
Auth is controlled by environment variables, not CLI flags (§ Authentication).
|
|
19
|
+
|
|
20
|
+
**Pick the right surface.** REST covers workflows, assets and the portable
|
|
21
|
+
bundles. Everything that is a *document* someone edits (a timeline sequence, a
|
|
22
|
+
storyboard, a sketch, a script, a mini app, a JS script) is a tRPC router, and
|
|
23
|
+
the REST routes for those kinds cover only import, export and build. An
|
|
24
|
+
integration that reads or writes a document calls tRPC, or calls the agent
|
|
25
|
+
capability of the same name over `/mcp`.
|
|
26
|
+
|
|
27
|
+
# Authentication
|
|
28
|
+
|
|
29
|
+
The server picks its auth mode from `SUPABASE_URL` and `SUPABASE_KEY` alone. It
|
|
30
|
+
reads neither `AUTH_PROVIDER` nor `NODETOOL_SERVER_MODE`.
|
|
31
|
+
|
|
32
|
+
| Mode | Enabled by | Accepted credentials |
|
|
33
|
+
|------|------------|----------------------|
|
|
34
|
+
| Local | Default, with the Supabase variables unset | Loopback connections run as user `"1"` with no token. `NODETOOL_TRUST_LOCALHOST=false` turns that off. Sources in `NODETOOL_TRUST_LOCAL_NETWORKS` (comma-separated CIDRs) also run as user `"1"` with no token. A bearer equal to `SERVER_AUTH_TOKEN` runs as user `"1"`. A token minted by `nodetool deploy users-add` runs as that API user. Anything else gets `401`. |
|
|
35
|
+
| Supabase | `SUPABASE_URL` and `SUPABASE_KEY` both set | Every non-public request needs a valid Supabase JWT. `SERVER_AUTH_TOKEN`, `NODETOOL_TRUST_LOCAL_NETWORKS` and API-user tokens are ignored. Loopback is trusted only with `NODETOOL_TRUST_LOCALHOST=true`. |
|
|
36
|
+
|
|
37
|
+
In both modes, an access token (`ntk_…`) created in **Settings → MCP → Connect
|
|
38
|
+
an agent remotely** authenticates as the person who created it. Send any token
|
|
39
|
+
as `Authorization: Bearer <token>`. A WebSocket client that cannot set headers
|
|
40
|
+
passes `?api_key=<token>` on the `/ws` URL.
|
|
41
|
+
|
|
42
|
+
# REST Endpoints
|
|
43
|
+
|
|
44
|
+
## Workflows
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# List workflows
|
|
48
|
+
curl http://localhost:7777/api/workflows \
|
|
49
|
+
-H "Authorization: Bearer TOKEN"
|
|
50
|
+
|
|
51
|
+
# Get a workflow
|
|
52
|
+
curl http://localhost:7777/api/workflows/<id> \
|
|
53
|
+
-H "Authorization: Bearer TOKEN"
|
|
54
|
+
|
|
55
|
+
# Export helpers
|
|
56
|
+
curl http://localhost:7777/api/workflows/<id>/dsl-export # TypeScript DSL
|
|
57
|
+
curl http://localhost:7777/api/workflows/<id>/export-bundle # .nodetool bundle (zip)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Run a saved workflow over REST. This is the route `run_workflow`,
|
|
61
|
+
`debug_workflow` and `nodetool debug` use. The editor runs over WebSocket
|
|
62
|
+
instead (§ WebSocket API).
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
curl -X POST http://localhost:7777/api/workflows/<id>/run \
|
|
66
|
+
-H "Authorization: Bearer TOKEN" \
|
|
67
|
+
-H "Content-Type: application/json" \
|
|
68
|
+
-d '{"params": {"prompt": "a red fox"}}'
|
|
69
|
+
# Same body, returns the full debug report (summary and verdict) instead of the run row
|
|
70
|
+
curl -X POST http://localhost:7777/api/workflows/<id>/debug ...
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The body also takes `background: true` to return a job id at once, and
|
|
74
|
+
`interactive: true` to park on escalations as a debug session (below).
|
|
75
|
+
|
|
76
|
+
## Documents (tRPC)
|
|
77
|
+
|
|
78
|
+
The routers under `/trpc`, one per document kind:
|
|
79
|
+
`timeline`, `storyboards`, `sketch`, `scripts`, `applications`, `jsScripts`,
|
|
80
|
+
`documents`, `workflows`, `projects`, `assets`, `collections`, `jobs`, `runs`,
|
|
81
|
+
`appRuns`, `appInstances`, `resources`, `models`, `customProviders`, `nodes`,
|
|
82
|
+
`memories`, `messages`, `threads`, `settings`, `skills`, `storage`, `packs`,
|
|
83
|
+
`costs`, `credits`, `files`, `fonts`, `games`, `integrations`, `triggers`,
|
|
84
|
+
`externalMcp`, `agentAccess`, `users`, `worker`, `workspace`.
|
|
85
|
+
|
|
86
|
+
Each follows the same shape: `list`, `get`, `create`, `update` (compare-and-swap
|
|
87
|
+
on `updated_at`), `delete`, plus sub-routers. Whole-document snapshots are
|
|
88
|
+
`timeline.versions`, `sketch.documentVersions` and `jsScripts.documentVersions`
|
|
89
|
+
(`sketch.versions` is a different thing: the per-layer generation takes).
|
|
90
|
+
`applications` also carries `publish`, `released`, `deploy`, `budget` and
|
|
91
|
+
`usage`, because publishing an app locks in the current graph of every workflow
|
|
92
|
+
it runs and caps what it may spend. Read the router in
|
|
93
|
+
`packages/websocket/src/trpc/routers/` for the exact procedure names rather than
|
|
94
|
+
guessing them. `/trpc/healthz` answers without auth.
|
|
95
|
+
|
|
96
|
+
An agent reaches the same data through the capability tools, which need no
|
|
97
|
+
client: `list_timelines`, `get_storyboard`, `edit_sketch`, `save_js_script`,
|
|
98
|
+
`edit_app`, and so on.
|
|
99
|
+
|
|
100
|
+
## Document REST routes
|
|
101
|
+
|
|
102
|
+
The REST side of the document kinds is import, export and build.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Mini apps
|
|
106
|
+
curl http://localhost:7777/api/applications/:id/export-bundle # app + every bound graph
|
|
107
|
+
curl -X POST http://localhost:7777/api/applications/import-bundle
|
|
108
|
+
curl -X POST http://localhost:7777/api/applications/build # {prompt|spec, provider, model, ...}
|
|
109
|
+
curl -X POST http://localhost:7777/api/applications/debug
|
|
110
|
+
curl http://localhost:7777/api/applications/examples
|
|
111
|
+
curl -X POST http://localhost:7777/api/applications/examples/:slug/install
|
|
112
|
+
|
|
113
|
+
# Timelines and storyboards
|
|
114
|
+
curl http://localhost:7777/api/timelines/:id/export-zip
|
|
115
|
+
curl -X POST http://localhost:7777/api/timelines/import-zip
|
|
116
|
+
curl http://localhost:7777/api/storyboards/:id/export-zip
|
|
117
|
+
curl -X POST http://localhost:7777/api/timelines/:id/isolate-subject
|
|
118
|
+
|
|
119
|
+
# Native games: the published revision as a zip (target=web or tauri)
|
|
120
|
+
curl -o game.zip 'http://localhost:7777/api/games/:id/export-zip?target=tauri'
|
|
121
|
+
# Compile the desktop executable on this machine; streams cargo output as NDJSON (refused on hosted servers)
|
|
122
|
+
curl -N -X POST http://localhost:7777/api/games/:id/build-executable
|
|
123
|
+
|
|
124
|
+
# JS scripts
|
|
125
|
+
curl -X POST http://localhost:7777/api/js-scripts/:id/run
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A build or an interactive debug runs for minutes, so those routes accept
|
|
129
|
+
`poll: true`, return a session id, and are read at
|
|
130
|
+
`GET /api/debug/sessions/:id` until they settle. Cancel with
|
|
131
|
+
`POST /api/debug/sessions/:id/cancel`.
|
|
132
|
+
|
|
133
|
+
## Collections (RAG)
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Upload a text file into a collection (multipart, field name "file")
|
|
137
|
+
curl -X POST http://localhost:7777/api/collections/<name>/index \
|
|
138
|
+
-H "Authorization: Bearer TOKEN" \
|
|
139
|
+
-F "file=@notes.md"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The route indexes text only: plain text, Markdown, HTML, CSV and JSON. It
|
|
143
|
+
returns `415` for PDFs, Office files and images, which need an indexing
|
|
144
|
+
workflow. The collection must have an embedding model.
|
|
145
|
+
|
|
146
|
+
## Models
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# OpenAI-compatible model list
|
|
150
|
+
curl http://localhost:7777/v1/models -H "Authorization: Bearer TOKEN"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Storage / Assets
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Asset bytes are served under /api/storage/...
|
|
157
|
+
curl http://localhost:7777/api/storage/<path>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Health
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
curl http://localhost:7777/health # liveness (no auth)
|
|
164
|
+
curl http://localhost:7777/ready # readiness
|
|
165
|
+
curl http://localhost:7777/api/health # detailed health
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
# Chat API (OpenAI-Compatible)
|
|
169
|
+
|
|
170
|
+
## HTTP
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Chat completion
|
|
174
|
+
curl -X POST http://localhost:7777/v1/chat/completions \
|
|
175
|
+
-H "Authorization: Bearer TOKEN" \
|
|
176
|
+
-H "Content-Type: application/json" \
|
|
177
|
+
-d '{
|
|
178
|
+
"model": "gpt-5.4",
|
|
179
|
+
"messages": [
|
|
180
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
181
|
+
{"role": "user", "content": "Hello!"}
|
|
182
|
+
],
|
|
183
|
+
"stream": false
|
|
184
|
+
}'
|
|
185
|
+
|
|
186
|
+
# Streaming (Server-Sent Events)
|
|
187
|
+
curl -X POST http://localhost:7777/v1/chat/completions \
|
|
188
|
+
-H "Authorization: Bearer TOKEN" \
|
|
189
|
+
-H "Content-Type: application/json" \
|
|
190
|
+
-d '{"model": "gpt-5.4", "messages": [{"role": "user", "content": "Hi"}], "stream": true}'
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Python Client (OpenAI SDK)
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
import openai
|
|
197
|
+
|
|
198
|
+
client = openai.OpenAI(api_key="TOKEN", base_url="http://localhost:7777/v1")
|
|
199
|
+
|
|
200
|
+
response = client.chat.completions.create(
|
|
201
|
+
model="gpt-5.4",
|
|
202
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
203
|
+
)
|
|
204
|
+
print(response.choices[0].message.content)
|
|
205
|
+
|
|
206
|
+
# Streaming
|
|
207
|
+
stream = client.chat.completions.create(
|
|
208
|
+
model="gpt-5.4",
|
|
209
|
+
messages=[{"role": "user", "content": "Hello!"}],
|
|
210
|
+
stream=True,
|
|
211
|
+
)
|
|
212
|
+
for chunk in stream:
|
|
213
|
+
if chunk.choices[0].delta.content:
|
|
214
|
+
print(chunk.choices[0].delta.content, end="")
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## JavaScript Client
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
const response = await fetch("http://localhost:7777/v1/chat/completions", {
|
|
221
|
+
method: "POST",
|
|
222
|
+
headers: {
|
|
223
|
+
Authorization: "Bearer TOKEN",
|
|
224
|
+
"Content-Type": "application/json",
|
|
225
|
+
},
|
|
226
|
+
body: JSON.stringify({
|
|
227
|
+
model: "gpt-5.4",
|
|
228
|
+
messages: [{ role: "user", content: "Hello!" }],
|
|
229
|
+
stream: false,
|
|
230
|
+
}),
|
|
231
|
+
});
|
|
232
|
+
const data = await response.json();
|
|
233
|
+
console.log(data.choices[0].message.content);
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
# WebSocket API — Running Jobs
|
|
237
|
+
|
|
238
|
+
**Endpoint**: `ws(s)://<host>/ws`. Messages are an envelope `{ command, data }`.
|
|
239
|
+
The server replies in MsgPack until the client sends `set_mode` with
|
|
240
|
+
`"text"`. A JSON client sends that first, or `JSON.parse` fails on every reply.
|
|
241
|
+
Identity comes from the connection's credential (§ Authentication), not from
|
|
242
|
+
fields in the request body.
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const socket = new WebSocket("ws://localhost:7777/ws?api_key=<token>");
|
|
246
|
+
|
|
247
|
+
socket.onopen = () => {
|
|
248
|
+
socket.send(JSON.stringify({ command: "set_mode", data: { mode: "text" } }));
|
|
249
|
+
// Start a workflow run
|
|
250
|
+
socket.send(JSON.stringify({
|
|
251
|
+
command: "run_job",
|
|
252
|
+
data: {
|
|
253
|
+
type: "run_job_request",
|
|
254
|
+
workflow_id: "<id>",
|
|
255
|
+
job_type: "workflow",
|
|
256
|
+
params: { input_name: "value" },
|
|
257
|
+
job_id: "<id>",
|
|
258
|
+
},
|
|
259
|
+
}));
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
socket.onmessage = (event) => {
|
|
263
|
+
const msg = JSON.parse(event.data);
|
|
264
|
+
switch (msg.type) {
|
|
265
|
+
case "job_update":
|
|
266
|
+
console.log(`Job ${msg.status}`); // running | completed | failed | cancelled | suspended
|
|
267
|
+
if (msg.result) console.log("Result:", msg.result);
|
|
268
|
+
break;
|
|
269
|
+
case "node_update":
|
|
270
|
+
console.log(`Node ${msg.node_name}: ${msg.status}`);
|
|
271
|
+
break;
|
|
272
|
+
case "node_progress":
|
|
273
|
+
console.log(`Progress: ${msg.progress}/${msg.total}`);
|
|
274
|
+
break;
|
|
275
|
+
case "output_update":
|
|
276
|
+
console.log(`Output ${msg.output_name}:`, msg.value);
|
|
277
|
+
break;
|
|
278
|
+
case "chunk":
|
|
279
|
+
process.stdout.write(msg.content);
|
|
280
|
+
break;
|
|
281
|
+
case "log_update":
|
|
282
|
+
console.log(`[${msg.severity}] ${msg.content}`);
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## Job Control Commands
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
socket.send(JSON.stringify({ command: "cancel_job", data: { job_id: "...", workflow_id: "..." } }));
|
|
292
|
+
socket.send(JSON.stringify({ command: "get_status", data: { job_id: "..." } }));
|
|
293
|
+
socket.send(JSON.stringify({ command: "reconnect_job", data: { job_id: "...", workflow_id: "..." } }));
|
|
294
|
+
|
|
295
|
+
// Stream input into a running node, then close the stream
|
|
296
|
+
socket.send(JSON.stringify({ command: "stream_input", data: { job_id: "...", input: "name", value: "data", handle: "..." } }));
|
|
297
|
+
socket.send(JSON.stringify({ command: "end_input_stream", data: { job_id: "...", input: "name", handle: "..." } }));
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
There is no pause or resume. An unknown command returns `Unknown command`.
|
|
301
|
+
|
|
302
|
+
# Server Message Types
|
|
303
|
+
|
|
304
|
+
| Type | Key fields | Purpose |
|
|
305
|
+
|------|-----------|---------|
|
|
306
|
+
| `job_update` | `status`, `result`, `error`, `cost` | Job lifecycle |
|
|
307
|
+
| `node_update` | `node_id`, `node_name`, `status`, `error`, `result` | Node lifecycle |
|
|
308
|
+
| `node_progress` | `progress`, `total`, `chunk` | Progress tracking |
|
|
309
|
+
| `output_update` | `output_name`, `value`, `output_type` | Node output values |
|
|
310
|
+
| `log_update` | `content`, `severity` | Log messages |
|
|
311
|
+
| `chunk` | `content`, `done` | Streaming text |
|
|
312
|
+
|
|
313
|
+
# MCP
|
|
314
|
+
|
|
315
|
+
`/mcp` serves the agent capability tools over streamable HTTP, so an outside
|
|
316
|
+
agent drives NodeTool with the same calls the in-product agent uses. Reach it
|
|
317
|
+
three ways:
|
|
318
|
+
|
|
319
|
+
- `nodetool mcp install` configures a CLI agent (Claude Code, Codex).
|
|
320
|
+
- In a NodeTool checkout, `npm run build:mcpb` builds `dist/nodetool.mcpb`, a one-file bundle Claude
|
|
321
|
+
Desktop installs by drag-and-drop. It is a stdio-to-HTTP bridge against a
|
|
322
|
+
running server's `/mcp`, and it starts in offline mode when the server is
|
|
323
|
+
down, then hot-attaches when it appears.
|
|
324
|
+
- A deployed server is reached by pointing the client at `/mcp` with a token
|
|
325
|
+
minted in **Settings → MCP → Connect an agent remotely**.
|
|
326
|
+
|
|
327
|
+
# Server Management (CLI)
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
nodetool serve # Start server (default 127.0.0.1:7777)
|
|
331
|
+
nodetool serve --host 0.0.0.0 # Bind all interfaces
|
|
332
|
+
nodetool serve --port 8080 # Custom port
|
|
333
|
+
nodetool workflows list # List saved workflows
|
|
334
|
+
nodetool workflows get <id> # Get workflow details
|
|
335
|
+
nodetool workflows run <id> # Run a workflow (uses the local DB)
|
|
336
|
+
nodetool jobs list # List execution jobs
|
|
337
|
+
nodetool secrets store OPENAI_API_KEY # Store an API key
|
|
338
|
+
```
|