agenticros 0.1.19 → 0.2.1
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/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +114 -30
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +125 -2
- package/dist/commands/skills.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/menu.js +22 -4
- package/dist/menu.js.map +1 -1
- package/dist/util/env.d.ts +2 -0
- package/dist/util/env.d.ts.map +1 -1
- package/dist/util/env.js +2 -0
- package/dist/util/env.js.map +1 -1
- package/dist/util/marketplace.d.ts +57 -0
- package/dist/util/marketplace.d.ts.map +1 -0
- package/dist/util/marketplace.js +144 -0
- package/dist/util/marketplace.js.map +1 -0
- package/dist/util/skills.d.ts +6 -6
- package/dist/util/skills.d.ts.map +1 -1
- package/dist/util/skills.js +14 -9
- package/dist/util/skills.js.map +1 -1
- package/package.json +12 -11
- package/runtime/BUNDLE.json +1 -1
- package/runtime/README.md +59 -2
- package/runtime/packages/agenticros/openclaw.plugin.json +1 -1
- package/runtime/packages/agenticros/src/config-page.ts +1 -1
- package/runtime/packages/agenticros/src/skill-loader.ts +109 -38
- package/runtime/packages/agenticros-claude-code/README.md +52 -9
- package/runtime/packages/agenticros-claude-code/dist/__tests__/capabilities-mcp.test.d.ts +2 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/capabilities-mcp.test.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/capabilities-mcp.test.js +773 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/capabilities-mcp.test.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/follow-me-registry.test.d.ts +2 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/follow-me-registry.test.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/follow-me-registry.test.js +97 -0
- package/runtime/packages/agenticros-claude-code/dist/__tests__/follow-me-registry.test.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts +2 -2
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js +5 -5
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/follow-me/depth-loop.d.ts +109 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/depth-loop.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/depth-loop.js +392 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/depth-loop.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts +8 -3
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.d.ts.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js +30 -12
- package/runtime/packages/agenticros-claude-code/dist/follow-me/loop.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/index.js +5 -5
- package/runtime/packages/agenticros-claude-code/dist/index.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/mission-registry.d.ts +16 -0
- package/runtime/packages/agenticros-claude-code/dist/mission-registry.d.ts.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/mission-registry.js +19 -0
- package/runtime/packages/agenticros-claude-code/dist/mission-registry.js.map +1 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts +9 -0
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/tools.js +700 -54
- package/runtime/packages/agenticros-claude-code/dist/tools.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/transport.d.ts +28 -8
- package/runtime/packages/agenticros-claude-code/dist/transport.d.ts.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/transport.js +37 -34
- package/runtime/packages/agenticros-claude-code/dist/transport.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/src/__tests__/capabilities-mcp.test.ts +2 -1
- package/runtime/packages/core/LICENSE +192 -0
- package/runtime/packages/core/README.md +88 -0
- package/runtime/packages/core/package.json +36 -3
- package/runtime/packages/core/src/__tests__/capabilities.test.ts +49 -44
- package/runtime/packages/core/src/capabilities.ts +19 -45
- package/runtime/packages/core/src/config.ts +1 -1
- package/runtime/scripts/configure_agenticros.sh +0 -0
- package/runtime/scripts/configure_for_sim.sh +0 -0
- package/runtime/scripts/fix-openclaw-control-ui-path.sh +0 -0
- package/runtime/scripts/install_cli.sh +0 -0
- package/runtime/scripts/install_rosbridge_from_source.sh +0 -0
- package/runtime/scripts/onboard_robot.sh +0 -0
- package/runtime/scripts/pack-runtime.mjs +9 -3
- package/runtime/scripts/refresh-skill-deps.mjs +0 -0
- package/runtime/scripts/run_demo_native.sh +0 -0
- package/runtime/scripts/run_nemoclaw_host_stack.sh +0 -0
- package/runtime/scripts/run_robot_rosbridge.sh +0 -0
- package/runtime/scripts/setup_gateway_plugin.sh +0 -0
- package/runtime/scripts/setup_robot.sh +0 -0
- package/runtime/scripts/setup_workspace.sh +0 -0
- package/runtime/scripts/sim/run_sim.sh +0 -0
- package/runtime/scripts/smoke_test_nemoclaw.sh +0 -0
- package/runtime/scripts/start_demo.sh +0 -0
- package/runtime/scripts/sync-skill-tools.mjs +2 -2
- package/runtime/scripts/use-openclaw-2026.2.26.sh +0 -0
- package/runtime/scripts/use-openclaw-2026.3.11.sh +0 -0
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agenticros/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "AgenticROS core — platform-agnostic ROS2 transport, types, and config",
|
|
5
|
+
"description": "AgenticROS core — platform-agnostic ROS2 transport, types, and config (the dep every AgenticROS skill imports).",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"agenticros",
|
|
8
|
+
"ros2",
|
|
9
|
+
"robotics",
|
|
10
|
+
"zenoh",
|
|
11
|
+
"rosbridge",
|
|
12
|
+
"webrtc",
|
|
13
|
+
"skill-sdk"
|
|
14
|
+
],
|
|
15
|
+
"homepage": "https://github.com/agenticros/agenticros#readme",
|
|
16
|
+
"bugs": "https://github.com/agenticros/agenticros/issues",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/agenticros/agenticros.git",
|
|
20
|
+
"directory": "packages/core"
|
|
21
|
+
},
|
|
6
22
|
"main": "./dist/index.js",
|
|
7
23
|
"types": "./dist/index.d.ts",
|
|
8
24
|
"exports": {
|
|
@@ -12,10 +28,27 @@
|
|
|
12
28
|
"default": "./dist/index.js"
|
|
13
29
|
}
|
|
14
30
|
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist/**/*.js",
|
|
33
|
+
"dist/**/*.d.ts",
|
|
34
|
+
"dist/**/*.js.map",
|
|
35
|
+
"dist/**/*.d.ts.map",
|
|
36
|
+
"!dist/**/__tests__/**",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=20"
|
|
45
|
+
},
|
|
15
46
|
"scripts": {
|
|
16
47
|
"build": "tsc",
|
|
17
48
|
"typecheck": "tsc --noEmit",
|
|
18
|
-
"test": "node --test \"dist/memory/__tests__/*.test.js\" \"dist/__tests__/*.test.js\""
|
|
49
|
+
"test": "node --test \"dist/memory/__tests__/*.test.js\" \"dist/__tests__/*.test.js\"",
|
|
50
|
+
"prepublishOnly": "npm run build",
|
|
51
|
+
"pack:dry": "npm pack --dry-run"
|
|
19
52
|
},
|
|
20
53
|
"dependencies": {
|
|
21
54
|
"@eclipse-zenoh/zenoh-ts": "^1.9.0",
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
* The most upstream of those is "the reader produces what we promised";
|
|
12
12
|
* everything else depends on that contract holding. So this file pins down:
|
|
13
13
|
* - BUILTIN_CAPABILITIES has the 6 intrinsic verbs we ship.
|
|
14
|
-
* - readSkillCapabilities() picks up
|
|
15
|
-
* - It
|
|
14
|
+
* - readSkillCapabilities() picks up the `agenticros` block from package.json.
|
|
15
|
+
* - It uses `agenticros.id` (not the package name) as the skill id.
|
|
16
16
|
* - It tags every capability with a source so dispatchers can filter.
|
|
17
17
|
* - It deduplicates within a skill so a malformed manifest can't blow up.
|
|
18
18
|
* - listAllCapabilities() merges intrinsic + skill in that order.
|
|
19
|
-
* - It tolerates non-skill packages (no
|
|
19
|
+
* - It tolerates non-skill packages (no `agenticros` key) silently.
|
|
20
20
|
*/
|
|
21
21
|
import { test } from "node:test";
|
|
22
22
|
import assert from "node:assert/strict";
|
|
@@ -40,12 +40,10 @@ async function makeSkillDir(
|
|
|
40
40
|
root: string,
|
|
41
41
|
name: string,
|
|
42
42
|
pkg: Record<string, unknown>,
|
|
43
|
-
sidecar?: Record<string, unknown>,
|
|
44
43
|
): Promise<string> {
|
|
45
44
|
const dir = path.join(root, name);
|
|
46
45
|
await mkdir(dir, { recursive: true });
|
|
47
46
|
await writeJson(path.join(dir, "package.json"), pkg);
|
|
48
|
-
if (sidecar) await writeJson(path.join(dir, "capabilities.json"), sidecar);
|
|
49
47
|
return dir;
|
|
50
48
|
}
|
|
51
49
|
|
|
@@ -66,14 +64,16 @@ test("BUILTIN_CAPABILITIES exposes the six intrinsic robot verbs", () => {
|
|
|
66
64
|
}
|
|
67
65
|
});
|
|
68
66
|
|
|
69
|
-
test("readSkillCapabilities: reads
|
|
67
|
+
test("readSkillCapabilities: reads capabilities from the `agenticros` block", async () => {
|
|
70
68
|
const root = await mkdtemp(path.join(tmpdir(), "agenticros-caps-"));
|
|
71
69
|
try {
|
|
72
70
|
const skillDir = await makeSkillDir(root, "skill-alpha", {
|
|
73
71
|
name: "agenticros-skill-alpha",
|
|
74
72
|
version: "0.0.1",
|
|
75
73
|
main: "dist/index.js",
|
|
76
|
-
|
|
74
|
+
agenticros: {
|
|
75
|
+
id: "alpha",
|
|
76
|
+
displayName: "Alpha",
|
|
77
77
|
capabilities: [
|
|
78
78
|
{
|
|
79
79
|
id: "wave_hello",
|
|
@@ -114,30 +114,23 @@ test("readSkillCapabilities: reads package.json agenticrosSkill object form", as
|
|
|
114
114
|
}
|
|
115
115
|
});
|
|
116
116
|
|
|
117
|
-
test("readSkillCapabilities:
|
|
117
|
+
test("readSkillCapabilities: uses agenticros.id (not the package name) for the skill id", async () => {
|
|
118
118
|
const root = await mkdtemp(path.join(tmpdir(), "agenticros-caps-"));
|
|
119
119
|
try {
|
|
120
|
-
const skillDir = await makeSkillDir(
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
agenticrosSkill: true,
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
capabilities: [
|
|
130
|
-
{ id: "sidecar_only", verb: "demo", description: "From sibling." },
|
|
131
|
-
],
|
|
120
|
+
const skillDir = await makeSkillDir(root, "weird-named-repo", {
|
|
121
|
+
name: "@some-org/totally-different-name",
|
|
122
|
+
version: "0.0.1",
|
|
123
|
+
agenticros: {
|
|
124
|
+
id: "explicit-id",
|
|
125
|
+
capabilities: [{ id: "do_thing", verb: "do", description: "Do." }],
|
|
132
126
|
},
|
|
133
|
-
);
|
|
134
|
-
|
|
127
|
+
});
|
|
135
128
|
const caps = readSkillCapabilities(parseConfig({ skillPaths: [skillDir] }));
|
|
136
129
|
assert.equal(caps.length, 1);
|
|
137
|
-
assert.equal(caps[0].id, "sidecar_only");
|
|
138
130
|
assert.equal(caps[0].source?.kind, "skill");
|
|
139
131
|
if (caps[0].source?.kind === "skill") {
|
|
140
|
-
assert.equal(caps[0].source.skillId, "
|
|
132
|
+
assert.equal(caps[0].source.skillId, "explicit-id");
|
|
133
|
+
assert.equal(caps[0].source.package, "@some-org/totally-different-name");
|
|
141
134
|
}
|
|
142
135
|
} finally {
|
|
143
136
|
await rm(root, { recursive: true, force: true });
|
|
@@ -158,33 +151,26 @@ test("readSkillCapabilities: silently ignores non-skill packages", async () => {
|
|
|
158
151
|
}
|
|
159
152
|
});
|
|
160
153
|
|
|
161
|
-
test("readSkillCapabilities: dedupes when an id appears in
|
|
154
|
+
test("readSkillCapabilities: dedupes within a skill when an id appears twice in the array", async () => {
|
|
162
155
|
const root = await mkdtemp(path.join(tmpdir(), "agenticros-caps-"));
|
|
163
156
|
try {
|
|
164
|
-
const skillDir = await makeSkillDir(
|
|
165
|
-
|
|
166
|
-
"
|
|
167
|
-
{
|
|
168
|
-
|
|
169
|
-
version: "0.0.1",
|
|
170
|
-
agenticrosSkill: {
|
|
171
|
-
capabilities: [
|
|
172
|
-
{ id: "shared_id", verb: "first", description: "From package.json." },
|
|
173
|
-
],
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
{
|
|
157
|
+
const skillDir = await makeSkillDir(root, "skill-dupe", {
|
|
158
|
+
name: "agenticros-skill-dupe",
|
|
159
|
+
version: "0.0.1",
|
|
160
|
+
agenticros: {
|
|
161
|
+
id: "dupe",
|
|
177
162
|
capabilities: [
|
|
178
|
-
{ id: "shared_id", verb: "
|
|
179
|
-
{ id: "
|
|
163
|
+
{ id: "shared_id", verb: "first", description: "First." },
|
|
164
|
+
{ id: "shared_id", verb: "second", description: "Duplicate (ignored)." },
|
|
165
|
+
{ id: "extra", verb: "demo", description: "Unique." },
|
|
180
166
|
],
|
|
181
167
|
},
|
|
182
|
-
);
|
|
168
|
+
});
|
|
183
169
|
const caps = readSkillCapabilities(parseConfig({ skillPaths: [skillDir] }));
|
|
184
170
|
const ids = caps.map((c) => c.id).sort();
|
|
185
171
|
assert.deepEqual(ids, ["extra", "shared_id"]);
|
|
186
172
|
const shared = caps.find((c) => c.id === "shared_id");
|
|
187
|
-
assert.equal(shared?.verb, "first", "
|
|
173
|
+
assert.equal(shared?.verb, "first", "first entry should win on duplicate id");
|
|
188
174
|
} finally {
|
|
189
175
|
await rm(root, { recursive: true, force: true });
|
|
190
176
|
}
|
|
@@ -196,7 +182,8 @@ test("readSkillCapabilities: drops entries without a valid id", async () => {
|
|
|
196
182
|
const skillDir = await makeSkillDir(root, "skill-bad", {
|
|
197
183
|
name: "agenticros-skill-bad",
|
|
198
184
|
version: "0.0.1",
|
|
199
|
-
|
|
185
|
+
agenticros: {
|
|
186
|
+
id: "bad",
|
|
200
187
|
capabilities: [
|
|
201
188
|
{ verb: "noid", description: "Missing id." },
|
|
202
189
|
{ id: "", verb: "empty", description: "Empty id." },
|
|
@@ -214,13 +201,31 @@ test("readSkillCapabilities: drops entries without a valid id", async () => {
|
|
|
214
201
|
}
|
|
215
202
|
});
|
|
216
203
|
|
|
204
|
+
test("readSkillCapabilities: skips packages with an `agenticros` block that lacks an `id`", async () => {
|
|
205
|
+
const root = await mkdtemp(path.join(tmpdir(), "agenticros-caps-"));
|
|
206
|
+
try {
|
|
207
|
+
const skillDir = await makeSkillDir(root, "skill-noid", {
|
|
208
|
+
name: "agenticros-skill-noid",
|
|
209
|
+
version: "0.0.1",
|
|
210
|
+
agenticros: {
|
|
211
|
+
capabilities: [{ id: "do_thing", verb: "do", description: "Do." }],
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
const caps = readSkillCapabilities(parseConfig({ skillPaths: [skillDir] }));
|
|
215
|
+
assert.equal(caps.length, 0);
|
|
216
|
+
} finally {
|
|
217
|
+
await rm(root, { recursive: true, force: true });
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
217
221
|
test("listAllCapabilities: built-ins first, then skill caps; counts add up", async () => {
|
|
218
222
|
const root = await mkdtemp(path.join(tmpdir(), "agenticros-caps-"));
|
|
219
223
|
try {
|
|
220
224
|
const skillDir = await makeSkillDir(root, "skill-extra", {
|
|
221
225
|
name: "agenticros-skill-extra",
|
|
222
226
|
version: "0.0.1",
|
|
223
|
-
|
|
227
|
+
agenticros: {
|
|
228
|
+
id: "extra",
|
|
224
229
|
capabilities: [
|
|
225
230
|
{ id: "extra_one", verb: "demo", description: "One." },
|
|
226
231
|
{ id: "extra_two", verb: "demo", description: "Two." },
|
|
@@ -169,16 +169,6 @@ export const BUILTIN_CAPABILITIES: readonly Capability[] = [
|
|
|
169
169
|
},
|
|
170
170
|
];
|
|
171
171
|
|
|
172
|
-
const SKILL_PACKAGE_PREFIX = "agenticros-skill-";
|
|
173
|
-
|
|
174
|
-
function deriveSkillId(packageName: string): string {
|
|
175
|
-
const lower = packageName.toLowerCase();
|
|
176
|
-
if (lower.startsWith(SKILL_PACKAGE_PREFIX)) {
|
|
177
|
-
return lower.slice(SKILL_PACKAGE_PREFIX.length);
|
|
178
|
-
}
|
|
179
|
-
return lower.replace(/^@[^/]+\//, "").replace(/[^a-z0-9]/g, "");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
172
|
function isCapabilityLike(value: unknown): value is Partial<Capability> & { id: string } {
|
|
183
173
|
if (!value || typeof value !== "object") return false;
|
|
184
174
|
const v = value as Record<string, unknown>;
|
|
@@ -204,53 +194,39 @@ function normalizeCapability(
|
|
|
204
194
|
}
|
|
205
195
|
|
|
206
196
|
/**
|
|
207
|
-
*
|
|
208
|
-
* `
|
|
209
|
-
*
|
|
197
|
+
* Read the `agenticros.capabilities[]` array from a skill's package.json.
|
|
198
|
+
* Returns `null` if the package doesn't declare a valid `agenticros` block.
|
|
199
|
+
*
|
|
200
|
+
* The legacy `agenticrosSkill: true | { capabilities }` form is NOT supported
|
|
201
|
+
* — every skill must use the single `agenticros` block as its source of truth.
|
|
210
202
|
*/
|
|
211
203
|
function readSkillManifestFromDir(
|
|
212
204
|
packageDir: string,
|
|
213
|
-
): { packageName: string; rawCaps: Array<Partial<Capability> & { id: string }> } | null {
|
|
205
|
+
): { packageName: string; skillId: string; rawCaps: Array<Partial<Capability> & { id: string }> } | null {
|
|
214
206
|
const pkgJsonPath = join(packageDir, "package.json");
|
|
215
207
|
if (!existsSync(pkgJsonPath)) return null;
|
|
216
208
|
let pkg: {
|
|
217
209
|
name?: string;
|
|
218
|
-
|
|
210
|
+
agenticros?: { id?: unknown; capabilities?: unknown };
|
|
219
211
|
};
|
|
220
212
|
try {
|
|
221
213
|
pkg = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
222
214
|
} catch {
|
|
223
215
|
return null;
|
|
224
216
|
}
|
|
225
|
-
if (pkg.
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
const packageName = pkg.name ?? "unknown";
|
|
217
|
+
if (!pkg.agenticros || typeof pkg.agenticros !== "object") return null;
|
|
218
|
+
if (typeof pkg.agenticros.id !== "string") return null;
|
|
229
219
|
|
|
220
|
+
const packageName = pkg.name ?? "unknown";
|
|
221
|
+
const skillId = pkg.agenticros.id;
|
|
230
222
|
const rawCaps: Array<Partial<Capability> & { id: string }> = [];
|
|
231
223
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if (
|
|
235
|
-
for (const c of caps) if (isCapabilityLike(c)) rawCaps.push(c);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const sidecarPath = join(packageDir, "capabilities.json");
|
|
240
|
-
if (existsSync(sidecarPath)) {
|
|
241
|
-
try {
|
|
242
|
-
const parsed = JSON.parse(readFileSync(sidecarPath, "utf-8"));
|
|
243
|
-
const arr = Array.isArray(parsed)
|
|
244
|
-
? parsed
|
|
245
|
-
: Array.isArray((parsed as { capabilities?: unknown }).capabilities)
|
|
246
|
-
? (parsed as { capabilities: unknown[] }).capabilities
|
|
247
|
-
: [];
|
|
248
|
-
for (const c of arr) if (isCapabilityLike(c)) rawCaps.push(c);
|
|
249
|
-
} catch {
|
|
250
|
-
}
|
|
224
|
+
const caps = pkg.agenticros.capabilities;
|
|
225
|
+
if (Array.isArray(caps)) {
|
|
226
|
+
for (const c of caps) if (isCapabilityLike(c)) rawCaps.push(c);
|
|
251
227
|
}
|
|
252
228
|
|
|
253
|
-
return { packageName, rawCaps };
|
|
229
|
+
return { packageName, skillId, rawCaps };
|
|
254
230
|
}
|
|
255
231
|
|
|
256
232
|
function resolvePackageDir(packageName: string, searchPaths: string[]): string | null {
|
|
@@ -290,15 +266,14 @@ export function readSkillCapabilities(config: AgenticROSConfig): Capability[] {
|
|
|
290
266
|
const absDir = resolvePath(dir);
|
|
291
267
|
const manifest = readSkillManifestFromDir(absDir);
|
|
292
268
|
if (!manifest) continue;
|
|
293
|
-
const skillId = deriveSkillId(manifest.packageName);
|
|
294
269
|
for (const raw of manifest.rawCaps) {
|
|
295
|
-
const key = `${skillId}:${raw.id}`;
|
|
270
|
+
const key = `${manifest.skillId}:${raw.id}`;
|
|
296
271
|
if (seen.has(key)) continue;
|
|
297
272
|
seen.add(key);
|
|
298
273
|
out.push(
|
|
299
274
|
normalizeCapability(raw, {
|
|
300
275
|
kind: "skill",
|
|
301
|
-
skillId,
|
|
276
|
+
skillId: manifest.skillId,
|
|
302
277
|
package: manifest.packageName,
|
|
303
278
|
path: absDir,
|
|
304
279
|
}),
|
|
@@ -311,15 +286,14 @@ export function readSkillCapabilities(config: AgenticROSConfig): Capability[] {
|
|
|
311
286
|
if (!packageDir) continue;
|
|
312
287
|
const manifest = readSkillManifestFromDir(packageDir);
|
|
313
288
|
if (!manifest) continue;
|
|
314
|
-
const skillId = deriveSkillId(manifest.packageName);
|
|
315
289
|
for (const raw of manifest.rawCaps) {
|
|
316
|
-
const key = `${skillId}:${raw.id}`;
|
|
290
|
+
const key = `${manifest.skillId}:${raw.id}`;
|
|
317
291
|
if (seen.has(key)) continue;
|
|
318
292
|
seen.add(key);
|
|
319
293
|
out.push(
|
|
320
294
|
normalizeCapability(raw, {
|
|
321
295
|
kind: "skill",
|
|
322
|
-
skillId,
|
|
296
|
+
skillId: manifest.skillId,
|
|
323
297
|
package: manifest.packageName,
|
|
324
298
|
path: packageDir,
|
|
325
299
|
}),
|
|
@@ -413,7 +413,7 @@ export const AgenticROSConfigSchema = z.object({
|
|
|
413
413
|
/** Per-skill config. Keys are skill ids (e.g. followme). Each skill validates its own slice. */
|
|
414
414
|
skills: z.record(z.string(), z.unknown()).default({}),
|
|
415
415
|
|
|
416
|
-
/** Directories to scan for skill packages (package.json with
|
|
416
|
+
/** Directories to scan for skill packages (package.json with an `agenticros` block). Resolved at gateway start. */
|
|
417
417
|
skillPaths: z.array(z.string()).default([]),
|
|
418
418
|
|
|
419
419
|
/** Npm (or local) package names to load as skills. Resolved via require.resolve from plugin context. */
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
import { execSync } from "node:child_process";
|
|
40
40
|
import { cpSync, existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
41
|
-
import { dirname, join, relative, resolve } from "node:path";
|
|
41
|
+
import { dirname, join, relative, resolve, sep as pathSep } from "node:path";
|
|
42
42
|
import { fileURLToPath } from "node:url";
|
|
43
43
|
|
|
44
44
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -117,8 +117,14 @@ function copyTree(src, dest, opts = {}) {
|
|
|
117
117
|
errorOnExist: false,
|
|
118
118
|
force: true,
|
|
119
119
|
filter: (s, _d) => {
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
// On Windows, fs.cpSync hands the filter back paths with `\` separators
|
|
121
|
+
// while `src` was built with `path.join` (also `\`), so split on the
|
|
122
|
+
// OS separator. Splitting on `/` here used to silently fail on Windows
|
|
123
|
+
// and let node_modules through, which then EPERM'd on the first
|
|
124
|
+
// symlink inside `.pnpm/...` because Win32 needs elevated rights to
|
|
125
|
+
// create symlinks.
|
|
126
|
+
const rel = s.startsWith(src + pathSep) ? s.slice(src.length + 1) : "";
|
|
127
|
+
const parts = rel.split(pathSep);
|
|
122
128
|
for (const p of parts) {
|
|
123
129
|
if (EXCLUDED_DIR_NAMES.has(p)) return false;
|
|
124
130
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -130,8 +130,8 @@ function findSkillEntryFromPath(dirPath) {
|
|
|
130
130
|
warn(`Invalid package.json in ${dirPath}: ${e?.message ?? e}`);
|
|
131
131
|
return null;
|
|
132
132
|
}
|
|
133
|
-
if (!pkg.
|
|
134
|
-
warn(`Not an AgenticROS skill (missing
|
|
133
|
+
if (!pkg.agenticros || typeof pkg.agenticros !== "object" || typeof pkg.agenticros.id !== "string") {
|
|
134
|
+
warn(`Not an AgenticROS skill (missing "agenticros": { "id": "..." } block): ${dirPath}`);
|
|
135
135
|
return null;
|
|
136
136
|
}
|
|
137
137
|
const main = pkg.main ?? "index.js";
|
|
File without changes
|
|
File without changes
|