familiar-vtt 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.

Potentially problematic release.


This version of familiar-vtt might be problematic. Click here for more details.

Files changed (105) hide show
  1. package/.github/workflows/publish.yml +23 -0
  2. package/.mcp.json +11 -0
  3. package/ARCHITECTURE.md +320 -0
  4. package/BUSINESS.md +547 -0
  5. package/CLAUDE.md +118 -0
  6. package/COMMUNITY_RESEARCH.md +225 -0
  7. package/LICENSE +21 -0
  8. package/TOOLS_REFERENCE.md +224 -0
  9. package/dist/module/main.js +1016 -0
  10. package/dist/module/main.js.map +7 -0
  11. package/dist/server/server/config.d.ts +22 -0
  12. package/dist/server/server/config.js +33 -0
  13. package/dist/server/server/config.js.map +1 -0
  14. package/dist/server/server/connector.d.ts +26 -0
  15. package/dist/server/server/connector.js +179 -0
  16. package/dist/server/server/connector.js.map +1 -0
  17. package/dist/server/server/http-transport.d.ts +10 -0
  18. package/dist/server/server/http-transport.js +43 -0
  19. package/dist/server/server/http-transport.js.map +1 -0
  20. package/dist/server/server/index.d.ts +2 -0
  21. package/dist/server/server/index.js +59 -0
  22. package/dist/server/server/index.js.map +1 -0
  23. package/dist/server/server/logger.d.ts +6 -0
  24. package/dist/server/server/logger.js +14 -0
  25. package/dist/server/server/logger.js.map +1 -0
  26. package/dist/server/server/tools/bundles.d.ts +56 -0
  27. package/dist/server/server/tools/bundles.js +187 -0
  28. package/dist/server/server/tools/bundles.js.map +1 -0
  29. package/dist/server/server/tools/canvas-environment.d.ts +3 -0
  30. package/dist/server/server/tools/canvas-environment.js +151 -0
  31. package/dist/server/server/tools/canvas-environment.js.map +1 -0
  32. package/dist/server/server/tools/canvas.d.ts +3 -0
  33. package/dist/server/server/tools/canvas.js +134 -0
  34. package/dist/server/server/tools/canvas.js.map +1 -0
  35. package/dist/server/server/tools/cards.d.ts +3 -0
  36. package/dist/server/server/tools/cards.js +35 -0
  37. package/dist/server/server/tools/cards.js.map +1 -0
  38. package/dist/server/server/tools/characters.d.ts +3 -0
  39. package/dist/server/server/tools/characters.js +115 -0
  40. package/dist/server/server/tools/characters.js.map +1 -0
  41. package/dist/server/server/tools/chat.d.ts +3 -0
  42. package/dist/server/server/tools/chat.js +23 -0
  43. package/dist/server/server/tools/chat.js.map +1 -0
  44. package/dist/server/server/tools/combat.d.ts +3 -0
  45. package/dist/server/server/tools/combat.js +38 -0
  46. package/dist/server/server/tools/combat.js.map +1 -0
  47. package/dist/server/server/tools/compendium.d.ts +3 -0
  48. package/dist/server/server/tools/compendium.js +33 -0
  49. package/dist/server/server/tools/compendium.js.map +1 -0
  50. package/dist/server/server/tools/dice.d.ts +3 -0
  51. package/dist/server/server/tools/dice.js +12 -0
  52. package/dist/server/server/tools/dice.js.map +1 -0
  53. package/dist/server/server/tools/effects.d.ts +3 -0
  54. package/dist/server/server/tools/effects.js +54 -0
  55. package/dist/server/server/tools/effects.js.map +1 -0
  56. package/dist/server/server/tools/ember-events.d.ts +3 -0
  57. package/dist/server/server/tools/ember-events.js +34 -0
  58. package/dist/server/server/tools/ember-events.js.map +1 -0
  59. package/dist/server/server/tools/folders.d.ts +3 -0
  60. package/dist/server/server/tools/folders.js +30 -0
  61. package/dist/server/server/tools/folders.js.map +1 -0
  62. package/dist/server/server/tools/helpers.d.ts +10 -0
  63. package/dist/server/server/tools/helpers.js +13 -0
  64. package/dist/server/server/tools/helpers.js.map +1 -0
  65. package/dist/server/server/tools/items.d.ts +3 -0
  66. package/dist/server/server/tools/items.js +23 -0
  67. package/dist/server/server/tools/items.js.map +1 -0
  68. package/dist/server/server/tools/journals.d.ts +3 -0
  69. package/dist/server/server/tools/journals.js +71 -0
  70. package/dist/server/server/tools/journals.js.map +1 -0
  71. package/dist/server/server/tools/macros.d.ts +3 -0
  72. package/dist/server/server/tools/macros.js +32 -0
  73. package/dist/server/server/tools/macros.js.map +1 -0
  74. package/dist/server/server/tools/playlists.d.ts +3 -0
  75. package/dist/server/server/tools/playlists.js +39 -0
  76. package/dist/server/server/tools/playlists.js.map +1 -0
  77. package/dist/server/server/tools/regions.d.ts +3 -0
  78. package/dist/server/server/tools/regions.js +65 -0
  79. package/dist/server/server/tools/regions.js.map +1 -0
  80. package/dist/server/server/tools/registry.d.ts +11 -0
  81. package/dist/server/server/tools/registry.js +73 -0
  82. package/dist/server/server/tools/registry.js.map +1 -0
  83. package/dist/server/server/tools/scenes.d.ts +3 -0
  84. package/dist/server/server/tools/scenes.js +142 -0
  85. package/dist/server/server/tools/scenes.js.map +1 -0
  86. package/dist/server/server/tools/tables.d.ts +3 -0
  87. package/dist/server/server/tools/tables.js +22 -0
  88. package/dist/server/server/tools/tables.js.map +1 -0
  89. package/dist/server/server/tools/world.d.ts +3 -0
  90. package/dist/server/server/tools/world.js +26 -0
  91. package/dist/server/server/tools/world.js.map +1 -0
  92. package/dist/server/shared/constants.d.ts +16 -0
  93. package/dist/server/shared/constants.js +17 -0
  94. package/dist/server/shared/constants.js.map +1 -0
  95. package/dist/server/shared/html.d.ts +4 -0
  96. package/dist/server/shared/html.js +9 -0
  97. package/dist/server/shared/html.js.map +1 -0
  98. package/dist/server/shared/protocol.d.ts +184 -0
  99. package/dist/server/shared/protocol.js +58 -0
  100. package/dist/server/shared/protocol.js.map +1 -0
  101. package/dist/server/shared/types.d.ts +21 -0
  102. package/dist/server/shared/types.js +2 -0
  103. package/dist/server/shared/types.js.map +1 -0
  104. package/module.json +21 -0
  105. package/package.json +81 -0
@@ -0,0 +1,184 @@
1
+ import { z } from 'zod';
2
+ /** Protocol header used for identification */
3
+ export declare const PROTOCOL_HEADER = "familiar";
4
+ /** All supported message types over WebSocket */
5
+ export declare const MessageType: {
6
+ /** Query from MCP server → Foundry module */
7
+ readonly QUERY: "mcp-query";
8
+ /** Response from Foundry module → MCP server */
9
+ readonly RESPONSE: "mcp-response";
10
+ /** Ping from server → module */
11
+ readonly PING: "ping";
12
+ /** Pong from module → server */
13
+ readonly PONG: "pong";
14
+ };
15
+ export type MessageType = (typeof MessageType)[keyof typeof MessageType];
16
+ /** Query payload sent from MCP server to Foundry module */
17
+ export declare const queryMessageSchema: z.ZodObject<{
18
+ type: z.ZodLiteral<"mcp-query">;
19
+ id: z.ZodString;
20
+ data: z.ZodObject<{
21
+ method: z.ZodString;
22
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
23
+ }, "strip", z.ZodTypeAny, {
24
+ method: string;
25
+ params?: Record<string, unknown> | undefined;
26
+ }, {
27
+ method: string;
28
+ params?: Record<string, unknown> | undefined;
29
+ }>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ type: "mcp-query";
32
+ id: string;
33
+ data: {
34
+ method: string;
35
+ params?: Record<string, unknown> | undefined;
36
+ };
37
+ }, {
38
+ type: "mcp-query";
39
+ id: string;
40
+ data: {
41
+ method: string;
42
+ params?: Record<string, unknown> | undefined;
43
+ };
44
+ }>;
45
+ /** Response payload sent from Foundry module to MCP server */
46
+ export declare const responseMessageSchema: z.ZodObject<{
47
+ type: z.ZodLiteral<"mcp-response">;
48
+ id: z.ZodString;
49
+ data: z.ZodObject<{
50
+ success: z.ZodBoolean;
51
+ result: z.ZodOptional<z.ZodUnknown>;
52
+ error: z.ZodOptional<z.ZodString>;
53
+ }, "strip", z.ZodTypeAny, {
54
+ success: boolean;
55
+ error?: string | undefined;
56
+ result?: unknown;
57
+ }, {
58
+ success: boolean;
59
+ error?: string | undefined;
60
+ result?: unknown;
61
+ }>;
62
+ }, "strip", z.ZodTypeAny, {
63
+ type: "mcp-response";
64
+ id: string;
65
+ data: {
66
+ success: boolean;
67
+ error?: string | undefined;
68
+ result?: unknown;
69
+ };
70
+ }, {
71
+ type: "mcp-response";
72
+ id: string;
73
+ data: {
74
+ success: boolean;
75
+ error?: string | undefined;
76
+ result?: unknown;
77
+ };
78
+ }>;
79
+ /** Ping message */
80
+ export declare const pingMessageSchema: z.ZodObject<{
81
+ type: z.ZodLiteral<"ping">;
82
+ id: z.ZodString;
83
+ }, "strip", z.ZodTypeAny, {
84
+ type: "ping";
85
+ id: string;
86
+ }, {
87
+ type: "ping";
88
+ id: string;
89
+ }>;
90
+ /** Pong message */
91
+ export declare const pongMessageSchema: z.ZodObject<{
92
+ type: z.ZodLiteral<"pong">;
93
+ id: z.ZodString;
94
+ }, "strip", z.ZodTypeAny, {
95
+ type: "pong";
96
+ id: string;
97
+ }, {
98
+ type: "pong";
99
+ id: string;
100
+ }>;
101
+ /** Union of all valid WebSocket messages */
102
+ export declare const socketMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObject<{
103
+ type: z.ZodLiteral<"mcp-query">;
104
+ id: z.ZodString;
105
+ data: z.ZodObject<{
106
+ method: z.ZodString;
107
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
108
+ }, "strip", z.ZodTypeAny, {
109
+ method: string;
110
+ params?: Record<string, unknown> | undefined;
111
+ }, {
112
+ method: string;
113
+ params?: Record<string, unknown> | undefined;
114
+ }>;
115
+ }, "strip", z.ZodTypeAny, {
116
+ type: "mcp-query";
117
+ id: string;
118
+ data: {
119
+ method: string;
120
+ params?: Record<string, unknown> | undefined;
121
+ };
122
+ }, {
123
+ type: "mcp-query";
124
+ id: string;
125
+ data: {
126
+ method: string;
127
+ params?: Record<string, unknown> | undefined;
128
+ };
129
+ }>, z.ZodObject<{
130
+ type: z.ZodLiteral<"mcp-response">;
131
+ id: z.ZodString;
132
+ data: z.ZodObject<{
133
+ success: z.ZodBoolean;
134
+ result: z.ZodOptional<z.ZodUnknown>;
135
+ error: z.ZodOptional<z.ZodString>;
136
+ }, "strip", z.ZodTypeAny, {
137
+ success: boolean;
138
+ error?: string | undefined;
139
+ result?: unknown;
140
+ }, {
141
+ success: boolean;
142
+ error?: string | undefined;
143
+ result?: unknown;
144
+ }>;
145
+ }, "strip", z.ZodTypeAny, {
146
+ type: "mcp-response";
147
+ id: string;
148
+ data: {
149
+ success: boolean;
150
+ error?: string | undefined;
151
+ result?: unknown;
152
+ };
153
+ }, {
154
+ type: "mcp-response";
155
+ id: string;
156
+ data: {
157
+ success: boolean;
158
+ error?: string | undefined;
159
+ result?: unknown;
160
+ };
161
+ }>, z.ZodObject<{
162
+ type: z.ZodLiteral<"ping">;
163
+ id: z.ZodString;
164
+ }, "strip", z.ZodTypeAny, {
165
+ type: "ping";
166
+ id: string;
167
+ }, {
168
+ type: "ping";
169
+ id: string;
170
+ }>, z.ZodObject<{
171
+ type: z.ZodLiteral<"pong">;
172
+ id: z.ZodString;
173
+ }, "strip", z.ZodTypeAny, {
174
+ type: "pong";
175
+ id: string;
176
+ }, {
177
+ type: "pong";
178
+ id: string;
179
+ }>]>;
180
+ export type QueryMessage = z.infer<typeof queryMessageSchema>;
181
+ export type ResponseMessage = z.infer<typeof responseMessageSchema>;
182
+ export type PingMessage = z.infer<typeof pingMessageSchema>;
183
+ export type PongMessage = z.infer<typeof pongMessageSchema>;
184
+ export type SocketMessage = z.infer<typeof socketMessageSchema>;
@@ -0,0 +1,58 @@
1
+ import { z } from 'zod';
2
+ import { MODULE_ID } from './constants.js';
3
+ /** Protocol header used for identification */
4
+ export const PROTOCOL_HEADER = MODULE_ID;
5
+ // ============================================
6
+ // Message Types
7
+ // ============================================
8
+ /** All supported message types over WebSocket */
9
+ export const MessageType = {
10
+ /** Query from MCP server → Foundry module */
11
+ QUERY: 'mcp-query',
12
+ /** Response from Foundry module → MCP server */
13
+ RESPONSE: 'mcp-response',
14
+ /** Ping from server → module */
15
+ PING: 'ping',
16
+ /** Pong from module → server */
17
+ PONG: 'pong',
18
+ };
19
+ // ============================================
20
+ // Message Schemas (Zod)
21
+ // ============================================
22
+ /** Query payload sent from MCP server to Foundry module */
23
+ export const queryMessageSchema = z.object({
24
+ type: z.literal(MessageType.QUERY),
25
+ id: z.string(),
26
+ data: z.object({
27
+ method: z.string(),
28
+ params: z.record(z.unknown()).optional(),
29
+ }),
30
+ });
31
+ /** Response payload sent from Foundry module to MCP server */
32
+ export const responseMessageSchema = z.object({
33
+ type: z.literal(MessageType.RESPONSE),
34
+ id: z.string(),
35
+ data: z.object({
36
+ success: z.boolean(),
37
+ result: z.unknown().optional(),
38
+ error: z.string().optional(),
39
+ }),
40
+ });
41
+ /** Ping message */
42
+ export const pingMessageSchema = z.object({
43
+ type: z.literal(MessageType.PING),
44
+ id: z.string(),
45
+ });
46
+ /** Pong message */
47
+ export const pongMessageSchema = z.object({
48
+ type: z.literal(MessageType.PONG),
49
+ id: z.string(),
50
+ });
51
+ /** Union of all valid WebSocket messages */
52
+ export const socketMessageSchema = z.discriminatedUnion('type', [
53
+ queryMessageSchema,
54
+ responseMessageSchema,
55
+ pingMessageSchema,
56
+ pongMessageSchema,
57
+ ]);
58
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/shared/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,8CAA8C;AAC9C,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC;AAEzC,+CAA+C;AAC/C,gBAAgB;AAChB,+CAA+C;AAE/C,iDAAiD;AACjD,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,6CAA6C;IAC7C,KAAK,EAAE,WAAW;IAClB,gDAAgD;IAChD,QAAQ,EAAE,cAAc;IACxB,gCAAgC;IAChC,IAAI,EAAE,MAAM;IACZ,gCAAgC;IAChC,IAAI,EAAE,MAAM;CACJ,CAAC;AAIX,+CAA+C;AAC/C,wBAAwB;AACxB,+CAA+C;AAE/C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC;IAClC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE;KACzC,CAAC;CACH,CAAC,CAAC;AAEH,8DAA8D;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC;IACrC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QACpB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;QAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAC7B,CAAC;CACH,CAAC,CAAC;AAEH,mBAAmB;AACnB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,mBAAmB;AACnB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC;IACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAEH,4CAA4C;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IAC9D,kBAAkB;IAClB,qBAAqB;IACrB,iBAAiB;IACjB,iBAAiB;CAClB,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /** Unique message correlation ID */
2
+ export type MessageId = string;
3
+ /** Result of a successful Foundry query */
4
+ export interface QueryResult {
5
+ success: true;
6
+ result: unknown;
7
+ }
8
+ /** Result of a failed Foundry query */
9
+ export interface QueryError {
10
+ success: false;
11
+ error: string;
12
+ }
13
+ /** Union result type from Foundry queries */
14
+ export type QueryResponse = QueryResult | QueryError;
15
+ /** Handler function signature for Foundry module query handlers */
16
+ export type QueryHandler = (params?: Record<string, unknown>) => Promise<QueryResponse>;
17
+ /** MCP tool content block (text response) */
18
+ export interface McpTextContent {
19
+ type: 'text';
20
+ text: string;
21
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/shared/types.ts"],"names":[],"mappings":""}
package/module.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "id": "familiar",
3
+ "title": "Familiar",
4
+ "description": "<p>Your AI familiar for Foundry VTT. AI DM assistant with 124 tools — manages scenes, combat, tokens, music, and more.</p>",
5
+ "version": "0.1.0",
6
+ "compatibility": {
7
+ "minimum": "12",
8
+ "verified": "13"
9
+ },
10
+ "authors": [
11
+ {
12
+ "name": "Ryan Jansen",
13
+ "url": "https://github.com/Ryanjansen92"
14
+ }
15
+ ],
16
+ "esmodules": ["main.js"],
17
+ "socket": true,
18
+ "url": "https://github.com/Ryanjansen92/familiar",
19
+ "bugs": "https://github.com/Ryanjansen92/familiar/issues",
20
+ "license": "LICENSE"
21
+ }
package/package.json ADDED
@@ -0,0 +1,81 @@
1
+ {
2
+ "name": "familiar-vtt",
3
+ "version": "0.1.0",
4
+ "description": "Your AI familiar for Foundry VTT — AI DM assistant",
5
+ "type": "module",
6
+ "engines": {
7
+ "node": ">=20"
8
+ },
9
+ "bin": {
10
+ "familiar-vtt": "dist/server/server/index.js"
11
+ },
12
+ "scripts": {
13
+ "build": "npm run build:server && npm run build:module",
14
+ "build:server": "tsc -p tsconfig.server.json",
15
+ "build:module": "esbuild src/module/main.ts --bundle --format=esm --outfile=dist/module/main.js --platform=browser --target=es2022 --minify --sourcemap",
16
+ "build:mcp-package": "esbuild src/server/index.ts --bundle --platform=node --format=esm --outfile=dist/mcp-package/index.mjs --external:bufferutil --external:utf-8-validate --minify --banner:js=\"#!/usr/bin/env node\"",
17
+ "deploy": "npm run build && node --input-type=module -e \"import fs from 'fs';const d=process.env.LOCALAPPDATA+'/FoundryVTT/Data/modules/familiar';fs.mkdirSync(d,{recursive:true});fs.copyFileSync('dist/module/main.js',d+'/main.js');fs.copyFileSync('module.json',d+'/module.json');console.log('Deployed to '+d)\"",
18
+ "dev": "tsx watch src/server/index.ts",
19
+ "inspect": "npx @modelcontextprotocol/inspector tsx src/server/index.ts",
20
+ "lint": "eslint .",
21
+ "lint:fix": "eslint . --fix",
22
+ "format": "prettier --write .",
23
+ "format:check": "prettier --check .",
24
+ "typecheck": "tsc --noEmit -p tsconfig.server.json && tsc --noEmit -p tsconfig.module.json",
25
+ "test": "vitest run",
26
+ "test:watch": "vitest",
27
+ "test:coverage": "vitest run --coverage",
28
+ "knip": "knip",
29
+ "lockfile-lint": "lockfile-lint --path package-lock.json --type npm --allowed-hosts npm --validate-https",
30
+ "prepare": "husky"
31
+ },
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.12.1",
34
+ "pino": "^10.3.1",
35
+ "ws": "^8.18.0",
36
+ "zod": "^3.25.0"
37
+ },
38
+ "devDependencies": {
39
+ "@commitlint/cli": "^20.4.1",
40
+ "@commitlint/config-conventional": "^20.4.1",
41
+ "@types/node": "^22.15.0",
42
+ "@types/ws": "^8.18.0",
43
+ "@vitest/coverage-v8": "^3.2.4",
44
+ "@vitest/eslint-plugin": "^1.6.7",
45
+ "esbuild": "^0.25.0",
46
+ "eslint": "^9.38.0",
47
+ "eslint-plugin-depend": "^1.4.0",
48
+ "eslint-plugin-no-secrets": "^2.2.2",
49
+ "eslint-plugin-promise": "^7.2.1",
50
+ "eslint-plugin-regexp": "^3.0.0",
51
+ "eslint-plugin-security": "^3.0.1",
52
+ "eslint-plugin-sonarjs": "^3.0.7",
53
+ "eslint-plugin-unicorn": "^63.0.0",
54
+ "husky": "^9.1.7",
55
+ "jiti": "^2.6.1",
56
+ "knip": "^5.83.1",
57
+ "lint-staged": "^16.2.7",
58
+ "lockfile-lint": "^5.0.0",
59
+ "prettier": "^3.5.0",
60
+ "tsx": "^4.19.0",
61
+ "typescript": "^5.9.3",
62
+ "typescript-eslint": "^8.55.0",
63
+ "vitest": "^3.2.0"
64
+ },
65
+ "keywords": [
66
+ "foundry-vtt",
67
+ "familiar",
68
+ "mcp",
69
+ "dnd",
70
+ "tabletop",
71
+ "ai",
72
+ "claude"
73
+ ],
74
+ "lint-staged": {
75
+ "*.ts": [
76
+ "eslint --no-warn-ignored --max-warnings 0",
77
+ "prettier --check"
78
+ ]
79
+ },
80
+ "license": "MIT"
81
+ }