@wutiankai/npc-dialogue 1.0.0-alpha.1
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 +226 -0
- package/dist/index.cjs +883 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +323 -0
- package/dist/index.d.ts +323 -0
- package/dist/index.js +847 -0
- package/dist/index.js.map +1 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# @wutiankai/npc-dialogue
|
|
2
|
+
|
|
3
|
+
AI-driven NPC dialogue engine with gate-based secret revelation and bilingual keyword matching. Designed for mystery and investigation games.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **AI NPC Dialogue** — Free-form conversations powered by any OpenAI-compatible provider
|
|
8
|
+
- **Gate Review System** — NPCs have gated secrets that unlock based on player input relevance
|
|
9
|
+
- **Bilingual Keyword Matching** — Cross-language keyword expansion (e.g. English → Chinese)
|
|
10
|
+
- **Trust Levels** — 3-tier trust system (0/1/2) that gates NPC knowledge access
|
|
11
|
+
- **Provider Abstraction** — Pluggable AI provider interface (OpenAI, passthrough, custom)
|
|
12
|
+
- **Audit Log** — Full dialogue pipeline logging for debugging
|
|
13
|
+
- **Zero Runtime Dependencies** — Lightweight, type-safe, ESM + CJS
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @wutiankai/npc-dialogue
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import {
|
|
23
|
+
DialogueEngine,
|
|
24
|
+
PassthroughProvider,
|
|
25
|
+
type NpcScript,
|
|
26
|
+
} from "@wutiankai/npc-dialogue";
|
|
27
|
+
|
|
28
|
+
// Define an NPC
|
|
29
|
+
const npc: NpcScript = {
|
|
30
|
+
npcId: "butler",
|
|
31
|
+
name: "James",
|
|
32
|
+
role: "The Butler",
|
|
33
|
+
worldSetting: "a murder mystery set in a Victorian manor",
|
|
34
|
+
persona: {
|
|
35
|
+
personality: "Formal, observant, slightly nervous",
|
|
36
|
+
background: "Served the family for 30 years",
|
|
37
|
+
speechPatterns: "Precise, avoids contractions",
|
|
38
|
+
},
|
|
39
|
+
publicKnowledge: [
|
|
40
|
+
{ id: "k1", topic: "house layout", content: "Knows every room" },
|
|
41
|
+
],
|
|
42
|
+
privateKnowledge: [
|
|
43
|
+
{ id: "k2", topic: "the master's will", content: "Saw the new will before the fire" },
|
|
44
|
+
],
|
|
45
|
+
gatedSecrets: [
|
|
46
|
+
{
|
|
47
|
+
id: "secret_will",
|
|
48
|
+
topicGateId: "topic_will",
|
|
49
|
+
description: "Knows about the changed will",
|
|
50
|
+
revealConditions: "player asks about the will with trust >= 1",
|
|
51
|
+
reactionWhenPressed: "becomes defensive",
|
|
52
|
+
triggerKeywords: ["will", "inheritance"],
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
ignorance: ["doesn't understand modern technology"],
|
|
56
|
+
relationships: [],
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Create engine
|
|
60
|
+
const provider = new PassthroughProvider();
|
|
61
|
+
const engine = new DialogueEngine(provider, {
|
|
62
|
+
lang: "en",
|
|
63
|
+
failOpen: true,
|
|
64
|
+
maxConversationHistory: 10,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
await engine.initialize();
|
|
68
|
+
|
|
69
|
+
// Talk to NPC
|
|
70
|
+
const result = await engine.dialogue({
|
|
71
|
+
npcScript: npc,
|
|
72
|
+
playerInput: "Tell me about the will",
|
|
73
|
+
context: {
|
|
74
|
+
currentRoom: "Study",
|
|
75
|
+
currentTurn: 3,
|
|
76
|
+
turnsRemaining: 5,
|
|
77
|
+
playerInventory: [],
|
|
78
|
+
discoveredClues: [],
|
|
79
|
+
currentTrust: 1,
|
|
80
|
+
exhaustedTopicGateIds: [],
|
|
81
|
+
recentExchanges: [],
|
|
82
|
+
validTopicGateIds: ["topic_will"],
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
console.log(result.dialogue);
|
|
87
|
+
console.log("Gate triggered:", result.candidateGateId);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Core Concepts
|
|
91
|
+
|
|
92
|
+
### NpcScript
|
|
93
|
+
|
|
94
|
+
The complete character definition for an NPC:
|
|
95
|
+
|
|
96
|
+
| Field | Description |
|
|
97
|
+
|-------|-------------|
|
|
98
|
+
| `persona` | Personality, background, speech patterns |
|
|
99
|
+
| `publicKnowledge` | Information available at trust 0 |
|
|
100
|
+
| `privateKnowledge` | Information available at trust >= 1 |
|
|
101
|
+
| `gatedSecrets` | Secrets that unlock through gate review |
|
|
102
|
+
| `worldSetting` | Optional genre/world framing for the AI prompt |
|
|
103
|
+
|
|
104
|
+
### Gate Review
|
|
105
|
+
|
|
106
|
+
Gated secrets have trigger keywords. When a player input matches keywords, the AI proposes a gate trigger. The `reviewGateTrigger` function validates:
|
|
107
|
+
|
|
108
|
+
1. **Keyword relevance** — Does the player's input relate to the secret's keywords?
|
|
109
|
+
2. **Evidence quality** — Did the AI provide supporting evidence?
|
|
110
|
+
3. **Confidence level** — Is the AI confident enough?
|
|
111
|
+
|
|
112
|
+
### Trust Levels
|
|
113
|
+
|
|
114
|
+
- **0** — Stranger: only public knowledge
|
|
115
|
+
- **1** — Acquaintance: private knowledge + softer gate thresholds
|
|
116
|
+
- **2** — Trusted: full access, deeper secrets
|
|
117
|
+
|
|
118
|
+
### Bilingual Keyword Matching
|
|
119
|
+
|
|
120
|
+
Pass a keyword map to expand English terms with Chinese equivalents:
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const keywordMap = {
|
|
124
|
+
"will": ["遗嘱"],
|
|
125
|
+
"key": ["钥匙"],
|
|
126
|
+
"garden": ["花园"],
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const engine = new DialogueEngine(provider, {
|
|
130
|
+
lang: "zh",
|
|
131
|
+
bilingualKeywordMap: keywordMap,
|
|
132
|
+
});
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## API Reference
|
|
136
|
+
|
|
137
|
+
### Classes
|
|
138
|
+
|
|
139
|
+
#### `DialogueEngine`
|
|
140
|
+
|
|
141
|
+
Main dialogue engine. Handles NPC conversations with AI.
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
new DialogueEngine(provider: NarrativeProvider, config: DialogueEngineConfig)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Methods:**
|
|
148
|
+
- `initialize()` — Set up the engine
|
|
149
|
+
- `dialogue(request: DialogueRequest)` — Process a player-NPC exchange
|
|
150
|
+
- `getStatus()` — Get current engine status
|
|
151
|
+
|
|
152
|
+
**Config:**
|
|
153
|
+
```ts
|
|
154
|
+
interface DialogueEngineConfig {
|
|
155
|
+
lang: "en" | "zh";
|
|
156
|
+
maxConversationHistory?: number; // default: 10
|
|
157
|
+
failOpen?: boolean; // default: true
|
|
158
|
+
bilingualKeywordMap?: Record<string, string[]>;
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### `PassthroughProvider`
|
|
163
|
+
|
|
164
|
+
Returns pre-formatted responses without AI. Useful for testing and non-AI modes.
|
|
165
|
+
|
|
166
|
+
#### `OpenAICompatibleProvider`
|
|
167
|
+
|
|
168
|
+
Connects to any OpenAI-compatible API.
|
|
169
|
+
|
|
170
|
+
```ts
|
|
171
|
+
new OpenAICompatibleProvider(config: ProviderConfig)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### `AuditLog`
|
|
175
|
+
|
|
176
|
+
Records all dialogue pipeline events for debugging.
|
|
177
|
+
|
|
178
|
+
### Functions
|
|
179
|
+
|
|
180
|
+
| Function | Description |
|
|
181
|
+
|----------|-------------|
|
|
182
|
+
| `reviewGateTrigger(response, input, script, context, options?)` | Validate AI-proposed gate triggers |
|
|
183
|
+
| `expandKeywordsBilingually(keywords, map?)` | Expand keywords with translations |
|
|
184
|
+
| `parseAiJson(text)` | Parse AI JSON output safely |
|
|
185
|
+
| `validateDialogueResponse(parsed)` | Validate AI response structure |
|
|
186
|
+
| `buildNpcDialoguePrompt(script, context)` | Build system + user prompts |
|
|
187
|
+
| `loadConfigFromEnv()` | Load provider config from environment variables |
|
|
188
|
+
|
|
189
|
+
### Types
|
|
190
|
+
|
|
191
|
+
Key exported types: `NpcScript`, `NpcSecret`, `DialogueAiResponse`, `DialogueContext`, `DialogueResult`, `DialogueEngineConfig`, `NarrativeProvider`, `TrustLevel`, `ProviderStatus`, `AuditRecord`.
|
|
192
|
+
|
|
193
|
+
## Custom Provider
|
|
194
|
+
|
|
195
|
+
Implement the `NarrativeProvider` interface:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import type { NarrativeProvider, NarrativeRequest, NarrativeResponse } from "@wutiankai/npc-dialogue";
|
|
199
|
+
|
|
200
|
+
class MyProvider implements NarrativeProvider {
|
|
201
|
+
async initialize(): Promise<void> { /* ... */ }
|
|
202
|
+
|
|
203
|
+
async generate(request: NarrativeRequest): Promise<NarrativeResponse> {
|
|
204
|
+
return {
|
|
205
|
+
requestId: request.id,
|
|
206
|
+
text: "NPC response text",
|
|
207
|
+
source: "ai",
|
|
208
|
+
validation: { passed: true, violations: [] },
|
|
209
|
+
timestamp: Date.now(),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getStatus(): ProviderStatus { /* ... */ }
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Building
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
npm run build # ESM + CJS + type declarations via tsup
|
|
221
|
+
npm run clean # Remove dist/
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
MIT
|