skillscript-runtime 0.18.9 → 0.19.0
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/README.md +1 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +11 -3
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli.js +13 -0
- package/dist/cli.js.map +1 -1
- package/dist/connectors/agent.d.ts +6 -2
- package/dist/connectors/agent.d.ts.map +1 -1
- package/dist/connectors/types.d.ts +2 -8
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/connectors/types.js.map +1 -1
- package/dist/dashboard/server.d.ts +49 -0
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +108 -0
- package/dist/dashboard/server.js.map +1 -1
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +42 -0
- package/dist/errors.js.map +1 -1
- package/dist/mcp-server.js +3 -3
- package/dist/mcp-server.js.map +1 -1
- package/dist/parser.d.ts +1 -1
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +4 -4
- package/dist/parser.js.map +1 -1
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/scheduler.d.ts +54 -11
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +103 -33
- package/dist/scheduler.js.map +1 -1
- package/dist/skill-catalog.js +7 -11
- package/dist/skill-catalog.js.map +1 -1
- package/dist/trace.d.ts +9 -1
- package/dist/trace.d.ts.map +1 -1
- package/dist/trace.js +10 -2
- package/dist/trace.js.map +1 -1
- package/docs/adopter-playbook.md +98 -0
- package/docs/configuration.md +2 -0
- package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
- package/package.json +1 -1
- package/scaffold/.env.example +22 -1
package/docs/adopter-playbook.md
CHANGED
|
@@ -370,6 +370,104 @@ Per-skill capability declaration: skills declare what shell binaries they need i
|
|
|
370
370
|
|
|
371
371
|
The operator policy validates `declared ∩ allowlist` — each skill's shell footprint becomes self-documenting and auditable. Slated for a future ring once the chokepoint + observability surfaces ship.
|
|
372
372
|
|
|
373
|
+
## Trigger model (v0.19.0 — BREAKING)
|
|
374
|
+
|
|
375
|
+
**v0.19.0 collapses the trigger surface to two primitives.** Per the Scott + Perry decision (memory `ceaf4579`):
|
|
376
|
+
|
|
377
|
+
| Primitive | Purpose |
|
|
378
|
+
|---|---|
|
|
379
|
+
| `cron` | Time-based fires (unchanged) |
|
|
380
|
+
| `event` | Generic external-signal fires via HTTP POST to `/event` |
|
|
381
|
+
|
|
382
|
+
The previous sources (`session`, `agent-event`, `file-watch`, `sensor`) are **removed**. They were either parse-only stubs that never fired or substrate-coupled concepts that belong outside the runtime. Anything external becomes an adapter that POSTs to `/event` — including what would have been a session/agent-event/file-watch/sensor trigger. The `DeliveryMeta.origin.trigger_kind` receiver enum also drops `"session"` in lockstep (pre-v1.0 cleanup; the value was never functionally emitted).
|
|
383
|
+
|
|
384
|
+
### The `event` primitive
|
|
385
|
+
|
|
386
|
+
Skills declare an event trigger in their frontmatter:
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
# Skill: prox-handler
|
|
390
|
+
# Status: Approved
|
|
391
|
+
# Triggers: event: prox
|
|
392
|
+
# Vars: ROOM, USER
|
|
393
|
+
|
|
394
|
+
t:
|
|
395
|
+
emit(text="${USER} entered ${ROOM}")
|
|
396
|
+
default: t
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
External services drive the skill by POSTing:
|
|
400
|
+
|
|
401
|
+
```
|
|
402
|
+
POST /event HTTP/1.1
|
|
403
|
+
Host: localhost:7878
|
|
404
|
+
Content-Type: application/json
|
|
405
|
+
Authorization: Bearer <token> # if SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN set
|
|
406
|
+
|
|
407
|
+
{
|
|
408
|
+
"event_name": "prox",
|
|
409
|
+
"params": { "ROOM": "kitchen", "USER": "scott" }
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Response on accept:
|
|
414
|
+
|
|
415
|
+
```json
|
|
416
|
+
{ "run_id": "f4a8b21c-...", "durability": "in-process" }
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
The `run_id` is the runtime's `trace_id` — adopters paste it into the dashboard `/fires` view or query via the `fires({trace_id})` MCP tool to look up completion status.
|
|
420
|
+
|
|
421
|
+
### Wire contract
|
|
422
|
+
|
|
423
|
+
| HTTP status | Meaning |
|
|
424
|
+
|---|---|
|
|
425
|
+
| **200** | Accepted into THIS process's in-memory queue. `{run_id, durability: "in-process"}`. Skill fires async; the 200 does NOT mean skill-completed |
|
|
426
|
+
| **400** | Body not JSON; or `event_name` missing/empty; or params don't match declared (missing required or unknown extras) |
|
|
427
|
+
| **401** | Auth token configured + missing/wrong `Authorization: Bearer <token>` |
|
|
428
|
+
| **404** | `/event` route not enabled OR `event_name` not registered |
|
|
429
|
+
| **405** | Wrong method (POST-only) |
|
|
430
|
+
|
|
431
|
+
**Param validation is strict v1**: every declared param must be present; no unknown params accepted. No defaults; no type coercion. JSON already carries types, and a type mismatch fails inside the consuming op with a real error. Defaults + types may land in v2 if real adopter need surfaces.
|
|
432
|
+
|
|
433
|
+
### `event_name` semantics
|
|
434
|
+
|
|
435
|
+
- **Public contract** addressed by POSTers. Skill behind the event can swap without breaking callers — the `skill_name` is private impl.
|
|
436
|
+
- **Case-insensitive** at register + lookup (normalized to lowercase internally).
|
|
437
|
+
- **1:1**: one `event_name` → exactly one skill in the deployment. Fan-out is NOT supported — a skill can call other skills via `$ execute_skill` if needed.
|
|
438
|
+
- **Cross-skill rebind allowed but audited**: registering an `event_name` that's already bound to a different skill replaces the binding (last-write-wins) AND logs a visible line (`event_name 'X' rebound: skill A → skill B`). Prevents silent cross-skill hijack without blocking the declarative re-save path. Same skill re-registering its own event is a silent upsert.
|
|
439
|
+
|
|
440
|
+
### Enabling the `/event` HTTP ingress
|
|
441
|
+
|
|
442
|
+
Off by default. Two operator knobs:
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
# Required to open the /event route
|
|
446
|
+
SKILLSCRIPT_EVENT_INGRESS_ENABLED=true
|
|
447
|
+
|
|
448
|
+
# Optional bearer-token auth (when set, required on every POST /event)
|
|
449
|
+
SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=<token>
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
When `eventIngressEnabled=true`, the route mounts on the same HTTP server as the dashboard/RPC (no second port). Default bind is `127.0.0.1` (localhost-only) — adopters wanting `0.0.0.0` external reach pass `--host 0.0.0.0` explicitly. Per Perry's framing: "enforce the DMZ assumption by the bind, not by hope."
|
|
453
|
+
|
|
454
|
+
### Durability honesty
|
|
455
|
+
|
|
456
|
+
**`200 = ACCEPTED, not durable**.** The skill is queued in this process's memory; if the process crashes or restarts before the queue drains, the fire is lost. The `durability: "in-process"` field on every successful response self-describes this — adopters reading the response know the contract without consulting docs. Cron triggers have the same property today (no catch-up replay if the process was down).
|
|
457
|
+
|
|
458
|
+
Durable / at-least-once delivery is a v2 if real adopter need surfaces. Don't oversell the 200 contract; build durable queueing on top yourself if you need it now.
|
|
459
|
+
|
|
460
|
+
### Migration from removed sources
|
|
461
|
+
|
|
462
|
+
If you have pre-v0.19.0 skills with `# Triggers: session: start` / `agent-event: X` / `file-watch: /path` / `sensor: X` declarations:
|
|
463
|
+
|
|
464
|
+
- **session start/end** → boot/shutdown lifecycle moved to the substrate (NanoClaw / your harness). If you need a runtime skill to fire at session-start, your harness POSTs to `/event` after boot.
|
|
465
|
+
- **agent-event** → external bridge (your agent fires `POST /event` when relevant).
|
|
466
|
+
- **file-watch** → external watcher script (inotify / chokidar / fswatch) POSTs to `/event`. The "how to call /event" pattern lives in the language reference call-example; the file-watching itself is standard OS plumbing — you own that script.
|
|
467
|
+
- **sensor** → same pattern as file-watch; sensor adapter POSTs to `/event`.
|
|
468
|
+
|
|
469
|
+
Skills declaring removed sources fail to parse on v0.19.0 (tier-1 parse error). Run `skillfile lint` against your corpus pre-upgrade to find them.
|
|
470
|
+
|
|
373
471
|
## Wiring the AgentConnector
|
|
374
472
|
|
|
375
473
|
`AgentConnector` is the substrate-neutral delivery surface for `# Output: agent: X` / `# Output: template: X` lifecycle hooks and `notify()` / `exchange()` ops. The runtime calls into the contract; your impl decides where the payload lands (webhook, tmux session, file drop, IPC pipe, Slack thread, your own agent harness, etc.).
|
package/docs/configuration.md
CHANGED
|
@@ -57,6 +57,8 @@ The CLI auto-loads `$SKILLSCRIPT_HOME/.env` at startup and populates `process.en
|
|
|
57
57
|
| `SKILLSCRIPT_POLL_INTERVAL_SECONDS=30` | Scheduler tick / poll interval (seconds) | env > config > default `30` |
|
|
58
58
|
| `SKILLSCRIPT_ABSOLUTE_TIMEOUT_MS=300000` | Runtime fallback timeout (ms) when no per-op / skill / connector default applies | env > config > default `300000` (5 min) |
|
|
59
59
|
| `SKILLSCRIPT_MAX_RECURSION_DEPTH=10` | Composition recursion depth ceiling for `$ execute_skill` chains | env > config > default `10` |
|
|
60
|
+
| `SKILLSCRIPT_EVENT_INGRESS_ENABLED=true` | Mount `POST /event` for v0.19.0 event-triggered skills. Default `false` — route returns 404 when not enabled. Shares `SKILLSCRIPT_PORT` with dashboard/RPC (one HTTP server). | env > default `false` |
|
|
61
|
+
| `SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=<token>` | Bearer-token auth for `POST /event`. When set, every event POST requires `Authorization: Bearer <token>`; 401 otherwise. Default unset = open-internally (still gated by bind address). | env > default unset |
|
|
60
62
|
| `OLLAMA_BASE_URL=http://...` | Ollama endpoint for LocalModel (default `http://localhost:11434`) | env > built-in default |
|
|
61
63
|
|
|
62
64
|
`SKILLSCRIPT_HOME` is the chicken-and-egg case — the path to `.env` requires it, so `.env` can't set it. Use shell, Docker `-e`, or systemd `Environment=` instead.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillscript-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Runtime, compiler, lint, CLI, and dashboard for Skillscript — a small declarative language for authoring agent workflows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Scott Shwarts <scotts@pobox.com>",
|
package/scaffold/.env.example
CHANGED
|
@@ -64,10 +64,31 @@
|
|
|
64
64
|
# reach the listener.
|
|
65
65
|
# SKILLSCRIPT_HOST=0.0.0.0
|
|
66
66
|
|
|
67
|
-
# Dashboard / serve HTTP port. Default 7878.
|
|
67
|
+
# Dashboard / serve HTTP port. Default 7878. Used for the SPA, JSON-RPC
|
|
68
|
+
# at /rpc, AND the v0.19.0 event-trigger ingress at /event (they share
|
|
69
|
+
# one HTTP server — no separate event port).
|
|
68
70
|
# SKILLSCRIPT_PORT=8080
|
|
69
71
|
|
|
70
72
|
|
|
73
|
+
# ─── Event-trigger HTTP ingress (v0.19.0) ──────────────────────────────
|
|
74
|
+
|
|
75
|
+
# Enable POST /event for external HTTP-triggered skills. Default false —
|
|
76
|
+
# the route returns 404 when not enabled. Once enabled, external services
|
|
77
|
+
# POST {event_name, params} and the runtime fires the registered skill
|
|
78
|
+
# asynchronously, returning 200 + {run_id, durability: "in-process"}.
|
|
79
|
+
# The route mounts on SKILLSCRIPT_PORT (above); no separate port.
|
|
80
|
+
# Localhost-only by default — set SKILLSCRIPT_HOST=0.0.0.0 to expose
|
|
81
|
+
# beyond loopback. "Enforce the DMZ assumption by the bind, not by hope."
|
|
82
|
+
# SKILLSCRIPT_EVENT_INGRESS_ENABLED=true
|
|
83
|
+
|
|
84
|
+
# Optional bearer-token auth for POST /event. When set, every event
|
|
85
|
+
# POST must carry `Authorization: Bearer <token>` matching this value;
|
|
86
|
+
# 401 otherwise. Default unset = open-internally (still gated by the
|
|
87
|
+
# bind address). Cheap to wire early — turning it on later is just an
|
|
88
|
+
# env edit + restart, no refactor.
|
|
89
|
+
# SKILLSCRIPT_EVENT_INGRESS_AUTH_TOKEN=your-secret-token-here
|
|
90
|
+
|
|
91
|
+
|
|
71
92
|
# ─── Runtime tuning ────────────────────────────────────────────────────
|
|
72
93
|
|
|
73
94
|
# Scheduler tick / poll interval in seconds. Default 30. Lower (e.g. 5)
|