@hybridlabor-api/aos 4.12.0 → 4.13.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/.agents/vendor-manifest.json +6 -0
- package/.claude/agents/reviewer.md +1 -1
- package/.claude/agents/techlead.md +1 -1
- package/.opencode/agents/architect.md +1 -1
- package/.opencode/agents/reviewer.md +1 -1
- package/.opencode/agents/techlead.md +1 -1
- package/README.de.md +297 -725
- package/README.md +295 -831
- package/README.pt.md +317 -677
- package/THIRD_PARTY_NOTICES.md +94 -0
- package/bin/aos-store.mjs +48 -45
- package/installer.js +22 -20
- package/lib/scenario-store-index.json +1 -0
- package/lib/store-shared.mjs +81 -4
- package/lib/store-ui/index.html +14 -5
- package/lib/store-ui/server.mjs +44 -21
- package/package.json +2 -2
- package/scripts/build-plugin-manifest.mjs +36 -13
- package/scripts/build-scenario-store-index.mjs +154 -0
- package/skills/bdbrainstorm/SKILL.md +1 -0
- package/skills/global_config/agent-pipeline/SKILL.md +4 -0
- package/skills/global_config/aos-store/SKILL.md +4 -4
- package/skills/global_config/design-control-loop/SKILL.md +184 -0
- package/skills/global_config/design-control-loop/references/agent-iteration.ts +174 -0
- package/skills/global_config/design-control-loop/references/agent-runner-templates.md +157 -0
- package/skills/global_config/design-control-loop/references/control-loop-taxonomy.md +75 -0
- package/skills/global_config/design-control-loop/references/example-control-loop.md +57 -0
- package/skills/global_config/design-control-loop/references/example-skill.md +171 -0
- package/skills/global_config/design-control-loop/references/memory-template.md +7 -0
- package/skills/global_config/design-control-loop/references/prompt-template.md +58 -0
- package/skills/global_config/design-control-loop/references/response-template.md +103 -0
- package/skills/global_config/design-control-loop/references/skill-template.md +57 -0
- package/skills/global_config/design-control-loop/references/workflow-template.yml +273 -0
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -413,7 +413,101 @@ store. Reasons are in `docs/handover/` and the branch description for
|
|
|
413
413
|
|
|
414
414
|
---
|
|
415
415
|
|
|
416
|
+
## humanlayer/skills
|
|
417
|
+
|
|
418
|
+
<https://github.com/humanlayer/skills> — MIT. Copyright (c) 2026 HumanLayer.
|
|
419
|
+
|
|
420
|
+
Tracked in `.agents/vendor-manifest.json` at pinned commit
|
|
421
|
+
`ca7c8088db69e315a8b2deea43820270457f8f3c`.
|
|
422
|
+
|
|
423
|
+
One skill is vendored as `skills/global_config/design-control-loop/`
|
|
424
|
+
(`SKILL.md` plus its 10 `references/` files, including the unmodified
|
|
425
|
+
`agent-iteration.ts` and `workflow-template.yml` templates). The upstream
|
|
426
|
+
`.claude-plugin/plugin.json` was not carried over.
|
|
427
|
+
|
|
428
|
+
AOS modifications, all in `SKILL.md` only: `category:`, `source:` and `license:`
|
|
429
|
+
added to the frontmatter; one delimited "AOS notes" section inserted directly
|
|
430
|
+
after the H1. Upstream prose and all `references/` files are byte-identical.
|
|
431
|
+
|
|
432
|
+
```
|
|
433
|
+
MIT License
|
|
434
|
+
|
|
435
|
+
Copyright (c) 2026 HumanLayer
|
|
436
|
+
|
|
437
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
438
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
439
|
+
in the Software without restriction, including without limitation the rights
|
|
440
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
441
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
442
|
+
furnished to do so, subject to the following conditions:
|
|
443
|
+
|
|
444
|
+
The above copyright notice and this permission notice shall be included in all
|
|
445
|
+
copies or substantial portions of the Software.
|
|
446
|
+
|
|
447
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
448
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
449
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
450
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
451
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
452
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
453
|
+
SOFTWARE.
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
416
458
|
## Note on `mcps/`
|
|
417
459
|
|
|
418
460
|
Sub-repositories vendored under `mcps/` carry their own `LICENSE` files in
|
|
419
461
|
their own directories and are not restated here.
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## scenario-labs/skills
|
|
466
|
+
|
|
467
|
+
- **Upstream:** <https://github.com/scenario-labs/skills>
|
|
468
|
+
- **License:** MIT
|
|
469
|
+
- **Copyright:** Copyright (c) 2026 Scenario
|
|
470
|
+
- **Pinned commit:** `5786accd3bb6d79808330230c698898862e8a1d4`
|
|
471
|
+
|
|
472
|
+
### Store index (second AOS Store source)
|
|
473
|
+
|
|
474
|
+
The AOS Store lists a starter set of skills from this project through
|
|
475
|
+
`lib/scenario-store-index.json` (regenerated by
|
|
476
|
+
`scripts/build-scenario-store-index.mjs` from a local clone and the pinned
|
|
477
|
+
commit). The index holds metadata and a per-file SHA-256 list only. The files
|
|
478
|
+
are not vendored: they are downloaded from
|
|
479
|
+
`https://raw.githubusercontent.com/scenario-labs/skills/<pinned commit>/` on
|
|
480
|
+
demand, only after an explicit `--net` or UI confirmation, and each file is
|
|
481
|
+
verified against its SHA-256 before anything is written.
|
|
482
|
+
|
|
483
|
+
Some of these skills contain Python and C# scripts, one of which
|
|
484
|
+
(`scenario-unity-expert`) executes code received through a local channel
|
|
485
|
+
without authentication. The store and its UI mark this before installation.
|
|
486
|
+
|
|
487
|
+
The MIT license covers the software and documentation in that repository. The
|
|
488
|
+
Scenario name and logo are trademarks of their owner and are **not** licensed
|
|
489
|
+
by it; AOS does not use the logo.
|
|
490
|
+
|
|
491
|
+
```
|
|
492
|
+
MIT License
|
|
493
|
+
|
|
494
|
+
Copyright (c) 2026 Scenario
|
|
495
|
+
|
|
496
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
497
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
498
|
+
in the Software without restriction, including without limitation the rights
|
|
499
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
500
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
501
|
+
furnished to do so, subject to the following conditions:
|
|
502
|
+
|
|
503
|
+
The above copyright notice and this permission notice shall be included in all
|
|
504
|
+
copies or substantial portions of the Software.
|
|
505
|
+
|
|
506
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
507
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
508
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
509
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
510
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
511
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
512
|
+
SOFTWARE.
|
|
513
|
+
```
|
package/bin/aos-store.mjs
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createHash } from 'node:crypto';
|
|
4
|
-
import { mkdirSync,
|
|
5
|
-
import { dirname,
|
|
4
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { dirname, resolve } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import { fetchSkillFiles, fileTargets, localAgents, localSkills, targetsFor as sharedTargetsFor, validateFiles,
|
|
7
|
+
import { fetchSkillFiles, fileTargets, findItem, installPlan, loadSources, localAgents, localSkills, planSkillFiles, planSummary, targetsFor as sharedTargetsFor, validateFiles, writePlan } from '../lib/store-shared.mjs';
|
|
8
8
|
|
|
9
9
|
const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
10
|
-
const
|
|
11
|
-
const RAW_BASE = (process.env.AOS_STORE_RAW_BASE || 'https://raw.githubusercontent.com/affaan-m/ECC').replace(/\/+$/, '');
|
|
12
|
-
const index = JSON.parse(readFileSync(INDEX_PATH, 'utf8'));
|
|
10
|
+
const sources = loadSources(ROOT);
|
|
13
11
|
const args = process.argv.slice(2);
|
|
14
12
|
const dryRun = args.includes('--dry-run');
|
|
15
13
|
const project = args.includes('--project');
|
|
@@ -17,21 +15,9 @@ const net = args.includes('--net');
|
|
|
17
15
|
const positional = args.filter((arg) => !arg.startsWith('--'));
|
|
18
16
|
const option = (name) => args.find((arg) => arg === name || arg.startsWith(`${name}=`))?.split('=').slice(1).join('=');
|
|
19
17
|
|
|
20
|
-
function loadIndex() {
|
|
21
|
-
if (!index.pinned_commit || !index.skills || !index.subagents) throw new Error('Invalid AOS store index');
|
|
22
|
-
return index;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
18
|
function allItems(type) {
|
|
26
19
|
const selected = type === 'agents' || type === 'subagents' ? 'subagents' : 'skills';
|
|
27
|
-
return Object.entries(index[selected] || {}).map(([name, item]) => ({ name, item, type: selected }));
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function findItem(name) {
|
|
31
|
-
for (const type of ['skills', 'subagents']) {
|
|
32
|
-
if (index[type]?.[name]) return { name, item: index[type][name], type };
|
|
33
|
-
}
|
|
34
|
-
return null;
|
|
20
|
+
return sources.flatMap((src) => Object.entries(src.index[selected] || {}).map(([name, item]) => ({ name, item, type: selected, src })));
|
|
35
21
|
}
|
|
36
22
|
|
|
37
23
|
const localSkillNames = () => new Set(localSkills(ROOT).keys());
|
|
@@ -42,15 +28,15 @@ function printItems(items) {
|
|
|
42
28
|
console.log('No store items found.');
|
|
43
29
|
return;
|
|
44
30
|
}
|
|
45
|
-
for (const { name, item, type } of items) {
|
|
31
|
+
for (const { name, item, type, src } of items) {
|
|
46
32
|
const kind = type === 'skills' ? 'skill' : 'agent';
|
|
47
|
-
console.log(`${kind}\t${name}\t${item.category}\t${item.description}`);
|
|
33
|
+
console.log(`${kind}\t${name}\t${item.category}\t${src.label}\t${item.description}`);
|
|
48
34
|
}
|
|
49
35
|
console.log(`\n${items.length} item(s).`);
|
|
50
36
|
}
|
|
51
37
|
|
|
52
|
-
async function download(upstreamPath) {
|
|
53
|
-
const url = `${
|
|
38
|
+
async function download(src, upstreamPath) {
|
|
39
|
+
const url = `${src.raw_base}/${src.pinned_commit}/${upstreamPath}`;
|
|
54
40
|
const response = await fetch(url, { headers: { 'user-agent': 'aos-store' } });
|
|
55
41
|
if (!response.ok) throw new Error(`Download failed (${response.status}): ${url}`);
|
|
56
42
|
return Buffer.from(await response.arrayBuffer());
|
|
@@ -60,42 +46,60 @@ const targetsFor = (type, name) => sharedTargetsFor(type, name, { project });
|
|
|
60
46
|
|
|
61
47
|
async function install(name) {
|
|
62
48
|
if (!/^[A-Za-z0-9_-]+$/.test(name)) throw new Error(`Invalid store name: ${name}`);
|
|
63
|
-
const found = findItem(name);
|
|
49
|
+
const found = findItem(sources, name);
|
|
64
50
|
if (!found) throw new Error(`Store item not found: ${name}`);
|
|
65
|
-
const {
|
|
51
|
+
const { type, src } = found;
|
|
66
52
|
const coreNames = type === 'skills' ? localSkillNames() : localAgentNames();
|
|
67
53
|
if (coreNames.has(name)) {
|
|
68
54
|
console.log(`Skipped ${name}: AOS core already provides it.`);
|
|
69
55
|
return;
|
|
70
56
|
}
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
|
|
57
|
+
const plan = installPlan(sources, found).filter((p) => !(p.type === 'skills' && p.name !== name && localSkillNames().has(p.name)));
|
|
58
|
+
for (const p of plan) if (p.item.files?.length > 1) validateFiles(p.item.files);
|
|
59
|
+
const multi = (p) => p.type === 'skills' && p.item.files?.length > 1;
|
|
60
|
+
const summary = planSummary(plan);
|
|
61
|
+
const notes = [];
|
|
62
|
+
if (summary.requires.length) notes.push(`also installs required skill(s): ${summary.requires.join(', ')}`);
|
|
63
|
+
if (summary.execBridge) notes.push(`WARNING: contains a script that executes code received over a local socket or file channel without authentication (${summary.execBridgeFiles.map((f) => `${f.skill}/${f.path}`).join(', ')}); install only if you use this bridge`);
|
|
64
|
+
else if (summary.hasScripts) notes.push(`WARNING: contains ${summary.scriptCount} script file(s); review before use`);
|
|
74
65
|
if (dryRun) {
|
|
75
|
-
for (const
|
|
76
|
-
|
|
77
|
-
|
|
66
|
+
for (const note of notes) console.log(note);
|
|
67
|
+
for (const p of plan) {
|
|
68
|
+
for (const target of targetsFor(p.type, p.name)) {
|
|
69
|
+
if (multi(p)) for (const file of fileTargets(target, p.item.files)) console.log(`[dry-run] write ${file}`);
|
|
70
|
+
else console.log(`[dry-run] write ${target}`);
|
|
71
|
+
}
|
|
78
72
|
}
|
|
79
73
|
return;
|
|
80
74
|
}
|
|
81
75
|
if (!net) {
|
|
82
76
|
throw new Error(`Downloading '${name}' requires internet access to fetch from upstream GitHub. Pass --net to confirm: aos store install ${name} --net`);
|
|
83
77
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
78
|
+
// All-or-nothing: download, hash-check and path-check every skill in memory before the first write.
|
|
79
|
+
const writes = [];
|
|
80
|
+
for (const p of plan) {
|
|
81
|
+
const pSrc = p.src;
|
|
82
|
+
let files;
|
|
83
|
+
if (multi(p)) {
|
|
84
|
+
files = await fetchSkillFiles(pSrc.raw_base, pSrc.pinned_commit, dirname(p.item.upstream_path), p.item.files);
|
|
85
|
+
} else {
|
|
86
|
+
const content = await download(pSrc, p.item.upstream_path);
|
|
87
|
+
const digest = createHash('sha256').update(content).digest('hex');
|
|
88
|
+
if (digest !== p.item.sha256) throw new Error(`SHA-256 mismatch for ${p.name}: expected ${p.item.sha256}, got ${digest}`);
|
|
89
|
+
files = null;
|
|
90
|
+
for (const target of targetsFor(p.type, p.name)) writes.push({ name: p.name, single: { target, content } });
|
|
89
91
|
}
|
|
90
|
-
|
|
92
|
+
if (files) for (const target of targetsFor(p.type, p.name)) writes.push({ name: p.name, target, plan: planSkillFiles(target, files) });
|
|
91
93
|
}
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
for (const note of notes) console.log(note);
|
|
95
|
+
for (const w of writes) {
|
|
96
|
+
if (w.single) {
|
|
97
|
+
mkdirSync(dirname(w.single.target), { recursive: true });
|
|
98
|
+
writeFileSync(w.single.target, w.single.content);
|
|
99
|
+
console.log(`Installed ${w.name} -> ${w.single.target}`);
|
|
100
|
+
} else {
|
|
101
|
+
console.log(`Installed ${w.name} (${writePlan(w.plan).length} files) -> ${dirname(w.target)}`);
|
|
102
|
+
}
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -108,7 +112,6 @@ function usage() {
|
|
|
108
112
|
}
|
|
109
113
|
|
|
110
114
|
async function main() {
|
|
111
|
-
loadIndex();
|
|
112
115
|
const command = positional[0] || 'list';
|
|
113
116
|
if (command === 'list') {
|
|
114
117
|
printItems(allItems(option('--type') || 'skills'));
|
package/installer.js
CHANGED
|
@@ -3354,27 +3354,27 @@ function loadPipelineConfig(projectDir = currentDir) {
|
|
|
3354
3354
|
function resolveAgentConfig(agentSlug, harness, pipelineConfig = null) {
|
|
3355
3355
|
const normSlug = agentSlug.toLowerCase().replace(/-/g, '_');
|
|
3356
3356
|
const roleCfg = pipelineConfig ? (pipelineConfig[normSlug] || pipelineConfig[agentSlug]) : null;
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
}
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
}
|
|
3357
|
+
// A role's model/harness describes where AO runs that role; only valid for that harness.
|
|
3358
|
+
const ownHarness = !!roleCfg && (!roleCfg.harness || roleCfg.harness === harness);
|
|
3359
|
+
if (roleCfg && ownHarness && roleCfg.model) {
|
|
3360
|
+
return {
|
|
3361
|
+
model: roleCfg.model,
|
|
3362
|
+
tier: roleCfg.tier || 'custom',
|
|
3363
|
+
enabled: roleCfg.enabled !== false,
|
|
3364
|
+
harness
|
|
3365
|
+
};
|
|
3366
|
+
}
|
|
3367
|
+
if (roleCfg && roleCfg.tier && CANONICAL_TIERS[roleCfg.tier] && CANONICAL_TIERS[roleCfg.tier][harness]) {
|
|
3368
|
+
return {
|
|
3369
|
+
model: CANONICAL_TIERS[roleCfg.tier][harness],
|
|
3370
|
+
tier: roleCfg.tier,
|
|
3371
|
+
enabled: roleCfg.enabled !== false,
|
|
3372
|
+
harness
|
|
3373
|
+
};
|
|
3374
3374
|
}
|
|
3375
3375
|
const defaultTier = (normSlug === 'architect' || normSlug === 'reviewer') ? 'reasoning_max' : 'standard_fast';
|
|
3376
3376
|
const fallbackModel = (CANONICAL_TIERS[defaultTier] && CANONICAL_TIERS[defaultTier][harness]) || 'inherit';
|
|
3377
|
-
return { model: fallbackModel, tier: defaultTier, enabled:
|
|
3377
|
+
return { model: fallbackModel, tier: defaultTier, enabled: !(roleCfg && roleCfg.model && roleCfg.enabled === false), harness };
|
|
3378
3378
|
}
|
|
3379
3379
|
|
|
3380
3380
|
// Generates .claude/agents/<name>.md — Claude Code's native subagent format.
|
|
@@ -3385,7 +3385,8 @@ function compileClaudeAgents(agents, targetDir, pipelineConfig = null) {
|
|
|
3385
3385
|
for (const a of agents) {
|
|
3386
3386
|
const slug = a.name.toLowerCase().replace(/_/g, '-');
|
|
3387
3387
|
const resolved = resolveAgentConfig(slug, 'claude', pipelineConfig);
|
|
3388
|
-
|
|
3388
|
+
let model = (resolved && resolved.model) ? resolved.model.toLowerCase() : (a.model ? a.model.toLowerCase() : 'inherit');
|
|
3389
|
+
if (!/^(opus|sonnet|haiku|inherit|claude-.+)$/.test(model)) model = CANONICAL_TIERS[resolved.tier in CANONICAL_TIERS ? resolved.tier : 'standard_fast'].claude;
|
|
3389
3390
|
const body = [
|
|
3390
3391
|
a.role,
|
|
3391
3392
|
a.skills.length ? `**Primary skills:** ${a.skills.join(', ')}` : null,
|
|
@@ -3412,7 +3413,8 @@ function compileOpenCodeAgents(agents, targetDir, pipelineConfig = null) {
|
|
|
3412
3413
|
for (const a of agents) {
|
|
3413
3414
|
const slug = a.name.toLowerCase().replace(/_/g, '-');
|
|
3414
3415
|
const resolved = resolveAgentConfig(slug, 'opencode', pipelineConfig);
|
|
3415
|
-
|
|
3416
|
+
let model = resolved && resolved.model ? resolved.model : null;
|
|
3417
|
+
if (model && !model.includes('/')) model = CANONICAL_TIERS[resolved.tier in CANONICAL_TIERS ? resolved.tier : 'standard_fast'].opencode;
|
|
3416
3418
|
const body = [
|
|
3417
3419
|
a.role,
|
|
3418
3420
|
a.skills.length ? `**Primary skills:** ${a.skills.join(', ')}` : null,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":"1.1.0","generated_at":"2026-09-28T16:20:46+02:00","pinned_commit":"5786accd3bb6d79808330230c698898862e8a1d4","source":{"id":"scenario","label":"Scenario","upstream":"https://github.com/scenario-labs/skills","raw_base":"https://raw.githubusercontent.com/scenario-labs/skills","license":"MIT","copyright":"Copyright (c) 2026 Scenario","third_party":true},"harness_support":["claude","antigravity","codex","cursor","roo"],"skills":{"scenario-blender-animation":{"description":"Use when animating characters or objects in Blender through Python, a bouncing ball, walk or run cy…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"aff7450263b6435bd3d654147d971f38ed8effb37ea6aac86e21a3e574d4fa49","upstream_path":"skills/dcc/blender/scenario-blender-animation/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"aff7450263b6435bd3d654147d971f38ed8effb37ea6aac86e21a3e574d4fa49","size":20288,"exec":false},{"path":"references/critique.md","sha256":"cb00a869d0847033d0d5dcc31ced3c4b21169f2c40158e8907ff22384d9c71da","size":29916,"exec":false},{"path":"references/expert-notes.md","sha256":"811e83faf618f9edfcc273d1c21d903c76c787dd73e2092c9c0d31cb3fd06454","size":27069,"exec":false},{"path":"references/procedures.md","sha256":"514cf2ce6f40ecb1184cc57ee63c21deb76193111986d2238e4e909e3fa9155c","size":41355,"exec":false},{"path":"references/sources.md","sha256":"1b45bbf9c056ce1bfd266a3bdfd55677803898758d47f4bafe39bdb34043f662","size":9058,"exec":false},{"path":"scripts/bx_anim.py","sha256":"75db8650041f02d881bb5895130571c8ea7e437d2c20fa77154d961ab8c5f005","size":103257,"exec":false}]},"scenario-blender-expert":{"description":"Use when doing any 3D work in Blender through Python or an MCP bridge, headless or in a live sessio…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"66af9735948dd16ed619c48fdd66b03124a4b521e70543df0f90f77fe6f55376","upstream_path":"skills/dcc/blender/scenario-blender-expert/SKILL.md","software":["Blender"],"hasScripts":true,"scriptCount":3,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"66af9735948dd16ed619c48fdd66b03124a4b521e70543df0f90f77fe6f55376","size":12817,"exec":false},{"path":"references/blender-5.2-deltas.md","sha256":"a3edcef99a5d44c3853901417b9682b17bdda3185bc74f3d1ccada6c7c5f6677","size":118596,"exec":false},{"path":"references/bpy-reliability.md","sha256":"b43625d8ae078dd983fb8b4ddc3d99fa3b71d793142ee1956d6b306b24957566","size":24633,"exec":false},{"path":"scripts/bx_audit.py","sha256":"0ff01ffdc6f9413c42be15016c84fbf8f0696434e1b30cc5ad952813d748a0f8","size":9810,"exec":false},{"path":"scripts/bx_gui.py","sha256":"d5c020f27d2714f7f773da30cfa190017be453a621bb45f1eccececa3a33d60c","size":8951,"exec":false},{"path":"scripts/bx_review.py","sha256":"3862dc1452960f01219206bbc0f24d487810d0f4cda6ab41b97108e522e53986","size":14914,"exec":false}]},"scenario-blender-geometry-nodes":{"description":"Use when building or debugging Geometry Nodes, headless or live: procedural modeling, scattering ob…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"c7465134d8506ad0975063974d5c462ea3638aadf9f316d74dc81c4b7a522923","upstream_path":"skills/dcc/blender/scenario-blender-geometry-nodes/SKILL.md","requires":["scenario-blender-expert"],"software":[],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"c7465134d8506ad0975063974d5c462ea3638aadf9f316d74dc81c4b7a522923","size":16371,"exec":false},{"path":"references/critique.md","sha256":"88331d11fad74946a8989cdfd1d79703f65fe8efd8565c9be152bdbb85cb9e8b","size":11373,"exec":false},{"path":"references/expert-notes.md","sha256":"49fa43b73f7a423a078e2405bd962545a3f6a2a10fa3e57965914b2eb9320c11","size":18172,"exec":false},{"path":"references/procedures.md","sha256":"8f0b2dc24dcbd01296351cee4177cdd7ce11fa7077402293541c9040f85cb58d","size":55863,"exec":false},{"path":"references/sources.md","sha256":"fe060140ec154d9f0c49e0efbe996a9ebf10c1eb0de0467614cf9aa2116df374","size":7510,"exec":false},{"path":"scripts/bx_gn.py","sha256":"b325317f54e1e944f33f1af91e141c20bd5ebe7d3a3c487738fa70fd725639e0","size":57043,"exec":false}]},"scenario-blender-hard-surface":{"description":"Use when modeling hard-surface objects in Blender (sci-fi panels, props, weapons, vehicles, robots,…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"f14733f37d3f0ee2654fcac4f9f0bb3c1bc3112854a38848f71736eb155a525d","upstream_path":"skills/dcc/blender/scenario-blender-hard-surface/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"f14733f37d3f0ee2654fcac4f9f0bb3c1bc3112854a38848f71736eb155a525d","size":18295,"exec":false},{"path":"references/critique.md","sha256":"32fae7dc8e3759556aa4571b868d5fcb783217ce9270c9802aa8b380ca24ee4d","size":14411,"exec":false},{"path":"references/expert-notes.md","sha256":"b9682d071a0fcafa03afa99ae9aecf3831176681d5e74eb7d10c27369386a87b","size":17875,"exec":false},{"path":"references/procedures.md","sha256":"6dbe1b7567a6ff1f21ff5debf4c9235cd7fc4ccea51f736a1b74448bcccca70c","size":25309,"exec":false},{"path":"references/sources.md","sha256":"71d90f1effa9477abdfe4bd77bea4d6b0fb8c21ae2ec449168d9b7d972ba77eb","size":7412,"exec":false},{"path":"scripts/bx_hardsurface.py","sha256":"a7eb60b356c16609573ea8bb0005cd1278e908dcd7593eb7ff1f749ceb7b9999","size":69529,"exec":false}]},"scenario-blender-lighting-rendering":{"description":"Use when lighting, rendering or compositing in Blender: light a character, product or hero shot, in…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"93a3bea574312104922feba0884afa05332a2a7e12720995b9fabb948e0d297e","upstream_path":"skills/dcc/blender/scenario-blender-lighting-rendering/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"93a3bea574312104922feba0884afa05332a2a7e12720995b9fabb948e0d297e","size":20126,"exec":false},{"path":"references/critique.md","sha256":"04c4b949a62019d4cfe70cbe536dc96b2411fdd0c82980b750004e0f04ce38db","size":8035,"exec":false},{"path":"references/expert-notes.md","sha256":"fcf07efdf876fa500f96e25ce8477c56bd70c3fe13451ee85b26146c75d70f38","size":19917,"exec":false},{"path":"references/procedures.md","sha256":"774ce5f5c1577d3a74845b73bd716348cb587d0f0d7ea447a5dd64e706ff84a0","size":30203,"exec":false},{"path":"references/sources.md","sha256":"8beafcf59b2822a81ce09f255ef81cc333d12a464f0a58e6f6ac5e37c3679999","size":15667,"exec":false},{"path":"scripts/bx_light.py","sha256":"6f6624765f2afdfebc0efc4b77313fee3cacef9e7d983bcb3a95c88c8fa2f8f2","size":102909,"exec":false}]},"scenario-blender-retopology":{"description":"Use when turning a dense sculpt, scan or AI-generated mesh into clean topology in Blender, for anim…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"b6f31d60d7cd7d4cd055d0e7ba160eaa58b9d165739055eb3a1c1e381c08036e","upstream_path":"skills/dcc/blender/scenario-blender-retopology/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"b6f31d60d7cd7d4cd055d0e7ba160eaa58b9d165739055eb3a1c1e381c08036e","size":22026,"exec":false},{"path":"references/critique.md","sha256":"f23b9afc01bc0489d834978277323e1612f576983be98c388ba54e0c0e5ba7d7","size":15592,"exec":false},{"path":"references/expert-notes.md","sha256":"b1faff4c7fdce09eadbe438f4c8d52bceb05930729dd54ad5e6cae9f8406dd58","size":36275,"exec":false},{"path":"references/procedures.md","sha256":"d55d861c34134a6d1681d67577d3c81f4d5be904fdd3c87108e4a6b940790ae5","size":31490,"exec":false},{"path":"references/sources.md","sha256":"d25df1db2d06c8e378349bf188ba19d229ea7f912b46097854afce669d234017","size":17379,"exec":false},{"path":"scripts/bx_retopo.py","sha256":"871005569e63d4d947e5d5a6cd6344f6bee4113302ec5498270b028ad53922dd","size":128751,"exec":false}]},"scenario-blender-texturing-shading":{"description":"Use when texturing, shading or look-developing in Blender: building a PBR material from a texture s…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"df7f11cc812e5b2dd61bd5770de88017fdb67898951e2957bbdc78717f40c45c","upstream_path":"skills/dcc/blender/scenario-blender-texturing-shading/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"df7f11cc812e5b2dd61bd5770de88017fdb67898951e2957bbdc78717f40c45c","size":15695,"exec":false},{"path":"references/critique.md","sha256":"8365bb221a2ad681120beb2346ec6ee194a0affca441d98243f35e66540a8d50","size":5828,"exec":false},{"path":"references/expert-notes.md","sha256":"0472e6a6faa26770e603f97a25bd1c34007b9c0220c98967973d937d7a4dbb20","size":28024,"exec":false},{"path":"references/procedures.md","sha256":"703f71d73daab57183ee472b6069e3368b6f79ce72e0a273f8a67ed29a5a61f4","size":31419,"exec":false},{"path":"references/sources.md","sha256":"093bd302b898e3bc3fc438cf0ed0be59cbc6057108c03091ea828d25f31e8503","size":11474,"exec":false},{"path":"scripts/bx_materials.py","sha256":"15877d81bea8d2c95e1393b7c6ce8c96182fdb1a8d26dfa6bfbaf2d88886e72b","size":87244,"exec":false}]},"scenario-blender-uv-baking":{"description":"Use when UV unwrapping, placing seams, straightening or packing UVs, setting texel density, laying …","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"4dba740b856bb7cda4b158c53f1972221d08059ef89bfaaca15a5ac985db9b90","upstream_path":"skills/dcc/blender/scenario-blender-uv-baking/SKILL.md","requires":["scenario-blender-expert"],"software":["Blender"],"hasScripts":true,"scriptCount":1,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"4dba740b856bb7cda4b158c53f1972221d08059ef89bfaaca15a5ac985db9b90","size":17085,"exec":false},{"path":"references/critique.md","sha256":"e9a0bde9c4b2b416cd3d73ceb4dee21f584175fdd7b855a3fa3e04ac434c7a7b","size":17474,"exec":false},{"path":"references/expert-notes.md","sha256":"04fba3c9f09eb7643a5d27329c6eed250da06bb55df9b2374e760a8e0689e52c","size":23242,"exec":false},{"path":"references/procedures.md","sha256":"c8c2f81b18fb66360c2a6ac71c918a2494318b775648e0af2d725d5636df4a94","size":17979,"exec":false},{"path":"references/sources.md","sha256":"fb8a8a3b4d69ab7119e7db3f2f60756bedbe275912e8acbd5e9339cbfef9bb95","size":12550,"exec":false},{"path":"scripts/bx_uvbake.py","sha256":"f07fd3b6c02fdeff9dfaa77e164f24843ece1113e23ba073e61b68002d5c0762","size":107567,"exec":false}]},"scenario-unity-expert":{"description":"Use when an agent drives Unity 6.3 (6000.3) on a Mac for any task: batch mode and -executeMethod jo…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"61a31dd57792d42514912d864f23aa4ac7511b2c288d78e491987f6747142357","upstream_path":"skills/game-engines/unity/scenario-unity-expert/SKILL.md","software":["Unity 6.3"],"hasScripts":true,"scriptCount":12,"execBridge":true,"execBridgeFiles":[{"path":"scripts/AgentKit/AgentBridge.cs","reason":"invokes a method named in a request + file inbox polled for requests"},{"path":"scripts/ut_live.py","reason":"calls exec()/eval() + file inbox polled for requests"}],"files":[{"path":"SKILL.md","sha256":"61a31dd57792d42514912d864f23aa4ac7511b2c288d78e491987f6747142357","size":20832,"exec":false},{"path":"references/gui-paths.md","sha256":"8571540332e3095ff1855b641ac847dc9a4bf14f64011883f77d1421c6c5f041","size":5161,"exec":false},{"path":"references/live-channels.md","sha256":"37c9bf7a84ee3f81cb003977de6ae7b819bddbc341babf842558ac4a33f10d81","size":10861,"exec":false},{"path":"references/procedures.md","sha256":"d0e79adbed05d073ca9d25f088155f677735210ebe99f27d10670007afed42ad","size":7975,"exec":false},{"path":"references/routing-handoffs.md","sha256":"99fc636babe797bd83f580d11d58cfd7db551528eb946251d09cd97067eb12b8","size":19866,"exec":false},{"path":"references/sources.md","sha256":"49d0bf4a5d0470f6c2d5d5f436cab43789b1f17e0b7b361bed277c397bc218cd","size":28778,"exec":false},{"path":"references/toolkit-map.md","sha256":"db1f8b6d2e1dd685d44398266c8f956d36b862cef867bb8b8cf7e3895a5ab7e3","size":38967,"exec":false},{"path":"references/unity-6.3-traps.md","sha256":"f2c308fdfde091b022077958cd93dac186441cb8fd5dc2ae049697533b4191f3","size":51439,"exec":false},{"path":"references/writing-jobs.md","sha256":"a0f58f7ba6ef31c460c437484305f88b57ee6621a5f5851ecfbc636cc54d8a7e","size":9767,"exec":false},{"path":"scripts/AgentKit/AgentAudit.cs","sha256":"ef3462273115de3e5dfe0728a1eb884a01bfca1368846f563ba3e82acc25c1a4","size":26345,"exec":false},{"path":"scripts/AgentKit/AgentBridge.cs","sha256":"1cd83d4ed4b03d4e4440eab88ca4ca777e6057478d93db2b98fb35f3cd5a0b10","size":12418,"exec":false},{"path":"scripts/AgentKit/AgentBuild.cs","sha256":"9d97386d404e30ba3b286e202e95645b39bcc7b449b791298ce181e9ec7dfa66","size":12631,"exec":false},{"path":"scripts/AgentKit/AgentCapture.cs","sha256":"ebbf7f867607a9f563760161fba53ab0336e91858bc741fb01ffdb183861390a","size":22677,"exec":false},{"path":"scripts/AgentKit/AgentJob.cs","sha256":"a7e56ca70de1a3714509f128d112ea2afaf7817ddfea5c8fd65e9cfd25498328","size":16347,"exec":false},{"path":"scripts/AgentKit/AgentJson.cs","sha256":"9ef0f999966536846a358d647126d863d38140dd5dcf1f2ab51719dc0f4ea6c0","size":12599,"exec":false},{"path":"scripts/AgentKit/AgentProfile.cs","sha256":"61047d48198e42ebd9b9d43d1fa51feab16475232b3ca02837d86850997d3d43","size":13210,"exec":false},{"path":"scripts/ut_env.py","sha256":"0945a5e3d32f0610f73a50a5c186b18cb63301df736ac25be0c8da27f83bc1ec","size":16048,"exec":false},{"path":"scripts/ut_live.py","sha256":"ad4b62c2f4f2551e5edd84a6ac70cb96b5a0956629d1c29034b20b2d92a177c7","size":21945,"exec":false},{"path":"scripts/ut_review.py","sha256":"b698fda1327c7073e1f82593f3f4050278ebd072631342f3a0bc709e0845bb44","size":24732,"exec":false},{"path":"scripts/ut_run.py","sha256":"64e0c0050faaf784c78e5bb3f575b1177d2d55ecc8c30e6dd2f14ae02b92a279","size":26972,"exec":false},{"path":"scripts/ut_stat.py","sha256":"367879ffa58641f67e7e44f190f01bac4b2864128f3ab567df028ac38f18ec9e","size":11680,"exec":false}]},"scenario-unity-performance":{"description":"Use when a Unity 6.3 game is slow or stutters: low fps, frame spikes, hitches when entering areas o…","category":"engineering-method","tier":"free","origin":"scenario","requires_auth":false,"sha256":"c12a5c903f396a72a15e56226d8a0dab553fef6caa13d9c801c54e8125c22333","upstream_path":"skills/game-engines/unity/scenario-unity-performance/SKILL.md","requires":["scenario-unity-expert"],"software":["Unity 6.3"],"hasScripts":true,"scriptCount":11,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"c12a5c903f396a72a15e56226d8a0dab553fef6caa13d9c801c54e8125c22333","size":19744,"exec":false},{"path":"references/critique.md","sha256":"2731a46adbeec0f9c3b4a77c4b9c3f48ea8b942a1c1541f83f6f0fe620b5aa2d","size":8642,"exec":false},{"path":"references/expert-notes.md","sha256":"9980ee29a301309ab626a67fedefe84948ca03bebb033326f9623b7db8918169","size":25410,"exec":false},{"path":"references/gui-paths.md","sha256":"da2d3546fec852aafec6cb353d021c14ed24ea0bd8a21a3545f0f9563caa84da","size":24245,"exec":false},{"path":"references/procedures.md","sha256":"d28316c0c66d52e921c8e0b6a9c2cd5c9e892763be5b35e10a13999c2a6f258e","size":44495,"exec":false},{"path":"references/sources.md","sha256":"ce76807bc6ca64274be03f998726197261f1946604918a7e3b3be08a9c3f3c4c","size":24539,"exec":false},{"path":"scripts/AgentKit/Performance/PerfAudit.cs","sha256":"1f04553de72dbcfcee20ae496d5e80f256b4376dc7a849558c4586b6101e165b","size":17453,"exec":false},{"path":"scripts/AgentKit/Performance/PerfBuild.cs","sha256":"a89fa1b4532123a5816f97394ecd35ce12a5e45072764dc1abebdcf267f50d0e","size":11692,"exec":false},{"path":"scripts/AgentKit/Performance/PerfCapture.cs","sha256":"0a1788e09d50c2fe1d97fe749bf884b0e887f5ecc7514b86823e1c508d51c743","size":12297,"exec":false},{"path":"scripts/AgentKit/Performance/PerfFrameDebug.cs","sha256":"19e69f94b6aced6358a15edd8c8d78ec992677b25372b55b4fa09383469fd879","size":16446,"exec":false},{"path":"scripts/AgentKit/Performance/PerfLod.cs","sha256":"cc9bf20740a9d5bbaaa7410c75a0003660f0d556737012a067bb02e8dcf4bd70","size":5062,"exec":false},{"path":"scripts/AgentKit/Performance/PerfRendering.cs","sha256":"af7ba69beeb6d74d17de949a81e13ab2112d6d45a47156c3653f4ecae15c1b1b","size":33683,"exec":false},{"path":"scripts/AgentKit/Performance/PerfShaders.cs","sha256":"6aa5cae1262e930c9a4fa07e18555f9b95dcce3391c8da33f82ae266f5cef9cd","size":13473,"exec":false},{"path":"scripts/Runtime/Performance/AgentKit.Performance.Runtime.asmdef","sha256":"eb71145c132486c46bfecc868a63b51c196a4437043c422d61e01de40e30d184","size":382,"exec":false},{"path":"scripts/Runtime/Performance/AllocScope.cs","sha256":"f469ee9f659dbda3d387817854999d141b1fd56889b8a3209f0f4fc63159da8e","size":2206,"exec":false},{"path":"scripts/Runtime/Performance/PerfProbe.cs","sha256":"2a42c3dc9a416d8655bb9f43335ff81535133d25ae04f206ad3ff24a4680c80f","size":28166,"exec":false},{"path":"scripts/ut_perf.py","sha256":"46cb7a5b9922546a6510eef9de4779017989681b1715f3fa3328d1502dd53fb7","size":44913,"exec":false}]},"scenario-unity-pipeline-automation":{"description":"Use when automating a Unity 6.3 content pipeline or build: importing an art drop (FBX, PNG) with As…","category":"engineering-method","tier":"free","origin":"scenario","requires_auth":false,"sha256":"438d60621e5c93a35d0f6085af22e9c1377ed154b24486c134d79cc9d584948c","upstream_path":"skills/game-engines/unity/scenario-unity-pipeline-automation/SKILL.md","requires":["scenario-unity-expert"],"software":["Unity 6.3"],"hasScripts":true,"scriptCount":16,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"438d60621e5c93a35d0f6085af22e9c1377ed154b24486c134d79cc9d584948c","size":19929,"exec":false},{"path":"references/critique.md","sha256":"4f35497615c24efa9c9265557f5794c5c343a20c99fd64e903c588bfa581e684","size":17680,"exec":false},{"path":"references/expert-notes.md","sha256":"134238c2280662d3e71153ea12c6e127713677f9a3b06441ce79250044168bbd","size":24228,"exec":false},{"path":"references/gui-paths.md","sha256":"441f6f46698e99cef420db6de67cf2cbf040d62e149528ad29174392b66c5038","size":15507,"exec":false},{"path":"references/procedures.md","sha256":"04c16e0d2b28fb1b619537f3f491a403d38c6304ea4b7b8befe7ab38575f2431","size":50486,"exec":false},{"path":"references/sources.md","sha256":"9db649871d50cec70bc7909ab0a4fd68bf902745cb128173c3994aa8b8c5a988","size":17352,"exec":false},{"path":"scripts/AgentKit/Pipeline/AddressablesJobs.cs","sha256":"862a2fc4c651be751cbfbf46a0e51b14eff7b7530f8691c72a8f0aedc2cf80dd","size":24414,"exec":false},{"path":"scripts/AgentKit/Pipeline/ArtDropJobs.cs","sha256":"38f5d8d349aa8362b453ae08e179dbaf6778fa2692ddf505601bea56fcd88f2b","size":37459,"exec":false},{"path":"scripts/AgentKit/Pipeline/EditorEditJobs.cs","sha256":"505a5816a64a92fb00536db5bfec238085fb1a95df0c960667260386c9627269","size":16776,"exec":false},{"path":"scripts/AgentKit/Pipeline/PipelineBuild.cs","sha256":"6774278798c91440489cce698138013cb1bf1a821e8b80a02c408656c1702729","size":17557,"exec":false},{"path":"scripts/AgentKit/Pipeline/PipelineChecks.cs","sha256":"558cb4716bd61abb73f6a8ef1ca0ebdb9f15df10be9c669b3f4102d7b1e76f05","size":13428,"exec":false},{"path":"scripts/AgentKit/Pipeline/PipelineRules.cs","sha256":"bec6dd9704f7668e9fed9cec3cc975bdfaebacbec4298b7c8a38056c36a263f4","size":7302,"exec":false},{"path":"scripts/AgentKit/Pipeline/PropImportPostprocessor.cs","sha256":"3cd1dee4c68e92e68e41757b932fa4c4e77f38f316f8d72fb9acfb275e06262e","size":6656,"exec":false},{"path":"scripts/AgentKit/Pipeline/Tests/PipelineContentTests.cs","sha256":"570276dda02f9ea24e887b5e6019ef9634cde5319974bfb2ce9a26e451be7227","size":7083,"exec":false},{"path":"scripts/AgentKit/PipelineCli/AgentKit.PipelineCli.asmdef","sha256":"73e86ed42f8560e39944febced4bc45c4b6087dc452495fe94d017724e7069e2","size":612,"exec":false},{"path":"scripts/AgentKit/PipelineCli/PipelineCliCommands.cs","sha256":"a0143e932002e3f6b54ef9b4bc334415c39823ae794751fc7db2d7dd622203f4","size":4296,"exec":false},{"path":"scripts/Runtime/AgentAddressablesSmoke.cs","sha256":"9dd0d8cb0b95ec65bed284d026eb1abc71ea2e2d62bdaa029f96b6198013ed6d","size":4174,"exec":false},{"path":"scripts/templates/PipelineAsmdef/Editor/Game.Pipeline.Editor.asmdef","sha256":"cf802502971da70b9a6b9c6f18d0d32728d3f5ff9c6c2b948ccdf38ddb918ed3","size":389,"exec":false},{"path":"scripts/templates/PipelineAsmdef/Editor/TextureRuleAudit.cs","sha256":"7c4256ca74aa2be2a1e453c40653807b895b00b7eade2ae601897e3fb596c75b","size":2327,"exec":false},{"path":"scripts/templates/PipelineAsmdef/Tests/Game.Pipeline.Tests.asmdef","sha256":"5289a53406fef4ee53d882bbaa825cc52a063514c1eb8b3e759ef2dc637eab03","size":568,"exec":false},{"path":"scripts/templates/PipelineAsmdef/Tests/TextureRuleTests.cs","sha256":"9ab47e781c293bd22a74ac44ca95b55164b6a1b4f20eb9e446237a15aa8a0e0a","size":1280,"exec":false},{"path":"scripts/ut_pipeline.py","sha256":"8b93ba575f6859d7dc05ba0c664eb8a210ccee22eec123835a59b853d6e5a05d","size":56155,"exec":false}]},"scenario-unity-shaders":{"description":"Use when a Unity 6.3 URP task involves shaders: hand-written HLSL, Shader Graph water, toon, dissol…","category":"media-eventtech","tier":"free","origin":"scenario","requires_auth":false,"sha256":"bf0cf46c1e6bb2d0ffe3852fc363a2ad3d1ded020cf4b7b41ffd7cae7e653de3","upstream_path":"skills/game-engines/unity/scenario-unity-shaders/SKILL.md","requires":["scenario-unity-expert"],"software":["Unity 6.3"],"hasScripts":true,"scriptCount":21,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"bf0cf46c1e6bb2d0ffe3852fc363a2ad3d1ded020cf4b7b41ffd7cae7e653de3","size":20513,"exec":false},{"path":"references/critique.md","sha256":"e8934e753805665a4bb8fbdea78db41268040eeb7695aba5ca790227137fd438","size":12242,"exec":false},{"path":"references/expert-notes.md","sha256":"23ba5da22cdd325b46c91df8b34c3b8a7b14fa28a0374ffb6beb888dea924856","size":25730,"exec":false},{"path":"references/gui-paths.md","sha256":"e00f3a24db197575541a9ae5287c5ac4350487fc517460d19e9c1316cd4ad315","size":18163,"exec":false},{"path":"references/procedures.md","sha256":"e4d6c4b92c3841d0a270533cec5c525bf258ddae8ac0fe8997e356da3630b1fa","size":44695,"exec":false},{"path":"references/sources.md","sha256":"6f498801b0b43200f1d6357f9077001c9fb78267ae0317086a903d27bc6d41f0","size":22805,"exec":false},{"path":"scripts/AgentKit/Shaders/ComputeJobs.cs","sha256":"e22096eb5b25adea4e7b685b4a671189c0a77ed7ecde3b0aa181a05269b2e333","size":6984,"exec":false},{"path":"scripts/AgentKit/Shaders/GpuCostJobs.cs","sha256":"48a53c13e2cabde1c7a13b66cde69baf67c2beeab15204a642cc72dc5edf5d41","size":9740,"exec":false},{"path":"scripts/AgentKit/Shaders/PsoJobs.cs","sha256":"e9e5a28f8f7df32005fbfb8943f328de127c764f004d06ef6fcc575f617056ab","size":9830,"exec":false},{"path":"scripts/AgentKit/Shaders/RendererFeatureJobs.cs","sha256":"db119383b251fced87b28ecf2d832578a576eb0beb8a54b23f5cb371f8385a3c","size":10833,"exec":false},{"path":"scripts/AgentKit/Shaders/ShaderGraphJobs.cs","sha256":"ce896c4f3d082f4f44221af6dfbd1ef0602f128e92a66af0bd626c0aa72808f3","size":9291,"exec":false},{"path":"scripts/AgentKit/Shaders/ShaderJobs.cs","sha256":"844d0757ddbe40212840ff7169d9a2a6a98d3e9ebcfbaad92acea85bf5b4ce98","size":27032,"exec":false},{"path":"scripts/AgentKit/Shaders/ShaderLab.cs","sha256":"87dccaefc8a312f3d0debdcacdcca2510fb415a4c70af987255bf67b6c67fb10","size":25080,"exec":false},{"path":"scripts/AgentKit/Shaders/VariantJobs.cs","sha256":"1b83dfa175aeeb8a12647d5a52221b3222f5b87a7d4fdcab1163bfc0e7b68ad4","size":24544,"exec":false},{"path":"scripts/Runtime/AgentFullscreenFeature.cs","sha256":"a838d52edd32af2fc3cb281d5ea89c957b453f9d7ad13d20213411e31c6f1e87","size":6243,"exec":false},{"path":"scripts/Runtime/AgentPsoProbe.cs","sha256":"d6da1632573854e9327e3a5b2b7d757a514f14e85ed5f7817038df1f73049f36","size":12803,"exec":false},{"path":"scripts/Shaders/AgentCompute.compute","sha256":"e63376793bdbfbd062e828e5c7e9e62b31fc2e3be62697df356a09466b548c80","size":1874,"exec":false},{"path":"scripts/Shaders/AgentCustomLighting.hlsl","sha256":"14092128d768901fadefc3e39d6c077a68c0438faae09a368ddee4fd77dfeb19","size":6105,"exec":false},{"path":"scripts/Shaders/AgentDissolve.shader","sha256":"c26c41c19b486df876c35670c95d7dc8a5417124b0df0b5ded34ab3373455e84","size":9467,"exec":false},{"path":"scripts/Shaders/AgentEdgeOutline.shader","sha256":"eb06e6c478344ed4a75acd2dbaee0f24e821fe6ad52241ad40b9958d4604d08e","size":4025,"exec":false},{"path":"scripts/Shaders/AgentGrayscale.shader","sha256":"3f986574b9af4b8013e0c7d361e410b8da00f327715e9dccbfc00c63fc28404b","size":1493,"exec":false},{"path":"scripts/Shaders/AgentLit.shader","sha256":"519555c889f33d8b53843aa0d3ab1396566d1428275f5f8464c2be45827dfe34","size":9152,"exec":false},{"path":"scripts/Shaders/AgentNoise.hlsl","sha256":"9d70aac4e3aacbf828fc6aaabd64bfa351446e87572ff3e5d618cfe038e4ce43","size":3208,"exec":false},{"path":"scripts/Shaders/AgentPasses.hlsl","sha256":"80b0ce1f1da27983f514228ad6639b5f52591e4bee9083491b2aa1bb551d37d8","size":5452,"exec":false},{"path":"scripts/Shaders/AgentToon.shader","sha256":"8f49cc1da741f457b6da3e0ac9ec564b4d89149d90cee0bff4df3007c05baa15","size":9828,"exec":false},{"path":"scripts/Shaders/AgentWater.shader","sha256":"b865a7bb72a28d1767d88b00e1c85e63676df0778c478b09d3d2e27a348e608a","size":9437,"exec":false},{"path":"scripts/ut_shaders.py","sha256":"71fcd7c4311b784d0fbc70f0d3f4a62f853455715f9dbe0d7952c7d4ec17f2cd","size":56132,"exec":false}]},"scenario-unity-ui":{"description":"Use when building or fixing game UI in Unity 6.3: main menu, settings screen (resolution, quality, …","category":"design-ui-ux","tier":"free","origin":"scenario","requires_auth":false,"sha256":"9cf61b9ca815b3ed1886d5bcec98ebfc22571f948803c5fc06bf9f584333f755","upstream_path":"skills/game-engines/unity/scenario-unity-ui/SKILL.md","requires":["scenario-unity-expert"],"software":["Unity 6.3"],"hasScripts":true,"scriptCount":32,"execBridge":false,"execBridgeFiles":[],"files":[{"path":"SKILL.md","sha256":"9cf61b9ca815b3ed1886d5bcec98ebfc22571f948803c5fc06bf9f584333f755","size":17307,"exec":false},{"path":"references/critique.md","sha256":"1467315c43abf62aad6d2174df54d93e9c4bdb232bf1834296c8f3c3766bb78a","size":8630,"exec":false},{"path":"references/expert-notes.md","sha256":"e0c128bf8645ee5fe221664cd5c781dabfb14ea6248f43d77d0733d378e7af8b","size":23781,"exec":false},{"path":"references/gui-paths.md","sha256":"66807ad5265940a31547daf5a8537cbc62141501065decd7b465e6dd4dbc1026","size":5200,"exec":false},{"path":"references/procedures.md","sha256":"29d4faa6e8f2ad331d9ce4aef85303e8b8d94f56f36df0d8274a2a4fdc0b438e","size":42170,"exec":false},{"path":"references/sources.md","sha256":"1c776696c9d54cf2b4b377ed8e61d2e92f9da8d4bc4a265ac4759ef71c7a28cb","size":16748,"exec":false},{"path":"scripts/AgentKit/UI/UIAudit.cs","sha256":"50714d1cacced7ed3b9744cfee771589ebc693727b275b8d55a0c98ed3795d45","size":39487,"exec":false},{"path":"scripts/AgentKit/UI/UIBuild.cs","sha256":"ac023db602fd898f174a5d2192aba29a629f825c0d5d48f9fbaeb1b2e21ab335","size":29856,"exec":false},{"path":"scripts/AgentKit/UI/UICapture.cs","sha256":"0c1ce99993d28f71c90f68897b7c6ca3ba8fadc85d20b399c48db2c7f2dfb964","size":33102,"exec":false},{"path":"scripts/AgentKit/UI/UIPerf.cs","sha256":"8985971fd81578a6fd3f9919de02108da269965dd6cd96065cbdff64a84368d4","size":26392,"exec":false},{"path":"scripts/AgentKit/UI/UISetup.cs","sha256":"07f23ef2a7e16eb5a1ab1833ed2972c7cdbc69e120309ae637f925e1f87cb2dc","size":5897,"exec":false},{"path":"scripts/AgentKit/UI/UIToolkitBuild.cs","sha256":"75049ce3ec93d2657d98046708afc5bf630fe2ac07f712ca6b584f5f1206d07d","size":20382,"exec":false},{"path":"scripts/Runtime/UI/AgentUI.Runtime.asmdef","sha256":"3c9fb95fe5977b71ae42137d01ba7d24cbfe674b2a0d5c5641b1da5038ccf4e3","size":444,"exec":false},{"path":"scripts/Runtime/UI/CanvasDeviceScale.cs","sha256":"43958d24558a260e2aff19a68a4d6dae2a4ee477dbda7ba050b8a1213fb0fa73","size":2069,"exec":false},{"path":"scripts/Runtime/UI/ClampedWidth.cs","sha256":"54f78309df4637a53c76250542a93189cdf0f9bfa06a15e24449a8857fe740ae","size":1994,"exec":false},{"path":"scripts/Runtime/UI/HudBar.cs","sha256":"14488466f574030b05a3eb35eeaedf9ae66b52d3d77878cbf877e802b5322abf","size":2906,"exec":false},{"path":"scripts/Runtime/UI/HudModel.cs","sha256":"4f44c529b07811e3486ec24816ed24203db203eb75442f76a5cc84cdc79f807b","size":3623,"exec":false},{"path":"scripts/Runtime/UI/HudView.cs","sha256":"712e93b3b1f6490007c4672dd31eb0bb44843af7e53bec9b8af55fac3ae9bbae","size":1481,"exec":false},{"path":"scripts/Runtime/UI/MenuRouter.cs","sha256":"3da348c7952fbf9c9e6f078a1eff44571b7e6dfe19697930b979ecd00ff3fdaa","size":4163,"exec":false},{"path":"scripts/Runtime/UI/MenuScreen.cs","sha256":"7b26db2aa577b13f19fd9a69c4d7112756e14c83d097258d65d84a56f3b6324d","size":4843,"exec":false},{"path":"scripts/Runtime/UI/PanelChangeLog.cs","sha256":"18ff907c0d203f42a47910a288337196d547176934600274fafbc49e123010fd","size":3676,"exec":false},{"path":"scripts/Runtime/UI/RebindRow.cs","sha256":"5650a5dcf31f703125916cf1af73b893ef9533286f91a0cd7e896c458b27ce5a","size":3454,"exec":false},{"path":"scripts/Runtime/UI/RebuildProbe.cs","sha256":"52c42816a5cf95d0b0cdb195ebc003db1dc8a75397e9a77b862bf51c4718283f","size":1212,"exec":false},{"path":"scripts/Runtime/UI/ScrollToSelection.cs","sha256":"d9401696c2b0cc5ee1659fef865801f358e0e226715b42a83ae25a9ad7944fbc","size":2264,"exec":false},{"path":"scripts/Runtime/UI/SelectableFeedback.cs","sha256":"ecf8bbab358a0a867208fb92e1e4a790c4cb993b992192d151f52f1ef0d80bad","size":3642,"exec":false},{"path":"scripts/Runtime/UI/SettingsScreen.cs","sha256":"7b386b9e7de1d4425fd4fdaaf9703d1a1499fbb1023baaee05456b23a7fa62e1","size":6628,"exec":false},{"path":"scripts/Runtime/UI/SettingsService.cs","sha256":"d19662fc7ed48b89b22af678db1c64c2ea3558331a5a3d44aad5fb550c7ef246","size":4291,"exec":false},{"path":"scripts/Runtime/UI/UILoader.cs","sha256":"ae3b8087cbe41f65d9c6aab54a2fbb41caa24fd7f8f4b504996945e6e8065f76","size":2504,"exec":false},{"path":"scripts/Runtime/UI/UiCounterSampler.cs","sha256":"34cebfc40d47925f8d378322b978bb84d54a61fc555699bafd77c1fbe649e824","size":4149,"exec":false},{"path":"scripts/Runtime/UI/UiPerfDriver.cs","sha256":"6ce266e1ca0f9e33fcbd4a45fadd0a29f996fe00ceca23cc4ef16591fe7d8288","size":927,"exec":false},{"path":"scripts/Runtime/UI/UiTheme.cs","sha256":"27a513e460d683f6c51f8cd16445aa53d4f7d3b11221d069d0717a13e98f265e","size":2572,"exec":false},{"path":"scripts/Runtime/UI/UitkHideDriver.cs","sha256":"ffe011cbf1b2d148a14b6ebe829269750de922594e52529fc63eae648829ff3b","size":6414,"exec":false},{"path":"scripts/Runtime/UI/UitkTextureGrid.cs","sha256":"8ae73058d4a3e59138d58849e9d2803559079ce0ef4cfb5c95396e980111e2ec","size":3052,"exec":false},{"path":"scripts/Runtime/UI/UitkVertexGrid.cs","sha256":"d33f5fe3c25e51f0e02f858981113fc67c5c63f4ca87f6f490a4f0dc43e8c3bf","size":2121,"exec":false},{"path":"scripts/templates/uitk/AgentRuntimeTheme.tss","sha256":"682e2b1c6cc1d6e332c15f56c840f7d8282cb1e5bc627eb6664580352a752fda","size":38,"exec":false},{"path":"scripts/templates/uitk/Hud.uss","sha256":"774b424ea9f9624b07970ef7c40f70fdec7835290e0d8bebdabb325db8e8d5cb","size":2445,"exec":false},{"path":"scripts/templates/uitk/Hud.uxml","sha256":"d379afb21468f1c516c4c4fe349f96b6d8d46d0e03406e1ac717a460d69b36f3","size":2643,"exec":false},{"path":"scripts/ut_ui.py","sha256":"0b2aaa743a160d4c8c31cb4e16513f9e4503de6a3129fdd4eaa4b13338ec5c46","size":24204,"exec":false}]}},"subagents":{}}
|
package/lib/store-shared.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { chmodSync, existsSync, lstatSync, mkdirSync, readdirSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { chmodSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { basename, dirname, join, resolve, sep } from 'node:path';
|
|
5
5
|
|
|
@@ -66,10 +66,10 @@ function assertNoSymlink(path) {
|
|
|
66
66
|
catch (e) { if (e.code !== 'ENOENT') throw e; }
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
// Checks every destination
|
|
70
|
-
export function
|
|
69
|
+
// Checks every destination; throws on an unsafe path and touches nothing.
|
|
70
|
+
export function planSkillFiles(skillMd, files) {
|
|
71
71
|
const dir = resolve(dirname(skillMd));
|
|
72
|
-
|
|
72
|
+
return files.map((f) => {
|
|
73
73
|
safeRel(f.path);
|
|
74
74
|
const dest = resolve(dir, ...f.path.split('/'));
|
|
75
75
|
if (!dest.startsWith(dir + sep)) throw new Error(`Path escapes skill dir: ${f.path}`);
|
|
@@ -77,6 +77,9 @@ export function writeSkillFiles(skillMd, files) {
|
|
|
77
77
|
assertNoSymlink(dir);
|
|
78
78
|
return { ...f, dest };
|
|
79
79
|
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function writePlan(plan) {
|
|
80
83
|
for (const f of plan) {
|
|
81
84
|
mkdirSync(dirname(f.dest), { recursive: true });
|
|
82
85
|
writeFileSync(f.dest, f.data);
|
|
@@ -85,6 +88,80 @@ export function writeSkillFiles(skillMd, files) {
|
|
|
85
88
|
return plan.map((f) => f.dest);
|
|
86
89
|
}
|
|
87
90
|
|
|
91
|
+
export const writeSkillFiles = (skillMd, files) => writePlan(planSkillFiles(skillMd, files));
|
|
92
|
+
|
|
93
|
+
const RAW_BASE_RE = /^https:\/\/raw\.githubusercontent\.com\/[\w.-]+\/[\w.-]+$/;
|
|
94
|
+
const ECC_SOURCE = {
|
|
95
|
+
id: 'ecc', label: 'ECC', raw_base: 'https://raw.githubusercontent.com/affaan-m/ECC',
|
|
96
|
+
license: 'MIT', copyright: 'Copyright (c) 2026 Affaan Mustafa', third_party: true,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Test overrides: AOS_STORE_INDEX / AOS_STORE_RAW_BASE (ECC), AOS_STORE_INDEX_SCENARIO / AOS_STORE_RAW_BASE_SCENARIO (Scenario).
|
|
100
|
+
export function loadSources(root, env = process.env) {
|
|
101
|
+
const specs = [
|
|
102
|
+
{ file: env.AOS_STORE_INDEX || join(root, 'lib', 'ecc-store-index.json'), base: env.AOS_STORE_RAW_BASE, fallback: ECC_SOURCE },
|
|
103
|
+
{ file: env.AOS_STORE_INDEX_SCENARIO || join(root, 'lib', 'scenario-store-index.json'), base: env.AOS_STORE_RAW_BASE_SCENARIO },
|
|
104
|
+
];
|
|
105
|
+
return specs.map(({ file, base, fallback }) => {
|
|
106
|
+
const index = JSON.parse(readFileSync(file, 'utf8'));
|
|
107
|
+
if (!index.pinned_commit || !index.skills || !index.subagents) throw new Error(`Invalid AOS store index: ${file}`);
|
|
108
|
+
const meta = { ...fallback, ...index.source };
|
|
109
|
+
if (!meta.id || !meta.label) throw new Error(`Store index has no source descriptor: ${file}`);
|
|
110
|
+
if (!base && !RAW_BASE_RE.test(meta.raw_base || '')) throw new Error(`Untrusted raw_base in ${file}: ${meta.raw_base}`);
|
|
111
|
+
return { ...meta, raw_base: (base || meta.raw_base).replace(/\/+$/, ''), pinned_commit: index.pinned_commit, index };
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function findItems(sources, name) {
|
|
116
|
+
const found = [];
|
|
117
|
+
for (const src of sources) {
|
|
118
|
+
for (const type of ['skills', 'subagents']) {
|
|
119
|
+
if (src.index[type]?.[name]) found.push({ name, item: src.index[type][name], type, src });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return found;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function findItem(sources, name) {
|
|
126
|
+
const found = findItems(sources, name);
|
|
127
|
+
if (found.length > 1) {
|
|
128
|
+
throw new Error(`Name collision: '${name}' exists in ${found.map((f) => f.src.label).join(' and ')}; refusing to pick one or overwrite`);
|
|
129
|
+
}
|
|
130
|
+
return found[0] || null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// The item plus the skills it requires (same source), dependencies first.
|
|
134
|
+
export function installPlan(sources, found) {
|
|
135
|
+
const plan = [];
|
|
136
|
+
const visit = (entry, chain) => {
|
|
137
|
+
if (chain.includes(entry.name)) throw new Error(`Circular requires: ${[...chain, entry.name].join(' -> ')}`);
|
|
138
|
+
for (const dep of entry.item.requires || []) {
|
|
139
|
+
const hit = findItem(sources, dep);
|
|
140
|
+
if (!hit || hit.src !== entry.src || hit.type !== 'skills') throw new Error(`${entry.name} requires '${dep}', which is not available in ${entry.src.label}`);
|
|
141
|
+
visit(hit, [...chain, entry.name]);
|
|
142
|
+
}
|
|
143
|
+
if (!plan.some((p) => p.name === entry.name)) plan.push(entry);
|
|
144
|
+
};
|
|
145
|
+
visit(found, []);
|
|
146
|
+
return plan;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function planSummary(plan) {
|
|
150
|
+
const all = plan.flatMap((p) => (p.item.files || []).map((f) => ({ ...f, skill: p.name })));
|
|
151
|
+
const bridge = plan.flatMap((p) => (p.item.execBridgeFiles || []).map((f) => ({ skill: p.name, ...f })));
|
|
152
|
+
return {
|
|
153
|
+
skills: plan.map((p) => p.name),
|
|
154
|
+
requires: plan.slice(0, -1).map((p) => p.name),
|
|
155
|
+
fileCount: all.length || plan.length,
|
|
156
|
+
totalSize: all.reduce((n, f) => n + f.size, 0),
|
|
157
|
+
scriptCount: plan.reduce((n, p) => n + (p.item.scriptCount || 0), 0),
|
|
158
|
+
hasScripts: plan.some((p) => p.item.hasScripts),
|
|
159
|
+
execBridge: plan.some((p) => p.item.execBridge),
|
|
160
|
+
execBridgeFiles: bridge,
|
|
161
|
+
software: [...new Set(plan.flatMap((p) => p.item.software || []))],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
88
165
|
export function localSkills(root) {
|
|
89
166
|
const found = new Map();
|
|
90
167
|
const visit = (dir) => {
|
package/lib/store-ui/index.html
CHANGED
|
@@ -56,6 +56,8 @@ dialog h2{font-family:var(--serif);font-weight:500;margin:0 0 .6rem}
|
|
|
56
56
|
dialog pre{margin:.6rem 0;padding:.7rem;border-radius:.6rem;background:var(--ink);color:var(--white);font-size:.7rem;overflow-x:auto;white-space:pre-wrap;word-break:break-all}
|
|
57
57
|
dialog .acts{display:flex;gap:.5rem;justify-content:flex-end;margin-top:1rem}
|
|
58
58
|
.err{color:oklch(0.5 0.2 25);font-size:.75rem}
|
|
59
|
+
.badge.warn{border-color:oklch(0.5 0.2 25);color:oklch(0.5 0.2 25)}
|
|
60
|
+
.warnbox{padding:.6rem .8rem;border:2px solid oklch(0.5 0.2 25);border-radius:.6rem;color:oklch(0.5 0.2 25);font-size:.78rem;font-weight:700}
|
|
59
61
|
</style></head><body>
|
|
60
62
|
<div class="container"><main id="app"></main></div>
|
|
61
63
|
<dialog id="dlg"></dialog>
|
|
@@ -70,7 +72,7 @@ const visible=()=>{const q=S.q.toLowerCase();return base().filter(i=>(S.sub==='i
|
|
|
70
72
|
const uniq=f=>[...new Set(S.data.items.map(f))].sort();
|
|
71
73
|
const count=(f,v)=>base().filter(i=>f(i)===v).length;
|
|
72
74
|
const chip=(a,v,label,n)=>`<button class="chip" aria-pressed="${S[a]===v}" data-a="${a}" data-v="${esc(v)}">${esc(label)}<b>${n}</b></button>`;
|
|
73
|
-
function strip(){const all=S.data.items;
|
|
75
|
+
function strip(){const all=S.data.items;return `<div class="strip"><div><strong>${all.length}</strong><small>total</small></div>${uniq(i=>i.source).map(s=>`<div><strong>${all.filter(i=>i.source===s).length}</strong><small>${esc(s)}</small></div>`).join('')}</div>`}
|
|
74
76
|
function tabs(){const n=base(),ic=n.filter(i=>i.installed).length,k=x=>S.data.items.filter(i=>i.kind===x).length;return `<div class="tabs">${chip('tab','skill','Skills',k('skill'))}${chip('tab','agent','Agents',k('agent'))}<span style="width:1rem"></span>${chip('sub','installed','Installed',ic)}${chip('sub','discover','Discover',n.length-ic)}</div>`}
|
|
75
77
|
const scopeToggle=()=>`<div class="scope"><span class="kicker" style="margin:0">Scope</span>${chip('scope','global','Global','')}${chip('scope','project','Project','')}</div>`;
|
|
76
78
|
function act(i){
|
|
@@ -81,7 +83,7 @@ function act(i){
|
|
|
81
83
|
}
|
|
82
84
|
function row(i){
|
|
83
85
|
const k=key(i),open=S.expanded.has(k);
|
|
84
|
-
const badge=i.fileCount>1?`<span class="badge">${i.fileCount} files</span>`:'';
|
|
86
|
+
const badge=(i.fileCount>1?`<span class="badge">${i.fileCount} files</span>`:'')+(i.execBridge?'<span class="badge warn">exec bridge</span>':'')+(i.requires.length?`<span class="badge">+${i.requires.length} required</span>`:'');
|
|
85
87
|
let h=`<div class="rowwrap"><div class="row"><span class="dot ${i.installed?'g':''}"></span><span class="n" data-a="exp" data-v="${esc(k)}" style="cursor:pointer" title="Show description">${esc(i.name)}${badge}</span><span class="d" style="color:var(--muted)">${esc(i.description)}</span><span class="c cat">${esc(i.category)}</span><span class="s src">${esc(i.source)}</span><span style="text-align:right">${act(i)}</span></div>`;
|
|
86
88
|
if(open){const d=i.core?i.description:S.detail[k];h+=`<div class="detail">${d===undefined?'Loading...':esc(d)}</div>`}
|
|
87
89
|
return h+'</div>';
|
|
@@ -109,9 +111,16 @@ async function preview(k){
|
|
|
109
111
|
try{
|
|
110
112
|
const d=await post('/api/preview',i);
|
|
111
113
|
const ok=d.ok&&d.targets.length;
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
114
|
+
const m=d.meta||{};
|
|
115
|
+
const fc=m.fileCount||i.fileCount,tc=fc>0?Math.round(d.targets.length/fc):1;const size=m.totalSize>0?` = ${fc} file(s) \u00d7 ${tc} target(s), ${(m.totalSize/1024).toFixed(1)} KB each`:(i.totalSize!=null?` = ${i.fileCount} file(s) \u00d7 ${tc} target(s), ${(i.totalSize/1024).toFixed(1)} KB each`:'');
|
|
116
|
+
const warn=(i.hasHooks?'<p class="err">Includes hooks \u2014 copied only, NOT registered in your harness settings; the skill may need manual wiring.</p>':'')
|
|
117
|
+
+(m.execBridge?`<p class="warnbox">Warning: contains a script that executes code received over a local socket or file channel without authentication \u2014 install only if you use this bridge.<br><span style="font-weight:400">${esc((m.execBridgeFiles||[]).map(f=>f.skill+'/'+f.path).join(', '))}</span></p>`:(m.hasScripts?`<p class="cmdnote">Contains ${m.scriptCount} script file(s) that run on your machine when the skill is used. Review them before use.</p>`:''))
|
|
118
|
+
+(m.software&&m.software.length?`<p class="cmdnote">Needs third-party software that is not included: ${esc(m.software.join(', '))}.</p>`:'')
|
|
119
|
+
+(m.requires&&m.requires.length?`<p class="cmdnote">Also installs required skill(s): ${esc(m.requires.join(', '))}.</p>`:'');
|
|
120
|
+
const srcLabel=m.source||i.source,pin=(m.pinned_commit||S.data.pinned_commit).slice(0,10);
|
|
121
|
+
const lic=m.license?` \u2014 ${esc(m.license)}${m.copyright?', '+esc(m.copyright):''}`:'';
|
|
122
|
+
const nfiles=m.fileCount||i.fileCount;
|
|
123
|
+
dlg.innerHTML=`<h2>Add ${esc(i.name)}</h2><p class="kicker">${scopeName()} scope \u2014 will write ${d.targets.length} file(s)${size}</p><p class="cmdnote">Source: ${esc(srcLabel)}${lic}${m.thirdParty?' (third-party content)':''}</p>${warn}<pre style="max-height:16rem;overflow:auto">${esc(ok?d.targets.join('\n'):(d.stdout+d.stderr).trim())}</pre><p class="cmdnote">Downloads ${nfiles>1?nfiles+' files':'the file'} from ${esc(srcLabel)} at ${esc(pin)}, each verified by SHA-256.</p><div id="res"></div><div class="acts"><button class="button secondary" data-a="close">Cancel</button>${ok?`<button class="button" data-a="confirm" data-v="${esc(k)}">Install to ${scopeName()}</button>`:''}</div>`;
|
|
115
124
|
dlg.showModal();
|
|
116
125
|
}catch(e){alert('Preview failed: '+e.message)}
|
|
117
126
|
finally{S.busy=null;render()}
|