skillscript-runtime 0.2.7 → 0.2.9

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.
@@ -0,0 +1,469 @@
1
+ // Static help content for the `help` MCP tool (v0.2.8). Cold-agent
2
+ // language discovery — answers the minimum-viable questions a new
3
+ // author needs to write a working skill, without needing to load the
4
+ // full language reference.
5
+ //
6
+ // Content layout:
7
+ // quickstart — ~500-token introduction; 6 questions + 1 worked example
8
+ // ops — op symbol legend with one-line shapes per op
9
+ // frontmatter — header keys + values
10
+ // examples — three canonical worked skills (minimal / threshold / branching)
11
+ // connectors — short explainer; delegates dynamic data to runtime_capabilities
12
+ // lint-codes — list of lint rules organized by tier
13
+ //
14
+ // Token estimates per topic are approximate; help() output is intended
15
+ // for an agent's working context, not for human reading.
16
+ const QUICKSTART = `# Skillscript — quickstart
17
+
18
+ Skillscript is a declarative language for authoring agent workflows. A
19
+ skill is a small program with named targets composed of typed ops. The
20
+ runtime walks dependencies backward from the goal target (declared via
21
+ \`default:\`) and dispatches each op in topological order.
22
+
23
+ ## 1. Shape of a skill file
24
+
25
+ \`\`\`
26
+ # Skill: my-skill ← required: skill name
27
+ # Description: What this skill does ← optional but recommended
28
+ # Status: Approved ← required: Draft | Approved | Disabled
29
+ # Vars: NAME=default-value, OTHER ← optional: declared variables
30
+ # Triggers: cron: 0 9 * * * ← optional: autonomous-dispatch sources
31
+
32
+ target_a: ← a named block of ops
33
+ @ curl -s https://example.com -> RAW
34
+ ~ prompt="Summarize: $(RAW)" -> SUMMARY
35
+
36
+ target_b: target_a ← Make-style: target_b depends on target_a
37
+ ! $(SUMMARY)
38
+
39
+ default: target_b ← goal target the runtime walks toward
40
+ \`\`\`
41
+
42
+ ## 2. Op symbol legend
43
+
44
+ | Op | Meaning |
45
+ |---|---|
46
+ | \`$ tool args -> VAR\` | MCP tool invocation; binds result to VAR |
47
+ | \`~ prompt="..." -> VAR\` | LocalModel call; binds output |
48
+ | \`> mode=... query=... limit=N -> VAR\` | Memory retrieval |
49
+ | \`@ command args -> VAR\` | Shell exec (structural sandbox; \`@ unsafe\` for full bash) |
50
+ | \`! text\` | Emit text to the user / output channel |
51
+ | \`?? prompt -> VAR\` | Ask user (interactive mode only) |
52
+ | \`$set NAME=value\` | Explicit variable binding |
53
+ | \`& skill-name args -> VAR\` | Inline a data-skill |
54
+
55
+ ## 3. Result binding
56
+
57
+ Most ops accept \`-> VAR\` to bind their output. Reference later via \`$(VAR)\`.
58
+ Optional \`(fallback: "default")\` after \`-> VAR\` binds the fallback on dispatch
59
+ error instead of propagating.
60
+
61
+ ## 4. Branching
62
+
63
+ \`\`\`
64
+ if $(VERDICT) == "urgent":
65
+ ! sound the alarm
66
+ elif $(COUNT) > "10":
67
+ ! threshold breached: $(COUNT) items
68
+ else:
69
+ ! all clear
70
+ \`\`\`
71
+
72
+ Numeric comparison (\`<\` / \`>\` / \`<=\` / \`>=\`) coerces both sides via Number();
73
+ non-numeric operands raise TypeMismatchError.
74
+
75
+ ## 5. Iteration
76
+
77
+ \`\`\`
78
+ foreach M in $(MEMORIES):
79
+ ! Processing $(M.id): $(M.summary)
80
+ \`\`\`
81
+
82
+ ## 6. How to see what's broken
83
+
84
+ - \`lint_skill({source})\` — diagnostics across tier-1 (errors), tier-2 (warnings), tier-3 (advisories)
85
+ - \`compile_skill({source, inputs?})\` — render the compiled artifact + surface compile errors
86
+ - \`runtime_capabilities()\` — discover wired connectors, models, shell-exec mode
87
+
88
+ ## Worked end-to-end example
89
+
90
+ \`\`\`
91
+ # Skill: morning-temperature-alert
92
+ # Description: Cron-fired check; alerts when overnight temp drops below threshold
93
+ # Status: Approved
94
+ # Vars: LOCATION=Asheville,NC, THRESHOLD=40
95
+ # Triggers: cron: 0 7 * * *
96
+
97
+ fetch:
98
+ @ curl -s "wttr.in/$(LOCATION|url)?format=j1" -> RAW (fallback: "")
99
+
100
+ evaluate: fetch
101
+ ~ prompt="Extract overnight low temperature in F from this JSON. Reply with only the number: $(RAW)" model=qwen -> TEMP
102
+
103
+ alert: evaluate
104
+ if $(TEMP|trim) < $(THRESHOLD):
105
+ ! Cold morning: overnight low $(TEMP|trim)°F (threshold $(THRESHOLD)°F)
106
+ else:
107
+ ! Temp ok: $(TEMP|trim)°F
108
+
109
+ default: alert
110
+ \`\`\`
111
+
112
+ Use \`help({topic: "ops"})\`, \`help({topic: "frontmatter"})\`, \`help({topic: "examples"})\`,
113
+ \`help({topic: "connectors"})\`, or \`help({topic: "lint-codes"})\` for deeper sections.
114
+ `;
115
+ const OPS = `# Op symbols — full reference
116
+
117
+ ## Dispatch ops (bind a result)
118
+
119
+ ### \`$\` — MCP tool invocation
120
+
121
+ \`\`\`
122
+ $ tool_name arg1=value1 arg2=value2 -> VAR [(fallback: "default")]
123
+ $ connector.tool_name args -> VAR
124
+ \`\`\`
125
+
126
+ Calls an MCP tool. Without an explicit connector prefix, routes to the
127
+ \`primary\` MCP connector. Fallback binds when dispatch errors.
128
+
129
+ **Built-in (v0.2.8):** \`$ execute_skill skill_name=child -> RESULT\` invokes
130
+ another stored skill end-to-end without requiring an MCP connector — pass
131
+ input vars as additional kwargs.
132
+
133
+ ### \`~\` — LocalModel call
134
+
135
+ \`\`\`
136
+ ~ prompt="..." model=qwen maxTokens=400 -> VAR [(fallback: "...")]
137
+ \`\`\`
138
+
139
+ LLM call against a configured LocalModel. \`model\` selects the named model;
140
+ default is \`default\`. Multi-line prompts via \`"..."\` are supported (parser
141
+ folds quoted-string continuations).
142
+
143
+ ### \`>\` — Memory retrieval
144
+
145
+ \`\`\`
146
+ > mode=fts query="..." limit=20 -> VAR [(fallback: "...")]
147
+ \`\`\`
148
+
149
+ Queries the configured MemoryStore. \`mode\` is substrate-specific
150
+ (\`fts\` / \`semantic\` / \`rerank\` are common). \`limit\` is required.
151
+
152
+ ### \`@\` — Shell exec
153
+
154
+ \`\`\`
155
+ @ command arg1 arg2 -> VAR [(fallback: "...")]
156
+ @ unsafe full-shell-command -> VAR
157
+ \`\`\`
158
+
159
+ Default mode: structural spawn — one binary, no shell metacharacters,
160
+ no pipes/redirects. \`@ unsafe\` opts into full bash; lint-flags tier-2.
161
+
162
+ ## Emission + control ops
163
+
164
+ ### \`!\` — Emit text
165
+
166
+ \`\`\`
167
+ ! Hello, $(NAME)!
168
+ \`\`\`
169
+
170
+ One-line literal emission. Variables substitute. No result binding.
171
+
172
+ ### \`??\` — Ask user
173
+
174
+ \`\`\`
175
+ ?? Are you sure? -> CONFIRM
176
+ \`\`\`
177
+
178
+ Interactive only. Autonomous-mode dispatch fails with a clean error.
179
+
180
+ ### \`$set\` — Explicit binding
181
+
182
+ \`\`\`
183
+ $set NAME=value
184
+ $set NAME=$(OTHER_VAR|trim)
185
+ \`\`\`
186
+
187
+ ### \`&\` — Inline data-skill
188
+
189
+ \`\`\`
190
+ & source-skill-name arg=value -> VAR
191
+ \`\`\`
192
+
193
+ References a \`# Type: data\` skill; the compiler inlines its emitted text
194
+ at compile time so the compiled artifact is a single resolved document.
195
+
196
+ ## Pipe filters
197
+
198
+ Apply on \`$(VAR|filter)\` references; chain left-to-right.
199
+
200
+ | Filter | Effect |
201
+ |---|---|
202
+ | \`url\` | encodeURIComponent |
203
+ | \`shell\` | POSIX single-quote escape |
204
+ | \`json\` | JSON.stringify |
205
+ | \`trim\` | Whitespace trim |
206
+ | \`length\` | Array element count or string char count (v0.2.5) |
207
+
208
+ ## Conditional grammar
209
+
210
+ \`\`\`
211
+ if $(VAR): ← truthy check
212
+ if $(VAR) == "literal": ← equality vs literal
213
+ if $(VAR) == $(OTHER): ← equality vs ref
214
+ if $(VAR) != "literal": ← inequality
215
+ if $(N) < "10": ← numeric comparison (v0.2.5)
216
+ if $(N) >= $(THRESHOLD): ← numeric vs ref
217
+ if $(M.id) in $(SEEN): ← set membership
218
+ if $(M.id) not in $(SEEN):
219
+ \`\`\`
220
+
221
+ Branches via \`if:\` / \`elif COND:\` / \`else:\`. The \`else:\` after a target
222
+ body is a separate error-handler block (distinguished by indentation scope).
223
+ `;
224
+ const FRONTMATTER = `# Frontmatter headers — full reference
225
+
226
+ Skill files open with \`# Key: value\` headers. Order isn't significant.
227
+
228
+ ## Required
229
+
230
+ - \`# Skill: <name>\` — identity. Reserved keywords (\`default\`, \`needs\`, etc.) rejected.
231
+ - \`# Status: Draft | Approved | Disabled\` — lifecycle state. Only Approved skills fire via triggers.
232
+
233
+ ## Common
234
+
235
+ - \`# Description: <prose>\` — human-readable explanation; surfaces in dashboards.
236
+ - \`# Type: procedural | data\` — \`procedural\` (default) for runtime-fired skills; \`data\` for compile-time-inlined fragments referenced by \`&\` ops.
237
+ - \`# Vars: NAME=default, OTHER\` — declared variables. \`NAME=default\` provides a default; bare \`NAME\` is required at invocation.
238
+ - \`# Triggers: cron: 0 9 * * *, session: start\` — autonomous-dispatch sources. Comma-separated entries split by source-keyword boundary; cron expressions with commas (\`30,45 9 * * 1-5\`) parse correctly.
239
+ - \`# Output: text | slack: chan | prompt-context: agent | template: agent | file: path | card: id | none\` — output routing.
240
+ - \`# OnError: <fallback-skill-name>\` — error-handler skill invoked when an op fails and no target-level \`else:\` catches.
241
+
242
+ ## Augmenting / Template only
243
+
244
+ - \`# Delivery-context: <prose>\` — routed to the receiving agent alongside the augment payload. v0.2.6.
245
+ - \`# Templates: <skill_name>, <skill_name>\` — comma-separated Template-skill names the receiving agent may fetch as follow-on actions. v0.2.6.
246
+
247
+ (Both fire \`unused-augmenting-header\` lint warning if set on a Headless skill — one with no \`prompt-context:\` or \`template:\` output declaration.)
248
+
249
+ ## Capabilities + retrieval
250
+
251
+ - \`# Requires: <namespace>:<key> -> VAR (fallback: "value")\` — declares external input requirements. \`user-var:\` or \`system-var:\` namespaces. Cascades resolve at compile.
252
+ - \`# Requires: connector_type.feature_flag\` — capability-style requires (e.g., \`local_model.streaming\`); validated against \`runtime_capabilities\`.
253
+
254
+ ## Performance
255
+
256
+ - \`# Timeout: <seconds>\` — skill-wide timeout. Falls back to per-op or runtime defaults.
257
+
258
+ ## Trigger declaration forms
259
+
260
+ \`\`\`
261
+ # Triggers: cron: 30,45 9 * * 1-5
262
+ # Triggers: session: start, session: end
263
+ # Triggers: cron: 0 7 * * *, agent-event: drift-detected
264
+ \`\`\`
265
+
266
+ Trigger sources today: \`cron\` (poll-based), \`session\` (\`start\` / \`end\` phases). Parse-only in v0.2: \`event\`, \`agent-event\`, \`file-watch\`, \`sensor\` (firing lands in v1.0).
267
+ `;
268
+ const EXAMPLES = `# Three canonical worked skills
269
+
270
+ ## 1. Minimal (single target, no dependencies)
271
+
272
+ \`\`\`
273
+ # Skill: hello
274
+ # Description: The canonical first-run example.
275
+ # Status: Approved
276
+ # Vars: WHO=world
277
+
278
+ greet:
279
+ ! Hello, $(WHO)!
280
+ ! Welcome to Skillscript.
281
+
282
+ default: greet
283
+ \`\`\`
284
+
285
+ Demonstrates: required headers, variable defaults, \`!\` emission with substitution.
286
+
287
+ ## 2. Cron-fired numeric threshold + count
288
+
289
+ \`\`\`
290
+ # Skill: queue-length-monitor
291
+ # Description: Count pending items in a queue and alert when the count exceeds threshold
292
+ # Status: Approved
293
+ # Vars: QUEUE_PATH=/var/queue/pending.json, THRESHOLD=10
294
+ # Triggers: cron: */5 * * * *
295
+
296
+ fetch:
297
+ @ cat $(QUEUE_PATH) -> ITEMS (fallback: "[]")
298
+
299
+ evaluate:
300
+ needs: fetch
301
+ if $(ITEMS|length) > $(THRESHOLD):
302
+ ! Queue backlog: $(ITEMS|length) items pending (threshold $(THRESHOLD)). Action required.
303
+ else:
304
+ ! Queue healthy: $(ITEMS|length) items pending (under $(THRESHOLD)).
305
+
306
+ default: evaluate
307
+ \`\`\`
308
+
309
+ Demonstrates: \`# Triggers:\` cron, shell \`@\` op with fallback, \`needs:\` body-line dep, numeric comparison, \`|length\` filter, \`if\` / \`else\`.
310
+
311
+ ## 3. LocalModel branching with agent delivery
312
+
313
+ \`\`\`
314
+ # Skill: classify-support-ticket
315
+ # Description: Classify an incoming ticket by urgency and route to oncall when severe
316
+ # Status: Approved
317
+ # Vars: TICKET_BODY
318
+ # Delivery-context: Urgent ticket triage — please assess + assign owner.
319
+ # Templates: ticket-assignment-procedure
320
+ # Output: prompt-context: oncall
321
+
322
+ classify:
323
+ ~ prompt="Classify this support ticket as one of: 'critical', 'normal', 'low'. Reply with only the label. Ticket: $(TICKET_BODY)" model=qwen -> VERDICT
324
+
325
+ route: classify
326
+ if $(VERDICT|trim) == "critical":
327
+ ! CRITICAL ticket needs immediate attention:
328
+ ! $(TICKET_BODY)
329
+ elif $(VERDICT|trim) == "normal":
330
+ ! Normal-priority ticket queued.
331
+ else:
332
+ ! Low-priority ticket logged.
333
+
334
+ default: route
335
+ \`\`\`
336
+
337
+ Demonstrates: \`~\` LocalModel op, named model selection, \`|trim\` filter on LLM output, ref-vs-literal comparison, agent delivery via \`prompt-context:\`, augmenting headers (\`# Delivery-context:\` + \`# Templates:\`).
338
+ `;
339
+ const CONNECTORS_PROLOGUE = `# Connectors
340
+
341
+ The runtime resolves \`$\` / \`~\` / \`>\` / \`# Output:\` dispatches through a
342
+ typed registry of five contracts:
343
+
344
+ | Contract | Purpose | Op |
345
+ |---|---|---|
346
+ | SkillStore | Skill source persistence + status lifecycle | (implicit) |
347
+ | MemoryStore | Knowledge retrieval | \`>\` |
348
+ | LocalModel | LLM inference | \`~\` |
349
+ | McpConnector | MCP tool dispatch | \`$\` |
350
+ | AgentConnector | Deliver augment/template payloads | \`# Output: prompt-context:\` / \`template:\` |
351
+
352
+ Skills don't import packages — they invoke connectors. The set wired into
353
+ this runtime, plus their feature flags, is discoverable via:
354
+
355
+ \`runtime_capabilities()\`
356
+
357
+ Call that tool for the live picture of which connectors are registered,
358
+ which feature flags they advertise, and which named instances exist
359
+ (e.g., \`default\` / \`qwen\` LocalModels).
360
+
361
+ For shell execution (\`@\` op), \`runtime_capabilities\` also reports
362
+ \`shellExecution.mode\` (\`"structural-spawn"\`) and
363
+ \`shellExecution.unsafe_enabled\` (whether \`@ unsafe\` is permitted in
364
+ this deployment).
365
+ `;
366
+ const LINT_CODES = `# Lint rule index
367
+
368
+ Three tiers per ERD §3:
369
+
370
+ - **Tier-1 (error)** — blocks compile. Must fix before the skill enters the SkillStore.
371
+ - **Tier-2 (warning)** — non-blocking but flagged. Common smell; review.
372
+ - **Tier-3 (info)** — advisory. Often style or organizational hints.
373
+
374
+ ## Tier-1 (error)
375
+
376
+ - \`parse-error\` — frontmatter or grammar fault surfaced by parse()
377
+ - \`no-targets\` — skill defines no targets
378
+ - \`no-entry-target\` — no \`default:\` declaration
379
+ - \`orphan-target\` — target unreachable from entry via dep graph
380
+ - \`unknown-capability\` — \`# Requires: connector.feature\` references a flag no registered connector advertises
381
+ - \`undeclared-var\` — \`$(VAR)\` reference not in \`# Vars:\` / \`# Requires:\` / output-bound / foreach iterator / tier-1 ambient (NOW/USER/SESSION_CONTEXT/TRIGGER_TYPE/TRIGGER_PAYLOAD/ERROR_CONTEXT)
382
+ - \`unknown-filter\` — \`|filter\` references an unregistered filter name
383
+ - \`malformed-op-grammar\` — op body doesn't match its grammar
384
+ - \`invalid-conditional-syntax\` — \`if\` condition doesn't match supported forms
385
+ - \`single-equals\` — \`if $(VAR) = "..."\` instead of \`==\` (specific diagnostic)
386
+ - \`indentation\` — tabs in indentation; mixed tabs/spaces
387
+ - \`reserved-keyword\` — variable/target/skill name collides with a reserved word
388
+ - \`unknown-skill-reference\` — \`&\` op references a skill not in the store
389
+ - \`disabled-skill-reference\` — \`&\` op references a Disabled skill
390
+ - \`credential-in-args\` — op arg looks like a secret literal
391
+ - \`status-disabled\` — skill marked \`# Status: Disabled\`
392
+ - \`circular-dependency\` — dep cycle between targets
393
+ - \`missing-dependency\` — \`needs:\` references a target not declared
394
+ - \`missing-skillstore-for-data-ref\` — \`&\` op fires without a SkillStore wired
395
+
396
+ ## Tier-2 (warning)
397
+
398
+ - \`deprecated-question\` — bare \`?\` op (deprecated v1; compile-error in v1.x)
399
+ - \`unsafe-shell-ambiguous-subst\` — \`$(NAME)\` inside \`@ unsafe\` body that isn't a declared variable; collides with bash command-sub syntax
400
+ - \`unsafe-shell-op\` — \`@ unsafe\` op present; requires human review every time
401
+ - \`unconfirmed-mutation\` — \`$\` op invokes a tool whose name suggests mutation (write/update/delete) without a preceding \`??\` confirmation
402
+ - \`model-contention\` — async + sync ops on the same model serialize on a single runtime worker
403
+ - \`draft-with-trigger\` — \`# Status: Draft\` skill has \`# Triggers:\` declared; triggers won't fire until Approved
404
+ - \`reference-to-disabled-skill\` — \`&\` op references a Disabled skill (also tier-1 in some contexts)
405
+ - \`unused-augmenting-header\` — \`# Delivery-context:\` or \`# Templates:\` set on a skill with no agent-bound output (v0.2.6)
406
+
407
+ ## Tier-3 (info)
408
+
409
+ - \`no-default-target\` — no \`default:\` declaration (relevant for data skills only; procedural skills hit tier-1)
410
+ - \`duplicate-skill-name\` — name collides with an existing stored skill
411
+ - \`plugin-collision\` — placeholder for v1.x plugin-loader name conflicts
412
+
413
+ \`compile_skill({source})\` runs the full lint preflight and reports
414
+ findings in the \`errors\` + \`warnings\` arrays. \`lint_skill({source})\`
415
+ returns the same diagnostics without compiling.
416
+ `;
417
+ export function helpResponse(topic, runtimeVersion, registry) {
418
+ if (topic === null) {
419
+ return {
420
+ topic: null,
421
+ version: runtimeVersion,
422
+ content: QUICKSTART,
423
+ available_topics: ["ops", "frontmatter", "examples", "connectors", "lint-codes"],
424
+ };
425
+ }
426
+ let content;
427
+ switch (topic) {
428
+ case "ops":
429
+ content = OPS;
430
+ break;
431
+ case "frontmatter":
432
+ content = FRONTMATTER;
433
+ break;
434
+ case "examples":
435
+ content = EXAMPLES;
436
+ break;
437
+ case "connectors":
438
+ content = renderConnectorsTopic(registry);
439
+ break;
440
+ case "lint-codes":
441
+ content = LINT_CODES;
442
+ break;
443
+ default:
444
+ content = `# Unknown topic '${topic}'\n\nValid topics: ops, frontmatter, examples, connectors, lint-codes`;
445
+ }
446
+ return { topic, version: runtimeVersion, content };
447
+ }
448
+ function renderConnectorsTopic(registry) {
449
+ if (registry === undefined)
450
+ return CONNECTORS_PROLOGUE;
451
+ const summary = [
452
+ `\n## Wired in this runtime`,
453
+ ``,
454
+ `*Call \`runtime_capabilities()\` for the full discovery payload.*`,
455
+ ``,
456
+ ];
457
+ const ss = registry.listSkillStores();
458
+ const ms = registry.listMemoryStores();
459
+ const lm = registry.listLocalModels();
460
+ const mc = registry.listMcpConnectors();
461
+ const ac = registry.listAgentConnectors();
462
+ summary.push(`- SkillStores: ${ss.length === 0 ? "(none)" : ss.map((e) => `${e.name} (${e.ctor.name})`).join(", ")}`);
463
+ summary.push(`- MemoryStores: ${ms.length === 0 ? "(none)" : ms.map((e) => `${e.name} (${e.ctor.name})`).join(", ")}`);
464
+ summary.push(`- LocalModels: ${lm.length === 0 ? "(none)" : lm.map((e) => e.name).join(", ")}`);
465
+ summary.push(`- McpConnectors: ${mc.length === 0 ? "(none)" : mc.map((e) => `${e.name} (${e.ctor.name})`).join(", ")}`);
466
+ summary.push(`- AgentConnectors: ${ac.length === 0 ? "(none — defaults to NoOp)" : ac.map((e) => `${e.name} (${e.ctor.name})`).join(", ")}`);
467
+ return CONNECTORS_PROLOGUE + summary.join("\n");
468
+ }
469
+ //# sourceMappingURL=help-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-content.js","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"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"}
@@ -27,6 +27,8 @@ import type { Registry } from "./connectors/registry.js";
27
27
  * lint_skill({source?|name}) → diagnostics across tiers (v0.2.3)
28
28
  * compile_skill({source?|name, inputs?})→ rendered artifact + errors (v0.2.3)
29
29
  * skill_write({name, source, overwrite?})→ commit to SkillStore (write, v0.2.3)
30
+ * execute_skill({skill_name, inputs?, mechanical?})→ run + return result (write, v0.2.8)
31
+ * help({topic?}) → cold-agent language discovery (read, v0.2.8)
30
32
  */
31
33
  export interface JsonRpcRequest {
32
34
  jsonrpc: "2.0";
@@ -84,6 +86,8 @@ export declare class McpServer {
84
86
  */
85
87
  runStdio(): void;
86
88
  private registerBuiltinTools;
89
+ private executeSkill;
90
+ private help;
87
91
  private lintSkill;
88
92
  private compileSkill;
89
93
  private skillWrite;
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmC,MAAM,uBAAuB,CAAC;AACzF,OAAO,KAAK,EAAE,SAAS,EAAgD,MAAM,gBAAgB,CAAC;AAC9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAMzD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,MAAM,eAAe,GAAG,sBAAsB,GAAG,oBAAoB,CAAC;AAI5E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,WAAW,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IACpC,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD,qBAAa,SAAS;IAIR,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,IAAI,EAAE,aAAa;IAKhD,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIjC,SAAS,IAAI,OAAO,EAAE;IAIhB,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAqD3D;;;;OAIG;IACH,QAAQ,IAAI,IAAI;IAyBhB,OAAO,CAAC,oBAAoB;YA0Nd,SAAS;YAyBT,YAAY;YAoDZ,UAAU;IAiCxB;;;OAGG;YACW,aAAa;YAWb,mBAAmB;CA2BlC"}
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAmC,MAAM,uBAAuB,CAAC;AACzF,OAAO,KAAK,EAAE,SAAS,EAAgD,MAAM,gBAAgB,CAAC;AAC9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAYzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1D;AAED,MAAM,MAAM,eAAe,GAAG,sBAAsB,GAAG,oBAAoB,CAAC;AAI5E,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,kGAAkG;IAClG,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,+FAA+F;IAC/F,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,wFAAwF;IACxF,WAAW,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;IACpC,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAKD,qBAAa,SAAS;IAIR,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IACzD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAEJ,IAAI,EAAE,aAAa;IAKhD,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIjC,SAAS,IAAI,OAAO,EAAE;IAIhB,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAqD3D;;;;OAIG;IACH,QAAQ,IAAI,IAAI;IAyBhB,OAAO,CAAC,oBAAoB;YAiQd,YAAY;YAiFZ,IAAI;YAOJ,SAAS;YAyBT,YAAY;YAoDZ,UAAU;IAiCxB;;;OAGG;YACW,aAAa;YAWb,mBAAmB;CA2BlC"}
@@ -2,6 +2,8 @@ import { healthMetrics } from "./metrics.js";
2
2
  import { lint } from "./lint.js";
3
3
  import { compile } from "./compile.js";
4
4
  import { LintFailureError } from "./errors.js";
5
+ import { executeSkillByName, RecursionDepthExceededError, SkillNotFoundForCompositionError, } from "./composition.js";
6
+ import { helpResponse } from "./help-content.js";
5
7
  const MCP_PROTOCOL_VERSION = "2024-11-05";
6
8
  const SERVER_NAME = "skillscript-runtime";
7
9
  export class McpServer {
@@ -10,7 +12,7 @@ export class McpServer {
10
12
  version;
11
13
  constructor(deps) {
12
14
  this.deps = deps;
13
- this.version = deps.serverVersion ?? "0.2.7";
15
+ this.version = deps.serverVersion ?? "0.2.9";
14
16
  this.registerBuiltinTools();
15
17
  }
16
18
  registerTool(tool) {
@@ -311,6 +313,127 @@ export class McpServer {
311
313
  },
312
314
  handler: async (args) => this.skillWrite(args),
313
315
  });
316
+ // ─── v0.2.8 — composition + discovery ──────────────────────────────────
317
+ this.registerTool({
318
+ name: "execute_skill",
319
+ description: "Execute a stored skill end-to-end against the runtime's wired connectors. Returns {skill_name, final_vars, transcript, outputs, errors, target_order}. `mechanical: true` previews dispatch without firing $/~/@/?? ops (TestFlight mode). Recursion-depth-guarded for composition chains (default 10). Write operation.",
320
+ inputSchema: {
321
+ type: "object",
322
+ properties: {
323
+ skill_name: { type: "string", description: "Skill name as stored in the SkillStore." },
324
+ inputs: {
325
+ type: "object",
326
+ additionalProperties: { type: "string" },
327
+ description: "Optional `# Vars:` overrides keyed by variable name.",
328
+ },
329
+ mechanical: {
330
+ type: "boolean",
331
+ description: "When true, $/~/@/?? ops bind placeholders instead of firing. Recurses through nested execute_skill calls.",
332
+ default: false,
333
+ },
334
+ },
335
+ required: ["skill_name"],
336
+ },
337
+ handler: async (args) => this.executeSkill(args),
338
+ });
339
+ this.registerTool({
340
+ name: "help",
341
+ description: "Cold-agent language discovery. `help()` returns a ~500-token quickstart. `help({topic})` returns a deeper section. Topics: ops / frontmatter / examples / connectors / lint-codes. Read-only.",
342
+ inputSchema: {
343
+ type: "object",
344
+ properties: {
345
+ topic: {
346
+ type: "string",
347
+ enum: ["ops", "frontmatter", "examples", "connectors", "lint-codes"],
348
+ description: "Optional topic for a deeper section. Omit for the quickstart.",
349
+ },
350
+ },
351
+ },
352
+ handler: async (args) => this.help(args),
353
+ });
354
+ }
355
+ async executeSkill(args) {
356
+ const skillName = args["skill_name"];
357
+ if (typeof skillName !== "string" || skillName === "") {
358
+ throw new Error("execute_skill: `skill_name` is required (non-empty string).");
359
+ }
360
+ const inputs = args["inputs"] ?? {};
361
+ const mechanical = args["mechanical"] === true;
362
+ // Build an ExecuteContext for the call. The MCP tool entry is the
363
+ // top-level — recursionDepth starts at 0 and increments inside
364
+ // executeSkillByName.
365
+ if (this.deps.registry === undefined) {
366
+ throw new Error("execute_skill: runtime registry not configured (McpServerDeps.registry missing).");
367
+ }
368
+ const ctx = {
369
+ registry: this.deps.registry,
370
+ mechanical,
371
+ recursionDepth: 0,
372
+ };
373
+ try {
374
+ const result = await executeSkillByName(skillName, inputs, {
375
+ skillStore: this.deps.skillStore,
376
+ ctx,
377
+ });
378
+ return {
379
+ skill_name: result.skill_name,
380
+ final_vars: result.final_vars,
381
+ transcript: result.transcript,
382
+ outputs: result.outputs,
383
+ errors: result.errors,
384
+ target_order: result.target_order,
385
+ mechanical,
386
+ };
387
+ }
388
+ catch (err) {
389
+ if (err instanceof SkillNotFoundForCompositionError) {
390
+ return {
391
+ skill_name: null,
392
+ final_vars: {},
393
+ transcript: [],
394
+ outputs: {},
395
+ errors: [{ class: "SkillNotFoundError", opKind: "execute_skill", target: "(root)", message: err.message }],
396
+ target_order: [],
397
+ mechanical,
398
+ };
399
+ }
400
+ if (err instanceof RecursionDepthExceededError) {
401
+ return {
402
+ skill_name: skillName,
403
+ final_vars: {},
404
+ transcript: [],
405
+ outputs: {},
406
+ errors: [{ class: "RecursionDepthExceededError", opKind: "execute_skill", target: "(root)", message: err.message, chain: err.chain }],
407
+ target_order: [],
408
+ mechanical,
409
+ };
410
+ }
411
+ if (err instanceof LintFailureError) {
412
+ return {
413
+ skill_name: skillName,
414
+ final_vars: {},
415
+ transcript: [],
416
+ outputs: {},
417
+ errors: [{ class: "LintFailureError", opKind: "execute_skill", target: "(root)", message: err.message }],
418
+ target_order: [],
419
+ mechanical,
420
+ };
421
+ }
422
+ // Unexpected — surface as a structured error rather than throw.
423
+ return {
424
+ skill_name: skillName,
425
+ final_vars: {},
426
+ transcript: [],
427
+ outputs: {},
428
+ errors: [{ class: err.name, opKind: "execute_skill", target: "(root)", message: err.message }],
429
+ target_order: [],
430
+ mechanical,
431
+ };
432
+ }
433
+ }
434
+ async help(args) {
435
+ const topic = typeof args["topic"] === "string" ? args["topic"] : null;
436
+ return helpResponse(topic, this.version, this.deps.registry);
314
437
  }
315
438
  // ─── v0.2.3 authoring-lifecycle handlers ───────────────────────────────────
316
439
  async lintSkill(args) {