agentsmesh 0.20.0 → 0.22.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/CHANGELOG.md +70 -0
- package/README.md +14 -1
- package/dist/canonical.js +81 -13
- package/dist/canonical.js.map +1 -1
- package/dist/cli.js +206 -162
- package/dist/engine.js +181 -15
- package/dist/engine.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +651 -232
- package/dist/index.js.map +1 -1
- package/dist/lessons.d.ts +155 -0
- package/dist/lessons.js +305 -0
- package/dist/lessons.js.map +1 -0
- package/dist/targets.js +22 -2
- package/dist/targets.js.map +1 -1
- package/package.json +12 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.22.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- c2a13ad: Add `agentsmesh init --lessons` and a new `agentsmesh/lessons` public API for
|
|
8
|
+
the lessons recall + capture subsystem.
|
|
9
|
+
|
|
10
|
+
The subsystem keeps agents from repeating past mistakes via a procedural rule
|
|
11
|
+
that lives in every target's root file: before any edit or command, scan
|
|
12
|
+
`.agentsmesh/lessons/index.yaml` and read every matched
|
|
13
|
+
`.agentsmesh/lessons/topics/<topic>.md`; after any failure, append to
|
|
14
|
+
`.agentsmesh/lessons/journal.md`. The optional repo-local `pnpm distill` /
|
|
15
|
+
`pnpm distill:apply` scripts can help maintain AgentsMesh's own topic routing,
|
|
16
|
+
but the generated rule does not require package-manager-specific tooling.
|
|
17
|
+
|
|
18
|
+
**Using it:**
|
|
19
|
+
- **Fresh init:** `agentsmesh init --lessons` — creates the canonical scaffold
|
|
20
|
+
AND the lessons subsystem in one command.
|
|
21
|
+
- **Retroactive add (existing project):** the same `agentsmesh init --lessons`
|
|
22
|
+
— when `agentsmesh.yaml` already exists, init only scaffolds the lessons
|
|
23
|
+
artifacts and appends the procedural rule to `_root.md`. Idempotent.
|
|
24
|
+
- After either flow, run `agentsmesh generate` to project the procedural rule
|
|
25
|
+
to every target's root file.
|
|
26
|
+
|
|
27
|
+
**Public API** (importable from `agentsmesh/lessons`):
|
|
28
|
+
- `scaffoldLessons(projectRoot)` — idempotent scaffolder used internally by
|
|
29
|
+
`init --lessons`; reusable from custom tooling.
|
|
30
|
+
- `loadLessonsIndex(projectRoot)`, `readTriggeredLessons(projectRoot, event)`,
|
|
31
|
+
`appendLessonToJournal(projectRoot, input)`, and `formatLessonBullet(input)` —
|
|
32
|
+
one high-level, target-agnostic read/write layer for integrations that should
|
|
33
|
+
not hand-roll filesystem access.
|
|
34
|
+
- `lessonsPaths(projectRoot)`, `LESSONS_PROCEDURAL_RULE`,
|
|
35
|
+
`LESSONS_JOURNAL_TEMPLATE`, `LESSONS_INDEX_TEMPLATE` — paths and templates.
|
|
36
|
+
- `parseIndex`, `LessonsIndexSchema`, `matchTriggers`, `scoreBullet`,
|
|
37
|
+
`loadLedger`, `saveLedger`, `hashBullet`, `parseBullets` — building blocks
|
|
38
|
+
for downstream tooling (custom distillers, recall hooks, IDE plugins).
|
|
39
|
+
|
|
40
|
+
**Universal across every target.** The subsystem uses plain markdown files
|
|
41
|
+
read via standard file I/O — no `Skill` tool, no description-match, no
|
|
42
|
+
per-target projection. Works in Claude Code, Codex CLI, Cline, Roo Code,
|
|
43
|
+
Cursor, Gemini CLI, Aider, Goose, and every other supported harness.
|
|
44
|
+
|
|
45
|
+
**Linter integration:** `agentsmesh lint` now validates the lessons subsystem
|
|
46
|
+
when present — checks that `index.yaml` parses, topic files referenced in the
|
|
47
|
+
index exist, and the journal file is well-formed.
|
|
48
|
+
|
|
49
|
+
**Constraints:**
|
|
50
|
+
- `--lessons` is project-mode only. Combining with `--global` errors out.
|
|
51
|
+
- Removal: `rm -rf .agentsmesh/lessons/` and strip the `## Lessons` paragraph
|
|
52
|
+
from `.agentsmesh/rules/_root.md`.
|
|
53
|
+
|
|
54
|
+
### Patch Changes
|
|
55
|
+
|
|
56
|
+
- c75a424: Surface marketplace sub-pack install failures instead of swallowing them silently, and route skill-pack sub-packs through the correct install path.
|
|
57
|
+
- c75a424: Fix qwen-code global-mode rule embedding. Rules were silently dropped when generating in global mode; they are now embedded inline using the same pattern as other global-mode targets.
|
|
58
|
+
- c75a424: Restructure the generation contract paragraph to lead with an explicit **NEVER edit generated files** prohibition naming the generated paths (`.claude/`, `.cursor/`, `AGENTS.md`, etc.), followed by **All changes MUST go through `.agentsmesh` first**. Agents were initially understanding the contract but forgetting it over multi-step conversations — front-loading the prohibition makes it stickier. All legacy contract body versions (v1-v10) remain detected for safe in-place upgrade.
|
|
59
|
+
|
|
60
|
+
## 0.21.0
|
|
61
|
+
|
|
62
|
+
### Minor Changes
|
|
63
|
+
|
|
64
|
+
- b1efca1: Harden install pipeline against third-party supply-chain attacks.
|
|
65
|
+
- **Strip elevated artifacts from non-local sources by default.** `hooks.yaml`, `permissions.yaml`, and `mcp.json` are now removed from any pack installed from a `github:`, `gitlab:`, or `git+...` source unless you opt in. These three files control your agent's tool settings (shell hooks, granted permissions, MCP launch specs) and a malicious pack shipping any of them could otherwise execute arbitrary local commands the next time the matching event fires. Opt in per-artifact with `--accept-hooks`, `--accept-permissions`, `--accept-mcp`, or all three with `--accept-elevated`. Local sources remain trusted as before.
|
|
66
|
+
- **Skill supporting-file traversal no longer follows symlinks.** A pack containing `skills/foo/keys -> /Users/victim/.ssh` previously pulled external bytes (private keys, etc.) into the canonical skill content. Skill traversal now uses the existing `readDirRecursiveNoSymlinks` helper, mirroring the hardening already applied to install-manifest hashing.
|
|
67
|
+
- **Redact credentials from remote-fetch error output.** `oauth2:<token>@`, `x-access-token:<token>@`, and any other userinfo-bearing URLs are now masked (`https://***@host/...`) in console warnings and thrown error messages so GitHub PATs and GitLab tokens never leak into CI logs, terminal scrollback, or log shippers.
|
|
68
|
+
- **Gate `git+file://` sources behind `AGENTSMESH_ALLOW_LOCAL_GIT=1`.** On shared/multi-tenant hosts a `git+file:///tmp/world-writable-repo` `extends:` clause could silently consume a repo planted by another user; combined with downstream elevated-artifact emission this was a local priv-esc vector. Set `AGENTSMESH_ALLOW_LOCAL_GIT=1` to enable for closed-network development.
|
|
69
|
+
- **Allowlist tar entry types on GitHub tarball extraction.** Previously only `Link` and `SymbolicLink` were rejected (denylist). Now only `File` and `Directory` entries extract; FIFOs, devices, hardlinks, and any future/exotic tar variant are rejected by default.
|
|
70
|
+
|
|
71
|
+
These changes apply to `agentsmesh install`, `agentsmesh refresh`, and any `extends:` resolution against a non-local source. They are behavior changes for users who were silently inheriting hooks/permissions/mcp from a remote pack — re-run with the matching `--accept-*` flag (or `--accept-elevated`) to preserve previous behavior intentionally.
|
|
72
|
+
|
|
3
73
|
## 0.20.0
|
|
4
74
|
|
|
5
75
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -87,6 +87,10 @@ AGENTS.md
|
|
|
87
87
|
hooks.yaml
|
|
88
88
|
permissions.yaml
|
|
89
89
|
ignore
|
|
90
|
+
lessons/
|
|
91
|
+
index.yaml
|
|
92
|
+
journal.md
|
|
93
|
+
topics/
|
|
90
94
|
```
|
|
91
95
|
|
|
92
96
|
```bash
|
|
@@ -111,6 +115,12 @@ agentsmesh check # CI-friendly drift gate against .agentsmesh/.lock
|
|
|
111
115
|
- **`generate`** — writes `CLAUDE.md`, `AGENTS.md`, `.cursor/`, `.github/copilot-instructions.md`, etc. from canonical sources.
|
|
112
116
|
- **`check`** — exits non-zero if generated files have drifted from `.agentsmesh/.lock`. Drop into CI.
|
|
113
117
|
|
|
118
|
+
Use `agentsmesh init --lessons` when you want the optional lessons recall +
|
|
119
|
+
capture subsystem. Agents read `.agentsmesh/lessons/index.yaml`, load only
|
|
120
|
+
matching topic files before edits/commands, and append failures to
|
|
121
|
+
`.agentsmesh/lessons/journal.md`; the procedural rule is projected through the
|
|
122
|
+
normal root rule, so it stays tool-agnostic.
|
|
123
|
+
|
|
114
124
|
If you installed via `npm install -D agentsmesh` (also `pnpm add -D` / `yarn add -D`), prefix each command with `npx`. The CLI ships as both `agentsmesh` and the shorter alias `amsh`.
|
|
115
125
|
|
|
116
126
|
---
|
|
@@ -208,6 +218,7 @@ AgentsMesh canonicalizes all of these — rules, commands, agents, skills, MCP s
|
|
|
208
218
|
- `hooks.yaml` — pre/post tool hooks.
|
|
209
219
|
- `permissions.yaml` — allow/deny rules where the target supports them.
|
|
210
220
|
- `ignore` — paths the assistant should not read or modify.
|
|
221
|
+
- `lessons/` — optional recall/capture memory: trigger index, append-only journal, and small topic rule files read directly by agents.
|
|
211
222
|
|
|
212
223
|
Configuration:
|
|
213
224
|
|
|
@@ -222,7 +233,7 @@ Detailed contracts: [Canonical Config](https://samplexbro.github.io/agentsmesh/c
|
|
|
222
233
|
## CLI usage
|
|
223
234
|
|
|
224
235
|
```bash
|
|
225
|
-
agentsmesh init [--global] [--yes]
|
|
236
|
+
agentsmesh init [--global] [--yes] [--lessons]
|
|
226
237
|
agentsmesh generate [--global] [--targets <csv>] [--check] [--dry-run] [--force] [--refresh-cache]
|
|
227
238
|
agentsmesh import --from <target> [--global]
|
|
228
239
|
agentsmesh convert --from <target> --to <target> [--global] [--dry-run]
|
|
@@ -233,6 +244,7 @@ agentsmesh check [--global]
|
|
|
233
244
|
agentsmesh merge [--global]
|
|
234
245
|
agentsmesh matrix [--global] [--targets <csv>] [--verbose]
|
|
235
246
|
agentsmesh install <source> [--sync] [--path <dir>] [--target <id>] [--as <kind>] [--name <id>] [--extends] [--all] [--dry-run] [--global] [--force]
|
|
247
|
+
[--accept-hooks|--accept-permissions|--accept-mcp|--accept-elevated]
|
|
236
248
|
agentsmesh uninstall <name>[,<name>...] [--all] [--keep-pack] [--keep-generated] [--dry-run] [--global] [--force]
|
|
237
249
|
agentsmesh installs list [--global]
|
|
238
250
|
agentsmesh refresh [<name>[,<name>...]] [--dry-run] [--force] [--json] [--global]
|
|
@@ -383,6 +395,7 @@ Every config file ships with a generated JSON Schema, so VS Code, JetBrains, and
|
|
|
383
395
|
| `AGENTSMESH_CACHE` | `~/.agentsmeshcache` | Override the remote-extends / tarball cache directory. |
|
|
384
396
|
| `AGENTSMESH_MAX_TARBALL_MB` | `500` | Maximum GitHub tarball size in MiB the install command will accept. Allowed range: `1`–`4096`. Increase this when installing from large monorepos. |
|
|
385
397
|
| `AGENTSMESH_STRICT_PLUGINS` | `0` | When set to `1`, a failed plugin descriptor import fails the build instead of warning-and-skip. Useful in CI where a missing plugin target is a regression. |
|
|
398
|
+
| `AGENTSMESH_ALLOW_LOCAL_GIT` | `0` | When set to `1`, enables `git+file://` sources in `extends` and `install`. Disabled by default because on shared hosts a world-writable repo could be planted by another user and combined with elevated-artifact emission for local privilege escalation. |
|
|
386
399
|
|
|
387
400
|
---
|
|
388
401
|
|
package/dist/canonical.js
CHANGED
|
@@ -185,6 +185,33 @@ async function readDirRecursive(dir, visited, branchSegments) {
|
|
|
185
185
|
);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
|
+
async function readDirRecursiveNoSymlinks(dir, branchSegments) {
|
|
189
|
+
const currentBranchSegments = branchSegments ?? [basename(dir)];
|
|
190
|
+
try {
|
|
191
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
192
|
+
const files = [];
|
|
193
|
+
for (const ent of entries) {
|
|
194
|
+
if (ent.isSymbolicLink()) continue;
|
|
195
|
+
const full = join(dir, ent.name);
|
|
196
|
+
if (ent.isDirectory()) {
|
|
197
|
+
const nextSegments = [...currentBranchSegments, ent.name];
|
|
198
|
+
if (shouldSkipRecursiveBranch(nextSegments)) continue;
|
|
199
|
+
files.push(...await readDirRecursiveNoSymlinks(full, nextSegments));
|
|
200
|
+
} else if (ent.isFile()) {
|
|
201
|
+
files.push(full);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return files;
|
|
205
|
+
} catch (err) {
|
|
206
|
+
const e = err;
|
|
207
|
+
if (e.code === "ENOENT" || e.code === "ENOTDIR" || e.code === "EACCES") return [];
|
|
208
|
+
throw new FileSystemError(
|
|
209
|
+
dir,
|
|
210
|
+
`Failed to read directory ${dir}: ${e.message}. Check permissions.`,
|
|
211
|
+
{ cause: err, errnoCode: e.code }
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
188
215
|
var MAX_RECURSIVE_DEPTH, MAX_SEGMENT_REPETITIONS;
|
|
189
216
|
var init_fs_traverse = __esm({
|
|
190
217
|
"src/utils/filesystem/fs-traverse.ts"() {
|
|
@@ -1023,7 +1050,7 @@ ${legacy}`, "");
|
|
|
1023
1050
|
}
|
|
1024
1051
|
return result.trim();
|
|
1025
1052
|
}
|
|
1026
|
-
var ROOT_INSTRUCTION_BODY_V1, ROOT_INSTRUCTION_BODY_V2, ROOT_INSTRUCTION_BODY_V3, ROOT_INSTRUCTION_BODY_V4, ROOT_INSTRUCTION_BODY_V5, ROOT_INSTRUCTION_BODY_V6, ROOT_INSTRUCTION_BODY_V7, ROOT_INSTRUCTION_BODY_V8, ROOT_INSTRUCTION_BODY, LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH, LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION, AGENTSMESH_CONTRACT_WITH_V1_BODY, AGENTSMESH_CONTRACT_WITH_V2_BODY, AGENTSMESH_CONTRACT_WITH_V3_BODY, AGENTSMESH_CONTRACT_WITH_V4_BODY, AGENTSMESH_CONTRACT_WITH_V5_BODY, AGENTSMESH_CONTRACT_WITH_V6_BODY, AGENTSMESH_CONTRACT_WITH_V7_BODY, AGENTSMESH_CONTRACT_WITH_V8_BODY, AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH, LEGACY_FORMS;
|
|
1053
|
+
var ROOT_INSTRUCTION_BODY_V1, ROOT_INSTRUCTION_BODY_V2, ROOT_INSTRUCTION_BODY_V3, ROOT_INSTRUCTION_BODY_V4, ROOT_INSTRUCTION_BODY_V5, ROOT_INSTRUCTION_BODY_V6, ROOT_INSTRUCTION_BODY_V7, ROOT_INSTRUCTION_BODY_V8, ROOT_INSTRUCTION_BODY_V9, ROOT_INSTRUCTION_BODY_V10, ROOT_INSTRUCTION_BODY, LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH, LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION, AGENTSMESH_CONTRACT_WITH_V1_BODY, AGENTSMESH_CONTRACT_WITH_V2_BODY, AGENTSMESH_CONTRACT_WITH_V3_BODY, AGENTSMESH_CONTRACT_WITH_V4_BODY, AGENTSMESH_CONTRACT_WITH_V5_BODY, AGENTSMESH_CONTRACT_WITH_V6_BODY, AGENTSMESH_CONTRACT_WITH_V7_BODY, AGENTSMESH_CONTRACT_WITH_V8_BODY, AGENTSMESH_CONTRACT_WITH_V9_BODY, AGENTSMESH_CONTRACT_WITH_V10_BODY, AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH, LEGACY_FORMS;
|
|
1027
1054
|
var init_root_instruction_paragraph = __esm({
|
|
1028
1055
|
"src/targets/projection/root-instruction-paragraph.ts"() {
|
|
1029
1056
|
init_managed_blocks();
|
|
@@ -1035,7 +1062,9 @@ var init_root_instruction_paragraph = __esm({
|
|
|
1035
1062
|
ROOT_INSTRUCTION_BODY_V6 = "Create canonical files in `.agentsmesh`: `rules/_root.md` and `rules/*.md` are Markdown rules; `commands/*.md`, `agents/*.md`, and `skills/*/SKILL.md` plus supporting files use Claude-style frontmatter Markdown; `mcp.json` is MCP JSON; `hooks.yaml` and `permissions.yaml` are YAML; `ignore` is gitignore-style text. Then run `agentsmesh generate`.";
|
|
1036
1063
|
ROOT_INSTRUCTION_BODY_V7 = "`.agentsmesh` is the only folder you edit or add these files in: `rules/_root.md` and `rules/*.md` are Markdown rules; `commands/*.md`, `agents/*.md`, and `skills/*/SKILL.md` plus supporting files use Claude-style frontmatter Markdown; `mcp.json` is MCP JSON; `hooks.yaml` and `permissions.yaml` are YAML; `ignore` is gitignore-style text. Do not edit generated tool files; run `agentsmesh generate`.";
|
|
1037
1064
|
ROOT_INSTRUCTION_BODY_V8 = "`agentsmesh.yaml` selects targets/features (`agentsmesh.local.yaml` overrides locally), and `.agentsmesh` is the only place to add or edit canonical items: `rules/_root.md`, `rules/*.md`, `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md` plus supporting files, `mcp.json`, `hooks.yaml`, `permissions.yaml`, and `ignore`; if missing run `agentsmesh init`, use `agentsmesh import --from <tool>` for native configs, `agentsmesh install <source>` or `install --sync` for reusable packs, then run `agentsmesh generate`. Use `diff`, `lint`, `check`, `watch`, `matrix`, and `merge` as needed; never edit generated tool files.";
|
|
1038
|
-
|
|
1065
|
+
ROOT_INSTRUCTION_BODY_V9 = "`agentsmesh.yaml` selects targets/features (`agentsmesh.local.yaml` overrides locally), and `.agentsmesh` is the only place to add or edit canonical items: `rules/_root.md`, `rules/*.md`, `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md` plus supporting files, `mcp.json`, `hooks.yaml`, `permissions.yaml`, and `ignore`; if missing run `agentsmesh init`, use `agentsmesh import --from <tool>` for native configs, `agentsmesh install <source>` or `install --sync` for reusable packs, then run `agentsmesh generate`. Use `diff`, `lint`, `check`, `watch`, `matrix`, `merge`, and `refresh` as needed; never edit generated tool files.";
|
|
1066
|
+
ROOT_INSTRUCTION_BODY_V10 = "**MUST follow when changing any rule, agent, command, skill, hook, MCP server, permission, or ignore pattern.** `agentsmesh.yaml` selects targets/features (`agentsmesh.local.yaml` overrides locally), and `.agentsmesh` is the only place to add or edit canonical items: `rules/_root.md`, `rules/*.md`, `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md` plus supporting files, `mcp.json`, `hooks.yaml`, `permissions.yaml`, and `ignore`; if missing run `agentsmesh init`, use `agentsmesh import --from <tool>` for native configs, `agentsmesh install <source>` or `install --sync` for reusable packs, then run `agentsmesh generate`. Use `diff`, `lint`, `check`, `watch`, `matrix`, `merge`, and `refresh` as needed; never edit generated tool files.";
|
|
1067
|
+
ROOT_INSTRUCTION_BODY = "**NEVER edit generated files** (`.claude/`, `.cursor/`, `AGENTS.md`, `.github/copilot-instructions.md`, and similar target outputs) \u2014 `agentsmesh generate` overwrites them. **All changes MUST go through `.agentsmesh` first**: edit `rules/_root.md`, `rules/*.md`, `commands/*.md`, `agents/*.md`, `skills/*/SKILL.md` plus supporting files, `mcp.json`, `hooks.yaml`, `permissions.yaml`, and `ignore`; `agentsmesh.yaml` selects targets/features (`agentsmesh.local.yaml` overrides locally); if missing run `agentsmesh init`, use `agentsmesh import --from <tool>` for native configs, `agentsmesh install <source>` or `install --sync` for reusable packs, then run `agentsmesh generate`. Use `diff`, `lint`, `check`, `watch`, `matrix`, `merge`, and `refresh` as needed.";
|
|
1039
1068
|
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = ROOT_INSTRUCTION_BODY_V1;
|
|
1040
1069
|
LEGACY_AGENTSMESH_ROOT_INSTRUCTION_SECTION = `## Project-Specific Rules
|
|
1041
1070
|
|
|
@@ -1064,12 +1093,20 @@ ${ROOT_INSTRUCTION_BODY_V7}`;
|
|
|
1064
1093
|
AGENTSMESH_CONTRACT_WITH_V8_BODY = `## AgentsMesh Generation Contract
|
|
1065
1094
|
|
|
1066
1095
|
${ROOT_INSTRUCTION_BODY_V8}`;
|
|
1096
|
+
AGENTSMESH_CONTRACT_WITH_V9_BODY = `## AgentsMesh Generation Contract
|
|
1097
|
+
|
|
1098
|
+
${ROOT_INSTRUCTION_BODY_V9}`;
|
|
1099
|
+
AGENTSMESH_CONTRACT_WITH_V10_BODY = `## AgentsMesh Generation Contract
|
|
1100
|
+
|
|
1101
|
+
${ROOT_INSTRUCTION_BODY_V10}`;
|
|
1067
1102
|
AGENTSMESH_ROOT_INSTRUCTION_PARAGRAPH = `${ROOT_CONTRACT_START}
|
|
1068
1103
|
## AgentsMesh Generation Contract
|
|
1069
1104
|
|
|
1070
1105
|
${ROOT_INSTRUCTION_BODY}
|
|
1071
1106
|
${ROOT_CONTRACT_END}`;
|
|
1072
1107
|
LEGACY_FORMS = [
|
|
1108
|
+
AGENTSMESH_CONTRACT_WITH_V10_BODY,
|
|
1109
|
+
AGENTSMESH_CONTRACT_WITH_V9_BODY,
|
|
1073
1110
|
AGENTSMESH_CONTRACT_WITH_V8_BODY,
|
|
1074
1111
|
AGENTSMESH_CONTRACT_WITH_V7_BODY,
|
|
1075
1112
|
AGENTSMESH_CONTRACT_WITH_V6_BODY,
|
|
@@ -15756,9 +15793,18 @@ function generateIgnore12(canonical) {
|
|
|
15756
15793
|
if (!canonical.ignore || canonical.ignore.length === 0) return [];
|
|
15757
15794
|
return [{ path: QWEN_IGNORE, content: canonical.ignore.join("\n") }];
|
|
15758
15795
|
}
|
|
15796
|
+
function renderQwenGlobalInstructions(canonical) {
|
|
15797
|
+
const root = canonical.rules.find((rule) => rule.root);
|
|
15798
|
+
const nonRootRules = canonical.rules.filter((rule) => {
|
|
15799
|
+
if (rule.root) return false;
|
|
15800
|
+
return rule.targets.length === 0 || rule.targets.includes(QWEN_CODE_TARGET);
|
|
15801
|
+
});
|
|
15802
|
+
return appendEmbeddedRulesBlock(root?.body.trim() ?? "", nonRootRules);
|
|
15803
|
+
}
|
|
15759
15804
|
var init_generator26 = __esm({
|
|
15760
15805
|
"src/targets/qwen-code/generator.ts"() {
|
|
15761
15806
|
init_markdown();
|
|
15807
|
+
init_managed_blocks();
|
|
15762
15808
|
init_constants21();
|
|
15763
15809
|
}
|
|
15764
15810
|
});
|
|
@@ -15841,6 +15887,7 @@ var init_qwen_code2 = __esm({
|
|
|
15841
15887
|
};
|
|
15842
15888
|
globalLayout22 = {
|
|
15843
15889
|
rootInstructionPath: QWEN_GLOBAL_ROOT,
|
|
15890
|
+
renderPrimaryRootInstruction: renderQwenGlobalInstructions,
|
|
15844
15891
|
skillDir: QWEN_GLOBAL_SKILLS_DIR,
|
|
15845
15892
|
managedOutputs: {
|
|
15846
15893
|
dirs: [QWEN_GLOBAL_COMMANDS_DIR, QWEN_GLOBAL_AGENTS_DIR, QWEN_GLOBAL_SKILLS_DIR],
|
|
@@ -18731,6 +18778,19 @@ init_fs();
|
|
|
18731
18778
|
|
|
18732
18779
|
// src/config/remote/git-remote.ts
|
|
18733
18780
|
init_fs();
|
|
18781
|
+
|
|
18782
|
+
// src/utils/output/redact-url-secrets.ts
|
|
18783
|
+
var URL_WITH_CREDENTIALS = /([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)([^/@\s"'<>]+)@([^\s"'<>]+)/g;
|
|
18784
|
+
function redactUrlSecrets(message) {
|
|
18785
|
+
return message.replace(
|
|
18786
|
+
URL_WITH_CREDENTIALS,
|
|
18787
|
+
(_full, scheme, _userinfo, rest) => {
|
|
18788
|
+
return `${scheme}***@${rest}`;
|
|
18789
|
+
}
|
|
18790
|
+
);
|
|
18791
|
+
}
|
|
18792
|
+
|
|
18793
|
+
// src/config/remote/git-remote.ts
|
|
18734
18794
|
var execFileAsync = promisify(execFile);
|
|
18735
18795
|
var REPO_DIRNAME = "repo";
|
|
18736
18796
|
function ensureNotFlag(value, kind) {
|
|
@@ -18764,12 +18824,13 @@ async function fetchGitRemoteExtend(parsed, extendName, options, cacheDir, build
|
|
|
18764
18824
|
await rm(stagedRoot, { recursive: true, force: true });
|
|
18765
18825
|
const allowFallback = options.allowOfflineFallback !== false;
|
|
18766
18826
|
if (allowFallback && await hasCachedRepo(cacheRepoDir)) {
|
|
18827
|
+
const rawMsg = err instanceof Error ? err.message : String(err);
|
|
18767
18828
|
console.warn(
|
|
18768
|
-
`[agentsmesh] Remote fetch failed for ${extendName}; using cached version. Error: ${
|
|
18829
|
+
`[agentsmesh] Remote fetch failed for ${extendName}; using cached version. Error: ${redactUrlSecrets(rawMsg)}`
|
|
18769
18830
|
);
|
|
18770
18831
|
return readCachedRepo(cacheRepoDir);
|
|
18771
18832
|
}
|
|
18772
|
-
throw err;
|
|
18833
|
+
throw err instanceof Error ? Object.assign(new Error(redactUrlSecrets(err.message)), { cause: err.cause }) : err;
|
|
18773
18834
|
}
|
|
18774
18835
|
}
|
|
18775
18836
|
async function readCachedRepo(repoDir) {
|
|
@@ -18930,13 +18991,14 @@ async function fetchGithubRemoteExtend(parsed, extendName, options, cacheDir, bu
|
|
|
18930
18991
|
if (allowFallback && await exists(extractDir)) {
|
|
18931
18992
|
const topDir2 = await findExtractTopDir(extractDir);
|
|
18932
18993
|
if (topDir2) {
|
|
18994
|
+
const rawMsg = err instanceof Error ? err.message : String(err);
|
|
18933
18995
|
console.warn(
|
|
18934
|
-
`[agentsmesh] Network failed for ${extendName}; using cached version. Error: ${
|
|
18996
|
+
`[agentsmesh] Network failed for ${extendName}; using cached version. Error: ${redactUrlSecrets(rawMsg)}`
|
|
18935
18997
|
);
|
|
18936
18998
|
return { resolvedPath: join(extractDir, topDir2), version: tag };
|
|
18937
18999
|
}
|
|
18938
19000
|
}
|
|
18939
|
-
throw err;
|
|
19001
|
+
throw err instanceof Error ? Object.assign(new Error(redactUrlSecrets(err.message)), { cause: err.cause }) : err;
|
|
18940
19002
|
}
|
|
18941
19003
|
await rm(extractDir, { recursive: true, force: true });
|
|
18942
19004
|
await mkdir(extractDir, { recursive: true });
|
|
@@ -18947,12 +19009,14 @@ async function fetchGithubRemoteExtend(parsed, extendName, options, cacheDir, bu
|
|
|
18947
19009
|
file: tarPath,
|
|
18948
19010
|
cwd: extractDir,
|
|
18949
19011
|
strict: true,
|
|
19012
|
+
// Allowlist entry types instead of denylist: only `File` and `Directory`
|
|
19013
|
+
// can be extracted. Hardlinks (`Link`), symlinks (`SymbolicLink`), FIFOs,
|
|
19014
|
+
// character/block devices, and any future/exotic tar entry type are
|
|
19015
|
+
// rejected. A denylist would silently let an unknown variant through.
|
|
18950
19016
|
filter: (entryPath, entry) => {
|
|
18951
19017
|
if (isZipSlipPath(entryPath)) return false;
|
|
18952
|
-
|
|
18953
|
-
|
|
18954
|
-
}
|
|
18955
|
-
return true;
|
|
19018
|
+
const type = entry && "type" in entry ? entry.type : void 0;
|
|
19019
|
+
return type === "File" || type === "Directory";
|
|
18956
19020
|
}
|
|
18957
19021
|
});
|
|
18958
19022
|
} finally {
|
|
@@ -19050,8 +19114,11 @@ function parseGitSource(source) {
|
|
|
19050
19114
|
return null;
|
|
19051
19115
|
}
|
|
19052
19116
|
const allowInsecure = process.env.AGENTSMESH_ALLOW_INSECURE_GIT === "1" || process.env.AGENTSMESH_ALLOW_INSECURE_GIT === "true";
|
|
19053
|
-
const
|
|
19054
|
-
|
|
19117
|
+
const allowLocalGit = process.env.AGENTSMESH_ALLOW_LOCAL_GIT === "1" || process.env.AGENTSMESH_ALLOW_LOCAL_GIT === "true";
|
|
19118
|
+
const allowed = ["https:", "ssh:"];
|
|
19119
|
+
if (allowInsecure) allowed.push("http:");
|
|
19120
|
+
if (allowLocalGit) allowed.push("file:");
|
|
19121
|
+
if (!allowed.includes(parsedUrl.protocol)) {
|
|
19055
19122
|
return null;
|
|
19056
19123
|
}
|
|
19057
19124
|
return { url, ref };
|
|
@@ -19576,6 +19643,7 @@ async function parseAgents(agentsDir, opts = {}) {
|
|
|
19576
19643
|
|
|
19577
19644
|
// src/canonical/features/skills.ts
|
|
19578
19645
|
init_fs();
|
|
19646
|
+
init_fs_traverse();
|
|
19579
19647
|
init_markdown();
|
|
19580
19648
|
init_boilerplate_filter();
|
|
19581
19649
|
async function readContent(path) {
|
|
@@ -19594,7 +19662,7 @@ function sanitizeSkillName(raw) {
|
|
|
19594
19662
|
return raw.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
19595
19663
|
}
|
|
19596
19664
|
async function listSupportingFiles(skillDir) {
|
|
19597
|
-
const files = await
|
|
19665
|
+
const files = await readDirRecursiveNoSymlinks(skillDir);
|
|
19598
19666
|
const result = [];
|
|
19599
19667
|
for (const absPath of files) {
|
|
19600
19668
|
const raw = absPath.slice(skillDir.length + 1);
|