agentwheel 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -6
- package/dist/index.js +282 -116
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,17 +24,19 @@ So you copy-paste. You forget which agent has the latest version. You tweak a ru
|
|
|
24
24
|
```bash
|
|
25
25
|
npm i -g agentwheel
|
|
26
26
|
agentwheel add github:your-org/agent-pack
|
|
27
|
-
|
|
28
|
-
agentwheel
|
|
27
|
+
cd ~/.openclaw
|
|
28
|
+
agentwheel sync --dry-run # show me what would change
|
|
29
|
+
agentwheel sync # install into the detected runtime
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
No lock-in. No central gatekeeper. Your packages live in plain git repos, your customizations live in your own repo, and anything reachable by a URL just works.
|
|
32
33
|
|
|
33
34
|
---
|
|
34
35
|
|
|
35
|
-
> **Status: early (v0.
|
|
36
|
+
> **Status: early (v0.4).** The lifecycle core is real and tested — local/git/skillkit/vercel
|
|
36
37
|
> sources, optional registry discovery, plan/sync/update/drift/uninstall, overlays, eject/remember,
|
|
37
|
-
> profiles, rich JSON merge, and pluggable adapters.
|
|
38
|
+
> profiles, runtime auto-detection, fleet targeting, rich JSON merge, and pluggable adapters.
|
|
39
|
+
> Expect sharp edges.
|
|
38
40
|
|
|
39
41
|
## What it does
|
|
40
42
|
|
|
@@ -51,8 +53,9 @@ npm i -g agentwheel
|
|
|
51
53
|
|
|
52
54
|
agentwheel init
|
|
53
55
|
agentwheel add github:your-org/agent-pack --adapter openclaw --mode tracking
|
|
54
|
-
|
|
55
|
-
agentwheel
|
|
56
|
+
cd ~/.openclaw
|
|
57
|
+
agentwheel sync --dry-run
|
|
58
|
+
agentwheel sync
|
|
56
59
|
```
|
|
57
60
|
|
|
58
61
|
Prefer pnpm? `pnpm add -g agentwheel` works too.
|
|
@@ -69,6 +72,48 @@ pnpm link --global
|
|
|
69
72
|
|
|
70
73
|
`plan`, `sync --dry-run`, and `update --dry-run` show exactly what would change before anything is written. They're the commands to trust.
|
|
71
74
|
|
|
75
|
+
## Runtime targeting
|
|
76
|
+
|
|
77
|
+
Normal use no longer needs `--target-root`. Run agentwheel inside a runtime folder and it detects
|
|
78
|
+
the target:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd ~/.openclaw
|
|
82
|
+
agentwheel sync github:your-org/agent-pack
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
If the current directory is already the runtime directory (`~/.openclaw`), agentwheel uses its
|
|
86
|
+
parent as the root so output lands in `~/.openclaw/skills`, not `~/.openclaw/.openclaw/skills`.
|
|
87
|
+
If the current directory contains a runtime directory (`./.openclaw`), that directory is used as
|
|
88
|
+
the target under the current project.
|
|
89
|
+
|
|
90
|
+
For a control-plane setup, define named agents in config. Global config lives at
|
|
91
|
+
`~/.agentwheel/config.json`; project config lives at `.agentwheel/config.json`; project values win.
|
|
92
|
+
|
|
93
|
+
```jsonc
|
|
94
|
+
{
|
|
95
|
+
"agents": {
|
|
96
|
+
"lab-openclaw": { "adapter": "openclaw", "root": "/Users/me/.openclaw-home" },
|
|
97
|
+
"docs-copilot": { "adapter": "copilot", "root": "/Users/me/projects/docs" }
|
|
98
|
+
},
|
|
99
|
+
"profiles": {
|
|
100
|
+
"daily": [
|
|
101
|
+
{ "agent": "lab-openclaw" },
|
|
102
|
+
{ "agent": "docs-copilot" }
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
agentwheel sync --agent lab-openclaw
|
|
110
|
+
agentwheel sync --all
|
|
111
|
+
agentwheel sync --profile daily
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Target resolution order is exact: `--target-root` wins, then `--agent`, then auto-detect from the
|
|
115
|
+
current directory, then fallback to the current directory.
|
|
116
|
+
|
|
72
117
|
## Core ideas
|
|
73
118
|
|
|
74
119
|
**Three places, one direction:**
|
|
@@ -172,6 +217,7 @@ clear conversion format.
|
|
|
172
217
|
- [x] **v0.1** — install spine: local sources; openclaw/claude/codex adapters; skills/rules/instructions; `plan` · `sync` · `--dry-run` · `uninstall`; manifest + drift + idempotency.
|
|
173
218
|
- [x] **v0.2** — git source driver; `update` (pinned & tracking); overlays/additive/override/eject; `init`; hermes + copilot adapters; commands/mcp/hooks artifacts; OpenClaw semantic plugin planning.
|
|
174
219
|
- [x] **v0.3** — skillkit/vercel source drivers; optional registry & federation; programmatic adapters behind `--allow-adapter-code`; rich JSON merge for mcp/hooks/settings; profiles.
|
|
220
|
+
- [x] **v0.4** — runtime auto-detection; no `--target-root` needed for normal use; fleet config with named agents; global + project config merge; `--agent` and `--all`.
|
|
175
221
|
|
|
176
222
|
## Design docs
|
|
177
223
|
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/cli/index.ts
|
|
11
11
|
import { mkdir as mkdir7, rm as rm8, writeFile as writeFile4 } from "fs/promises";
|
|
12
|
-
import { join as
|
|
12
|
+
import { join as join19 } from "path";
|
|
13
13
|
import { Command } from "commander";
|
|
14
14
|
|
|
15
15
|
// src/adapters/resolve.ts
|
|
@@ -1584,7 +1584,8 @@ async function stageSource(driver, source, options = {}) {
|
|
|
1584
1584
|
|
|
1585
1585
|
// src/model/workspace.ts
|
|
1586
1586
|
import { readFile as readFile8 } from "fs/promises";
|
|
1587
|
-
import {
|
|
1587
|
+
import { homedir as homedir3 } from "os";
|
|
1588
|
+
import { dirname as dirname6, join as join13, resolve as resolve8 } from "path";
|
|
1588
1589
|
import { z as z5 } from "zod";
|
|
1589
1590
|
var workspacePackageSchema = z5.object({
|
|
1590
1591
|
name: z5.string().min(1),
|
|
@@ -1598,6 +1599,7 @@ var workspacePackageSchema = z5.object({
|
|
|
1598
1599
|
requestedRef: z5.string().min(1).optional()
|
|
1599
1600
|
});
|
|
1600
1601
|
var workspaceProfileRuntimeSchema = z5.object({
|
|
1602
|
+
agent: z5.string().min(1).optional(),
|
|
1601
1603
|
adapter: z5.string().min(1).default("openclaw"),
|
|
1602
1604
|
adapterConfig: z5.string().min(1).optional(),
|
|
1603
1605
|
adapterModule: z5.string().min(1).optional(),
|
|
@@ -1611,18 +1613,23 @@ var workspaceRegistrySchema = z5.object({
|
|
|
1611
1613
|
sources: z5.array(z5.string().min(1)).optional(),
|
|
1612
1614
|
ttlSeconds: z5.number().int().positive().optional()
|
|
1613
1615
|
}).default({});
|
|
1616
|
+
var workspaceAgentSchema = z5.object({
|
|
1617
|
+
adapter: z5.string().min(1),
|
|
1618
|
+
root: z5.string().min(1)
|
|
1619
|
+
});
|
|
1614
1620
|
var workspaceConfigSchema = z5.object({
|
|
1615
1621
|
schemaVersion: z5.literal(1),
|
|
1616
1622
|
packages: z5.array(workspacePackageSchema).default([]),
|
|
1617
1623
|
registry: workspaceRegistrySchema,
|
|
1618
|
-
profiles: z5.record(z5.string(), workspaceProfileSchema).default({})
|
|
1624
|
+
profiles: z5.record(z5.string(), workspaceProfileSchema).default({}),
|
|
1625
|
+
agents: z5.record(z5.string(), workspaceAgentSchema).default({})
|
|
1619
1626
|
});
|
|
1620
1627
|
function workspaceConfigPath(workspaceRoot) {
|
|
1621
1628
|
return join13(workspaceRoot, ".agentwheel", "config.json");
|
|
1622
1629
|
}
|
|
1623
1630
|
async function readWorkspaceConfig(workspaceRoot) {
|
|
1624
1631
|
const path = workspaceConfigPath(workspaceRoot);
|
|
1625
|
-
if (!await pathExists(path)) return
|
|
1632
|
+
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
1626
1633
|
return workspaceConfigSchema.parse(JSON.parse(await readFile8(path, "utf8")));
|
|
1627
1634
|
}
|
|
1628
1635
|
async function writeWorkspaceConfig(workspaceRoot, config) {
|
|
@@ -1632,15 +1639,58 @@ function upsertPackage(config, entry) {
|
|
|
1632
1639
|
const packages = config.packages.filter((candidate) => candidate.name !== entry.name);
|
|
1633
1640
|
packages.push(entry);
|
|
1634
1641
|
packages.sort((a, b) => a.name.localeCompare(b.name));
|
|
1635
|
-
return { schemaVersion: 1, packages, registry: config.registry ?? {}, profiles: config.profiles ?? {} };
|
|
1642
|
+
return { schemaVersion: 1, packages, registry: config.registry ?? {}, profiles: config.profiles ?? {}, agents: config.agents ?? {} };
|
|
1643
|
+
}
|
|
1644
|
+
function globalWorkspaceConfigPath(globalRoot = homedir3()) {
|
|
1645
|
+
return join13(globalRoot, ".agentwheel", "config.json");
|
|
1646
|
+
}
|
|
1647
|
+
async function findWorkspaceRoot(start = process.cwd()) {
|
|
1648
|
+
let current = resolve8(start);
|
|
1649
|
+
while (true) {
|
|
1650
|
+
if (await pathExists(workspaceConfigPath(current))) return current;
|
|
1651
|
+
const parent = dirname6(current);
|
|
1652
|
+
if (parent === current) return resolve8(start);
|
|
1653
|
+
current = parent;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
async function readMergedWorkspaceConfig(projectRoot, options = {}) {
|
|
1657
|
+
const global = await readConfigPath(globalWorkspaceConfigPath(options.globalRoot));
|
|
1658
|
+
const project = await readWorkspaceConfig(projectRoot);
|
|
1659
|
+
return mergeWorkspaceConfig(global, project);
|
|
1660
|
+
}
|
|
1661
|
+
function mergeWorkspaceConfig(global, project) {
|
|
1662
|
+
return workspaceConfigSchema.parse({
|
|
1663
|
+
schemaVersion: 1,
|
|
1664
|
+
packages: project.packages.length > 0 ? project.packages : global.packages,
|
|
1665
|
+
registry: {
|
|
1666
|
+
...global.registry,
|
|
1667
|
+
...project.registry,
|
|
1668
|
+
sources: project.registry.sources ?? global.registry.sources,
|
|
1669
|
+
ttlSeconds: project.registry.ttlSeconds ?? global.registry.ttlSeconds
|
|
1670
|
+
},
|
|
1671
|
+
profiles: { ...global.profiles, ...project.profiles },
|
|
1672
|
+
agents: { ...global.agents, ...project.agents }
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
function resolveConfigPath(path, baseRoot) {
|
|
1676
|
+
if (path.startsWith("~/")) return resolve8(homedir3(), path.slice(2));
|
|
1677
|
+
if (path === "~") return homedir3();
|
|
1678
|
+
return path.startsWith("/") ? resolve8(path) : resolve8(baseRoot, path);
|
|
1679
|
+
}
|
|
1680
|
+
function emptyWorkspaceConfig() {
|
|
1681
|
+
return { schemaVersion: 1, packages: [], registry: {}, profiles: {}, agents: {} };
|
|
1682
|
+
}
|
|
1683
|
+
async function readConfigPath(path) {
|
|
1684
|
+
if (!await pathExists(path)) return emptyWorkspaceConfig();
|
|
1685
|
+
return workspaceConfigSchema.parse(JSON.parse(await readFile8(path, "utf8")));
|
|
1636
1686
|
}
|
|
1637
1687
|
|
|
1638
1688
|
// src/lifecycle/customization.ts
|
|
1639
1689
|
import { appendFile, cp as cp4, mkdir as mkdir6, rm as rm5 } from "fs/promises";
|
|
1640
|
-
import { dirname as
|
|
1690
|
+
import { dirname as dirname7, join as join14 } from "path";
|
|
1641
1691
|
async function remember(workspaceRoot, runtime, text) {
|
|
1642
1692
|
const overlayPath = join14(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
|
|
1643
|
-
await mkdir6(
|
|
1693
|
+
await mkdir6(dirname7(overlayPath), { recursive: true });
|
|
1644
1694
|
await appendFile(overlayPath, `${text.trim()}
|
|
1645
1695
|
`, "utf8");
|
|
1646
1696
|
return { overlayPath };
|
|
@@ -1665,7 +1715,7 @@ async function ejectArtifact(workspaceRoot, item) {
|
|
|
1665
1715
|
throw new Error(`Artifact not found: ${item}`);
|
|
1666
1716
|
}
|
|
1667
1717
|
const ejectedPath = join14(workspaceRoot, ".agentwheel", "ejected", ...parsed.packageName.split("/"), parsed.type, parsed.name);
|
|
1668
|
-
await mkdir6(
|
|
1718
|
+
await mkdir6(dirname7(ejectedPath), { recursive: true });
|
|
1669
1719
|
await rm5(ejectedPath, { recursive: true, force: true });
|
|
1670
1720
|
await cp4(artifact.stagedPath ?? artifact.sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
|
|
1671
1721
|
return { ...parsed, ejectedPath };
|
|
@@ -1690,8 +1740,8 @@ import { join as join16 } from "path";
|
|
|
1690
1740
|
|
|
1691
1741
|
// src/registry/client.ts
|
|
1692
1742
|
import { readFile as readFile9, rm as rm6, stat as stat6 } from "fs/promises";
|
|
1693
|
-
import { homedir as
|
|
1694
|
-
import { dirname as
|
|
1743
|
+
import { homedir as homedir4 } from "os";
|
|
1744
|
+
import { dirname as dirname8, join as join15, resolve as resolve9 } from "path";
|
|
1695
1745
|
import { fileURLToPath } from "url";
|
|
1696
1746
|
|
|
1697
1747
|
// src/model/registry.ts
|
|
@@ -1762,7 +1812,7 @@ var RegistryClient = class {
|
|
|
1762
1812
|
return process.env.AGENTWHEEL_REGISTRY.split(",").map((source) => source.trim()).filter(Boolean);
|
|
1763
1813
|
}
|
|
1764
1814
|
if (this.options.workspaceRoot) {
|
|
1765
|
-
const config = await
|
|
1815
|
+
const config = await readMergedWorkspaceConfig(this.options.workspaceRoot);
|
|
1766
1816
|
if (config.registry.sources?.length) return config.registry.sources;
|
|
1767
1817
|
}
|
|
1768
1818
|
return [DEFAULT_REGISTRY_SOURCE];
|
|
@@ -1770,7 +1820,7 @@ var RegistryClient = class {
|
|
|
1770
1820
|
async getTtlMs() {
|
|
1771
1821
|
if (this.options.ttlMs !== void 0) return this.options.ttlMs;
|
|
1772
1822
|
if (this.options.workspaceRoot) {
|
|
1773
|
-
const config = await
|
|
1823
|
+
const config = await readMergedWorkspaceConfig(this.options.workspaceRoot);
|
|
1774
1824
|
if (config.registry.ttlSeconds !== void 0) return config.registry.ttlSeconds * 1e3;
|
|
1775
1825
|
}
|
|
1776
1826
|
return DEFAULT_REGISTRY_TTL_MS;
|
|
@@ -1794,11 +1844,11 @@ var RegistryClient = class {
|
|
|
1794
1844
|
}
|
|
1795
1845
|
const filePath = source.startsWith("file:") ? fileURLToPath(source) : source;
|
|
1796
1846
|
if (await pathExists(filePath)) {
|
|
1797
|
-
const fullPath =
|
|
1847
|
+
const fullPath = resolve9(filePath);
|
|
1798
1848
|
const stats = await stat6(fullPath);
|
|
1799
1849
|
return readFile9(stats.isDirectory() ? join15(fullPath, "index.json") : fullPath, "utf8");
|
|
1800
1850
|
}
|
|
1801
|
-
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join15(
|
|
1851
|
+
const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join15(dirname8(this.cachePath), "registry-repos") }));
|
|
1802
1852
|
return readFile9(join15(resolved.resolvedPath, "index.json"), "utf8");
|
|
1803
1853
|
}
|
|
1804
1854
|
};
|
|
@@ -1821,7 +1871,7 @@ function mergeIndexes(indexes) {
|
|
|
1821
1871
|
return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
1822
1872
|
}
|
|
1823
1873
|
function defaultRegistryCachePath() {
|
|
1824
|
-
return join15(
|
|
1874
|
+
return join15(homedir4(), ".agentwheel", "registry-cache.json");
|
|
1825
1875
|
}
|
|
1826
1876
|
function sameSources(a, b) {
|
|
1827
1877
|
return a.length === b.length && a.every((source, index) => source === b[index]);
|
|
@@ -1829,7 +1879,7 @@ function sameSources(a, b) {
|
|
|
1829
1879
|
|
|
1830
1880
|
// src/lifecycle/profile.ts
|
|
1831
1881
|
async function syncProfile(options) {
|
|
1832
|
-
const config = await
|
|
1882
|
+
const config = await readMergedWorkspaceConfig(options.workspaceRoot);
|
|
1833
1883
|
const profile = config.profiles[options.profile];
|
|
1834
1884
|
if (!profile) {
|
|
1835
1885
|
throw new Error(`Unknown profile: ${options.profile}`);
|
|
@@ -1841,9 +1891,9 @@ async function syncProfile(options) {
|
|
|
1841
1891
|
const results = [];
|
|
1842
1892
|
for (const pkg of packages) {
|
|
1843
1893
|
for (const runtime of profile.runtimes) {
|
|
1844
|
-
const
|
|
1894
|
+
const target = resolveProfileRuntime(runtime, config, options.workspaceRoot);
|
|
1845
1895
|
const adapter = await resolveAdapter({
|
|
1846
|
-
adapter:
|
|
1896
|
+
adapter: target.adapter,
|
|
1847
1897
|
adapterConfig: runtime.adapterConfig,
|
|
1848
1898
|
adapterModule: runtime.adapterModule,
|
|
1849
1899
|
allowAdapterCode: options.allowAdapterCode,
|
|
@@ -1858,8 +1908,8 @@ async function syncProfile(options) {
|
|
|
1858
1908
|
mode: options.mode ?? pkg.mode
|
|
1859
1909
|
});
|
|
1860
1910
|
try {
|
|
1861
|
-
const plan = await createInstallPlan(bundle, adapter, targetRoot, await readInstallManifest(targetRoot, adapter.name));
|
|
1862
|
-
results.push({ runtime: adapter.name, packageName: pkg.name, plan });
|
|
1911
|
+
const plan = await createInstallPlan(bundle, adapter, target.targetRoot, await readInstallManifest(target.targetRoot, adapter.name));
|
|
1912
|
+
results.push({ runtime: adapter.name, targetRoot: target.targetRoot, packageName: pkg.name, plan });
|
|
1863
1913
|
if (!options.dryRun) {
|
|
1864
1914
|
await applyInstallPlan(plan, bundle.sourceLock, { executePlugins: runtime.executePlugins ?? options.executePlugins });
|
|
1865
1915
|
}
|
|
@@ -1870,6 +1920,17 @@ async function syncProfile(options) {
|
|
|
1870
1920
|
}
|
|
1871
1921
|
return results;
|
|
1872
1922
|
}
|
|
1923
|
+
function resolveProfileRuntime(runtime, config, workspaceRoot) {
|
|
1924
|
+
if (runtime.agent) {
|
|
1925
|
+
const agent = config.agents[runtime.agent];
|
|
1926
|
+
if (!agent) throw new Error(`Unknown agent in profile: ${runtime.agent}`);
|
|
1927
|
+
return { adapter: agent.adapter, targetRoot: resolveConfigPath(agent.root, workspaceRoot) };
|
|
1928
|
+
}
|
|
1929
|
+
return {
|
|
1930
|
+
adapter: runtime.adapter,
|
|
1931
|
+
targetRoot: runtime.targetRoot ? resolveConfigPath(runtime.targetRoot, workspaceRoot) : workspaceRoot
|
|
1932
|
+
};
|
|
1933
|
+
}
|
|
1873
1934
|
async function packageFromSource(source, options) {
|
|
1874
1935
|
const resolved = await resolvePackageSource(source, options.workspaceRoot);
|
|
1875
1936
|
const driver = options.driver ?? inferSourceDriverName(resolved.source);
|
|
@@ -1885,13 +1946,14 @@ async function packageFromSource(source, options) {
|
|
|
1885
1946
|
// src/lifecycle/source-plan.ts
|
|
1886
1947
|
import { join as join17 } from "path";
|
|
1887
1948
|
async function createSourcePlan(options) {
|
|
1888
|
-
const
|
|
1949
|
+
const workspaceRoot = options.workspaceRoot ?? options.targetRoot;
|
|
1950
|
+
const resolvedInput = await resolvePackageSource(options.source, workspaceRoot);
|
|
1889
1951
|
const resolvedSource = resolvedInput.source;
|
|
1890
1952
|
const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedSource));
|
|
1891
1953
|
const bundle = await stageSource(driver, resolvedSource, {
|
|
1892
|
-
workspaceRoot
|
|
1954
|
+
workspaceRoot,
|
|
1893
1955
|
adapter: options.adapter,
|
|
1894
|
-
cacheRoot: join17(
|
|
1956
|
+
cacheRoot: join17(workspaceRoot, ".agentwheel", "cache"),
|
|
1895
1957
|
mode: options.mode
|
|
1896
1958
|
});
|
|
1897
1959
|
const manifest = await readInstallManifest(options.targetRoot, options.adapter.name);
|
|
@@ -1916,9 +1978,97 @@ function shouldUpdatePackage(pkg, lock) {
|
|
|
1916
1978
|
return { shouldUpdate: false, reason: "pinned source unchanged" };
|
|
1917
1979
|
}
|
|
1918
1980
|
|
|
1981
|
+
// src/runtime/target.ts
|
|
1982
|
+
import { basename as basename7, dirname as dirname9, join as join18, resolve as resolve10 } from "path";
|
|
1983
|
+
var runtimeMarkers = [
|
|
1984
|
+
{ adapter: "openclaw", dirs: [".openclaw", ".clawdbot", ".moltbot"] },
|
|
1985
|
+
{ adapter: "claude", dirs: [".claude"] },
|
|
1986
|
+
{ adapter: "codex", dirs: [".codex"] },
|
|
1987
|
+
{ adapter: "hermes", dirs: [".hermes"] },
|
|
1988
|
+
{ adapter: "copilot", dirs: [".github"] }
|
|
1989
|
+
];
|
|
1990
|
+
async function resolveRuntimeTarget(request = {}) {
|
|
1991
|
+
const cwd = resolve10(request.cwd ?? process.cwd());
|
|
1992
|
+
if (request.targetRoot) {
|
|
1993
|
+
const targetRoot = resolve10(request.targetRoot);
|
|
1994
|
+
return {
|
|
1995
|
+
adapter: request.adapter ?? "openclaw",
|
|
1996
|
+
targetRoot,
|
|
1997
|
+
workspaceRoot: targetRoot,
|
|
1998
|
+
source: "target-root"
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
const workspaceRoot = await findWorkspaceRoot(cwd);
|
|
2002
|
+
const config = await readMergedWorkspaceConfig(workspaceRoot, { globalRoot: request.globalRoot });
|
|
2003
|
+
if (request.agent) {
|
|
2004
|
+
return targetFromAgent(request.agent, config, workspaceRoot);
|
|
2005
|
+
}
|
|
2006
|
+
const detected = await detectRuntimeTarget(cwd, request.adapter);
|
|
2007
|
+
if (detected) {
|
|
2008
|
+
return { ...detected, workspaceRoot: await findWorkspaceRoot(detected.targetRoot), source: "auto-detect" };
|
|
2009
|
+
}
|
|
2010
|
+
return {
|
|
2011
|
+
adapter: request.adapter ?? "openclaw",
|
|
2012
|
+
targetRoot: cwd,
|
|
2013
|
+
workspaceRoot,
|
|
2014
|
+
source: "cwd"
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
async function resolveAllRuntimeTargets(request = {}) {
|
|
2018
|
+
if (request.targetRoot) return [await resolveRuntimeTarget(request)];
|
|
2019
|
+
if (request.agent) return [await resolveRuntimeTarget(request)];
|
|
2020
|
+
const cwd = resolve10(request.cwd ?? process.cwd());
|
|
2021
|
+
const workspaceRoot = await findWorkspaceRoot(cwd);
|
|
2022
|
+
const config = await readMergedWorkspaceConfig(workspaceRoot, { globalRoot: request.globalRoot });
|
|
2023
|
+
const targets = Object.entries(config.agents).map(([name]) => targetFromAgent(name, config, workspaceRoot));
|
|
2024
|
+
if (targets.length === 0) {
|
|
2025
|
+
throw new Error("No agents configured. Add agents to .agentwheel/config.json or pass --target-root.");
|
|
2026
|
+
}
|
|
2027
|
+
return targets;
|
|
2028
|
+
}
|
|
2029
|
+
async function detectRuntimeTarget(cwd = process.cwd(), adapterFilter) {
|
|
2030
|
+
const root = resolve10(cwd);
|
|
2031
|
+
const matches = [];
|
|
2032
|
+
for (const marker of runtimeMarkers) {
|
|
2033
|
+
if (adapterFilter && marker.adapter !== adapterFilter) continue;
|
|
2034
|
+
for (const dir of marker.dirs) {
|
|
2035
|
+
if (basename7(root) === dir) {
|
|
2036
|
+
matches.push({ adapter: marker.adapter, targetRoot: dirname9(root) });
|
|
2037
|
+
} else if (await pathExists(join18(root, dir))) {
|
|
2038
|
+
matches.push({ adapter: marker.adapter, targetRoot: root });
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
const unique = dedupeTargets(matches);
|
|
2043
|
+
if (unique.length > 1) {
|
|
2044
|
+
throw new Error(`Multiple runtime directories detected: ${unique.map((item) => `${item.adapter} at ${item.targetRoot}`).join(", ")}. Pass --adapter or --agent.`);
|
|
2045
|
+
}
|
|
2046
|
+
return unique[0];
|
|
2047
|
+
}
|
|
2048
|
+
function targetFromAgent(name, config, workspaceRoot) {
|
|
2049
|
+
const agent = config.agents[name];
|
|
2050
|
+
if (!agent) {
|
|
2051
|
+
throw new Error(`Unknown agent: ${name}`);
|
|
2052
|
+
}
|
|
2053
|
+
return {
|
|
2054
|
+
agentName: name,
|
|
2055
|
+
adapter: agent.adapter,
|
|
2056
|
+
targetRoot: resolveConfigPath(agent.root, workspaceRoot),
|
|
2057
|
+
workspaceRoot,
|
|
2058
|
+
source: "agent"
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
function dedupeTargets(matches) {
|
|
2062
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
2063
|
+
for (const match of matches) {
|
|
2064
|
+
byKey.set(`${match.adapter}:${match.targetRoot}`, match);
|
|
2065
|
+
}
|
|
2066
|
+
return [...byKey.values()];
|
|
2067
|
+
}
|
|
2068
|
+
|
|
1919
2069
|
// src/cli/index.ts
|
|
1920
2070
|
var program = new Command();
|
|
1921
|
-
program.name("agentwheel").description("Multi-runtime agent artifact orchestrator").version("0.
|
|
2071
|
+
program.name("agentwheel").description("Multi-runtime agent artifact orchestrator").version("0.4.0");
|
|
1922
2072
|
program.command("init").argument("[kind]", "workspace or package", "workspace").option("--target-root <path>", "workspace root", process.cwd()).action(async (kind, options) => {
|
|
1923
2073
|
const root = normalizeTargetRoot(options.targetRoot);
|
|
1924
2074
|
if (kind === "package") {
|
|
@@ -1949,7 +2099,7 @@ program.command("add").argument("<source>", "package source").option("--driver <
|
|
|
1949
2099
|
const bundle = await stageSource(driver, resolvedSource, {
|
|
1950
2100
|
workspaceRoot: targetRoot,
|
|
1951
2101
|
adapter,
|
|
1952
|
-
cacheRoot:
|
|
2102
|
+
cacheRoot: join19(targetRoot, ".agentwheel", "cache"),
|
|
1953
2103
|
mode: options.mode
|
|
1954
2104
|
});
|
|
1955
2105
|
const name = options.name ?? resolvedInput.registryEntry?.name ?? bundle.source.packageName ?? source;
|
|
@@ -1972,7 +2122,7 @@ program.command("list").argument("<source>", "package source").option("--driver
|
|
|
1972
2122
|
const targetRoot = normalizeTargetRoot(options.targetRoot);
|
|
1973
2123
|
const resolvedInput = await resolvePackageSource(source, targetRoot);
|
|
1974
2124
|
const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
|
|
1975
|
-
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot:
|
|
2125
|
+
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join19(targetRoot, ".agentwheel", "cache") }))));
|
|
1976
2126
|
const artifacts = await driver.list(resolved);
|
|
1977
2127
|
for (const artifact of artifacts) {
|
|
1978
2128
|
console.log(`${artifact.type} ${artifact.name} ${artifact.relativePath}`);
|
|
@@ -1982,7 +2132,7 @@ program.command("scan").argument("<source>", "package source").option("--driver
|
|
|
1982
2132
|
const targetRoot = normalizeTargetRoot(options.targetRoot);
|
|
1983
2133
|
const resolvedInput = await resolvePackageSource(source, targetRoot);
|
|
1984
2134
|
const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
|
|
1985
|
-
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot:
|
|
2135
|
+
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join19(targetRoot, ".agentwheel", "cache") }))));
|
|
1986
2136
|
const result = await driver.scan(resolved);
|
|
1987
2137
|
if (result.findings.length === 0) {
|
|
1988
2138
|
console.log("Scan ok: no findings");
|
|
@@ -1993,17 +2143,20 @@ program.command("scan").argument("<source>", "package source").option("--driver
|
|
|
1993
2143
|
}
|
|
1994
2144
|
if (!result.ok) process.exitCode = 1;
|
|
1995
2145
|
});
|
|
1996
|
-
program.command("plan").argument("<source>", "source directory").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter", "openclaw").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root",
|
|
1997
|
-
const
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2146
|
+
program.command("plan").argument("<source>", "source directory").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter", "openclaw").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--mode <mode>", "pinned or tracking").option("--dry-run", "accepted for symmetry; plan never writes", false).action(async (source, options) => {
|
|
2147
|
+
const targets = await resolveCliTargets(options);
|
|
2148
|
+
for (const target of targets) {
|
|
2149
|
+
const { plan, bundle } = await buildPlan(source, target, options);
|
|
2150
|
+
console.log(formatPlan(plan));
|
|
2151
|
+
await rm8(bundle.root, { recursive: true, force: true });
|
|
2152
|
+
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2153
|
+
}
|
|
2001
2154
|
});
|
|
2002
|
-
program.command("sync").argument("[source]", "source directory").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter", "openclaw").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root",
|
|
2155
|
+
program.command("sync").argument("[source]", "source directory").option("--driver <driver>", "source driver").option("--adapter <adapter>", "built-in adapter", "openclaw").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--mode <mode>", "pinned or tracking").option("--profile <name>", "workspace runtime profile").option("--dry-run", "show plan without writing", false).option("--execute-plugins", "execute semantic plugin installs", false).action(async (source, options) => {
|
|
2003
2156
|
if (options.profile) {
|
|
2004
|
-
const
|
|
2157
|
+
const target = await resolveRuntimeTarget({ targetRoot: options.targetRoot, adapter: options.adapter, agent: options.agent });
|
|
2005
2158
|
const results = await syncProfile({
|
|
2006
|
-
workspaceRoot:
|
|
2159
|
+
workspaceRoot: target.workspaceRoot,
|
|
2007
2160
|
profile: options.profile,
|
|
2008
2161
|
source,
|
|
2009
2162
|
driver: options.driver,
|
|
@@ -2014,66 +2167,37 @@ program.command("sync").argument("[source]", "source directory").option("--drive
|
|
|
2014
2167
|
warn: (message) => console.warn(message)
|
|
2015
2168
|
});
|
|
2016
2169
|
for (const result of results) {
|
|
2017
|
-
console.log(`Profile ${options.profile} / ${result.runtime} / ${result.packageName}:`);
|
|
2170
|
+
console.log(`Profile ${options.profile} / ${result.runtime} / ${result.packageName} at ${result.targetRoot}:`);
|
|
2018
2171
|
console.log(formatPlan(result.plan));
|
|
2019
2172
|
if (result.plan.hasBlockingChanges) process.exitCode = 1;
|
|
2020
2173
|
}
|
|
2021
2174
|
if (!options.dryRun) console.log("Applied.");
|
|
2022
2175
|
return;
|
|
2023
2176
|
}
|
|
2177
|
+
const targets = await resolveCliTargets(options);
|
|
2024
2178
|
if (!source) {
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
console.log(formatPlan(plan));
|
|
2029
|
-
if (!options.dryRun) {
|
|
2030
|
-
await applyInstallPlan(plan, bundle.sourceLock, { executePlugins: options.executePlugins });
|
|
2031
|
-
console.log("Applied.");
|
|
2032
|
-
}
|
|
2033
|
-
await rm8(bundle.root, { recursive: true, force: true });
|
|
2034
|
-
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2035
|
-
});
|
|
2036
|
-
program.command("update").option("--target-root <path>", "workspace root", process.cwd()).option("--dry-run", "show plans without writing", false).option("--execute-plugins", "execute semantic plugin installs", false).option("--allow-adapter-code", "allow loading local adapter code from configured packages", false).action(async (options) => {
|
|
2037
|
-
const targetRoot = normalizeTargetRoot(options.targetRoot);
|
|
2038
|
-
const config = await readWorkspaceConfig(targetRoot);
|
|
2039
|
-
if (config.packages.length === 0) {
|
|
2040
|
-
console.log("No packages configured.");
|
|
2179
|
+
for (const target of targets) {
|
|
2180
|
+
await runConfiguredPackages(target, options, { useUpdateDecision: false });
|
|
2181
|
+
}
|
|
2041
2182
|
return;
|
|
2042
2183
|
}
|
|
2043
|
-
for (const
|
|
2044
|
-
const
|
|
2045
|
-
adapter: pkg.adapter,
|
|
2046
|
-
adapterConfig: pkg.adapterConfig,
|
|
2047
|
-
adapterModule: pkg.adapterModule,
|
|
2048
|
-
allowAdapterCode: options.allowAdapterCode,
|
|
2049
|
-
baseDir: targetRoot,
|
|
2050
|
-
warn: (message) => console.warn(message)
|
|
2051
|
-
});
|
|
2052
|
-
const lock = await readSourceLock(targetRoot, adapter.name);
|
|
2053
|
-
const decision = shouldUpdatePackage(pkg, lock);
|
|
2054
|
-
if (!decision.shouldUpdate) {
|
|
2055
|
-
console.log(`Skipping ${pkg.name}: ${decision.reason}.`);
|
|
2056
|
-
continue;
|
|
2057
|
-
}
|
|
2058
|
-
const { plan, bundle } = await buildPlan(pkg.source, {
|
|
2059
|
-
driver: pkg.driver,
|
|
2060
|
-
adapter: pkg.adapter,
|
|
2061
|
-
adapterConfig: pkg.adapterConfig,
|
|
2062
|
-
adapterModule: pkg.adapterModule,
|
|
2063
|
-
allowAdapterCode: options.allowAdapterCode,
|
|
2064
|
-
targetRoot,
|
|
2065
|
-
mode: pkg.mode
|
|
2066
|
-
});
|
|
2067
|
-
console.log(`Update ${pkg.name}:`);
|
|
2184
|
+
for (const target of targets) {
|
|
2185
|
+
const { plan, bundle } = await buildPlan(source, target, options);
|
|
2068
2186
|
console.log(formatPlan(plan));
|
|
2069
2187
|
if (!options.dryRun) {
|
|
2070
2188
|
await applyInstallPlan(plan, bundle.sourceLock, { executePlugins: options.executePlugins });
|
|
2071
|
-
console.log(`Applied ${
|
|
2189
|
+
console.log(`Applied ${target.adapter} at ${target.targetRoot}.`);
|
|
2072
2190
|
}
|
|
2073
2191
|
await rm8(bundle.root, { recursive: true, force: true });
|
|
2074
2192
|
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2075
2193
|
}
|
|
2076
2194
|
});
|
|
2195
|
+
program.command("update").option("--adapter <adapter>", "built-in adapter").option("--target-root <path>", "workspace root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--dry-run", "show plans without writing", false).option("--execute-plugins", "execute semantic plugin installs", false).option("--allow-adapter-code", "allow loading local adapter code from configured packages", false).action(async (options) => {
|
|
2196
|
+
const targets = await resolveCliTargets(options);
|
|
2197
|
+
for (const target of targets) {
|
|
2198
|
+
await runConfiguredPackages(target, options, { useUpdateDecision: true });
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2077
2201
|
program.command("registry").description("manage optional registry indexes").addCommand(
|
|
2078
2202
|
new Command("update").description("refresh the local registry cache").option("--target-root <path>", "workspace root", process.cwd()).action(async (options) => {
|
|
2079
2203
|
const client = new RegistryClient({ workspaceRoot: normalizeTargetRoot(options.targetRoot) });
|
|
@@ -2101,54 +2225,96 @@ program.command("eject").argument("<item>", "package/type/name").option("--targe
|
|
|
2101
2225
|
const result = await ejectArtifact(targetRoot, item);
|
|
2102
2226
|
console.log(`Ejected ${item} to ${result.ejectedPath}.`);
|
|
2103
2227
|
});
|
|
2104
|
-
program.command("uninstall").option("--adapter <adapter>", "adapter", "openclaw").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root",
|
|
2105
|
-
const
|
|
2106
|
-
const
|
|
2107
|
-
adapter
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
await uninstall(plan, options.dryRun);
|
|
2122
|
-
if (!options.dryRun && programmaticAdapter) {
|
|
2123
|
-
await programmaticAdapter.programmatic?.uninstall?.({ targetRoot, adapterName: programmaticAdapter.name });
|
|
2228
|
+
program.command("uninstall").option("--adapter <adapter>", "adapter", "openclaw").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("--target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--all", "run for every configured agent", false).option("--dry-run", "show removals without writing", false).action(async (options) => {
|
|
2229
|
+
const targets = await resolveCliTargets(options);
|
|
2230
|
+
for (const target of targets) {
|
|
2231
|
+
const adapter = await resolveAdapterForTarget(target, options);
|
|
2232
|
+
const manifest = await readInstallManifest(target.targetRoot, adapter.name);
|
|
2233
|
+
if (!manifest) {
|
|
2234
|
+
console.log(`No install manifest for ${adapter.name} at ${target.targetRoot}`);
|
|
2235
|
+
continue;
|
|
2236
|
+
}
|
|
2237
|
+
const plan = await createUninstallPlan(manifest);
|
|
2238
|
+
console.log(formatPlan(plan));
|
|
2239
|
+
await uninstall(plan, options.dryRun);
|
|
2240
|
+
if (!options.dryRun) {
|
|
2241
|
+
await adapter.programmatic?.uninstall?.({ targetRoot: target.targetRoot, adapterName: adapter.name });
|
|
2242
|
+
console.log(`Uninstalled ${adapter.name} at ${target.targetRoot}.`);
|
|
2243
|
+
}
|
|
2244
|
+
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2124
2245
|
}
|
|
2125
|
-
if (!options.dryRun) console.log("Uninstalled.");
|
|
2126
|
-
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2127
2246
|
});
|
|
2128
|
-
async function buildPlan(source, options) {
|
|
2129
|
-
const
|
|
2130
|
-
const adapter = await resolveAdapter({
|
|
2131
|
-
adapter: options.adapter,
|
|
2132
|
-
adapterConfig: options.adapterConfig,
|
|
2133
|
-
adapterModule: options.adapterModule,
|
|
2134
|
-
allowAdapterCode: options.allowAdapterCode,
|
|
2135
|
-
baseDir: targetRoot,
|
|
2136
|
-
warn: (message) => console.warn(message)
|
|
2137
|
-
});
|
|
2247
|
+
async function buildPlan(source, target, options) {
|
|
2248
|
+
const adapter = await resolveAdapterForTarget(target, options);
|
|
2138
2249
|
const result = await createSourcePlan({
|
|
2139
2250
|
source,
|
|
2140
|
-
targetRoot,
|
|
2251
|
+
targetRoot: target.targetRoot,
|
|
2252
|
+
workspaceRoot: target.workspaceRoot,
|
|
2141
2253
|
adapter,
|
|
2142
2254
|
driver: options.driver,
|
|
2143
2255
|
mode: options.mode
|
|
2144
2256
|
});
|
|
2145
2257
|
return { plan: result.plan, bundle: result.bundle };
|
|
2146
2258
|
}
|
|
2259
|
+
async function resolveCliTargets(options) {
|
|
2260
|
+
if (options.all) {
|
|
2261
|
+
return resolveAllRuntimeTargets({ targetRoot: options.targetRoot, adapter: options.adapter, agent: options.agent, all: options.all });
|
|
2262
|
+
}
|
|
2263
|
+
return [await resolveRuntimeTarget({ targetRoot: options.targetRoot, adapter: options.adapter, agent: options.agent })];
|
|
2264
|
+
}
|
|
2265
|
+
async function resolveAdapterForTarget(target, options) {
|
|
2266
|
+
return resolveAdapter({
|
|
2267
|
+
adapter: target.adapter,
|
|
2268
|
+
adapterConfig: options.adapterConfig,
|
|
2269
|
+
adapterModule: options.adapterModule,
|
|
2270
|
+
allowAdapterCode: options.allowAdapterCode,
|
|
2271
|
+
baseDir: target.workspaceRoot,
|
|
2272
|
+
warn: (message) => console.warn(message)
|
|
2273
|
+
});
|
|
2274
|
+
}
|
|
2275
|
+
async function runConfiguredPackages(target, options, behavior) {
|
|
2276
|
+
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
2277
|
+
if (config.packages.length === 0) {
|
|
2278
|
+
console.log(`No packages configured at ${target.workspaceRoot}.`);
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
for (const pkg of config.packages) {
|
|
2282
|
+
const targetForPackage = options.adapter || target.source !== "cwd" ? target : { ...target, adapter: pkg.adapter };
|
|
2283
|
+
const adapter = await resolveAdapterForTarget(targetForPackage, {
|
|
2284
|
+
adapterConfig: options.adapterConfig ?? pkg.adapterConfig,
|
|
2285
|
+
adapterModule: options.adapterModule ?? pkg.adapterModule,
|
|
2286
|
+
allowAdapterCode: options.allowAdapterCode
|
|
2287
|
+
});
|
|
2288
|
+
if (behavior.useUpdateDecision) {
|
|
2289
|
+
const lock = await readSourceLock(targetForPackage.targetRoot, adapter.name);
|
|
2290
|
+
const decision = shouldUpdatePackage(pkg, lock);
|
|
2291
|
+
if (!decision.shouldUpdate) {
|
|
2292
|
+
console.log(`Skipping ${pkg.name}: ${decision.reason}.`);
|
|
2293
|
+
continue;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
const { plan, bundle } = await buildPlan(pkg.source, targetForPackage, {
|
|
2297
|
+
driver: pkg.driver,
|
|
2298
|
+
adapterConfig: options.adapterConfig ?? pkg.adapterConfig,
|
|
2299
|
+
adapterModule: options.adapterModule ?? pkg.adapterModule,
|
|
2300
|
+
allowAdapterCode: options.allowAdapterCode,
|
|
2301
|
+
mode: pkg.mode
|
|
2302
|
+
});
|
|
2303
|
+
console.log(`${behavior.useUpdateDecision ? "Update" : "Sync"} ${pkg.name} (${adapter.name} at ${targetForPackage.targetRoot}):`);
|
|
2304
|
+
console.log(formatPlan(plan));
|
|
2305
|
+
if (!options.dryRun) {
|
|
2306
|
+
await applyInstallPlan(plan, bundle.sourceLock, { executePlugins: options.executePlugins });
|
|
2307
|
+
console.log(`Applied ${pkg.name}.`);
|
|
2308
|
+
}
|
|
2309
|
+
await rm8(bundle.root, { recursive: true, force: true });
|
|
2310
|
+
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2147
2313
|
async function initPackage(root) {
|
|
2148
|
-
await mkdir7(
|
|
2149
|
-
await mkdir7(
|
|
2150
|
-
await mkdir7(
|
|
2151
|
-
const manifestPath =
|
|
2314
|
+
await mkdir7(join19(root, "instructions"), { recursive: true });
|
|
2315
|
+
await mkdir7(join19(root, "rules"), { recursive: true });
|
|
2316
|
+
await mkdir7(join19(root, "skills"), { recursive: true });
|
|
2317
|
+
const manifestPath = join19(root, "agentwheel.json");
|
|
2152
2318
|
const manifest = {
|
|
2153
2319
|
schemaVersion: 1,
|
|
2154
2320
|
name: "example/agentwheel-package",
|
|
@@ -2161,7 +2327,7 @@ async function initPackage(root) {
|
|
|
2161
2327
|
};
|
|
2162
2328
|
await writeFile4(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
2163
2329
|
`, "utf8");
|
|
2164
|
-
await writeFile4(
|
|
2330
|
+
await writeFile4(join19(root, "instructions", "AGENTS.md"), "# Agent Instructions\n", "utf8");
|
|
2165
2331
|
}
|
|
2166
2332
|
function printRegistryEntries(entries) {
|
|
2167
2333
|
for (const entry of entries) {
|