skillscript-runtime 0.17.3 → 0.17.5
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/bootstrap.d.ts +18 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +1 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/cli.js +42 -6
- package/dist/cli.js.map +1 -1
- package/dist/composition.d.ts +9 -0
- package/dist/composition.d.ts.map +1 -1
- package/dist/composition.js +19 -8
- package/dist/composition.js.map +1 -1
- package/dist/dotenv-loader.d.ts +29 -0
- package/dist/dotenv-loader.d.ts.map +1 -0
- package/dist/dotenv-loader.js +86 -0
- package/dist/dotenv-loader.js.map +1 -0
- package/dist/help-content.d.ts.map +1 -1
- package/dist/help-content.js +33 -4
- package/dist/help-content.js.map +1 -1
- package/dist/lint.d.ts.map +1 -1
- package/dist/lint.js +149 -0
- package/dist/lint.js.map +1 -1
- package/dist/parser.d.ts +1 -0
- package/dist/parser.d.ts.map +1 -1
- package/dist/parser.js +29 -0
- package/dist/parser.js.map +1 -1
- package/dist/runtime-config.d.ts +10 -0
- package/dist/runtime-config.d.ts.map +1 -1
- package/dist/runtime-config.js +8 -0
- package/dist/runtime-config.js.map +1 -1
- package/docs/configuration.md +75 -0
- package/docs/language-reference.md +70 -13
- package/examples/skillscripts/hello-world.skill.provenance.json +1 -1
- package/package.json +1 -1
- package/scaffold/.env.example +89 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"help-content.d.ts","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAm1BzD,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,cAAc,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,QAAQ,GAClB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqBzB"}
|
package/dist/help-content.js
CHANGED
|
@@ -260,13 +260,15 @@ inline(skill="common-prelude")
|
|
|
260
260
|
|
|
261
261
|
### \`execute_skill(name="...", ...kwargs) -> R\` — runtime skill composition
|
|
262
262
|
|
|
263
|
-
Invokes another stored skill end-to-end against the runtime's connectors. Returns the
|
|
263
|
+
Invokes another stored skill end-to-end against the runtime's connectors. Returns the child's execution record — \`outputs\` + \`transcript\` + \`errors\` + \`target_order\` + (filtered) \`final_vars\`. Access via \`\${R.outputs.text}\`, \`\${R.transcript}\`, \`\${R.final_vars.FIELD}\`, etc.
|
|
264
264
|
|
|
265
265
|
\`\`\`
|
|
266
266
|
execute_skill(name="extract-json-number", JSON_BLOB="\${RAW}", FIELD_PATH="total_count") -> RESULT
|
|
267
|
-
emit(text="Extracted: \${RESULT.
|
|
267
|
+
emit(text="Extracted: \${RESULT.outputs.text}")
|
|
268
268
|
\`\`\`
|
|
269
269
|
|
|
270
|
+
**v0.17.3 — Returns filter.** \`R.final_vars\` is filtered to the called skill's \`# Returns: X, Y, Z\` declaration. Skills without \`# Returns:\` declared export nothing from \`final_vars\` — the caller sees \`outputs\` + \`transcript\` + execution metadata, but no internal vars. Internal scratch (large JSON, intermediate computations, debug values) stays local to the child and never serializes into the caller's \`R\`. To expose a value for caller consumption, declare it in the called skill's \`# Returns:\` header.
|
|
271
|
+
|
|
270
272
|
\`name\` is the canonical kwarg, aligning with \`skill_read({name})\` / \`skill_write({name})\` / \`skill_status({name})\`. \`skill_name\` is accepted as a silent back-compat alias.
|
|
271
273
|
|
|
272
274
|
## Class 3: External MCP dispatch
|
|
@@ -402,7 +404,8 @@ Skill files open with \`# Key: value\` headers. Order isn't significant.
|
|
|
402
404
|
|
|
403
405
|
- \`# Description: <prose>\` — human-readable explanation; surfaces in dashboards.
|
|
404
406
|
- \`# Type: procedural | data\` — \`procedural\` (default) for runtime-fired skills; \`data\` for compile-time-inlined fragments referenced by \`inline(skill="...")\`.
|
|
405
|
-
- \`# Vars: NAME=default, OTHER\` — declared variables. \`NAME=default\` provides a default; bare \`NAME\` is required at invocation.
|
|
407
|
+
- \`# Vars: NAME=default, OTHER\` — declared variables. \`NAME=default\` provides a default; bare \`NAME\` is required at invocation. Quoted defaults (\`NAME="hello world"\`) strip one matched layer of surrounding quotes at parse time — quoted-spaced values bind correctly; bare values bind unchanged.
|
|
408
|
+
- \`# Returns: X, Y, Z\` — declared export surface for \`execute_skill\` composition. Names that propagate from this skill's \`final_vars\` into the caller's bound \`R\`. Internal scratch vars NOT listed here stay local — never serialized into the caller's result. Skills without \`# Returns:\` export nothing from \`final_vars\` (outputs + transcript + metadata still flow). Symmetric with \`# Vars:\` (input surface ↔ output surface).
|
|
406
409
|
- \`# 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.
|
|
407
410
|
- \`# Output: text | agent: <name> | template: <name> | file: path | none\` — output routing. Five kinds, all substrate-neutral. **Two substrate-neutral lifecycle hooks**: \`agent: <name>\` routes via AgentConnector as augment-kind delivery; \`template: <name>\` routes as template-kind delivery (receiving agent executes the rendered playbook). Both default to **joined emissions string** (the \`emit(text=...)\` lines concatenated with newlines). \`text\` / \`file:\` default to the **last-bound variable value** (structured), falling back to the emissions array when no var was bound. If your skill emits multiple lines and a downstream consumer only sees the final tool output via \`outputs.text\`, that's the structured-default behavior — use \`# Output: agent: <name>\` (or another text-coerced kind) to publish the joined emissions instead. **For substrate-specific delivery destinations** (Slack, WhatsApp, Discord, pagerduty, custom dashboards, etc.) — that's contract-between-the-skill-and-the-substrate territory, downstream of the language. Two paths: (1) \`$ <connector>.<tool> ...\` inside the skill body to dispatch through an adopter-wired MCP connector, or (2) deliver via \`agent: <name>\` to an agent whose AgentConnector decides how to surface the result.
|
|
408
411
|
- \`# OnError: <fallback-skill-name>\` — error-handler skill invoked when an op fails and no target-level \`else:\` catches.
|
|
@@ -701,7 +704,33 @@ Two kwarg-forwarding styles, both supported:
|
|
|
701
704
|
- **Bare kwargs** — \`USER="\${USER_NAME}"\` natural skill grammar
|
|
702
705
|
- **\`inputs={...}\` JSON** — useful when forwarding many fields verbatim
|
|
703
706
|
|
|
704
|
-
The bound \`-> R\` carries the child's
|
|
707
|
+
The bound \`-> R\` carries the child's execution record into the host's scope:
|
|
708
|
+
- \`\${R.outputs.text}\` — the joined emission stream (the canonical accessor, what 100% of composers reach for)
|
|
709
|
+
- \`\${R.transcript}\` — array of individual emit lines
|
|
710
|
+
- \`\${R.final_vars.FIELD}\` — the child's declared exports (see \`# Returns:\` below)
|
|
711
|
+
- \`\${R.errors}\`, \`\${R.target_order}\` — execution metadata
|
|
712
|
+
|
|
713
|
+
**Declaring what gets exported (v0.17.3).** The child skill controls what's visible to the caller via its \`# Returns: X, Y, Z\` frontmatter header. Internal scratch (large JSON, intermediate computations) stays local; only declared names propagate into \`R.final_vars\`. Skills without \`# Returns:\` export nothing from \`final_vars\` — outputs + transcript + metadata still flow.
|
|
714
|
+
|
|
715
|
+
\`\`\`
|
|
716
|
+
# Skill: get-weather
|
|
717
|
+
# Vars: LOCATION=Valdese
|
|
718
|
+
# Returns: SUMMARY, TEMP_F
|
|
719
|
+
|
|
720
|
+
fetch:
|
|
721
|
+
shell(command="curl -s 'wttr.in/\${LOCATION|url}?format=j1'") -> RAW
|
|
722
|
+
$ json_parse \${RAW} -> PARSED
|
|
723
|
+
|
|
724
|
+
shape: fetch
|
|
725
|
+
$set TEMP_F = \${PARSED.current_condition.0.temp_F}
|
|
726
|
+
$set SUMMARY = "\${LOCATION}: \${TEMP_F}°F"
|
|
727
|
+
emit(text="\${SUMMARY}")
|
|
728
|
+
default: shape
|
|
729
|
+
\`\`\`
|
|
730
|
+
|
|
731
|
+
Caller binding \`-> R\` sees \`R.final_vars = {SUMMARY, TEMP_F}\` — NOT \`RAW\` or \`PARSED\` (internal scratch, filtered out by the Returns surface). Closes the "skills are functions; declare what you return" contract: internal state stays internal.
|
|
732
|
+
|
|
733
|
+
Lint \`unknown-returns-ref\` (tier-1) catches names declared in \`# Returns:\` that aren't bound anywhere in the skill body.
|
|
705
734
|
|
|
706
735
|
## Limits & lint signals
|
|
707
736
|
|
package/dist/help-content.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help-content.js","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,kEAAkE;AAClE,qEAAqE;AACrE,2BAA2B;AAC3B,EAAE;AACF,kBAAkB;AAClB,0EAA0E;AAC1E,+DAA+D;AAC/D,uCAAuC;AACvC,kFAAkF;AAClF,kFAAkF;AAClF,uDAAuD;AACvD,EAAE;AACF,uEAAuE;AACvE,yDAAyD;AAIzD,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+HlB,CAAC;AAEF,MAAM,GAAG,GAAG
|
|
1
|
+
{"version":3,"file":"help-content.js","sourceRoot":"","sources":["../src/help-content.ts"],"names":[],"mappings":"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"}
|
package/dist/lint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"lint.d.ts","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
|
package/dist/lint.js
CHANGED
|
@@ -1929,6 +1929,154 @@ const SET_JSON_LITERAL_ADVISORY = {
|
|
|
1929
1929
|
// substitution and advise. False positives possible (if a user binds a
|
|
1930
1930
|
// non-composition var named with `.transcript`), but the suggestion
|
|
1931
1931
|
// reads as a helpful nudge either way.
|
|
1932
|
+
// v0.17.4 — `${R.final_vars.X}` where R was bound by `$ execute_skill
|
|
1933
|
+
// skill_name="<child>" ... -> R` and `X` isn't in `<child>`'s declared
|
|
1934
|
+
// `# Returns:`. The runtime filter drops the value silently — the
|
|
1935
|
+
// caller gets `undefined`/empty at substitution time. Lint catches the
|
|
1936
|
+
// asymmetry between caller's reach and child's declared export.
|
|
1937
|
+
// Sibling to v0.17.3's `unknown-returns-ref` (tier-1) on the
|
|
1938
|
+
// declaration side; this rule is tier-2 advisory on the consumer side.
|
|
1939
|
+
//
|
|
1940
|
+
// Forward-reference deferred: if the called skill isn't in the
|
|
1941
|
+
// SkillStore at lint time, skip — `unknown-skill-reference` (tier-2)
|
|
1942
|
+
// already flags the missing-ref case. Once the called skill exists,
|
|
1943
|
+
// this rule fires the next time the host is linted.
|
|
1944
|
+
const UNEXPORTED_FINAL_VAR_ACCESS = {
|
|
1945
|
+
id: "unexported-final-var-access",
|
|
1946
|
+
severity: "warning",
|
|
1947
|
+
description: "A `${R.final_vars.X}` reference accesses a name not declared in the called skill's `# Returns:` header. The runtime filter drops the value; the substitution renders empty.",
|
|
1948
|
+
remediation: "Add `X` to the called skill's `# Returns:` header (to export it), or remove the access (if you meant `${R.outputs.text}` or another always-exported field).",
|
|
1949
|
+
check: async (ctx) => {
|
|
1950
|
+
if (ctx.skillStore === undefined)
|
|
1951
|
+
return [];
|
|
1952
|
+
// Step 1: build a map of execute_skill bindings — { boundVar: calledSkillName }
|
|
1953
|
+
const bindings = new Map();
|
|
1954
|
+
for (const target of ctx.parsed.targets.values()) {
|
|
1955
|
+
walkOps(target.ops, (op) => {
|
|
1956
|
+
if (op.kind !== "$" || op.outputVar === undefined)
|
|
1957
|
+
return;
|
|
1958
|
+
if (!/^execute_skill\b/.test(op.body))
|
|
1959
|
+
return;
|
|
1960
|
+
// v0.15.2 — accept either `name` or `skill_name` (back-compat alias).
|
|
1961
|
+
const m = /\b(?:skill_name|name)\s*=\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z_][\w-]*))/.exec(op.body);
|
|
1962
|
+
if (m === null)
|
|
1963
|
+
return;
|
|
1964
|
+
const skillName = m[1] ?? m[2] ?? m[3];
|
|
1965
|
+
if (skillName === undefined || skillName === "")
|
|
1966
|
+
return;
|
|
1967
|
+
bindings.set(op.outputVar, skillName);
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1970
|
+
if (bindings.size === 0)
|
|
1971
|
+
return [];
|
|
1972
|
+
// Step 2: load each referenced skill's parsed.returns. Cache the
|
|
1973
|
+
// lookup so multiple references to the same child resolve once.
|
|
1974
|
+
const returnsCache = new Map();
|
|
1975
|
+
const loadReturns = async (skillName) => {
|
|
1976
|
+
if (returnsCache.has(skillName))
|
|
1977
|
+
return returnsCache.get(skillName);
|
|
1978
|
+
let result;
|
|
1979
|
+
try {
|
|
1980
|
+
const loaded = await ctx.skillStore.load(skillName);
|
|
1981
|
+
const parsed = parse(loaded.source);
|
|
1982
|
+
result = new Set(parsed.returns);
|
|
1983
|
+
}
|
|
1984
|
+
catch {
|
|
1985
|
+
result = null; // missing skill — forward-reference deferred to unknown-skill-reference
|
|
1986
|
+
}
|
|
1987
|
+
returnsCache.set(skillName, result);
|
|
1988
|
+
return result;
|
|
1989
|
+
};
|
|
1990
|
+
// Step 3: walk ops looking for both `${R.final_vars.X}` (iteration-view
|
|
1991
|
+
// explicit path) and `${R.X}` (canonical top-level path per v0.17.5).
|
|
1992
|
+
// For top-level: skip always-exported envelope fields (outputs,
|
|
1993
|
+
// transcript, etc. — those are valid sibling access). For
|
|
1994
|
+
// final_vars-explicit: skip the `.final_vars` segment itself.
|
|
1995
|
+
const findings = [];
|
|
1996
|
+
const reported = new Set();
|
|
1997
|
+
// Always-exported result-envelope fields. Top-level access to these
|
|
1998
|
+
// is canonical and must NOT fire this rule. Source-of-truth aligned
|
|
1999
|
+
// with parser's RESERVED_ENVELOPE_FIELDS — declared returns can't
|
|
2000
|
+
// collide with these, so any top-level `${R.<field>}` where `<field>`
|
|
2001
|
+
// is in this set is sibling-access to the envelope, not an
|
|
2002
|
+
// unexported-return reach.
|
|
2003
|
+
const ALWAYS_EXPORTED = new Set(["skill_name", "outputs", "transcript", "errors", "target_order", "fallbacks", "agent_delivery_receipts", "final_vars"]);
|
|
2004
|
+
// Two regexes — explicit path `${R.final_vars.X}` and top-level
|
|
2005
|
+
// path `${R.X}`. Both forms (`$(...)` legacy + `${...}` canonical).
|
|
2006
|
+
// The top-level regex is more permissive — caller-side checks below
|
|
2007
|
+
// filter out envelope-field hits and non-execute_skill bindings.
|
|
2008
|
+
const reExplicit = /\$[({]([A-Za-z_]\w*)\.final_vars\.([A-Za-z_]\w*)/g;
|
|
2009
|
+
const reTopLevel = /\$[({]([A-Za-z_]\w*)\.([A-Za-z_]\w*)/g;
|
|
2010
|
+
for (const [targetName, target] of ctx.parsed.targets) {
|
|
2011
|
+
const scanString = async (s) => {
|
|
2012
|
+
const localMatches = [];
|
|
2013
|
+
let m;
|
|
2014
|
+
reExplicit.lastIndex = 0;
|
|
2015
|
+
while ((m = reExplicit.exec(s)) !== null) {
|
|
2016
|
+
localMatches.push({ bindVar: m[1], fieldName: m[2], raw: m[0], via: "final_vars" });
|
|
2017
|
+
}
|
|
2018
|
+
reTopLevel.lastIndex = 0;
|
|
2019
|
+
while ((m = reTopLevel.exec(s)) !== null) {
|
|
2020
|
+
// Skip `${R.final_vars.X}` matches — already captured by
|
|
2021
|
+
// reExplicit above with the X named, not "final_vars".
|
|
2022
|
+
if (m[2] === "final_vars")
|
|
2023
|
+
continue;
|
|
2024
|
+
// Skip the other always-exported envelope fields.
|
|
2025
|
+
if (ALWAYS_EXPORTED.has(m[2]))
|
|
2026
|
+
continue;
|
|
2027
|
+
localMatches.push({ bindVar: m[1], fieldName: m[2], raw: m[0], via: "top-level" });
|
|
2028
|
+
}
|
|
2029
|
+
for (const { bindVar, fieldName, raw, via } of localMatches) {
|
|
2030
|
+
if (!bindings.has(bindVar))
|
|
2031
|
+
continue;
|
|
2032
|
+
const calledSkill = bindings.get(bindVar);
|
|
2033
|
+
const returns = await loadReturns(calledSkill);
|
|
2034
|
+
if (returns === null)
|
|
2035
|
+
continue; // forward-ref, deferred
|
|
2036
|
+
if (returns.has(fieldName))
|
|
2037
|
+
continue;
|
|
2038
|
+
const key = `${targetName}:${raw}`;
|
|
2039
|
+
if (reported.has(key))
|
|
2040
|
+
continue;
|
|
2041
|
+
reported.add(key);
|
|
2042
|
+
const declared = returns.size === 0 ? "(none — skill has no `# Returns:` header)" : `[${Array.from(returns).join(", ")}]`;
|
|
2043
|
+
const remediation = via === "top-level"
|
|
2044
|
+
? `Add '${fieldName}' to '${calledSkill}'\`s \`# Returns:\` (declared returns access via \`\${${bindVar}.<name>}\` top-level), or use \`\${${bindVar}.outputs.text}\` for the always-exported emission stream.`
|
|
2045
|
+
: `Add '${fieldName}' to '${calledSkill}'\`s \`# Returns:\` or use \`\${${bindVar}.outputs.text}\` for the always-exported emission stream.`;
|
|
2046
|
+
findings.push({
|
|
2047
|
+
rule: "unexported-final-var-access",
|
|
2048
|
+
severity: "warning",
|
|
2049
|
+
message: `\`${raw}...}\` in target '${targetName}' accesses '${fieldName}' on the result of \`execute_skill\` to '${calledSkill}', but '${fieldName}' isn't in that skill's \`# Returns:\` (declared: ${declared}). The runtime filter drops it; substitution renders empty. ${remediation}`,
|
|
2050
|
+
block: targetName,
|
|
2051
|
+
extras: { bind_var: bindVar, called_skill: calledSkill, field: fieldName, declared_returns: Array.from(returns), access_path: via },
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
const collect = async (op) => {
|
|
2056
|
+
if (op.body !== undefined)
|
|
2057
|
+
await scanString(op.body);
|
|
2058
|
+
if (op.setValue !== undefined)
|
|
2059
|
+
await scanString(op.setValue);
|
|
2060
|
+
};
|
|
2061
|
+
const walkAsync = async (ops) => {
|
|
2062
|
+
for (const op of ops) {
|
|
2063
|
+
await collect(op);
|
|
2064
|
+
if (op.foreachBody !== undefined)
|
|
2065
|
+
await walkAsync(op.foreachBody);
|
|
2066
|
+
if (op.ifBranches !== undefined)
|
|
2067
|
+
for (const b of op.ifBranches)
|
|
2068
|
+
await walkAsync(b.body);
|
|
2069
|
+
if (op.ifElseBody !== undefined)
|
|
2070
|
+
await walkAsync(op.ifElseBody);
|
|
2071
|
+
}
|
|
2072
|
+
};
|
|
2073
|
+
await walkAsync(target.ops);
|
|
2074
|
+
if (target.elseBlock !== undefined)
|
|
2075
|
+
await walkAsync(target.elseBlock);
|
|
2076
|
+
}
|
|
2077
|
+
return findings;
|
|
2078
|
+
},
|
|
2079
|
+
};
|
|
1932
2080
|
const TRANSCRIPT_FOOTGUN = {
|
|
1933
2081
|
id: "transcript-footgun",
|
|
1934
2082
|
severity: "warning",
|
|
@@ -2636,6 +2784,7 @@ const RULES = [
|
|
|
2636
2784
|
DEPRECATED_ADDRESSED_TO,
|
|
2637
2785
|
LEGACY_FRONTMATTER_HEADER,
|
|
2638
2786
|
TRANSCRIPT_FOOTGUN,
|
|
2787
|
+
UNEXPORTED_FINAL_VAR_ACCESS,
|
|
2639
2788
|
SET_JSON_LITERAL_ADVISORY,
|
|
2640
2789
|
SKILL_NAME_COLLISION,
|
|
2641
2790
|
UNKNOWN_LLM_MODEL,
|