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.
Files changed (41) hide show
  1. package/dist/commands/publish-skill.d.ts.map +1 -1
  2. package/dist/commands/publish-skill.js +19 -0
  3. package/dist/commands/publish-skill.js.map +1 -1
  4. package/dist/commands/skills.d.ts +2 -0
  5. package/dist/commands/skills.d.ts.map +1 -1
  6. package/dist/commands/skills.js +150 -42
  7. package/dist/commands/skills.js.map +1 -1
  8. package/dist/index.js +2 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/util/marketplace.d.ts +2 -0
  11. package/dist/util/marketplace.d.ts.map +1 -1
  12. package/dist/util/marketplace.js.map +1 -1
  13. package/package.json +2 -2
  14. package/runtime/BUNDLE.json +1 -1
  15. package/runtime/docs/cli.md +2 -2
  16. package/runtime/packages/agenticros/src/tools/ros2-mission.ts +3 -2
  17. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts +2 -0
  18. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.d.ts.map +1 -1
  19. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js +14 -0
  20. package/runtime/packages/agenticros-claude-code/dist/find-object/find-object.js.map +1 -1
  21. package/runtime/packages/agenticros-claude-code/dist/tools.d.ts +3 -1
  22. package/runtime/packages/agenticros-claude-code/dist/tools.d.ts.map +1 -1
  23. package/runtime/packages/agenticros-claude-code/dist/tools.js +6 -4
  24. package/runtime/packages/agenticros-claude-code/dist/tools.js.map +1 -1
  25. package/runtime/packages/agenticros-claude-code/src/find-object/find-object.ts +16 -0
  26. package/runtime/packages/agenticros-claude-code/src/tools.ts +6 -3
  27. package/runtime/packages/agenticros-gemini/src/find-object/find-object.ts +16 -0
  28. package/runtime/packages/agenticros-gemini/src/tools.ts +5 -2
  29. package/runtime/packages/core/package.json +1 -1
  30. package/runtime/packages/core/src/__tests__/mission-retry-cancel.test.ts +165 -0
  31. package/runtime/packages/core/src/__tests__/skill-refs.test.ts +14 -0
  32. package/runtime/packages/core/src/external-capability.ts +67 -25
  33. package/runtime/packages/core/src/index.ts +3 -1
  34. package/runtime/packages/core/src/mission.ts +188 -31
  35. package/runtime/packages/core/src/skill-refs.ts +257 -30
  36. package/runtime/pnpm-lock.yaml +23 -2
  37. package/runtime/scripts/check-cli-tarball-install.mjs +41 -8
  38. package/templates/skills/camera/package.json +17 -6
  39. package/templates/skills/depth/package.json +18 -6
  40. package/templates/skills/hello/package.json +16 -5
  41. package/templates/skills/robot/package.json +18 -6
@@ -1,17 +1,29 @@
1
1
  /**
2
- * skillRefs → ~/.agenticros/skills-cache resolver (marketplace auto-fetch v1).
2
+ * skillRefs → ~/.agenticros/skills-cache resolver (marketplace auto-fetch).
3
3
  *
4
- * Declarative refs like `agenticros/navigate-to` or `owner/skill@main` are
5
- * resolved via the skills marketplace install API, cloned into the cache,
6
- * built if needed, and returned as absolute skillPaths for capability
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 { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
- import { homedir } from "node:os";
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
- /** owner/skill (lowercase) */
24
- marketplaceRef: string;
25
- owner: string;
26
- skill: string;
27
- /** git ref / branch pin; default main */
28
- gitRef: string;
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
- /** Parse `owner/skill` or `owner/skill@branch`. */
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(`Install descriptor for ${marketplaceRef} has no githubUrl`);
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 cachePathFor(
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(`Invalid skillRef "${rawRef}" (expected owner/skill or owner/skill@ref)`);
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 = cachePathFor(cacheRoot, parsed.owner, parsed.skill, parsed.gitRef);
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, opts.apiBase);
186
- const gitRef = parsed.gitRef !== "main" ? parsed.gitRef : descriptor.ref || "main";
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, parsed.skill), { recursive: true });
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, parsed.skill),
402
+ join(cacheRoot, parsed.owner!, parsed.skill!),
199
403
  log,
200
404
  );
201
405
  } catch {
202
- // Branch pin may be a tag or default branch name mismatch — full clone + checkout.
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
- const dir = cachePathFor(cacheRoot, parsed.owner, parsed.skill, parsed.gitRef);
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);
@@ -66,8 +66,8 @@ importers:
66
66
  packages/agenticros-cli:
67
67
  dependencies:
68
68
  '@agenticros/core':
69
- specifier: workspace:*
70
- version: link:../core
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 { existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync } from "node:fs";
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
- const fs = await import("node:fs");
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
- fs.writeFileSync(join(fakeOld, "tsconfig.base.json"), '{"old":"to-be-overwritten"}');
256
+ writeFileSync(join(fakeOld, "tsconfig.base.json"), '{"old":"to-be-overwritten"}');
224
257
  mkdirSync(join(fakeOld, "packages"), { recursive: true });
225
- fs.writeFileSync(
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 = fs.statSync(src).isDirectory();
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 = fs.statSync(join(fakeOld, "tsconfig.base.json"));
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 = fs.readFileSync(join(fakeOld, "tsconfig.base.json"), "utf8");
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-skill-{{slug}}",
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": ["vision"],
19
- "screenshots": ["docs/icon.png"],
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.6.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": ["agenticros", "camera", "vision"],
37
- "license": "Apache-2.0"
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-skill-{{slug}}",
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": ["vision", "telemetry"],
19
- "screenshots": ["docs/icon.png"],
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.6.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": ["agenticros", "depth", "realsense"],
37
- "license": "Apache-2.0"
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-skill-{{slug}}",
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": ["communication"],
19
- "screenshots": ["docs/icon.png"],
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": ["agenticros", "tutorial", "getting-started"],
36
- "license": "Apache-2.0"
39
+ "keywords": [
40
+ "agenticros",
41
+ "tutorial",
42
+ "getting-started"
43
+ ],
44
+ "license": "Apache-2.0",
45
+ "publishConfig": {
46
+ "access": "public"
47
+ }
37
48
  }