agentwheel 0.16.1 → 0.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.js +290 -176
- package/openpack.json +1 -1
- package/package.json +1 -1
- package/skills/agentwheel/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -189,6 +189,12 @@ agentwheel install mcp-registry:publisher/server-name --adapter claude --local
|
|
|
189
189
|
agentwheel install clawhub:@openclaw/whatsapp --adapter openclaw --local
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
+
### Private GitHub sources
|
|
193
|
+
|
|
194
|
+
OpenPack manifests stay portable and do not contain personal GitHub accounts or tokens. Configure
|
|
195
|
+
local `gh` accounts through a user-local auth profile; see [Git Authentication](docs/git-authentication.md)
|
|
196
|
+
for the configuration format and runtime behavior.
|
|
197
|
+
|
|
192
198
|
`mcp-registry:<server-name>` reads the public MCP Registry and stages a generated OpenPack package
|
|
193
199
|
only when the server exposes a safe unauthenticated `streamable-http` remote. Entries that require
|
|
194
200
|
secret headers or only publish native package instructions remain discovery-only until they are
|
package/dist/index.js
CHANGED
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
import { createHash as createHash12 } from "crypto";
|
|
13
13
|
import { existsSync } from "fs";
|
|
14
14
|
import { mkdir as mkdir23, rm as rm12, writeFile as writeFile22 } from "fs/promises";
|
|
15
|
-
import { homedir as
|
|
16
|
-
import { dirname as dirname32, join as
|
|
15
|
+
import { homedir as homedir11 } from "os";
|
|
16
|
+
import { dirname as dirname32, join as join46, resolve as resolve22 } from "path";
|
|
17
17
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
18
18
|
import { Command } from "commander";
|
|
19
19
|
|
|
@@ -941,6 +941,9 @@ function mergeOpenClawJson(base, incoming, path = []) {
|
|
|
941
941
|
if (path.join(".") === "agents.list" && Array.isArray(base) && Array.isArray(incoming)) {
|
|
942
942
|
return mergeOpenClawAgentsById(base, incoming);
|
|
943
943
|
}
|
|
944
|
+
if (isAgentwheelSkillRouterRepositoriesPath(path) && Array.isArray(base) && Array.isArray(incoming)) {
|
|
945
|
+
return mergeOpenClawRecordsByKey(base, incoming, "name");
|
|
946
|
+
}
|
|
944
947
|
if (Array.isArray(base) && Array.isArray(incoming)) {
|
|
945
948
|
return deepMerge(base, incoming);
|
|
946
949
|
}
|
|
@@ -956,6 +959,9 @@ function mergeOpenClawJson(base, incoming, path = []) {
|
|
|
956
959
|
function isMcpServerCodexAgentsPath(path) {
|
|
957
960
|
return path.length === 5 && path[0] === "mcp" && path[1] === "servers" && path[3] === "codex" && path[4] === "agents";
|
|
958
961
|
}
|
|
962
|
+
function isAgentwheelSkillRouterRepositoriesPath(path) {
|
|
963
|
+
return path.join(".") === "plugins.entries.agentwheel-skill-router.config.repositories";
|
|
964
|
+
}
|
|
959
965
|
function expandEnvPlaceholders(value, sourcePath) {
|
|
960
966
|
if (typeof value === "string") {
|
|
961
967
|
return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => {
|
|
@@ -1011,6 +1017,35 @@ function mergeOpenClawAgentsById(base, incoming) {
|
|
|
1011
1017
|
}
|
|
1012
1018
|
return out;
|
|
1013
1019
|
}
|
|
1020
|
+
function mergeOpenClawRecordsByKey(base, incoming, key) {
|
|
1021
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
1022
|
+
for (const value of incoming) {
|
|
1023
|
+
const recordKey = isRecord(value) && typeof value[key] === "string" ? value[key] : void 0;
|
|
1024
|
+
if (recordKey) replacements.set(recordKey, value);
|
|
1025
|
+
}
|
|
1026
|
+
const out = [];
|
|
1027
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
1028
|
+
for (const value of base) {
|
|
1029
|
+
const recordKey = isRecord(value) && typeof value[key] === "string" ? value[key] : void 0;
|
|
1030
|
+
const replacement = recordKey ? replacements.get(recordKey) : void 0;
|
|
1031
|
+
if (!recordKey || !replacement) {
|
|
1032
|
+
out.push(value);
|
|
1033
|
+
continue;
|
|
1034
|
+
}
|
|
1035
|
+
if (!emitted.has(recordKey)) {
|
|
1036
|
+
out.push(replacement);
|
|
1037
|
+
emitted.add(recordKey);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
for (const value of incoming) {
|
|
1041
|
+
const recordKey = isRecord(value) && typeof value[key] === "string" ? value[key] : void 0;
|
|
1042
|
+
if (!recordKey || !emitted.has(recordKey)) {
|
|
1043
|
+
out.push(value);
|
|
1044
|
+
if (recordKey) emitted.add(recordKey);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
return out;
|
|
1048
|
+
}
|
|
1014
1049
|
|
|
1015
1050
|
// src/install/manifest.ts
|
|
1016
1051
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -5915,9 +5950,80 @@ function cachePathFor(packageName, cacheRoot) {
|
|
|
5915
5950
|
// src/source/git.ts
|
|
5916
5951
|
import { execFile as execFile4 } from "child_process";
|
|
5917
5952
|
import { cp as cp2, mkdir as mkdir13, rename as rename3, rm as rm6, writeFile as writeFile15 } from "fs/promises";
|
|
5918
|
-
import { homedir as
|
|
5919
|
-
import { basename as basename11, dirname as dirname16, join as
|
|
5953
|
+
import { homedir as homedir3 } from "os";
|
|
5954
|
+
import { basename as basename11, dirname as dirname16, join as join22, resolve as resolve7 } from "path";
|
|
5920
5955
|
import { promisify as promisify4 } from "util";
|
|
5956
|
+
|
|
5957
|
+
// src/source/auth.ts
|
|
5958
|
+
import { readFile as readFile18 } from "fs/promises";
|
|
5959
|
+
import { homedir as homedir2 } from "os";
|
|
5960
|
+
import { join as join21 } from "path";
|
|
5961
|
+
var AUTH_CONFIG_ENV = "AGENTWHEEL_AUTH_CONFIG";
|
|
5962
|
+
async function gitAuthArguments(url) {
|
|
5963
|
+
const profile = await matchingGitAuthProfile(url);
|
|
5964
|
+
if (!profile) return [];
|
|
5965
|
+
if (profile.provider !== "gh") {
|
|
5966
|
+
throw new Error(`Unsupported Agentwheel Git auth provider: ${profile.provider}`);
|
|
5967
|
+
}
|
|
5968
|
+
const account = shellQuote(profile.account);
|
|
5969
|
+
const helper = `!f() { echo username=x-access-token; echo password="$(gh auth token --user ${account})"; }; f`;
|
|
5970
|
+
return ["-c", "credential.helper=", "-c", `credential.helper=${helper}`];
|
|
5971
|
+
}
|
|
5972
|
+
async function matchingGitAuthProfile(url) {
|
|
5973
|
+
const config = await readGitAuthConfig();
|
|
5974
|
+
if (!config) return void 0;
|
|
5975
|
+
const repository = repositoryKey(url);
|
|
5976
|
+
return Object.values(config.profiles).find(
|
|
5977
|
+
(profile) => profile.repositories.some((pattern) => matchesRepository(pattern, repository))
|
|
5978
|
+
);
|
|
5979
|
+
}
|
|
5980
|
+
async function readGitAuthConfig() {
|
|
5981
|
+
const path = process.env[AUTH_CONFIG_ENV] ?? join21(homedir2(), ".agentwheel", "auth.json");
|
|
5982
|
+
try {
|
|
5983
|
+
const parsed = JSON.parse(await readFile18(path, "utf8"));
|
|
5984
|
+
return parseGitAuthConfig(parsed, path);
|
|
5985
|
+
} catch (error) {
|
|
5986
|
+
if (isMissingFile(error)) return void 0;
|
|
5987
|
+
if (error instanceof SyntaxError) throw new Error(`Invalid Agentwheel auth config JSON: ${path}`);
|
|
5988
|
+
throw error;
|
|
5989
|
+
}
|
|
5990
|
+
}
|
|
5991
|
+
function parseGitAuthConfig(value, path) {
|
|
5992
|
+
if (!isRecord8(value) || !isRecord8(value.profiles)) {
|
|
5993
|
+
throw new Error(`Invalid Agentwheel auth config: expected profiles in ${path}`);
|
|
5994
|
+
}
|
|
5995
|
+
const profiles = {};
|
|
5996
|
+
for (const [name, candidate] of Object.entries(value.profiles)) {
|
|
5997
|
+
if (!isRecord8(candidate) || candidate.provider !== "gh" || typeof candidate.account !== "string" || !Array.isArray(candidate.repositories)) {
|
|
5998
|
+
throw new Error(`Invalid Agentwheel auth profile '${name}' in ${path}`);
|
|
5999
|
+
}
|
|
6000
|
+
const repositories = candidate.repositories.filter((repository) => typeof repository === "string" && repository.length > 0);
|
|
6001
|
+
if (repositories.length !== candidate.repositories.length) {
|
|
6002
|
+
throw new Error(`Invalid repository matcher in Agentwheel auth profile '${name}' in ${path}`);
|
|
6003
|
+
}
|
|
6004
|
+
profiles[name] = { provider: "gh", account: candidate.account, repositories };
|
|
6005
|
+
}
|
|
6006
|
+
return { profiles };
|
|
6007
|
+
}
|
|
6008
|
+
function repositoryKey(url) {
|
|
6009
|
+
const parsed = new URL(url);
|
|
6010
|
+
return `${parsed.host}/${parsed.pathname.replace(/^\//, "").replace(/\.git$/, "")}`.toLowerCase();
|
|
6011
|
+
}
|
|
6012
|
+
function matchesRepository(pattern, repository) {
|
|
6013
|
+
const escaped = pattern.toLowerCase().replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
6014
|
+
return new RegExp(`^${escaped}$`).test(repository);
|
|
6015
|
+
}
|
|
6016
|
+
function shellQuote(value) {
|
|
6017
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
6018
|
+
}
|
|
6019
|
+
function isRecord8(value) {
|
|
6020
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6021
|
+
}
|
|
6022
|
+
function isMissingFile(error) {
|
|
6023
|
+
return isRecord8(error) && error.code === "ENOENT";
|
|
6024
|
+
}
|
|
6025
|
+
|
|
6026
|
+
// src/source/git.ts
|
|
5921
6027
|
var execFileAsync4 = promisify4(execFile4);
|
|
5922
6028
|
var GitSourceDriver = class {
|
|
5923
6029
|
name = "git";
|
|
@@ -5940,14 +6046,22 @@ var GitSourceDriver = class {
|
|
|
5940
6046
|
return withFilesystemLock(`${resolved.resolvedPath}.lock`, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
|
|
5941
6047
|
const parsed = parseGitSource(resolved.source);
|
|
5942
6048
|
await mkdir13(resolve7(resolved.resolvedPath, ".."), { recursive: true });
|
|
5943
|
-
if (!await pathExists(
|
|
6049
|
+
if (!await pathExists(join22(resolved.resolvedPath, ".git"))) {
|
|
5944
6050
|
if (resolved.frozenLock) {
|
|
5945
6051
|
throw new Error(`Frozen lock requires cached git checkout at ${resolved.resolvedPath}`);
|
|
5946
6052
|
}
|
|
5947
6053
|
await rm6(resolved.resolvedPath, { recursive: true, force: true });
|
|
5948
|
-
await git(["clone", parsed.url, resolved.resolvedPath]);
|
|
6054
|
+
await git([...await gitAuthArguments(parsed.url), "clone", parsed.url, resolved.resolvedPath]);
|
|
5949
6055
|
} else if (!resolved.frozenLock) {
|
|
5950
|
-
await git([
|
|
6056
|
+
await git([
|
|
6057
|
+
...await gitAuthArguments(parsed.url),
|
|
6058
|
+
"-C",
|
|
6059
|
+
resolved.resolvedPath,
|
|
6060
|
+
"fetch",
|
|
6061
|
+
"--tags",
|
|
6062
|
+
"--prune",
|
|
6063
|
+
"origin"
|
|
6064
|
+
]);
|
|
5951
6065
|
}
|
|
5952
6066
|
const ref = resolved.requestedRef ?? parsed.ref ?? "HEAD";
|
|
5953
6067
|
if (ref === "HEAD") {
|
|
@@ -6007,20 +6121,20 @@ function parseGitSource(source) {
|
|
|
6007
6121
|
throw new Error(`Invalid git source: ${source}`);
|
|
6008
6122
|
}
|
|
6009
6123
|
function cachePathFor2(url, cacheRoot) {
|
|
6010
|
-
const root = cacheRoot ? resolve7(cacheRoot) :
|
|
6124
|
+
const root = cacheRoot ? resolve7(cacheRoot) : join22(homedir3(), ".agentwheel", "cache");
|
|
6011
6125
|
const slug2 = url.replace(/^[a-z]+:\/\//i, "").replace(/\.git$/i, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "");
|
|
6012
|
-
return
|
|
6126
|
+
return join22(root, slug2 || basename11(url));
|
|
6013
6127
|
}
|
|
6014
6128
|
async function git(args) {
|
|
6015
6129
|
return execFileAsync4("git", args, { maxBuffer: 1024 * 1024 * 10 });
|
|
6016
6130
|
}
|
|
6017
6131
|
async function snapshotCheckout(checkoutPath, commit) {
|
|
6018
|
-
const snapshotPath =
|
|
6132
|
+
const snapshotPath = join22(dirname16(checkoutPath), `${basename11(checkoutPath)}-${commit.slice(0, 12)}`);
|
|
6019
6133
|
if (await pathExists(snapshotPath)) return snapshotPath;
|
|
6020
|
-
const tempPath =
|
|
6134
|
+
const tempPath = join22(dirname16(checkoutPath), `${basename11(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
|
|
6021
6135
|
await rm6(tempPath, { recursive: true, force: true });
|
|
6022
6136
|
await cp2(checkoutPath, tempPath, { recursive: true, dereference: true });
|
|
6023
|
-
await rm6(
|
|
6137
|
+
await rm6(join22(tempPath, ".git"), { recursive: true, force: true });
|
|
6024
6138
|
try {
|
|
6025
6139
|
await rename3(tempPath, snapshotPath);
|
|
6026
6140
|
} catch (error) {
|
|
@@ -6036,7 +6150,7 @@ async function withFilesystemLock(lockPath, timeoutMs, fn) {
|
|
|
6036
6150
|
while (true) {
|
|
6037
6151
|
try {
|
|
6038
6152
|
await mkdir13(lockPath);
|
|
6039
|
-
await writeFile15(
|
|
6153
|
+
await writeFile15(join22(lockPath, "owner.json"), JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
|
|
6040
6154
|
break;
|
|
6041
6155
|
} catch (error) {
|
|
6042
6156
|
if (!isAlreadyExists2(error)) throw error;
|
|
@@ -6058,7 +6172,7 @@ function isAlreadyExists2(error) {
|
|
|
6058
6172
|
|
|
6059
6173
|
// src/source/mcp-registry.ts
|
|
6060
6174
|
import { mkdir as mkdir14, writeFile as writeFile16 } from "fs/promises";
|
|
6061
|
-
import { basename as basename12, dirname as dirname17, join as
|
|
6175
|
+
import { basename as basename12, dirname as dirname17, join as join23, resolve as resolve8 } from "path";
|
|
6062
6176
|
var registryBaseUrl = "https://registry.modelcontextprotocol.io/v0.1";
|
|
6063
6177
|
var sourcePrefix2 = "mcp-registry:";
|
|
6064
6178
|
var McpRegistrySourceDriver = class {
|
|
@@ -6124,7 +6238,7 @@ var McpRegistrySourceDriver = class {
|
|
|
6124
6238
|
return this.local.list({ ...resolved, driver: "local" });
|
|
6125
6239
|
}
|
|
6126
6240
|
async scan(resolved) {
|
|
6127
|
-
if (!await pathExists(
|
|
6241
|
+
if (!await pathExists(join23(resolved.resolvedPath, "mcp"))) {
|
|
6128
6242
|
return { ok: false, findings: [{ level: "error", message: "MCP registry source has no generated mcp artifact" }] };
|
|
6129
6243
|
}
|
|
6130
6244
|
return { ok: true, findings: [] };
|
|
@@ -6164,9 +6278,9 @@ function isSafeHttpUrl(value) {
|
|
|
6164
6278
|
}
|
|
6165
6279
|
async function writeGeneratedPackage2(root, server) {
|
|
6166
6280
|
const serverId = installNameFor3(server.serverName);
|
|
6167
|
-
const mcpPath =
|
|
6281
|
+
const mcpPath = join23(root, "mcp", `${serverId}.json`);
|
|
6168
6282
|
await mkdir14(dirname17(mcpPath), { recursive: true });
|
|
6169
|
-
await writeFile16(
|
|
6283
|
+
await writeFile16(join23(root, "openpack.json"), `${JSON.stringify({
|
|
6170
6284
|
schemaVersion: 2,
|
|
6171
6285
|
name: `mcp-registry/${server.serverName}`,
|
|
6172
6286
|
version: server.version ?? "latest",
|
|
@@ -6187,20 +6301,20 @@ function installNameFor3(serverName) {
|
|
|
6187
6301
|
return basename12(serverName).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "mcp-server";
|
|
6188
6302
|
}
|
|
6189
6303
|
function cachePathFor3(serverName, cacheRoot) {
|
|
6190
|
-
const root = cacheRoot ? resolve8(cacheRoot) :
|
|
6304
|
+
const root = cacheRoot ? resolve8(cacheRoot) : join23(process.env.HOME ?? ".", ".agentwheel", "cache");
|
|
6191
6305
|
const slug2 = `mcp-registry-${serverName}`.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "");
|
|
6192
|
-
return
|
|
6306
|
+
return join23(root, slug2 || "mcp-registry-server");
|
|
6193
6307
|
}
|
|
6194
6308
|
|
|
6195
6309
|
// src/source/skillkit.ts
|
|
6196
|
-
import { cp as cp3, mkdir as mkdir15, readFile as
|
|
6197
|
-
import { homedir as
|
|
6198
|
-
import { basename as basename14, dirname as dirname19, join as
|
|
6310
|
+
import { cp as cp3, mkdir as mkdir15, readFile as readFile19, rm as rm7 } from "fs/promises";
|
|
6311
|
+
import { homedir as homedir4 } from "os";
|
|
6312
|
+
import { basename as basename14, dirname as dirname19, join as join25, resolve as resolve9 } from "path";
|
|
6199
6313
|
import * as defaultSkillKit from "@skillkit/core";
|
|
6200
6314
|
|
|
6201
6315
|
// src/source/skill-artifacts.ts
|
|
6202
6316
|
import { readdir as readdir2, stat as stat4 } from "fs/promises";
|
|
6203
|
-
import { basename as basename13, dirname as dirname18, extname as extname2, join as
|
|
6317
|
+
import { basename as basename13, dirname as dirname18, extname as extname2, join as join24 } from "path";
|
|
6204
6318
|
async function artifactsFromSkillPaths(paths, packageName) {
|
|
6205
6319
|
const artifacts = [];
|
|
6206
6320
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -6222,14 +6336,14 @@ async function discoverSkillPaths(root) {
|
|
|
6222
6336
|
async function artifactFromSkillPath(item, packageName) {
|
|
6223
6337
|
const stats = await stat4(item.path);
|
|
6224
6338
|
if (stats.isDirectory()) {
|
|
6225
|
-
const skillMd =
|
|
6339
|
+
const skillMd = join24(item.path, "SKILL.md");
|
|
6226
6340
|
if (!await pathExists(skillMd)) return void 0;
|
|
6227
6341
|
const name = sanitizeSkillName(item.name ?? basename13(item.path));
|
|
6228
6342
|
return {
|
|
6229
6343
|
type: "skills",
|
|
6230
6344
|
name,
|
|
6231
6345
|
sourcePath: item.path,
|
|
6232
|
-
relativePath:
|
|
6346
|
+
relativePath: join24("skills", name),
|
|
6233
6347
|
kind: "dir",
|
|
6234
6348
|
hash: await hashPath(item.path),
|
|
6235
6349
|
packageName,
|
|
@@ -6243,7 +6357,7 @@ async function artifactFromSkillPath(item, packageName) {
|
|
|
6243
6357
|
type: "skills",
|
|
6244
6358
|
name,
|
|
6245
6359
|
sourcePath: dir,
|
|
6246
|
-
relativePath:
|
|
6360
|
+
relativePath: join24("skills", name),
|
|
6247
6361
|
kind: "dir",
|
|
6248
6362
|
hash: await hashPath(dir),
|
|
6249
6363
|
packageName,
|
|
@@ -6256,7 +6370,7 @@ async function artifactFromSkillPath(item, packageName) {
|
|
|
6256
6370
|
type: "skills",
|
|
6257
6371
|
name,
|
|
6258
6372
|
sourcePath: item.path,
|
|
6259
|
-
relativePath:
|
|
6373
|
+
relativePath: join24("skills", `${name}.md`),
|
|
6260
6374
|
kind: "file",
|
|
6261
6375
|
hash: await hashPath(item.path),
|
|
6262
6376
|
packageName,
|
|
@@ -6274,7 +6388,7 @@ async function walk(dir, paths) {
|
|
|
6274
6388
|
}
|
|
6275
6389
|
for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6276
6390
|
if (!entry.isDirectory() || entry.name === ".git" || entry.name === "node_modules") continue;
|
|
6277
|
-
await walk(
|
|
6391
|
+
await walk(join24(dir, entry.name), paths);
|
|
6278
6392
|
}
|
|
6279
6393
|
}
|
|
6280
6394
|
function sanitizeSkillName(name) {
|
|
@@ -6374,9 +6488,9 @@ var SkillKitSourceDriver = class {
|
|
|
6374
6488
|
throw new Error("SkillKit translateSkill API unavailable");
|
|
6375
6489
|
}
|
|
6376
6490
|
for (const skill of this.discover(resolved.resolvedPath)) {
|
|
6377
|
-
const skillMd =
|
|
6491
|
+
const skillMd = join25(skill.path, "SKILL.md");
|
|
6378
6492
|
if (await pathExists(skillMd)) {
|
|
6379
|
-
this.core.translateSkill(await
|
|
6493
|
+
this.core.translateSkill(await readFile19(skillMd, "utf8"), "openclaw", { sourceFilename: "SKILL.md" });
|
|
6380
6494
|
}
|
|
6381
6495
|
}
|
|
6382
6496
|
return resolved;
|
|
@@ -6405,8 +6519,8 @@ function normalizeProviderSource(spec) {
|
|
|
6405
6519
|
return spec;
|
|
6406
6520
|
}
|
|
6407
6521
|
function cachePathFor4(spec, cacheRoot) {
|
|
6408
|
-
const root = cacheRoot ? resolve9(cacheRoot) :
|
|
6409
|
-
return
|
|
6522
|
+
const root = cacheRoot ? resolve9(cacheRoot) : join25(homedir4(), ".agentwheel", "cache");
|
|
6523
|
+
return join25(root, "skillkit", packageSlug(spec));
|
|
6410
6524
|
}
|
|
6411
6525
|
function packageSlug(spec) {
|
|
6412
6526
|
return spec.replace(/^[a-z]+:\/\//i, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "source";
|
|
@@ -6419,7 +6533,7 @@ function mapSeverity(severity) {
|
|
|
6419
6533
|
|
|
6420
6534
|
// src/source/vercel-skills.ts
|
|
6421
6535
|
import { stat as stat5 } from "fs/promises";
|
|
6422
|
-
import { basename as basename15, join as
|
|
6536
|
+
import { basename as basename15, join as join26, relative as relative5, resolve as resolve10 } from "path";
|
|
6423
6537
|
var VercelSkillsSourceDriver = class {
|
|
6424
6538
|
name = "vercel-skills";
|
|
6425
6539
|
git = new GitSourceDriver();
|
|
@@ -6482,7 +6596,7 @@ var VercelSkillsSourceDriver = class {
|
|
|
6482
6596
|
};
|
|
6483
6597
|
async function resolveVercelSkillSubpath(root, subpath) {
|
|
6484
6598
|
if (!subpath) return root;
|
|
6485
|
-
const candidates = [
|
|
6599
|
+
const candidates = [join26(root, subpath), join26(root, "skills", subpath)];
|
|
6486
6600
|
for (const candidate of candidates) {
|
|
6487
6601
|
if (await pathExists(candidate)) return candidate;
|
|
6488
6602
|
}
|
|
@@ -6553,13 +6667,13 @@ function getSourceDriver(name = "local") {
|
|
|
6553
6667
|
|
|
6554
6668
|
// src/staging/staging.ts
|
|
6555
6669
|
import { chmod, cp as cp5, mkdir as mkdir18, mkdtemp as mkdtemp3, readdir as readdir5, stat as stat8 } from "fs/promises";
|
|
6556
|
-
import { basename as basename19, dirname as dirname23, join as
|
|
6670
|
+
import { basename as basename19, dirname as dirname23, join as join30, relative as relative7, resolve as resolve12, sep as sep2 } from "path";
|
|
6557
6671
|
import { tmpdir as tmpdir4 } from "os";
|
|
6558
6672
|
|
|
6559
6673
|
// src/compose/markdown.ts
|
|
6560
6674
|
import { createHash as createHash6 } from "crypto";
|
|
6561
|
-
import { readdir as readdir3, readFile as
|
|
6562
|
-
import { basename as basename16, dirname as dirname20, extname as extname3, join as
|
|
6675
|
+
import { readdir as readdir3, readFile as readFile20, stat as stat6, writeFile as writeFile17 } from "fs/promises";
|
|
6676
|
+
import { basename as basename16, dirname as dirname20, extname as extname3, join as join27, relative as relative6, resolve as resolve11, sep } from "path";
|
|
6563
6677
|
var includePattern = /<!--\s*openpack:include(\?)?\s+([^>]+?)\s*-->/g;
|
|
6564
6678
|
var escapedIncludePattern = /<!--\s*openpack\\:include(\?)?\s+([^>]+?)\s*-->/g;
|
|
6565
6679
|
var generatedPattern = /<!--\s*(?:BEGIN|END)\s+openpack:include\b/;
|
|
@@ -6597,7 +6711,7 @@ async function validateMarkdownIncludes(artifacts, packageRoot, options = {}) {
|
|
|
6597
6711
|
}
|
|
6598
6712
|
}
|
|
6599
6713
|
async function expandFile(file, packageRoot, appendEntries, artifactPaths, options) {
|
|
6600
|
-
const raw = await
|
|
6714
|
+
const raw = await readFile20(file, "utf8");
|
|
6601
6715
|
const owner = ownerSelector(packageRoot, file, options.nodeId);
|
|
6602
6716
|
const expanded = await expandContent(raw, packageRoot, [owner], artifactPaths, options);
|
|
6603
6717
|
let content = expanded.content;
|
|
@@ -6690,7 +6804,7 @@ async function expandInclude(selector, packageRoot, artifactPaths, options) {
|
|
|
6690
6804
|
if (!stats.isFile()) {
|
|
6691
6805
|
throw new Error(`OpenPack include is not a file: ${displaySelector}`);
|
|
6692
6806
|
}
|
|
6693
|
-
const raw = sourceContent ?? await
|
|
6807
|
+
const raw = sourceContent ?? await readFile20(sourcePath, "utf8");
|
|
6694
6808
|
const { optional: _optional, markers: _markers, chain: _chain, ...childOptions } = options;
|
|
6695
6809
|
const expanded = await expandContent(raw, includePackageRoot, [...options.chain, displaySelector], includeArtifactPaths, {
|
|
6696
6810
|
...childOptions,
|
|
@@ -6766,7 +6880,7 @@ async function listMarkdownFiles(root) {
|
|
|
6766
6880
|
const out = [];
|
|
6767
6881
|
async function walk2(dir) {
|
|
6768
6882
|
for (const entry of (await readdir3(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
6769
|
-
const full =
|
|
6883
|
+
const full = join27(dir, entry.name);
|
|
6770
6884
|
if (entry.isDirectory()) {
|
|
6771
6885
|
await walk2(full);
|
|
6772
6886
|
} else if (entry.isFile() && extname3(entry.name).toLowerCase() === ".md") {
|
|
@@ -6826,8 +6940,8 @@ function artifactPathMap(artifacts) {
|
|
|
6826
6940
|
}
|
|
6827
6941
|
|
|
6828
6942
|
// src/staging/customize.ts
|
|
6829
|
-
import { cp as cp4, mkdir as mkdir16, readdir as readdir4, readFile as
|
|
6830
|
-
import { dirname as dirname21, join as
|
|
6943
|
+
import { cp as cp4, mkdir as mkdir16, readdir as readdir4, readFile as readFile21, writeFile as writeFile18 } from "fs/promises";
|
|
6944
|
+
import { dirname as dirname21, join as join28 } from "path";
|
|
6831
6945
|
async function applyCustomizations(artifacts, options) {
|
|
6832
6946
|
let next = [...artifacts];
|
|
6833
6947
|
next = await applyReplacements2(next, options, "override", installableArtifactTypes());
|
|
@@ -6843,14 +6957,14 @@ async function applyFragmentCustomizations(artifacts, options) {
|
|
|
6843
6957
|
return next.sort((a, b) => `${a.type}:${a.name}:${a.channel}`.localeCompare(`${b.type}:${b.name}:${b.channel}`));
|
|
6844
6958
|
}
|
|
6845
6959
|
async function applyInstructionOverlay(artifacts, options) {
|
|
6846
|
-
const overlayPath =
|
|
6960
|
+
const overlayPath = join28(options.workspaceRoot, ".agentwheel", "overlays", options.adapter.name, "instructions.local.md");
|
|
6847
6961
|
if (!await pathExists(overlayPath)) return artifacts;
|
|
6848
6962
|
const index = artifacts.findIndex((artifact2) => artifact2.type === "instructions");
|
|
6849
6963
|
if (index < 0) return artifacts;
|
|
6850
6964
|
const artifact = artifacts[index];
|
|
6851
|
-
const managed = await
|
|
6852
|
-
const local = await
|
|
6853
|
-
const composedPath =
|
|
6965
|
+
const managed = await readFile21(artifact.stagedPath ?? artifact.sourcePath, "utf8");
|
|
6966
|
+
const local = await readFile21(overlayPath, "utf8");
|
|
6967
|
+
const composedPath = join28(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
|
|
6854
6968
|
await mkdir16(dirname21(composedPath), { recursive: true });
|
|
6855
6969
|
await writeFile18(
|
|
6856
6970
|
composedPath,
|
|
@@ -6878,19 +6992,19 @@ async function applyInstructionOverlay(artifacts, options) {
|
|
|
6878
6992
|
return [...artifacts.slice(0, index), updated, ...artifacts.slice(index + 1)];
|
|
6879
6993
|
}
|
|
6880
6994
|
async function applyAdditions(artifacts, options) {
|
|
6881
|
-
const additionsRoot =
|
|
6882
|
-
const rulesRoot =
|
|
6995
|
+
const additionsRoot = join28(options.workspaceRoot, ".agentwheel", "additions");
|
|
6996
|
+
const rulesRoot = join28(additionsRoot, "rules");
|
|
6883
6997
|
if (!await pathExists(rulesRoot)) return artifacts;
|
|
6884
6998
|
const additions = [];
|
|
6885
6999
|
for (const entry of await sortedDirEntries2(rulesRoot)) {
|
|
6886
|
-
const full =
|
|
7000
|
+
const full = join28(rulesRoot, entry.name);
|
|
6887
7001
|
if (!entry.isFile()) continue;
|
|
6888
7002
|
additions.push({
|
|
6889
7003
|
type: "rules",
|
|
6890
7004
|
name: entry.name,
|
|
6891
7005
|
sourcePath: full,
|
|
6892
7006
|
stagedPath: full,
|
|
6893
|
-
relativePath:
|
|
7007
|
+
relativePath: join28("additions", "rules", entry.name),
|
|
6894
7008
|
kind: "file",
|
|
6895
7009
|
hash: await hashPath(full),
|
|
6896
7010
|
packageName: options.packageName,
|
|
@@ -6914,16 +7028,16 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
|
|
|
6914
7028
|
);
|
|
6915
7029
|
}
|
|
6916
7030
|
for (const type of artifactTypes) {
|
|
6917
|
-
const typeRoot =
|
|
7031
|
+
const typeRoot = join28(root, type);
|
|
6918
7032
|
if (!await pathExists(typeRoot)) continue;
|
|
6919
7033
|
for (const entry of await sortedDirEntries2(typeRoot)) {
|
|
6920
7034
|
const artifactMapKey = `${type}:${entry.name}`;
|
|
6921
7035
|
if (seen.has(artifactMapKey)) continue;
|
|
6922
7036
|
seen.add(artifactMapKey);
|
|
6923
|
-
const full =
|
|
7037
|
+
const full = join28(typeRoot, entry.name);
|
|
6924
7038
|
const artifactKind = entry.isDirectory() ? "dir" : "file";
|
|
6925
7039
|
const existing = byKey.get(artifactMapKey);
|
|
6926
|
-
const stagedPath =
|
|
7040
|
+
const stagedPath = join28(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
|
|
6927
7041
|
await mkdir16(dirname21(stagedPath), { recursive: true });
|
|
6928
7042
|
await cp4(full, stagedPath, { recursive: artifactKind === "dir", dereference: true });
|
|
6929
7043
|
byKey.set(artifactMapKey, {
|
|
@@ -6932,7 +7046,7 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
|
|
|
6932
7046
|
name: entry.name,
|
|
6933
7047
|
sourcePath: full,
|
|
6934
7048
|
stagedPath,
|
|
6935
|
-
relativePath: existing?.relativePath ??
|
|
7049
|
+
relativePath: existing?.relativePath ?? join28(type, entry.name),
|
|
6936
7050
|
kind: artifactKind,
|
|
6937
7051
|
hash: await hashPath(stagedPath),
|
|
6938
7052
|
packageName,
|
|
@@ -6947,13 +7061,13 @@ function replacementRoots(options, channel) {
|
|
|
6947
7061
|
const stateDir = channel === "override" ? "overrides" : "ejected";
|
|
6948
7062
|
const roots = [];
|
|
6949
7063
|
if (options.graphNodeId) {
|
|
6950
|
-
roots.push({ root:
|
|
7064
|
+
roots.push({ root: join28(options.workspaceRoot, ".agentwheel", stateDir, ...options.graphNodeId.split("/")), kind: "node" });
|
|
6951
7065
|
}
|
|
6952
7066
|
if (options.packageName && options.packageVersion) {
|
|
6953
|
-
roots.push({ root:
|
|
7067
|
+
roots.push({ root: join28(options.workspaceRoot, ".agentwheel", stateDir, ...`${options.packageName}@${options.packageVersion}`.split("/")), kind: "version" });
|
|
6954
7068
|
}
|
|
6955
7069
|
if (options.packageName) {
|
|
6956
|
-
roots.push({ root:
|
|
7070
|
+
roots.push({ root: join28(options.workspaceRoot, ".agentwheel", stateDir, ...options.packageName.split("/")), kind: "package" });
|
|
6957
7071
|
}
|
|
6958
7072
|
return roots;
|
|
6959
7073
|
}
|
|
@@ -6968,8 +7082,8 @@ async function sortedDirEntries2(path) {
|
|
|
6968
7082
|
}
|
|
6969
7083
|
|
|
6970
7084
|
// src/staging/claude-subagents.ts
|
|
6971
|
-
import { mkdir as mkdir17, readFile as
|
|
6972
|
-
import { basename as basename18, dirname as dirname22, join as
|
|
7085
|
+
import { mkdir as mkdir17, readFile as readFile22, writeFile as writeFile19 } from "fs/promises";
|
|
7086
|
+
import { basename as basename18, dirname as dirname22, join as join29 } from "path";
|
|
6973
7087
|
async function renderClaudeSubagents(artifacts, stageRoot, adapter) {
|
|
6974
7088
|
if (adapter?.name !== "claude") return artifacts;
|
|
6975
7089
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -6991,15 +7105,15 @@ async function renderClaudeSubagents(artifacts, stageRoot, adapter) {
|
|
|
6991
7105
|
async function renderClaudeSubagent(artifact, stageRoot) {
|
|
6992
7106
|
const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
|
|
6993
7107
|
const agentName = claudeAgentName(artifact);
|
|
6994
|
-
const markdownPath = artifact.kind === "dir" ?
|
|
7108
|
+
const markdownPath = artifact.kind === "dir" ? join29(sourcePath, "AGENTS.md") : sourcePath;
|
|
6995
7109
|
if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
|
|
6996
7110
|
throw new Error(`Claude subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
|
|
6997
7111
|
}
|
|
6998
7112
|
if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !sourcePath.toLowerCase().endsWith(".md")) {
|
|
6999
7113
|
throw new Error(`Claude subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
|
|
7000
7114
|
}
|
|
7001
|
-
const content = await
|
|
7002
|
-
const renderedPath =
|
|
7115
|
+
const content = await readFile22(markdownPath, "utf8");
|
|
7116
|
+
const renderedPath = join29(stageRoot, ".agentwheel-rendered", "claude-subagents", `${agentName}.md`);
|
|
7003
7117
|
await mkdir17(dirname22(renderedPath), { recursive: true });
|
|
7004
7118
|
await writeFile19(renderedPath, content.endsWith("\n") ? content : `${content}
|
|
7005
7119
|
`, "utf8");
|
|
@@ -7008,7 +7122,7 @@ async function renderClaudeSubagent(artifact, stageRoot) {
|
|
|
7008
7122
|
name: `${agentName}.md`,
|
|
7009
7123
|
sourcePath: renderedPath,
|
|
7010
7124
|
stagedPath: renderedPath,
|
|
7011
|
-
relativePath:
|
|
7125
|
+
relativePath: join29("subagents", `${agentName}.md`),
|
|
7012
7126
|
kind: "file",
|
|
7013
7127
|
hash: await hashPath(renderedPath)
|
|
7014
7128
|
};
|
|
@@ -7031,10 +7145,10 @@ async function stageResolvedSourceRaw(driver, resolved) {
|
|
|
7031
7145
|
return stageResolvedArtifactsRaw(resolved, artifacts);
|
|
7032
7146
|
}
|
|
7033
7147
|
async function stageResolvedArtifactsRaw(resolved, artifacts) {
|
|
7034
|
-
const root = await mkdtemp3(
|
|
7148
|
+
const root = await mkdtemp3(join30(tmpdir4(), "agentwheel-stage-"));
|
|
7035
7149
|
const stagedArtifacts = [];
|
|
7036
7150
|
for (const artifact of artifacts) {
|
|
7037
|
-
const stagedPath =
|
|
7151
|
+
const stagedPath = join30(root, artifact.relativePath);
|
|
7038
7152
|
await mkdir18(dirname23(stagedPath), { recursive: true });
|
|
7039
7153
|
await cp5(artifact.sourcePath, stagedPath, {
|
|
7040
7154
|
recursive: artifact.kind === "dir",
|
|
@@ -7122,7 +7236,7 @@ async function composeAssets(artifact, packageRoot, stagedPath) {
|
|
|
7122
7236
|
}
|
|
7123
7237
|
for (const asset of artifact.assets) {
|
|
7124
7238
|
const source = resolvePackagePath(packageRoot, asset.from);
|
|
7125
|
-
const dest =
|
|
7239
|
+
const dest = join30(stagedPath, asset.into);
|
|
7126
7240
|
await copyAsset(asset, source, dest);
|
|
7127
7241
|
}
|
|
7128
7242
|
}
|
|
@@ -7131,7 +7245,7 @@ async function copyAsset(asset, source, dest) {
|
|
|
7131
7245
|
if (sourceStats.isFile()) {
|
|
7132
7246
|
if (matchesAny(basename19(source), asset.include)) {
|
|
7133
7247
|
await mkdir18(dest, { recursive: true });
|
|
7134
|
-
await copyAssetFile(source,
|
|
7248
|
+
await copyAssetFile(source, join30(dest, basename19(source)), asset);
|
|
7135
7249
|
}
|
|
7136
7250
|
return;
|
|
7137
7251
|
}
|
|
@@ -7147,7 +7261,7 @@ async function copyAsset(asset, source, dest) {
|
|
|
7147
7261
|
for (const file of await listFiles(source)) {
|
|
7148
7262
|
const rel = relative7(source, file).replaceAll("\\", "/");
|
|
7149
7263
|
if (!matchesAny(rel, asset.include) && !matchesAny(basename19(file), asset.include)) continue;
|
|
7150
|
-
await copyAssetFile(file,
|
|
7264
|
+
await copyAssetFile(file, join30(dest, rel), asset);
|
|
7151
7265
|
}
|
|
7152
7266
|
}
|
|
7153
7267
|
async function copyAssetFile(source, dest, asset) {
|
|
@@ -7167,7 +7281,7 @@ async function listFiles(root) {
|
|
|
7167
7281
|
const out = [];
|
|
7168
7282
|
async function walk2(dir) {
|
|
7169
7283
|
for (const entry of (await readdir5(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
7170
|
-
const full =
|
|
7284
|
+
const full = join30(dir, entry.name);
|
|
7171
7285
|
if (entry.isDirectory()) {
|
|
7172
7286
|
await walk2(full);
|
|
7173
7287
|
} else if (entry.isFile()) {
|
|
@@ -7186,7 +7300,7 @@ async function normalizeCopiedModes(path) {
|
|
|
7186
7300
|
}
|
|
7187
7301
|
if (!stats.isDirectory()) return;
|
|
7188
7302
|
for (const entry of await readdir5(path, { withFileTypes: true })) {
|
|
7189
|
-
await normalizeCopiedModes(
|
|
7303
|
+
await normalizeCopiedModes(join30(path, entry.name));
|
|
7190
7304
|
}
|
|
7191
7305
|
}
|
|
7192
7306
|
function matchesAny(path, patterns) {
|
|
@@ -7199,9 +7313,9 @@ function matchesGlob(path, pattern) {
|
|
|
7199
7313
|
}
|
|
7200
7314
|
|
|
7201
7315
|
// src/model/workspace.ts
|
|
7202
|
-
import { readFile as
|
|
7203
|
-
import { homedir as
|
|
7204
|
-
import { dirname as dirname24, join as
|
|
7316
|
+
import { readFile as readFile23 } from "fs/promises";
|
|
7317
|
+
import { homedir as homedir5 } from "os";
|
|
7318
|
+
import { dirname as dirname24, join as join31, resolve as resolve13 } from "path";
|
|
7205
7319
|
import { z as z6 } from "zod";
|
|
7206
7320
|
|
|
7207
7321
|
// src/resolve/semver.ts
|
|
@@ -7472,12 +7586,12 @@ var workspaceConfigSchema = z6.discriminatedUnion("schemaVersion", [
|
|
|
7472
7586
|
workspaceConfigV2Schema
|
|
7473
7587
|
]);
|
|
7474
7588
|
function workspaceConfigPath(workspaceRoot) {
|
|
7475
|
-
return
|
|
7589
|
+
return join31(workspaceRoot, ".agentwheel", "config.json");
|
|
7476
7590
|
}
|
|
7477
7591
|
async function readWorkspaceConfig(workspaceRoot) {
|
|
7478
7592
|
const path = workspaceConfigPath(workspaceRoot);
|
|
7479
7593
|
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
7480
|
-
return workspaceConfigSchema.parse(JSON.parse(await
|
|
7594
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile23(path, "utf8")));
|
|
7481
7595
|
}
|
|
7482
7596
|
async function writeWorkspaceConfig(workspaceRoot, config) {
|
|
7483
7597
|
await writeJsonAtomic(workspaceConfigPath(workspaceRoot), workspaceConfigSchema.parse(config));
|
|
@@ -7489,8 +7603,8 @@ function upsertPackage(config, entry) {
|
|
|
7489
7603
|
packages.sort((a, b) => a.name.localeCompare(b.name));
|
|
7490
7604
|
return workspaceConfigSchema.parse({ ...parsed, packages });
|
|
7491
7605
|
}
|
|
7492
|
-
function globalWorkspaceConfigPath(globalRoot =
|
|
7493
|
-
return
|
|
7606
|
+
function globalWorkspaceConfigPath(globalRoot = homedir5()) {
|
|
7607
|
+
return join31(globalRoot, ".agentwheel", "config.json");
|
|
7494
7608
|
}
|
|
7495
7609
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
7496
7610
|
let current = resolve13(start);
|
|
@@ -7526,8 +7640,8 @@ function mergeWorkspaceConfig(global, project) {
|
|
|
7526
7640
|
});
|
|
7527
7641
|
}
|
|
7528
7642
|
function resolveConfigPath(path, baseRoot) {
|
|
7529
|
-
if (path.startsWith("~/")) return resolve13(
|
|
7530
|
-
if (path === "~") return
|
|
7643
|
+
if (path.startsWith("~/")) return resolve13(homedir5(), path.slice(2));
|
|
7644
|
+
if (path === "~") return homedir5();
|
|
7531
7645
|
return path.startsWith("/") ? resolve13(path) : resolve13(baseRoot, path);
|
|
7532
7646
|
}
|
|
7533
7647
|
function emptyWorkspaceConfig() {
|
|
@@ -7538,7 +7652,7 @@ function isCompositeWorkspaceProfile(profile) {
|
|
|
7538
7652
|
}
|
|
7539
7653
|
async function readConfigPath(path) {
|
|
7540
7654
|
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
7541
|
-
return workspaceConfigSchema.parse(JSON.parse(await
|
|
7655
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile23(path, "utf8")));
|
|
7542
7656
|
}
|
|
7543
7657
|
function mergeWorkspaceTrust(global, project) {
|
|
7544
7658
|
return {
|
|
@@ -7554,17 +7668,17 @@ function sortedUnique2(values) {
|
|
|
7554
7668
|
|
|
7555
7669
|
// src/lifecycle/customization.ts
|
|
7556
7670
|
import { appendFile, cp as cp6, mkdir as mkdir19, rm as rm9 } from "fs/promises";
|
|
7557
|
-
import { dirname as dirname26, join as
|
|
7671
|
+
import { dirname as dirname26, join as join34 } from "path";
|
|
7558
7672
|
|
|
7559
7673
|
// src/resolve/graph.ts
|
|
7560
7674
|
import { createHash as createHash8 } from "crypto";
|
|
7561
|
-
import { mkdtemp as mkdtemp4, readdir as readdir6, readFile as
|
|
7675
|
+
import { mkdtemp as mkdtemp4, readdir as readdir6, readFile as readFile26, stat as stat10 } from "fs/promises";
|
|
7562
7676
|
import { tmpdir as tmpdir5 } from "os";
|
|
7563
|
-
import { basename as basename20, extname as extname4, join as
|
|
7677
|
+
import { basename as basename20, extname as extname4, join as join33 } from "path";
|
|
7564
7678
|
|
|
7565
7679
|
// src/model/workspace-composition.ts
|
|
7566
7680
|
import { createHash as createHash7 } from "crypto";
|
|
7567
|
-
import { readFile as
|
|
7681
|
+
import { readFile as readFile24 } from "fs/promises";
|
|
7568
7682
|
import { z as z7 } from "zod";
|
|
7569
7683
|
var selectionSourceConfigSchema = z7.object({
|
|
7570
7684
|
schemaVersion: z7.literal(2),
|
|
@@ -7583,12 +7697,12 @@ async function resolveSelectionImport(sourceRoot, sourceDriver, selection) {
|
|
|
7583
7697
|
}
|
|
7584
7698
|
let raw;
|
|
7585
7699
|
try {
|
|
7586
|
-
raw = JSON.parse(await
|
|
7700
|
+
raw = JSON.parse(await readFile24(path, "utf8"));
|
|
7587
7701
|
} catch (error) {
|
|
7588
7702
|
const message = error instanceof Error ? error.message : String(error);
|
|
7589
7703
|
throw new Error(`Selection import '${parsedSelection.export}' cannot parse ${path}: ${message}`);
|
|
7590
7704
|
}
|
|
7591
|
-
if (!
|
|
7705
|
+
if (!isRecord9(raw) || raw.schemaVersion !== 2) {
|
|
7592
7706
|
throw new Error(`Selection import '${parsedSelection.export}' requires schemaVersion 2 in ${path}.`);
|
|
7593
7707
|
}
|
|
7594
7708
|
let sourceConfig;
|
|
@@ -7676,18 +7790,18 @@ function stableValue2(value) {
|
|
|
7676
7790
|
}
|
|
7677
7791
|
return out;
|
|
7678
7792
|
}
|
|
7679
|
-
function
|
|
7793
|
+
function isRecord9(value) {
|
|
7680
7794
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
7681
7795
|
}
|
|
7682
7796
|
|
|
7683
7797
|
// src/resolve/identity.ts
|
|
7684
|
-
import { homedir as
|
|
7798
|
+
import { homedir as homedir7 } from "os";
|
|
7685
7799
|
import { resolve as resolve15 } from "path";
|
|
7686
7800
|
|
|
7687
7801
|
// src/registry/client.ts
|
|
7688
|
-
import { readFile as
|
|
7689
|
-
import { homedir as
|
|
7690
|
-
import { dirname as dirname25, join as
|
|
7802
|
+
import { readFile as readFile25, rm as rm8, stat as stat9 } from "fs/promises";
|
|
7803
|
+
import { homedir as homedir6 } from "os";
|
|
7804
|
+
import { dirname as dirname25, join as join32, resolve as resolve14 } from "path";
|
|
7691
7805
|
import { fileURLToPath } from "url";
|
|
7692
7806
|
|
|
7693
7807
|
// src/model/registry.ts
|
|
@@ -7784,7 +7898,7 @@ var RegistryClient = class {
|
|
|
7784
7898
|
}
|
|
7785
7899
|
async readCache() {
|
|
7786
7900
|
if (!await pathExists(this.cachePath)) return void 0;
|
|
7787
|
-
return registryCacheSchema.parse(JSON.parse(await
|
|
7901
|
+
return registryCacheSchema.parse(JSON.parse(await readFile25(this.cachePath, "utf8")));
|
|
7788
7902
|
}
|
|
7789
7903
|
isExpired(cache, ttlMs) {
|
|
7790
7904
|
return this.now().getTime() - new Date(cache.fetchedAt).getTime() > ttlMs;
|
|
@@ -7803,10 +7917,10 @@ var RegistryClient = class {
|
|
|
7803
7917
|
if (await pathExists(filePath)) {
|
|
7804
7918
|
const fullPath = resolve14(filePath);
|
|
7805
7919
|
const stats = await stat9(fullPath);
|
|
7806
|
-
return
|
|
7920
|
+
return readFile25(stats.isDirectory() ? join32(fullPath, "index.json") : fullPath, "utf8");
|
|
7807
7921
|
}
|
|
7808
|
-
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot:
|
|
7809
|
-
return
|
|
7922
|
+
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join32(dirname25(this.cachePath), "registry-repos") }));
|
|
7923
|
+
return readFile25(join32(resolved.resolvedPath, "index.json"), "utf8");
|
|
7810
7924
|
}
|
|
7811
7925
|
warnCompatibility(entries) {
|
|
7812
7926
|
for (const entry of entries) {
|
|
@@ -7844,7 +7958,7 @@ function mergeIndexes(indexes) {
|
|
|
7844
7958
|
return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
7845
7959
|
}
|
|
7846
7960
|
function defaultRegistryCachePath() {
|
|
7847
|
-
return
|
|
7961
|
+
return join32(homedir6(), ".agentwheel", "registry-cache.json");
|
|
7848
7962
|
}
|
|
7849
7963
|
function sameSources(a, b) {
|
|
7850
7964
|
return a.length === b.length && a.every((source, index) => source === b[index]);
|
|
@@ -7929,8 +8043,8 @@ function localSourcePath(source) {
|
|
|
7929
8043
|
return source.startsWith("local:") ? source.slice("local:".length) : source;
|
|
7930
8044
|
}
|
|
7931
8045
|
function resolveLocalPath(path, declaringPackageRoot) {
|
|
7932
|
-
if (path === "~") return
|
|
7933
|
-
if (path.startsWith("~/")) return resolve15(
|
|
8046
|
+
if (path === "~") return homedir7();
|
|
8047
|
+
if (path.startsWith("~/")) return resolve15(homedir7(), path.slice(2));
|
|
7934
8048
|
if (path.startsWith("/")) return resolve15(path);
|
|
7935
8049
|
return resolve15(declaringPackageRoot, path);
|
|
7936
8050
|
}
|
|
@@ -8008,7 +8122,7 @@ function normalizeLiteralProviderSpec(source, prefix) {
|
|
|
8008
8122
|
var cacheLocks = /* @__PURE__ */ new Map();
|
|
8009
8123
|
async function resolveDependencyGraph(roots, options) {
|
|
8010
8124
|
if (roots.length === 0) throw new Error("At least one graph root is required.");
|
|
8011
|
-
const graphRoot = await mkdtemp4(
|
|
8125
|
+
const graphRoot = await mkdtemp4(join33(tmpdir5(), "agentwheel-graph-"));
|
|
8012
8126
|
const fetchCache = /* @__PURE__ */ new Map();
|
|
8013
8127
|
const nodesByKey = /* @__PURE__ */ new Map();
|
|
8014
8128
|
const rootResults = [];
|
|
@@ -8528,7 +8642,7 @@ async function collectIncludeNeeds(artifact, artifactsByRelativePath) {
|
|
|
8528
8642
|
const file = stack.shift();
|
|
8529
8643
|
if (scanned.has(file)) continue;
|
|
8530
8644
|
scanned.add(file);
|
|
8531
|
-
const content = await
|
|
8645
|
+
const content = await readFile26(file, "utf8");
|
|
8532
8646
|
for (const include of extractOpenPackIncludeSelectors(content)) {
|
|
8533
8647
|
await collectIncludeSelector(include.raw, include.optional, artifactsByRelativePath, scanned, stack, needs);
|
|
8534
8648
|
}
|
|
@@ -8571,7 +8685,7 @@ async function listMarkdownFiles2(root) {
|
|
|
8571
8685
|
const out = [];
|
|
8572
8686
|
async function walk2(dir) {
|
|
8573
8687
|
for (const entry of (await readdir6(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
8574
|
-
const full =
|
|
8688
|
+
const full = join33(dir, entry.name);
|
|
8575
8689
|
if (entry.isDirectory()) {
|
|
8576
8690
|
await walk2(full);
|
|
8577
8691
|
} else if (entry.isFile() && extname4(entry.name).toLowerCase() === ".md") {
|
|
@@ -8606,7 +8720,7 @@ async function fetchPackage(normalized, mode, options, fetchCache, refOverride)
|
|
|
8606
8720
|
const promise = (async () => {
|
|
8607
8721
|
const driver = getSourceDriver(normalized.driver);
|
|
8608
8722
|
const resolved = await driver.resolve(normalized.source, {
|
|
8609
|
-
cacheRoot: options.cacheRoot ??
|
|
8723
|
+
cacheRoot: options.cacheRoot ?? join33(options.workspaceRoot, ".agentwheel", "cache"),
|
|
8610
8724
|
mode,
|
|
8611
8725
|
ref: refOverride ?? normalized.requestedRef,
|
|
8612
8726
|
frozenLock: hardLockedCheckout
|
|
@@ -8813,7 +8927,7 @@ async function mapLimit(items, limit, fn) {
|
|
|
8813
8927
|
|
|
8814
8928
|
// src/lifecycle/customization.ts
|
|
8815
8929
|
async function remember(workspaceRoot, runtime, text) {
|
|
8816
|
-
const overlayPath =
|
|
8930
|
+
const overlayPath = join34(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
|
|
8817
8931
|
await mkdir19(dirname26(overlayPath), { recursive: true });
|
|
8818
8932
|
await appendFile(overlayPath, `${text.trim()}
|
|
8819
8933
|
`, "utf8");
|
|
@@ -8837,7 +8951,7 @@ async function ejectArtifact(workspaceRoot, item) {
|
|
|
8837
8951
|
throw new Error(`Artifact not found: ${item}`);
|
|
8838
8952
|
}
|
|
8839
8953
|
const ejectedIdentity = parsed.packageIdentity === parsed.packageName ? parsed.packageIdentity : candidate.nodeId === parsed.packageIdentity ? candidate.nodeId : `${candidate.packageName}@${candidate.packageVersion}`;
|
|
8840
|
-
const ejectedPath =
|
|
8954
|
+
const ejectedPath = join34(workspaceRoot, ".agentwheel", "ejected", ...ejectedIdentity.split("/"), parsed.type, parsed.name);
|
|
8841
8955
|
await mkdir19(dirname26(ejectedPath), { recursive: true });
|
|
8842
8956
|
await rm9(ejectedPath, { recursive: true, force: true });
|
|
8843
8957
|
await cp6(artifact.stagedPath ?? artifact.sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
|
|
@@ -8880,7 +8994,7 @@ async function stageEjectCandidate(workspaceRoot, pkg) {
|
|
|
8880
8994
|
const adapter = pkg.adapterConfig ? await loadAdapterConfig(pkg.adapterConfig) : getAdapter(pkg.adapter);
|
|
8881
8995
|
const bundle = await stageSource(driver, normalized.source, {
|
|
8882
8996
|
adapter,
|
|
8883
|
-
cacheRoot:
|
|
8997
|
+
cacheRoot: join34(workspaceRoot, ".agentwheel", "cache"),
|
|
8884
8998
|
mode: pkg.mode,
|
|
8885
8999
|
ref: normalized.requestedRef ?? pkg.requestedRef
|
|
8886
9000
|
});
|
|
@@ -8932,7 +9046,7 @@ import { rm as rm10 } from "fs/promises";
|
|
|
8932
9046
|
// src/lifecycle/source-plan.ts
|
|
8933
9047
|
import { createHash as createHash10 } from "crypto";
|
|
8934
9048
|
import { mkdir as mkdir21 } from "fs/promises";
|
|
8935
|
-
import { dirname as dirname28, join as
|
|
9049
|
+
import { dirname as dirname28, join as join37 } from "path";
|
|
8936
9050
|
|
|
8937
9051
|
// src/resolve/graph-diff.ts
|
|
8938
9052
|
function diffGraphLocks(previous, next) {
|
|
@@ -9094,11 +9208,11 @@ function formatSelectionImport(root) {
|
|
|
9094
9208
|
|
|
9095
9209
|
// src/resolve/render.ts
|
|
9096
9210
|
import { createHash as createHash9 } from "crypto";
|
|
9097
|
-
import { readFile as
|
|
9211
|
+
import { readFile as readFile27, mkdtemp as mkdtemp5 } from "fs/promises";
|
|
9098
9212
|
import { tmpdir as tmpdir6 } from "os";
|
|
9099
|
-
import { join as
|
|
9213
|
+
import { join as join35 } from "path";
|
|
9100
9214
|
async function renderGraphForTarget(graph, targetContext = {}) {
|
|
9101
|
-
const root = await mkdtemp5(
|
|
9215
|
+
const root = await mkdtemp5(join35(tmpdir6(), "agentwheel-render-"));
|
|
9102
9216
|
const artifacts = [];
|
|
9103
9217
|
const stagedNodes = /* @__PURE__ */ new Map();
|
|
9104
9218
|
const includeEdges = /* @__PURE__ */ new Map();
|
|
@@ -9220,7 +9334,7 @@ async function artifactContentMap(artifacts) {
|
|
|
9220
9334
|
const out = /* @__PURE__ */ new Map();
|
|
9221
9335
|
for (const artifact of artifacts) {
|
|
9222
9336
|
if (artifact.kind !== "file") continue;
|
|
9223
|
-
out.set(artifact.relativePath.replaceAll("\\", "/"), await
|
|
9337
|
+
out.set(artifact.relativePath.replaceAll("\\", "/"), await readFile27(artifact.stagedPath ?? artifact.sourcePath, "utf8"));
|
|
9224
9338
|
}
|
|
9225
9339
|
return out;
|
|
9226
9340
|
}
|
|
@@ -9483,9 +9597,9 @@ function lockArtifactFor(artifact) {
|
|
|
9483
9597
|
}
|
|
9484
9598
|
|
|
9485
9599
|
// src/lifecycle/trust.ts
|
|
9486
|
-
import { mkdir as mkdir20, readFile as
|
|
9487
|
-
import { homedir as
|
|
9488
|
-
import { dirname as dirname27, join as
|
|
9600
|
+
import { mkdir as mkdir20, readFile as readFile28 } from "fs/promises";
|
|
9601
|
+
import { homedir as homedir8 } from "os";
|
|
9602
|
+
import { dirname as dirname27, join as join36 } from "path";
|
|
9489
9603
|
import { z as z9 } from "zod";
|
|
9490
9604
|
var trustStoreSchema = z9.object({
|
|
9491
9605
|
version: z9.literal(1),
|
|
@@ -9559,14 +9673,14 @@ function sortedUnique5(values) {
|
|
|
9559
9673
|
}
|
|
9560
9674
|
async function readTrustStore(path) {
|
|
9561
9675
|
if (!await pathExists(path)) return { version: 1, acceptedSources: [] };
|
|
9562
|
-
return trustStoreSchema.parse(JSON.parse(await
|
|
9676
|
+
return trustStoreSchema.parse(JSON.parse(await readFile28(path, "utf8")));
|
|
9563
9677
|
}
|
|
9564
9678
|
async function writeTrustStore(path, store) {
|
|
9565
9679
|
await mkdir20(dirname27(path), { recursive: true });
|
|
9566
9680
|
await writeJsonAtomic(path, trustStoreSchema.parse(store));
|
|
9567
9681
|
}
|
|
9568
9682
|
function defaultTrustStorePath() {
|
|
9569
|
-
return process.env.AGENTWHEEL_TRUST_STORE ??
|
|
9683
|
+
return process.env.AGENTWHEEL_TRUST_STORE ?? join36(homedir8(), ".agentwheel", "trust.json");
|
|
9570
9684
|
}
|
|
9571
9685
|
|
|
9572
9686
|
// src/lifecycle/ownership.ts
|
|
@@ -9738,7 +9852,7 @@ async function createGraphSourcePlan(options) {
|
|
|
9738
9852
|
const registryClient = new RegistryClient({ workspaceRoot, offline: lockMode, offlineLabel: lockLabel, warn });
|
|
9739
9853
|
const graph = await resolveDependencyGraph(options.roots, {
|
|
9740
9854
|
workspaceRoot,
|
|
9741
|
-
cacheRoot:
|
|
9855
|
+
cacheRoot: join37(workspaceRoot, ".agentwheel", "cache"),
|
|
9742
9856
|
registryClient,
|
|
9743
9857
|
noDeps: options.noDeps,
|
|
9744
9858
|
includeSuggestions: options.includeSuggestions,
|
|
@@ -9844,7 +9958,7 @@ async function readExistingGraphLock(path) {
|
|
|
9844
9958
|
return readGraphLock(path);
|
|
9845
9959
|
}
|
|
9846
9960
|
function pathForGraphLock(workspaceRoot, targetKey2, adapter, targetFingerprint) {
|
|
9847
|
-
return
|
|
9961
|
+
return join37(workspaceRoot, ".agentwheel", "locks", sanitizePathSegment(targetKey2), sanitizePathSegment(adapter), `${targetFingerprint}.graph-lock.json`);
|
|
9848
9962
|
}
|
|
9849
9963
|
function sanitizePathSegment(value) {
|
|
9850
9964
|
return value.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "default";
|
|
@@ -9976,7 +10090,7 @@ function targetLabel(target) {
|
|
|
9976
10090
|
}
|
|
9977
10091
|
|
|
9978
10092
|
// src/runtime/target.ts
|
|
9979
|
-
import { basename as basename21, dirname as dirname29, join as
|
|
10093
|
+
import { basename as basename21, dirname as dirname29, join as join38, resolve as resolve17 } from "path";
|
|
9980
10094
|
var runtimeMarkers = [
|
|
9981
10095
|
{ adapter: "openclaw", dirs: [".openclaw", ".clawdbot", ".moltbot"] },
|
|
9982
10096
|
{ adapter: "claude", dirs: [".claude"] },
|
|
@@ -10098,7 +10212,7 @@ async function detectRuntimeTargets(cwd = process.cwd(), adapterFilter) {
|
|
|
10098
10212
|
for (const dir of marker.dirs) {
|
|
10099
10213
|
if (basename21(root) === dir) {
|
|
10100
10214
|
matches.push({ adapter: marker.adapter, targetRoot: dirname29(root) });
|
|
10101
|
-
} else if (await pathExists(
|
|
10215
|
+
} else if (await pathExists(join38(root, dir))) {
|
|
10102
10216
|
matches.push({ adapter: marker.adapter, targetRoot: root });
|
|
10103
10217
|
}
|
|
10104
10218
|
}
|
|
@@ -10442,9 +10556,9 @@ function shellQuoteArg(value) {
|
|
|
10442
10556
|
}
|
|
10443
10557
|
|
|
10444
10558
|
// src/cli/update-check.ts
|
|
10445
|
-
import { mkdir as mkdir22, readFile as
|
|
10446
|
-
import { homedir as
|
|
10447
|
-
import { dirname as dirname30, join as
|
|
10559
|
+
import { mkdir as mkdir22, readFile as readFile29, writeFile as writeFile20 } from "fs/promises";
|
|
10560
|
+
import { homedir as homedir9 } from "os";
|
|
10561
|
+
import { dirname as dirname30, join as join39 } from "path";
|
|
10448
10562
|
var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
10449
10563
|
var DEFAULT_TIMEOUT_MS = 300;
|
|
10450
10564
|
var REGISTRY_URL = "https://registry.npmjs.org/agentwheel";
|
|
@@ -10452,7 +10566,7 @@ async function maybeCheckForUpdate(options) {
|
|
|
10452
10566
|
if (isDisabled(options)) return;
|
|
10453
10567
|
const now = options.now?.() ?? /* @__PURE__ */ new Date();
|
|
10454
10568
|
const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
|
|
10455
|
-
const cachePath = options.cachePath ??
|
|
10569
|
+
const cachePath = options.cachePath ?? join39(homedir9(), ".agentwheel", "update-check.json");
|
|
10456
10570
|
try {
|
|
10457
10571
|
const cached = await readCache(cachePath);
|
|
10458
10572
|
if (cached && now.getTime() - Date.parse(cached.checkedAt) < ttlMs) {
|
|
@@ -10489,7 +10603,7 @@ async function fetchLatestVersion(fetchImpl, timeoutMs) {
|
|
|
10489
10603
|
}
|
|
10490
10604
|
async function readCache(path) {
|
|
10491
10605
|
try {
|
|
10492
|
-
const parsed = JSON.parse(await
|
|
10606
|
+
const parsed = JSON.parse(await readFile29(path, "utf8"));
|
|
10493
10607
|
if (typeof parsed.checkedAt !== "string" || typeof parsed.latest !== "string") return void 0;
|
|
10494
10608
|
return { checkedAt: parsed.checkedAt, latest: parsed.latest };
|
|
10495
10609
|
} catch {
|
|
@@ -10661,13 +10775,13 @@ function isCrossPackageSelector(value) {
|
|
|
10661
10775
|
}
|
|
10662
10776
|
|
|
10663
10777
|
// src/model/package-migrate.ts
|
|
10664
|
-
import { readFile as
|
|
10665
|
-
import { join as
|
|
10778
|
+
import { readFile as readFile30, rename as rename4, writeFile as writeFile21 } from "fs/promises";
|
|
10779
|
+
import { join as join41, resolve as resolve19 } from "path";
|
|
10666
10780
|
import { applyEdits, modify, parse as parse5 } from "jsonc-parser";
|
|
10667
10781
|
async function migratePackageManifest(root) {
|
|
10668
10782
|
const packageRoot = resolve19(root);
|
|
10669
10783
|
for (const name of openPackManifestNames) {
|
|
10670
|
-
const path =
|
|
10784
|
+
const path = join41(packageRoot, name);
|
|
10671
10785
|
if (await pathExists(path)) {
|
|
10672
10786
|
return { changed: false, to: path, message: `Package already uses ${name}.` };
|
|
10673
10787
|
}
|
|
@@ -10676,10 +10790,10 @@ async function migratePackageManifest(root) {
|
|
|
10676
10790
|
if (!legacyName) {
|
|
10677
10791
|
throw new Error(`No legacy package manifest found at ${packageRoot}`);
|
|
10678
10792
|
}
|
|
10679
|
-
const from =
|
|
10793
|
+
const from = join41(packageRoot, legacyName);
|
|
10680
10794
|
const toName = legacyName.endsWith(".jsonc") ? "openpack.jsonc" : "openpack.json";
|
|
10681
|
-
const to =
|
|
10682
|
-
const content = await
|
|
10795
|
+
const to = join41(packageRoot, toName);
|
|
10796
|
+
const content = await readFile30(from, "utf8");
|
|
10683
10797
|
const updated = updateSchemaVersion(content);
|
|
10684
10798
|
await rename4(from, to);
|
|
10685
10799
|
await writeFile21(to, updated, "utf8");
|
|
@@ -10687,7 +10801,7 @@ async function migratePackageManifest(root) {
|
|
|
10687
10801
|
}
|
|
10688
10802
|
async function firstExistingLegacyManifest(root) {
|
|
10689
10803
|
for (const name of legacyPackageManifestNames) {
|
|
10690
|
-
if (await pathExists(
|
|
10804
|
+
if (await pathExists(join41(root, name))) return name;
|
|
10691
10805
|
}
|
|
10692
10806
|
return void 0;
|
|
10693
10807
|
}
|
|
@@ -10705,14 +10819,14 @@ function updateSchemaVersion(content) {
|
|
|
10705
10819
|
|
|
10706
10820
|
// src/cli/version.ts
|
|
10707
10821
|
import { readFileSync } from "fs";
|
|
10708
|
-
import { dirname as dirname31, join as
|
|
10822
|
+
import { dirname as dirname31, join as join42 } from "path";
|
|
10709
10823
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
10710
10824
|
var FALLBACK_VERSION = "0.0.0";
|
|
10711
10825
|
function resolveCliVersion() {
|
|
10712
10826
|
let dir = dirname31(fileURLToPath2(import.meta.url));
|
|
10713
10827
|
while (true) {
|
|
10714
10828
|
try {
|
|
10715
|
-
const pkg = JSON.parse(readFileSync(
|
|
10829
|
+
const pkg = JSON.parse(readFileSync(join42(dir, "package.json"), "utf8"));
|
|
10716
10830
|
if (pkg.name === "agentwheel" && typeof pkg.version === "string") {
|
|
10717
10831
|
return pkg.version;
|
|
10718
10832
|
}
|
|
@@ -10726,8 +10840,8 @@ function resolveCliVersion() {
|
|
|
10726
10840
|
|
|
10727
10841
|
// src/version/policy.ts
|
|
10728
10842
|
import { execFile as execFile5 } from "child_process";
|
|
10729
|
-
import { readFile as
|
|
10730
|
-
import { join as
|
|
10843
|
+
import { readFile as readFile31 } from "fs/promises";
|
|
10844
|
+
import { join as join43, resolve as resolve20 } from "path";
|
|
10731
10845
|
import { promisify as promisify5 } from "util";
|
|
10732
10846
|
import { parse as parseJsonc } from "jsonc-parser";
|
|
10733
10847
|
import { z as z10 } from "zod";
|
|
@@ -10836,7 +10950,7 @@ async function discoverVersionsFromSource(pkg, workspaceRoot) {
|
|
|
10836
10950
|
}
|
|
10837
10951
|
const driver = getSourceDriver(driverName);
|
|
10838
10952
|
const resolved = await driver.resolve(pkg.source, {
|
|
10839
|
-
cacheRoot:
|
|
10953
|
+
cacheRoot: join43(workspaceRoot, ".agentwheel", "cache"),
|
|
10840
10954
|
mode: "tracking",
|
|
10841
10955
|
ref: pkg.requestedRef
|
|
10842
10956
|
});
|
|
@@ -10930,12 +11044,12 @@ function gitUrlFromSource(source) {
|
|
|
10930
11044
|
throw new Error(`Version discovery does not support Git source: ${source}`);
|
|
10931
11045
|
}
|
|
10932
11046
|
function versionCachePath(workspaceRoot) {
|
|
10933
|
-
return
|
|
11047
|
+
return join43(workspaceRoot, ".agentwheel", "cache", "version-index.json");
|
|
10934
11048
|
}
|
|
10935
11049
|
async function readVersionCache(path) {
|
|
10936
11050
|
if (!await pathExists(path)) return { schemaVersion: 1, sources: {} };
|
|
10937
11051
|
try {
|
|
10938
|
-
return versionCacheSchema.parse(JSON.parse(await
|
|
11052
|
+
return versionCacheSchema.parse(JSON.parse(await readFile31(path, "utf8")));
|
|
10939
11053
|
} catch {
|
|
10940
11054
|
return { schemaVersion: 1, sources: {} };
|
|
10941
11055
|
}
|
|
@@ -10943,8 +11057,8 @@ async function readVersionCache(path) {
|
|
|
10943
11057
|
|
|
10944
11058
|
// src/profile/members.ts
|
|
10945
11059
|
import { execFile as execFile6 } from "child_process";
|
|
10946
|
-
import { readFile as
|
|
10947
|
-
import { join as
|
|
11060
|
+
import { readFile as readFile32 } from "fs/promises";
|
|
11061
|
+
import { join as join44, resolve as resolve21 } from "path";
|
|
10948
11062
|
import { promisify as promisify6 } from "util";
|
|
10949
11063
|
import { z as z12 } from "zod";
|
|
10950
11064
|
|
|
@@ -11130,11 +11244,11 @@ async function invokeMemberStatus(member, parentWorkspace, chain, options, cliEn
|
|
|
11130
11244
|
} else {
|
|
11131
11245
|
const sshArgs = sshArguments(member);
|
|
11132
11246
|
const remoteArgs = [
|
|
11133
|
-
`cd ${
|
|
11247
|
+
`cd ${shellQuote2(member.workspace)}`,
|
|
11134
11248
|
"&&",
|
|
11135
|
-
`AGENTWHEEL_COMPOSITE_CHAIN=${
|
|
11249
|
+
`AGENTWHEEL_COMPOSITE_CHAIN=${shellQuote2(JSON.stringify(chain))}`,
|
|
11136
11250
|
"agentwheel",
|
|
11137
|
-
...args.map(
|
|
11251
|
+
...args.map(shellQuote2)
|
|
11138
11252
|
];
|
|
11139
11253
|
const result = await execFileAsync6("ssh", [...sshArgs, remoteArgs.join(" ")], {
|
|
11140
11254
|
env,
|
|
@@ -11173,12 +11287,12 @@ async function runMemberAgentwheel(member, parentWorkspace, args, chain) {
|
|
|
11173
11287
|
return { stdout: result2.stdout, stderr: result2.stderr };
|
|
11174
11288
|
}
|
|
11175
11289
|
const remoteArgs = [
|
|
11176
|
-
`cd ${
|
|
11290
|
+
`cd ${shellQuote2(member.workspace)}`,
|
|
11177
11291
|
"&&",
|
|
11178
|
-
`AGENTWHEEL_COMPOSITE_CHAIN=${
|
|
11292
|
+
`AGENTWHEEL_COMPOSITE_CHAIN=${shellQuote2(JSON.stringify(chain))}`,
|
|
11179
11293
|
"agentwheel",
|
|
11180
11294
|
"--no-update-check",
|
|
11181
|
-
...args.map(
|
|
11295
|
+
...args.map(shellQuote2)
|
|
11182
11296
|
];
|
|
11183
11297
|
const result = await execFileAsync6("ssh", [...sshArguments(member), remoteArgs.join(" ")], {
|
|
11184
11298
|
env,
|
|
@@ -11202,7 +11316,7 @@ function sshArguments(member) {
|
|
|
11202
11316
|
destination
|
|
11203
11317
|
];
|
|
11204
11318
|
}
|
|
11205
|
-
function
|
|
11319
|
+
function shellQuote2(value) {
|
|
11206
11320
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
11207
11321
|
}
|
|
11208
11322
|
function commandErrorDetail(error) {
|
|
@@ -11240,12 +11354,12 @@ function memberFailure(member, health, error) {
|
|
|
11240
11354
|
};
|
|
11241
11355
|
}
|
|
11242
11356
|
function memberCachePath(workspaceRoot, profileName, memberId) {
|
|
11243
|
-
return
|
|
11357
|
+
return join44(workspaceRoot, ".agentwheel", "cache", "member-status", profileName, `${memberId}.json`);
|
|
11244
11358
|
}
|
|
11245
11359
|
async function readMemberCache(path) {
|
|
11246
11360
|
if (!await pathExists(path)) return void 0;
|
|
11247
11361
|
try {
|
|
11248
|
-
return memberCacheSchema.parse(JSON.parse(await
|
|
11362
|
+
return memberCacheSchema.parse(JSON.parse(await readFile32(path, "utf8")));
|
|
11249
11363
|
} catch {
|
|
11250
11364
|
return void 0;
|
|
11251
11365
|
}
|
|
@@ -11314,9 +11428,9 @@ function valueAfter(lines, prefix) {
|
|
|
11314
11428
|
|
|
11315
11429
|
// src/catalogue/client.ts
|
|
11316
11430
|
import { createHash as createHash11 } from "crypto";
|
|
11317
|
-
import { readFile as
|
|
11318
|
-
import { homedir as
|
|
11319
|
-
import { join as
|
|
11431
|
+
import { readFile as readFile33, rm as rm11 } from "fs/promises";
|
|
11432
|
+
import { homedir as homedir10 } from "os";
|
|
11433
|
+
import { join as join45 } from "path";
|
|
11320
11434
|
|
|
11321
11435
|
// src/model/catalogue.ts
|
|
11322
11436
|
import { z as z13 } from "zod";
|
|
@@ -11511,7 +11625,7 @@ var CatalogueClient = class {
|
|
|
11511
11625
|
async readCache() {
|
|
11512
11626
|
if (!await pathExists(this.cachePath)) return void 0;
|
|
11513
11627
|
try {
|
|
11514
|
-
const value = JSON.parse(await
|
|
11628
|
+
const value = JSON.parse(await readFile33(this.cachePath, "utf8"));
|
|
11515
11629
|
const envelope = catalogueCacheEnvelopeSchema.parse(value);
|
|
11516
11630
|
if (envelope.contentHash) {
|
|
11517
11631
|
const contentHash = catalogueContentHash(envelope.enriched, envelope.vercel);
|
|
@@ -11567,7 +11681,7 @@ var CatalogueClient = class {
|
|
|
11567
11681
|
}
|
|
11568
11682
|
};
|
|
11569
11683
|
function defaultCatalogueCachePath() {
|
|
11570
|
-
return
|
|
11684
|
+
return join45(homedir10(), ".agentwheel", "catalogue-cache.json");
|
|
11571
11685
|
}
|
|
11572
11686
|
function sameSources2(a, b) {
|
|
11573
11687
|
return a.length === b.length && a.every((source, index) => source === b[index]);
|
|
@@ -11652,7 +11766,7 @@ function normalizeRegistryEntry(entry) {
|
|
|
11652
11766
|
tags: sortedUniqueStrings(entry.tags),
|
|
11653
11767
|
provides: [],
|
|
11654
11768
|
source: entry.source,
|
|
11655
|
-
installCommand: `npx agentwheel install ${
|
|
11769
|
+
installCommand: `npx agentwheel install ${shellQuote3(entry.name)}`,
|
|
11656
11770
|
installability: "registry",
|
|
11657
11771
|
provenances: ["registry"],
|
|
11658
11772
|
archived: false,
|
|
@@ -11700,7 +11814,7 @@ function normalizeVercelEntry(entry) {
|
|
|
11700
11814
|
provides: ["skills"],
|
|
11701
11815
|
source,
|
|
11702
11816
|
repoUrl: `https://github.com/${entry.o}/${entry.r}`,
|
|
11703
|
-
installCommand: `npx agentwheel install ${
|
|
11817
|
+
installCommand: `npx agentwheel install ${shellQuote3(source)}`,
|
|
11704
11818
|
installability: "source",
|
|
11705
11819
|
provenances: ["vercel"],
|
|
11706
11820
|
archived: false,
|
|
@@ -11897,11 +12011,11 @@ function enrichedInstallCommand(entry, source) {
|
|
|
11897
12011
|
const catalogueCommand = nonEmpty(entry.installCommand);
|
|
11898
12012
|
if (!source) return catalogueCommand;
|
|
11899
12013
|
if (entry.ecosystem === "mcp-registry" || entry.ecosystem === "clawhub") {
|
|
11900
|
-
return catalogueCommand ?? `npx agentwheel install ${
|
|
12014
|
+
return catalogueCommand ?? `npx agentwheel install ${shellQuote3(source)}`;
|
|
11901
12015
|
}
|
|
11902
|
-
return `npx agentwheel install ${
|
|
12016
|
+
return `npx agentwheel install ${shellQuote3(source)}`;
|
|
11903
12017
|
}
|
|
11904
|
-
function
|
|
12018
|
+
function shellQuote3(value) {
|
|
11905
12019
|
return `'${value.replaceAll("'", `'"'"'`)}'`;
|
|
11906
12020
|
}
|
|
11907
12021
|
function matchesPhrase(fields, query) {
|
|
@@ -11977,7 +12091,7 @@ program.command("list").description("list artifacts exposed by a package source"
|
|
|
11977
12091
|
const resolvedInput = await resolvePackageSource(source, targetRoot);
|
|
11978
12092
|
const selectedArtifacts = selectedArtifactsFromOptionsOrRegistry(options, resolvedInput.registryEntry);
|
|
11979
12093
|
const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
|
|
11980
|
-
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot:
|
|
12094
|
+
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join46(targetRoot, ".agentwheel", "cache") }))));
|
|
11981
12095
|
const artifacts = filterArtifactsBySelection(await driver.list(resolved), selectedArtifacts);
|
|
11982
12096
|
for (const artifact of artifacts) {
|
|
11983
12097
|
console.log(`${artifact.type} ${artifact.name} ${artifact.relativePath}`);
|
|
@@ -12029,7 +12143,7 @@ program.command("scan").description("scan a package source for validation findin
|
|
|
12029
12143
|
const targetRoot = normalizeTargetRoot(options.targetRoot);
|
|
12030
12144
|
const resolvedInput = await resolvePackageSource(source, targetRoot);
|
|
12031
12145
|
const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
|
|
12032
|
-
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot:
|
|
12146
|
+
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join46(targetRoot, ".agentwheel", "cache") }))));
|
|
12033
12147
|
const result = await driver.scan(resolved);
|
|
12034
12148
|
if (result.findings.length === 0) {
|
|
12035
12149
|
console.log("Scan ok: no findings");
|
|
@@ -12297,7 +12411,7 @@ journalCommand.command("list").description("show pending apply journals for reso
|
|
|
12297
12411
|
if (!journal) continue;
|
|
12298
12412
|
pending += 1;
|
|
12299
12413
|
console.log(`PENDING ${state.adapter.name}/${state.installationType} at ${state.installRoot}`);
|
|
12300
|
-
console.log(` journal: ${
|
|
12414
|
+
console.log(` journal: ${join46(state.installRoot, ".agentwheel", `${state.state.stateKey}.apply-journal.json`)}`);
|
|
12301
12415
|
console.log(` stateKey: ${state.state.stateKey}`);
|
|
12302
12416
|
console.log(` createdAt: ${journal.createdAt}`);
|
|
12303
12417
|
console.log(` updatedAt: ${journal.updatedAt}`);
|
|
@@ -12600,7 +12714,7 @@ async function packageEntryFromSource(source, targetRoot, options) {
|
|
|
12600
12714
|
const bundle = await stageSource(driver, resolvedSource, {
|
|
12601
12715
|
workspaceRoot: targetRoot,
|
|
12602
12716
|
adapter,
|
|
12603
|
-
cacheRoot:
|
|
12717
|
+
cacheRoot: join46(targetRoot, ".agentwheel", "cache"),
|
|
12604
12718
|
mode: options.mode,
|
|
12605
12719
|
ref: initialVersion?.ref,
|
|
12606
12720
|
frozenLock: lockMode,
|
|
@@ -13234,7 +13348,7 @@ function keepManifestEntryOperation(entry, targetRoot, scopeDescription, operati
|
|
|
13234
13348
|
artifactType: entry.artifactType,
|
|
13235
13349
|
artifactName: entry.artifactName,
|
|
13236
13350
|
kind: entry.kind,
|
|
13237
|
-
destPath: operation?.destPath ??
|
|
13351
|
+
destPath: operation?.destPath ?? join46(targetRoot, entry.path),
|
|
13238
13352
|
relativeDestPath: entry.path,
|
|
13239
13353
|
desiredHash: entry.sourceHash,
|
|
13240
13354
|
currentHash: operation?.currentHash ?? entry.hash,
|
|
@@ -13819,12 +13933,12 @@ async function printDoctor(target, options) {
|
|
|
13819
13933
|
const requestedSkills = doctorSkillRequests(target, options);
|
|
13820
13934
|
const skills = [];
|
|
13821
13935
|
for (const request of requestedSkills) {
|
|
13822
|
-
const skillPath =
|
|
13936
|
+
const skillPath = join46(state.installRoot, targetMapping.dest, request.name);
|
|
13823
13937
|
const exists = await pathExists(skillPath);
|
|
13824
13938
|
const manifestEntry = manifest?.entries.find((entry) => {
|
|
13825
13939
|
if (entry.artifactType !== "skills") return false;
|
|
13826
13940
|
const legacyInstallName = "installName" in entry && typeof entry.installName === "string" ? entry.installName : void 0;
|
|
13827
|
-
return entry.artifactName === request.name || legacyInstallName === request.name || entry.path ===
|
|
13941
|
+
return entry.artifactName === request.name || legacyInstallName === request.name || entry.path === join46(targetMapping.dest, request.name);
|
|
13828
13942
|
});
|
|
13829
13943
|
const status = manifestEntry ? "managed" : exists ? "present-unmanaged" : "missing";
|
|
13830
13944
|
skills.push({
|
|
@@ -13904,7 +14018,7 @@ function doctorSkillLabel(name) {
|
|
|
13904
14018
|
return `${name} skill`;
|
|
13905
14019
|
}
|
|
13906
14020
|
function isSyncwheelWorkspace(targetRoot) {
|
|
13907
|
-
return existsSync(
|
|
14021
|
+
return existsSync(join46(targetRoot, ".syncwheel", "manifest.json"));
|
|
13908
14022
|
}
|
|
13909
14023
|
function skillInstallCommand(adapter, installationType, options, skill, behavior = {}) {
|
|
13910
14024
|
const args = [
|
|
@@ -13972,7 +14086,7 @@ function normalizeRuntimeScopeOptions(options, behavior = {}) {
|
|
|
13972
14086
|
}
|
|
13973
14087
|
const canDefaultTargetRoot = !options.agent && !options.all && !options.allDetected && !options.profile;
|
|
13974
14088
|
if (!targetRoot && canDefaultTargetRoot && (options.user || installationType === "user" || behavior.defaultUser)) {
|
|
13975
|
-
targetRoot =
|
|
14089
|
+
targetRoot = homedir11();
|
|
13976
14090
|
}
|
|
13977
14091
|
if (!installationType && behavior.defaultUser) {
|
|
13978
14092
|
installationType = "user";
|
|
@@ -13992,12 +14106,12 @@ function looksLikeSourceSpecifier(value) {
|
|
|
13992
14106
|
return value.includes(":") || value.startsWith("/") || value.startsWith("./") || value.startsWith("../") || value === "~" || value.startsWith("~/");
|
|
13993
14107
|
}
|
|
13994
14108
|
function normalizeCliPath(value) {
|
|
13995
|
-
if (value === "~") return
|
|
13996
|
-
if (value.startsWith("~/")) return resolve22(
|
|
14109
|
+
if (value === "~") return homedir11();
|
|
14110
|
+
if (value.startsWith("~/")) return resolve22(homedir11(), value.slice(2));
|
|
13997
14111
|
return resolve22(value);
|
|
13998
14112
|
}
|
|
13999
14113
|
function isHomePath(path) {
|
|
14000
|
-
return resolve22(path) === resolve22(
|
|
14114
|
+
return resolve22(path) === resolve22(homedir11());
|
|
14001
14115
|
}
|
|
14002
14116
|
function adapterListFromOption(adapter) {
|
|
14003
14117
|
if (!adapter) return [];
|
|
@@ -14052,10 +14166,10 @@ function filterUninstallPlanBySelection(plan, selected) {
|
|
|
14052
14166
|
};
|
|
14053
14167
|
}
|
|
14054
14168
|
async function initPackage(root) {
|
|
14055
|
-
await mkdir23(
|
|
14056
|
-
await mkdir23(
|
|
14057
|
-
await mkdir23(
|
|
14058
|
-
const manifestPath =
|
|
14169
|
+
await mkdir23(join46(root, "instructions"), { recursive: true });
|
|
14170
|
+
await mkdir23(join46(root, "rules"), { recursive: true });
|
|
14171
|
+
await mkdir23(join46(root, "skills"), { recursive: true });
|
|
14172
|
+
const manifestPath = join46(root, "openpack.json");
|
|
14059
14173
|
const manifest = {
|
|
14060
14174
|
schemaVersion: 2,
|
|
14061
14175
|
name: "example/agentwheel-package",
|
|
@@ -14068,7 +14182,7 @@ async function initPackage(root) {
|
|
|
14068
14182
|
};
|
|
14069
14183
|
await writeFile22(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
14070
14184
|
`, "utf8");
|
|
14071
|
-
await writeFile22(
|
|
14185
|
+
await writeFile22(join46(root, "instructions", "AGENTS.md"), "# Agent Instructions\n", "utf8");
|
|
14072
14186
|
}
|
|
14073
14187
|
async function defaultBootstrapPackage(_root) {
|
|
14074
14188
|
const packageRoot = await findAgentwheelPackageRoot(dirname32(fileURLToPath3(import.meta.url)));
|
package/openpack.json
CHANGED
package/package.json
CHANGED