@passioncode-ai/fabric-agent-adapter 0.3.1 → 0.4.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/CHANGELOG.md +82 -0
- package/LICENSE +151 -17
- package/README.md +51 -6
- package/SECURITY.md +16 -3
- package/bin/fabric-agent-adapter.js +87 -43
- package/package.json +13 -8
- package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +5 -6
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +8 -5
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +240 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/dashboard.md +32 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/events-and-notifications.md +44 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/lifecycle.md +63 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/migrating-a-service.md +32 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +83 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/surfaces-and-auth.md +58 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +373 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +380 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +663 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +226 -0
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +23 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,87 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.3 - 2026-09-29
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **License.** The adapter is now source-available under
|
|
8
|
+
`PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0`, with a
|
|
9
|
+
commercial license on request (contact@passioncode.ai). Versions up to and including
|
|
10
|
+
v0.4.2, and npm releases up to and including 0.3.1, were released under MIT and remain
|
|
11
|
+
available under it. The manifests, the three skills' `license:` and the README say the
|
|
12
|
+
same; contributions come in under `CLA.md`, which the new PR template asks for.
|
|
13
|
+
`test/validate.py` fails a tree that slips back to MIT.
|
|
14
|
+
- Author and marketplace owner are PassionCode.ai (`https://passioncode.ai/`).
|
|
15
|
+
- **Contract pin** moves from `20a818e` to `a5a2709` (fabric-agent-contract `main`), the
|
|
16
|
+
commit `building-fabric-services` already pinned. Between the two the provider
|
|
17
|
+
profiles are unchanged — only the `fabric-service/0.1` extension was added — and
|
|
18
|
+
`adapt_project.py check --contract` gives the same verdicts for an MCP, an A2A and a
|
|
19
|
+
local-runner bundle at both commits (declaration shape PASS). One pin for all three
|
|
20
|
+
skills.
|
|
21
|
+
- `creating-fabric-agents` hands the agent's own loop to `agent-orchestrator`, its
|
|
22
|
+
eval suite to `agent-evals` (agent-stack) and plugin packaging to `make-skill`;
|
|
23
|
+
`adapting-projects-to-fabric` sends wire-level MCP/A2A questions to `agent-interop`.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- The installer's help names the launcher by its npm org name,
|
|
28
|
+
`npx @passioncode-ai/passioncode@latest update`; the bare `passioncode` is not ours.
|
|
29
|
+
- A distributed eval named a personal agent as its example service; the
|
|
30
|
+
`building-fabric-services` evals use `example-agent`, and its description says "a
|
|
31
|
+
macOS machine" instead of naming whose.
|
|
32
|
+
|
|
33
|
+
## 0.4.2 - 2026-09-29
|
|
34
|
+
|
|
35
|
+
- Kit: `LoopbackHTTPServer`, a `ThreadingHTTPServer` whose bind asks no resolver.
|
|
36
|
+
`http.server` calls `socket.getfqdn()` between `bind()` and `listen()`; on a macOS
|
|
37
|
+
CI runner that held a service's port bound but silent for over 20 seconds. The
|
|
38
|
+
sample service and the skill's startup order use it, and the skill names the trap.
|
|
39
|
+
- Kit: a garbled pid file (for example a superscript digit) now reads as "no pid"
|
|
40
|
+
instead of raising `ValueError` while naming the holder of a lock.
|
|
41
|
+
|
|
42
|
+
## 0.4.1 - 2026-09-29
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- `building-fabric-services` could not be loaded by a strict YAML reader: its
|
|
47
|
+
front-matter `description` was an unquoted plain scalar holding `: `
|
|
48
|
+
("fabric-service/0.1 extension: which surface", line 3, column 493), which YAML
|
|
49
|
+
rejects with "mapping values are not allowed here". Claude Code read it
|
|
50
|
+
leniently, so the plugin worked, but an agent reading the skill from
|
|
51
|
+
`~/.agents/skills` could drop it. The description is now a folded block
|
|
52
|
+
scalar (`>-`) with the exact same text (927 characters).
|
|
53
|
+
- The validator could not see that class of defect: `test/validate.py` now
|
|
54
|
+
parses every SKILL.md front matter strictly (standard library only) and
|
|
55
|
+
rejects what a YAML reader rejects in an unquoted value — `: ` or a trailing
|
|
56
|
+
`:`, ` #` (a comment that silently truncates the value), a leading indicator
|
|
57
|
+
character, a duplicate key, an unclosed quote, an undeclared multi-line
|
|
58
|
+
value — with the line and column. `test/test_validate.py` plants each case.
|
|
59
|
+
`validate.py --frontmatter <SKILL.md ...>` checks installed copies anywhere.
|
|
60
|
+
- The release smoke test looked for `~/.claude/skills`, where the installer has
|
|
61
|
+
not written since 0.4.0, so it would fail on the first release that ran it.
|
|
62
|
+
It now checks all three skills in `~/.agents/skills`, that `~/.claude/skills`
|
|
63
|
+
stays untouched, and that the installed front matter parses strictly.
|
|
64
|
+
- `SKILL-CARD.md` versions and the release smoke paths joined the validator's
|
|
65
|
+
sync checks.
|
|
66
|
+
|
|
67
|
+
## 0.4.0 - 2026-09-28
|
|
68
|
+
|
|
69
|
+
- Add the `building-fabric-services` skill for the `fabric-service/0.1` local
|
|
70
|
+
service extension (Fabric Agent Contract DEC-0015): surface choice (MCP
|
|
71
|
+
streamable HTTP, CLI, A2A), token and one-time login, state and cache
|
|
72
|
+
directories, one copy per machine, launchd, descriptor, well-known document,
|
|
73
|
+
events feed and notifications.
|
|
74
|
+
- Ship reference kits in Python (`fabric_service.py`) and Node
|
|
75
|
+
(`fabric-service.mjs`) whose instance locks exclude each other, a complete
|
|
76
|
+
`sample_service.py`, and `check_service.py`, a live conformance probe that
|
|
77
|
+
reports PASS, FAIL or NOT_RUN per rule.
|
|
78
|
+
- `creating-fabric-agents` now routes an agent that runs as a service through
|
|
79
|
+
the new skill.
|
|
80
|
+
- Fix the installer shadowing its own plugin: `npx @passioncode-ai/fabric-agent-adapter`
|
|
81
|
+
and `install.sh` now install into the agents hub `~/.agents/skills`; a plain
|
|
82
|
+
copy into `~/.claude/skills` is refused while the plugin is installed, and
|
|
83
|
+
`--prune-shadow` moves existing shadowing copies aside.
|
|
84
|
+
|
|
3
85
|
## 0.3.1 - 2026-08-27
|
|
4
86
|
|
|
5
87
|
- Fix the executable bit on `bin/fabric-agent-adapter.js` and `install.sh`: the
|
package/LICENSE
CHANGED
|
@@ -1,22 +1,156 @@
|
|
|
1
|
-
|
|
1
|
+
Copyright (c) 2026 Siarhei Sheleh
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This software is source-available, not open source. You may use it under
|
|
4
|
+
either of the two licenses below, at your option:
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
6
|
+
1. PolyForm Noncommercial License 1.0.0
|
|
7
|
+
SPDX: PolyForm-Noncommercial-1.0.0
|
|
8
|
+
2. PolyForm Internal Use License 1.0.0
|
|
9
|
+
SPDX: LicenseRef-PolyForm-Internal-Use-1.0.0
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
In short: individuals and noncommercial organisations may use, change and
|
|
12
|
+
share it for noncommercial purposes; any company may use it, and change it,
|
|
13
|
+
for its own internal operations. Distributing it commercially, or building
|
|
14
|
+
this software or its code into a product or service you provide to others,
|
|
15
|
+
needs a separate commercial license: contact@passioncode.ai.
|
|
16
|
+
This summary is not part of either license; the texts below govern.
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
18
|
+
Versions up to and including v0.4.2 of this repository (and npm releases up to and
|
|
19
|
+
including 0.3.1) were released under the MIT License; those releases remain available
|
|
20
|
+
under MIT.
|
|
22
21
|
|
|
22
|
+
Required Notice: Copyright (c) 2026 Siarhei Sheleh (https://passioncode.ai)
|
|
23
|
+
|
|
24
|
+
================================================================================
|
|
25
|
+
|
|
26
|
+
# PolyForm Noncommercial License 1.0.0
|
|
27
|
+
|
|
28
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
29
|
+
|
|
30
|
+
## Acceptance
|
|
31
|
+
|
|
32
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
33
|
+
|
|
34
|
+
## Copyright License
|
|
35
|
+
|
|
36
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only distribute the software according to [Distribution License](#distribution-license) and make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license).
|
|
37
|
+
|
|
38
|
+
## Distribution License
|
|
39
|
+
|
|
40
|
+
The licensor grants you an additional copyright license to distribute copies of the software. Your license to distribute covers distributing the software with changes and new works permitted by [Changes and New Works License](#changes-and-new-works-license).
|
|
41
|
+
|
|
42
|
+
## Notices
|
|
43
|
+
|
|
44
|
+
You must ensure that anyone who gets a copy of any part of the software from you also gets a copy of these terms or the URL for them above, as well as copies of any plain-text lines beginning with `Required Notice:` that the licensor provided with the software. For example:
|
|
45
|
+
|
|
46
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
47
|
+
|
|
48
|
+
## Changes and New Works License
|
|
49
|
+
|
|
50
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
51
|
+
|
|
52
|
+
## Patent License
|
|
53
|
+
|
|
54
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
55
|
+
|
|
56
|
+
## Noncommercial Purposes
|
|
57
|
+
|
|
58
|
+
Any noncommercial purpose is a permitted purpose.
|
|
59
|
+
|
|
60
|
+
## Personal Uses
|
|
61
|
+
|
|
62
|
+
Personal use for research, experiment, and testing for the benefit of public knowledge, personal study, private entertainment, hobby projects, amateur pursuits, or religious observance, without any anticipated commercial application, is use for a permitted purpose.
|
|
63
|
+
|
|
64
|
+
## Noncommercial Organizations
|
|
65
|
+
|
|
66
|
+
Use by any charitable organization, educational institution, public research organization, public safety or health organization, environmental protection organization, or government institution is use for a permitted purpose regardless of the source of funding or obligations resulting from the funding.
|
|
67
|
+
|
|
68
|
+
## Fair Use
|
|
69
|
+
|
|
70
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
71
|
+
|
|
72
|
+
## No Other Rights
|
|
73
|
+
|
|
74
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
75
|
+
|
|
76
|
+
## Patent Defense
|
|
77
|
+
|
|
78
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
79
|
+
|
|
80
|
+
## Violations
|
|
81
|
+
|
|
82
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
83
|
+
|
|
84
|
+
## No Liability
|
|
85
|
+
|
|
86
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
87
|
+
|
|
88
|
+
## Definitions
|
|
89
|
+
|
|
90
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
91
|
+
|
|
92
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
93
|
+
|
|
94
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
95
|
+
|
|
96
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
97
|
+
|
|
98
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
99
|
+
|
|
100
|
+
================================================================================
|
|
101
|
+
|
|
102
|
+
# PolyForm Internal Use License 1.0.0
|
|
103
|
+
|
|
104
|
+
<https://polyformproject.org/licenses/internal-use/1.0.0>
|
|
105
|
+
|
|
106
|
+
## Acceptance
|
|
107
|
+
|
|
108
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
109
|
+
|
|
110
|
+
## Copyright License
|
|
111
|
+
|
|
112
|
+
The licensor grants you a copyright license for the software to do everything you might do with the software that would otherwise infringe the licensor's copyright in it for any permitted purpose. However, you may only make changes or new works based on the software according to [Changes and New Works License](#changes-and-new-works-license), and you may not distribute the software.
|
|
113
|
+
|
|
114
|
+
## Changes and New Works License
|
|
115
|
+
|
|
116
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
117
|
+
|
|
118
|
+
## Patent License
|
|
119
|
+
|
|
120
|
+
The licensor grants you a patent license for the software that covers patent claims the licensor can license, or becomes able to license, that you would infringe by using the software.
|
|
121
|
+
|
|
122
|
+
## Fair Use
|
|
123
|
+
|
|
124
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
125
|
+
|
|
126
|
+
## Internal Business Use
|
|
127
|
+
|
|
128
|
+
Use of the software for the internal business operations of you and your company is use for a permitted purpose.
|
|
129
|
+
|
|
130
|
+
## No Other Rights
|
|
131
|
+
|
|
132
|
+
These terms do not allow you to sublicense or transfer any of your licenses to anyone else, or prevent the licensor from granting licenses to anyone else. These terms do not imply any other licenses.
|
|
133
|
+
|
|
134
|
+
## Patent Defense
|
|
135
|
+
|
|
136
|
+
If you make any written claim that the software infringes or contributes to infringement of any patent, your patent license for the software granted under these terms ends immediately. If your company makes such a claim, your patent license ends immediately for work on behalf of your company.
|
|
137
|
+
|
|
138
|
+
## Violations
|
|
139
|
+
|
|
140
|
+
The first time you are notified in writing that you have violated any of these terms, or done anything with the software not covered by your licenses, your licenses can nonetheless continue if you come into full compliance with these terms, and take practical steps to correct past violations, within 32 days of receiving notice. Otherwise, all your licenses end immediately.
|
|
141
|
+
|
|
142
|
+
## No Liability
|
|
143
|
+
|
|
144
|
+
***As far as the law allows, the software comes as is, without any warranty or condition, and the licensor will not be liable to you for any damages arising out of these terms or the use or nature of the software, under any kind of legal claim.***
|
|
145
|
+
|
|
146
|
+
## Definitions
|
|
147
|
+
|
|
148
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
149
|
+
|
|
150
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
151
|
+
|
|
152
|
+
**Your company** is any legal entity, sole proprietorship, or other kind of organization that you work for, plus all organizations that have control over, are under the control of, or are under common control with that organization. **Control** means ownership of substantially all the assets of an entity, or the power to direct its management and policies by vote, contract, or otherwise. Control can be direct or indirect.
|
|
153
|
+
|
|
154
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
155
|
+
|
|
156
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
package/README.md
CHANGED
|
@@ -1,13 +1,38 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://passioncode.ai/">
|
|
3
|
+
<img src="assets/passioncode-icon-256.png" width="104" height="104" alt="PassionCode.ai passion fruit mark">
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
6
|
+
|
|
1
7
|
# Fabric Agent Adapter
|
|
2
8
|
|
|
9
|
+
> **PassionCode.ai — The agent-agnostic operating system for AI-native teams.**
|
|
10
|
+
|
|
11
|
+
**From vibe coding to passion coding.** PassionCode.ai moves the control point from
|
|
12
|
+
managing agents one by one to operating Projects. Fabric Agent Adapter is the portable
|
|
13
|
+
on-ramp: it helps an existing repository become a compatible, replaceable Provider
|
|
14
|
+
without moving the Project onto one proprietary agent runtime.
|
|
15
|
+
|
|
3
16
|
[](https://www.npmjs.com/package/@passioncode-ai/fabric-agent-adapter)
|
|
4
17
|
[](https://github.com/passioncode-ai/fabric-agent-adapter/actions/workflows/validate.yml)
|
|
5
|
-
[](LICENSE)
|
|
19
|
+
|
|
20
|
+
Private, portable Agent Skills for the
|
|
21
|
+
[Fabric Agent Contract](https://github.com/passioncode-ai/fabric-agent-contract):
|
|
22
|
+
`adapting-projects-to-fabric`, `creating-fabric-agents` and
|
|
23
|
+
`building-fabric-services`.
|
|
6
24
|
|
|
7
|
-
|
|
8
|
-
|
|
25
|
+
`building-fabric-services` makes an agent a long-lived local service with a dashboard
|
|
26
|
+
that is always alive, runs as one copy, keeps its state through a reinstall and appears
|
|
27
|
+
in Fabric Dashboards by itself — the `fabric-service/0.1` extension. It ships Python and
|
|
28
|
+
Node reference kits (`scripts/fabric_service.py`, `scripts/fabric-service.mjs`), a
|
|
29
|
+
complete `scripts/sample_service.py`, and `scripts/check_service.py`, a live probe:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python3 plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py example-agent
|
|
33
|
+
```
|
|
9
34
|
|
|
10
|
-
|
|
35
|
+
For provider bundles the adapting skill helps an agent author:
|
|
11
36
|
|
|
12
37
|
- inspect the project's stable integration surfaces without executing it;
|
|
13
38
|
- choose A2A `1.0`, MCP `2026-07-28`, or `fabric-local-runner/0.1` per capability;
|
|
@@ -26,7 +51,8 @@ The repository is private; the npm package is public. The npm path needs no GitH
|
|
|
26
51
|
npm — no GitHub access required:
|
|
27
52
|
|
|
28
53
|
```bash
|
|
29
|
-
npx @passioncode-ai/fabric-agent-adapter # installs
|
|
54
|
+
npx @passioncode-ai/fabric-agent-adapter # installs every skill into the agents hub ~/.agents/skills
|
|
55
|
+
npx @passioncode-ai/fabric-agent-adapter --prune-shadow # remove ~/.claude/skills copies that shadow the plugin
|
|
30
56
|
```
|
|
31
57
|
|
|
32
58
|
Generic Agent Skills clients:
|
|
@@ -34,6 +60,7 @@ Generic Agent Skills clients:
|
|
|
34
60
|
```bash
|
|
35
61
|
npx skills add passioncode-ai/fabric-agent-adapter --skill adapting-projects-to-fabric
|
|
36
62
|
npx skills add passioncode-ai/fabric-agent-adapter --skill creating-fabric-agents
|
|
63
|
+
npx skills add passioncode-ai/fabric-agent-adapter --skill building-fabric-services
|
|
37
64
|
```
|
|
38
65
|
|
|
39
66
|
Claude Code plugin marketplace:
|
|
@@ -52,6 +79,12 @@ Adapt this project for Fabric compatibility. Inspect it, choose the profile per
|
|
|
52
79
|
capability, scaffold the provider bundle, and report every conformance gate.
|
|
53
80
|
```
|
|
54
81
|
|
|
82
|
+
Or, for an agent that must keep running with a dashboard:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
Make this agent a local service with an always-on dashboard, following fabric-service/0.1.
|
|
86
|
+
```
|
|
87
|
+
|
|
55
88
|
Or, for an agent that does not exist yet:
|
|
56
89
|
|
|
57
90
|
```text
|
|
@@ -86,11 +119,23 @@ claude plugin validate ./plugins/fabric-agent-adapter --strict
|
|
|
86
119
|
claude plugin validate . --strict
|
|
87
120
|
```
|
|
88
121
|
|
|
122
|
+
`test/validate.py` reads every SKILL.md front matter as strictly as a YAML parser does; an
|
|
123
|
+
unquoted value holding `: ` fails it. `python3 test/validate.py --frontmatter <SKILL.md ...>`
|
|
124
|
+
checks copies installed elsewhere, such as `~/.agents/skills/*/SKILL.md`.
|
|
125
|
+
|
|
89
126
|
## Contract pin
|
|
90
127
|
|
|
91
128
|
- version: `0.1.0`
|
|
92
|
-
- commit: `
|
|
129
|
+
- commit: `a5a27092ba0dcc5facfbeae8b359146dfb403e9a`
|
|
93
130
|
|
|
94
131
|
The contract repository is normative. Updating the pin requires a new adapter release,
|
|
95
132
|
fixture review, and a complete validation run.
|
|
96
133
|
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
Source-available under PolyForm Noncommercial or Internal Use; commercial license on
|
|
137
|
+
request (contact@passioncode.ai). SPDX:
|
|
138
|
+
`PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0` — see
|
|
139
|
+
[LICENSE](LICENSE). Versions up to and including v0.4.2 (npm up to 0.3.1) were released
|
|
140
|
+
under the MIT License and remain available under it. Contributions are accepted under
|
|
141
|
+
[CLA.md](CLA.md) ([CONTRIBUTING.md](CONTRIBUTING.md)).
|
package/SECURITY.md
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
# Security
|
|
2
2
|
|
|
3
|
-
Report vulnerabilities privately to
|
|
4
|
-
|
|
5
|
-
or customer project data.
|
|
3
|
+
Report vulnerabilities privately to contact@passioncode.ai. Do not open a public issue
|
|
4
|
+
containing credentials, private provider URLs, or customer project data.
|
|
6
5
|
|
|
7
6
|
The adapter must not write secret values to manifests, fixtures, probes, logs, or command
|
|
8
7
|
arguments. Generated and external provider outputs are untrusted. Live probes must be
|
|
9
8
|
bounded and non-publishing until explicit scoped grants exist in a project binding.
|
|
10
9
|
|
|
10
|
+
|
|
11
|
+
## What the installers and scripts touch
|
|
12
|
+
|
|
13
|
+
- `npx @passioncode-ai/fabric-agent-adapter` and `install.sh` write only
|
|
14
|
+
`~/.agents/skills/<skill>`; `--target claude` writes `~/.claude/skills/<skill>` and is
|
|
15
|
+
refused while the plugin is installed; `--prune-shadow` moves shadowing copies into
|
|
16
|
+
`~/.claude/skills-shadow-backup/`.
|
|
17
|
+
- `building-fabric-services/scripts/check_service.py` reads a descriptor and the token
|
|
18
|
+
file it names, talks only to `127.0.0.1:<port>`, and redeems one login code it asked
|
|
19
|
+
for itself (creating one dashboard session). It never prints the token.
|
|
20
|
+
- The service kits create the service token (0600) and the instance lock in the
|
|
21
|
+
service's own data directory, and write a launchd plist and a descriptor only when an
|
|
22
|
+
installer calls them. The token is readable by any process of the same user; the
|
|
23
|
+
protocol defends against web pages and mistakes, not against hostile local code.
|
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
/*
|
|
3
3
|
* fabric-agent-adapter installer CLI.
|
|
4
4
|
*
|
|
5
|
-
* Installs every skill this plugin ships into
|
|
6
|
-
* (
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* the repository is private; the npm package needs none)
|
|
5
|
+
* Installs every skill this plugin ships into the shared agents hub
|
|
6
|
+
* ~/.agents/skills/<name> (read by Codex, Cursor, Gemini, OpenCode and others).
|
|
7
|
+
* Claude Code gets the skills through the plugin, never through a plain copy:
|
|
8
|
+
* a copy in ~/.claude/skills shadows the plugin and serves its frozen version
|
|
9
|
+
* forever. Idempotent; an existing install is skipped unless --force.
|
|
10
|
+
* Zero dependencies.
|
|
12
11
|
*/
|
|
13
12
|
'use strict';
|
|
14
13
|
|
|
@@ -18,20 +17,25 @@ const os = require('os');
|
|
|
18
17
|
|
|
19
18
|
const ROOT = path.resolve(__dirname, '..');
|
|
20
19
|
const REPO = 'passioncode-ai/fabric-agent-adapter';
|
|
20
|
+
const PLUGIN_ID = 'fabric-agent-adapter@fabric-agent-adapter';
|
|
21
21
|
|
|
22
22
|
function usage() {
|
|
23
23
|
console.log(`fabric-agent-adapter installer
|
|
24
24
|
|
|
25
25
|
Usage:
|
|
26
26
|
npx @passioncode-ai/fabric-agent-adapter [--force]
|
|
27
|
-
install every skill
|
|
28
|
-
|
|
27
|
+
install every skill into the agents hub ~/.agents/skills
|
|
28
|
+
npx @passioncode-ai/fabric-agent-adapter --target claude [--force]
|
|
29
|
+
plain copy into ~/.claude/skills — refused while the plugin is installed
|
|
30
|
+
npx @passioncode-ai/fabric-agent-adapter --prune-shadow
|
|
31
|
+
remove plain ~/.claude/skills copies that shadow the installed plugin
|
|
29
32
|
npx @passioncode-ai/fabric-agent-adapter --help
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
Claude Code (recommended):
|
|
35
|
+
claude plugin marketplace add ${REPO}
|
|
36
|
+
claude plugin install ${PLUGIN_ID}
|
|
37
|
+
Every PassionCode.ai skill for every agent at once:
|
|
38
|
+
npx @passioncode-ai/passioncode@latest update`);
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
function copyDir(src, dest) {
|
|
@@ -44,15 +48,38 @@ function copyDir(src, dest) {
|
|
|
44
48
|
}
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
function pluginInstalled(home) {
|
|
52
|
+
try {
|
|
53
|
+
const data = JSON.parse(fs.readFileSync(path.join(home, '.claude/plugins/installed_plugins.json'), 'utf8'));
|
|
54
|
+
const records = (data.plugins || {})[PLUGIN_ID] || [];
|
|
55
|
+
return records.some((r) => r.installPath && fs.existsSync(path.join(r.installPath, 'skills')));
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function skillNames() {
|
|
62
|
+
const skillRoot = path.join(ROOT, 'plugins/fabric-agent-adapter/skills');
|
|
63
|
+
if (!fs.existsSync(skillRoot)) return { skillRoot, names: [] };
|
|
64
|
+
// Iterate rather than name one skill: a skill added to the plugin must not
|
|
65
|
+
// require an installer change to reach anybody.
|
|
66
|
+
const names = fs.readdirSync(skillRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
67
|
+
return { skillRoot, names };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function pruneShadows(home, names) {
|
|
71
|
+
let removed = 0;
|
|
72
|
+
for (const name of names) {
|
|
73
|
+
const shadow = path.join(home, '.claude', 'skills', name);
|
|
74
|
+
let info;
|
|
75
|
+
try { info = fs.lstatSync(shadow); } catch { continue; }
|
|
76
|
+
const backup = path.join(home, '.claude', 'skills-shadow-backup', `${name}-${Date.now()}`);
|
|
77
|
+
fs.mkdirSync(path.dirname(backup), { recursive: true });
|
|
78
|
+
fs.renameSync(shadow, backup);
|
|
79
|
+
console.log(`Removed shadowing ${info.isSymbolicLink() ? 'link' : 'copy'} ${shadow} (kept at ${backup})`);
|
|
80
|
+
removed += 1;
|
|
51
81
|
}
|
|
52
|
-
|
|
53
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
54
|
-
copyDir(src, dest);
|
|
55
|
-
console.log(`Installed ${label} -> ${dest}`);
|
|
82
|
+
if (!removed) console.log('No shadowing copies found.');
|
|
56
83
|
}
|
|
57
84
|
|
|
58
85
|
function main(argv) {
|
|
@@ -62,39 +89,56 @@ function main(argv) {
|
|
|
62
89
|
return 0;
|
|
63
90
|
}
|
|
64
91
|
const force = args.includes('--force');
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
const prune = args.includes('--prune-shadow');
|
|
93
|
+
let target = 'agents';
|
|
94
|
+
const known = new Set(['--force', '--prune-shadow']);
|
|
95
|
+
const unknown = [];
|
|
96
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
97
|
+
if (args[i] === '--target') {
|
|
98
|
+
target = args[i + 1];
|
|
99
|
+
i += 1;
|
|
100
|
+
} else if (!known.has(args[i])) unknown.push(args[i]);
|
|
101
|
+
}
|
|
102
|
+
if (unknown.length || !['agents', 'claude'].includes(target)) {
|
|
103
|
+
console.error(`unknown argument(s): ${unknown.concat(['agents', 'claude'].includes(target) ? [] : [`--target ${target}`]).join(' ')}`);
|
|
68
104
|
usage();
|
|
69
105
|
return 2;
|
|
70
106
|
}
|
|
71
107
|
|
|
72
|
-
const skillRoot =
|
|
73
|
-
if (!
|
|
74
|
-
console.error(`error:
|
|
108
|
+
const { skillRoot, names } = skillNames();
|
|
109
|
+
if (!names.length) {
|
|
110
|
+
console.error(`error: no skills found under ${skillRoot} — corrupted package?`);
|
|
75
111
|
return 1;
|
|
76
112
|
}
|
|
113
|
+
const home = os.homedir();
|
|
114
|
+
const hasPlugin = pluginInstalled(home);
|
|
77
115
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
116
|
+
if (prune) {
|
|
117
|
+
if (!hasPlugin) {
|
|
118
|
+
console.error(`error: the ${PLUGIN_ID} plugin is not installed, so a copy in ~/.claude/skills is not a shadow — nothing removed.`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
pruneShadows(home, names);
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
if (target === 'claude' && hasPlugin) {
|
|
125
|
+
console.error(`error: the ${PLUGIN_ID} plugin is installed; a plain copy in ~/.claude/skills would shadow it. Update the plugin instead:\n claude plugin marketplace update fabric-agent-adapter && claude plugin update ${PLUGIN_ID}`);
|
|
87
126
|
return 1;
|
|
88
127
|
}
|
|
89
128
|
|
|
90
|
-
const
|
|
129
|
+
const destRoot = target === 'claude' ? path.join(home, '.claude', 'skills') : path.join(home, '.agents', 'skills');
|
|
91
130
|
for (const name of names) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
131
|
+
const dest = path.join(destRoot, name);
|
|
132
|
+
if (fs.existsSync(dest) && !force) {
|
|
133
|
+
console.log(`skip: ${name} already installed at ${dest} (rerun with --force to overwrite)`);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
fs.rmSync(dest, { recursive: true, force: true });
|
|
137
|
+
copyDir(path.join(skillRoot, name), dest);
|
|
138
|
+
console.log(`Installed ${name} -> ${dest}`);
|
|
139
|
+
}
|
|
140
|
+
if (target === 'agents' && !hasPlugin) {
|
|
141
|
+
console.log(`Claude Code reads plugins, not the hub:\n claude plugin marketplace add ${REPO} && claude plugin install ${PLUGIN_ID}`);
|
|
98
142
|
}
|
|
99
143
|
console.log('Restart your agent — skills load at session start.');
|
|
100
144
|
return 0;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.3
|
|
4
|
-
"description": "Create
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"description": "Create Fabric-compatible agents, run them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract. This package is the installer CLI.",
|
|
5
5
|
"scripts": {
|
|
6
|
-
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q"
|
|
6
|
+
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test test/"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
9
|
"fabric-agent-adapter": "bin/fabric-agent-adapter.js"
|
|
@@ -17,14 +17,16 @@
|
|
|
17
17
|
"README.md",
|
|
18
18
|
"LICENSE",
|
|
19
19
|
"CHANGELOG.md",
|
|
20
|
-
"SECURITY.md"
|
|
20
|
+
"SECURITY.md",
|
|
21
|
+
"!**/__pycache__/**",
|
|
22
|
+
"!**/*.pyc"
|
|
21
23
|
],
|
|
22
24
|
"repository": "github:passioncode-ai/fabric-agent-adapter",
|
|
23
25
|
"homepage": "https://github.com/passioncode-ai/fabric-agent-adapter",
|
|
24
|
-
"license": "
|
|
26
|
+
"license": "PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0",
|
|
25
27
|
"author": {
|
|
26
|
-
"name": "
|
|
27
|
-
"url": "https://
|
|
28
|
+
"name": "PassionCode.ai",
|
|
29
|
+
"url": "https://passioncode.ai/"
|
|
28
30
|
},
|
|
29
31
|
"engines": {
|
|
30
32
|
"node": ">=16"
|
|
@@ -39,6 +41,9 @@
|
|
|
39
41
|
"provider",
|
|
40
42
|
"conformance",
|
|
41
43
|
"claude-code",
|
|
42
|
-
"skill"
|
|
44
|
+
"skill",
|
|
45
|
+
"local-service",
|
|
46
|
+
"dashboard",
|
|
47
|
+
"launchd"
|
|
43
48
|
]
|
|
44
49
|
}
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "fabric-agent-adapter",
|
|
4
4
|
"displayName": "Fabric Agent Adapter",
|
|
5
|
-
"description": "Create new Fabric-compatible agents and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles.",
|
|
6
|
-
"version": "0.3
|
|
5
|
+
"description": "Create new Fabric-compatible agents, build them as always-alive local services with dashboards (fabric-service/0.1), and adapt existing projects to the Fabric Agent Contract through evidence-backed MCP, A2A, or local-runner provider bundles.",
|
|
6
|
+
"version": "0.4.3",
|
|
7
7
|
"author": {
|
|
8
|
-
"name": "
|
|
9
|
-
"url": "https://
|
|
8
|
+
"name": "PassionCode.ai",
|
|
9
|
+
"url": "https://passioncode.ai/"
|
|
10
10
|
},
|
|
11
11
|
"homepage": "https://github.com/passioncode-ai/fabric-agent-adapter",
|
|
12
12
|
"repository": "https://github.com/passioncode-ai/fabric-agent-adapter",
|
|
13
|
-
"license": "
|
|
13
|
+
"license": "PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0",
|
|
14
14
|
"keywords": [
|
|
15
15
|
"fabric",
|
|
16
16
|
"agent",
|
|
@@ -22,4 +22,3 @@
|
|
|
22
22
|
"conformance"
|
|
23
23
|
]
|
|
24
24
|
}
|
|
25
|
-
|