allagents 0.2.2 → 0.3.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 +32 -1
- package/dist/index.js +335 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -130,9 +130,21 @@ allagents plugin validate <path>
|
|
|
130
130
|
|
|
131
131
|
## .allagents/workspace.yaml
|
|
132
132
|
|
|
133
|
-
The workspace configuration file lives in `.allagents/workspace.yaml` and defines repositories, plugins, and target clients:
|
|
133
|
+
The workspace configuration file lives in `.allagents/workspace.yaml` and defines repositories, plugins, workspace files, and target clients:
|
|
134
134
|
|
|
135
135
|
```yaml
|
|
136
|
+
# Workspace file sync (optional) - copy files from a shared source
|
|
137
|
+
workspace:
|
|
138
|
+
source: ../shared-config # Default base for relative paths
|
|
139
|
+
files:
|
|
140
|
+
- AGENTS.md # String shorthand: same source and dest
|
|
141
|
+
- source: docs/guide.md # Object form: explicit source
|
|
142
|
+
dest: GUIDE.md # Optional dest (defaults to basename)
|
|
143
|
+
- dest: CUSTOM.md # File-level source override
|
|
144
|
+
source: ../other-config/CUSTOM.md
|
|
145
|
+
- dest: AGENTS.md # GitHub source
|
|
146
|
+
source: owner/repo/path/AGENTS.md
|
|
147
|
+
|
|
136
148
|
repositories:
|
|
137
149
|
- path: ../my-project
|
|
138
150
|
owner: myorg
|
|
@@ -154,6 +166,25 @@ clients:
|
|
|
154
166
|
- cursor
|
|
155
167
|
```
|
|
156
168
|
|
|
169
|
+
### Workspace File Sync
|
|
170
|
+
|
|
171
|
+
The `workspace:` section enables syncing files from external sources to your workspace root. This is useful for sharing agent configurations (AGENTS.md, CLAUDE.md) across multiple projects.
|
|
172
|
+
|
|
173
|
+
**Key behaviors:**
|
|
174
|
+
- **Source of truth is remote** - Local copies are overwritten on every sync
|
|
175
|
+
- **Deleted files are restored** - If you delete AGENTS.md locally, sync restores it
|
|
176
|
+
- **WORKSPACE-RULES injection** - AGENTS.md and CLAUDE.md automatically get workspace discovery rules injected
|
|
177
|
+
|
|
178
|
+
**Source resolution:**
|
|
179
|
+
| Format | Example | Resolves to |
|
|
180
|
+
|--------|---------|-------------|
|
|
181
|
+
| String shorthand | `AGENTS.md` | `{workspace.source}/AGENTS.md` |
|
|
182
|
+
| Relative source | `source: docs/guide.md` | `{workspace.source}/docs/guide.md` |
|
|
183
|
+
| File-level override | `source: ../other/file.md` | `../other/file.md` (relative to workspace) |
|
|
184
|
+
| GitHub source | `source: owner/repo/path/file.md` | Fetched from GitHub cache |
|
|
185
|
+
|
|
186
|
+
**GitHub sources** are fetched fresh on every sync (always pulls latest).
|
|
187
|
+
|
|
157
188
|
### Plugin Spec Format
|
|
158
189
|
|
|
159
190
|
Plugins use the `plugin@marketplace` format:
|
package/dist/index.js
CHANGED
|
@@ -17720,12 +17720,12 @@ var RepositorySchema = exports_external.object({
|
|
|
17720
17720
|
var WorkspaceFileSchema = exports_external.union([
|
|
17721
17721
|
exports_external.string(),
|
|
17722
17722
|
exports_external.object({
|
|
17723
|
-
source: exports_external.string(),
|
|
17723
|
+
source: exports_external.string().optional(),
|
|
17724
17724
|
dest: exports_external.string().optional()
|
|
17725
17725
|
})
|
|
17726
17726
|
]);
|
|
17727
17727
|
var WorkspaceSchema = exports_external.object({
|
|
17728
|
-
source: exports_external.string(),
|
|
17728
|
+
source: exports_external.string().optional(),
|
|
17729
17729
|
files: exports_external.array(WorkspaceFileSchema)
|
|
17730
17730
|
});
|
|
17731
17731
|
var PluginSourceSchema = exports_external.string();
|
|
@@ -19431,6 +19431,31 @@ function validatePluginSource(source) {
|
|
|
19431
19431
|
}
|
|
19432
19432
|
return { valid: true };
|
|
19433
19433
|
}
|
|
19434
|
+
function parseFileSource(source, baseDir = process.cwd()) {
|
|
19435
|
+
if (isGitHubUrl(source)) {
|
|
19436
|
+
const parsed = parseGitHubUrl(source);
|
|
19437
|
+
if (parsed) {
|
|
19438
|
+
return {
|
|
19439
|
+
type: "github",
|
|
19440
|
+
original: source,
|
|
19441
|
+
normalized: source,
|
|
19442
|
+
owner: parsed.owner,
|
|
19443
|
+
repo: parsed.repo,
|
|
19444
|
+
...parsed.subpath && { filePath: parsed.subpath }
|
|
19445
|
+
};
|
|
19446
|
+
}
|
|
19447
|
+
return {
|
|
19448
|
+
type: "local",
|
|
19449
|
+
original: source,
|
|
19450
|
+
normalized: normalizePluginPath(source, baseDir)
|
|
19451
|
+
};
|
|
19452
|
+
}
|
|
19453
|
+
return {
|
|
19454
|
+
type: "local",
|
|
19455
|
+
original: source,
|
|
19456
|
+
normalized: normalizePluginPath(source, baseDir)
|
|
19457
|
+
};
|
|
19458
|
+
}
|
|
19434
19459
|
async function verifyGitHubUrlExists(source) {
|
|
19435
19460
|
const parsed = parseGitHubUrl(source);
|
|
19436
19461
|
if (!parsed) {
|
|
@@ -19943,8 +19968,56 @@ async function copyPluginToWorkspace(pluginPath, workspacePath, client, options2
|
|
|
19943
19968
|
]);
|
|
19944
19969
|
return [...commandResults, ...skillResults, ...hookResults, ...agentResults];
|
|
19945
19970
|
}
|
|
19971
|
+
function isExplicitGitHubSource(source) {
|
|
19972
|
+
if (source.startsWith("https://github.com/") || source.startsWith("http://github.com/") || source.startsWith("github.com/") || source.startsWith("gh:")) {
|
|
19973
|
+
return true;
|
|
19974
|
+
}
|
|
19975
|
+
if (!source.startsWith(".") && !source.startsWith("/") && source.includes("/")) {
|
|
19976
|
+
const parts = source.split("/");
|
|
19977
|
+
if (parts.length >= 3) {
|
|
19978
|
+
const validOwnerRepo = /^[a-zA-Z0-9_.-]+$/;
|
|
19979
|
+
if (parts[0] && parts[1] && validOwnerRepo.test(parts[0]) && validOwnerRepo.test(parts[1])) {
|
|
19980
|
+
return true;
|
|
19981
|
+
}
|
|
19982
|
+
}
|
|
19983
|
+
}
|
|
19984
|
+
return false;
|
|
19985
|
+
}
|
|
19986
|
+
function resolveFileSourcePath(source, defaultSourcePath, githubCache) {
|
|
19987
|
+
if (!isExplicitGitHubSource(source)) {
|
|
19988
|
+
if (source.startsWith("/")) {
|
|
19989
|
+
return { path: source };
|
|
19990
|
+
}
|
|
19991
|
+
if (source.startsWith("../")) {
|
|
19992
|
+
return { path: join4(process.cwd(), source) };
|
|
19993
|
+
}
|
|
19994
|
+
if (defaultSourcePath) {
|
|
19995
|
+
return { path: join4(defaultSourcePath, source) };
|
|
19996
|
+
}
|
|
19997
|
+
return { path: join4(process.cwd(), source) };
|
|
19998
|
+
}
|
|
19999
|
+
const parsed = parseFileSource(source);
|
|
20000
|
+
if (parsed.type === "github" && parsed.owner && parsed.repo && parsed.filePath) {
|
|
20001
|
+
const cacheKey = `${parsed.owner}/${parsed.repo}`;
|
|
20002
|
+
const cachePath = githubCache?.get(cacheKey);
|
|
20003
|
+
if (!cachePath) {
|
|
20004
|
+
return {
|
|
20005
|
+
path: "",
|
|
20006
|
+
error: `GitHub cache not found for ${cacheKey}. Ensure the repo is fetched.`
|
|
20007
|
+
};
|
|
20008
|
+
}
|
|
20009
|
+
return { path: join4(cachePath, parsed.filePath) };
|
|
20010
|
+
}
|
|
20011
|
+
if (parsed.type === "github") {
|
|
20012
|
+
return {
|
|
20013
|
+
path: "",
|
|
20014
|
+
error: `Invalid GitHub file source: ${source}. Must include path to file (e.g., owner/repo/path/to/file.md)`
|
|
20015
|
+
};
|
|
20016
|
+
}
|
|
20017
|
+
return null;
|
|
20018
|
+
}
|
|
19946
20019
|
async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {}) {
|
|
19947
|
-
const { dryRun = false } = options2;
|
|
20020
|
+
const { dryRun = false, githubCache } = options2;
|
|
19948
20021
|
const results = [];
|
|
19949
20022
|
const stringPatterns = [];
|
|
19950
20023
|
const objectEntries = [];
|
|
@@ -19953,55 +20026,113 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
19953
20026
|
if (typeof file === "string") {
|
|
19954
20027
|
stringPatterns.push(file);
|
|
19955
20028
|
} else {
|
|
19956
|
-
|
|
20029
|
+
let dest = file.dest;
|
|
20030
|
+
if (!dest && file.source) {
|
|
20031
|
+
const parts = file.source.split("/");
|
|
20032
|
+
dest = parts[parts.length - 1] || file.source;
|
|
20033
|
+
}
|
|
20034
|
+
if (!dest) {
|
|
20035
|
+
results.push({
|
|
20036
|
+
source: "unknown",
|
|
20037
|
+
destination: join4(workspacePath, "unknown"),
|
|
20038
|
+
action: "failed",
|
|
20039
|
+
error: "File entry must have at least source or dest specified"
|
|
20040
|
+
});
|
|
20041
|
+
continue;
|
|
20042
|
+
}
|
|
20043
|
+
objectEntries.push(file.source ? { source: file.source, dest } : { dest });
|
|
19957
20044
|
}
|
|
19958
20045
|
}
|
|
19959
20046
|
if (stringPatterns.length > 0) {
|
|
19960
|
-
|
|
19961
|
-
|
|
19962
|
-
|
|
19963
|
-
|
|
19964
|
-
|
|
19965
|
-
|
|
20047
|
+
if (!sourcePath) {
|
|
20048
|
+
for (const pattern of stringPatterns) {
|
|
20049
|
+
if (!isGlobPattern(pattern) && !pattern.startsWith("!")) {
|
|
20050
|
+
results.push({
|
|
20051
|
+
source: pattern,
|
|
20052
|
+
destination: join4(workspacePath, pattern),
|
|
20053
|
+
action: "failed",
|
|
20054
|
+
error: `Cannot resolve file '${pattern}' - no workspace.source configured and no explicit source provided`
|
|
20055
|
+
});
|
|
20056
|
+
}
|
|
20057
|
+
}
|
|
20058
|
+
} else {
|
|
20059
|
+
const resolvedFiles = await resolveGlobPatterns(sourcePath, stringPatterns);
|
|
20060
|
+
for (const resolved of resolvedFiles) {
|
|
20061
|
+
const destPath = join4(workspacePath, resolved.relativePath);
|
|
20062
|
+
if (!existsSync3(resolved.sourcePath)) {
|
|
20063
|
+
const wasLiteral = stringPatterns.some((p) => !isGlobPattern(p) && !p.startsWith("!") && p === resolved.relativePath);
|
|
20064
|
+
if (wasLiteral) {
|
|
20065
|
+
results.push({
|
|
20066
|
+
source: resolved.sourcePath,
|
|
20067
|
+
destination: destPath,
|
|
20068
|
+
action: "failed",
|
|
20069
|
+
error: `Source file not found: ${resolved.sourcePath}`
|
|
20070
|
+
});
|
|
20071
|
+
}
|
|
20072
|
+
continue;
|
|
20073
|
+
}
|
|
20074
|
+
if (dryRun) {
|
|
20075
|
+
results.push({ source: resolved.sourcePath, destination: destPath, action: "copied" });
|
|
20076
|
+
if (AGENT_FILES2.includes(resolved.relativePath)) {
|
|
20077
|
+
copiedAgentFiles.push(resolved.relativePath);
|
|
20078
|
+
}
|
|
20079
|
+
continue;
|
|
20080
|
+
}
|
|
20081
|
+
try {
|
|
20082
|
+
await mkdir2(dirname2(destPath), { recursive: true });
|
|
20083
|
+
const content = await readFile3(resolved.sourcePath, "utf-8");
|
|
20084
|
+
await writeFile(destPath, content, "utf-8");
|
|
20085
|
+
results.push({ source: resolved.sourcePath, destination: destPath, action: "copied" });
|
|
20086
|
+
if (AGENT_FILES2.includes(resolved.relativePath)) {
|
|
20087
|
+
copiedAgentFiles.push(resolved.relativePath);
|
|
20088
|
+
}
|
|
20089
|
+
} catch (error) {
|
|
19966
20090
|
results.push({
|
|
19967
20091
|
source: resolved.sourcePath,
|
|
19968
20092
|
destination: destPath,
|
|
19969
20093
|
action: "failed",
|
|
19970
|
-
error:
|
|
20094
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
19971
20095
|
});
|
|
19972
20096
|
}
|
|
20097
|
+
}
|
|
20098
|
+
}
|
|
20099
|
+
}
|
|
20100
|
+
for (const entry of objectEntries) {
|
|
20101
|
+
const destPath = join4(workspacePath, entry.dest);
|
|
20102
|
+
let srcPath;
|
|
20103
|
+
if (entry.source) {
|
|
20104
|
+
const resolved = resolveFileSourcePath(entry.source, sourcePath, githubCache);
|
|
20105
|
+
if (!resolved) {
|
|
20106
|
+
results.push({
|
|
20107
|
+
source: entry.source,
|
|
20108
|
+
destination: destPath,
|
|
20109
|
+
action: "failed",
|
|
20110
|
+
error: `Failed to resolve source: ${entry.source}`
|
|
20111
|
+
});
|
|
19973
20112
|
continue;
|
|
19974
20113
|
}
|
|
19975
|
-
if (
|
|
19976
|
-
results.push({
|
|
19977
|
-
|
|
19978
|
-
|
|
19979
|
-
|
|
20114
|
+
if (resolved.error) {
|
|
20115
|
+
results.push({
|
|
20116
|
+
source: entry.source,
|
|
20117
|
+
destination: destPath,
|
|
20118
|
+
action: "failed",
|
|
20119
|
+
error: resolved.error
|
|
20120
|
+
});
|
|
19980
20121
|
continue;
|
|
19981
20122
|
}
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
await writeFile(destPath, content, "utf-8");
|
|
19986
|
-
results.push({ source: resolved.sourcePath, destination: destPath, action: "copied" });
|
|
19987
|
-
if (AGENT_FILES2.includes(resolved.relativePath)) {
|
|
19988
|
-
copiedAgentFiles.push(resolved.relativePath);
|
|
19989
|
-
}
|
|
19990
|
-
} catch (error) {
|
|
20123
|
+
srcPath = resolved.path;
|
|
20124
|
+
} else {
|
|
20125
|
+
if (!sourcePath) {
|
|
19991
20126
|
results.push({
|
|
19992
|
-
source:
|
|
20127
|
+
source: entry.dest,
|
|
19993
20128
|
destination: destPath,
|
|
19994
20129
|
action: "failed",
|
|
19995
|
-
error:
|
|
20130
|
+
error: `Cannot resolve file '${entry.dest}' - no workspace.source configured and no explicit source provided`
|
|
19996
20131
|
});
|
|
20132
|
+
continue;
|
|
19997
20133
|
}
|
|
20134
|
+
srcPath = join4(sourcePath, entry.dest);
|
|
19998
20135
|
}
|
|
19999
|
-
}
|
|
20000
|
-
for (const entry of objectEntries) {
|
|
20001
|
-
const srcPath = join4(sourcePath, entry.source);
|
|
20002
|
-
const basename = entry.source.split("/").pop() || entry.source;
|
|
20003
|
-
const destFilename = entry.dest ?? basename;
|
|
20004
|
-
const destPath = join4(workspacePath, destFilename);
|
|
20005
20136
|
if (!existsSync3(srcPath)) {
|
|
20006
20137
|
results.push({
|
|
20007
20138
|
source: srcPath,
|
|
@@ -20013,8 +20144,8 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
20013
20144
|
}
|
|
20014
20145
|
if (dryRun) {
|
|
20015
20146
|
results.push({ source: srcPath, destination: destPath, action: "copied" });
|
|
20016
|
-
if (AGENT_FILES2.includes(
|
|
20017
|
-
copiedAgentFiles.push(
|
|
20147
|
+
if (AGENT_FILES2.includes(entry.dest)) {
|
|
20148
|
+
copiedAgentFiles.push(entry.dest);
|
|
20018
20149
|
}
|
|
20019
20150
|
continue;
|
|
20020
20151
|
}
|
|
@@ -20023,8 +20154,8 @@ async function copyWorkspaceFiles(sourcePath, workspacePath, files, options2 = {
|
|
|
20023
20154
|
const content = await readFile3(srcPath, "utf-8");
|
|
20024
20155
|
await writeFile(destPath, content, "utf-8");
|
|
20025
20156
|
results.push({ source: srcPath, destination: destPath, action: "copied" });
|
|
20026
|
-
if (AGENT_FILES2.includes(
|
|
20027
|
-
copiedAgentFiles.push(
|
|
20157
|
+
if (AGENT_FILES2.includes(entry.dest)) {
|
|
20158
|
+
copiedAgentFiles.push(entry.dest);
|
|
20028
20159
|
}
|
|
20029
20160
|
} catch (error) {
|
|
20030
20161
|
results.push({
|
|
@@ -20451,6 +20582,130 @@ async function cleanupEmptyParents(workspacePath, filePath) {
|
|
|
20451
20582
|
}
|
|
20452
20583
|
}
|
|
20453
20584
|
}
|
|
20585
|
+
function isExplicitGitHubSourceForCollection(source) {
|
|
20586
|
+
if (source.startsWith("https://github.com/") || source.startsWith("http://github.com/") || source.startsWith("github.com/") || source.startsWith("gh:")) {
|
|
20587
|
+
return true;
|
|
20588
|
+
}
|
|
20589
|
+
if (!source.startsWith(".") && !source.startsWith("/") && source.includes("/")) {
|
|
20590
|
+
const parts = source.split("/");
|
|
20591
|
+
if (parts.length >= 3) {
|
|
20592
|
+
const validOwnerRepo = /^[a-zA-Z0-9_.-]+$/;
|
|
20593
|
+
if (parts[0] && parts[1] && validOwnerRepo.test(parts[0]) && validOwnerRepo.test(parts[1])) {
|
|
20594
|
+
return true;
|
|
20595
|
+
}
|
|
20596
|
+
}
|
|
20597
|
+
}
|
|
20598
|
+
return false;
|
|
20599
|
+
}
|
|
20600
|
+
function collectGitHubReposFromFiles(files) {
|
|
20601
|
+
const repos = new Map;
|
|
20602
|
+
for (const file of files) {
|
|
20603
|
+
if (typeof file === "string") {
|
|
20604
|
+
continue;
|
|
20605
|
+
}
|
|
20606
|
+
if (file.source && isExplicitGitHubSourceForCollection(file.source)) {
|
|
20607
|
+
const parsed = parseFileSource(file.source);
|
|
20608
|
+
if (parsed.type === "github" && parsed.owner && parsed.repo) {
|
|
20609
|
+
const key = `${parsed.owner}/${parsed.repo}`;
|
|
20610
|
+
if (!repos.has(key)) {
|
|
20611
|
+
repos.set(key, {
|
|
20612
|
+
owner: parsed.owner,
|
|
20613
|
+
repo: parsed.repo,
|
|
20614
|
+
key
|
|
20615
|
+
});
|
|
20616
|
+
}
|
|
20617
|
+
}
|
|
20618
|
+
}
|
|
20619
|
+
}
|
|
20620
|
+
return Array.from(repos.values());
|
|
20621
|
+
}
|
|
20622
|
+
async function fetchFileSourceRepos(repos, _force) {
|
|
20623
|
+
const cache = new Map;
|
|
20624
|
+
const errors2 = [];
|
|
20625
|
+
for (const repo of repos) {
|
|
20626
|
+
const result = await fetchPlugin(`${repo.owner}/${repo.repo}`, { force: true });
|
|
20627
|
+
if (result.success) {
|
|
20628
|
+
cache.set(repo.key, result.cachePath);
|
|
20629
|
+
} else {
|
|
20630
|
+
errors2.push(`Failed to fetch ${repo.key}: ${result.error || "Unknown error"}`);
|
|
20631
|
+
}
|
|
20632
|
+
}
|
|
20633
|
+
return { cache, errors: errors2 };
|
|
20634
|
+
}
|
|
20635
|
+
function isExplicitGitHubSourceForValidation(source) {
|
|
20636
|
+
if (source.startsWith("https://github.com/") || source.startsWith("http://github.com/") || source.startsWith("github.com/") || source.startsWith("gh:")) {
|
|
20637
|
+
return true;
|
|
20638
|
+
}
|
|
20639
|
+
if (!source.startsWith(".") && !source.startsWith("/") && source.includes("/")) {
|
|
20640
|
+
const parts = source.split("/");
|
|
20641
|
+
if (parts.length >= 3) {
|
|
20642
|
+
const validOwnerRepo = /^[a-zA-Z0-9_.-]+$/;
|
|
20643
|
+
if (parts[0] && parts[1] && validOwnerRepo.test(parts[0]) && validOwnerRepo.test(parts[1])) {
|
|
20644
|
+
return true;
|
|
20645
|
+
}
|
|
20646
|
+
}
|
|
20647
|
+
}
|
|
20648
|
+
return false;
|
|
20649
|
+
}
|
|
20650
|
+
function validateFileSources(files, defaultSourcePath, githubCache) {
|
|
20651
|
+
const errors2 = [];
|
|
20652
|
+
for (const file of files) {
|
|
20653
|
+
if (typeof file === "string") {
|
|
20654
|
+
if (!defaultSourcePath) {
|
|
20655
|
+
errors2.push(`Cannot resolve file '${file}' - no workspace.source configured`);
|
|
20656
|
+
continue;
|
|
20657
|
+
}
|
|
20658
|
+
const fullPath = join7(defaultSourcePath, file);
|
|
20659
|
+
if (!existsSync6(fullPath)) {
|
|
20660
|
+
errors2.push(`File source not found: ${fullPath}`);
|
|
20661
|
+
}
|
|
20662
|
+
continue;
|
|
20663
|
+
}
|
|
20664
|
+
if (file.source) {
|
|
20665
|
+
if (isExplicitGitHubSourceForValidation(file.source)) {
|
|
20666
|
+
const parsed = parseFileSource(file.source);
|
|
20667
|
+
if (!parsed.owner || !parsed.repo || !parsed.filePath) {
|
|
20668
|
+
errors2.push(`Invalid GitHub file source: ${file.source}. Must include path to file.`);
|
|
20669
|
+
continue;
|
|
20670
|
+
}
|
|
20671
|
+
const cacheKey = `${parsed.owner}/${parsed.repo}`;
|
|
20672
|
+
const cachePath = githubCache.get(cacheKey);
|
|
20673
|
+
if (!cachePath) {
|
|
20674
|
+
errors2.push(`GitHub cache not found for ${cacheKey}`);
|
|
20675
|
+
continue;
|
|
20676
|
+
}
|
|
20677
|
+
const fullPath = join7(cachePath, parsed.filePath);
|
|
20678
|
+
if (!existsSync6(fullPath)) {
|
|
20679
|
+
errors2.push(`Path not found in repository: ${cacheKey}/${parsed.filePath}`);
|
|
20680
|
+
}
|
|
20681
|
+
} else {
|
|
20682
|
+
let fullPath;
|
|
20683
|
+
if (file.source.startsWith("/")) {
|
|
20684
|
+
fullPath = file.source;
|
|
20685
|
+
} else if (file.source.startsWith("../")) {
|
|
20686
|
+
fullPath = resolve4(file.source);
|
|
20687
|
+
} else if (defaultSourcePath) {
|
|
20688
|
+
fullPath = join7(defaultSourcePath, file.source);
|
|
20689
|
+
} else {
|
|
20690
|
+
fullPath = resolve4(file.source);
|
|
20691
|
+
}
|
|
20692
|
+
if (!existsSync6(fullPath)) {
|
|
20693
|
+
errors2.push(`File source not found: ${fullPath}`);
|
|
20694
|
+
}
|
|
20695
|
+
}
|
|
20696
|
+
} else {
|
|
20697
|
+
if (!defaultSourcePath) {
|
|
20698
|
+
errors2.push(`Cannot resolve file '${file.dest}' - no workspace.source configured and no explicit source provided`);
|
|
20699
|
+
continue;
|
|
20700
|
+
}
|
|
20701
|
+
const fullPath = join7(defaultSourcePath, file.dest ?? "");
|
|
20702
|
+
if (!existsSync6(fullPath)) {
|
|
20703
|
+
errors2.push(`File source not found: ${fullPath}`);
|
|
20704
|
+
}
|
|
20705
|
+
}
|
|
20706
|
+
}
|
|
20707
|
+
return errors2;
|
|
20708
|
+
}
|
|
20454
20709
|
function collectSyncedPaths(copyResults, workspacePath, clients) {
|
|
20455
20710
|
const result = {};
|
|
20456
20711
|
for (const client of clients) {
|
|
@@ -20623,17 +20878,52 @@ ${errors2}`
|
|
|
20623
20878
|
}
|
|
20624
20879
|
const pluginResults = await Promise.all(validatedPlugins.map((validatedPlugin) => copyValidatedPlugin(validatedPlugin, workspacePath, config.clients, dryRun)));
|
|
20625
20880
|
let workspaceFileResults = [];
|
|
20626
|
-
if (config.workspace
|
|
20627
|
-
const sourcePath = validatedWorkspaceSource
|
|
20881
|
+
if (config.workspace) {
|
|
20882
|
+
const sourcePath = validatedWorkspaceSource?.resolved;
|
|
20628
20883
|
const filesToCopy = [...config.workspace.files];
|
|
20629
|
-
|
|
20630
|
-
const
|
|
20631
|
-
|
|
20632
|
-
filesToCopy.
|
|
20884
|
+
if (sourcePath) {
|
|
20885
|
+
for (const agentFile of AGENT_FILES) {
|
|
20886
|
+
const agentPath = join7(sourcePath, agentFile);
|
|
20887
|
+
if (existsSync6(agentPath) && !filesToCopy.includes(agentFile)) {
|
|
20888
|
+
filesToCopy.push(agentFile);
|
|
20889
|
+
}
|
|
20633
20890
|
}
|
|
20634
20891
|
}
|
|
20635
|
-
|
|
20636
|
-
|
|
20892
|
+
const fileSourceRepos = collectGitHubReposFromFiles(filesToCopy);
|
|
20893
|
+
let githubCache = new Map;
|
|
20894
|
+
if (fileSourceRepos.length > 0) {
|
|
20895
|
+
const { cache, errors: errors2 } = await fetchFileSourceRepos(fileSourceRepos, force);
|
|
20896
|
+
if (errors2.length > 0) {
|
|
20897
|
+
return {
|
|
20898
|
+
success: false,
|
|
20899
|
+
pluginResults,
|
|
20900
|
+
totalCopied: 0,
|
|
20901
|
+
totalFailed: errors2.length,
|
|
20902
|
+
totalSkipped: 0,
|
|
20903
|
+
totalGenerated: 0,
|
|
20904
|
+
error: `File source fetch failed (workspace unchanged):
|
|
20905
|
+
${errors2.map((e) => ` - ${e}`).join(`
|
|
20906
|
+
`)}`
|
|
20907
|
+
};
|
|
20908
|
+
}
|
|
20909
|
+
githubCache = cache;
|
|
20910
|
+
}
|
|
20911
|
+
const fileValidationErrors = validateFileSources(filesToCopy, sourcePath, githubCache);
|
|
20912
|
+
if (fileValidationErrors.length > 0) {
|
|
20913
|
+
return {
|
|
20914
|
+
success: false,
|
|
20915
|
+
pluginResults,
|
|
20916
|
+
totalCopied: 0,
|
|
20917
|
+
totalFailed: fileValidationErrors.length,
|
|
20918
|
+
totalSkipped: 0,
|
|
20919
|
+
totalGenerated: 0,
|
|
20920
|
+
error: `File source validation failed (workspace unchanged):
|
|
20921
|
+
${fileValidationErrors.map((e) => ` - ${e}`).join(`
|
|
20922
|
+
`)}`
|
|
20923
|
+
};
|
|
20924
|
+
}
|
|
20925
|
+
workspaceFileResults = await copyWorkspaceFiles(sourcePath, workspacePath, filesToCopy, { dryRun, githubCache });
|
|
20926
|
+
if (!dryRun && config.clients.includes("claude") && sourcePath) {
|
|
20637
20927
|
const claudePath = join7(workspacePath, "CLAUDE.md");
|
|
20638
20928
|
const agentsPath = join7(workspacePath, "AGENTS.md");
|
|
20639
20929
|
const claudeExistsInSource = existsSync6(join7(sourcePath, "CLAUDE.md"));
|