@passioncode-ai/fabric-agent-adapter 0.4.2 → 0.5.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/LICENSE +150 -17
- package/README.md +44 -6
- package/SECURITY.md +2 -3
- package/bin/fabric-agent-adapter.js +1 -1
- package/package.json +5 -5
- package/plugins/fabric-agent-adapter/.claude-plugin/plugin.json +4 -4
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/SKILL.md +25 -6
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/provider-entry.md +53 -0
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py +15 -2
- package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/fabric_provider.py +242 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/SKILL.md +23 -7
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/interop.md +77 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/references/protocol.md +1 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py +174 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-interop.mjs +188 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric-service.mjs +8 -1
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_interop.py +424 -0
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/fabric_service.py +14 -2
- package/plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/sample_service.py +116 -1
- package/plugins/fabric-agent-adapter/skills/creating-fabric-agents/SKILL.md +22 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,75 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.0 - 2026-09-30
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`fabric-interop/0.1` in the kits** (Fabric Agent Contract DEC-0016).
|
|
8
|
+
`building-fabric-services/scripts/fabric_interop.py` and its Node twin
|
|
9
|
+
`fabric-interop.mjs`: W3C trace context (`child_traceparent`, `trace_ids`), a
|
|
10
|
+
capability served as the MCP tool of its name with annotations from its effect,
|
|
11
|
+
durable jobs (`JobStore`: ids survive a restart, terminal states never change,
|
|
12
|
+
`unknown-job` for an unknown id), the result envelope with `usage`, and elicitations
|
|
13
|
+
(a titled single-select in form mode, URL mode for secrets; form mode refuses a
|
|
14
|
+
secret field). Python also ships `McpToolServer`, a minimal `tools/list` /
|
|
15
|
+
`tools/call` dispatcher with `fabric.job.get` and `fabric.job.cancel` built in.
|
|
16
|
+
- Events carry `traceId` and `spanId` as a pair (`make_event`, `makeEvent`).
|
|
17
|
+
- The sample service serves MCP at `/mcp`: `sample.echo`, and `sample.draft`, a job
|
|
18
|
+
that stops for a title choice and completes with a traced result. `register` writes
|
|
19
|
+
its manifest and schemas and points the descriptor's `fabricManifest` at it.
|
|
20
|
+
- The probe `check_service.py` gains seven `interop.*` rules: manifest link (G-07),
|
|
21
|
+
capability list, tools equal to the manifest (FAC-SEM-017), job tools, unknown job,
|
|
22
|
+
trace propagation and event trace pairs. It calls only `tools/list` and
|
|
23
|
+
`fabric.job.get` for a made-up id.
|
|
24
|
+
- `adapting-projects-to-fabric/scripts/fabric_provider.py`: writes, validates and
|
|
25
|
+
removes `fabric-provider/0.1` entries for agents that are not services — argv only,
|
|
26
|
+
env values as `secret-ref:` references, never the id of an existing service.
|
|
27
|
+
- `adapt_project.py scaffold --job` writes the capability's interop block; an `mcp`
|
|
28
|
+
capability now requires the tool of its own name instead of `tool:replace-me`, and
|
|
29
|
+
`check` refuses a malformed interop block.
|
|
30
|
+
- Skills teach it: `building-fabric-services` gains `references/interop.md`,
|
|
31
|
+
`adapting-projects-to-fabric` gains `references/provider-entry.md` and step 4b, and
|
|
32
|
+
`creating-fabric-agents` starts new agents on it. Trigger and scenario evals added
|
|
33
|
+
first.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- **Contract pin** moves from `a5a2709` to `a22dea3` (fabric-agent-contract `main`,
|
|
38
|
+
AR-1: interop, provider entries, runner catalogue, pipelines). The provider profiles
|
|
39
|
+
and every existing schema field are unchanged; the contract added schemas and
|
|
40
|
+
optional fields only (DEC-0016). **One pin**: `fabric-contract.lock.json`, and
|
|
41
|
+
`test/validate.py` fails any live file that names another contract revision (G-11).
|
|
42
|
+
- The README has a newcomer path that starts the sample service and probes it.
|
|
43
|
+
|
|
44
|
+
## 0.4.3 - 2026-09-29
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- **License.** The adapter is now source-available under
|
|
49
|
+
`PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0`, with a
|
|
50
|
+
commercial license on request (contact@passioncode.ai). Versions up to and including
|
|
51
|
+
v0.4.2, on GitHub and on npm, were released under MIT and remain available under it. The manifests, the three skills' `license:` and the README say the
|
|
52
|
+
same; contributions come in under `CLA.md`, which the new PR template asks for.
|
|
53
|
+
`test/validate.py` fails a tree that slips back to MIT.
|
|
54
|
+
- Author and marketplace owner are PassionCode.ai (`https://passioncode.ai/`).
|
|
55
|
+
- **Contract pin** moves from `20a818e` to `a5a2709` (fabric-agent-contract `main`), the
|
|
56
|
+
commit `building-fabric-services` already pinned. Between the two the provider
|
|
57
|
+
profiles are unchanged — only the `fabric-service/0.1` extension was added — and
|
|
58
|
+
`adapt_project.py check --contract` gives the same verdicts for an MCP, an A2A and a
|
|
59
|
+
local-runner bundle at both commits (declaration shape PASS). One pin for all three
|
|
60
|
+
skills.
|
|
61
|
+
- `creating-fabric-agents` hands the agent's own loop to `agent-orchestrator`, its
|
|
62
|
+
eval suite to `agent-evals` (agent-stack) and plugin packaging to `make-skill`;
|
|
63
|
+
`adapting-projects-to-fabric` sends wire-level MCP/A2A questions to `agent-interop`.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- The installer's help names the launcher by its npm org name,
|
|
68
|
+
`npx @passioncode-ai/passioncode@latest update`; the bare `passioncode` is not ours.
|
|
69
|
+
- A distributed eval named a personal agent as its example service; the
|
|
70
|
+
`building-fabric-services` evals use `example-agent`, and its description says "a
|
|
71
|
+
macOS machine" instead of naming whose.
|
|
72
|
+
|
|
3
73
|
## 0.4.2 - 2026-09-29
|
|
4
74
|
|
|
5
75
|
- Kit: `LoopbackHTTPServer`, a `ThreadingHTTPServer` whose bind asks no resolver.
|
package/LICENSE
CHANGED
|
@@ -1,22 +1,155 @@
|
|
|
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
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
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 of its npm package, were
|
|
19
|
+
released under the MIT License; those releases remain available under MIT.
|
|
22
20
|
|
|
21
|
+
Required Notice: Copyright (c) 2026 Siarhei Sheleh (https://passioncode.ai)
|
|
22
|
+
|
|
23
|
+
================================================================================
|
|
24
|
+
|
|
25
|
+
# PolyForm Noncommercial License 1.0.0
|
|
26
|
+
|
|
27
|
+
<https://polyformproject.org/licenses/noncommercial/1.0.0>
|
|
28
|
+
|
|
29
|
+
## Acceptance
|
|
30
|
+
|
|
31
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
32
|
+
|
|
33
|
+
## Copyright License
|
|
34
|
+
|
|
35
|
+
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).
|
|
36
|
+
|
|
37
|
+
## Distribution License
|
|
38
|
+
|
|
39
|
+
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).
|
|
40
|
+
|
|
41
|
+
## Notices
|
|
42
|
+
|
|
43
|
+
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:
|
|
44
|
+
|
|
45
|
+
> Required Notice: Copyright Yoyodyne, Inc. (http://example.com)
|
|
46
|
+
|
|
47
|
+
## Changes and New Works License
|
|
48
|
+
|
|
49
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
50
|
+
|
|
51
|
+
## Patent License
|
|
52
|
+
|
|
53
|
+
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.
|
|
54
|
+
|
|
55
|
+
## Noncommercial Purposes
|
|
56
|
+
|
|
57
|
+
Any noncommercial purpose is a permitted purpose.
|
|
58
|
+
|
|
59
|
+
## Personal Uses
|
|
60
|
+
|
|
61
|
+
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.
|
|
62
|
+
|
|
63
|
+
## Noncommercial Organizations
|
|
64
|
+
|
|
65
|
+
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.
|
|
66
|
+
|
|
67
|
+
## Fair Use
|
|
68
|
+
|
|
69
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
70
|
+
|
|
71
|
+
## No Other Rights
|
|
72
|
+
|
|
73
|
+
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.
|
|
74
|
+
|
|
75
|
+
## Patent Defense
|
|
76
|
+
|
|
77
|
+
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.
|
|
78
|
+
|
|
79
|
+
## Violations
|
|
80
|
+
|
|
81
|
+
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.
|
|
82
|
+
|
|
83
|
+
## No Liability
|
|
84
|
+
|
|
85
|
+
***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.***
|
|
86
|
+
|
|
87
|
+
## Definitions
|
|
88
|
+
|
|
89
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
90
|
+
|
|
91
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
92
|
+
|
|
93
|
+
**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.
|
|
94
|
+
|
|
95
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
96
|
+
|
|
97
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
|
98
|
+
|
|
99
|
+
================================================================================
|
|
100
|
+
|
|
101
|
+
# PolyForm Internal Use License 1.0.0
|
|
102
|
+
|
|
103
|
+
<https://polyformproject.org/licenses/internal-use/1.0.0>
|
|
104
|
+
|
|
105
|
+
## Acceptance
|
|
106
|
+
|
|
107
|
+
In order to get any license under these terms, you must agree to them as both strict obligations and conditions to all your licenses.
|
|
108
|
+
|
|
109
|
+
## Copyright License
|
|
110
|
+
|
|
111
|
+
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.
|
|
112
|
+
|
|
113
|
+
## Changes and New Works License
|
|
114
|
+
|
|
115
|
+
The licensor grants you an additional copyright license to make changes and new works based on the software for any permitted purpose.
|
|
116
|
+
|
|
117
|
+
## Patent License
|
|
118
|
+
|
|
119
|
+
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.
|
|
120
|
+
|
|
121
|
+
## Fair Use
|
|
122
|
+
|
|
123
|
+
You may have "fair use" rights for the software under the law. These terms do not limit them.
|
|
124
|
+
|
|
125
|
+
## Internal Business Use
|
|
126
|
+
|
|
127
|
+
Use of the software for the internal business operations of you and your company is use for a permitted purpose.
|
|
128
|
+
|
|
129
|
+
## No Other Rights
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
## Patent Defense
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
## Violations
|
|
138
|
+
|
|
139
|
+
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.
|
|
140
|
+
|
|
141
|
+
## No Liability
|
|
142
|
+
|
|
143
|
+
***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.***
|
|
144
|
+
|
|
145
|
+
## Definitions
|
|
146
|
+
|
|
147
|
+
The **licensor** is the individual or entity offering these terms, and the **software** is the software the licensor makes available under these terms.
|
|
148
|
+
|
|
149
|
+
**You** refers to the individual or entity agreeing to these terms.
|
|
150
|
+
|
|
151
|
+
**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.
|
|
152
|
+
|
|
153
|
+
**Your licenses** are all the licenses granted to you for the software under these terms.
|
|
154
|
+
|
|
155
|
+
**Use** means anything you do with the software requiring one of your licenses.
|
package/README.md
CHANGED
|
@@ -15,9 +15,9 @@ without moving the Project onto one proprietary agent runtime.
|
|
|
15
15
|
|
|
16
16
|
[](https://www.npmjs.com/package/@passioncode-ai/fabric-agent-adapter)
|
|
17
17
|
[](https://github.com/passioncode-ai/fabric-agent-adapter/actions/workflows/validate.yml)
|
|
18
|
-
[](LICENSE)
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Portable Agent Skills that make any agent Fabric-compatible, for the
|
|
21
21
|
[Fabric Agent Contract](https://github.com/passioncode-ai/fabric-agent-contract):
|
|
22
22
|
`adapting-projects-to-fabric`, `creating-fabric-agents` and
|
|
23
23
|
`building-fabric-services`.
|
|
@@ -32,6 +32,14 @@ complete `scripts/sample_service.py`, and `scripts/check_service.py`, a live pro
|
|
|
32
32
|
python3 plugins/fabric-agent-adapter/skills/building-fabric-services/scripts/check_service.py example-agent
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
Services and agents that other agents call follow `fabric-interop/0.1`: each capability
|
|
36
|
+
is the MCP tool of its name, long work is a job with a stable id (`fabric.job.get`,
|
|
37
|
+
`fabric.job.cancel`), a question for a person is an elicitation, and every call carries
|
|
38
|
+
one W3C trace. The kits ship the helpers (`scripts/fabric_interop.py`,
|
|
39
|
+
`scripts/fabric-interop.mjs`), the sample service serves a job end to end, and the probe
|
|
40
|
+
checks the interop rules. An agent that is not a service is announced with a provider
|
|
41
|
+
entry: `adapting-projects-to-fabric/scripts/fabric_provider.py`.
|
|
42
|
+
|
|
35
43
|
For provider bundles the adapting skill helps an agent author:
|
|
36
44
|
|
|
37
45
|
- inspect the project's stable integration surfaces without executing it;
|
|
@@ -46,7 +54,7 @@ yet ship the host registry/runtime needed to connect and authorize a live provid
|
|
|
46
54
|
|
|
47
55
|
## Install
|
|
48
56
|
|
|
49
|
-
The repository
|
|
57
|
+
The repository and the npm package are public; neither path needs an account.
|
|
50
58
|
|
|
51
59
|
npm — no GitHub access required:
|
|
52
60
|
|
|
@@ -110,6 +118,23 @@ python3 "$SKILL_DIR/scripts/adapt_project.py" check /path/to/project \
|
|
|
110
118
|
Scaffolding is non-destructive by default. It writes only the paths declared in the
|
|
111
119
|
[delivery brief](docs/evidence/specs/2026-08-27-brief.md) and refuses collisions.
|
|
112
120
|
|
|
121
|
+
## Verify one service (newcomer path)
|
|
122
|
+
|
|
123
|
+
After installing (above), with Python 3.9+ and no other dependency:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
KIT=plugins/fabric-agent-adapter/skills/building-fabric-services/scripts # or ~/.agents/skills/building-fabric-services/scripts
|
|
127
|
+
DATA=$(mktemp -d); SERVICES=$(mktemp -d)
|
|
128
|
+
python3 "$KIT/sample_service.py" serve --port 47190 --data-dir "$DATA" &
|
|
129
|
+
python3 "$KIT/sample_service.py" register --port 47190 --data-dir "$DATA" --services-dir "$SERVICES"
|
|
130
|
+
python3 "$KIT/check_service.py" sample --services-dir "$SERVICES" # exit 0: no FAIL
|
|
131
|
+
kill %1
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The probe prints one line per rule — `PASS`, `FAIL` or `NOT_RUN` with its evidence — and
|
|
135
|
+
exits 1 on any `FAIL`. Run it against your own service by its id once its installer has
|
|
136
|
+
written the descriptor.
|
|
137
|
+
|
|
113
138
|
## Validate this repository
|
|
114
139
|
|
|
115
140
|
```bash
|
|
@@ -125,8 +150,21 @@ checks copies installed elsewhere, such as `~/.agents/skills/*/SKILL.md`.
|
|
|
125
150
|
|
|
126
151
|
## Contract pin
|
|
127
152
|
|
|
153
|
+
The one pin is [`fabric-contract.lock.json`](fabric-contract.lock.json):
|
|
154
|
+
|
|
128
155
|
- version: `0.1.0`
|
|
129
|
-
- commit: `
|
|
156
|
+
- commit: `a22dea359ba04b8fe549abe81a5131552cb90eff`
|
|
157
|
+
|
|
158
|
+
Every other mention of the contract revision — this section, the skills' metadata, the
|
|
159
|
+
skill card, `adapt_project.py` — must equal it; `python3 test/validate.py` fails a tree
|
|
160
|
+
where one does not. The contract repository is normative. Updating the pin requires a
|
|
161
|
+
new adapter release, fixture review, and a complete validation run.
|
|
162
|
+
|
|
163
|
+
## License
|
|
130
164
|
|
|
131
|
-
|
|
132
|
-
|
|
165
|
+
Source-available under PolyForm Noncommercial or Internal Use; commercial license on
|
|
166
|
+
request (contact@passioncode.ai). SPDX:
|
|
167
|
+
`PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0` — see
|
|
168
|
+
[LICENSE](LICENSE). Versions up to and including v0.4.2 (on GitHub and on npm) were
|
|
169
|
+
released under the MIT License and remain available under it. Contributions are accepted under
|
|
170
|
+
[CLA.md](CLA.md) ([CONTRIBUTING.md](CONTRIBUTING.md)).
|
package/SECURITY.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
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
|
|
@@ -35,7 +35,7 @@ Claude Code (recommended):
|
|
|
35
35
|
claude plugin marketplace add ${REPO}
|
|
36
36
|
claude plugin install ${PLUGIN_ID}
|
|
37
37
|
Every PassionCode.ai skill for every agent at once:
|
|
38
|
-
npx passioncode@latest update`);
|
|
38
|
+
npx @passioncode-ai/passioncode@latest update`);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
function copyDir(src, dest) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@passioncode-ai/fabric-agent-adapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
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 && node --test test
|
|
6
|
+
"test": "python3 test/validate.py && python3 -m unittest discover -s test -q && node --test 'test/*.test.mjs'"
|
|
7
7
|
},
|
|
8
8
|
"bin": {
|
|
9
9
|
"fabric-agent-adapter": "bin/fabric-agent-adapter.js"
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
],
|
|
24
24
|
"repository": "github:passioncode-ai/fabric-agent-adapter",
|
|
25
25
|
"homepage": "https://github.com/passioncode-ai/fabric-agent-adapter",
|
|
26
|
-
"license": "
|
|
26
|
+
"license": "PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0",
|
|
27
27
|
"author": {
|
|
28
|
-
"name": "
|
|
29
|
-
"url": "https://
|
|
28
|
+
"name": "PassionCode.ai",
|
|
29
|
+
"url": "https://passioncode.ai/"
|
|
30
30
|
},
|
|
31
31
|
"engines": {
|
|
32
32
|
"node": ">=16"
|
|
@@ -3,14 +3,14 @@
|
|
|
3
3
|
"name": "fabric-agent-adapter",
|
|
4
4
|
"displayName": "Fabric Agent Adapter",
|
|
5
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.
|
|
6
|
+
"version": "0.5.0",
|
|
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",
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: adapting-projects-to-fabric
|
|
3
3
|
description: Use when adapting an existing agent, MCP server, A2A peer, HTTP service, or terminal CLI to the Fabric Agent Contract—choosing MCP/A2A/local-runner, scaffolding a provider bundle, or checking Fabric compatibility; also for «подключить проект к Fabric» or «сделать агента совместимым с Fabric». NOT for building the Fabric host/orchestrator, configuring an MCP client, or a brand-new agent — that is creating-fabric-agents.
|
|
4
|
-
license:
|
|
4
|
+
license: PolyForm-Noncommercial-1.0.0 OR LicenseRef-PolyForm-Internal-Use-1.0.0
|
|
5
5
|
compatibility: Requires filesystem access and Python 3.9+. Exact schema checks additionally need git, Node.js, pnpm, and the pinned private fabric-agent-contract checkout. Works without those tools in an explicitly degraded structural-check mode.
|
|
6
6
|
metadata:
|
|
7
|
-
author:
|
|
8
|
-
version: "0.
|
|
7
|
+
author: PassionCode.ai
|
|
8
|
+
version: "0.5.0"
|
|
9
9
|
contract-version: "0.1.0"
|
|
10
|
-
contract-commit: "
|
|
10
|
+
contract-commit: "a22dea359ba04b8fe549abe81a5131552cb90eff"
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
# Adapting projects to Fabric
|
|
@@ -22,6 +22,9 @@ Use this skill to adapt or assess a provider project. Do not use it to:
|
|
|
22
22
|
|
|
23
23
|
- design the Fabric host, registry, scheduler, admission service, or project binding runtime;
|
|
24
24
|
- add an MCP server to Claude Code, Codex, or an agent gateway;
|
|
25
|
+
- answer wire-level MCP or A2A questions (transports, sessions, auth handshakes, task
|
|
26
|
+
states on the wire) — that is `agent-interop` (agent-stack); the pinned contract stays
|
|
27
|
+
normative for what Fabric requires;
|
|
25
28
|
- design a new agent from scratch — that is the sibling skill creating-fabric-agents;
|
|
26
29
|
- claim admission merely because generated files or a valid manifest exist.
|
|
27
30
|
|
|
@@ -67,7 +70,7 @@ Use exactly:
|
|
|
67
70
|
|
|
68
71
|
- contract version `0.1.0`;
|
|
69
72
|
- repository `https://github.com/passioncode-ai/fabric-agent-contract`;
|
|
70
|
-
- commit `
|
|
73
|
+
- commit `a22dea359ba04b8fe549abe81a5131552cb90eff`.
|
|
71
74
|
|
|
72
75
|
Read the pinned contract's guide
|
|
73
76
|
`docs/guides/connecting-compatible-agents.md`, the selected profile specification, and
|
|
@@ -90,7 +93,10 @@ python3 <skill-dir>/scripts/adapt_project.py scaffold <project-root> \
|
|
|
90
93
|
--schema-base https://agents.example/fabric
|
|
91
94
|
```
|
|
92
95
|
|
|
93
|
-
Valid profiles are `mcp`, `a2a`, and `local-runner`.
|
|
96
|
+
Valid profiles are `mcp`, `a2a`, and `local-runner`. For `mcp` the capability is served
|
|
97
|
+
as the MCP tool of its own name (`requiredFeatures: ["tool:<capability>"]`, contract
|
|
98
|
+
`fabric-interop/0.1`); add `--job` when its work may outlive one request, which writes
|
|
99
|
+
`"job": true` in the capability's interop block. The helper creates only the locked
|
|
94
100
|
target paths. It refuses any collision. Do not use `--force` unless the user explicitly
|
|
95
101
|
authorizes replacement after the exact conflicting files and diff are shown.
|
|
96
102
|
|
|
@@ -105,6 +111,11 @@ Preserve the chosen ownership boundary:
|
|
|
105
111
|
- A2A maps the provider's remote task, progress, artifact, cancellation, and terminal
|
|
106
112
|
states; Fabric does not take over its internal loop.
|
|
107
113
|
- MCP exposes bounded tools/resources/prompts while Fabric owns planning and retries.
|
|
114
|
+
The served tool's name, input and output schemas equal the manifest's (FAC-SEM-017);
|
|
115
|
+
long work returns a job handle and serves `fabric.job.get` / `fabric.job.cancel`; a
|
|
116
|
+
question for a person is a form-mode choice, a secret goes through URL mode; every call
|
|
117
|
+
runs as a child span of `_meta.traceparent`. The kit for all of it is
|
|
118
|
+
`building-fabric-services`'s `scripts/fabric_interop.py`.
|
|
108
119
|
- Local runner maps typed input, executable identity, result location, cancellation,
|
|
109
120
|
heartbeat, and partial results without relying on ambient accounts.
|
|
110
121
|
|
|
@@ -112,6 +123,14 @@ Keep model selection and provider-internal reasoning outside the Fabric contract
|
|
|
112
123
|
typed outcomes, evidence, artifacts, and protocol-visible state—not chain-of-thought.
|
|
113
124
|
Treat all provider output as untrusted until schemas and semantic assertions pass.
|
|
114
125
|
|
|
126
|
+
### 4b. Announce an agent that is not a service
|
|
127
|
+
|
|
128
|
+
An agent Fabric reaches as a CLI or a stdio MCP server gets a provider entry, written by
|
|
129
|
+
its installer with [`scripts/fabric_provider.py`](scripts/fabric_provider.py) and removed
|
|
130
|
+
by its uninstaller — argv arrays only, env values as `secret-ref:` references, never the
|
|
131
|
+
id of an existing service. Load [provider entries](references/provider-entry.md). An
|
|
132
|
+
agent that runs as a service uses a descriptor instead (`building-fabric-services`).
|
|
133
|
+
|
|
115
134
|
### 5. Make probes safe and meaningful
|
|
116
135
|
|
|
117
136
|
For each capability, create at least one bounded fixture that:
|
package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/references/provider-entry.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Provider entries: agents that are not services
|
|
2
|
+
|
|
3
|
+
Normative source: the Fabric Agent Contract's `docs/specification/provider.md`
|
|
4
|
+
(`fabric-provider/0.1`, DEC-0016) at the commit this plugin pins.
|
|
5
|
+
|
|
6
|
+
An agent Fabric reaches as a CLI or a stdio MCP server — not a long-running service —
|
|
7
|
+
is announced by one entry, `providers/<id>.json`, in the same root as the services
|
|
8
|
+
directory:
|
|
9
|
+
|
|
10
|
+
| Platform | Directory |
|
|
11
|
+
|---|---|
|
|
12
|
+
| macOS | `~/Library/Application Support/ai.passioncode.fabric/providers/` |
|
|
13
|
+
| Linux | `${XDG_DATA_HOME:-~/.local/share}/passioncode-fabric/providers/` |
|
|
14
|
+
| any | `FABRIC_PROVIDERS_DIR` when set |
|
|
15
|
+
|
|
16
|
+
A service uses a descriptor instead (the `building-fabric-services` skill). One id is a
|
|
17
|
+
service or a provider, never both.
|
|
18
|
+
|
|
19
|
+
## The writer
|
|
20
|
+
|
|
21
|
+
`scripts/fabric_provider.py` is the installer's tool; it writes atomically, mode 0600,
|
|
22
|
+
and refuses what the contract refuses.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python3 scripts/fabric_provider.py write --id example-agent --name "Example Agent" \
|
|
26
|
+
--manifest ~/.local/share/example-agent/fabric-agent.json --installed-by "example-agent 1.0.0" \
|
|
27
|
+
--env EXAMPLE_API_KEY=secret-ref:example-agent/EXAMPLE_API_KEY \
|
|
28
|
+
--stdio ~/.local/bin/example-agent mcp
|
|
29
|
+
python3 scripts/fabric_provider.py write ... --url http://127.0.0.1:47201/mcp
|
|
30
|
+
python3 scripts/fabric_provider.py validate ~/Library/Application\ Support/ai.passioncode.fabric/providers/example-agent.json
|
|
31
|
+
python3 scripts/fabric_provider.py remove example-agent # the uninstaller
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`--stdio` takes the rest of the line as the argument array; there is no shell string.
|
|
35
|
+
|
|
36
|
+
It refuses, with one sentence that never quotes a value:
|
|
37
|
+
|
|
38
|
+
- an id that is already a service in `services/` (FAC-SEM-013);
|
|
39
|
+
- an env value that is not `secret-ref:<name>`, or a reference that has the shape of a
|
|
40
|
+
credential itself — a token prefix, a private key, a JWT (FAC-SEM-015);
|
|
41
|
+
- a URL other than `http://127.0.0.1:<port>/mcp`, a manifest path that is not an
|
|
42
|
+
absolute or `~/` path to `fabric-agent.json`, a shell-string command, unknown fields.
|
|
43
|
+
|
|
44
|
+
From Python: `write_provider_entry(entry)`, `remove_provider_entry(id)`,
|
|
45
|
+
`validate_provider_entry(entry)`, `providers_dir()`.
|
|
46
|
+
|
|
47
|
+
## What the entry does not do
|
|
48
|
+
|
|
49
|
+
It grants nothing: Fabric lists the agent, and admission (probes) and a project binding
|
|
50
|
+
still decide what it may do. The manifest it points at is the authority for the
|
|
51
|
+
agent's capabilities. The contract's rule that the manifest's `provider.id` "equals" the
|
|
52
|
+
entry's id cannot hold as written — `provider.id` is a URI, the entry id a slug — so only
|
|
53
|
+
"the manifest resolves" is checked until the contract answers OQ-0001.
|
package/plugins/fabric-agent-adapter/skills/adapting-projects-to-fabric/scripts/adapt_project.py
CHANGED
|
@@ -16,7 +16,8 @@ from urllib.parse import urlparse
|
|
|
16
16
|
|
|
17
17
|
CONTRACT_VERSION = "0.1.0"
|
|
18
18
|
CONTRACT_REPOSITORY = "https://github.com/passioncode-ai/fabric-agent-contract"
|
|
19
|
-
CONTRACT_COMMIT = "
|
|
19
|
+
CONTRACT_COMMIT = "a22dea359ba04b8fe549abe81a5131552cb90eff"
|
|
20
|
+
INTEROP_KEY = "https://fabric.passioncode.ai/agent-contract/extensions/interop/0.1"
|
|
20
21
|
MCP_REVISION = "2026-07-28"
|
|
21
22
|
A2A_VERSION = "1.0"
|
|
22
23
|
LOCAL_VERSION = "fabric-local-runner/0.1"
|
|
@@ -167,7 +168,8 @@ def _profile(args: argparse.Namespace, schema_base: str) -> Dict[str, Any]:
|
|
|
167
168
|
"kind": "mcp",
|
|
168
169
|
"protocolRevision": MCP_REVISION,
|
|
169
170
|
"connection": connection,
|
|
170
|
-
|
|
171
|
+
# fabric-interop/0.1 C3.1: the capability is served as the MCP tool of its own name.
|
|
172
|
+
"requiredFeatures": ["tool:%s" % args.capability_name],
|
|
171
173
|
"probes": [probe],
|
|
172
174
|
}
|
|
173
175
|
if profile == "a2a":
|
|
@@ -215,6 +217,8 @@ def _generated_files(args: argparse.Namespace) -> Dict[str, str]:
|
|
|
215
217
|
_require_absolute_uri(args.agent_card_url, "Agent Card URL")
|
|
216
218
|
if urlparse(args.agent_card_url).scheme != "https":
|
|
217
219
|
raise AdaptationError("Agent Card URL must use HTTPS")
|
|
220
|
+
if getattr(args, "job", False) and args.profile != "mcp":
|
|
221
|
+
raise AdaptationError("--job marks an MCP capability as a job (fabric-interop/0.1); %s has no job handle" % args.profile)
|
|
218
222
|
for runtime_arg in args.runtime_arg:
|
|
219
223
|
lowered = runtime_arg.lower().replace("_", "").replace("-", "")
|
|
220
224
|
if any(term in lowered for term in ("password", "apikey", "accesstoken", "clientsecret")):
|
|
@@ -249,6 +253,8 @@ def _generated_files(args: argparse.Namespace) -> Dict[str, str]:
|
|
|
249
253
|
}
|
|
250
254
|
],
|
|
251
255
|
}
|
|
256
|
+
if getattr(args, "job", False):
|
|
257
|
+
manifest["capabilities"][0]["extensions"] = {INTEROP_KEY: {"job": True}}
|
|
252
258
|
lock = {
|
|
253
259
|
"contract": "fabric-agent-contract",
|
|
254
260
|
"version": CONTRACT_VERSION,
|
|
@@ -431,6 +437,12 @@ def check_project(root: Path, contract: Optional[Path]) -> Dict[str, Any]:
|
|
|
431
437
|
errors.append("capability[%d] must pin %s=%s" % (index, expected[0], expected[1]))
|
|
432
438
|
if not profile.get("probes"):
|
|
433
439
|
errors.append("capability[%d] must declare probes" % index)
|
|
440
|
+
block = (capability.get("extensions") or {}).get(INTEROP_KEY)
|
|
441
|
+
if block is not None:
|
|
442
|
+
if not isinstance(block, dict) or set(block) - {"job"} or not isinstance(block.get("job", False), bool):
|
|
443
|
+
errors.append("capability[%d] interop block must be {\"job\": true|false}" % index)
|
|
444
|
+
elif kind != "mcp":
|
|
445
|
+
errors.append("capability[%d] interop block is for an mcp capability, not %s" % (index, kind))
|
|
434
446
|
for field in ("inputSchema", "outputSchema"):
|
|
435
447
|
value = capability.get(field)
|
|
436
448
|
try:
|
|
@@ -503,6 +515,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
503
515
|
scaffold.add_argument("--runner-kind", default="replace-me")
|
|
504
516
|
scaffold.add_argument("--executable-ref", default="urn:executable:replace-me")
|
|
505
517
|
scaffold.add_argument("--runtime-arg", action="append", default=[])
|
|
518
|
+
scaffold.add_argument("--job", action="store_true", help="the capability's work may outlive one request (fabric-interop/0.1 job)")
|
|
506
519
|
scaffold.add_argument("--force", action="store_true")
|
|
507
520
|
scaffold.add_argument("--json", action="store_true")
|
|
508
521
|
|