@reallyartificial/grain 0.2.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/README.md ADDED
@@ -0,0 +1,138 @@
1
+ # @reallyartificial/grain
2
+
3
+ TypeScript SDK for [Grain](https://github.com/anthropics/grain) — a structured data format for describing AI agents.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @reallyartificial/grain
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```typescript
14
+ import { Grain } from "@reallyartificial/grain"
15
+
16
+ // Load from file
17
+ const agent = Grain.load("./my-agent.agent.yaml")
18
+
19
+ // Generate system prompt
20
+ const prompt = agent.toPrompt()
21
+
22
+ // Channel-specific prompt
23
+ const slackPrompt = agent.toPrompt("slack")
24
+
25
+ // Clean YAML for LLM consumption (strips metadata)
26
+ const yaml = agent.toString()
27
+ ```
28
+
29
+ ### Create programmatically
30
+
31
+ ```typescript
32
+ import { Grain, Presets } from "@reallyartificial/grain"
33
+
34
+ const agent = Grain.create("my-bot", { name: "My Bot", description: "Does helpful things" })
35
+ .setPersonality("warmth", 0.8)
36
+ .setPersonality("confidence", 0.9)
37
+ .addRule({
38
+ id: "always-greet",
39
+ condition: { type: "always" },
40
+ action: { type: "respond-with-style", style: { warmth: 0.9 } },
41
+ })
42
+ .addBoundary({
43
+ description: "Never share internal data",
44
+ category: "data",
45
+ enforcement: "hard",
46
+ onViolation: "refuse",
47
+ })
48
+ .addTool({ id: "search", usage: "Search knowledge base" })
49
+
50
+ console.log(agent.toPrompt())
51
+ ```
52
+
53
+ ### Immutable mutations
54
+
55
+ Every method returns a new `Grain` — the original is never modified.
56
+
57
+ ```typescript
58
+ const base = Grain.create("my-bot")
59
+ const withRule = base.addRule({ id: "r1", condition: { type: "always" }, action: { type: "require-confirmation" } })
60
+
61
+ console.log(base.rules.length) // 0
62
+ console.log(withRule.rules.length) // 1
63
+ ```
64
+
65
+ ### Merge and diff
66
+
67
+ ```typescript
68
+ const a = Grain.create("bot-a").setPersonality("warmth", 0.3)
69
+ const b = Grain.create("bot-b").setPersonality("warmth", 0.9)
70
+
71
+ const merged = a.merge(b) // b wins on conflicts
72
+ const changes = a.diff(b) // { "voice.personality.warmth": { before: 0.3, after: 0.9 } }
73
+ ```
74
+
75
+ ## CLI
76
+
77
+ ```bash
78
+ npx @reallyartificial/grain validate my-agent.agent.yaml
79
+ npx @reallyartificial/grain generate my-agent.agent.yaml --channel slack
80
+ npx @reallyartificial/grain info my-agent.agent.yaml
81
+ ```
82
+
83
+ ## Minimal Spec
84
+
85
+ ```yaml
86
+ specVersion: "1.0"
87
+ id: my-bot
88
+ version: 1.0.0
89
+ meta:
90
+ name: My Bot
91
+ description: Does helpful things
92
+ ```
93
+
94
+ ## API
95
+
96
+ ### Constructors
97
+ - `Grain.create(id, opts?)` — Create with defaults
98
+ - `Grain.from(yamlOrJson)` — Parse from string
99
+ - `Grain.load(filePath)` — Load from file
100
+ - `Grain.of(spec)` — Wrap a plain AgentSpec object
101
+
102
+ ### Mutations (return new Grain)
103
+ - `addRule(rule)` / `removeRule(id)` / `addRules(rules)`
104
+ - `addBoundary(b)` / `removeBoundary(desc)` / `addBoundaries(bs)`
105
+ - `addTool(t)` / `removeTool(name)` / `addTools(ts)`
106
+ - `addSkill(s)` / `removeSkill(name)` / `addSkills(ss)`
107
+ - `addExpertise(domain, proficiency)` / `removeExpertise(domain)`
108
+ - `setPersonality(dim, value)` — validates 0-1 range
109
+ - `set(path, value)` / `get(path)` — generic deep access
110
+ - `merge(other)` — deep merge, other wins
111
+
112
+ ### Accessors
113
+ - `id`, `name`, `version` — scalars
114
+ - `personality`, `rules`, `boundaries`, `tools`, `skills`, `expertise` — copies
115
+ - `data` — raw frozen AgentSpec
116
+ - `isValid` — boolean
117
+
118
+ ### Queries
119
+ - `hasRule(id)`, `hasTool(name)`, `hasSkill(name)`
120
+
121
+ ### Output
122
+ - `toString(channel?)` — Clean YAML for LLMs (strips metadata)
123
+ - `toPrompt(channel?)` — Natural language system prompt
124
+ - `toYAML()` — Full YAML with all metadata
125
+ - `toJSON()` — Full JSON
126
+ - `validate()` — Returns `ValidationError[]`
127
+ - `diff(other)` — Structural diff
128
+
129
+ ### Presets
130
+ - `Presets.personality.professional`
131
+ - `Presets.personality.friendly`
132
+ - `Presets.personality.expert`
133
+ - `Presets.personality.creative`
134
+ - `Presets.personality.executor`
135
+
136
+ ## License
137
+
138
+ MIT