run-dmcp 0.1.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.
Files changed (167) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +79 -0
  3. package/dist/__tests__/engineVocabulary.test.d.ts +1 -0
  4. package/dist/__tests__/engineVocabulary.test.js +147 -0
  5. package/dist/db/__tests__/connection.test.d.ts +1 -0
  6. package/dist/db/__tests__/connection.test.js +72 -0
  7. package/dist/db/__tests__/testDb.d.ts +33 -0
  8. package/dist/db/__tests__/testDb.js +41 -0
  9. package/dist/db/connection.d.ts +22 -0
  10. package/dist/db/connection.js +107 -0
  11. package/dist/db/schema.d.ts +1 -0
  12. package/dist/db/schema.js +725 -0
  13. package/dist/events/emitter.d.ts +22 -0
  14. package/dist/events/emitter.js +71 -0
  15. package/dist/http/server.d.ts +3 -0
  16. package/dist/http/server.js +649 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +92 -0
  19. package/dist/register/abilities.d.ts +2 -0
  20. package/dist/register/abilities.js +165 -0
  21. package/dist/register/audio.d.ts +2 -0
  22. package/dist/register/audio.js +326 -0
  23. package/dist/register/batch.d.ts +2 -0
  24. package/dist/register/batch.js +343 -0
  25. package/dist/register/character.d.ts +2 -0
  26. package/dist/register/character.js +324 -0
  27. package/dist/register/combat.d.ts +2 -0
  28. package/dist/register/combat.js +207 -0
  29. package/dist/register/core.d.ts +2 -0
  30. package/dist/register/core.js +1040 -0
  31. package/dist/register/display.d.ts +2 -0
  32. package/dist/register/display.js +263 -0
  33. package/dist/register/factions.d.ts +2 -0
  34. package/dist/register/factions.js +186 -0
  35. package/dist/register/images.d.ts +2 -0
  36. package/dist/register/images.js +400 -0
  37. package/dist/register/inventory.d.ts +2 -0
  38. package/dist/register/inventory.js +115 -0
  39. package/dist/register/mcp-prompts.d.ts +2 -0
  40. package/dist/register/mcp-prompts.js +684 -0
  41. package/dist/register/mcp-resources.d.ts +2 -0
  42. package/dist/register/mcp-resources.js +335 -0
  43. package/dist/register/narrative.d.ts +2 -0
  44. package/dist/register/narrative.js +242 -0
  45. package/dist/register/notes.d.ts +2 -0
  46. package/dist/register/notes.js +170 -0
  47. package/dist/register/pause.d.ts +2 -0
  48. package/dist/register/pause.js +580 -0
  49. package/dist/register/quests.d.ts +2 -0
  50. package/dist/register/quests.js +118 -0
  51. package/dist/register/relationships.d.ts +2 -0
  52. package/dist/register/relationships.js +147 -0
  53. package/dist/register/resources.d.ts +2 -0
  54. package/dist/register/resources.js +277 -0
  55. package/dist/register/secrets.d.ts +2 -0
  56. package/dist/register/secrets.js +192 -0
  57. package/dist/register/status.d.ts +2 -0
  58. package/dist/register/status.js +130 -0
  59. package/dist/register/tables.d.ts +2 -0
  60. package/dist/register/tables.js +146 -0
  61. package/dist/register/tags.d.ts +2 -0
  62. package/dist/register/tags.js +114 -0
  63. package/dist/register/time.d.ts +2 -0
  64. package/dist/register/time.js +281 -0
  65. package/dist/register/world.d.ts +2 -0
  66. package/dist/register/world.js +127 -0
  67. package/dist/schemas/index.d.ts +921 -0
  68. package/dist/schemas/index.js +121 -0
  69. package/dist/test-setup.d.ts +1 -0
  70. package/dist/test-setup.js +13 -0
  71. package/dist/tools/__tests__/audio.test.d.ts +1 -0
  72. package/dist/tools/__tests__/audio.test.js +59 -0
  73. package/dist/tools/__tests__/conserved.test.d.ts +1 -0
  74. package/dist/tools/__tests__/conserved.test.js +488 -0
  75. package/dist/tools/__tests__/constraint.test.d.ts +1 -0
  76. package/dist/tools/__tests__/constraint.test.js +212 -0
  77. package/dist/tools/__tests__/expiry-consequences.test.d.ts +1 -0
  78. package/dist/tools/__tests__/expiry-consequences.test.js +110 -0
  79. package/dist/tools/__tests__/images.test.d.ts +1 -0
  80. package/dist/tools/__tests__/images.test.js +59 -0
  81. package/dist/tools/__tests__/relationship.test.d.ts +1 -0
  82. package/dist/tools/__tests__/relationship.test.js +132 -0
  83. package/dist/tools/__tests__/resource-constraints.test.d.ts +1 -0
  84. package/dist/tools/__tests__/resource-constraints.test.js +131 -0
  85. package/dist/tools/__tests__/resource.test.d.ts +1 -0
  86. package/dist/tools/__tests__/resource.test.js +190 -0
  87. package/dist/tools/__tests__/time.test.d.ts +1 -0
  88. package/dist/tools/__tests__/time.test.js +404 -0
  89. package/dist/tools/__tests__/timers.test.d.ts +1 -0
  90. package/dist/tools/__tests__/timers.test.js +426 -0
  91. package/dist/tools/__tests__/world.test.d.ts +1 -0
  92. package/dist/tools/__tests__/world.test.js +70 -0
  93. package/dist/tools/ability.d.ts +48 -0
  94. package/dist/tools/ability.js +238 -0
  95. package/dist/tools/audio.d.ts +24 -0
  96. package/dist/tools/audio.js +365 -0
  97. package/dist/tools/character.d.ts +70 -0
  98. package/dist/tools/character.js +309 -0
  99. package/dist/tools/combat.d.ts +13 -0
  100. package/dist/tools/combat.js +195 -0
  101. package/dist/tools/constraint.d.ts +132 -0
  102. package/dist/tools/constraint.js +269 -0
  103. package/dist/tools/dice.d.ts +23 -0
  104. package/dist/tools/dice.js +111 -0
  105. package/dist/tools/display.d.ts +120 -0
  106. package/dist/tools/display.js +528 -0
  107. package/dist/tools/faction.d.ts +61 -0
  108. package/dist/tools/faction.js +269 -0
  109. package/dist/tools/game.d.ts +96 -0
  110. package/dist/tools/game.js +526 -0
  111. package/dist/tools/image-prompt.d.ts +49 -0
  112. package/dist/tools/image-prompt.js +479 -0
  113. package/dist/tools/images.d.ts +47 -0
  114. package/dist/tools/images.js +449 -0
  115. package/dist/tools/inventory.d.ts +20 -0
  116. package/dist/tools/inventory.js +145 -0
  117. package/dist/tools/narrative.d.ts +58 -0
  118. package/dist/tools/narrative.js +237 -0
  119. package/dist/tools/notes.d.ts +41 -0
  120. package/dist/tools/notes.js +220 -0
  121. package/dist/tools/pause.d.ts +110 -0
  122. package/dist/tools/pause.js +1254 -0
  123. package/dist/tools/quest.d.ts +34 -0
  124. package/dist/tools/quest.js +164 -0
  125. package/dist/tools/relationship.d.ts +74 -0
  126. package/dist/tools/relationship.js +324 -0
  127. package/dist/tools/resource.d.ts +93 -0
  128. package/dist/tools/resource.js +374 -0
  129. package/dist/tools/rules.d.ts +4 -0
  130. package/dist/tools/rules.js +30 -0
  131. package/dist/tools/secrets.d.ts +49 -0
  132. package/dist/tools/secrets.js +195 -0
  133. package/dist/tools/status.d.ts +36 -0
  134. package/dist/tools/status.js +218 -0
  135. package/dist/tools/tables.d.ts +33 -0
  136. package/dist/tools/tables.js +209 -0
  137. package/dist/tools/tags.d.ts +52 -0
  138. package/dist/tools/tags.js +176 -0
  139. package/dist/tools/time.d.ts +33 -0
  140. package/dist/tools/time.js +276 -0
  141. package/dist/tools/timers.d.ts +41 -0
  142. package/dist/tools/timers.js +215 -0
  143. package/dist/tools/world.d.ts +78 -0
  144. package/dist/tools/world.js +331 -0
  145. package/dist/types/index.d.ts +969 -0
  146. package/dist/types/index.js +1 -0
  147. package/dist/utils/__tests__/json.test.d.ts +1 -0
  148. package/dist/utils/__tests__/json.test.js +55 -0
  149. package/dist/utils/__tests__/validation.test.d.ts +1 -0
  150. package/dist/utils/__tests__/validation.test.js +90 -0
  151. package/dist/utils/errors.d.ts +44 -0
  152. package/dist/utils/errors.js +121 -0
  153. package/dist/utils/json.d.ts +9 -0
  154. package/dist/utils/json.js +23 -0
  155. package/dist/utils/logger.d.ts +7 -0
  156. package/dist/utils/logger.js +50 -0
  157. package/dist/utils/output-schemas.d.ts +594 -0
  158. package/dist/utils/output-schemas.js +331 -0
  159. package/dist/utils/tool-annotations.d.ts +147 -0
  160. package/dist/utils/tool-annotations.js +98 -0
  161. package/dist/utils/validation.d.ts +34 -0
  162. package/dist/utils/validation.js +52 -0
  163. package/dist/utils/verbosity.d.ts +57 -0
  164. package/dist/utils/verbosity.js +67 -0
  165. package/dist/utils/webui.d.ts +20 -0
  166. package/dist/utils/webui.js +35 -0
  167. package/package.json +75 -0
@@ -0,0 +1,121 @@
1
+ import { z } from "zod";
2
+ // Reusable Zod schemas for image generation
3
+ export const subjectDescriptionSchema = z.object({
4
+ type: z.enum(["character", "location", "item", "scene"]),
5
+ primaryDescription: z.string(),
6
+ physicalTraits: z.object({
7
+ age: z.string().optional(),
8
+ gender: z.string().optional(),
9
+ bodyType: z.string().optional(),
10
+ height: z.string().optional(),
11
+ skinTone: z.string().optional(),
12
+ hairColor: z.string().optional(),
13
+ hairStyle: z.string().optional(),
14
+ eyeColor: z.string().optional(),
15
+ facialFeatures: z.string().optional(),
16
+ distinguishingMarks: z.array(z.string()).optional(),
17
+ }).optional(),
18
+ attire: z.object({
19
+ description: z.string(),
20
+ colors: z.array(z.string()).optional(),
21
+ materials: z.array(z.string()).optional(),
22
+ accessories: z.array(z.string()).optional(),
23
+ }).optional(),
24
+ environment: z.object({
25
+ setting: z.string(),
26
+ timeOfDay: z.string().optional(),
27
+ weather: z.string().optional(),
28
+ lighting: z.string().optional(),
29
+ architecture: z.string().optional(),
30
+ vegetation: z.string().optional(),
31
+ notableFeatures: z.array(z.string()).optional(),
32
+ }).optional(),
33
+ objectDetails: z.object({
34
+ material: z.string().optional(),
35
+ size: z.string().optional(),
36
+ condition: z.string().optional(),
37
+ glowOrEffects: z.string().optional(),
38
+ }).optional(),
39
+ pose: z.string().optional(),
40
+ expression: z.string().optional(),
41
+ action: z.string().optional(),
42
+ });
43
+ export const styleDescriptionSchema = z.object({
44
+ artisticStyle: z.string(),
45
+ genre: z.string(),
46
+ mood: z.string(),
47
+ colorScheme: z.string().optional(),
48
+ influences: z.array(z.string()).optional(),
49
+ qualityTags: z.array(z.string()).optional(),
50
+ negativeElements: z.array(z.string()).optional(),
51
+ });
52
+ export const compositionDescriptionSchema = z.object({
53
+ framing: z.string(),
54
+ cameraAngle: z.string().optional(),
55
+ aspectRatio: z.string().optional(),
56
+ focusPoint: z.string().optional(),
57
+ background: z.string().optional(),
58
+ depth: z.string().optional(),
59
+ });
60
+ export const comfyUIPromptSchema = z.object({
61
+ positive: z.string(),
62
+ negative: z.string(),
63
+ checkpoint: z.string().optional(),
64
+ loras: z.array(z.object({
65
+ name: z.string(),
66
+ weight: z.number(),
67
+ })).optional(),
68
+ samplerSettings: z.object({
69
+ sampler: z.string().optional(),
70
+ scheduler: z.string().optional(),
71
+ steps: z.number().optional(),
72
+ cfg: z.number().optional(),
73
+ }).optional(),
74
+ });
75
+ export const generatedImageSchema = z.object({
76
+ id: z.string(),
77
+ tool: z.string(),
78
+ prompt: z.string(),
79
+ url: z.string().optional(),
80
+ base64: z.string().optional(),
81
+ seed: z.number().optional(),
82
+ timestamp: z.string(),
83
+ metadata: z.record(z.string(), z.unknown()).optional(),
84
+ });
85
+ export const imageGenSchema = z.object({
86
+ subject: subjectDescriptionSchema,
87
+ style: styleDescriptionSchema,
88
+ composition: compositionDescriptionSchema,
89
+ prompts: z.object({
90
+ generic: z.string().optional(),
91
+ sdxl: z.string().optional(),
92
+ dalle: z.string().optional(),
93
+ midjourney: z.string().optional(),
94
+ flux: z.string().optional(),
95
+ comfyui: comfyUIPromptSchema.optional(),
96
+ }).optional(),
97
+ generations: z.array(generatedImageSchema).optional(),
98
+ consistency: z.object({
99
+ characterRef: z.string().optional(),
100
+ seedImage: z.string().optional(),
101
+ colorPalette: z.array(z.string()).optional(),
102
+ styleRef: z.string().optional(),
103
+ }).optional(),
104
+ }).describe("Image generation metadata for visual representation");
105
+ // Voice schema for characters
106
+ export const voiceSchema = z.object({
107
+ pitch: z.enum(["very_low", "low", "medium", "high", "very_high"]).describe("Voice pitch"),
108
+ speed: z.enum(["very_slow", "slow", "medium", "fast", "very_fast"]).describe("Speaking speed"),
109
+ tone: z.string().describe("Voice tone (e.g., 'gravelly', 'melodic', 'nasal', 'breathy')"),
110
+ accent: z.string().optional().describe("Accent (e.g., 'Scottish', 'French', 'Brooklyn')"),
111
+ quirks: z.array(z.string()).optional().describe("Speech quirks (e.g., 'stutters when nervous')"),
112
+ description: z.string().optional().describe("Free-form voice description for more nuance"),
113
+ });
114
+ // Random table entry schema
115
+ export const tableEntrySchema = z.object({
116
+ minRoll: z.number().optional().describe("Minimum roll to get this result (for ranged tables)"),
117
+ maxRoll: z.number().optional().describe("Maximum roll for this result"),
118
+ weight: z.number().optional().describe("Weight for weighted random selection"),
119
+ result: z.string().describe("The result text"),
120
+ effects: z.record(z.unknown()).optional().describe("Optional structured effects"),
121
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ // Vitest setupFiles entry (see vitest.config.ts): a process-wide safety net
2
+ // guaranteeing no test can ever open the real on-disk database.
3
+ //
4
+ // `getDatabase()` resolves DMCP_DB_PATH lazily, so the per-test fixture in
5
+ // src/db/__tests__/testDb.ts is normally sufficient. This exists for the
6
+ // cases the fixture cannot cover -- a `getDatabase()` reached at module scope,
7
+ // or from code a test imports before its own `beforeEach` runs. A setupFiles
8
+ // module is imported before the test file itself, so this lands first.
9
+ //
10
+ // Nothing should ever `delete` this env var mid-run; doing so re-opens the
11
+ // hole for every subsequent test.
12
+ process.env.DMCP_DB_PATH = ":memory:";
13
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,59 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { createTestDb, destroyTestDb } from '../../db/__tests__/testDb.js';
4
+ import { getDatabase } from '../../db/connection.js';
5
+ import { createGame } from '../game.js';
6
+ import { createCharacter } from '../character.js';
7
+ import { getAudio, setPrimaryAudio } from '../audio.js';
8
+ // Inserts a stored_audio row directly via SQL so these tests can exercise
9
+ // setPrimaryAudio() without going through storeAudio()'s file I/O / network
10
+ // fetch, which is unrelated to the atomicity behavior under test here.
11
+ function insertStoredAudio(params) {
12
+ const db = getDatabase();
13
+ const id = uuidv4();
14
+ db.prepare(`
15
+ INSERT INTO stored_audio (id, game_id, entity_id, entity_type, file_path, file_size, mime_type, source, is_primary, created_at)
16
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
17
+ `).run(id, params.gameId, params.entityId, params.entityType, `${id}.mp3`, 100, 'audio/mpeg', 'uploaded', params.isPrimary ? 1 : 0, new Date().toISOString());
18
+ return id;
19
+ }
20
+ describe('setPrimaryAudio', () => {
21
+ let gameId;
22
+ let characterId;
23
+ beforeEach(() => {
24
+ createTestDb();
25
+ gameId = createGame({ name: 'Test Game', setting: 'Test Setting', style: 'Test Style' }).id;
26
+ characterId = createCharacter({ gameId, name: 'Narrator', isPlayer: false }).id;
27
+ });
28
+ afterEach(() => {
29
+ destroyTestDb();
30
+ });
31
+ it('unsets the previous primary and sets the new one', () => {
32
+ const first = insertStoredAudio({ gameId, entityId: characterId, entityType: 'character', isPrimary: true });
33
+ const second = insertStoredAudio({ gameId, entityId: characterId, entityType: 'character', isPrimary: false });
34
+ setPrimaryAudio(second);
35
+ expect(getAudio(first)?.isPrimary).toBe(false);
36
+ expect(getAudio(second)?.isPrimary).toBe(true);
37
+ });
38
+ it('leaves NO partial write when the second update fails mid-operation: the old primary stays primary', () => {
39
+ const first = insertStoredAudio({ gameId, entityId: characterId, entityType: 'character', isPrimary: true });
40
+ const second = insertStoredAudio({ gameId, entityId: characterId, entityType: 'character', isPrimary: false });
41
+ // Fault injection: make the UPDATE that sets `second` as primary fail,
42
+ // simulating a mid-operation failure between the unset and the set.
43
+ const db = getDatabase();
44
+ db.exec(`
45
+ CREATE TRIGGER fail_set_new_primary_audio
46
+ BEFORE UPDATE ON stored_audio
47
+ WHEN NEW.id = '${second}' AND NEW.is_primary = 1
48
+ BEGIN
49
+ SELECT RAISE(ABORT, 'simulated failure');
50
+ END;
51
+ `);
52
+ expect(() => setPrimaryAudio(second)).toThrow();
53
+ // Without a real transaction, the first UPDATE (unsetting `first`)
54
+ // would have already committed, leaving NO primary at all. With a
55
+ // transaction, `first` must still be primary.
56
+ expect(getAudio(first)?.isPrimary).toBe(true);
57
+ expect(getAudio(second)?.isPrimary).toBe(false);
58
+ });
59
+ });
@@ -0,0 +1 @@
1
+ export {};