@agentproto/persona 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/chunk-TMV2PWI4.mjs +29 -0
- package/dist/chunk-TMV2PWI4.mjs.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.mjs +14 -0
- package/dist/index.mjs.map +1 -0
- package/dist/manifest/index.d.ts +90 -0
- package/dist/manifest/index.mjs +28 -0
- package/dist/manifest/index.mjs.map +1 -0
- package/dist/types-CwL32wDG.d.ts +238 -0
- package/package.json +68 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 agentproto contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# @agentproto/persona
|
|
2
|
+
|
|
3
|
+
AIP-25 `PERSONA.md` reference implementation. A single-doc markdown + frontmatter format for portable agent personas — the public face, voice register, backstory, and boundaries of a character — sibling to AIP-23 IDENTITY (heavy substance) and building block of AIP-24 ASSEMBLY.
|
|
4
|
+
|
|
5
|
+
> **Status: 0.1.0-alpha.** Generated by `scripts/scaffold-aip.mjs` — `build()` and `validate()` bodies are TODOs.
|
|
6
|
+
|
|
7
|
+
Spec: <https://agentproto.sh/docs/aip-25>
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { definePersona } from "@agentproto/persona"
|
|
13
|
+
|
|
14
|
+
const x = definePersona({
|
|
15
|
+
id: "my-persona",
|
|
16
|
+
description: "Short purpose.",
|
|
17
|
+
// ...
|
|
18
|
+
})
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
MIT — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { createDoctype } from '@agentproto/define-doctype';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @agentproto/persona v0.1.0-alpha
|
|
6
|
+
* AIP-25 PERSONA.md `definePersona` reference implementation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var personaFrontmatterSchema = z.object({ "schema": z.literal("persona/v1").describe("Schema dispatch tag. MUST be 'persona/v1' for this version of AIP-25."), "name": z.string().regex(new RegExp("^[a-z][a-z0-9-]*[a-z0-9]$")).min(2).max(64).describe("Machine identifier. Lowercase, digits, dashes. Must start with a letter, end with a letter or digit. Unique within the registry that hosts the persona."), "title": z.string().min(1).max(120).describe("Human-readable display title, sentence case."), "description": z.string().min(1).max(2e3).describe("One-paragraph elevator pitch. The persona's purpose, audience, and shape."), "version": z.string().regex(new RegExp("^\\d+\\.\\d+\\.\\d+(?:[-+][a-zA-Z0-9.-]+)?$")).describe("Semver. Bump on breaking change to identity, voice, or boundaries."), "extends": z.string().regex(new RegExp("^(\\.{1,2}/)[^\\s]+PERSONA\\.md$")).describe("Relative path to a parent PERSONA.md. Triggers composition. Path MUST end in 'PERSONA.md'.").optional(), "avatar": z.string().min(1).describe("Public visual face. URL, data URI, or 'ws://avatars/<slug>' ref. Schema does not validate scheme; the loader resolves.").optional(), "backstory": z.object({ "oneLineHook": z.string().min(1).max(280).describe("Punchy elevator hook. One sentence the catalog can show next to the persona name.").optional(), "background": z.string().min(1).describe("Long-form lore prose, in markdown. The character's history, motivations, and context.").optional(), "archetypes": z.array(z.string().regex(new RegExp("^[a-z][a-z0-9-]*[a-z0-9]$"))).max(12).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Categorical archetype labels. Lowercase kebab-case. Examples: mentor, craftsman, sentinel, trickster. The catalog MAY cluster by these.").default([]), "era": z.string().min(1).max(80).describe("Free-form era label. Conventional values: 'contemporary', 'timeless', '<year>', '<year>-<year>', '<period>'. Free-form to accept any setting.").optional(), "setting": z.string().min(1).max(120).describe("Free-form setting label. Conventional values: 'real-world', 'fictional-<universe>'. Free-form to accept any setting.").optional() }).strict().default({}), "voice": z.object({ "register": z.string().min(1).max(80).describe("Voice register. Conventional values: warm-direct, playful, terse, academic. Custom values welcome \u2014 free-form to accept any author label.").optional(), "signaturePhrases": z.array(z.string().min(1).max(200)).max(24).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Catchphrases the character uses. Append-and-dedupe under extends \u2014 lineage accumulates phrases.").default([]), "tonality": z.array(z.string().min(1).max(60)).max(16).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Tonal adjectives. Examples: rigorous, encouraging, dry, warm. Append-and-dedupe under extends.").default([]), "formality": z.number().int().gte(0).lte(10).describe("Formality scale, 0 (extremely casual) to 10 (extremely formal). Optional.").optional(), "emojiUsage": z.enum(["never", "sparing", "frequent"]).describe("Emoji posture. 'never' = no emojis ever; 'sparing' = occasional, intentional; 'frequent' = part of the voice.").optional(), "signOff": z.string().min(1).max(200).describe("Sign-off the persona uses to close messages. Examples: '\u2014M.', 'Yours, Marcus', 'Until next time'.").optional() }).strict().default({}), "boundaries": z.object({ "refuses": z.array(z.string().min(1).max(200)).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Topics the persona refuses outright. Free-form prose; the persona body SHOULD demonstrate the refusal posture in voice samples. Append-and-dedupe under extends.").default([]), "defers": z.array(z.string().min(1).max(200)).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Topics the persona defers to a specialist on. Append-and-dedupe under extends.").default([]), "redirects": z.array(z.object({ "topic": z.string().min(1).max(200).describe("The topic the persona redirects."), "to": z.string().regex(new RegExp("^(ws://(personas|operators|skills)/[^\\s]+|\\.{1,2}/[^\\s]+)$")).describe("Redirect target. ws:// ref to a persona/operator/skill, or a relative path."), "notes": z.string().min(1).max(500).describe("Optional prose describing why the redirect exists.").optional() }).strict()).describe("Topic-to-target redirects. Merge-by-`topic` under extends \u2014 child entry with same topic replaces parent's.").default([]) }).strict().default({}), "defaultLocale": z.string().regex(new RegExp("^[a-z]{2,3}(-[A-Z][a-zA-Z0-9]+)*(-[A-Z]{2})?(-[a-zA-Z0-9]+)*$")).describe("BCP-47 locale tag. Examples: 'en', 'en-US', 'fr-FR', 'pt-BR'.").optional(), "multilingual": z.array(z.string().regex(new RegExp("^[a-z]{2,3}(-[A-Z][a-zA-Z0-9]+)*(-[A-Z]{2})?(-[a-zA-Z0-9]+)*$"))).max(32).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Fallback locales. BCP-47. Append-and-dedupe under extends.").default([]), "relationships": z.array(z.object({ "persona": z.string().regex(new RegExp("^ws://personas/[^\\s]+$")).describe("ws:// ref to another persona/v1 manifest in the registry."), "kind": z.string().min(1).max(60).describe("Relationship kind. Conventional values: mentor-of, peer-of, mentee-of, rival-of, partner-of. Free-form to accept any author label."), "notes": z.string().min(1).max(1e3).describe("Optional prose describing the relationship.").optional() }).strict()).describe("Named relationships to other personas. Merge-by-`persona` under extends \u2014 child entry with same ref replaces parent's.").default([]), "identity": z.string().regex(new RegExp("^ws://identities/[^\\s]+$")).describe("Optional AIP-23 identity workspace ref. The persona's inner substance.").optional(), "appliesTo": z.array(z.string().regex(new RegExp("^(ws://(operators|skills|assemblies/[a-z0-9-]+|personas)/[^\\s]+|\\.\\./[^\\s]+)$")).describe("Cross-AIP ref. Operator (AIP-9), skill (AIP-3), assembly seat (AIP-24), or relative path.")).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Bind this persona to specific consumers. Local-only \u2014 not inherited under extends.").default([]), "tags": z.array(z.string().regex(new RegExp("^[a-z][a-z0-9-]*$"))).max(16).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: "All items must be unique!" }).describe("Catalog tags. Lowercase kebab-case. Append-and-dedupe under extends.").default([]), "metadata": z.record(z.string(), z.any()).describe("Vendor extensions, namespaced under <vendor>. Hosts MUST tolerate unknown keys; vendor namespaces MUST NOT override the meaning of fields defined in this AIP.").default({}) }).strict().describe("Validates the YAML frontmatter portion of an AIP-25 PERSONA.md manifest. Single-doc, no oneOf \u2014 every persona is the same shape. The body is markdown and not validated by this schema.");
|
|
10
|
+
var definePersona = createDoctype({
|
|
11
|
+
aip: 25,
|
|
12
|
+
name: "persona",
|
|
13
|
+
readIdentity: (def) => def.name,
|
|
14
|
+
validate(def) {
|
|
15
|
+
const result = personaFrontmatterSchema.safeParse(def);
|
|
16
|
+
if (!result.success) {
|
|
17
|
+
throw new Error(
|
|
18
|
+
`definePersona (AIP-25): ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
build(def) {
|
|
23
|
+
return { ...def };
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export { definePersona, personaFrontmatterSchema };
|
|
28
|
+
//# sourceMappingURL=chunk-TMV2PWI4.mjs.map
|
|
29
|
+
//# sourceMappingURL=chunk-TMV2PWI4.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema.ts","../src/define-persona.ts"],"names":[],"mappings":";;;;;;;;AAeO,IAAM,2BAA2B,CAAA,CAAE,MAAA,CAAO,EAAE,QAAA,EAAU,CAAA,CAAE,QAAQ,YAAY,CAAA,CAAE,SAAS,uEAAuE,CAAA,EAAG,QAAQ,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,IAAI,OAAO,2BAA2B,CAAC,EAAE,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,CAAS,yJAAyJ,GAAG,OAAA,EAAS,CAAA,CAAE,QAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,CAAS,8CAA8C,CAAA,EAAG,aAAA,EAAe,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAI,EAAE,QAAA,CAAS,2EAA2E,GAAG,SAAA,EAAW,CAAA,CAAE,QAAO,CAAE,KAAA,CAAM,IAAI,MAAA,CAAO,6CAA6C,CAAC,CAAA,CAAE,QAAA,CAAS,oEAAoE,CAAA,EAAG,SAAA,EAAW,EAAE,MAAA,EAAO,CAAE,MAAM,IAAI,MAAA,CAAO,kCAAkC,CAAC,CAAA,CAAE,SAAS,4FAA4F,CAAA,CAAE,UAAS,EAAG,QAAA,EAAU,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,QAAA,CAAS,wHAAwH,EAAE,QAAA,EAAS,EAAG,aAAa,CAAA,CAAE,MAAA,CAAO,EAAE,aAAA,EAAe,CAAA,CAAE,QAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA,CAAS,mFAAmF,CAAA,CAAE,QAAA,IAAY,YAAA,EAAc,CAAA,CAAE,QAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,QAAA,CAAS,uFAAuF,CAAA,CAAE,QAAA,IAAY,YAAA,EAAc,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,IAAI,OAAO,2BAA2B,CAAC,CAAC,CAAA,CAAE,IAAI,EAAE,CAAA,CAAE,OAAO,CAAC,GAAA,KAAQ,IAAI,KAAA,CAAM,CAAC,MAAM,CAAA,KAAM,GAAA,CAAI,QAAQ,IAAI,CAAA,IAAK,CAAC,CAAA,EAAG,EAAE,SAAS,2BAAA,EAA6B,EAAE,QAAA,CAAS,yIAAyI,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,KAAA,EAAO,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,EAAE,CAAA,CAAE,SAAS,+IAA+I,CAAA,CAAE,UAAS,EAAG,SAAA,EAAW,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAG,EAAE,QAAA,CAAS,sHAAsH,EAAE,QAAA,EAAS,EAAG,CAAA,CAAE,MAAA,GAAS,OAAA,CAAQ,EAAW,CAAA,EAAG,OAAA,EAAS,EAAE,MAAA,CAAO,EAAE,YAAY,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,CAAS,gJAA2I,EAAE,QAAA,EAAS,EAAG,oBAAoB,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAG,CAAC,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAM,CAAC,IAAA,EAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA,IAAK,CAAC,GAAG,EAAE,OAAA,EAAS,6BAA6B,CAAA,CAAE,SAAS,sGAAiG,CAAA,CAAE,QAAQ,EAAW,GAAG,UAAA,EAAY,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,EAAE,CAAC,CAAA,CAAE,IAAI,EAAE,CAAA,CAAE,OAAO,CAAC,GAAA,KAAQ,IAAI,KAAA,CAAM,CAAC,MAAM,CAAA,KAAM,GAAA,CAAI,QAAQ,IAAI,CAAA,IAAK,CAAC,CAAA,EAAG,EAAE,SAAS,2BAAA,EAA6B,EAAE,QAAA,CAAS,gGAAgG,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,WAAA,EAAa,EAAE,MAAA,EAAO,CAAE,KAAI,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA,CAAE,QAAA,CAAS,2EAA2E,CAAA,CAAE,QAAA,IAAY,YAAA,EAAc,CAAA,CAAE,KAAK,CAAC,OAAA,EAAQ,WAAU,UAAU,CAAC,EAAE,QAAA,CAAS,+GAA+G,EAAE,QAAA,EAAS,EAAG,WAAW,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAG,EAAE,QAAA,CAAS,wGAAmG,EAAE,QAAA,EAAS,EAAG,CAAA,CAAE,MAAA,GAAS,OAAA,CAAQ,EAAW,CAAA,EAAG,YAAA,EAAc,EAAE,MAAA,CAAO,EAAE,WAAW,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAO,CAAE,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAG,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAM,CAAC,IAAA,EAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA,IAAK,CAAC,GAAG,EAAE,OAAA,EAAS,6BAA6B,CAAA,CAAE,SAAS,kKAAkK,CAAA,CAAE,QAAQ,EAAW,GAAG,QAAA,EAAU,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,GAAG,CAAC,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,IAAI,KAAA,CAAM,CAAC,MAAM,CAAA,KAAM,GAAA,CAAI,QAAQ,IAAI,CAAA,IAAK,CAAC,CAAA,EAAG,EAAE,SAAS,2BAAA,EAA6B,EAAE,QAAA,CAAS,gFAAgF,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,WAAA,EAAa,EAAE,KAAA,CAAM,CAAA,CAAE,OAAO,EAAE,OAAA,EAAS,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,GAAG,CAAA,CAAE,SAAS,kCAAkC,CAAA,EAAG,MAAM,CAAA,CAAE,MAAA,EAAO,CAAE,KAAA,CAAM,IAAI,MAAA,CAAO,+DAA+D,CAAC,CAAA,CAAE,QAAA,CAAS,6EAA6E,CAAA,EAAG,OAAA,EAAS,EAAE,MAAA,EAAO,CAAE,IAAI,CAAC,CAAA,CAAE,IAAI,GAAG,CAAA,CAAE,SAAS,oDAAoD,CAAA,CAAE,UAAS,EAAG,EAAE,MAAA,EAAQ,EAAE,QAAA,CAAS,iHAA4G,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,EAAE,MAAA,EAAO,CAAE,QAAQ,EAAW,GAAG,eAAA,EAAiB,CAAA,CAAE,QAAO,CAAE,KAAA,CAAM,IAAI,MAAA,CAAO,+DAA+D,CAAC,CAAA,CAAE,QAAA,CAAS,+DAA+D,CAAA,CAAE,QAAA,IAAY,cAAA,EAAgB,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA,GAAS,KAAA,CAAM,IAAI,OAAO,+DAA+D,CAAC,CAAC,CAAA,CAAE,GAAA,CAAI,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,GAAA,KAAQ,GAAA,CAAI,MAAM,CAAC,IAAA,EAAM,MAAM,GAAA,CAAI,OAAA,CAAQ,IAAI,CAAA,IAAK,CAAC,GAAG,EAAE,OAAA,EAAS,6BAA6B,CAAA,CAAE,QAAA,CAAS,4DAA4D,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,eAAA,EAAiB,EAAE,KAAA,CAAM,CAAA,CAAE,OAAO,EAAE,SAAA,EAAW,EAAE,MAAA,EAAO,CAAE,MAAM,IAAI,MAAA,CAAO,yBAAyB,CAAC,CAAA,CAAE,SAAS,2DAA2D,CAAA,EAAG,QAAQ,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,GAAA,CAAI,EAAE,EAAE,QAAA,CAAS,oIAAoI,GAAG,OAAA,EAAS,CAAA,CAAE,QAAO,CAAE,GAAA,CAAI,CAAC,CAAA,CAAE,GAAA,CAAI,GAAI,CAAA,CAAE,SAAS,6CAA6C,CAAA,CAAE,UAAS,EAAG,EAAE,MAAA,EAAQ,EAAE,QAAA,CAAS,6HAAwH,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,UAAA,EAAY,EAAE,MAAA,EAAO,CAAE,MAAM,IAAI,MAAA,CAAO,2BAA2B,CAAC,CAAA,CAAE,SAAS,wEAAwE,CAAA,CAAE,UAAS,EAAG,WAAA,EAAa,EAAE,KAAA,CAAM,CAAA,CAAE,QAAO,CAAE,KAAA,CAAM,IAAI,MAAA,CAAO,mFAAmF,CAAC,CAAA,CAAE,QAAA,CAAS,2FAA2F,CAAC,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,KAAA,CAAM,CAAC,IAAA,EAAM,CAAA,KAAM,IAAI,OAAA,CAAQ,IAAI,KAAK,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,2BAAA,EAA6B,CAAA,CAAE,QAAA,CAAS,yFAAoF,CAAA,CAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,QAAQ,CAAA,CAAE,KAAA,CAAM,EAAE,MAAA,EAAO,CAAE,MAAM,IAAI,MAAA,CAAO,mBAAmB,CAAC,CAAC,EAAE,GAAA,CAAI,EAAE,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAA,CAAI,KAAA,CAAM,CAAC,IAAA,EAAM,CAAA,KAAM,IAAI,OAAA,CAAQ,IAAI,KAAK,CAAC,CAAA,EAAG,EAAE,OAAA,EAAS,2BAAA,EAA6B,CAAA,CAAE,QAAA,CAAS,sEAAsE,CAAA,CAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,YAAY,CAAA,CAAE,MAAA,CAAO,EAAE,MAAA,EAAO,EAAG,EAAE,GAAA,EAAK,EAAE,QAAA,CAAS,gKAAgK,EAAE,OAAA,CAAQ,EAAW,CAAA,EAAG,EAAE,MAAA,EAAO,CAAE,SAAS,8LAAyL;ACMppO,IAAM,gBAAgB,aAAA,CAAgD;AAAA,EAC3E,GAAA,EAAK,EAAA;AAAA,EACL,IAAA,EAAM,SAAA;AAAA,EACN,YAAA,EAAc,CAAC,GAAA,KAAQ,GAAA,CAAI,IAAA;AAAA,EAC3B,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,MAAA,GAAS,wBAAA,CAAyB,SAAA,CAAU,GAAG,CAAA;AACrD,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,CAAA,wBAAA,EAA2B,OAAO,KAAA,CAAM,MAAA,CACrC,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,OACf;AAAA,IACF;AAAA,EAIF,CAAA;AAAA,EACA,MAAM,GAAA,EAAK;AAKT,IAAA,OAAO,EAAE,GAAG,GAAA,EAAI;AAAA,EAClB;AACF,CAAC","file":"chunk-TMV2PWI4.mjs","sourcesContent":["/**\n * AIP-25 PERSONA.md frontmatter zod schema.\n *\n * Generated from `resources/aip-25/draft/PERSONA.schema.json` via\n * json-schema-to-zod. Imported by both `define-persona.ts` (TS path\n * validation) and `manifest/index.ts` (.md path validation) so every\n * field-level constraint runs in both authoring paths from a single\n * source of truth — re-run scaffold-aip to refresh after spec changes.\n *\n * Cross-field rules (if/then/allOf in JSON Schema) don't translate\n * cleanly and live in `define-persona.ts`'s `validate(def)` instead.\n */\n\nimport { z } from \"zod\"\n\nexport const personaFrontmatterSchema = z.object({ \"schema\": z.literal(\"persona/v1\").describe(\"Schema dispatch tag. MUST be 'persona/v1' for this version of AIP-25.\"), \"name\": z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*[a-z0-9]$\")).min(2).max(64).describe(\"Machine identifier. Lowercase, digits, dashes. Must start with a letter, end with a letter or digit. Unique within the registry that hosts the persona.\"), \"title\": z.string().min(1).max(120).describe(\"Human-readable display title, sentence case.\"), \"description\": z.string().min(1).max(2000).describe(\"One-paragraph elevator pitch. The persona's purpose, audience, and shape.\"), \"version\": z.string().regex(new RegExp(\"^\\\\d+\\\\.\\\\d+\\\\.\\\\d+(?:[-+][a-zA-Z0-9.-]+)?$\")).describe(\"Semver. Bump on breaking change to identity, voice, or boundaries.\"), \"extends\": z.string().regex(new RegExp(\"^(\\\\.{1,2}/)[^\\\\s]+PERSONA\\\\.md$\")).describe(\"Relative path to a parent PERSONA.md. Triggers composition. Path MUST end in 'PERSONA.md'.\").optional(), \"avatar\": z.string().min(1).describe(\"Public visual face. URL, data URI, or 'ws://avatars/<slug>' ref. Schema does not validate scheme; the loader resolves.\").optional(), \"backstory\": z.object({ \"oneLineHook\": z.string().min(1).max(280).describe(\"Punchy elevator hook. One sentence the catalog can show next to the persona name.\").optional(), \"background\": z.string().min(1).describe(\"Long-form lore prose, in markdown. The character's history, motivations, and context.\").optional(), \"archetypes\": z.array(z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*[a-z0-9]$\"))).max(12).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Categorical archetype labels. Lowercase kebab-case. Examples: mentor, craftsman, sentinel, trickster. The catalog MAY cluster by these.\").default([] as never), \"era\": z.string().min(1).max(80).describe(\"Free-form era label. Conventional values: 'contemporary', 'timeless', '<year>', '<year>-<year>', '<period>'. Free-form to accept any setting.\").optional(), \"setting\": z.string().min(1).max(120).describe(\"Free-form setting label. Conventional values: 'real-world', 'fictional-<universe>'. Free-form to accept any setting.\").optional() }).strict().default({} as never), \"voice\": z.object({ \"register\": z.string().min(1).max(80).describe(\"Voice register. Conventional values: warm-direct, playful, terse, academic. Custom values welcome — free-form to accept any author label.\").optional(), \"signaturePhrases\": z.array(z.string().min(1).max(200)).max(24).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Catchphrases the character uses. Append-and-dedupe under extends — lineage accumulates phrases.\").default([] as never), \"tonality\": z.array(z.string().min(1).max(60)).max(16).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Tonal adjectives. Examples: rigorous, encouraging, dry, warm. Append-and-dedupe under extends.\").default([] as never), \"formality\": z.number().int().gte(0).lte(10).describe(\"Formality scale, 0 (extremely casual) to 10 (extremely formal). Optional.\").optional(), \"emojiUsage\": z.enum([\"never\",\"sparing\",\"frequent\"]).describe(\"Emoji posture. 'never' = no emojis ever; 'sparing' = occasional, intentional; 'frequent' = part of the voice.\").optional(), \"signOff\": z.string().min(1).max(200).describe(\"Sign-off the persona uses to close messages. Examples: '—M.', 'Yours, Marcus', 'Until next time'.\").optional() }).strict().default({} as never), \"boundaries\": z.object({ \"refuses\": z.array(z.string().min(1).max(200)).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Topics the persona refuses outright. Free-form prose; the persona body SHOULD demonstrate the refusal posture in voice samples. Append-and-dedupe under extends.\").default([] as never), \"defers\": z.array(z.string().min(1).max(200)).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Topics the persona defers to a specialist on. Append-and-dedupe under extends.\").default([] as never), \"redirects\": z.array(z.object({ \"topic\": z.string().min(1).max(200).describe(\"The topic the persona redirects.\"), \"to\": z.string().regex(new RegExp(\"^(ws://(personas|operators|skills)/[^\\\\s]+|\\\\.{1,2}/[^\\\\s]+)$\")).describe(\"Redirect target. ws:// ref to a persona/operator/skill, or a relative path.\"), \"notes\": z.string().min(1).max(500).describe(\"Optional prose describing why the redirect exists.\").optional() }).strict()).describe(\"Topic-to-target redirects. Merge-by-`topic` under extends — child entry with same topic replaces parent's.\").default([] as never) }).strict().default({} as never), \"defaultLocale\": z.string().regex(new RegExp(\"^[a-z]{2,3}(-[A-Z][a-zA-Z0-9]+)*(-[A-Z]{2})?(-[a-zA-Z0-9]+)*$\")).describe(\"BCP-47 locale tag. Examples: 'en', 'en-US', 'fr-FR', 'pt-BR'.\").optional(), \"multilingual\": z.array(z.string().regex(new RegExp(\"^[a-z]{2,3}(-[A-Z][a-zA-Z0-9]+)*(-[A-Z]{2})?(-[a-zA-Z0-9]+)*$\"))).max(32).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Fallback locales. BCP-47. Append-and-dedupe under extends.\").default([] as never), \"relationships\": z.array(z.object({ \"persona\": z.string().regex(new RegExp(\"^ws://personas/[^\\\\s]+$\")).describe(\"ws:// ref to another persona/v1 manifest in the registry.\"), \"kind\": z.string().min(1).max(60).describe(\"Relationship kind. Conventional values: mentor-of, peer-of, mentee-of, rival-of, partner-of. Free-form to accept any author label.\"), \"notes\": z.string().min(1).max(1000).describe(\"Optional prose describing the relationship.\").optional() }).strict()).describe(\"Named relationships to other personas. Merge-by-`persona` under extends — child entry with same ref replaces parent's.\").default([] as never), \"identity\": z.string().regex(new RegExp(\"^ws://identities/[^\\\\s]+$\")).describe(\"Optional AIP-23 identity workspace ref. The persona's inner substance.\").optional(), \"appliesTo\": z.array(z.string().regex(new RegExp(\"^(ws://(operators|skills|assemblies/[a-z0-9-]+|personas)/[^\\\\s]+|\\\\.\\\\./[^\\\\s]+)$\")).describe(\"Cross-AIP ref. Operator (AIP-9), skill (AIP-3), assembly seat (AIP-24), or relative path.\")).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Bind this persona to specific consumers. Local-only — not inherited under extends.\").default([] as never), \"tags\": z.array(z.string().regex(new RegExp(\"^[a-z][a-z0-9-]*$\"))).max(16).refine((arr) => arr.every((item, i) => arr.indexOf(item) == i), { message: \"All items must be unique!\" }).describe(\"Catalog tags. Lowercase kebab-case. Append-and-dedupe under extends.\").default([] as never), \"metadata\": z.record(z.string(), z.any()).describe(\"Vendor extensions, namespaced under <vendor>. Hosts MUST tolerate unknown keys; vendor namespaces MUST NOT override the meaning of fields defined in this AIP.\").default({} as never) }).strict().describe(\"Validates the YAML frontmatter portion of an AIP-25 PERSONA.md manifest. Single-doc, no oneOf — every persona is the same shape. The body is markdown and not validated by this schema.\")\n\nexport type PersonaFrontmatter = z.infer<typeof personaFrontmatterSchema>\n","import { createDoctype } from \"@agentproto/define-doctype\"\nimport { personaFrontmatterSchema } from \"./schema.js\"\nimport type { PersonaDefinition, PersonaHandle } from \"./types.js\"\n\n/**\n * AIP-25 reference implementation of `definePersona`.\n *\n * Built on `createDoctype` so the cross-AIP invariants (id pattern,\n * description length, top-level freeze, \"definePersona (AIP-25): …\"\n * error prefix) run uniformly with every other AIP defineX.\n *\n * Field-level validation runs the schema-derived zod from\n * `./schema.ts` against the input. Same source of truth as the .md\n * path uses (`parsePersonaManifest`), so a malformed TS-authored\n * definition fails with the same diagnostic as a malformed manifest.\n * Cross-field rules go in `validate(def)` after the zod check.\n *\n * Identity / description extractors detected from the JSON Schema:\n * readIdentity: def.name\n * readDescription: def.description.\n */\nexport const definePersona = createDoctype<PersonaDefinition, PersonaHandle>({\n aip: 25,\n name: \"persona\",\n readIdentity: (def) => def.name,\n validate(def) {\n const result = personaFrontmatterSchema.safeParse(def)\n if (!result.success) {\n throw new Error(\n `definePersona (AIP-25): ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n // TODO: spec-25-specific cross-field rules (if/then/allOf in\n // the JSON Schema) — those don't translate to zod cleanly and\n // belong here. See @agentproto/operator's autonomy=gated rule.\n },\n build(def) {\n // Default build: spread the validated definition into a fresh object.\n // Hand-tune for nested freezing (Object.freeze on arrays/objects) and\n // for fields that need defaults applied — see @agentproto/operator\n // for a reference shape.\n return { ...def } as PersonaHandle\n },\n})\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { P as PersonaDefinition } from './types-CwL32wDG.js';
|
|
2
|
+
export { a as PersonaHandle } from './types-CwL32wDG.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AIP-25 reference implementation of `definePersona`.
|
|
6
|
+
*
|
|
7
|
+
* Built on `createDoctype` so the cross-AIP invariants (id pattern,
|
|
8
|
+
* description length, top-level freeze, "definePersona (AIP-25): …"
|
|
9
|
+
* error prefix) run uniformly with every other AIP defineX.
|
|
10
|
+
*
|
|
11
|
+
* Field-level validation runs the schema-derived zod from
|
|
12
|
+
* `./schema.ts` against the input. Same source of truth as the .md
|
|
13
|
+
* path uses (`parsePersonaManifest`), so a malformed TS-authored
|
|
14
|
+
* definition fails with the same diagnostic as a malformed manifest.
|
|
15
|
+
* Cross-field rules go in `validate(def)` after the zod check.
|
|
16
|
+
*
|
|
17
|
+
* Identity / description extractors detected from the JSON Schema:
|
|
18
|
+
* readIdentity: def.name
|
|
19
|
+
* readDescription: def.description.
|
|
20
|
+
*/
|
|
21
|
+
declare const definePersona: (def: PersonaDefinition) => Readonly<PersonaDefinition>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @agentproto/persona — AIP-25 PERSONA.md `definePersona` reference impl.
|
|
25
|
+
*
|
|
26
|
+
* A single-doc markdown + frontmatter format for portable agent personas — the public face, voice register, backstory, and boundaries of a character — sibling to AIP-23 IDENTITY (heavy substance) and building block of AIP-24 ASSEMBLY.
|
|
27
|
+
*
|
|
28
|
+
* Spec: https://agentproto.sh/docs/aip-25
|
|
29
|
+
*
|
|
30
|
+
* Authoring paths:
|
|
31
|
+
* - TS: `definePersona({...})` → `PersonaHandle`
|
|
32
|
+
* - MD: `parsePersonaManifest(src) → personaFromManifest({...})` → `PersonaHandle`
|
|
33
|
+
*/
|
|
34
|
+
declare const SPEC_NAME: "agentpersona/v1";
|
|
35
|
+
declare const SPEC_VERSION: "1.0.0-alpha";
|
|
36
|
+
|
|
37
|
+
export { PersonaDefinition, SPEC_NAME, SPEC_VERSION, definePersona };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { definePersona } from './chunk-TMV2PWI4.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @agentproto/persona v0.1.0-alpha
|
|
5
|
+
* AIP-25 PERSONA.md `definePersona` reference implementation.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
var SPEC_NAME = "agentpersona/v1";
|
|
10
|
+
var SPEC_VERSION = "1.0.0-alpha";
|
|
11
|
+
|
|
12
|
+
export { SPEC_NAME, SPEC_VERSION };
|
|
13
|
+
//# sourceMappingURL=index.mjs.map
|
|
14
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAYO,IAAM,SAAA,GAAY;AAClB,IAAM,YAAA,GAAe","file":"index.mjs","sourcesContent":["/**\n * @agentproto/persona — AIP-25 PERSONA.md `definePersona` reference impl.\n *\n * A single-doc markdown + frontmatter format for portable agent personas — the public face, voice register, backstory, and boundaries of a character — sibling to AIP-23 IDENTITY (heavy substance) and building block of AIP-24 ASSEMBLY.\n *\n * Spec: https://agentproto.sh/docs/aip-25\n *\n * Authoring paths:\n * - TS: `definePersona({...})` → `PersonaHandle`\n * - MD: `parsePersonaManifest(src) → personaFromManifest({...})` → `PersonaHandle`\n */\n\nexport const SPEC_NAME = \"agentpersona/v1\" as const\nexport const SPEC_VERSION = \"1.0.0-alpha\" as const\n\nexport { definePersona } from \"./define-persona.js\"\nexport type { PersonaDefinition, PersonaHandle } from \"./types.js\"\n"]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { a as PersonaHandle } from '../types-CwL32wDG.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AIP-25 PERSONA.md frontmatter zod schema.
|
|
6
|
+
*
|
|
7
|
+
* Generated from `resources/aip-25/draft/PERSONA.schema.json` via
|
|
8
|
+
* json-schema-to-zod. Imported by both `define-persona.ts` (TS path
|
|
9
|
+
* validation) and `manifest/index.ts` (.md path validation) so every
|
|
10
|
+
* field-level constraint runs in both authoring paths from a single
|
|
11
|
+
* source of truth — re-run scaffold-aip to refresh after spec changes.
|
|
12
|
+
*
|
|
13
|
+
* Cross-field rules (if/then/allOf in JSON Schema) don't translate
|
|
14
|
+
* cleanly and live in `define-persona.ts`'s `validate(def)` instead.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
declare const personaFrontmatterSchema: z.ZodObject<{
|
|
18
|
+
schema: z.ZodLiteral<"persona/v1">;
|
|
19
|
+
name: z.ZodString;
|
|
20
|
+
title: z.ZodString;
|
|
21
|
+
description: z.ZodString;
|
|
22
|
+
version: z.ZodString;
|
|
23
|
+
extends: z.ZodOptional<z.ZodString>;
|
|
24
|
+
avatar: z.ZodOptional<z.ZodString>;
|
|
25
|
+
backstory: z.ZodDefault<z.ZodObject<{
|
|
26
|
+
oneLineHook: z.ZodOptional<z.ZodString>;
|
|
27
|
+
background: z.ZodOptional<z.ZodString>;
|
|
28
|
+
archetypes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
29
|
+
era: z.ZodOptional<z.ZodString>;
|
|
30
|
+
setting: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strict>>;
|
|
32
|
+
voice: z.ZodDefault<z.ZodObject<{
|
|
33
|
+
register: z.ZodOptional<z.ZodString>;
|
|
34
|
+
signaturePhrases: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
35
|
+
tonality: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
36
|
+
formality: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
emojiUsage: z.ZodOptional<z.ZodEnum<{
|
|
38
|
+
never: "never";
|
|
39
|
+
sparing: "sparing";
|
|
40
|
+
frequent: "frequent";
|
|
41
|
+
}>>;
|
|
42
|
+
signOff: z.ZodOptional<z.ZodString>;
|
|
43
|
+
}, z.core.$strict>>;
|
|
44
|
+
boundaries: z.ZodDefault<z.ZodObject<{
|
|
45
|
+
refuses: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
46
|
+
defers: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
47
|
+
redirects: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
48
|
+
topic: z.ZodString;
|
|
49
|
+
to: z.ZodString;
|
|
50
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
51
|
+
}, z.core.$strict>>>;
|
|
52
|
+
}, z.core.$strict>>;
|
|
53
|
+
defaultLocale: z.ZodOptional<z.ZodString>;
|
|
54
|
+
multilingual: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
55
|
+
relationships: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
56
|
+
persona: z.ZodString;
|
|
57
|
+
kind: z.ZodString;
|
|
58
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
59
|
+
}, z.core.$strict>>>;
|
|
60
|
+
identity: z.ZodOptional<z.ZodString>;
|
|
61
|
+
appliesTo: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
62
|
+
tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
63
|
+
metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodAny>>;
|
|
64
|
+
}, z.core.$strict>;
|
|
65
|
+
type PersonaFrontmatter = z.infer<typeof personaFrontmatterSchema>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* AIP-25 PERSONA.md sidecar parser + manifest-to-handle constructor.
|
|
69
|
+
*
|
|
70
|
+
* Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:
|
|
71
|
+
* the .md provides metadata; the TS module supplies any spec-specific
|
|
72
|
+
* runtime bits (schemas, execute bodies, …) that can't live in
|
|
73
|
+
* frontmatter. Both inputs end up in `definePersona` so the cross-AIP
|
|
74
|
+
* invariants run uniformly.
|
|
75
|
+
*
|
|
76
|
+
*
|
|
77
|
+
* The frontmatter zod schema below was generated from
|
|
78
|
+
* `resources/aip-25/draft/PERSONA.schema.json` via json-schema-to-zod.
|
|
79
|
+
* Re-run scaffold-aip to refresh after spec changes (or hand-tune
|
|
80
|
+
* any constraint the converter doesn't capture cleanly).
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
interface PersonaManifest {
|
|
84
|
+
frontmatter: PersonaFrontmatter;
|
|
85
|
+
body: string;
|
|
86
|
+
}
|
|
87
|
+
declare function parsePersonaManifest(source: string): PersonaManifest;
|
|
88
|
+
declare function personaFromManifest(manifest: PersonaManifest): PersonaHandle;
|
|
89
|
+
|
|
90
|
+
export { type PersonaFrontmatter, type PersonaManifest, parsePersonaManifest, personaFromManifest, personaFrontmatterSchema };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { personaFrontmatterSchema, definePersona } from '../chunk-TMV2PWI4.mjs';
|
|
2
|
+
export { personaFrontmatterSchema } from '../chunk-TMV2PWI4.mjs';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @agentproto/persona v0.1.0-alpha
|
|
7
|
+
* AIP-25 PERSONA.md `definePersona` reference implementation.
|
|
8
|
+
*/
|
|
9
|
+
function parsePersonaManifest(source) {
|
|
10
|
+
const parsed = matter(source);
|
|
11
|
+
if (Object.keys(parsed.data).length === 0) {
|
|
12
|
+
throw new Error("parsePersonaManifest: missing or empty frontmatter");
|
|
13
|
+
}
|
|
14
|
+
const result = personaFrontmatterSchema.safeParse(parsed.data);
|
|
15
|
+
if (!result.success) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`parsePersonaManifest: invalid frontmatter \u2014 ${result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")}`
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return { frontmatter: result.data, body: parsed.content };
|
|
21
|
+
}
|
|
22
|
+
function personaFromManifest(manifest) {
|
|
23
|
+
return definePersona(manifest.frontmatter);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { parsePersonaManifest, personaFromManifest };
|
|
27
|
+
//# sourceMappingURL=index.mjs.map
|
|
28
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/manifest/index.ts"],"names":[],"mappings":";;;;;;;;AA8BO,SAAS,qBAAqB,MAAA,EAAiC;AACpE,EAAA,MAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AAC5B,EAAA,IAAI,OAAO,IAAA,CAAK,MAAA,CAAO,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,MAAM,oDAAoD,CAAA;AAAA,EACtE;AACA,EAAA,MAAM,MAAA,GAAS,wBAAA,CAAyB,SAAA,CAAU,MAAA,CAAO,IAAI,CAAA;AAC7D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iDAAA,EAA+C,OAAO,KAAA,CAAM,MAAA,CACzD,IAAI,CAAC,CAAA,KAAM,GAAG,CAAA,CAAE,IAAA,CAAK,KAAK,GAAG,CAAC,KAAK,CAAA,CAAE,OAAO,EAAE,CAAA,CAC9C,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,KACf;AAAA,EACF;AACA,EAAA,OAAO,EAAE,WAAA,EAAa,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,OAAO,OAAA,EAAQ;AAC1D;AAEO,SAAS,oBAAoB,QAAA,EAA0C;AAK5E,EAAA,OAAO,aAAA,CAAc,SAAS,WAA2C,CAAA;AAC3E","file":"index.mjs","sourcesContent":["/**\n * AIP-25 PERSONA.md sidecar parser + manifest-to-handle constructor.\n *\n * Mirror of `@agentproto/tool/manifest` and `@agentproto/driver/manifest`:\n * the .md provides metadata; the TS module supplies any spec-specific\n * runtime bits (schemas, execute bodies, …) that can't live in\n * frontmatter. Both inputs end up in `definePersona` so the cross-AIP\n * invariants run uniformly.\n *\n *\n * The frontmatter zod schema below was generated from\n * `resources/aip-25/draft/PERSONA.schema.json` via json-schema-to-zod.\n * Re-run scaffold-aip to refresh after spec changes (or hand-tune\n * any constraint the converter doesn't capture cleanly).\n */\n\nimport matter from \"gray-matter\"\nimport { personaFrontmatterSchema, type PersonaFrontmatter } from \"../schema.js\"\nimport { definePersona } from \"../define-persona.js\"\nimport type { PersonaDefinition, PersonaHandle } from \"../types.js\"\n\n// Re-export so consumers can import the schema + inferred type either\n// from \"@@agentproto/persona/manifest\" or directly from \"@@agentproto/persona/schema\".\nexport { personaFrontmatterSchema, type PersonaFrontmatter }\n\nexport interface PersonaManifest {\n frontmatter: PersonaFrontmatter\n body: string\n}\n\nexport function parsePersonaManifest(source: string): PersonaManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parsePersonaManifest: missing or empty frontmatter\")\n }\n const result = personaFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parsePersonaManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\nexport function personaFromManifest(manifest: PersonaManifest): PersonaHandle {\n // The zod-validated frontmatter is structurally compatible with\n // PersonaDefinition; the cast pins the typing once the manifest\n // schema and the TS interface diverge (e.g. handle has frozen fields\n // a literal config doesn't carry yet).\n return definePersona(manifest.frontmatter as unknown as PersonaDefinition)\n}\n"]}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIP-25 PersonaDefinition + PersonaHandle.
|
|
3
|
+
*
|
|
4
|
+
* `PersonaDefinition` was generated from
|
|
5
|
+
* `resources/aip-25/draft/PERSONA.schema.json` via json-schema-to-typescript.
|
|
6
|
+
* `PersonaHandle` is the readonly view of the same shape; tighten it
|
|
7
|
+
* by hand for fields that get defaults applied in build().
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Validates the YAML frontmatter portion of an AIP-25 PERSONA.md manifest. Single-doc, no oneOf — every persona is the same shape. The body is markdown and not validated by this schema.
|
|
11
|
+
*/
|
|
12
|
+
interface PersonaDefinition {
|
|
13
|
+
/**
|
|
14
|
+
* Schema dispatch tag. MUST be 'persona/v1' for this version of AIP-25.
|
|
15
|
+
*/
|
|
16
|
+
schema: "persona/v1";
|
|
17
|
+
/**
|
|
18
|
+
* Machine identifier. Lowercase, digits, dashes. Must start with a letter, end with a letter or digit. Unique within the registry that hosts the persona.
|
|
19
|
+
*/
|
|
20
|
+
name: string;
|
|
21
|
+
/**
|
|
22
|
+
* Human-readable display title, sentence case.
|
|
23
|
+
*/
|
|
24
|
+
title: string;
|
|
25
|
+
/**
|
|
26
|
+
* One-paragraph elevator pitch. The persona's purpose, audience, and shape.
|
|
27
|
+
*/
|
|
28
|
+
description: string;
|
|
29
|
+
/**
|
|
30
|
+
* Semver. Bump on breaking change to identity, voice, or boundaries.
|
|
31
|
+
*/
|
|
32
|
+
version: string;
|
|
33
|
+
/**
|
|
34
|
+
* Relative path to a parent PERSONA.md. Triggers composition. Path MUST end in 'PERSONA.md'.
|
|
35
|
+
*/
|
|
36
|
+
extends?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Public visual face. URL, data URI, or 'ws://avatars/<slug>' ref. Schema does not validate scheme; the loader resolves.
|
|
39
|
+
*/
|
|
40
|
+
avatar?: string;
|
|
41
|
+
backstory?: {
|
|
42
|
+
/**
|
|
43
|
+
* Punchy elevator hook. One sentence the catalog can show next to the persona name.
|
|
44
|
+
*/
|
|
45
|
+
oneLineHook?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Long-form lore prose, in markdown. The character's history, motivations, and context.
|
|
48
|
+
*/
|
|
49
|
+
background?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Categorical archetype labels. Lowercase kebab-case. Examples: mentor, craftsman, sentinel, trickster. The catalog MAY cluster by these.
|
|
52
|
+
*
|
|
53
|
+
* @maxItems 12
|
|
54
|
+
*/
|
|
55
|
+
archetypes?: [] | [string] | [string, string] | [string, string, string] | [string, string, string, string] | [string, string, string, string, string] | [string, string, string, string, string, string] | [string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string];
|
|
56
|
+
/**
|
|
57
|
+
* Free-form era label. Conventional values: 'contemporary', 'timeless', '<year>', '<year>-<year>', '<period>'. Free-form to accept any setting.
|
|
58
|
+
*/
|
|
59
|
+
era?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Free-form setting label. Conventional values: 'real-world', 'fictional-<universe>'. Free-form to accept any setting.
|
|
62
|
+
*/
|
|
63
|
+
setting?: string;
|
|
64
|
+
};
|
|
65
|
+
voice?: {
|
|
66
|
+
/**
|
|
67
|
+
* Voice register. Conventional values: warm-direct, playful, terse, academic. Custom values welcome — free-form to accept any author label.
|
|
68
|
+
*/
|
|
69
|
+
register?: string;
|
|
70
|
+
/**
|
|
71
|
+
* Catchphrases the character uses. Append-and-dedupe under extends — lineage accumulates phrases.
|
|
72
|
+
*
|
|
73
|
+
* @maxItems 24
|
|
74
|
+
*/
|
|
75
|
+
signaturePhrases?: string[];
|
|
76
|
+
/**
|
|
77
|
+
* Tonal adjectives. Examples: rigorous, encouraging, dry, warm. Append-and-dedupe under extends.
|
|
78
|
+
*
|
|
79
|
+
* @maxItems 16
|
|
80
|
+
*/
|
|
81
|
+
tonality?: [] | [string] | [string, string] | [string, string, string] | [string, string, string, string] | [string, string, string, string, string] | [string, string, string, string, string, string] | [string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string, string, string] | [
|
|
82
|
+
string,
|
|
83
|
+
string,
|
|
84
|
+
string,
|
|
85
|
+
string,
|
|
86
|
+
string,
|
|
87
|
+
string,
|
|
88
|
+
string,
|
|
89
|
+
string,
|
|
90
|
+
string,
|
|
91
|
+
string,
|
|
92
|
+
string,
|
|
93
|
+
string,
|
|
94
|
+
string,
|
|
95
|
+
string,
|
|
96
|
+
string
|
|
97
|
+
] | [
|
|
98
|
+
string,
|
|
99
|
+
string,
|
|
100
|
+
string,
|
|
101
|
+
string,
|
|
102
|
+
string,
|
|
103
|
+
string,
|
|
104
|
+
string,
|
|
105
|
+
string,
|
|
106
|
+
string,
|
|
107
|
+
string,
|
|
108
|
+
string,
|
|
109
|
+
string,
|
|
110
|
+
string,
|
|
111
|
+
string,
|
|
112
|
+
string,
|
|
113
|
+
string
|
|
114
|
+
];
|
|
115
|
+
/**
|
|
116
|
+
* Formality scale, 0 (extremely casual) to 10 (extremely formal). Optional.
|
|
117
|
+
*/
|
|
118
|
+
formality?: number;
|
|
119
|
+
/**
|
|
120
|
+
* Emoji posture. 'never' = no emojis ever; 'sparing' = occasional, intentional; 'frequent' = part of the voice.
|
|
121
|
+
*/
|
|
122
|
+
emojiUsage?: "never" | "sparing" | "frequent";
|
|
123
|
+
/**
|
|
124
|
+
* Sign-off the persona uses to close messages. Examples: '—M.', 'Yours, Marcus', 'Until next time'.
|
|
125
|
+
*/
|
|
126
|
+
signOff?: string;
|
|
127
|
+
};
|
|
128
|
+
boundaries?: {
|
|
129
|
+
/**
|
|
130
|
+
* Topics the persona refuses outright. Free-form prose; the persona body SHOULD demonstrate the refusal posture in voice samples. Append-and-dedupe under extends.
|
|
131
|
+
*/
|
|
132
|
+
refuses?: string[];
|
|
133
|
+
/**
|
|
134
|
+
* Topics the persona defers to a specialist on. Append-and-dedupe under extends.
|
|
135
|
+
*/
|
|
136
|
+
defers?: string[];
|
|
137
|
+
/**
|
|
138
|
+
* Topic-to-target redirects. Merge-by-`topic` under extends — child entry with same topic replaces parent's.
|
|
139
|
+
*/
|
|
140
|
+
redirects?: {
|
|
141
|
+
/**
|
|
142
|
+
* The topic the persona redirects.
|
|
143
|
+
*/
|
|
144
|
+
topic: string;
|
|
145
|
+
/**
|
|
146
|
+
* Redirect target. ws:// ref to a persona/operator/skill, or a relative path.
|
|
147
|
+
*/
|
|
148
|
+
to: string;
|
|
149
|
+
/**
|
|
150
|
+
* Optional prose describing why the redirect exists.
|
|
151
|
+
*/
|
|
152
|
+
notes?: string;
|
|
153
|
+
}[];
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* BCP-47 locale tag. Examples: 'en', 'en-US', 'fr-FR', 'pt-BR'.
|
|
157
|
+
*/
|
|
158
|
+
defaultLocale?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Fallback locales. BCP-47. Append-and-dedupe under extends.
|
|
161
|
+
*
|
|
162
|
+
* @maxItems 32
|
|
163
|
+
*/
|
|
164
|
+
multilingual?: string[];
|
|
165
|
+
/**
|
|
166
|
+
* Named relationships to other personas. Merge-by-`persona` under extends — child entry with same ref replaces parent's.
|
|
167
|
+
*/
|
|
168
|
+
relationships?: {
|
|
169
|
+
/**
|
|
170
|
+
* ws:// ref to another persona/v1 manifest in the registry.
|
|
171
|
+
*/
|
|
172
|
+
persona: string;
|
|
173
|
+
/**
|
|
174
|
+
* Relationship kind. Conventional values: mentor-of, peer-of, mentee-of, rival-of, partner-of. Free-form to accept any author label.
|
|
175
|
+
*/
|
|
176
|
+
kind: string;
|
|
177
|
+
/**
|
|
178
|
+
* Optional prose describing the relationship.
|
|
179
|
+
*/
|
|
180
|
+
notes?: string;
|
|
181
|
+
}[];
|
|
182
|
+
/**
|
|
183
|
+
* Optional AIP-23 identity workspace ref. The persona's inner substance.
|
|
184
|
+
*/
|
|
185
|
+
identity?: string;
|
|
186
|
+
/**
|
|
187
|
+
* Bind this persona to specific consumers. Local-only — not inherited under extends.
|
|
188
|
+
*/
|
|
189
|
+
appliesTo?: string[];
|
|
190
|
+
/**
|
|
191
|
+
* Catalog tags. Lowercase kebab-case. Append-and-dedupe under extends.
|
|
192
|
+
*
|
|
193
|
+
* @maxItems 16
|
|
194
|
+
*/
|
|
195
|
+
tags?: [] | [string] | [string, string] | [string, string, string] | [string, string, string, string] | [string, string, string, string, string] | [string, string, string, string, string, string] | [string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string, string] | [string, string, string, string, string, string, string, string, string, string, string, string, string, string] | [
|
|
196
|
+
string,
|
|
197
|
+
string,
|
|
198
|
+
string,
|
|
199
|
+
string,
|
|
200
|
+
string,
|
|
201
|
+
string,
|
|
202
|
+
string,
|
|
203
|
+
string,
|
|
204
|
+
string,
|
|
205
|
+
string,
|
|
206
|
+
string,
|
|
207
|
+
string,
|
|
208
|
+
string,
|
|
209
|
+
string,
|
|
210
|
+
string
|
|
211
|
+
] | [
|
|
212
|
+
string,
|
|
213
|
+
string,
|
|
214
|
+
string,
|
|
215
|
+
string,
|
|
216
|
+
string,
|
|
217
|
+
string,
|
|
218
|
+
string,
|
|
219
|
+
string,
|
|
220
|
+
string,
|
|
221
|
+
string,
|
|
222
|
+
string,
|
|
223
|
+
string,
|
|
224
|
+
string,
|
|
225
|
+
string,
|
|
226
|
+
string,
|
|
227
|
+
string
|
|
228
|
+
];
|
|
229
|
+
/**
|
|
230
|
+
* Vendor extensions, namespaced under <vendor>. Hosts MUST tolerate unknown keys; vendor namespaces MUST NOT override the meaning of fields defined in this AIP.
|
|
231
|
+
*/
|
|
232
|
+
metadata?: {
|
|
233
|
+
[k: string]: unknown;
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
type PersonaHandle = Readonly<PersonaDefinition>;
|
|
237
|
+
|
|
238
|
+
export type { PersonaDefinition as P, PersonaHandle as a };
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentproto/persona",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "@agentproto/persona — AIP-25 PERSONA.md reference implementation. A single-doc markdown + frontmatter format for portable agent personas — the public face, voice register, backstory, and boundaries of a character — sibling to AIP-23 IDENTITY (heavy substance) and building block of AIP-24 ASSEMBLY.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentproto",
|
|
7
|
+
"aip-25",
|
|
8
|
+
"persona",
|
|
9
|
+
"definePersona",
|
|
10
|
+
"open-standard",
|
|
11
|
+
"agentic"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://agentproto.sh/docs/aip-25",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/agentproto/ts",
|
|
17
|
+
"directory": "packages/persona"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/agentproto/ts/issues"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "dist/index.mjs",
|
|
25
|
+
"module": "dist/index.mjs",
|
|
26
|
+
"types": "dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"default": "./dist/index.mjs"
|
|
32
|
+
},
|
|
33
|
+
"./manifest": {
|
|
34
|
+
"types": "./dist/manifest/index.d.ts",
|
|
35
|
+
"import": "./dist/manifest/index.mjs",
|
|
36
|
+
"default": "./dist/manifest/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"gray-matter": "^4.0.3",
|
|
50
|
+
"zod": "^4.4.3",
|
|
51
|
+
"@agentproto/define-doctype": "0.1.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.6.2",
|
|
55
|
+
"tsup": "^8.5.1",
|
|
56
|
+
"typescript": "^5.9.3",
|
|
57
|
+
"vitest": "^3.2.4",
|
|
58
|
+
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"dev": "tsup --watch",
|
|
62
|
+
"build": "tsup",
|
|
63
|
+
"clean": "rm -rf dist",
|
|
64
|
+
"check-types": "tsc --noEmit",
|
|
65
|
+
"test": "vitest run --passWithNoTests",
|
|
66
|
+
"test:watch": "vitest"
|
|
67
|
+
}
|
|
68
|
+
}
|