@nextsparkjs/plugin-ai 0.1.0-beta.68 → 0.1.0-beta.73

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.
@@ -308,6 +308,25 @@ export const aiHistoryFields: EntityField[] = [
308
308
  readOnly: true,
309
309
  },
310
310
  },
311
+ {
312
+ name: 'updatedAt',
313
+ type: 'datetime',
314
+ required: false,
315
+ display: {
316
+ label: 'Updated At',
317
+ description: 'When the record was last updated',
318
+ showInList: false,
319
+ showInDetail: true,
320
+ showInForm: false,
321
+ order: 98,
322
+ columnWidth: 6,
323
+ },
324
+ api: {
325
+ searchable: false,
326
+ sortable: true,
327
+ readOnly: true,
328
+ },
329
+ },
311
330
  {
312
331
  name: 'completedAt',
313
332
  type: 'datetime',
@@ -318,7 +337,7 @@ export const aiHistoryFields: EntityField[] = [
318
337
  showInList: false,
319
338
  showInDetail: true,
320
339
  showInForm: false,
321
- order: 98,
340
+ order: 99,
322
341
  columnWidth: 6,
323
342
  },
324
343
  api: {
@@ -10,9 +10,9 @@
10
10
  -- MAIN AI_HISTORY TABLE
11
11
  -- =============================================
12
12
 
13
- DROP TABLE IF EXISTS "ai_history" CASCADE;
13
+ DROP TABLE IF EXISTS "ai-history" CASCADE;
14
14
 
15
- CREATE TABLE "ai_history" (
15
+ CREATE TABLE "ai-history" (
16
16
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
17
17
  "userId" TEXT NOT NULL REFERENCES "users"(id) ON DELETE CASCADE,
18
18
 
@@ -41,6 +41,7 @@ CREATE TABLE "ai_history" (
41
41
 
42
42
  -- Timestamps
43
43
  "createdAt" TIMESTAMPTZ NOT NULL DEFAULT now(),
44
+ "updatedAt" TIMESTAMPTZ NOT NULL DEFAULT now(),
44
45
  "completedAt" TIMESTAMPTZ
45
46
  );
46
47
 
@@ -48,46 +49,46 @@ CREATE TABLE "ai_history" (
48
49
  -- INDEXES
49
50
  -- =============================================
50
51
 
51
- CREATE INDEX IF NOT EXISTS idx_ai_history_user_id ON "ai_history"("userId");
52
- CREATE INDEX IF NOT EXISTS idx_ai_history_entity ON "ai_history"("relatedEntityType", "relatedEntityId") WHERE "relatedEntityType" IS NOT NULL;
53
- CREATE INDEX IF NOT EXISTS idx_ai_history_status ON "ai_history"(status);
54
- CREATE INDEX IF NOT EXISTS idx_ai_history_operation ON "ai_history"(operation);
55
- CREATE INDEX IF NOT EXISTS idx_ai_history_model ON "ai_history"(model);
56
- CREATE INDEX IF NOT EXISTS idx_ai_history_provider ON "ai_history"(provider);
57
- CREATE INDEX IF NOT EXISTS idx_ai_history_created_at ON "ai_history"("createdAt" DESC);
58
- CREATE INDEX IF NOT EXISTS idx_ai_history_user_status ON "ai_history"("userId", status);
59
- CREATE INDEX IF NOT EXISTS idx_ai_history_user_operation ON "ai_history"("userId", operation);
60
- CREATE INDEX IF NOT EXISTS idx_ai_history_tokens_input ON "ai_history"("tokensInput") WHERE "tokensInput" IS NOT NULL;
61
- CREATE INDEX IF NOT EXISTS idx_ai_history_tokens_output ON "ai_history"("tokensOutput") WHERE "tokensOutput" IS NOT NULL;
52
+ CREATE INDEX IF NOT EXISTS idx_ai-history_user_id ON "ai-history"("userId");
53
+ CREATE INDEX IF NOT EXISTS idx_ai-history_entity ON "ai-history"("relatedEntityType", "relatedEntityId") WHERE "relatedEntityType" IS NOT NULL;
54
+ CREATE INDEX IF NOT EXISTS idx_ai-history_status ON "ai-history"(status);
55
+ CREATE INDEX IF NOT EXISTS idx_ai-history_operation ON "ai-history"(operation);
56
+ CREATE INDEX IF NOT EXISTS idx_ai-history_model ON "ai-history"(model);
57
+ CREATE INDEX IF NOT EXISTS idx_ai-history_provider ON "ai-history"(provider);
58
+ CREATE INDEX IF NOT EXISTS idx_ai-history_created_at ON "ai-history"("createdAt" DESC);
59
+ CREATE INDEX IF NOT EXISTS idx_ai-history_user_status ON "ai-history"("userId", status);
60
+ CREATE INDEX IF NOT EXISTS idx_ai-history_user_operation ON "ai-history"("userId", operation);
61
+ CREATE INDEX IF NOT EXISTS idx_ai-history_tokens_input ON "ai-history"("tokensInput") WHERE "tokensInput" IS NOT NULL;
62
+ CREATE INDEX IF NOT EXISTS idx_ai-history_tokens_output ON "ai-history"("tokensOutput") WHERE "tokensOutput" IS NOT NULL;
62
63
 
63
64
  -- =============================================
64
65
  -- ROW LEVEL SECURITY (enableRLS: true)
65
66
  -- =============================================
66
67
 
67
68
  -- Enable RLS
68
- ALTER TABLE "ai_history" ENABLE ROW LEVEL SECURITY;
69
+ ALTER TABLE "ai-history" ENABLE ROW LEVEL SECURITY;
69
70
 
70
- -- Policies for ai_history table
71
- DROP POLICY IF EXISTS "Users can view own ai history" ON "ai_history";
72
- CREATE POLICY "Users can view own ai history" ON "ai_history"
71
+ -- Policies for ai-history table
72
+ DROP POLICY IF EXISTS "Users can view own ai history" ON "ai-history";
73
+ CREATE POLICY "Users can view own ai history" ON "ai-history"
73
74
  FOR SELECT USING ("userId" = public.get_auth_user_id());
74
75
 
75
- DROP POLICY IF EXISTS "Users can insert own ai history" ON "ai_history";
76
- CREATE POLICY "Users can insert own ai history" ON "ai_history"
76
+ DROP POLICY IF EXISTS "Users can insert own ai history" ON "ai-history";
77
+ CREATE POLICY "Users can insert own ai history" ON "ai-history"
77
78
  FOR INSERT WITH CHECK ("userId" = public.get_auth_user_id());
78
79
 
79
- DROP POLICY IF EXISTS "Users can update own ai history" ON "ai_history";
80
- CREATE POLICY "Users can update own ai history" ON "ai_history"
80
+ DROP POLICY IF EXISTS "Users can update own ai history" ON "ai-history";
81
+ CREATE POLICY "Users can update own ai history" ON "ai-history"
81
82
  FOR UPDATE USING ("userId" = public.get_auth_user_id())
82
83
  WITH CHECK ("userId" = public.get_auth_user_id());
83
84
 
84
- DROP POLICY IF EXISTS "Users can delete own ai history" ON "ai_history";
85
- CREATE POLICY "Users can delete own ai history" ON "ai_history"
85
+ DROP POLICY IF EXISTS "Users can delete own ai history" ON "ai-history";
86
+ CREATE POLICY "Users can delete own ai history" ON "ai-history"
86
87
  FOR DELETE USING ("userId" = public.get_auth_user_id());
87
88
 
88
89
  -- Admins can manage all ai history
89
- DROP POLICY IF EXISTS "Admins can manage all ai history" ON "ai_history";
90
- CREATE POLICY "Admins can manage all ai history" ON "ai_history"
90
+ DROP POLICY IF EXISTS "Admins can manage all ai history" ON "ai-history";
91
+ CREATE POLICY "Admins can manage all ai history" ON "ai-history"
91
92
  FOR ALL USING (
92
93
  EXISTS (
93
94
  SELECT 1 FROM "users"
@@ -103,10 +104,17 @@ CREATE POLICY "Admins can manage all ai history" ON "ai_history"
103
104
  )
104
105
  );
105
106
 
107
+ -- =============================================
108
+ -- TRIGGER: Auto-update updatedAt
109
+ -- =============================================
110
+ CREATE TRIGGER ai-history_set_updated_at
111
+ BEFORE UPDATE ON "ai-history"
112
+ FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
113
+
106
114
  -- =============================================
107
115
  -- TRIGGER: Auto-update completedAt
108
116
  -- =============================================
109
- CREATE OR REPLACE FUNCTION update_ai_history_completed_at()
117
+ CREATE OR REPLACE FUNCTION update_ai-history_completed_at()
110
118
  RETURNS TRIGGER AS $$
111
119
  BEGIN
112
120
  IF NEW.status IN ('completed', 'failed') AND OLD.status NOT IN ('completed', 'failed') THEN
@@ -116,16 +124,16 @@ BEGIN
116
124
  END;
117
125
  $$ LANGUAGE plpgsql;
118
126
 
119
- CREATE TRIGGER ai_history_completed_at
120
- BEFORE UPDATE ON "ai_history"
127
+ CREATE TRIGGER ai-history_completed_at
128
+ BEFORE UPDATE ON "ai-history"
121
129
  FOR EACH ROW
122
- EXECUTE FUNCTION update_ai_history_completed_at();
130
+ EXECUTE FUNCTION update_ai-history_completed_at();
123
131
 
124
132
  -- =============================================
125
133
  -- CONSTRAINT: Token Split Validation
126
134
  -- =============================================
127
135
  -- Ensures data integrity: tokensUsed = tokensInput + tokensOutput when both present
128
- ALTER TABLE "ai_history"
136
+ ALTER TABLE "ai-history"
129
137
  ADD CONSTRAINT chk_tokens_sum
130
138
  CHECK (
131
139
  ("tokensInput" IS NULL AND "tokensOutput" IS NULL)
@@ -136,23 +144,24 @@ CHECK (
136
144
  -- =============================================
137
145
  -- COMMENTS
138
146
  -- =============================================
139
- COMMENT ON TABLE "ai_history" IS 'Generic audit trail for AI interactions with cost and performance metrics';
140
- COMMENT ON COLUMN "ai_history"."userId" IS 'User who initiated the AI operation';
141
- COMMENT ON COLUMN "ai_history"."relatedEntityType" IS 'Type of entity this operation relates to (e.g., ''contents'', ''products'', ''campaigns'')';
142
- COMMENT ON COLUMN "ai_history"."relatedEntityId" IS 'ID of the related entity (polymorphic relationship)';
143
- COMMENT ON COLUMN "ai_history".operation IS 'Type of AI operation: generate, refine, analyze, chat, completion, or other';
144
- COMMENT ON COLUMN "ai_history".model IS 'AI model used (e.g., claude-3-5-sonnet-20241022, gpt-4)';
145
- COMMENT ON COLUMN "ai_history".provider IS 'AI provider: anthropic, openai, etc.';
146
- COMMENT ON COLUMN "ai_history".status IS 'Processing status: pending, processing, completed, or failed';
147
- COMMENT ON COLUMN "ai_history"."tokensUsed" IS 'Total tokens consumed (input + output) - kept for backward compatibility';
148
- COMMENT ON COLUMN "ai_history"."tokensInput" IS 'Input tokens (prompt) - for precise cost calculation with asymmetric pricing';
149
- COMMENT ON COLUMN "ai_history"."tokensOutput" IS 'Output tokens (completion) - for precise cost calculation with asymmetric pricing';
150
- COMMENT ON COLUMN "ai_history"."creditsUsed" IS 'Credits deducted for this operation';
151
- COMMENT ON COLUMN "ai_history"."estimatedCost" IS 'Cost in USD based on model pricing';
152
- COMMENT ON COLUMN "ai_history"."balanceAfter" IS 'User credit balance after this operation';
153
- COMMENT ON COLUMN "ai_history"."errorMessage" IS 'Error message if operation failed';
154
- COMMENT ON COLUMN "ai_history"."createdAt" IS 'When the AI operation was initiated';
155
- COMMENT ON COLUMN "ai_history"."completedAt" IS 'When the AI operation finished (success or failure)';
147
+ COMMENT ON TABLE "ai-history" IS 'Generic audit trail for AI interactions with cost and performance metrics';
148
+ COMMENT ON COLUMN "ai-history"."userId" IS 'User who initiated the AI operation';
149
+ COMMENT ON COLUMN "ai-history"."relatedEntityType" IS 'Type of entity this operation relates to (e.g., ''contents'', ''products'', ''campaigns'')';
150
+ COMMENT ON COLUMN "ai-history"."relatedEntityId" IS 'ID of the related entity (polymorphic relationship)';
151
+ COMMENT ON COLUMN "ai-history".operation IS 'Type of AI operation: generate, refine, analyze, chat, completion, or other';
152
+ COMMENT ON COLUMN "ai-history".model IS 'AI model used (e.g., claude-3-5-sonnet-20241022, gpt-4)';
153
+ COMMENT ON COLUMN "ai-history".provider IS 'AI provider: anthropic, openai, etc.';
154
+ COMMENT ON COLUMN "ai-history".status IS 'Processing status: pending, processing, completed, or failed';
155
+ COMMENT ON COLUMN "ai-history"."tokensUsed" IS 'Total tokens consumed (input + output) - kept for backward compatibility';
156
+ COMMENT ON COLUMN "ai-history"."tokensInput" IS 'Input tokens (prompt) - for precise cost calculation with asymmetric pricing';
157
+ COMMENT ON COLUMN "ai-history"."tokensOutput" IS 'Output tokens (completion) - for precise cost calculation with asymmetric pricing';
158
+ COMMENT ON COLUMN "ai-history"."creditsUsed" IS 'Credits deducted for this operation';
159
+ COMMENT ON COLUMN "ai-history"."estimatedCost" IS 'Cost in USD based on model pricing';
160
+ COMMENT ON COLUMN "ai-history"."balanceAfter" IS 'User credit balance after this operation';
161
+ COMMENT ON COLUMN "ai-history"."errorMessage" IS 'Error message if operation failed';
162
+ COMMENT ON COLUMN "ai-history"."createdAt" IS 'When the AI operation was initiated';
163
+ COMMENT ON COLUMN "ai-history"."updatedAt" IS 'When the record was last updated';
164
+ COMMENT ON COLUMN "ai-history"."completedAt" IS 'When the AI operation finished (success or failure)';
156
165
 
157
166
  -- =============================================
158
167
  -- MIGRATION COMPLETE
@@ -162,6 +171,6 @@ DO $$
162
171
  BEGIN
163
172
  RAISE NOTICE 'AI History entity migration completed successfully!';
164
173
  RAISE NOTICE 'Plugin: ai';
165
- RAISE NOTICE 'Table created: ai_history';
174
+ RAISE NOTICE 'Table created: ai-history';
166
175
  RAISE NOTICE 'RLS policies enabled for user isolation';
167
176
  END $$;
@@ -4,7 +4,7 @@
4
4
  -- Entity: ai-history
5
5
  -- =============================================
6
6
  --
7
- -- This migration adds comprehensive metadata capabilities through ai_history_metas table
7
+ -- This migration adds comprehensive metadata capabilities through ai-history_metas table
8
8
  --
9
9
  -- Purpose: Flexible metadata storage for AI operations
10
10
  -- - Better query performance (indexed key-value lookups)
@@ -29,9 +29,9 @@
29
29
  -- AI_HISTORY_METAS TABLE
30
30
  -- =============================================
31
31
 
32
- CREATE TABLE IF NOT EXISTS public."ai_history_metas" (
32
+ CREATE TABLE IF NOT EXISTS public."ai-history_metas" (
33
33
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
34
- "entityId" TEXT NOT NULL REFERENCES public."ai_history"(id) ON DELETE CASCADE,
34
+ "entityId" TEXT NOT NULL REFERENCES public."ai-history"(id) ON DELETE CASCADE,
35
35
  "metaKey" TEXT NOT NULL,
36
36
  "metaValue" JSONB NOT NULL DEFAULT '{}'::jsonb,
37
37
  "dataType" TEXT DEFAULT 'json' CHECK ("dataType" IN ('string', 'number', 'boolean', 'json', 'array')),
@@ -41,54 +41,54 @@ CREATE TABLE IF NOT EXISTS public."ai_history_metas" (
41
41
  "updatedAt" TIMESTAMPTZ NOT NULL DEFAULT now(),
42
42
 
43
43
  -- Prevent duplicate keys per history record
44
- CONSTRAINT ai_history_metas_unique_key UNIQUE ("entityId", "metaKey")
44
+ CONSTRAINT ai-history_metas_unique_key UNIQUE ("entityId", "metaKey")
45
45
  );
46
46
 
47
47
  -- Trigger for auto-updating updatedAt (using Better Auth's function)
48
- CREATE TRIGGER ai_history_metas_set_updated_at
49
- BEFORE UPDATE ON public."ai_history_metas"
48
+ CREATE TRIGGER ai-history_metas_set_updated_at
49
+ BEFORE UPDATE ON public."ai-history_metas"
50
50
  FOR EACH ROW EXECUTE FUNCTION public.set_updated_at();
51
51
 
52
52
  -- Indexes for efficient queries
53
- CREATE INDEX idx_ai_history_metas_entity_id ON public."ai_history_metas"("entityId");
54
- CREATE INDEX idx_ai_history_metas_key ON public."ai_history_metas"("metaKey");
55
- CREATE INDEX idx_ai_history_metas_composite ON public."ai_history_metas"("entityId", "metaKey");
53
+ CREATE INDEX idx_ai-history_metas_entity_id ON public."ai-history_metas"("entityId");
54
+ CREATE INDEX idx_ai-history_metas_key ON public."ai-history_metas"("metaKey");
55
+ CREATE INDEX idx_ai-history_metas_composite ON public."ai-history_metas"("entityId", "metaKey");
56
56
 
57
57
  -- GIN index for JSONB queries (enables @>, ?, ?&, ?| operators)
58
- CREATE INDEX idx_ai_history_metas_value_gin ON public."ai_history_metas" USING GIN ("metaValue");
58
+ CREATE INDEX idx_ai-history_metas_value_gin ON public."ai-history_metas" USING GIN ("metaValue");
59
59
 
60
60
  -- RLS Policies
61
- ALTER TABLE public."ai_history_metas" ENABLE ROW LEVEL SECURITY;
61
+ ALTER TABLE public."ai-history_metas" ENABLE ROW LEVEL SECURITY;
62
62
 
63
63
  -- Cleanup existing policies
64
- DROP POLICY IF EXISTS "AI history metas owner can do all" ON public."ai_history_metas";
65
- DROP POLICY IF EXISTS "AI history metas inherit parent access" ON public."ai_history_metas";
64
+ DROP POLICY IF EXISTS "AI history metas owner can do all" ON public."ai-history_metas";
65
+ DROP POLICY IF EXISTS "AI history metas inherit parent access" ON public."ai-history_metas";
66
66
 
67
- -- Policy: Inherit access from parent ai_history record
67
+ -- Policy: Inherit access from parent ai-history record
68
68
  CREATE POLICY "AI history metas inherit parent access"
69
- ON public."ai_history_metas"
69
+ ON public."ai-history_metas"
70
70
  FOR ALL TO authenticated
71
71
  USING (
72
72
  EXISTS (
73
- SELECT 1 FROM public."ai_history"
74
- WHERE "ai_history".id = "ai_history_metas"."entityId"
75
- AND "ai_history"."userId" = public.get_auth_user_id()
73
+ SELECT 1 FROM public."ai-history"
74
+ WHERE "ai-history".id = "ai-history_metas"."entityId"
75
+ AND "ai-history"."userId" = public.get_auth_user_id()
76
76
  )
77
77
  )
78
78
  WITH CHECK (
79
79
  EXISTS (
80
- SELECT 1 FROM public."ai_history"
81
- WHERE "ai_history".id = "ai_history_metas"."entityId"
82
- AND "ai_history"."userId" = public.get_auth_user_id()
80
+ SELECT 1 FROM public."ai-history"
81
+ WHERE "ai-history".id = "ai-history_metas"."entityId"
82
+ AND "ai-history"."userId" = public.get_auth_user_id()
83
83
  )
84
84
  );
85
85
 
86
86
  -- Comments for documentation
87
- COMMENT ON TABLE public."ai_history_metas" IS 'Flexible metadata storage for AI history records. Supports any key-value pairs with JSONB values.';
88
- COMMENT ON COLUMN public."ai_history_metas"."metaValue" IS 'JSONB value allows storing any data structure (string, number, boolean, object, array)';
89
- COMMENT ON COLUMN public."ai_history_metas"."dataType" IS 'Hint for parsing metaValue on client side (actual type is always JSONB in DB)';
90
- COMMENT ON COLUMN public."ai_history_metas"."isPublic" IS 'Whether this meta is publicly accessible or private to owner';
91
- COMMENT ON COLUMN public."ai_history_metas"."isSearchable" IS 'Whether this meta should be included in search operations';
87
+ COMMENT ON TABLE public."ai-history_metas" IS 'Flexible metadata storage for AI history records. Supports any key-value pairs with JSONB values.';
88
+ COMMENT ON COLUMN public."ai-history_metas"."metaValue" IS 'JSONB value allows storing any data structure (string, number, boolean, object, array)';
89
+ COMMENT ON COLUMN public."ai-history_metas"."dataType" IS 'Hint for parsing metaValue on client side (actual type is always JSONB in DB)';
90
+ COMMENT ON COLUMN public."ai-history_metas"."isPublic" IS 'Whether this meta is publicly accessible or private to owner';
91
+ COMMENT ON COLUMN public."ai-history_metas"."isSearchable" IS 'Whether this meta should be included in search operations';
92
92
 
93
93
  -- =============================================
94
94
  -- MIGRATION COMPLETE
@@ -97,7 +97,7 @@ COMMENT ON COLUMN public."ai_history_metas"."isSearchable" IS 'Whether this meta
97
97
  DO $$
98
98
  BEGIN
99
99
  RAISE NOTICE 'AI History metadata migration completed successfully!';
100
- RAISE NOTICE 'Created: ai_history_metas table for flexible metadata';
100
+ RAISE NOTICE 'Created: ai-history_metas table for flexible metadata';
101
101
  RAISE NOTICE 'Performance: GIN indexes for fast JSONB queries';
102
- RAISE NOTICE 'Security: RLS policies enabled on ai_history_metas';
102
+ RAISE NOTICE 'Security: RLS policies enabled on ai-history_metas';
103
103
  END $$;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/plugin-ai",
3
- "version": "0.1.0-beta.68",
3
+ "version": "0.1.0-beta.73",
4
4
  "private": false,
5
5
  "main": "./plugin.config.ts",
6
6
  "requiredPlugins": [],
@@ -12,16 +12,16 @@
12
12
  "ollama-ai-provider": "^1.2.0"
13
13
  },
14
14
  "peerDependencies": {
15
+ "@nextsparkjs/core": "workspace:*",
15
16
  "@tanstack/react-query": "^5.0.0",
16
17
  "lucide-react": "^0.539.0",
17
18
  "next": "^15.0.0",
18
19
  "react": "^19.0.0",
19
20
  "react-dom": "^19.0.0",
20
- "zod": "^4.0.0",
21
- "@nextsparkjs/core": "0.1.0-beta.68"
21
+ "zod": "^4.0.0"
22
22
  },
23
23
  "nextspark": {
24
24
  "type": "plugin",
25
25
  "name": "ai"
26
26
  }
27
- }
27
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 NextSpark
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.