agenticros 0.4.0 → 0.5.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/dist/commands/publish-skill.d.ts.map +1 -1
- package/dist/commands/publish-skill.js +19 -0
- package/dist/commands/publish-skill.js.map +1 -1
- package/dist/commands/skills.d.ts +2 -0
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +150 -42
- package/dist/commands/skills.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/util/marketplace.d.ts +2 -0
- package/dist/util/marketplace.d.ts.map +1 -1
- package/dist/util/marketplace.js.map +1 -1
- package/package.json +2 -2
- package/runtime/BUNDLE.json +1 -1
- package/runtime/docs/cli.md +2 -2
- package/runtime/packages/agenticros/src/tools/ros2-mission.ts +3 -2
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts +2 -0
- 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 +14 -0
- package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts +3 -1
- package/runtime/packages/agenticros-claude-code/dist/tools.d.ts.map +1 -1
- package/runtime/packages/agenticros-claude-code/dist/tools.js +6 -4
- package/runtime/packages/agenticros-claude-code/dist/tools.js.map +1 -1
- package/runtime/packages/agenticros-claude-code/src/find-object/find-object.ts +16 -0
- package/runtime/packages/agenticros-claude-code/src/tools.ts +6 -3
- package/runtime/packages/agenticros-gemini/src/find-object/find-object.ts +16 -0
- package/runtime/packages/agenticros-gemini/src/tools.ts +5 -2
- package/runtime/packages/core/package.json +1 -1
- package/runtime/packages/core/src/__tests__/mission-retry-cancel.test.ts +165 -0
- package/runtime/packages/core/src/__tests__/skill-refs.test.ts +14 -0
- package/runtime/packages/core/src/external-capability.ts +67 -25
- package/runtime/packages/core/src/index.ts +3 -1
- package/runtime/packages/core/src/mission.ts +188 -31
- package/runtime/packages/core/src/skill-refs.ts +257 -30
- package/runtime/pnpm-lock.yaml +23 -2
- package/runtime/scripts/check-cli-tarball-install.mjs +41 -8
- package/templates/skills/camera/package.json +17 -6
- package/templates/skills/depth/package.json +18 -6
- package/templates/skills/hello/package.json +16 -5
- package/templates/skills/robot/package.json +18 -6
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* skillRefs → ~/.agenticros/skills-cache resolver (marketplace auto-fetch
|
|
2
|
+
* skillRefs → ~/.agenticros/skills-cache resolver (marketplace auto-fetch).
|
|
3
3
|
*
|
|
4
|
-
* Declarative refs like `
|
|
5
|
-
* resolved via the skills marketplace
|
|
6
|
-
*
|
|
7
|
-
* reading / OpenClaw loading.
|
|
4
|
+
* Declarative refs like `owner/skill`, `owner/skill@main`, or
|
|
5
|
+
* `@agenticros-skills/foo@^1.0.0` are resolved via the skills marketplace
|
|
6
|
+
* install API (or directly from npm), cached under ~/.agenticros/skills-cache,
|
|
7
|
+
* and returned as absolute skillPaths for capability reading / OpenClaw loading.
|
|
8
|
+
*
|
|
9
|
+
* Prefer npm when the install descriptor includes `npmPackage` (or the ref
|
|
10
|
+
* is already a scoped npm name). Fall back to git clone + build.
|
|
8
11
|
*
|
|
9
12
|
* Never auto-upgrades: if the cache dir for a pin already exists, reuse it
|
|
10
|
-
* (optional pull when AGENTICROS_SKILLS_CACHE_PULL=1).
|
|
13
|
+
* (optional pull when AGENTICROS_SKILLS_CACHE_PULL=1 for git caches).
|
|
11
14
|
*/
|
|
12
15
|
|
|
13
|
-
import {
|
|
14
|
-
|
|
16
|
+
import {
|
|
17
|
+
existsSync,
|
|
18
|
+
mkdirSync,
|
|
19
|
+
mkdtempSync,
|
|
20
|
+
readFileSync,
|
|
21
|
+
readdirSync,
|
|
22
|
+
renameSync,
|
|
23
|
+
rmSync,
|
|
24
|
+
writeFileSync,
|
|
25
|
+
} from "node:fs";
|
|
26
|
+
import { tmpdir, homedir } from "node:os";
|
|
15
27
|
import { basename, join } from "node:path";
|
|
16
28
|
import { execFileSync } from "node:child_process";
|
|
17
29
|
import type { AgenticROSConfig } from "./config.js";
|
|
@@ -20,12 +32,17 @@ export const DEFAULT_SKILLS_API = "https://skills.agenticros.com/api";
|
|
|
20
32
|
export const DEFAULT_SKILLS_CACHE_DIR = join(homedir(), ".agenticros", "skills-cache");
|
|
21
33
|
|
|
22
34
|
export interface ParsedSkillRef {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
kind: "marketplace" | "npm";
|
|
36
|
+
/** owner/skill (lowercase) — marketplace refs only */
|
|
37
|
+
marketplaceRef?: string;
|
|
38
|
+
owner?: string;
|
|
39
|
+
skill?: string;
|
|
40
|
+
/** git ref / branch pin; default main — marketplace refs */
|
|
41
|
+
gitRef?: string;
|
|
42
|
+
/** Scoped npm package name — npm refs */
|
|
43
|
+
npmPackage?: string;
|
|
44
|
+
/** Semver range or exact version pin — npm refs (default: latest resolved) */
|
|
45
|
+
npmVersion?: string;
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
export interface InstallDescriptor {
|
|
@@ -36,6 +53,10 @@ export interface InstallDescriptor {
|
|
|
36
53
|
githubUrl: string;
|
|
37
54
|
ref: string;
|
|
38
55
|
buildCmd: string;
|
|
56
|
+
/** When set, prefer npm pack over git clone. */
|
|
57
|
+
npmPackage?: string;
|
|
58
|
+
/** Pinned npm version when known. */
|
|
59
|
+
npmVersion?: string;
|
|
39
60
|
}
|
|
40
61
|
|
|
41
62
|
export interface ResolveSkillRefsOptions {
|
|
@@ -54,10 +75,37 @@ export interface ResolveSkillRefsResult {
|
|
|
54
75
|
errors: Array<{ ref: string; error: string }>;
|
|
55
76
|
}
|
|
56
77
|
|
|
57
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Parse `owner/skill`, `owner/skill@branch`, or `@scope/name[@semver]`.
|
|
80
|
+
*/
|
|
58
81
|
export function parseSkillRef(raw: string): ParsedSkillRef | null {
|
|
59
82
|
const trimmed = raw.trim();
|
|
60
83
|
if (!trimmed) return null;
|
|
84
|
+
|
|
85
|
+
if (trimmed.startsWith("@")) {
|
|
86
|
+
// @scope/name or @scope/name@1.2.3 / @scope/name@^1.0.0
|
|
87
|
+
const withoutAt = trimmed.slice(1);
|
|
88
|
+
const slash = withoutAt.indexOf("/");
|
|
89
|
+
if (slash <= 0) return null;
|
|
90
|
+
const scope = withoutAt.slice(0, slash);
|
|
91
|
+
const rest = withoutAt.slice(slash + 1);
|
|
92
|
+
if (!scope || !rest) return null;
|
|
93
|
+
// Version pin is the last @ after the package name segment.
|
|
94
|
+
const at = rest.lastIndexOf("@");
|
|
95
|
+
let pkgName = rest;
|
|
96
|
+
let npmVersion: string | undefined;
|
|
97
|
+
if (at > 0) {
|
|
98
|
+
pkgName = rest.slice(0, at);
|
|
99
|
+
npmVersion = rest.slice(at + 1).trim() || undefined;
|
|
100
|
+
}
|
|
101
|
+
if (!pkgName || pkgName.includes("/")) return null;
|
|
102
|
+
return {
|
|
103
|
+
kind: "npm",
|
|
104
|
+
npmPackage: `@${scope}/${pkgName}`,
|
|
105
|
+
npmVersion,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
61
109
|
const at = trimmed.lastIndexOf("@");
|
|
62
110
|
let body = trimmed;
|
|
63
111
|
let gitRef = "main";
|
|
@@ -71,6 +119,7 @@ export function parseSkillRef(raw: string): ParsedSkillRef | null {
|
|
|
71
119
|
const skill = parts.slice(1).join("/").toLowerCase();
|
|
72
120
|
if (!owner || !skill) return null;
|
|
73
121
|
return {
|
|
122
|
+
kind: "marketplace",
|
|
74
123
|
marketplaceRef: `${owner}/${skill}`,
|
|
75
124
|
owner,
|
|
76
125
|
skill,
|
|
@@ -107,13 +156,15 @@ export async function fetchInstallDescriptor(
|
|
|
107
156
|
throw new Error(`Marketplace install ${res.status}: ${body.slice(0, 200)}`);
|
|
108
157
|
}
|
|
109
158
|
const desc = (await res.json()) as InstallDescriptor;
|
|
110
|
-
if (!desc.githubUrl) {
|
|
111
|
-
throw new Error(
|
|
159
|
+
if (!desc.githubUrl && !desc.npmPackage && !desc.packageName) {
|
|
160
|
+
throw new Error(
|
|
161
|
+
`Install descriptor for ${marketplaceRef} has neither githubUrl nor npmPackage`,
|
|
162
|
+
);
|
|
112
163
|
}
|
|
113
164
|
return desc;
|
|
114
165
|
}
|
|
115
166
|
|
|
116
|
-
function
|
|
167
|
+
function cachePathForGit(
|
|
117
168
|
cacheDir: string,
|
|
118
169
|
owner: string,
|
|
119
170
|
skill: string,
|
|
@@ -123,6 +174,12 @@ function cachePathFor(
|
|
|
123
174
|
return join(cacheDir, owner, skill, safeRef);
|
|
124
175
|
}
|
|
125
176
|
|
|
177
|
+
function cachePathForNpm(cacheDir: string, npmPackage: string, version: string): string {
|
|
178
|
+
const safeName = npmPackage.replace(/^@/, "").replace(/\//g, "__");
|
|
179
|
+
const safeVer = version.replace(/[^a-zA-Z0-9._+-]+/g, "_");
|
|
180
|
+
return join(cacheDir, "npm", safeName, safeVer);
|
|
181
|
+
}
|
|
182
|
+
|
|
126
183
|
function hasBuiltEntry(dir: string): boolean {
|
|
127
184
|
try {
|
|
128
185
|
const pkg = JSON.parse(readFileSync(join(dir, "package.json"), "utf8")) as {
|
|
@@ -140,6 +197,10 @@ function run(cmd: string, args: string[], cwd: string, log: (m: string) => void)
|
|
|
140
197
|
execFileSync(cmd, args, { cwd, stdio: "inherit" });
|
|
141
198
|
}
|
|
142
199
|
|
|
200
|
+
function runCapture(cmd: string, args: string[], cwd: string): string {
|
|
201
|
+
return execFileSync(cmd, args, { cwd, encoding: "utf8" }).trim();
|
|
202
|
+
}
|
|
203
|
+
|
|
143
204
|
function hasBin(name: string): boolean {
|
|
144
205
|
try {
|
|
145
206
|
execFileSync(name, ["--version"], { stdio: "ignore" });
|
|
@@ -149,6 +210,124 @@ function hasBin(name: string): boolean {
|
|
|
149
210
|
}
|
|
150
211
|
}
|
|
151
212
|
|
|
213
|
+
function safeNpmVersionPin(raw: string | undefined): string {
|
|
214
|
+
if (!raw || !raw.trim()) return "latest";
|
|
215
|
+
return raw.trim();
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Resolve the exact version npm would install for a package@range.
|
|
220
|
+
*/
|
|
221
|
+
function resolveNpmVersion(npmPackage: string, versionRange: string, log: (m: string) => void): string {
|
|
222
|
+
const spec = versionRange === "latest" ? npmPackage : `${npmPackage}@${versionRange}`;
|
|
223
|
+
log(`Resolving npm version for ${spec}`);
|
|
224
|
+
const out = runCapture("npm", ["view", spec, "version"], process.cwd());
|
|
225
|
+
// npm view can return a single version or a JSON array for ranges — take last line.
|
|
226
|
+
const lines = out.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
227
|
+
const last = lines[lines.length - 1] ?? "";
|
|
228
|
+
// Strip quotes if JSON-ish
|
|
229
|
+
const cleaned = last.replace(/^"|"$/g, "");
|
|
230
|
+
if (!cleaned) throw new Error(`Could not resolve npm version for ${spec}`);
|
|
231
|
+
return cleaned;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Pack an npm package into the skills cache and return the absolute dir.
|
|
236
|
+
*/
|
|
237
|
+
export async function ensureNpmPackageCached(
|
|
238
|
+
npmPackage: string,
|
|
239
|
+
versionRange: string | undefined,
|
|
240
|
+
opts: ResolveSkillRefsOptions = {},
|
|
241
|
+
): Promise<string> {
|
|
242
|
+
const log = opts.onLog ?? (() => undefined);
|
|
243
|
+
const cacheRoot = skillsCacheDir(opts.cacheDir);
|
|
244
|
+
const pin = safeNpmVersionPin(versionRange);
|
|
245
|
+
|
|
246
|
+
// Fast path: exact version already cached
|
|
247
|
+
if (pin !== "latest" && !pin.startsWith("^") && !pin.startsWith("~") && !pin.includes("*")) {
|
|
248
|
+
const exactDir = cachePathForNpm(cacheRoot, npmPackage, pin);
|
|
249
|
+
if (existsSync(join(exactDir, "package.json"))) {
|
|
250
|
+
if (!hasBuiltEntry(exactDir) && !opts.offline) {
|
|
251
|
+
await buildInPlace(exactDir, log);
|
|
252
|
+
}
|
|
253
|
+
return exactDir;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (opts.offline) {
|
|
258
|
+
// Best-effort: look for any cached version of this package
|
|
259
|
+
const safeName = npmPackage.replace(/^@/, "").replace(/\//g, "__");
|
|
260
|
+
const pkgRoot = join(cacheRoot, "npm", safeName);
|
|
261
|
+
if (existsSync(pkgRoot)) {
|
|
262
|
+
const versions = readdirSync(pkgRoot).filter((v) =>
|
|
263
|
+
existsSync(join(pkgRoot, v, "package.json")),
|
|
264
|
+
);
|
|
265
|
+
if (versions.length > 0) {
|
|
266
|
+
versions.sort();
|
|
267
|
+
return join(pkgRoot, versions[versions.length - 1]!);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
throw new Error(`npm package ${npmPackage}@${pin} not in cache (offline)`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const resolvedVersion = resolveNpmVersion(npmPackage, pin, log);
|
|
274
|
+
const dir = cachePathForNpm(cacheRoot, npmPackage, resolvedVersion);
|
|
275
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
276
|
+
if (!hasBuiltEntry(dir)) {
|
|
277
|
+
await buildInPlace(dir, log);
|
|
278
|
+
}
|
|
279
|
+
return dir;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
mkdirSync(join(cacheRoot, "npm", npmPackage.replace(/^@/, "").replace(/\//g, "__")), {
|
|
283
|
+
recursive: true,
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const tmp = mkdtempSync(join(tmpdir(), "agenticros-skill-npm-"));
|
|
287
|
+
try {
|
|
288
|
+
const spec = `${npmPackage}@${resolvedVersion}`;
|
|
289
|
+
log(`npm pack ${spec} → ${tmp}`);
|
|
290
|
+
const tgzName = runCapture("npm", ["pack", spec, "--pack-destination", tmp], tmp);
|
|
291
|
+
const tgzPath = join(tmp, tgzName);
|
|
292
|
+
const extractDir = join(tmp, "extract");
|
|
293
|
+
mkdirSync(extractDir, { recursive: true });
|
|
294
|
+
run("tar", ["-xzf", tgzPath, "-C", extractDir], tmp, log);
|
|
295
|
+
const packedRoot = join(extractDir, "package");
|
|
296
|
+
if (!existsSync(join(packedRoot, "package.json"))) {
|
|
297
|
+
throw new Error(`npm pack for ${spec} did not produce package/package.json`);
|
|
298
|
+
}
|
|
299
|
+
mkdirSync(join(dir, ".."), { recursive: true });
|
|
300
|
+
if (existsSync(dir)) {
|
|
301
|
+
rmSync(dir, { recursive: true, force: true });
|
|
302
|
+
}
|
|
303
|
+
renameSync(packedRoot, dir);
|
|
304
|
+
writeFileSync(
|
|
305
|
+
join(dir, ".agenticros-skill-ref.json"),
|
|
306
|
+
JSON.stringify(
|
|
307
|
+
{
|
|
308
|
+
kind: "npm",
|
|
309
|
+
npmPackage,
|
|
310
|
+
npmVersion: resolvedVersion,
|
|
311
|
+
cachedAt: new Date().toISOString(),
|
|
312
|
+
},
|
|
313
|
+
null,
|
|
314
|
+
2,
|
|
315
|
+
),
|
|
316
|
+
);
|
|
317
|
+
} finally {
|
|
318
|
+
try {
|
|
319
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
320
|
+
} catch {
|
|
321
|
+
/* ignore */
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
if (!hasBuiltEntry(dir)) {
|
|
326
|
+
await buildInPlace(dir, log);
|
|
327
|
+
}
|
|
328
|
+
return dir;
|
|
329
|
+
}
|
|
330
|
+
|
|
152
331
|
/**
|
|
153
332
|
* Ensure one skillRef is present under the cache. Returns absolute path or throws.
|
|
154
333
|
*/
|
|
@@ -158,11 +337,18 @@ export async function ensureSkillRefCached(
|
|
|
158
337
|
): Promise<string> {
|
|
159
338
|
const parsed = parseSkillRef(rawRef);
|
|
160
339
|
if (!parsed) {
|
|
161
|
-
throw new Error(
|
|
340
|
+
throw new Error(
|
|
341
|
+
`Invalid skillRef "${rawRef}" (expected owner/skill, owner/skill@ref, or @scope/name[@semver])`,
|
|
342
|
+
);
|
|
162
343
|
}
|
|
163
344
|
const log = opts.onLog ?? (() => undefined);
|
|
345
|
+
|
|
346
|
+
if (parsed.kind === "npm") {
|
|
347
|
+
return ensureNpmPackageCached(parsed.npmPackage!, parsed.npmVersion, opts);
|
|
348
|
+
}
|
|
349
|
+
|
|
164
350
|
const cacheRoot = skillsCacheDir(opts.cacheDir);
|
|
165
|
-
const dir =
|
|
351
|
+
const dir = cachePathForGit(cacheRoot, parsed.owner!, parsed.skill!, parsed.gitRef!);
|
|
166
352
|
|
|
167
353
|
if (existsSync(join(dir, "package.json"))) {
|
|
168
354
|
if (opts.pullIfPresent || process.env.AGENTICROS_SKILLS_CACHE_PULL === "1") {
|
|
@@ -182,25 +368,42 @@ export async function ensureSkillRefCached(
|
|
|
182
368
|
throw new Error(`skillRef ${parsed.marketplaceRef} not in cache (offline)`);
|
|
183
369
|
}
|
|
184
370
|
|
|
185
|
-
const descriptor = await fetchInstallDescriptor(parsed.marketplaceRef
|
|
186
|
-
|
|
371
|
+
const descriptor = await fetchInstallDescriptor(parsed.marketplaceRef!, opts.apiBase);
|
|
372
|
+
|
|
373
|
+
// Prefer npm when the marketplace advertises an npm package.
|
|
374
|
+
const npmPkg = descriptor.npmPackage || (descriptor.packageName?.startsWith("@") ? descriptor.packageName : undefined);
|
|
375
|
+
if (npmPkg) {
|
|
376
|
+
const version =
|
|
377
|
+
parsed.gitRef && parsed.gitRef !== "main"
|
|
378
|
+
? parsed.gitRef
|
|
379
|
+
: descriptor.npmVersion;
|
|
380
|
+
log(`Install descriptor prefers npm: ${npmPkg}${version ? `@${version}` : ""}`);
|
|
381
|
+
return ensureNpmPackageCached(npmPkg, version, opts);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (!descriptor.githubUrl) {
|
|
385
|
+
throw new Error(
|
|
386
|
+
`Install descriptor for ${parsed.marketplaceRef} has no githubUrl or npmPackage`,
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const gitRef = parsed.gitRef !== "main" ? parsed.gitRef! : descriptor.ref || "main";
|
|
187
391
|
const repoUrl = descriptor.githubUrl.endsWith(".git")
|
|
188
392
|
? descriptor.githubUrl
|
|
189
393
|
: `${descriptor.githubUrl}.git`;
|
|
190
394
|
|
|
191
|
-
mkdirSync(join(cacheRoot, parsed.owner
|
|
395
|
+
mkdirSync(join(cacheRoot, parsed.owner!, parsed.skill!), { recursive: true });
|
|
192
396
|
if (!existsSync(join(dir, ".git"))) {
|
|
193
397
|
log(`Cloning ${repoUrl} (${gitRef}) → ${dir}`);
|
|
194
398
|
try {
|
|
195
399
|
run(
|
|
196
400
|
"git",
|
|
197
401
|
["clone", "--branch", gitRef, "--single-branch", "--depth", "1", repoUrl, dir],
|
|
198
|
-
join(cacheRoot, parsed.owner
|
|
402
|
+
join(cacheRoot, parsed.owner!, parsed.skill!),
|
|
199
403
|
log,
|
|
200
404
|
);
|
|
201
405
|
} catch {
|
|
202
|
-
|
|
203
|
-
run("git", ["clone", "--depth", "1", repoUrl, dir], join(cacheRoot, parsed.owner, parsed.skill), log);
|
|
406
|
+
run("git", ["clone", "--depth", "1", repoUrl, dir], join(cacheRoot, parsed.owner!, parsed.skill!), log);
|
|
204
407
|
try {
|
|
205
408
|
run("git", ["checkout", gitRef], dir, log);
|
|
206
409
|
} catch {
|
|
@@ -209,12 +412,12 @@ export async function ensureSkillRefCached(
|
|
|
209
412
|
}
|
|
210
413
|
}
|
|
211
414
|
|
|
212
|
-
// Marker for which marketplace ref produced this cache entry
|
|
213
415
|
try {
|
|
214
416
|
writeFileSync(
|
|
215
417
|
join(dir, ".agenticros-skill-ref.json"),
|
|
216
418
|
JSON.stringify(
|
|
217
419
|
{
|
|
420
|
+
kind: "git",
|
|
218
421
|
marketplaceRef: parsed.marketplaceRef,
|
|
219
422
|
gitRef,
|
|
220
423
|
githubUrl: descriptor.githubUrl,
|
|
@@ -274,8 +477,6 @@ export async function resolveSkillRefs(
|
|
|
274
477
|
|
|
275
478
|
/**
|
|
276
479
|
* Return a config copy with skillRefs resolved into skillPaths (deduped).
|
|
277
|
-
* Sync-friendly path: if offline or empty refs, returns config unchanged
|
|
278
|
-
* except merging any already-cached paths when possible without network.
|
|
279
480
|
*/
|
|
280
481
|
export async function withResolvedSkillRefs(
|
|
281
482
|
config: AgenticROSConfig,
|
|
@@ -314,7 +515,33 @@ export function applyCachedSkillRefs(config: AgenticROSConfig): AgenticROSConfig
|
|
|
314
515
|
for (const raw of refs) {
|
|
315
516
|
const parsed = parseSkillRef(raw);
|
|
316
517
|
if (!parsed) continue;
|
|
317
|
-
|
|
518
|
+
if (parsed.kind === "npm") {
|
|
519
|
+
const safeName = parsed.npmPackage!.replace(/^@/, "").replace(/\//g, "__");
|
|
520
|
+
const pkgRoot = join(cacheRoot, "npm", safeName);
|
|
521
|
+
if (!existsSync(pkgRoot)) continue;
|
|
522
|
+
const pin = parsed.npmVersion;
|
|
523
|
+
if (pin && !pin.startsWith("^") && !pin.startsWith("~") && !pin.includes("*") && pin !== "latest") {
|
|
524
|
+
const dir = cachePathForNpm(cacheRoot, parsed.npmPackage!, pin);
|
|
525
|
+
if (existsSync(join(dir, "package.json")) && !have.has(dir)) {
|
|
526
|
+
have.add(dir);
|
|
527
|
+
merged.push(dir);
|
|
528
|
+
}
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
// Any cached version — prefer highest lexical version dir
|
|
532
|
+
const versions = readdirSync(pkgRoot).filter((v) =>
|
|
533
|
+
existsSync(join(pkgRoot, v, "package.json")),
|
|
534
|
+
);
|
|
535
|
+
if (versions.length === 0) continue;
|
|
536
|
+
versions.sort();
|
|
537
|
+
const dir = join(pkgRoot, versions[versions.length - 1]!);
|
|
538
|
+
if (!have.has(dir)) {
|
|
539
|
+
have.add(dir);
|
|
540
|
+
merged.push(dir);
|
|
541
|
+
}
|
|
542
|
+
continue;
|
|
543
|
+
}
|
|
544
|
+
const dir = cachePathForGit(cacheRoot, parsed.owner!, parsed.skill!, parsed.gitRef!);
|
|
318
545
|
if (existsSync(join(dir, "package.json")) && !have.has(dir)) {
|
|
319
546
|
have.add(dir);
|
|
320
547
|
merged.push(dir);
|
package/runtime/pnpm-lock.yaml
CHANGED
|
@@ -66,8 +66,8 @@ importers:
|
|
|
66
66
|
packages/agenticros-cli:
|
|
67
67
|
dependencies:
|
|
68
68
|
'@agenticros/core':
|
|
69
|
-
specifier:
|
|
70
|
-
version:
|
|
69
|
+
specifier: ^0.8.0
|
|
70
|
+
version: 0.8.0
|
|
71
71
|
'@inquirer/prompts':
|
|
72
72
|
specifier: ^7.0.0
|
|
73
73
|
version: 7.10.1(@types/node@20.19.35)
|
|
@@ -178,6 +178,10 @@ importers:
|
|
|
178
178
|
|
|
179
179
|
packages:
|
|
180
180
|
|
|
181
|
+
'@agenticros/core@0.8.0':
|
|
182
|
+
resolution: {integrity: sha512-E6WJBHhd0QE2YTGBrKe84q+SAGjgLMCp785BRh8UJDS4WUKqL80B04TMjZ1JLjtphCl/uk9XNZPjIjzBixz0kg==}
|
|
183
|
+
engines: {node: '>=20'}
|
|
184
|
+
|
|
181
185
|
'@eclipse-zenoh/zenoh-ts@1.9.0':
|
|
182
186
|
resolution: {integrity: sha512-qG3VR9Yt81+KjH0WOybyKcNVS0vtBmmhyUJ7dCc5n+8AeAEYTpEvMBTh43Lwu8P+imzMYvFqjaMAO2HFK+x9hA==}
|
|
183
187
|
|
|
@@ -1977,6 +1981,23 @@ packages:
|
|
|
1977
1981
|
|
|
1978
1982
|
snapshots:
|
|
1979
1983
|
|
|
1984
|
+
'@agenticros/core@0.8.0':
|
|
1985
|
+
dependencies:
|
|
1986
|
+
'@eclipse-zenoh/zenoh-ts': 1.9.0(patch_hash=pdjq6ms3zvqwikn6vpqzasydsy)
|
|
1987
|
+
'@foxglove/cdr': 3.5.0
|
|
1988
|
+
'@foxglove/rosmsg': 4.2.2
|
|
1989
|
+
'@foxglove/rosmsg2-serialization': 3.1.0
|
|
1990
|
+
ws: 8.19.0
|
|
1991
|
+
zod: 3.25.76
|
|
1992
|
+
optionalDependencies:
|
|
1993
|
+
node-datachannel: 0.12.0
|
|
1994
|
+
rclnodejs: 1.8.2
|
|
1995
|
+
transitivePeerDependencies:
|
|
1996
|
+
- bufferutil
|
|
1997
|
+
- jiti
|
|
1998
|
+
- supports-color
|
|
1999
|
+
- utf-8-validate
|
|
2000
|
+
|
|
1980
2001
|
'@eclipse-zenoh/zenoh-ts@1.9.0(patch_hash=pdjq6ms3zvqwikn6vpqzasydsy)':
|
|
1981
2002
|
dependencies:
|
|
1982
2003
|
'@thi.ng/leb128': 3.1.79
|
|
@@ -32,7 +32,16 @@
|
|
|
32
32
|
*/
|
|
33
33
|
|
|
34
34
|
import { execSync, spawnSync } from "node:child_process";
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
existsSync,
|
|
37
|
+
mkdirSync,
|
|
38
|
+
mkdtempSync,
|
|
39
|
+
readdirSync,
|
|
40
|
+
readFileSync,
|
|
41
|
+
rmSync,
|
|
42
|
+
statSync,
|
|
43
|
+
writeFileSync,
|
|
44
|
+
} from "node:fs";
|
|
36
45
|
import { tmpdir } from "node:os";
|
|
37
46
|
import { dirname, join, resolve } from "node:path";
|
|
38
47
|
import { fileURLToPath } from "node:url";
|
|
@@ -132,6 +141,31 @@ try {
|
|
|
132
141
|
}
|
|
133
142
|
ok(`Extracted to ${pkgDir}`);
|
|
134
143
|
|
|
144
|
+
// 3a. published package.json must not contain pnpm workspace: protocol
|
|
145
|
+
// (npm / npx consumers cannot resolve workspace:* — broke agenticros@0.4.0).
|
|
146
|
+
step("Checking published package.json has no workspace: dependencies...");
|
|
147
|
+
const publishedPkg = JSON.parse(
|
|
148
|
+
readFileSync(join(pkgDir, "package.json"), "utf8"),
|
|
149
|
+
);
|
|
150
|
+
const badDeps = [];
|
|
151
|
+
for (const section of ["dependencies", "optionalDependencies", "peerDependencies"]) {
|
|
152
|
+
const block = publishedPkg[section];
|
|
153
|
+
if (!block || typeof block !== "object") continue;
|
|
154
|
+
for (const [name, range] of Object.entries(block)) {
|
|
155
|
+
if (typeof range === "string" && range.startsWith("workspace:")) {
|
|
156
|
+
badDeps.push(`${section}.${name}=${range}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (badDeps.length > 0) {
|
|
161
|
+
fail(
|
|
162
|
+
`Published package.json still has workspace: protocol (npm cannot install this):\n ${badDeps.join("\n ")}\n` +
|
|
163
|
+
`Use a semver range against the published @agenticros/core (e.g. "^0.7.0").`,
|
|
164
|
+
);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
ok("No workspace: protocol in published dependencies.");
|
|
168
|
+
|
|
135
169
|
// 3. critical files present in the SHIPPED tarball
|
|
136
170
|
step("Verifying critical runtime files are in the tarball...");
|
|
137
171
|
const runtimeInTar = join(pkgDir, "runtime");
|
|
@@ -150,8 +184,7 @@ try {
|
|
|
150
184
|
|
|
151
185
|
// 5. write inline .npmrc (mirrors init.ts writeInitNpmrcInline)
|
|
152
186
|
step("Writing inline .npmrc (mirroring writeInitNpmrcInline)...");
|
|
153
|
-
|
|
154
|
-
fs.writeFileSync(
|
|
187
|
+
writeFileSync(
|
|
155
188
|
join(installDir, ".npmrc"),
|
|
156
189
|
[
|
|
157
190
|
"shamefully-hoist=false",
|
|
@@ -220,9 +253,9 @@ try {
|
|
|
220
253
|
step("Simulating refresh over a pre-existing snapshot (regression test for 0.1.7)...");
|
|
221
254
|
const fakeOld = join(work, "old-install");
|
|
222
255
|
mkdirSync(fakeOld);
|
|
223
|
-
|
|
256
|
+
writeFileSync(join(fakeOld, "tsconfig.base.json"), '{"old":"to-be-overwritten"}');
|
|
224
257
|
mkdirSync(join(fakeOld, "packages"), { recursive: true });
|
|
225
|
-
|
|
258
|
+
writeFileSync(
|
|
226
259
|
join(fakeOld, "packages", "preserved.txt"),
|
|
227
260
|
"must survive overlay refresh",
|
|
228
261
|
);
|
|
@@ -234,7 +267,7 @@ try {
|
|
|
234
267
|
const src = join(runtimeInTar, rel);
|
|
235
268
|
const dst = join(fakeOld, rel);
|
|
236
269
|
if (!existsSync(src)) continue;
|
|
237
|
-
const srcIsDir =
|
|
270
|
+
const srcIsDir = statSync(src).isDirectory();
|
|
238
271
|
if (srcIsDir && existsSync(dst)) {
|
|
239
272
|
run("cp", ["-a", `${src}/.`, `${dst}/`]);
|
|
240
273
|
} else {
|
|
@@ -243,12 +276,12 @@ try {
|
|
|
243
276
|
}
|
|
244
277
|
}
|
|
245
278
|
|
|
246
|
-
const tsStat =
|
|
279
|
+
const tsStat = statSync(join(fakeOld, "tsconfig.base.json"));
|
|
247
280
|
if (!tsStat.isFile()) {
|
|
248
281
|
fail("Refresh turned tsconfig.base.json into a non-file. cp branching is wrong.");
|
|
249
282
|
process.exit(1);
|
|
250
283
|
}
|
|
251
|
-
const tsContent =
|
|
284
|
+
const tsContent = readFileSync(join(fakeOld, "tsconfig.base.json"), "utf8");
|
|
252
285
|
if (tsContent.includes('"old":"to-be-overwritten"')) {
|
|
253
286
|
fail("Refresh failed to overwrite tsconfig.base.json with the bundle's version.");
|
|
254
287
|
process.exit(1);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "agenticros-
|
|
2
|
+
"name": "@agenticros-skills/{{slug}}",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "{{description}}",
|
|
@@ -15,8 +15,12 @@
|
|
|
15
15
|
"displayName": "{{displayName}}",
|
|
16
16
|
"description": "{{description}}",
|
|
17
17
|
"tutorial": false,
|
|
18
|
-
"categories": [
|
|
19
|
-
|
|
18
|
+
"categories": [
|
|
19
|
+
"vision"
|
|
20
|
+
],
|
|
21
|
+
"screenshots": [
|
|
22
|
+
"docs/icon.png"
|
|
23
|
+
],
|
|
20
24
|
"capabilities": [
|
|
21
25
|
{
|
|
22
26
|
"id": "{{toolName}}",
|
|
@@ -26,13 +30,20 @@
|
|
|
26
30
|
]
|
|
27
31
|
},
|
|
28
32
|
"dependencies": {
|
|
29
|
-
"@agenticros/core": "^0.
|
|
33
|
+
"@agenticros/core": "^0.8.0",
|
|
30
34
|
"@sinclair/typebox": "^0.34.0"
|
|
31
35
|
},
|
|
32
36
|
"devDependencies": {
|
|
33
37
|
"@types/node": "^20.17.0",
|
|
34
38
|
"typescript": "^5.7.0"
|
|
35
39
|
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
|
|
40
|
+
"keywords": [
|
|
41
|
+
"agenticros",
|
|
42
|
+
"camera",
|
|
43
|
+
"vision"
|
|
44
|
+
],
|
|
45
|
+
"license": "Apache-2.0",
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
}
|
|
38
49
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "agenticros-
|
|
2
|
+
"name": "@agenticros-skills/{{slug}}",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "{{description}}",
|
|
@@ -15,8 +15,13 @@
|
|
|
15
15
|
"displayName": "{{displayName}}",
|
|
16
16
|
"description": "{{description}}",
|
|
17
17
|
"tutorial": false,
|
|
18
|
-
"categories": [
|
|
19
|
-
|
|
18
|
+
"categories": [
|
|
19
|
+
"vision",
|
|
20
|
+
"telemetry"
|
|
21
|
+
],
|
|
22
|
+
"screenshots": [
|
|
23
|
+
"docs/icon.png"
|
|
24
|
+
],
|
|
20
25
|
"capabilities": [
|
|
21
26
|
{
|
|
22
27
|
"id": "{{toolName}}",
|
|
@@ -26,13 +31,20 @@
|
|
|
26
31
|
]
|
|
27
32
|
},
|
|
28
33
|
"dependencies": {
|
|
29
|
-
"@agenticros/core": "^0.
|
|
34
|
+
"@agenticros/core": "^0.8.0",
|
|
30
35
|
"@sinclair/typebox": "^0.34.0"
|
|
31
36
|
},
|
|
32
37
|
"devDependencies": {
|
|
33
38
|
"@types/node": "^20.17.0",
|
|
34
39
|
"typescript": "^5.7.0"
|
|
35
40
|
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
|
|
41
|
+
"keywords": [
|
|
42
|
+
"agenticros",
|
|
43
|
+
"depth",
|
|
44
|
+
"realsense"
|
|
45
|
+
],
|
|
46
|
+
"license": "Apache-2.0",
|
|
47
|
+
"publishConfig": {
|
|
48
|
+
"access": "public"
|
|
49
|
+
}
|
|
38
50
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "agenticros-
|
|
2
|
+
"name": "@agenticros-skills/{{slug}}",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "{{description}}",
|
|
@@ -15,8 +15,12 @@
|
|
|
15
15
|
"displayName": "{{displayName}}",
|
|
16
16
|
"description": "{{description}}",
|
|
17
17
|
"tutorial": true,
|
|
18
|
-
"categories": [
|
|
19
|
-
|
|
18
|
+
"categories": [
|
|
19
|
+
"communication"
|
|
20
|
+
],
|
|
21
|
+
"screenshots": [
|
|
22
|
+
"docs/icon.png"
|
|
23
|
+
],
|
|
20
24
|
"capabilities": [
|
|
21
25
|
{
|
|
22
26
|
"id": "{{toolName}}",
|
|
@@ -32,6 +36,13 @@
|
|
|
32
36
|
"@types/node": "^20.17.0",
|
|
33
37
|
"typescript": "^5.7.0"
|
|
34
38
|
},
|
|
35
|
-
"keywords": [
|
|
36
|
-
|
|
39
|
+
"keywords": [
|
|
40
|
+
"agenticros",
|
|
41
|
+
"tutorial",
|
|
42
|
+
"getting-started"
|
|
43
|
+
],
|
|
44
|
+
"license": "Apache-2.0",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
}
|
|
37
48
|
}
|