@aihu-plugin/agent-readiness 2.0.2 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ npm install @aihu-plugin/agent-readiness
|
|
|
21
21
|
bun add @aihu-plugin/agent-readiness
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
24
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
25
25
|
|
|
26
26
|
<!-- END_AUTOGEN: install -->
|
|
27
27
|
|
|
@@ -32,12 +32,12 @@ bun add @aihu-plugin/agent-readiness
|
|
|
32
32
|
|
|
33
33
|
| | |
|
|
34
34
|
|---|---|
|
|
35
|
-
| **Version** | `2.0.
|
|
35
|
+
| **Version** | `2.0.4` |
|
|
36
36
|
| **Tier** | C — Agent surface — discovery manifests (llms.txt, MCP Server Card, robots) |
|
|
37
37
|
| **Published files** | 3 entries |
|
|
38
38
|
| **License** | MIT |
|
|
39
39
|
|
|
40
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
40
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
41
41
|
|
|
42
42
|
<!-- END_AUTOGEN: stats -->
|
|
43
43
|
|
|
@@ -50,7 +50,7 @@ bun add @aihu-plugin/agent-readiness
|
|
|
50
50
|
|---|---|---|
|
|
51
51
|
| `.` | `./dist/index.js` | `—` |
|
|
52
52
|
|
|
53
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
53
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
54
54
|
|
|
55
55
|
<!-- END_AUTOGEN: exports -->
|
|
56
56
|
|
|
@@ -64,7 +64,7 @@ bun add @aihu-plugin/agent-readiness
|
|
|
64
64
|
- `@aihu/server` — `workspace:*`
|
|
65
65
|
- `@aihu/agent` — `workspace:*`
|
|
66
66
|
|
|
67
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
67
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
68
68
|
|
|
69
69
|
<!-- END_AUTOGEN: deps -->
|
|
70
70
|
|
|
@@ -77,7 +77,7 @@ bun add @aihu-plugin/agent-readiness
|
|
|
77
77
|
- [@aihu/server](../server)
|
|
78
78
|
- [Aihu framework root](../../README.md)
|
|
79
79
|
|
|
80
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
80
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
81
81
|
|
|
82
82
|
<!-- END_AUTOGEN: see-also -->
|
|
83
83
|
|
|
@@ -88,6 +88,6 @@ bun add @aihu-plugin/agent-readiness
|
|
|
88
88
|
|
|
89
89
|
MIT — see [LICENSE](../../LICENSE).
|
|
90
90
|
|
|
91
|
-
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.
|
|
91
|
+
<sub><i>Auto-generated against `@aihu-plugin/agent-readiness@2.0.4`.</i></sub>
|
|
92
92
|
|
|
93
93
|
<!-- END_AUTOGEN: license -->
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,26 @@ interface LlmsTxtConfig {
|
|
|
98
98
|
readonly summary?: string;
|
|
99
99
|
readonly sections: ReadonlyArray<LlmsTxtSection>;
|
|
100
100
|
readonly optional?: ReadonlyArray<LlmsTxtLink>;
|
|
101
|
+
/**
|
|
102
|
+
* Component metadata, rendered as a `## Components` section listing each
|
|
103
|
+
* component's tag, description, callable actions, and readable state.
|
|
104
|
+
* When empty (zero components) the section is omitted entirely.
|
|
105
|
+
*/
|
|
106
|
+
readonly components?: ReadonlyArray<ComponentMetaLike>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Minimal shape used for the `## Components` section. Structurally compatible
|
|
110
|
+
* with @aihu/agent `AgentMetadata` (tag/describes/state/actions).
|
|
111
|
+
*/
|
|
112
|
+
interface ComponentMetaLike {
|
|
113
|
+
readonly tag: string;
|
|
114
|
+
readonly describes?: string;
|
|
115
|
+
readonly state?: Record<string, string>;
|
|
116
|
+
readonly actions?: Record<string, {
|
|
117
|
+
readonly returns?: Record<string, {
|
|
118
|
+
type: string;
|
|
119
|
+
}>;
|
|
120
|
+
}>;
|
|
101
121
|
}
|
|
102
122
|
declare function generateLlmsTxt(config: LlmsTxtConfig): string;
|
|
103
123
|
declare function generateLlmsFullTxt(config: LlmsTxtConfig): string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/a2a-card.ts","../src/content-negotiation.ts","../src/llms-txt.ts","../src/mcp-discovery.ts","../src/robots.ts","../src/sitemap.ts","../src/types.ts","../src/mcp-server-card.ts","../src/vite-plugin.ts"],"mappings":";;;;;;AAMA;;UAAiB,eAAA;EAAA,SACN,SAAA;EAAA,SACA,iBAAA;AAAA;AAAA,UAGM,QAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,OAAA;EAAA,SACN,IAAA;EAAA,SACA,WAAA;EAAA,SACA,GAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA;IAAA,SACE,SAAA;IAAA,SACA,iBAAA;EAAA;EAAA,SAEF,MAAA,GAAS,aAAA,CAAc,QAAA;AAAA;AAAA,UAGjB,aAAA;EAAA,SACN,IAAA;EAAA,SACA,WAAA;EAAA,SACA,GAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA,GAAe,eAAA;EAAA,SACf,MAAA,GAAS,aAAA,CAAc,QAAA;AAAA;AANlC;;;;AAAA,iBAagB,eAAA,CAAgB,MAAA,EAAQ,aAAA,GAAgB,OAAA;;;;;AApCxD;;;;;AAKA;;;UCCiB,gBAAA;EDAN;;;;ECKT,OAAA,CAAQ,IAAA,WAAe,OAAA;AAAA;AAAA,UAGR,yBAAA;EAAA,SACN,QAAA,EAAU,gBAAA;EDKY;;;;EAAA,SCAtB,cAAA,IAAkB,OAAA;AAAA;;;;;;;;ADG7B;;;;;;;;iBCegB,+BAAA,CAAgC,IAAA,EAAM,yBAAA,GAA4B,UAAA;;;UC5CjE,WAAA;EAAA,SACN,KAAA;EAAA,SACA,GAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,KAAA;EAAA,SACA,KAAA,EAAO,aAAA,CAAc,WAAA;AAAA;AAAA,UAGf,aAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA,EAAU,aAAA,CAAc,cAAA;EAAA,SACxB,QAAA,GAAW,aAAA,CAAc,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/a2a-card.ts","../src/content-negotiation.ts","../src/llms-txt.ts","../src/mcp-discovery.ts","../src/robots.ts","../src/sitemap.ts","../src/types.ts","../src/mcp-server-card.ts","../src/vite-plugin.ts"],"mappings":";;;;;;AAMA;;UAAiB,eAAA;EAAA,SACN,SAAA;EAAA,SACA,iBAAA;AAAA;AAAA,UAGM,QAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,OAAA;EAAA,SACN,IAAA;EAAA,SACA,WAAA;EAAA,SACA,GAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA;IAAA,SACE,SAAA;IAAA,SACA,iBAAA;EAAA;EAAA,SAEF,MAAA,GAAS,aAAA,CAAc,QAAA;AAAA;AAAA,UAGjB,aAAA;EAAA,SACN,IAAA;EAAA,SACA,WAAA;EAAA,SACA,GAAA;EAAA,SACA,OAAA;EAAA,SACA,YAAA,GAAe,eAAA;EAAA,SACf,MAAA,GAAS,aAAA,CAAc,QAAA;AAAA;AANlC;;;;AAAA,iBAagB,eAAA,CAAgB,MAAA,EAAQ,aAAA,GAAgB,OAAA;;;;;AApCxD;;;;;AAKA;;;UCCiB,gBAAA;EDAN;;;;ECKT,OAAA,CAAQ,IAAA,WAAe,OAAA;AAAA;AAAA,UAGR,yBAAA;EAAA,SACN,QAAA,EAAU,gBAAA;EDKY;;;;EAAA,SCAtB,cAAA,IAAkB,OAAA;AAAA;;;;;;;;ADG7B;;;;;;;;iBCegB,+BAAA,CAAgC,IAAA,EAAM,yBAAA,GAA4B,UAAA;;;UC5CjE,WAAA;EAAA,SACN,KAAA;EAAA,SACA,GAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,cAAA;EAAA,SACN,KAAA;EAAA,SACA,KAAA,EAAO,aAAA,CAAc,WAAA;AAAA;AAAA,UAGf,aAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA,EAAU,aAAA,CAAc,cAAA;EAAA,SACxB,QAAA,GAAW,aAAA,CAAc,WAAA;EFDzB;;;AAGX;;EAHW,SEOA,UAAA,GAAa,aAAA,CAAc,iBAAA;AAAA;;;;;UAa5B,iBAAA;EAAA,SACC,GAAA;EAAA,SACA,SAAA;EAAA,SACA,KAAA,GAAQ,MAAA;EAAA,SACR,OAAA,GAAU,MAAA;IAAA,SAA0B,OAAA,GAAU,MAAA;MAAiB,IAAA;IAAA;EAAA;AAAA;AAAA,iBA4D1D,eAAA,CAAgB,MAAA,EAAQ,aAAA;AAAA,iBAIxB,mBAAA,CAAoB,MAAA,EAAQ,aAAA;;;;;;AFhG5C;;UGAiB,kBAAA;EAAA,SACN,GAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;AAAA;AAAA,UAGM,YAAA;EAAA,SACN,UAAA,EAAY,MAAA,SAAe,kBAAA;AAAA;AAAA,UAGrB,kBAAA;EAAA,SACN,IAAA;EAAA,SACA,GAAA;EAAA,SACA,WAAA;AAAA;;;;;;;;iBAUK,oBAAA,CAAqB,MAAA,EAAQ,kBAAA,GAAqB,YAAA;;;cC7BrD,WAAA,EAAa,aAAA;AAAA,UAgBT,UAAA;EAAA,SACN,SAAA,WAAoB,aAAA;EAAA,SACpB,KAAA,GAAQ,aAAA;EAAA,SACR,QAAA,GAAW,aAAA;EAAA,SACX,UAAA;AAAA;AAAA,UAGM,YAAA;EAAA,SACN,QAAA,8BAAsC,aAAA,CAAc,UAAA;EAAA,SACpD,QAAA,GAAW,aAAA,CAAc,UAAA;EAAA,SACzB,OAAA;AAAA;AAAA,iBAgBK,iBAAA,CAAkB,MAAA,GAAQ,YAAA;;;;;;AJpC1C;KKDY,iBAAA;AAAA,UASK,UAAA;EAAA,SACN,GAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,GAAa,iBAAA;EAAA,SACb,QAAA;AAAA;AAAA,UAGM,aAAA;EAAA,SACN,KAAA,EAAO,aAAA,CAAc,UAAA;AAAA;;;;ALLhC;iBKqBgB,kBAAA,CAAmB,MAAA,EAAQ,aAAA;;;;;;AL3B3C;;UMCiB,aAAA;EAAA,SACN,IAAA;EAAA,SACA,gBAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,GAAS,aAAA;ENFE;;AAGtB;;EAHsB,SMOX,WAAA;AAAA;;;;;;UAQM,oBAAA;EAAA,SAEN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,OAAA;ENPuB;EAAA,SMWvB,QAAA;EAAA,SAGA,IAAA,GAAO,aAAA;EAAA,SAGP,YAAA,GAAe,aAAA,CAAc,cAAA;EAAA,SAC7B,YAAA,GAAe,aAAA,CAAc,WAAA;;WAI7B,QAAA,GAAW,YAAA;EAAA,SACX,YAAA,GAAe,aAAA,CAAc,UAAA;EAAA,SAC7B,OAAA;ENfsB;EAAA,SMmBtB,MAAA,GAAS,aAAA,CAAc,UAAA;ENxBvB;EAAA,SM4BA,OAAA;EN1BA;;;;;EAAA,SMkCA,OAAA;IAAA,SAEM,YAAA,GAAe,eAAA;IAAA,SAA0B,MAAA,GAAS,aAAA,CAAc,QAAA;EAAA;EN1BjE;;;;;EAAA,SMkCL,YAAA;ENlC6C;;;;;EAAA,SM0C7C,YAAA,GAAe,aAAA,CAAc,UAAA;ELxEvB;;;;;EAAA,SKgFN,MAAA,GAAS,aAAA,CAAc,MAAA;AAAA;;;UC9EjB,UAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA;EAAA,SACA,WAAA;EAAA,SACA,WAAA,GAAc,MAAA;AAAA;;;;UAMR,aAAA;EAAA,SACN,OAAA;EAAA,SACA,OAAA;EAAA,SACA,eAAA;EAAA,SACA,UAAA;IAAA,SACE,IAAA;IAAA,SACA,OAAA;IAAA,SACA,WAAA;IAAA,SACA,QAAA;EAAA;EAAA,SAEF,SAAA;IAAA,SACE,IAAA;IAAA,SACA,GAAA;EAAA;EAAA,SAEF,YAAA;IAAA,SACE,KAAA;IAAA,SACA,SAAA;IAAA,SACA,OAAA;EAAA;EAAA,SAEF,KAAA,GAAQ,aAAA;IAAA,SACN,IAAA;IAAA,SACA,WAAA;EAAA;EAAA,SAEF,IAAA;IAAA,SACE,IAAA;IAAA,SACA,mBAAA;IAAA,SACA,gBAAA;EAAA;AAAA;AAAA,UAII,mBAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;EAAA,SACA,QAAA;EAAA,SACA,MAAA,GAAS,aAAA,CAAc,UAAA;EAAA,SACvB,IAAA,GAAO,aAAA;EAAA,SACP,WAAA;EAAA,SACA,QAAA;EPnBoD;EAAA,SOqBpD,eAAA;;WAEA,aAAA;AAAA;ANrDX;;;;;;;;;AAAA,iBMiEgB,qBAAA,CAAsB,MAAA,EAAQ,mBAAA,GAAsB,aAAA;;;;APvEpE;;;;UQUU,UAAA;EAAA,SACC,IAAA;EACT,eAAA,IAAmB,MAAA;IACjB,WAAA;MACE,GAAA,GAAM,EAAA,GAAK,GAAA,OAAU,GAAA,OAAU,IAAA;IAAA;EAAA;EAGnC,cAAA,IAAkB,OAAA,OAAc,MAAA,UAAgB,OAAA;EAChD,kBAAA,IAAsB,IAAA;AAAA;ARPxB;;;;;;;;;;;;;;;;AAAA,iBQ0BgB,0BAAA,CAA2B,MAAA,EAAQ,oBAAA;EAAA,SACxC,OAAA,EAAS,YAAA;EAAA,SACT,WAAA,EAAa,YAAA;EAAA,SACb,aAAA,EAAe,YAAA;EAAA,SACf,SAAA,EAAW,YAAA;EAAA,SACX,OAAA,EAAS,YAAA;EAAA,SACT,YAAA,EAAc,YAAA;EAAA,SACd,UAAA,EAAY,YAAA;AAAA;;;;;;;;;;;ARRvB;;iBQwHgB,6BAAA,CAA8B,MAAA,EAAQ,oBAAA,GAAuB,UAAA;;cA4FhE,cAAA,SAAc,6BAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{json as
|
|
2
|
-
`).trimEnd()};function
|
|
3
|
-
`)};function
|
|
4
|
-
Allow: /`)}else if(n===`deny-all`){for(let e of
|
|
5
|
-
Allow: /`)}else for(let e of n)t.push(
|
|
1
|
+
import{getAllAgentMetadata as e}from"@aihu/agent";import{json as t,notFound as n}from"@aihu/server";function r(e){return{name:e.name,...e.description===void 0?{}:{description:e.description},url:e.url,...e.version===void 0?{}:{version:e.version},capabilities:{streaming:e.capabilities?.streaming??!1,pushNotifications:e.capabilities?.pushNotifications??!1},...e.skills!==void 0&&e.skills.length>0?{skills:e.skills}:{}}}function i(e){let t=e.estimateTokens??(e=>Math.ceil(e.length/4));return async(n,r)=>{if(!(n.headers.get(`Accept`)??``).includes(`text/markdown`))return r();let i=new URL(n.url).pathname,a=await e.resolver.resolve(i);if(a===null)return r();let o=t(a);return new Response(a,{status:200,headers:{"Content-Type":`text/markdown; charset=utf-8`,"x-markdown-tokens":String(o)}})}}const a=e=>e.description?`- [${e.title}](${e.url}): ${e.description}`:`- [${e.title}](${e.url})`,o=e=>{let t=e?Object.entries(e):[];return t.length===0?`{}`:`{ ${t.map(([e,t])=>`${e}: ${t.type}`).join(`, `)} }`},s=e=>{let t=[`### ${e.tag}`];e.describes&&t.push(e.describes);let n=e.actions?Object.entries(e.actions):[];if(n.length>0){t.push(`Actions:`);for(let[e,r]of n)t.push(`- \`${e}()\` → ${o(r?.returns)}`)}let r=e.state?Object.entries(e.state):[];if(r.length>0){t.push(`State:`);for(let[e,n]of r)t.push(`- \`${e}\`: ${n}`)}return t},c=(e,t)=>{let n=[`# ${e.name}`,``];e.summary&&n.push(`> ${e.summary}`,``);for(let t of e.sections)if(t.links.length!==0){n.push(`## ${t.title}`);for(let e of t.links)n.push(a(e));n.push(``)}if(e.components?.length){n.push(`## Components`,``);for(let t of e.components)n.push(...s(t),``)}if(e.optional?.length){n.push(`## ${t}`);for(let t of e.optional)n.push(a(t));n.push(``)}return n.join(`
|
|
2
|
+
`).trimEnd()};function l(e){return c(e,`Optional`)}function u(e){return c(e,`More`)}function d(e){return{mcpServers:{[e.name.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-|-$/g,``)]:{url:e.url,name:e.name,...e.description===void 0?{}:{description:e.description}}}}}function f(e){let t=e.skills?.map(e=>({name:e.name,description:e.description})),n;e.auth&&(n={type:`oauth2`,authorizationServer:`${new URL(e.auth.tokenUrl).origin}/.well-known/oauth-authorization-server`,resourceMetadata:`${e.endpoint}/.well-known/oauth-protected-resource`});let r={name:e.name,version:e.version,...e.description===void 0?{}:{description:e.description},...e.homepage===void 0?{}:{homepage:e.homepage}};return{$schema:`https://modelcontextprotocol.io/schemas/server-card/v1.0`,version:`1.0`,protocolVersion:e.protocolVersion??`2025-06-18`,serverInfo:r,transport:{type:e.transportType??`streamable-http`,url:e.endpoint},capabilities:{tools:!0,resources:!1,prompts:!1},...t===void 0?{}:{tools:t},...n===void 0?{}:{auth:n}}}const p=[`GPTBot`,`ClaudeBot`,`PerplexityBot`,`Googlebot-Extended`,`CCBot`,`anthropic-ai`,`Google-Extended`,`Bytespider`,`cohere-ai`,`OAI-SearchBot`,`ChatGPT-User`,`DuckAssistBot`,`Applebot`],m=e=>{let t=(Array.isArray(e.userAgent)?e.userAgent:[e.userAgent]).map(e=>`User-agent: ${e}`);if(e.disallow)for(let n of e.disallow)t.push(`Disallow: ${n}`);if(e.allow)for(let n of e.allow)t.push(`Allow: ${n}`);return e.crawlDelay!==void 0&&t.push(`Crawl-delay: ${e.crawlDelay}`),t.join(`
|
|
3
|
+
`)};function h(e={}){let t=[],{aiAgents:n=`allow-all`}=e;if(e.standard?.length)for(let n of e.standard)t.push(m(n));if(n===`allow-all`){for(let e of p)t.push(`User-agent: ${e}\nAllow: /`);t.push(`User-agent: *
|
|
4
|
+
Allow: /`)}else if(n===`deny-all`){for(let e of p)t.push(`User-agent: ${e}\nDisallow: /`);t.push(`User-agent: *
|
|
5
|
+
Allow: /`)}else for(let e of n)t.push(m(e));let r=t.join(`
|
|
6
6
|
|
|
7
|
-
`);return e.sitemap&&(r+=`\n\nSitemap: ${e.sitemap}`),r.trimEnd()}function
|
|
8
|
-
`)}function
|
|
9
|
-
`);if(e.siteUrl){let t={"@context":`https://schema.org`,"@type":`SoftwareApplication`,name:e.name,url:e.siteUrl,applicationCategory:`DeveloperApplication`,operatingSystem:`Web`,offers:{"@type":`Offer`,price:`0`,priceCurrency:`USD`}};return e.summary!==void 0&&(t.description=e.summary),e.version!==void 0&&(t.version=e.version),`<script type="application/ld+json">${JSON.stringify(t)}<\/script>`}return``}return{name:`aihu-agent-readiness`,configureServer(e){e.middlewares.use(async(e,r,i)=>{let a=e.url??`/`,o=[[`/llms.txt`,t.llmsTxt],[`/llms-full.txt`,t.llmsFullTxt],[`/.well-known/mcp/server-card.json`,t.mcpServerCard],[`/robots.txt`,t.robotsTxt],[`/.well-known/agent.json`,t.a2aCard],[`/.well-known/mcp.json`,t.mcpDiscovery],[`/sitemap.xml`,t.sitemapXml]];for(let[e,t]of o)if((a===e||a.startsWith(`${e}?`))&&await n(a,t,r))return;i()})},async generateBundle(e,n){let r=[[`llms.txt`,t.llmsTxt],[`llms-full.txt`,t.llmsFullTxt],[`.well-known/mcp/server-card.json`,t.mcpServerCard],[`robots.txt`,t.robotsTxt],[`.well-known/agent.json`,t.a2aCard],[`.well-known/mcp.json`,t.mcpDiscovery],[`sitemap.xml`,t.sitemapXml]];for(let[e,t]of r){let n=await t(new Request(`http://localhost/${e}`),{params:{},url:new URL(`http://localhost/${e}`)});if(n.status===200){let t=await n.text();this.emitFile({type:`asset`,fileName:e,source:t})}}},transformIndexHtml(e){let t=r();return t?e.replace(`</head>`,`${t}\n</head>`):e}}}const
|
|
7
|
+
`);return e.sitemap&&(r+=`\n\nSitemap: ${e.sitemap}`),r.trimEnd()}function g(e){return e.replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`)}function _(e){let t=[`<?xml version="1.0" encoding="UTF-8"?>`,`<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`];for(let n of e.pages)t.push(` <url>`),t.push(` <loc>${g(n.url)}</loc>`),n.lastmod&&t.push(` <lastmod>${n.lastmod}</lastmod>`),n.changefreq&&t.push(` <changefreq>${n.changefreq}</changefreq>`),n.priority!==void 0&&t.push(` <priority>${n.priority.toFixed(1)}</priority>`),t.push(` </url>`);return t.push(`</urlset>`),t.join(`
|
|
8
|
+
`)}function v(i){return{llmsTxt:t=>{let n=e(),r=l({name:i.name,sections:i.llmsSections??[],components:n,...i.summary===void 0?{}:{summary:i.summary},...i.llmsOptional===void 0?{}:{optional:i.llmsOptional}});return new Response(r,{status:200,headers:{"Content-Type":`text/plain; charset=utf-8`}})},llmsFullTxt:t=>{let n=e(),r=u({name:i.name,sections:i.llmsSections??[],components:n,...i.summary===void 0?{}:{summary:i.summary},...i.llmsOptional===void 0?{}:{optional:i.llmsOptional}});return new Response(r,{status:200,headers:{"Content-Type":`text/plain; charset=utf-8`}})},mcpServerCard:e=>i.endpoint?t(f({name:i.name,version:i.version??`0.0.0`,endpoint:i.endpoint,...i.skills===void 0?{}:{skills:i.skills},...i.auth===void 0?{}:{auth:i.auth},...i.summary===void 0?{}:{description:i.summary}})):n(),robotsTxt:e=>{let t=h({...i.aiAgents===void 0?{}:{aiAgents:i.aiAgents},...i.standardBots===void 0?{}:{standard:i.standardBots},...i.sitemap===void 0?{}:{sitemap:i.sitemap}});return new Response(t,{status:200,headers:{"Content-Type":`text/plain; charset=utf-8`}})},a2aCard:e=>{if(!i.a2aCard||!i.siteUrl)return n();let a=i.a2aCard===!0?{}:i.a2aCard;return t(r({name:i.name,url:i.siteUrl,...i.summary===void 0?{}:{description:i.summary},...i.version===void 0?{}:{version:i.version},...a.capabilities===void 0?{}:{capabilities:a.capabilities},...a.skills===void 0?{}:{skills:a.skills}}))},mcpDiscovery:e=>{if(!i.mcpDiscovery)return n();let r=i.endpoint??(i.siteUrl?`${i.siteUrl}/.well-known/mcp/server-card.json`:void 0);return r?t(d({name:i.name,url:r,...i.summary===void 0?{}:{description:i.summary}})):n()},sitemapXml:e=>{if(!i.sitemapPages)return n();let t=_({pages:i.sitemapPages});return new Response(t,{status:200,headers:{"Content-Type":`application/xml; charset=utf-8`}})}}}function y(e){let t=v(e),n=async(e,t,n)=>{let r=await t(new Request(`http://localhost${e}`),{params:{},url:new URL(`http://localhost${e}`)}),i=await r.text(),a=r.headers.get(`Content-Type`)??`text/plain`;return r.status===404?!1:(n.writeHead(r.status,{"Content-Type":a}),n.end(i),!0)};function r(){if(e.jsonLd===!1)return``;if(Array.isArray(e.jsonLd))return e.jsonLd.map(e=>`<script type="application/ld+json">${JSON.stringify(e)}<\/script>`).join(`
|
|
9
|
+
`);if(e.siteUrl){let t={"@context":`https://schema.org`,"@type":`SoftwareApplication`,name:e.name,url:e.siteUrl,applicationCategory:`DeveloperApplication`,operatingSystem:`Web`,offers:{"@type":`Offer`,price:`0`,priceCurrency:`USD`}};return e.summary!==void 0&&(t.description=e.summary),e.version!==void 0&&(t.version=e.version),`<script type="application/ld+json">${JSON.stringify(t)}<\/script>`}return``}return{name:`aihu-agent-readiness`,configureServer(e){e.middlewares.use(async(e,r,i)=>{let a=e.url??`/`,o=[[`/llms.txt`,t.llmsTxt],[`/llms-full.txt`,t.llmsFullTxt],[`/.well-known/mcp/server-card.json`,t.mcpServerCard],[`/robots.txt`,t.robotsTxt],[`/.well-known/agent.json`,t.a2aCard],[`/.well-known/mcp.json`,t.mcpDiscovery],[`/sitemap.xml`,t.sitemapXml]];for(let[e,t]of o)if((a===e||a.startsWith(`${e}?`))&&await n(a,t,r))return;i()})},async generateBundle(e,n){let r=[[`llms.txt`,t.llmsTxt],[`llms-full.txt`,t.llmsFullTxt],[`.well-known/mcp/server-card.json`,t.mcpServerCard],[`robots.txt`,t.robotsTxt],[`.well-known/agent.json`,t.a2aCard],[`.well-known/mcp.json`,t.mcpDiscovery],[`sitemap.xml`,t.sitemapXml]];for(let[e,t]of r){let n=await t(new Request(`http://localhost/${e}`),{params:{},url:new URL(`http://localhost/${e}`)});if(n.status===200){let t=await n.text();this.emitFile({type:`asset`,fileName:e,source:t})}}},transformIndexHtml(e){let t=r();return t?e.replace(`</head>`,`${t}\n</head>`):e}}}const b=y;export{p as AI_BOT_LIST,b as agentReadiness,v as createAgentReadinessRoutes,i as createContentNegotiationHandler,r as generateA2aCard,u as generateLlmsFullTxt,l as generateLlmsTxt,d as generateMcpDiscovery,f as generateMcpServerCard,h as generateRobotsTxt,_ as generateSitemapXml,y as viteAgentReadinessIntegration};
|
|
10
10
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/a2a-card.ts","../src/content-negotiation.ts","../src/llms-txt.ts","../src/mcp-discovery.ts","../src/mcp-server-card.ts","../src/robots.ts","../src/sitemap.ts","../src/vite-plugin.ts"],"sourcesContent":["/**\n * Google A2A (Agent-to-Agent) Agent Card generator.\n * Discovery: GET /.well-known/agent.json\n * Spec: https://google.github.io/A2A/specification/\n */\n\nexport interface A2aCapabilities {\n readonly streaming?: boolean\n readonly pushNotifications?: boolean\n}\n\nexport interface A2aSkill {\n readonly id: string\n readonly name: string\n readonly description?: string\n}\n\nexport interface A2aCard {\n readonly name: string\n readonly description?: string\n readonly url: string\n readonly version?: string\n readonly capabilities: {\n readonly streaming: boolean\n readonly pushNotifications: boolean\n }\n readonly skills?: ReadonlyArray<A2aSkill>\n}\n\nexport interface A2aCardConfig {\n readonly name: string\n readonly description?: string\n readonly url: string\n readonly version?: string\n readonly capabilities?: A2aCapabilities\n readonly skills?: ReadonlyArray<A2aSkill>\n}\n\n/**\n * Generate an A2A Agent Card object.\n * Pure function. No I/O.\n */\nexport function generateA2aCard(config: A2aCardConfig): A2aCard {\n return {\n name: config.name,\n ...(config.description !== undefined ? { description: config.description } : {}),\n url: config.url,\n ...(config.version !== undefined ? { version: config.version } : {}),\n capabilities: {\n streaming: config.capabilities?.streaming ?? false,\n pushNotifications: config.capabilities?.pushNotifications ?? false,\n },\n ...(config.skills !== undefined && config.skills.length > 0 ? { skills: config.skills } : {}),\n }\n}\n","import type { Middleware } from '@aihu/server'\n\n/**\n * Abstract interface for resolving markdown content from a URL path.\n *\n * Edge-safe: this module does NOT import fs, path, Deno.readFile,\n * Bun.file, or any filesystem API. The resolver is injected by the caller.\n *\n * SECURITY: Concrete resolver implementations MUST sanitize the `path`\n * argument before any filesystem access. Reject paths containing `..`,\n * null bytes, or other traversal patterns.\n */\nexport interface MarkdownResolver {\n /**\n * Return markdown content for the given URL path, or null when none exists.\n * Implementations must catch errors internally and return null rather than throw.\n */\n resolve(path: string): Promise<string | null>\n}\n\nexport interface ContentNegotiationOptions {\n readonly resolver: MarkdownResolver\n /**\n * Token count estimator for the x-markdown-tokens response header.\n * Default: Math.ceil(content.length / 4).\n */\n readonly estimateTokens?: (content: string) => number\n}\n\n/**\n * Create a content-negotiation middleware.\n *\n * Behavior:\n * 1. If Accept does NOT include text/markdown → call next()\n * 2. If Accept includes text/markdown:\n * a. Call resolver.resolve(url.pathname)\n * b. null result → call next() (fall through)\n * c. string result → return 200 with:\n * - Content-Type: text/markdown; charset=utf-8\n * - x-markdown-tokens: {count} (integer string, estimate)\n * - Body: the markdown content\n *\n * Does NOT modify responses from next().\n */\nexport function createContentNegotiationHandler(opts: ContentNegotiationOptions): Middleware {\n const estimateTokens = opts.estimateTokens ?? ((content: string) => Math.ceil(content.length / 4))\n\n return async (req, next) => {\n const accept = req.headers.get('Accept') ?? ''\n if (!accept.includes('text/markdown')) {\n return next()\n }\n\n const pathname = new URL(req.url).pathname\n const content = await opts.resolver.resolve(pathname)\n\n if (content === null) {\n return next()\n }\n\n const tokens = estimateTokens(content)\n return new Response(content, {\n status: 200,\n headers: {\n 'Content-Type': 'text/markdown; charset=utf-8',\n 'x-markdown-tokens': String(tokens),\n },\n })\n }\n}\n","export interface LlmsTxtLink {\n readonly title: string\n readonly url: string\n readonly description?: string\n}\n\nexport interface LlmsTxtSection {\n readonly title: string\n readonly links: ReadonlyArray<LlmsTxtLink>\n}\n\nexport interface LlmsTxtConfig {\n readonly name: string\n readonly summary?: string\n readonly sections: ReadonlyArray<LlmsTxtSection>\n readonly optional?: ReadonlyArray<LlmsTxtLink>\n}\n\n/** Minimal shape used for llms.txt link generation. Structurally compatible with @aihu/agent AgentMetadata. */\ninterface AgentMetadataLike {\n readonly tag: string\n readonly describes?: string\n}\n\nconst renderLink = (link: LlmsTxtLink): string =>\n link.description\n ? `- [${link.title}](${link.url}): ${link.description}`\n : `- [${link.title}](${link.url})`\n\nconst renderDocument = (config: LlmsTxtConfig, optionalHeading: string): string => {\n const lines: string[] = [`# ${config.name}`, '']\n if (config.summary) {\n lines.push(`> ${config.summary}`, '')\n }\n for (const section of config.sections) {\n if (section.links.length === 0) continue\n lines.push(`## ${section.title}`)\n for (const link of section.links) lines.push(renderLink(link))\n lines.push('')\n }\n if (config.optional?.length) {\n lines.push(`## ${optionalHeading}`)\n for (const link of config.optional) lines.push(renderLink(link))\n lines.push('')\n }\n return lines.join('\\n').trimEnd()\n}\n\nexport function generateLlmsTxt(config: LlmsTxtConfig): string {\n return renderDocument(config, 'Optional')\n}\n\nexport function generateLlmsFullTxt(config: LlmsTxtConfig): string {\n return renderDocument(config, 'More')\n}\n\nexport function agentMetadataToLlmsTxtLink(\n meta: AgentMetadataLike,\n baseUrl: string,\n): LlmsTxtLink | null {\n if (!meta.describes) return null\n return { title: meta.tag, url: `${baseUrl}/components#${meta.tag}` }\n}\n","/**\n * MCP Discovery document generator.\n * Discovery: GET /.well-known/mcp.json\n * Advertises MCP server endpoints to AI agents before page load.\n */\n\nexport interface McpDiscoveryServer {\n readonly url: string\n readonly name: string\n readonly description?: string\n}\n\nexport interface McpDiscovery {\n readonly mcpServers: Record<string, McpDiscoveryServer>\n}\n\nexport interface McpDiscoveryConfig {\n readonly name: string\n readonly url: string\n readonly description?: string\n}\n\n/**\n * Generate an MCP Discovery document.\n * Pure function. No I/O.\n *\n * Produces a /.well-known/mcp.json document with a single `mcpServers` entry.\n * The key is the name normalized to lowercase alphanumeric + hyphens.\n */\nexport function generateMcpDiscovery(config: McpDiscoveryConfig): McpDiscovery {\n const key = config.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n return {\n mcpServers: {\n [key]: {\n url: config.url,\n name: config.name,\n ...(config.description !== undefined ? { description: config.description } : {}),\n },\n },\n }\n}\n","/**\n * MCP Server Card generator.\n * Schema: SEP-1649/SEP-2127, protocolVersion 2025-06-18.\n * Discovery: GET /.well-known/mcp/server-card.json\n */\n\nimport type { McpAuthConfig } from './types.ts'\n\n/** Minimal shape used for skill generation. Structurally compatible with @aihu/agent AgentMetadata. */\ninterface AgentMetadataLike {\n readonly tag: string\n readonly actions?: Record<string, { desc?: string }>\n}\n\nexport interface AgentSkill {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly inputSchema?: Record<string, unknown>\n}\n\n/**\n * MCP Server Card output object. Valid JSON when serialized.\n */\nexport interface McpServerCard {\n readonly $schema: 'https://modelcontextprotocol.io/schemas/server-card/v1.0'\n readonly version: '1.0'\n readonly protocolVersion: string\n readonly serverInfo: {\n readonly name: string\n readonly version: string\n readonly description?: string\n readonly homepage?: string\n }\n readonly transport: {\n readonly type: 'streamable-http' | 'sse'\n readonly url: string\n }\n readonly capabilities: {\n readonly tools: boolean\n readonly resources: boolean\n readonly prompts: boolean\n }\n readonly tools?: ReadonlyArray<{\n readonly name: string\n readonly description: string\n }>\n readonly auth?: {\n readonly type: 'oauth2'\n readonly authorizationServer: string\n readonly resourceMetadata?: string\n }\n}\n\nexport interface McpServerCardConfig {\n readonly name: string\n readonly version: string\n readonly endpoint: string\n readonly skills?: ReadonlyArray<AgentSkill>\n readonly auth?: McpAuthConfig\n readonly description?: string\n readonly homepage?: string\n /** Default: '2025-06-18'. */\n readonly protocolVersion?: string\n /** Default: 'streamable-http'. */\n readonly transportType?: 'streamable-http' | 'sse'\n}\n\n/**\n * Generate an MCP Server Card object.\n * Pure function. No I/O.\n *\n * `capabilities` is always `{ tools: true, resources: false, prompts: false }` in v0.\n *\n * SECURITY: auth output block must never contain client secrets, tokens, or\n * passwords. Only public URLs are emitted.\n */\nexport function generateMcpServerCard(config: McpServerCardConfig): McpServerCard {\n const tools = config.skills?.map((s) => ({ name: s.name, description: s.description }))\n\n let auth: McpServerCard['auth']\n if (config.auth) {\n const tokenUrl = new URL(config.auth.tokenUrl)\n const authorizationServer = `${tokenUrl.origin}/.well-known/oauth-authorization-server`\n const resourceMetadata = `${config.endpoint}/.well-known/oauth-protected-resource`\n auth = { type: 'oauth2', authorizationServer, resourceMetadata }\n }\n\n const serverInfo: McpServerCard['serverInfo'] = {\n name: config.name,\n version: config.version,\n ...(config.description !== undefined ? { description: config.description } : {}),\n ...(config.homepage !== undefined ? { homepage: config.homepage } : {}),\n }\n\n return {\n $schema: 'https://modelcontextprotocol.io/schemas/server-card/v1.0',\n version: '1.0',\n protocolVersion: config.protocolVersion ?? '2025-06-18',\n serverInfo,\n transport: {\n type: config.transportType ?? 'streamable-http',\n url: config.endpoint,\n },\n capabilities: { tools: true, resources: false, prompts: false },\n ...(tools !== undefined ? { tools } : {}),\n ...(auth !== undefined ? { auth } : {}),\n }\n}\n\n/**\n * Derive AgentSkill[] from AgentMetadata.actions.\n * id = \"{meta.tag}.{actionName}\", name = actionName, description = desc string.\n * @internal\n */\nexport function agentMetadataToSkills(meta: AgentMetadataLike): ReadonlyArray<AgentSkill> {\n if (!meta.actions) return []\n return Object.entries(meta.actions).map(([actionName, action]) => ({\n id: `${meta.tag}.${actionName}`,\n name: actionName,\n description: action?.desc ?? '',\n }))\n}\n","export const AI_BOT_LIST: ReadonlyArray<string> = [\n 'GPTBot',\n 'ClaudeBot',\n 'PerplexityBot',\n 'Googlebot-Extended',\n 'CCBot',\n 'anthropic-ai',\n 'Google-Extended',\n 'Bytespider',\n 'cohere-ai',\n 'OAI-SearchBot',\n 'ChatGPT-User',\n 'DuckAssistBot',\n 'Applebot',\n]\n\nexport interface RobotsRule {\n readonly userAgent: string | ReadonlyArray<string>\n readonly allow?: ReadonlyArray<string>\n readonly disallow?: ReadonlyArray<string>\n readonly crawlDelay?: number\n}\n\nexport interface RobotsConfig {\n readonly aiAgents?: 'allow-all' | 'deny-all' | ReadonlyArray<RobotsRule>\n readonly standard?: ReadonlyArray<RobotsRule>\n readonly sitemap?: string\n}\n\nconst renderRule = (rule: RobotsRule): string => {\n const agents = Array.isArray(rule.userAgent) ? rule.userAgent : [rule.userAgent]\n const lines: string[] = (agents as string[]).map((a) => `User-agent: ${a}`)\n if (rule.disallow) {\n for (const path of rule.disallow) lines.push(`Disallow: ${path}`)\n }\n if (rule.allow) {\n for (const path of rule.allow) lines.push(`Allow: ${path}`)\n }\n if (rule.crawlDelay !== undefined) lines.push(`Crawl-delay: ${rule.crawlDelay}`)\n return lines.join('\\n')\n}\n\nexport function generateRobotsTxt(config: RobotsConfig = {}): string {\n const blocks: string[] = []\n const { aiAgents = 'allow-all' } = config\n\n if (config.standard?.length) {\n for (const rule of config.standard) {\n blocks.push(renderRule(rule))\n }\n }\n\n if (aiAgents === 'allow-all') {\n // Per spec §3.4: explicit Allow: / for each AI bot in AI_BOT_LIST plus wildcard\n for (const bot of AI_BOT_LIST) {\n blocks.push(`User-agent: ${bot}\\nAllow: /`)\n }\n blocks.push('User-agent: *\\nAllow: /')\n } else if (aiAgents === 'deny-all') {\n for (const bot of AI_BOT_LIST) {\n blocks.push(`User-agent: ${bot}\\nDisallow: /`)\n }\n blocks.push('User-agent: *\\nAllow: /')\n } else {\n for (const rule of aiAgents) {\n blocks.push(renderRule(rule))\n }\n }\n\n let output = blocks.join('\\n\\n')\n if (config.sitemap) output += `\\n\\nSitemap: ${config.sitemap}`\n return output.trimEnd()\n}\n","/**\n * XML Sitemap generator.\n * Spec: https://www.sitemaps.org/protocol.html\n */\n\nexport type SitemapChangefreq =\n | 'always'\n | 'hourly'\n | 'daily'\n | 'weekly'\n | 'monthly'\n | 'yearly'\n | 'never'\n\nexport interface SitemapUrl {\n readonly url: string\n readonly lastmod?: string\n readonly changefreq?: SitemapChangefreq\n readonly priority?: number\n}\n\nexport interface SitemapConfig {\n readonly pages: ReadonlyArray<SitemapUrl>\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\n/**\n * Generate a sitemap.xml string from a list of page URLs.\n * Pure function. No I/O.\n */\nexport function generateSitemapXml(config: SitemapConfig): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">',\n ]\n for (const page of config.pages) {\n lines.push(' <url>')\n lines.push(` <loc>${escapeXml(page.url)}</loc>`)\n if (page.lastmod) lines.push(` <lastmod>${page.lastmod}</lastmod>`)\n if (page.changefreq) lines.push(` <changefreq>${page.changefreq}</changefreq>`)\n if (page.priority !== undefined) {\n lines.push(` <priority>${page.priority.toFixed(1)}</priority>`)\n }\n lines.push(' </url>')\n }\n lines.push('</urlset>')\n return lines.join('\\n')\n}\n","import type { RouteHandler } from '@aihu/server'\nimport { json, notFound } from '@aihu/server'\nimport { generateA2aCard } from './a2a-card.ts'\nimport { generateLlmsFullTxt, generateLlmsTxt } from './llms-txt.ts'\nimport { generateMcpDiscovery } from './mcp-discovery.ts'\nimport { generateMcpServerCard } from './mcp-server-card.ts'\nimport { generateRobotsTxt } from './robots.ts'\nimport { generateSitemapXml } from './sitemap.ts'\nimport type { AgentReadinessConfig } from './types.ts'\n\n/**\n * Minimal Vite Plugin interface — avoids importing from 'vite' at compile time\n * while remaining structurally compatible. `vite` is external in rolldown.config.ts.\n * @internal\n */\ninterface VitePlugin {\n readonly name: string\n configureServer?: (server: {\n middlewares: {\n use: (fn: (req: any, res: any, next: () => void) => void) => void\n }\n }) => void\n generateBundle?: (options: any, bundle: any) => Promise<void>\n transformIndexHtml?: (html: string) => string\n}\n\n/**\n * Create fetch-API route handlers for all agent-readiness endpoints.\n * Each handler generates fresh content on every request (pure functions, negligible cost).\n *\n * @example\n * const ar = createAgentReadinessRoutes({ name: 'My App', endpoint: '...' })\n * const router = createRequestRouter({\n * routes: [\n * defineRoute('/llms.txt', ar.llmsTxt),\n * defineRoute('/llms-full.txt', ar.llmsFullTxt),\n * defineRoute('/.well-known/mcp/server-card.json', ar.mcpServerCard),\n * defineRoute('/robots.txt', ar.robotsTxt),\n * ...appRoutes,\n * ],\n * })\n */\nexport function createAgentReadinessRoutes(config: AgentReadinessConfig): {\n readonly llmsTxt: RouteHandler\n readonly llmsFullTxt: RouteHandler\n readonly mcpServerCard: RouteHandler\n readonly robotsTxt: RouteHandler\n readonly a2aCard: RouteHandler\n readonly mcpDiscovery: RouteHandler\n readonly sitemapXml: RouteHandler\n} {\n const llmsTxt: RouteHandler = (_req) => {\n const txt = generateLlmsTxt({\n name: config.name,\n sections: config.llmsSections ?? [],\n ...(config.summary !== undefined ? { summary: config.summary } : {}),\n ...(config.llmsOptional !== undefined ? { optional: config.llmsOptional } : {}),\n })\n // TODO: add Components section once @aihu/agent exports getAllAgentMetadata()\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const llmsFullTxt: RouteHandler = (_req) => {\n const txt = generateLlmsFullTxt({\n name: config.name,\n sections: config.llmsSections ?? [],\n ...(config.summary !== undefined ? { summary: config.summary } : {}),\n ...(config.llmsOptional !== undefined ? { optional: config.llmsOptional } : {}),\n })\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const mcpServerCard: RouteHandler = (_req) => {\n if (!config.endpoint) return notFound()\n const card = generateMcpServerCard({\n name: config.name,\n version: config.version ?? '0.0.0',\n endpoint: config.endpoint,\n ...(config.skills !== undefined ? { skills: config.skills } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n })\n return json(card)\n }\n\n const robotsTxt: RouteHandler = (_req) => {\n const txt = generateRobotsTxt({\n ...(config.aiAgents !== undefined ? { aiAgents: config.aiAgents } : {}),\n ...(config.standardBots !== undefined ? { standard: config.standardBots } : {}),\n ...(config.sitemap !== undefined ? { sitemap: config.sitemap } : {}),\n })\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const a2aCard: RouteHandler = (_req) => {\n if (!config.a2aCard) return notFound()\n if (!config.siteUrl) return notFound()\n const a2aConfig = config.a2aCard === true ? {} : config.a2aCard\n const card = generateA2aCard({\n name: config.name,\n url: config.siteUrl,\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n ...(config.version !== undefined ? { version: config.version } : {}),\n ...(a2aConfig.capabilities !== undefined ? { capabilities: a2aConfig.capabilities } : {}),\n ...(a2aConfig.skills !== undefined ? { skills: a2aConfig.skills } : {}),\n })\n return json(card)\n }\n\n const mcpDiscovery: RouteHandler = (_req) => {\n if (!config.mcpDiscovery) return notFound()\n const mcpUrl =\n config.endpoint ??\n (config.siteUrl ? `${config.siteUrl}/.well-known/mcp/server-card.json` : undefined)\n if (!mcpUrl) return notFound()\n const discovery = generateMcpDiscovery({\n name: config.name,\n url: mcpUrl,\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n })\n return json(discovery)\n }\n\n const sitemapXml: RouteHandler = (_req) => {\n if (!config.sitemapPages) return notFound()\n const xml = generateSitemapXml({ pages: config.sitemapPages })\n return new Response(xml, {\n status: 200,\n headers: { 'Content-Type': 'application/xml; charset=utf-8' },\n })\n }\n\n return { llmsTxt, llmsFullTxt, mcpServerCard, robotsTxt, a2aCard, mcpDiscovery, sitemapXml }\n}\n\n/**\n * The `viteAgentReadinessIntegration()` Vite plugin (v0.7.4 canonical name).\n *\n * configureServer (dev): serves /llms.txt, /llms-full.txt, /.well-known/mcp/server-card.json, /robots.txt\n * generateBundle (build): writes all four files as static assets to output dir\n *\n * Route injection: does NOT inject into createRequestRouter automatically.\n * Use createAgentReadinessRoutes() for fetch-API integration.\n *\n * Previously named `agentReadiness`. That name is kept as a deprecated alias\n * until v1.0 to avoid a breaking change.\n */\nexport function viteAgentReadinessIntegration(config: AgentReadinessConfig): VitePlugin {\n const routes = createAgentReadinessRoutes(config)\n\n const serveResponse = async (path: string, handler: RouteHandler, res: any): Promise<boolean> => {\n const req = new Request(`http://localhost${path}`)\n const response = await handler(req, { params: {}, url: new URL(`http://localhost${path}`) })\n const body = await response.text()\n const ct = response.headers.get('Content-Type') ?? 'text/plain'\n if (response.status === 404) return false\n res.writeHead(response.status, { 'Content-Type': ct })\n res.end(body)\n return true\n }\n\n function buildJsonLdTags(): string {\n if (config.jsonLd === false) return ''\n if (Array.isArray(config.jsonLd)) {\n return config.jsonLd\n .map((obj) => `<script type=\"application/ld+json\">${JSON.stringify(obj)}</script>`)\n .join('\\n')\n }\n if (config.siteUrl) {\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': 'SoftwareApplication',\n name: config.name,\n url: config.siteUrl,\n applicationCategory: 'DeveloperApplication',\n operatingSystem: 'Web',\n offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },\n }\n if (config.summary !== undefined) schema.description = config.summary\n if (config.version !== undefined) schema.version = config.version\n return `<script type=\"application/ld+json\">${JSON.stringify(schema)}</script>`\n }\n return ''\n }\n\n return {\n name: 'aihu-agent-readiness',\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url as string | undefined) ?? '/'\n const pathMap: Array<[string, RouteHandler]> = [\n ['/llms.txt', routes.llmsTxt],\n ['/llms-full.txt', routes.llmsFullTxt],\n ['/.well-known/mcp/server-card.json', routes.mcpServerCard],\n ['/robots.txt', routes.robotsTxt],\n ['/.well-known/agent.json', routes.a2aCard],\n ['/.well-known/mcp.json', routes.mcpDiscovery],\n ['/sitemap.xml', routes.sitemapXml],\n ]\n for (const [path, handler] of pathMap) {\n if (url === path || url.startsWith(`${path}?`)) {\n const handled = await serveResponse(url, handler, res)\n if (handled) return\n }\n }\n next()\n })\n },\n async generateBundle(_options, _bundle) {\n const files: Array<[string, RouteHandler]> = [\n ['llms.txt', routes.llmsTxt],\n ['llms-full.txt', routes.llmsFullTxt],\n ['.well-known/mcp/server-card.json', routes.mcpServerCard],\n ['robots.txt', routes.robotsTxt],\n ['.well-known/agent.json', routes.a2aCard],\n ['.well-known/mcp.json', routes.mcpDiscovery],\n ['sitemap.xml', routes.sitemapXml],\n ]\n for (const [name, handler] of files) {\n const req = new Request(`http://localhost/${name}`)\n const response = await handler(req, {\n params: {},\n url: new URL(`http://localhost/${name}`),\n })\n if (response.status === 200) {\n const body = await response.text()\n ;(this as any).emitFile({ type: 'asset', fileName: name, source: body })\n }\n }\n },\n transformIndexHtml(html: string): string {\n const tags = buildJsonLdTags()\n if (!tags) return html\n return html.replace('</head>', `${tags}\\n</head>`)\n },\n }\n}\n\n/** @deprecated Use `viteAgentReadinessIntegration` instead. Will be removed in v1.0. */\nexport const agentReadiness = viteAgentReadinessIntegration\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/a2a-card.ts","../src/content-negotiation.ts","../src/llms-txt.ts","../src/mcp-discovery.ts","../src/mcp-server-card.ts","../src/robots.ts","../src/sitemap.ts","../src/vite-plugin.ts"],"sourcesContent":["/**\n * Google A2A (Agent-to-Agent) Agent Card generator.\n * Discovery: GET /.well-known/agent.json\n * Spec: https://google.github.io/A2A/specification/\n */\n\nexport interface A2aCapabilities {\n readonly streaming?: boolean\n readonly pushNotifications?: boolean\n}\n\nexport interface A2aSkill {\n readonly id: string\n readonly name: string\n readonly description?: string\n}\n\nexport interface A2aCard {\n readonly name: string\n readonly description?: string\n readonly url: string\n readonly version?: string\n readonly capabilities: {\n readonly streaming: boolean\n readonly pushNotifications: boolean\n }\n readonly skills?: ReadonlyArray<A2aSkill>\n}\n\nexport interface A2aCardConfig {\n readonly name: string\n readonly description?: string\n readonly url: string\n readonly version?: string\n readonly capabilities?: A2aCapabilities\n readonly skills?: ReadonlyArray<A2aSkill>\n}\n\n/**\n * Generate an A2A Agent Card object.\n * Pure function. No I/O.\n */\nexport function generateA2aCard(config: A2aCardConfig): A2aCard {\n return {\n name: config.name,\n ...(config.description !== undefined ? { description: config.description } : {}),\n url: config.url,\n ...(config.version !== undefined ? { version: config.version } : {}),\n capabilities: {\n streaming: config.capabilities?.streaming ?? false,\n pushNotifications: config.capabilities?.pushNotifications ?? false,\n },\n ...(config.skills !== undefined && config.skills.length > 0 ? { skills: config.skills } : {}),\n }\n}\n","import type { Middleware } from '@aihu/server'\n\n/**\n * Abstract interface for resolving markdown content from a URL path.\n *\n * Edge-safe: this module does NOT import fs, path, Deno.readFile,\n * Bun.file, or any filesystem API. The resolver is injected by the caller.\n *\n * SECURITY: Concrete resolver implementations MUST sanitize the `path`\n * argument before any filesystem access. Reject paths containing `..`,\n * null bytes, or other traversal patterns.\n */\nexport interface MarkdownResolver {\n /**\n * Return markdown content for the given URL path, or null when none exists.\n * Implementations must catch errors internally and return null rather than throw.\n */\n resolve(path: string): Promise<string | null>\n}\n\nexport interface ContentNegotiationOptions {\n readonly resolver: MarkdownResolver\n /**\n * Token count estimator for the x-markdown-tokens response header.\n * Default: Math.ceil(content.length / 4).\n */\n readonly estimateTokens?: (content: string) => number\n}\n\n/**\n * Create a content-negotiation middleware.\n *\n * Behavior:\n * 1. If Accept does NOT include text/markdown → call next()\n * 2. If Accept includes text/markdown:\n * a. Call resolver.resolve(url.pathname)\n * b. null result → call next() (fall through)\n * c. string result → return 200 with:\n * - Content-Type: text/markdown; charset=utf-8\n * - x-markdown-tokens: {count} (integer string, estimate)\n * - Body: the markdown content\n *\n * Does NOT modify responses from next().\n */\nexport function createContentNegotiationHandler(opts: ContentNegotiationOptions): Middleware {\n const estimateTokens = opts.estimateTokens ?? ((content: string) => Math.ceil(content.length / 4))\n\n return async (req, next) => {\n const accept = req.headers.get('Accept') ?? ''\n if (!accept.includes('text/markdown')) {\n return next()\n }\n\n const pathname = new URL(req.url).pathname\n const content = await opts.resolver.resolve(pathname)\n\n if (content === null) {\n return next()\n }\n\n const tokens = estimateTokens(content)\n return new Response(content, {\n status: 200,\n headers: {\n 'Content-Type': 'text/markdown; charset=utf-8',\n 'x-markdown-tokens': String(tokens),\n },\n })\n }\n}\n","export interface LlmsTxtLink {\n readonly title: string\n readonly url: string\n readonly description?: string\n}\n\nexport interface LlmsTxtSection {\n readonly title: string\n readonly links: ReadonlyArray<LlmsTxtLink>\n}\n\nexport interface LlmsTxtConfig {\n readonly name: string\n readonly summary?: string\n readonly sections: ReadonlyArray<LlmsTxtSection>\n readonly optional?: ReadonlyArray<LlmsTxtLink>\n /**\n * Component metadata, rendered as a `## Components` section listing each\n * component's tag, description, callable actions, and readable state.\n * When empty (zero components) the section is omitted entirely.\n */\n readonly components?: ReadonlyArray<ComponentMetaLike>\n}\n\n/** Minimal shape used for llms.txt link generation. Structurally compatible with @aihu/agent AgentMetadata. */\ninterface AgentMetadataLike {\n readonly tag: string\n readonly describes?: string\n}\n\n/**\n * Minimal shape used for the `## Components` section. Structurally compatible\n * with @aihu/agent `AgentMetadata` (tag/describes/state/actions).\n */\ninterface ComponentMetaLike {\n readonly tag: string\n readonly describes?: string\n readonly state?: Record<string, string>\n readonly actions?: Record<string, { readonly returns?: Record<string, { type: string }> }>\n}\n\nconst renderLink = (link: LlmsTxtLink): string =>\n link.description\n ? `- [${link.title}](${link.url}): ${link.description}`\n : `- [${link.title}](${link.url})`\n\n/** Render a single action's return shape as `{ field: type, ... }`, or `{}` when no returns. */\nconst renderActionReturns = (returns?: Record<string, { type: string }>): string => {\n const entries = returns ? Object.entries(returns) : []\n if (entries.length === 0) return '{}'\n return `{ ${entries.map(([field, schema]) => `${field}: ${schema.type}`).join(', ')} }`\n}\n\n/** Render one component as markdown lines: heading, describes, actions, state. */\nconst renderComponent = (meta: ComponentMetaLike): string[] => {\n const lines: string[] = [`### ${meta.tag}`]\n if (meta.describes) lines.push(meta.describes)\n const actions = meta.actions ? Object.entries(meta.actions) : []\n if (actions.length > 0) {\n lines.push('Actions:')\n for (const [name, action] of actions) {\n lines.push(`- \\`${name}()\\` → ${renderActionReturns(action?.returns)}`)\n }\n }\n const state = meta.state ? Object.entries(meta.state) : []\n if (state.length > 0) {\n lines.push('State:')\n for (const [name, desc] of state) lines.push(`- \\`${name}\\`: ${desc}`)\n }\n return lines\n}\n\nconst renderDocument = (config: LlmsTxtConfig, optionalHeading: string): string => {\n const lines: string[] = [`# ${config.name}`, '']\n if (config.summary) {\n lines.push(`> ${config.summary}`, '')\n }\n for (const section of config.sections) {\n if (section.links.length === 0) continue\n lines.push(`## ${section.title}`)\n for (const link of section.links) lines.push(renderLink(link))\n lines.push('')\n }\n // Components section: omitted entirely when zero components (no empty header).\n if (config.components?.length) {\n lines.push('## Components', '')\n for (const meta of config.components) {\n lines.push(...renderComponent(meta), '')\n }\n }\n if (config.optional?.length) {\n lines.push(`## ${optionalHeading}`)\n for (const link of config.optional) lines.push(renderLink(link))\n lines.push('')\n }\n return lines.join('\\n').trimEnd()\n}\n\nexport function generateLlmsTxt(config: LlmsTxtConfig): string {\n return renderDocument(config, 'Optional')\n}\n\nexport function generateLlmsFullTxt(config: LlmsTxtConfig): string {\n return renderDocument(config, 'More')\n}\n\nexport function agentMetadataToLlmsTxtLink(\n meta: AgentMetadataLike,\n baseUrl: string,\n): LlmsTxtLink | null {\n if (!meta.describes) return null\n return { title: meta.tag, url: `${baseUrl}/components#${meta.tag}` }\n}\n","/**\n * MCP Discovery document generator.\n * Discovery: GET /.well-known/mcp.json\n * Advertises MCP server endpoints to AI agents before page load.\n */\n\nexport interface McpDiscoveryServer {\n readonly url: string\n readonly name: string\n readonly description?: string\n}\n\nexport interface McpDiscovery {\n readonly mcpServers: Record<string, McpDiscoveryServer>\n}\n\nexport interface McpDiscoveryConfig {\n readonly name: string\n readonly url: string\n readonly description?: string\n}\n\n/**\n * Generate an MCP Discovery document.\n * Pure function. No I/O.\n *\n * Produces a /.well-known/mcp.json document with a single `mcpServers` entry.\n * The key is the name normalized to lowercase alphanumeric + hyphens.\n */\nexport function generateMcpDiscovery(config: McpDiscoveryConfig): McpDiscovery {\n const key = config.name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '')\n return {\n mcpServers: {\n [key]: {\n url: config.url,\n name: config.name,\n ...(config.description !== undefined ? { description: config.description } : {}),\n },\n },\n }\n}\n","/**\n * MCP Server Card generator.\n * Schema: SEP-1649/SEP-2127, protocolVersion 2025-06-18.\n * Discovery: GET /.well-known/mcp/server-card.json\n */\n\nimport type { McpAuthConfig } from './types.ts'\n\n/** Minimal shape used for skill generation. Structurally compatible with @aihu/agent AgentMetadata. */\ninterface AgentMetadataLike {\n readonly tag: string\n readonly actions?: Record<string, { desc?: string }>\n}\n\nexport interface AgentSkill {\n readonly id: string\n readonly name: string\n readonly description: string\n readonly inputSchema?: Record<string, unknown>\n}\n\n/**\n * MCP Server Card output object. Valid JSON when serialized.\n */\nexport interface McpServerCard {\n readonly $schema: 'https://modelcontextprotocol.io/schemas/server-card/v1.0'\n readonly version: '1.0'\n readonly protocolVersion: string\n readonly serverInfo: {\n readonly name: string\n readonly version: string\n readonly description?: string\n readonly homepage?: string\n }\n readonly transport: {\n readonly type: 'streamable-http' | 'sse'\n readonly url: string\n }\n readonly capabilities: {\n readonly tools: boolean\n readonly resources: boolean\n readonly prompts: boolean\n }\n readonly tools?: ReadonlyArray<{\n readonly name: string\n readonly description: string\n }>\n readonly auth?: {\n readonly type: 'oauth2'\n readonly authorizationServer: string\n readonly resourceMetadata?: string\n }\n}\n\nexport interface McpServerCardConfig {\n readonly name: string\n readonly version: string\n readonly endpoint: string\n readonly skills?: ReadonlyArray<AgentSkill>\n readonly auth?: McpAuthConfig\n readonly description?: string\n readonly homepage?: string\n /** Default: '2025-06-18'. */\n readonly protocolVersion?: string\n /** Default: 'streamable-http'. */\n readonly transportType?: 'streamable-http' | 'sse'\n}\n\n/**\n * Generate an MCP Server Card object.\n * Pure function. No I/O.\n *\n * `capabilities` is always `{ tools: true, resources: false, prompts: false }` in v0.\n *\n * SECURITY: auth output block must never contain client secrets, tokens, or\n * passwords. Only public URLs are emitted.\n */\nexport function generateMcpServerCard(config: McpServerCardConfig): McpServerCard {\n const tools = config.skills?.map((s) => ({ name: s.name, description: s.description }))\n\n let auth: McpServerCard['auth']\n if (config.auth) {\n const tokenUrl = new URL(config.auth.tokenUrl)\n const authorizationServer = `${tokenUrl.origin}/.well-known/oauth-authorization-server`\n const resourceMetadata = `${config.endpoint}/.well-known/oauth-protected-resource`\n auth = { type: 'oauth2', authorizationServer, resourceMetadata }\n }\n\n const serverInfo: McpServerCard['serverInfo'] = {\n name: config.name,\n version: config.version,\n ...(config.description !== undefined ? { description: config.description } : {}),\n ...(config.homepage !== undefined ? { homepage: config.homepage } : {}),\n }\n\n return {\n $schema: 'https://modelcontextprotocol.io/schemas/server-card/v1.0',\n version: '1.0',\n protocolVersion: config.protocolVersion ?? '2025-06-18',\n serverInfo,\n transport: {\n type: config.transportType ?? 'streamable-http',\n url: config.endpoint,\n },\n capabilities: { tools: true, resources: false, prompts: false },\n ...(tools !== undefined ? { tools } : {}),\n ...(auth !== undefined ? { auth } : {}),\n }\n}\n\n/**\n * Derive AgentSkill[] from AgentMetadata.actions.\n * id = \"{meta.tag}.{actionName}\", name = actionName, description = desc string.\n * @internal\n */\nexport function agentMetadataToSkills(meta: AgentMetadataLike): ReadonlyArray<AgentSkill> {\n if (!meta.actions) return []\n return Object.entries(meta.actions).map(([actionName, action]) => ({\n id: `${meta.tag}.${actionName}`,\n name: actionName,\n description: action?.desc ?? '',\n }))\n}\n","export const AI_BOT_LIST: ReadonlyArray<string> = [\n 'GPTBot',\n 'ClaudeBot',\n 'PerplexityBot',\n 'Googlebot-Extended',\n 'CCBot',\n 'anthropic-ai',\n 'Google-Extended',\n 'Bytespider',\n 'cohere-ai',\n 'OAI-SearchBot',\n 'ChatGPT-User',\n 'DuckAssistBot',\n 'Applebot',\n]\n\nexport interface RobotsRule {\n readonly userAgent: string | ReadonlyArray<string>\n readonly allow?: ReadonlyArray<string>\n readonly disallow?: ReadonlyArray<string>\n readonly crawlDelay?: number\n}\n\nexport interface RobotsConfig {\n readonly aiAgents?: 'allow-all' | 'deny-all' | ReadonlyArray<RobotsRule>\n readonly standard?: ReadonlyArray<RobotsRule>\n readonly sitemap?: string\n}\n\nconst renderRule = (rule: RobotsRule): string => {\n const agents = Array.isArray(rule.userAgent) ? rule.userAgent : [rule.userAgent]\n const lines: string[] = (agents as string[]).map((a) => `User-agent: ${a}`)\n if (rule.disallow) {\n for (const path of rule.disallow) lines.push(`Disallow: ${path}`)\n }\n if (rule.allow) {\n for (const path of rule.allow) lines.push(`Allow: ${path}`)\n }\n if (rule.crawlDelay !== undefined) lines.push(`Crawl-delay: ${rule.crawlDelay}`)\n return lines.join('\\n')\n}\n\nexport function generateRobotsTxt(config: RobotsConfig = {}): string {\n const blocks: string[] = []\n const { aiAgents = 'allow-all' } = config\n\n if (config.standard?.length) {\n for (const rule of config.standard) {\n blocks.push(renderRule(rule))\n }\n }\n\n if (aiAgents === 'allow-all') {\n // Per spec §3.4: explicit Allow: / for each AI bot in AI_BOT_LIST plus wildcard\n for (const bot of AI_BOT_LIST) {\n blocks.push(`User-agent: ${bot}\\nAllow: /`)\n }\n blocks.push('User-agent: *\\nAllow: /')\n } else if (aiAgents === 'deny-all') {\n for (const bot of AI_BOT_LIST) {\n blocks.push(`User-agent: ${bot}\\nDisallow: /`)\n }\n blocks.push('User-agent: *\\nAllow: /')\n } else {\n for (const rule of aiAgents) {\n blocks.push(renderRule(rule))\n }\n }\n\n let output = blocks.join('\\n\\n')\n if (config.sitemap) output += `\\n\\nSitemap: ${config.sitemap}`\n return output.trimEnd()\n}\n","/**\n * XML Sitemap generator.\n * Spec: https://www.sitemaps.org/protocol.html\n */\n\nexport type SitemapChangefreq =\n | 'always'\n | 'hourly'\n | 'daily'\n | 'weekly'\n | 'monthly'\n | 'yearly'\n | 'never'\n\nexport interface SitemapUrl {\n readonly url: string\n readonly lastmod?: string\n readonly changefreq?: SitemapChangefreq\n readonly priority?: number\n}\n\nexport interface SitemapConfig {\n readonly pages: ReadonlyArray<SitemapUrl>\n}\n\nfunction escapeXml(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\n/**\n * Generate a sitemap.xml string from a list of page URLs.\n * Pure function. No I/O.\n */\nexport function generateSitemapXml(config: SitemapConfig): string {\n const lines: string[] = [\n '<?xml version=\"1.0\" encoding=\"UTF-8\"?>',\n '<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">',\n ]\n for (const page of config.pages) {\n lines.push(' <url>')\n lines.push(` <loc>${escapeXml(page.url)}</loc>`)\n if (page.lastmod) lines.push(` <lastmod>${page.lastmod}</lastmod>`)\n if (page.changefreq) lines.push(` <changefreq>${page.changefreq}</changefreq>`)\n if (page.priority !== undefined) {\n lines.push(` <priority>${page.priority.toFixed(1)}</priority>`)\n }\n lines.push(' </url>')\n }\n lines.push('</urlset>')\n return lines.join('\\n')\n}\n","import { getAllAgentMetadata } from '@aihu/agent'\nimport type { RouteHandler } from '@aihu/server'\nimport { json, notFound } from '@aihu/server'\nimport { generateA2aCard } from './a2a-card.ts'\nimport { generateLlmsFullTxt, generateLlmsTxt } from './llms-txt.ts'\nimport { generateMcpDiscovery } from './mcp-discovery.ts'\nimport { generateMcpServerCard } from './mcp-server-card.ts'\nimport { generateRobotsTxt } from './robots.ts'\nimport { generateSitemapXml } from './sitemap.ts'\nimport type { AgentReadinessConfig } from './types.ts'\n\n/**\n * Minimal Vite Plugin interface — avoids importing from 'vite' at compile time\n * while remaining structurally compatible. `vite` is external in rolldown.config.ts.\n * @internal\n */\ninterface VitePlugin {\n readonly name: string\n configureServer?: (server: {\n middlewares: {\n use: (fn: (req: any, res: any, next: () => void) => void) => void\n }\n }) => void\n generateBundle?: (options: any, bundle: any) => Promise<void>\n transformIndexHtml?: (html: string) => string\n}\n\n/**\n * Create fetch-API route handlers for all agent-readiness endpoints.\n * Each handler generates fresh content on every request (pure functions, negligible cost).\n *\n * @example\n * const ar = createAgentReadinessRoutes({ name: 'My App', endpoint: '...' })\n * const router = createRequestRouter({\n * routes: [\n * defineRoute('/llms.txt', ar.llmsTxt),\n * defineRoute('/llms-full.txt', ar.llmsFullTxt),\n * defineRoute('/.well-known/mcp/server-card.json', ar.mcpServerCard),\n * defineRoute('/robots.txt', ar.robotsTxt),\n * ...appRoutes,\n * ],\n * })\n */\nexport function createAgentReadinessRoutes(config: AgentReadinessConfig): {\n readonly llmsTxt: RouteHandler\n readonly llmsFullTxt: RouteHandler\n readonly mcpServerCard: RouteHandler\n readonly robotsTxt: RouteHandler\n readonly a2aCard: RouteHandler\n readonly mcpDiscovery: RouteHandler\n readonly sitemapXml: RouteHandler\n} {\n const llmsTxt: RouteHandler = (_req) => {\n // Snapshot the component registry at request/build time, consistent with\n // how the rest of the config is read. Zero components → omitted section.\n const components = getAllAgentMetadata()\n const txt = generateLlmsTxt({\n name: config.name,\n sections: config.llmsSections ?? [],\n components,\n ...(config.summary !== undefined ? { summary: config.summary } : {}),\n ...(config.llmsOptional !== undefined ? { optional: config.llmsOptional } : {}),\n })\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const llmsFullTxt: RouteHandler = (_req) => {\n const components = getAllAgentMetadata()\n const txt = generateLlmsFullTxt({\n name: config.name,\n sections: config.llmsSections ?? [],\n components,\n ...(config.summary !== undefined ? { summary: config.summary } : {}),\n ...(config.llmsOptional !== undefined ? { optional: config.llmsOptional } : {}),\n })\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const mcpServerCard: RouteHandler = (_req) => {\n if (!config.endpoint) return notFound()\n const card = generateMcpServerCard({\n name: config.name,\n version: config.version ?? '0.0.0',\n endpoint: config.endpoint,\n ...(config.skills !== undefined ? { skills: config.skills } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n })\n return json(card)\n }\n\n const robotsTxt: RouteHandler = (_req) => {\n const txt = generateRobotsTxt({\n ...(config.aiAgents !== undefined ? { aiAgents: config.aiAgents } : {}),\n ...(config.standardBots !== undefined ? { standard: config.standardBots } : {}),\n ...(config.sitemap !== undefined ? { sitemap: config.sitemap } : {}),\n })\n return new Response(txt, {\n status: 200,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n\n const a2aCard: RouteHandler = (_req) => {\n if (!config.a2aCard) return notFound()\n if (!config.siteUrl) return notFound()\n const a2aConfig = config.a2aCard === true ? {} : config.a2aCard\n const card = generateA2aCard({\n name: config.name,\n url: config.siteUrl,\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n ...(config.version !== undefined ? { version: config.version } : {}),\n ...(a2aConfig.capabilities !== undefined ? { capabilities: a2aConfig.capabilities } : {}),\n ...(a2aConfig.skills !== undefined ? { skills: a2aConfig.skills } : {}),\n })\n return json(card)\n }\n\n const mcpDiscovery: RouteHandler = (_req) => {\n if (!config.mcpDiscovery) return notFound()\n const mcpUrl =\n config.endpoint ??\n (config.siteUrl ? `${config.siteUrl}/.well-known/mcp/server-card.json` : undefined)\n if (!mcpUrl) return notFound()\n const discovery = generateMcpDiscovery({\n name: config.name,\n url: mcpUrl,\n ...(config.summary !== undefined ? { description: config.summary } : {}),\n })\n return json(discovery)\n }\n\n const sitemapXml: RouteHandler = (_req) => {\n if (!config.sitemapPages) return notFound()\n const xml = generateSitemapXml({ pages: config.sitemapPages })\n return new Response(xml, {\n status: 200,\n headers: { 'Content-Type': 'application/xml; charset=utf-8' },\n })\n }\n\n return { llmsTxt, llmsFullTxt, mcpServerCard, robotsTxt, a2aCard, mcpDiscovery, sitemapXml }\n}\n\n/**\n * The `viteAgentReadinessIntegration()` Vite plugin (v0.7.4 canonical name).\n *\n * configureServer (dev): serves /llms.txt, /llms-full.txt, /.well-known/mcp/server-card.json, /robots.txt\n * generateBundle (build): writes all four files as static assets to output dir\n *\n * Route injection: does NOT inject into createRequestRouter automatically.\n * Use createAgentReadinessRoutes() for fetch-API integration.\n *\n * Previously named `agentReadiness`. That name is kept as a deprecated alias\n * until v1.0 to avoid a breaking change.\n */\nexport function viteAgentReadinessIntegration(config: AgentReadinessConfig): VitePlugin {\n const routes = createAgentReadinessRoutes(config)\n\n const serveResponse = async (path: string, handler: RouteHandler, res: any): Promise<boolean> => {\n const req = new Request(`http://localhost${path}`)\n const response = await handler(req, { params: {}, url: new URL(`http://localhost${path}`) })\n const body = await response.text()\n const ct = response.headers.get('Content-Type') ?? 'text/plain'\n if (response.status === 404) return false\n res.writeHead(response.status, { 'Content-Type': ct })\n res.end(body)\n return true\n }\n\n function buildJsonLdTags(): string {\n if (config.jsonLd === false) return ''\n if (Array.isArray(config.jsonLd)) {\n return config.jsonLd\n .map((obj) => `<script type=\"application/ld+json\">${JSON.stringify(obj)}</script>`)\n .join('\\n')\n }\n if (config.siteUrl) {\n const schema: Record<string, unknown> = {\n '@context': 'https://schema.org',\n '@type': 'SoftwareApplication',\n name: config.name,\n url: config.siteUrl,\n applicationCategory: 'DeveloperApplication',\n operatingSystem: 'Web',\n offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },\n }\n if (config.summary !== undefined) schema.description = config.summary\n if (config.version !== undefined) schema.version = config.version\n return `<script type=\"application/ld+json\">${JSON.stringify(schema)}</script>`\n }\n return ''\n }\n\n return {\n name: 'aihu-agent-readiness',\n configureServer(server) {\n server.middlewares.use(async (req, res, next) => {\n const url = (req.url as string | undefined) ?? '/'\n const pathMap: Array<[string, RouteHandler]> = [\n ['/llms.txt', routes.llmsTxt],\n ['/llms-full.txt', routes.llmsFullTxt],\n ['/.well-known/mcp/server-card.json', routes.mcpServerCard],\n ['/robots.txt', routes.robotsTxt],\n ['/.well-known/agent.json', routes.a2aCard],\n ['/.well-known/mcp.json', routes.mcpDiscovery],\n ['/sitemap.xml', routes.sitemapXml],\n ]\n for (const [path, handler] of pathMap) {\n if (url === path || url.startsWith(`${path}?`)) {\n const handled = await serveResponse(url, handler, res)\n if (handled) return\n }\n }\n next()\n })\n },\n async generateBundle(_options, _bundle) {\n const files: Array<[string, RouteHandler]> = [\n ['llms.txt', routes.llmsTxt],\n ['llms-full.txt', routes.llmsFullTxt],\n ['.well-known/mcp/server-card.json', routes.mcpServerCard],\n ['robots.txt', routes.robotsTxt],\n ['.well-known/agent.json', routes.a2aCard],\n ['.well-known/mcp.json', routes.mcpDiscovery],\n ['sitemap.xml', routes.sitemapXml],\n ]\n for (const [name, handler] of files) {\n const req = new Request(`http://localhost/${name}`)\n const response = await handler(req, {\n params: {},\n url: new URL(`http://localhost/${name}`),\n })\n if (response.status === 200) {\n const body = await response.text()\n ;(this as any).emitFile({ type: 'asset', fileName: name, source: body })\n }\n }\n },\n transformIndexHtml(html: string): string {\n const tags = buildJsonLdTags()\n if (!tags) return html\n return html.replace('</head>', `${tags}\\n</head>`)\n },\n }\n}\n\n/** @deprecated Use `viteAgentReadinessIntegration` instead. Will be removed in v1.0. */\nexport const agentReadiness = viteAgentReadinessIntegration\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aihu-plugin/agent-readiness",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@aihu/server": "0.1
|
|
27
|
+
"@aihu/server": "0.2.1",
|
|
28
28
|
"@aihu/agent": "0.1.0"
|
|
29
29
|
},
|
|
30
30
|
"description": "Discovery + readiness manifest emitter so agents can introspect aihu apps.",
|