tutuca 0.9.29 → 0.9.31
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 +25 -0
- package/dist/tutuca-cli.js +172 -31
- package/dist/tutuca-dev.js +89 -25
- package/dist/tutuca-dev.min.js +3 -3
- package/dist/tutuca-extra.js +66 -22
- package/dist/tutuca-extra.min.js +3 -3
- package/dist/tutuca.js +63 -19
- package/dist/tutuca.min.js +3 -3
- package/package.json +9 -4
- package/skill/SKILL.md +36 -0
- package/skill/advanced.md +170 -0
- package/skill/cli.md +110 -0
- package/skill/core.md +677 -0
package/README.md
CHANGED
|
@@ -11,6 +11,9 @@ Zero-dependency batteries included SPA framework.
|
|
|
11
11
|
|
|
12
12
|
## Quick Start
|
|
13
13
|
|
|
14
|
+
For an interactive walk-through with editable examples, see the
|
|
15
|
+
[tutorial](https://marianoguerra.github.io/tutuca/tutorial.html).
|
|
16
|
+
|
|
14
17
|
### CDN (no install)
|
|
15
18
|
|
|
16
19
|
```html
|
|
@@ -92,6 +95,7 @@ tutuca help [command]
|
|
|
92
95
|
| `lint [name]` | Run lint checks — all, or one by name (exit 2 on errors) |
|
|
93
96
|
| `render [name] [--title t] [--view v]` | Render examples to HTML |
|
|
94
97
|
| `doctor` | Lint + render smoke test over the whole module |
|
|
98
|
+
| `install-skill [--user] [--force]` | Install the tutuca Claude Code skill (no module path needed) |
|
|
95
99
|
|
|
96
100
|
Global flags: `-f, --format <cli\|md\|json\|html>`, `-o, --output <file>`, `--pretty`, `-h, --help`.
|
|
97
101
|
|
|
@@ -135,6 +139,27 @@ The invocation stays short even without wrapping, but common patterns:
|
|
|
135
139
|
- **`justfile` / `Makefile`** — one recipe per subcommand, passing through positionals
|
|
136
140
|
- **Programmatic** — `import "tutuca/cli"` (the bundled entry) for custom build integration
|
|
137
141
|
|
|
142
|
+
## Use with Claude Code
|
|
143
|
+
|
|
144
|
+
Tutuca ships an LLM-facing reference (`SKILL.md` + `core.md` / `cli.md` /
|
|
145
|
+
`advanced.md`) packaged as a [Claude Code skill](https://docs.claude.com/en/docs/claude-code/skills).
|
|
146
|
+
Once installed, Claude auto-loads it whenever a session touches tutuca
|
|
147
|
+
components, views, macros, or the CLI.
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
# project-scoped: writes ./.claude/skills/tutuca/ (commit it for the team)
|
|
151
|
+
npx tutuca install-skill
|
|
152
|
+
|
|
153
|
+
# or user-scoped: writes ~/.claude/skills/tutuca/
|
|
154
|
+
npx tutuca install-skill --user
|
|
155
|
+
|
|
156
|
+
# overwrite an existing install
|
|
157
|
+
npx tutuca install-skill --force
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The skill content is generated from `docs/llm/`, so the same reference
|
|
161
|
+
runs locally (`tutuca <module> doctor`) and inside Claude.
|
|
162
|
+
|
|
138
163
|
## License
|
|
139
164
|
|
|
140
165
|
MIT
|
package/dist/tutuca-cli.js
CHANGED
|
@@ -1394,7 +1394,7 @@ class ParseContext {
|
|
|
1394
1394
|
parseHTML(html) {
|
|
1395
1395
|
const t = this.document.createElement("template");
|
|
1396
1396
|
t.innerHTML = html;
|
|
1397
|
-
return
|
|
1397
|
+
return t.content.childNodes;
|
|
1398
1398
|
}
|
|
1399
1399
|
addNodeIf(Class, val, extra) {
|
|
1400
1400
|
if (val !== null) {
|
|
@@ -1614,7 +1614,20 @@ var init_anode = __esm(() => {
|
|
|
1614
1614
|
return this.val.toPathItem();
|
|
1615
1615
|
}
|
|
1616
1616
|
static parse(html, px) {
|
|
1617
|
-
|
|
1617
|
+
const nodes = px.parseHTML(html);
|
|
1618
|
+
if (nodes.length === 0)
|
|
1619
|
+
return new TextNode("");
|
|
1620
|
+
if (nodes.length === 1)
|
|
1621
|
+
return ANode.fromDOM(nodes[0], px);
|
|
1622
|
+
const childs = new Array(nodes.length);
|
|
1623
|
+
for (let i = 0;i < nodes.length; i++)
|
|
1624
|
+
childs[i] = ANode.fromDOM(nodes[i], px);
|
|
1625
|
+
const trimmed = condenseChildsWhites(childs);
|
|
1626
|
+
if (trimmed.length === 0)
|
|
1627
|
+
return new TextNode("");
|
|
1628
|
+
if (trimmed.length === 1)
|
|
1629
|
+
return trimmed[0];
|
|
1630
|
+
return new FragmentNode(trimmed);
|
|
1618
1631
|
}
|
|
1619
1632
|
static fromDOM(node, px) {
|
|
1620
1633
|
if (node instanceof px.Text)
|
|
@@ -1634,10 +1647,8 @@ var init_anode = __esm(() => {
|
|
|
1634
1647
|
switch (name) {
|
|
1635
1648
|
case "slot":
|
|
1636
1649
|
return new SlotNode(null, vp.const(value), maybeFragment(childs));
|
|
1637
|
-
case "text":
|
|
1638
|
-
|
|
1639
|
-
return v !== null ? new RenderTextNode(null, v) : null;
|
|
1640
|
-
}
|
|
1650
|
+
case "text":
|
|
1651
|
+
return px.addNodeIf(RenderTextNode, vp.parseText(value, px));
|
|
1641
1652
|
case "render":
|
|
1642
1653
|
return px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
|
|
1643
1654
|
case "render-it":
|
|
@@ -2025,7 +2036,11 @@ class ComponentStack {
|
|
|
2025
2036
|
}
|
|
2026
2037
|
}
|
|
2027
2038
|
registerMacros(macros) {
|
|
2028
|
-
|
|
2039
|
+
for (const key in macros) {
|
|
2040
|
+
const lower = key.toLowerCase();
|
|
2041
|
+
console.assert(this.macros[lower] === undefined, "macro key collision", lower);
|
|
2042
|
+
this.macros[lower] = macros[key];
|
|
2043
|
+
}
|
|
2029
2044
|
}
|
|
2030
2045
|
getCompFor(v) {
|
|
2031
2046
|
return this.comps.getCompFor(v);
|
|
@@ -2083,7 +2098,10 @@ function checkMacroCallArgs(lx, view, Comp) {
|
|
|
2083
2098
|
const { defaults } = macro;
|
|
2084
2099
|
for (const argName in macroNode.attrs) {
|
|
2085
2100
|
if (!(argName in defaults)) {
|
|
2086
|
-
lx.error(UNKNOWN_MACRO_ARG, {
|
|
2101
|
+
lx.error(UNKNOWN_MACRO_ARG, {
|
|
2102
|
+
name: argName,
|
|
2103
|
+
macroName: macroNode.name
|
|
2104
|
+
});
|
|
2087
2105
|
}
|
|
2088
2106
|
}
|
|
2089
2107
|
}
|
|
@@ -2244,7 +2262,7 @@ function checkConsistentAttrVal(lx, val, fields, proto, computed, scope, alter,
|
|
|
2244
2262
|
if (alter[val.name] === undefined) {
|
|
2245
2263
|
lx.error(ALT_HANDLER_NOT_DEFINED, { name: val.name });
|
|
2246
2264
|
}
|
|
2247
|
-
} else if (valName !== "ConstVal" && valName !== "BindVal") {
|
|
2265
|
+
} else if (valName !== "ConstVal" && valName !== "BindVal" && valName !== "DynVal") {
|
|
2248
2266
|
console.log(val);
|
|
2249
2267
|
}
|
|
2250
2268
|
}
|
|
@@ -2258,8 +2276,21 @@ function checkConsistentAttrs(lx, Comp, referencedAlters, referencedComputed) {
|
|
|
2258
2276
|
for (const attr of view.ctx.attrs) {
|
|
2259
2277
|
const { attrs, wrapperAttrs, textChild, isMacroCall } = attr;
|
|
2260
2278
|
if (attrs?.constructor.name === "DynAttrs") {
|
|
2279
|
+
const seenNames = new Set;
|
|
2261
2280
|
for (const attr2 of attrs.items) {
|
|
2262
|
-
|
|
2281
|
+
const name = attr2?.name;
|
|
2282
|
+
if (name !== undefined && name !== "data-eid") {
|
|
2283
|
+
if (seenNames.has(name)) {
|
|
2284
|
+
lx.error(DUPLICATE_ATTR_DEFINITION, { name });
|
|
2285
|
+
} else {
|
|
2286
|
+
seenNames.add(name);
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
if (attr2?.constructor.name === "IfAttr") {
|
|
2290
|
+
for (const subVal of [attr2.condVal, attr2.thenVal, attr2.elseVal]) {
|
|
2291
|
+
checkConsistentAttrVal(lx, subVal, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
|
|
2292
|
+
}
|
|
2293
|
+
} else if (attr2?.val !== undefined) {
|
|
2263
2294
|
checkConsistentAttrVal(lx, attr2.val, fields, proto, computed, scope, alter, referencedAlters, referencedComputed, isMacroCall);
|
|
2264
2295
|
}
|
|
2265
2296
|
}
|
|
@@ -2346,7 +2377,7 @@ class LintContext {
|
|
|
2346
2377
|
this.reports.push({ id, info, level, context: { ...this.frame } });
|
|
2347
2378
|
}
|
|
2348
2379
|
}
|
|
2349
|
-
var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
|
|
2380
|
+
var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
|
|
2350
2381
|
var init_lint_check = __esm(() => {
|
|
2351
2382
|
init_anode();
|
|
2352
2383
|
NO_WRAPPERS = {};
|
|
@@ -7706,7 +7737,7 @@ class Renderer {
|
|
|
7706
7737
|
this.cache = new WeakMapDomCache;
|
|
7707
7738
|
}
|
|
7708
7739
|
getSeqInfo(seq) {
|
|
7709
|
-
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter :
|
|
7740
|
+
return isIndexed(seq) ? imIndexedIter : isKeyed(seq) ? imKeyedIter : seq?.[SEQ_INFO] ?? unkIter;
|
|
7710
7741
|
}
|
|
7711
7742
|
renderTag(tag, attrs, childs) {
|
|
7712
7743
|
return h(tag, attrs, childs);
|
|
@@ -7822,12 +7853,12 @@ var DATASET_ATTRS, imIndexedIter = (seq, visit) => {
|
|
|
7822
7853
|
}, imKeyedIter = (seq, visit) => {
|
|
7823
7854
|
for (const [k, v] of seq.toSeq().entries())
|
|
7824
7855
|
visit(k, v, "sk");
|
|
7825
|
-
}, unkIter = () => {},
|
|
7856
|
+
}, unkIter = () => {}, SEQ_INFO;
|
|
7826
7857
|
var init_renderer = __esm(() => {
|
|
7827
7858
|
init_immutable();
|
|
7828
7859
|
init_vdom();
|
|
7829
7860
|
DATASET_ATTRS = ["nid", "cid", "eid", "vid", "si", "sk"];
|
|
7830
|
-
|
|
7861
|
+
SEQ_INFO = Symbol.for("tutuca.seqInfo");
|
|
7831
7862
|
});
|
|
7832
7863
|
|
|
7833
7864
|
// src/util/render.js
|
|
@@ -8027,11 +8058,105 @@ var init__registry = __esm(() => {
|
|
|
8027
8058
|
};
|
|
8028
8059
|
});
|
|
8029
8060
|
|
|
8061
|
+
// tools/cli/commands/install-skill.js
|
|
8062
|
+
var exports_install_skill = {};
|
|
8063
|
+
__export(exports_install_skill, {
|
|
8064
|
+
run: () => run,
|
|
8065
|
+
describe: () => describe
|
|
8066
|
+
});
|
|
8067
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
8068
|
+
import { homedir } from "node:os";
|
|
8069
|
+
import { dirname, resolve } from "node:path";
|
|
8070
|
+
import { parseArgs } from "node:util";
|
|
8071
|
+
import { fileURLToPath } from "node:url";
|
|
8072
|
+
function findSkillDir() {
|
|
8073
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
8074
|
+
const candidates = [resolve(here, "..", "..", "..", "skill"), resolve(here, "..", "skill")];
|
|
8075
|
+
for (const c of candidates) {
|
|
8076
|
+
if (existsSync(resolve(c, "SKILL.md")))
|
|
8077
|
+
return c;
|
|
8078
|
+
}
|
|
8079
|
+
return null;
|
|
8080
|
+
}
|
|
8081
|
+
function targetDir(scope) {
|
|
8082
|
+
if (scope === "user")
|
|
8083
|
+
return resolve(homedir(), ".claude/skills/tutuca");
|
|
8084
|
+
return resolve(process.cwd(), ".claude/skills/tutuca");
|
|
8085
|
+
}
|
|
8086
|
+
async function run(argv) {
|
|
8087
|
+
const parsed = parseArgs({
|
|
8088
|
+
args: argv,
|
|
8089
|
+
options: {
|
|
8090
|
+
user: { type: "boolean", default: false },
|
|
8091
|
+
project: { type: "boolean", default: false },
|
|
8092
|
+
force: { type: "boolean", short: "f", default: false },
|
|
8093
|
+
help: { type: "boolean", short: "h", default: false }
|
|
8094
|
+
},
|
|
8095
|
+
allowPositionals: false
|
|
8096
|
+
});
|
|
8097
|
+
if (parsed.values.help) {
|
|
8098
|
+
process.stdout.write(`tutuca install-skill [--user | --project] [--force]
|
|
8099
|
+
` + `
|
|
8100
|
+
` + ` Copies SKILL.md + core.md + cli.md + advanced.md into
|
|
8101
|
+
` + ` .claude/skills/tutuca/. Defaults to --project (cwd).
|
|
8102
|
+
` + ` --user installs at ~/.claude/skills/tutuca/.
|
|
8103
|
+
` + ` --force overwrites existing files.
|
|
8104
|
+
`);
|
|
8105
|
+
return;
|
|
8106
|
+
}
|
|
8107
|
+
if (parsed.values.user && parsed.values.project) {
|
|
8108
|
+
process.stderr.write(`tutuca: --user and --project are mutually exclusive
|
|
8109
|
+
`);
|
|
8110
|
+
process.exit(1);
|
|
8111
|
+
}
|
|
8112
|
+
const scope = parsed.values.user ? "user" : "project";
|
|
8113
|
+
const target = targetDir(scope);
|
|
8114
|
+
const src = findSkillDir();
|
|
8115
|
+
if (!src) {
|
|
8116
|
+
process.stderr.write(`tutuca: skill assets not found alongside this CLI.
|
|
8117
|
+
` + "If you're running from a checkout, run `bun scripts/build-skill.js` first.\n");
|
|
8118
|
+
process.exit(1);
|
|
8119
|
+
}
|
|
8120
|
+
if (existsSync(target) && !parsed.values.force) {
|
|
8121
|
+
const existing = readdirSync(target).filter((n) => SKILL_FILES.includes(n));
|
|
8122
|
+
if (existing.length > 0) {
|
|
8123
|
+
process.stderr.write(`tutuca: ${target} already contains skill files. Re-run with --force to overwrite.
|
|
8124
|
+
`);
|
|
8125
|
+
process.exit(1);
|
|
8126
|
+
}
|
|
8127
|
+
}
|
|
8128
|
+
mkdirSync(target, { recursive: true });
|
|
8129
|
+
for (const name of SKILL_FILES) {
|
|
8130
|
+
const from = resolve(src, name);
|
|
8131
|
+
if (!existsSync(from)) {
|
|
8132
|
+
process.stderr.write(`tutuca: missing skill asset: ${from}
|
|
8133
|
+
`);
|
|
8134
|
+
process.exit(1);
|
|
8135
|
+
}
|
|
8136
|
+
const buf = readFileSync(from);
|
|
8137
|
+
writeFileSync(resolve(target, name), buf);
|
|
8138
|
+
}
|
|
8139
|
+
const rel = scope === "project" ? ".claude/skills/tutuca" : target;
|
|
8140
|
+
process.stdout.write(`installed tutuca skill → ${rel}
|
|
8141
|
+
`);
|
|
8142
|
+
process.stdout.write(`Open a Claude Code session in this directory to use it.
|
|
8143
|
+
`);
|
|
8144
|
+
}
|
|
8145
|
+
var describe = "Install the tutuca Claude Code skill into .claude/skills/tutuca/.", SKILL_FILES;
|
|
8146
|
+
var init_install_skill = __esm(() => {
|
|
8147
|
+
SKILL_FILES = ["SKILL.md", "core.md", "cli.md", "advanced.md"];
|
|
8148
|
+
});
|
|
8149
|
+
|
|
8030
8150
|
// tools/tutuca.js
|
|
8031
8151
|
init__registry();
|
|
8032
8152
|
|
|
8033
8153
|
// tools/cli/commands/help.js
|
|
8034
|
-
var
|
|
8154
|
+
var exports_help = {};
|
|
8155
|
+
__export(exports_help, {
|
|
8156
|
+
run: () => run2,
|
|
8157
|
+
describe: () => describe2
|
|
8158
|
+
});
|
|
8159
|
+
var describe2 = "Show usage. `help <command>` for per-command detail.";
|
|
8035
8160
|
var OVERVIEW = `tutuca — CLI for inspecting, documenting, linting and rendering tutuca
|
|
8036
8161
|
components defined in an ES module.
|
|
8037
8162
|
|
|
@@ -8109,6 +8234,11 @@ COMMANDS (no module required)
|
|
|
8109
8234
|
Without [command]: prints this full reference.
|
|
8110
8235
|
With [command]: prints that command's one-line description.
|
|
8111
8236
|
|
|
8237
|
+
install-skill [--user | --project] [--force]
|
|
8238
|
+
Copy the bundled Claude Code skill (SKILL.md + core/cli/advanced.md)
|
|
8239
|
+
into .claude/skills/tutuca/. Default scope is --project (cwd);
|
|
8240
|
+
--user installs at ~/.claude/skills/tutuca/. --force overwrites.
|
|
8241
|
+
|
|
8112
8242
|
GLOBAL FLAGS
|
|
8113
8243
|
-f, --format <cli|md|json|html>
|
|
8114
8244
|
Output format. Defaults per command:
|
|
@@ -8150,19 +8280,22 @@ EXAMPLES
|
|
|
8150
8280
|
# CI smoke test
|
|
8151
8281
|
tutuca ./src/components.js doctor
|
|
8152
8282
|
`;
|
|
8153
|
-
async function
|
|
8283
|
+
async function run2(argv) {
|
|
8154
8284
|
const target = argv?.[0];
|
|
8155
8285
|
if (!target) {
|
|
8156
8286
|
process.stdout.write(OVERVIEW);
|
|
8157
8287
|
return;
|
|
8158
8288
|
}
|
|
8159
8289
|
if (target === "help") {
|
|
8160
|
-
process.stdout.write(`help: ${
|
|
8290
|
+
process.stdout.write(`help: ${describe2}
|
|
8161
8291
|
`);
|
|
8162
8292
|
return;
|
|
8163
8293
|
}
|
|
8164
8294
|
const { COMMANDS: COMMANDS2 } = await Promise.resolve().then(() => (init__registry(), exports__registry));
|
|
8165
|
-
const
|
|
8295
|
+
const noModule = {
|
|
8296
|
+
"install-skill": await Promise.resolve().then(() => (init_install_skill(), exports_install_skill))
|
|
8297
|
+
};
|
|
8298
|
+
const cmd = COMMANDS2[target] ?? noModule[target];
|
|
8166
8299
|
if (!cmd) {
|
|
8167
8300
|
process.stderr.write(`tutuca: unknown command: ${target}
|
|
8168
8301
|
`);
|
|
@@ -8174,8 +8307,11 @@ async function run(argv) {
|
|
|
8174
8307
|
process.stdout.write("Run `tutuca help` for the full reference including signatures and flags.\n");
|
|
8175
8308
|
}
|
|
8176
8309
|
|
|
8310
|
+
// tools/tutuca.js
|
|
8311
|
+
init_install_skill();
|
|
8312
|
+
|
|
8177
8313
|
// tools/cli/with-module.js
|
|
8178
|
-
import { parseArgs } from "node:util";
|
|
8314
|
+
import { parseArgs as parseArgs2 } from "node:util";
|
|
8179
8315
|
|
|
8180
8316
|
// tools/cli/env.js
|
|
8181
8317
|
init_anode();
|
|
@@ -8205,16 +8341,16 @@ async function createNodeEnv() {
|
|
|
8205
8341
|
}
|
|
8206
8342
|
|
|
8207
8343
|
// tools/cli/load.js
|
|
8208
|
-
import { resolve } from "node:path";
|
|
8344
|
+
import { resolve as resolve2 } from "node:path";
|
|
8209
8345
|
async function loadAndNormalize(modulePath) {
|
|
8210
|
-
const abs =
|
|
8346
|
+
const abs = resolve2(modulePath);
|
|
8211
8347
|
const mod = await import(abs);
|
|
8212
8348
|
const { normalized } = normalizeModule(mod, { path: abs });
|
|
8213
8349
|
return normalized;
|
|
8214
8350
|
}
|
|
8215
8351
|
|
|
8216
8352
|
// tools/cli/output.js
|
|
8217
|
-
import { writeFileSync } from "node:fs";
|
|
8353
|
+
import { writeFileSync as writeFileSync2 } from "node:fs";
|
|
8218
8354
|
|
|
8219
8355
|
// tools/format/cli.js
|
|
8220
8356
|
var exports_cli = {};
|
|
@@ -8606,7 +8742,7 @@ async function formatResult(formatName, result, options = {}) {
|
|
|
8606
8742
|
async function emit(result, { format: format5, pretty, output }) {
|
|
8607
8743
|
const text = await formatResult(format5, result, { pretty });
|
|
8608
8744
|
if (output) {
|
|
8609
|
-
|
|
8745
|
+
writeFileSync2(output, text);
|
|
8610
8746
|
} else {
|
|
8611
8747
|
process.stdout.write(text);
|
|
8612
8748
|
if (!text.endsWith(`
|
|
@@ -8618,7 +8754,7 @@ async function emit(result, { format: format5, pretty, output }) {
|
|
|
8618
8754
|
|
|
8619
8755
|
// tools/cli/with-module.js
|
|
8620
8756
|
async function runCommand(cmd, argv, globalOpts) {
|
|
8621
|
-
const parsed =
|
|
8757
|
+
const parsed = parseArgs2({
|
|
8622
8758
|
args: argv,
|
|
8623
8759
|
options: cmd.parseOptions ?? {},
|
|
8624
8760
|
allowPositionals: true
|
|
@@ -8639,6 +8775,10 @@ async function runCommand(cmd, argv, globalOpts) {
|
|
|
8639
8775
|
}
|
|
8640
8776
|
|
|
8641
8777
|
// tools/tutuca.js
|
|
8778
|
+
var NO_MODULE_COMMANDS = {
|
|
8779
|
+
help: exports_help,
|
|
8780
|
+
"install-skill": exports_install_skill
|
|
8781
|
+
};
|
|
8642
8782
|
function usageError(msg) {
|
|
8643
8783
|
process.stderr.write(`tutuca: ${msg}
|
|
8644
8784
|
Run \`tutuca help\` for usage.
|
|
@@ -8675,13 +8815,13 @@ function extractGlobals(argv) {
|
|
|
8675
8815
|
async function main() {
|
|
8676
8816
|
const { opts, rest } = extractGlobals(process.argv.slice(2));
|
|
8677
8817
|
if (rest.length === 0 || opts.help && rest.length === 0) {
|
|
8678
|
-
await
|
|
8818
|
+
await run2([], opts);
|
|
8679
8819
|
return;
|
|
8680
8820
|
}
|
|
8681
8821
|
let command;
|
|
8682
8822
|
let commandArgs;
|
|
8683
|
-
if (rest[0]
|
|
8684
|
-
command =
|
|
8823
|
+
if (NO_MODULE_COMMANDS[rest[0]]) {
|
|
8824
|
+
command = rest[0];
|
|
8685
8825
|
commandArgs = rest.slice(1);
|
|
8686
8826
|
} else if (opts.module) {
|
|
8687
8827
|
command = rest[0];
|
|
@@ -8693,12 +8833,13 @@ async function main() {
|
|
|
8693
8833
|
command = rest[1];
|
|
8694
8834
|
commandArgs = rest.slice(2);
|
|
8695
8835
|
}
|
|
8696
|
-
if (
|
|
8697
|
-
|
|
8836
|
+
if (NO_MODULE_COMMANDS[command]) {
|
|
8837
|
+
const args = opts.help ? [...commandArgs, "--help"] : commandArgs;
|
|
8838
|
+
await NO_MODULE_COMMANDS[command].run(args, opts);
|
|
8698
8839
|
return;
|
|
8699
8840
|
}
|
|
8700
|
-
if (
|
|
8701
|
-
await
|
|
8841
|
+
if (opts.help) {
|
|
8842
|
+
await run2([command], opts);
|
|
8702
8843
|
return;
|
|
8703
8844
|
}
|
|
8704
8845
|
const cmd = COMMANDS[command];
|