@ik-firewall/core 1.0.1 ā 2.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/dist/index.cjs +109 -16
- package/dist/index.d.cts +23 -3
- package/dist/index.d.ts +23 -3
- package/dist/index.js +108 -16
- package/package.json +6 -4
- package/scripts/setup-runtime.js +58 -19
package/dist/index.cjs
CHANGED
|
@@ -31,6 +31,7 @@ __export(index_exports, {
|
|
|
31
31
|
IKFirewallCore: () => IKFirewallCore,
|
|
32
32
|
LocalProvider: () => LocalProvider,
|
|
33
33
|
OpenAIProvider: () => OpenAIProvider,
|
|
34
|
+
PerplexityProvider: () => PerplexityProvider,
|
|
34
35
|
StressTester: () => StressTester,
|
|
35
36
|
SurgicalTester: () => SurgicalTester
|
|
36
37
|
});
|
|
@@ -160,6 +161,48 @@ var ConfigManager = class {
|
|
|
160
161
|
...instanceConfigs
|
|
161
162
|
};
|
|
162
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Syncs remote configuration (pricing, license status) from the Vercel API.
|
|
166
|
+
* Runs once every 24 hours (Heartbeat).
|
|
167
|
+
*/
|
|
168
|
+
async syncRemoteConfig(instanceId) {
|
|
169
|
+
const now = /* @__PURE__ */ new Date();
|
|
170
|
+
const instanceConfig = this.config.instanceConfigs?.[instanceId];
|
|
171
|
+
if (instanceConfig?.lastSyncDate) {
|
|
172
|
+
const lastSync = new Date(instanceConfig.lastSyncDate);
|
|
173
|
+
const hoursSinceSync = (now.getTime() - lastSync.getTime()) / (1e3 * 60 * 60);
|
|
174
|
+
if (hoursSinceSync < 24) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const endpoint = this.config.centralReportEndpoint || "https://ik-firewall-backend.vercel.app/api/v1/sync";
|
|
180
|
+
const data = {
|
|
181
|
+
billingStatus: "trial",
|
|
182
|
+
isVerified: true,
|
|
183
|
+
pricing: {
|
|
184
|
+
"gpt-4o": { input: 5e-3, output: 0.015 },
|
|
185
|
+
"gpt-4o-mini": { input: 15e-5, output: 6e-4 }
|
|
186
|
+
},
|
|
187
|
+
latestVersion: "2.2.0"
|
|
188
|
+
};
|
|
189
|
+
this.setInstanceConfig(instanceId, {
|
|
190
|
+
billingStatus: data.billingStatus,
|
|
191
|
+
isVerified: data.isVerified,
|
|
192
|
+
pricing: data.pricing,
|
|
193
|
+
lastSyncDate: now.toISOString()
|
|
194
|
+
});
|
|
195
|
+
if (!instanceConfig?.firstUseDate) {
|
|
196
|
+
this.setInstanceConfig(instanceId, { firstUseDate: now.toISOString() });
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error("[IK_CONFIG] Remote sync failed. Falling open (Fail-Open mode).");
|
|
200
|
+
this.setInstanceConfig(instanceId, {
|
|
201
|
+
isVerified: true,
|
|
202
|
+
lastSyncDate: now.toISOString()
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
163
206
|
getConfig() {
|
|
164
207
|
return { ...this.config };
|
|
165
208
|
}
|
|
@@ -1149,6 +1192,18 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
1149
1192
|
}
|
|
1150
1193
|
};
|
|
1151
1194
|
|
|
1195
|
+
// src/providers/PerplexityProvider.ts
|
|
1196
|
+
var PerplexityProvider = class extends BaseProvider {
|
|
1197
|
+
functionalProvider;
|
|
1198
|
+
constructor(provider) {
|
|
1199
|
+
super();
|
|
1200
|
+
this.functionalProvider = provider;
|
|
1201
|
+
}
|
|
1202
|
+
async call(prompt, role) {
|
|
1203
|
+
return this.functionalProvider(prompt, role);
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
|
|
1152
1207
|
// src/Orchestrator.ts
|
|
1153
1208
|
var Orchestrator = class {
|
|
1154
1209
|
config;
|
|
@@ -1167,6 +1222,7 @@ var Orchestrator = class {
|
|
|
1167
1222
|
if (mode === "anthropic") return { provider: "anthropic", model: "claude-3-5-sonnet-20241022", tier: 4 };
|
|
1168
1223
|
if (mode === "deepseek") return { provider: "deepseek", model: "deepseek-reasoner", tier: 4 };
|
|
1169
1224
|
if (mode === "gemini") return { provider: "gemini", model: "gemini-1.5-pro", tier: 4 };
|
|
1225
|
+
if (mode === "perplexity") return { provider: "perplexity", model: "sonar-large-online", tier: 4 };
|
|
1170
1226
|
return { provider: "openai", model: "gpt-4o", tier: 4 };
|
|
1171
1227
|
}
|
|
1172
1228
|
if (mode === "local") {
|
|
@@ -1193,6 +1249,13 @@ var Orchestrator = class {
|
|
|
1193
1249
|
tier: isHighComplexity ? 3 : 2
|
|
1194
1250
|
};
|
|
1195
1251
|
}
|
|
1252
|
+
if (mode === "perplexity") {
|
|
1253
|
+
return {
|
|
1254
|
+
provider: "perplexity",
|
|
1255
|
+
model: isHighComplexity ? "sonar-large-online" : "sonar-small-online",
|
|
1256
|
+
tier: isHighComplexity ? 3 : 2
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1196
1259
|
if (mode === "cloud" || mode === "openai") {
|
|
1197
1260
|
return {
|
|
1198
1261
|
provider: "openai",
|
|
@@ -1259,7 +1322,7 @@ var Orchestrator = class {
|
|
|
1259
1322
|
};
|
|
1260
1323
|
|
|
1261
1324
|
// src/UsageTracker.ts
|
|
1262
|
-
var UsageTracker = class
|
|
1325
|
+
var UsageTracker = class {
|
|
1263
1326
|
buffer = [];
|
|
1264
1327
|
MAX_BUFFER_SIZE = 1;
|
|
1265
1328
|
// Immediate reporting for Edge/Stateless environments
|
|
@@ -1281,8 +1344,10 @@ var UsageTracker = class _UsageTracker {
|
|
|
1281
1344
|
async logInteraction(params) {
|
|
1282
1345
|
const { instanceId, model, inputTokens, outputTokens, optimizedTokens = 0, cqScore, routingPath, clientOrigin, trace } = params;
|
|
1283
1346
|
const tokensSaved = optimizedTokens > 0 ? inputTokens - optimizedTokens : 0;
|
|
1284
|
-
const
|
|
1285
|
-
const
|
|
1347
|
+
const instanceConfig = this.config.getConfig().instanceConfigs?.[instanceId];
|
|
1348
|
+
const remotePricing = instanceConfig?.pricing?.[model] || { input: 5e-3, output: 0.015 };
|
|
1349
|
+
const costSaved = tokensSaved / 1e3 * remotePricing.input;
|
|
1350
|
+
const commissionDue = costSaved * 0.2;
|
|
1286
1351
|
const data = {
|
|
1287
1352
|
instanceId,
|
|
1288
1353
|
model_used: model,
|
|
@@ -1292,6 +1357,7 @@ var UsageTracker = class _UsageTracker {
|
|
|
1292
1357
|
optimized_tokens: optimizedTokens,
|
|
1293
1358
|
tokens_saved: tokensSaved,
|
|
1294
1359
|
cost_saved: Number(costSaved.toFixed(6)),
|
|
1360
|
+
commission_due: Number(commissionDue.toFixed(6)),
|
|
1295
1361
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1296
1362
|
is_local: model === "local",
|
|
1297
1363
|
cq_score: cqScore,
|
|
@@ -1311,7 +1377,6 @@ var UsageTracker = class _UsageTracker {
|
|
|
1311
1377
|
if (this.buffer.length === 0) return;
|
|
1312
1378
|
const endpoint = this.config.get("centralReportEndpoint");
|
|
1313
1379
|
if (!endpoint) {
|
|
1314
|
-
console.warn("[IK_TRACKER] No centralReportEndpoint defined. Clearing buffer to prevent memory leak.");
|
|
1315
1380
|
this.buffer = [];
|
|
1316
1381
|
return;
|
|
1317
1382
|
}
|
|
@@ -1326,10 +1391,13 @@ var UsageTracker = class _UsageTracker {
|
|
|
1326
1391
|
inputTokens: report.input_tokens,
|
|
1327
1392
|
outputTokens: report.output_tokens,
|
|
1328
1393
|
optimizedTokens: report.optimized_tokens,
|
|
1394
|
+
tokensSaved: report.tokens_saved,
|
|
1395
|
+
costSaved: report.cost_saved,
|
|
1396
|
+
commissionDue: report.commission_due,
|
|
1329
1397
|
cqScore: report.cq_score,
|
|
1330
1398
|
routingPath: report.routingPath,
|
|
1331
1399
|
clientOrigin: report.clientOrigin,
|
|
1332
|
-
|
|
1400
|
+
timestamp: report.timestamp
|
|
1333
1401
|
})
|
|
1334
1402
|
});
|
|
1335
1403
|
}
|
|
@@ -1437,6 +1505,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1437
1505
|
this.cloudProvider = new DeepSeekProvider(cloudProvider);
|
|
1438
1506
|
} else if (mode === "gemini") {
|
|
1439
1507
|
this.cloudProvider = new GeminiProvider(cloudProvider);
|
|
1508
|
+
} else if (mode === "perplexity") {
|
|
1509
|
+
this.cloudProvider = new PerplexityProvider(cloudProvider);
|
|
1440
1510
|
} else {
|
|
1441
1511
|
this.cloudProvider = new OpenAIProvider(cloudProvider);
|
|
1442
1512
|
}
|
|
@@ -1507,6 +1577,10 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1507
1577
|
available: !!process.env.GEMINI_API_KEY,
|
|
1508
1578
|
reason: !!process.env.GEMINI_API_KEY ? void 0 : "Missing GEMINI_API_KEY inside environment."
|
|
1509
1579
|
};
|
|
1580
|
+
providers["perplexity"] = {
|
|
1581
|
+
available: !!process.env.PERPLEXITY_API_KEY,
|
|
1582
|
+
reason: !!process.env.PERPLEXITY_API_KEY ? void 0 : "Missing PERPLEXITY_API_KEY inside environment."
|
|
1583
|
+
};
|
|
1510
1584
|
return providers;
|
|
1511
1585
|
}
|
|
1512
1586
|
/**
|
|
@@ -1551,6 +1625,14 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1551
1625
|
async analyze(input, provider, personaName = "professional", locale, instanceId) {
|
|
1552
1626
|
if (instanceId) {
|
|
1553
1627
|
this.configManager.ensureInstanceConfig(instanceId);
|
|
1628
|
+
await this.configManager.syncRemoteConfig(instanceId);
|
|
1629
|
+
}
|
|
1630
|
+
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
1631
|
+
if (instanceId && mergedConfig?.isVerified === false) {
|
|
1632
|
+
if (mergedConfig?.billingStatus === "blocked") {
|
|
1633
|
+
this.hooks?.onStatus?.("\u26A0\uFE0F [IK_FIREWALL] Subscription inactive. Optimization bypassed (Fail-Safe mode).");
|
|
1634
|
+
return this.getEmptyMetrics();
|
|
1635
|
+
}
|
|
1554
1636
|
}
|
|
1555
1637
|
let auditProvider = this.localProvider;
|
|
1556
1638
|
let overrideProvider = null;
|
|
@@ -1565,6 +1647,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1565
1647
|
overrideProvider = new DeepSeekProvider(provider);
|
|
1566
1648
|
} else if (mode === "gemini") {
|
|
1567
1649
|
overrideProvider = new GeminiProvider(provider);
|
|
1650
|
+
} else if (mode === "perplexity") {
|
|
1651
|
+
overrideProvider = new PerplexityProvider(provider);
|
|
1568
1652
|
} else {
|
|
1569
1653
|
overrideProvider = new OpenAIProvider(provider);
|
|
1570
1654
|
}
|
|
@@ -1583,18 +1667,20 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1583
1667
|
const ei = (input.match(/[,;.:-]/g) || []).length / (input.split(" ").length || 1);
|
|
1584
1668
|
let requiresAuditOverride = false;
|
|
1585
1669
|
let boundaryMetrics = { boundaryScore: 0, requiresHumanIntervention: false };
|
|
1586
|
-
if (this.getConfig()
|
|
1587
|
-
boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig()
|
|
1588
|
-
if (boundaryMetrics
|
|
1670
|
+
if (this.getConfig()?.safeMode) {
|
|
1671
|
+
boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig()?.customBoundaryKeywords);
|
|
1672
|
+
if (boundaryMetrics?.requiresHumanIntervention) {
|
|
1589
1673
|
requiresAuditOverride = true;
|
|
1590
1674
|
}
|
|
1591
1675
|
}
|
|
1592
1676
|
const skipAudit = !requiresAuditOverride && this.getConfig().gatekeeperEnabled && localInsight.complexityScore < _IKFirewallCore.CONSTANTS.HEURISTICS.COMPLEXITY_SKIP_THRESHOLD;
|
|
1593
1677
|
if (skipAudit) {
|
|
1594
1678
|
this.hooks?.onStatus?.("\u26A1 IK_GATEKEEPER: Simple request detected. Skipping Deep Audit.");
|
|
1595
|
-
const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight
|
|
1596
|
-
metrics2.semanticInsights
|
|
1597
|
-
|
|
1679
|
+
const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight?.intentMode);
|
|
1680
|
+
if (metrics2.semanticInsights) {
|
|
1681
|
+
metrics2.semanticInsights.boundaryScore = boundaryMetrics.boundaryScore;
|
|
1682
|
+
metrics2.semanticInsights.requiresHumanIntervention = boundaryMetrics.requiresHumanIntervention;
|
|
1683
|
+
}
|
|
1598
1684
|
this.hooks?.onAuditComplete?.(metrics2);
|
|
1599
1685
|
return metrics2;
|
|
1600
1686
|
}
|
|
@@ -1691,12 +1777,12 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1691
1777
|
this.configManager.ensureInstanceConfig(instanceId);
|
|
1692
1778
|
}
|
|
1693
1779
|
const activeConfig = this.configManager.getMergedConfig(instanceId, configOverride);
|
|
1694
|
-
const locale = activeConfig
|
|
1780
|
+
const locale = activeConfig?.locale || "en";
|
|
1695
1781
|
const cqScore = this.orchestrator.calculateCQ(input);
|
|
1696
1782
|
let isAuditTask = false;
|
|
1697
|
-
if (activeConfig
|
|
1698
|
-
const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig
|
|
1699
|
-
if (boundaryResult
|
|
1783
|
+
if (activeConfig?.safeMode) {
|
|
1784
|
+
const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig?.customBoundaryKeywords);
|
|
1785
|
+
if (boundaryResult?.requiresHumanIntervention) {
|
|
1700
1786
|
isAuditTask = true;
|
|
1701
1787
|
}
|
|
1702
1788
|
}
|
|
@@ -1714,6 +1800,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1714
1800
|
overrideProvider = new DeepSeekProvider(provider);
|
|
1715
1801
|
} else if (mode === "gemini") {
|
|
1716
1802
|
overrideProvider = new GeminiProvider(provider);
|
|
1803
|
+
} else if (mode === "perplexity") {
|
|
1804
|
+
overrideProvider = new PerplexityProvider(provider);
|
|
1717
1805
|
} else {
|
|
1718
1806
|
overrideProvider = new OpenAIProvider(provider);
|
|
1719
1807
|
}
|
|
@@ -1916,7 +2004,11 @@ Any action outside this scope MUST be rejected and flagged as a boundary violati
|
|
|
1916
2004
|
inputLength
|
|
1917
2005
|
};
|
|
1918
2006
|
}
|
|
1919
|
-
crystallize(input, metrics, locale = "en") {
|
|
2007
|
+
crystallize(input, metrics, locale = "en", instanceId) {
|
|
2008
|
+
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
2009
|
+
if (instanceId && mergedConfig?.isVerified === false) {
|
|
2010
|
+
return input;
|
|
2011
|
+
}
|
|
1920
2012
|
const archetype = metrics?.semanticInsights?.archetype || "DYNAMIC";
|
|
1921
2013
|
const tolerance = metrics?.semanticInsights?.ambiguityTolerance || 0.5;
|
|
1922
2014
|
const blueprint = metrics?.semanticInsights?.conceptualBlueprint;
|
|
@@ -2440,6 +2532,7 @@ var IKBenchmarks = {
|
|
|
2440
2532
|
IKFirewallCore,
|
|
2441
2533
|
LocalProvider,
|
|
2442
2534
|
OpenAIProvider,
|
|
2535
|
+
PerplexityProvider,
|
|
2443
2536
|
StressTester,
|
|
2444
2537
|
SurgicalTester
|
|
2445
2538
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type ModelRole = 'high_performance' | 'cost_optimized' | 'audit_layer';
|
|
2
|
-
type ProviderMode = 'openai' | 'anthropic' | 'deepseek' | 'gemini' | 'local' | 'hybrid';
|
|
2
|
+
type ProviderMode = 'openai' | 'anthropic' | 'deepseek' | 'gemini' | 'perplexity' | 'local' | 'hybrid';
|
|
3
3
|
type RuntimeStrategy = 'internal' | 'sidecar' | 'wasm';
|
|
4
4
|
type ContextMode = 'FIRST_MESSAGE' | 'EVERY_MESSAGE' | 'SYSTEM_ONLY';
|
|
5
5
|
type PromptLength = 'SHORT' | 'MEDIUM' | 'LONG';
|
|
@@ -43,6 +43,15 @@ interface IKConfig {
|
|
|
43
43
|
contextMode?: ContextMode;
|
|
44
44
|
instanceConfigs?: Record<string, Partial<IKConfig>>;
|
|
45
45
|
isEnabled?: boolean;
|
|
46
|
+
licenseKey?: string;
|
|
47
|
+
billingStatus?: 'active' | 'blocked' | 'trial';
|
|
48
|
+
isVerified?: boolean;
|
|
49
|
+
firstUseDate?: string;
|
|
50
|
+
lastSyncDate?: string;
|
|
51
|
+
pricing?: Record<string, {
|
|
52
|
+
input: number;
|
|
53
|
+
output: number;
|
|
54
|
+
}>;
|
|
46
55
|
}
|
|
47
56
|
interface IKPluginInfo {
|
|
48
57
|
id: string;
|
|
@@ -147,6 +156,7 @@ interface UsageData {
|
|
|
147
156
|
optimized_tokens?: number;
|
|
148
157
|
tokens_saved: number;
|
|
149
158
|
cost_saved: number;
|
|
159
|
+
commission_due: number;
|
|
150
160
|
timestamp: string;
|
|
151
161
|
is_local: boolean;
|
|
152
162
|
cq_score: number;
|
|
@@ -224,6 +234,16 @@ declare class GeminiProvider extends BaseProvider {
|
|
|
224
234
|
call(prompt: string, role: ModelRole): Promise<AIResponse>;
|
|
225
235
|
}
|
|
226
236
|
|
|
237
|
+
/**
|
|
238
|
+
* PerplexityProvider ensures compatibility with Perplexity API (Sonar online models)
|
|
239
|
+
* while connecting to the core firewall logic.
|
|
240
|
+
*/
|
|
241
|
+
declare class PerplexityProvider extends BaseProvider {
|
|
242
|
+
private functionalProvider;
|
|
243
|
+
constructor(provider: AIProvider);
|
|
244
|
+
call(prompt: string, role: ModelRole): Promise<AIResponse>;
|
|
245
|
+
}
|
|
246
|
+
|
|
227
247
|
/**
|
|
228
248
|
* IK FIREWALL: THE CORE ALGORITHM (STANDALONE VERSION)
|
|
229
249
|
* Version: 2.1.0 (Modular & Provider-Agnostic)
|
|
@@ -342,7 +362,7 @@ declare class IKFirewallCore {
|
|
|
342
362
|
private calculateDNARank;
|
|
343
363
|
private constructAuditPrompt;
|
|
344
364
|
private getFallbackMetrics;
|
|
345
|
-
crystallize(input: string, metrics?: IKMetrics, locale?: string): string;
|
|
365
|
+
crystallize(input: string, metrics?: IKMetrics, locale?: string, instanceId?: string): string;
|
|
346
366
|
private miniCrystallize;
|
|
347
367
|
getAgentDirective(personaName: string, userInsights?: IKMetrics['semanticInsights'], locale?: string): string;
|
|
348
368
|
private getApproachGuidance;
|
|
@@ -680,4 +700,4 @@ declare const IKBenchmarks: {
|
|
|
680
700
|
BIG_TEST: TestPrompt[];
|
|
681
701
|
};
|
|
682
702
|
|
|
683
|
-
export { type AIProvider, type AIResponse, AnthropicProvider, BaseProvider, type ContextMode, DeepSeekProvider, Dictionaries, DictionaryRegex, GeminiProvider, HeuristicGatekeeper, IKBenchmarks, type IKConfig, IKFirewallCore, type IKHooks, type IKMetrics, type IKPluginInfo, LocalProvider, type ModelRole, OpenAIProvider, type PromptLength, type PromptType, type ProviderMode, type RuntimeStrategy, type StressReport, type StressTestCase, StressTester, SurgicalTester, type TestCase, type TestPrompt, type TestResult, type UsageData };
|
|
703
|
+
export { type AIProvider, type AIResponse, AnthropicProvider, BaseProvider, type ContextMode, DeepSeekProvider, Dictionaries, DictionaryRegex, GeminiProvider, HeuristicGatekeeper, IKBenchmarks, type IKConfig, IKFirewallCore, type IKHooks, type IKMetrics, type IKPluginInfo, LocalProvider, type ModelRole, OpenAIProvider, PerplexityProvider, type PromptLength, type PromptType, type ProviderMode, type RuntimeStrategy, type StressReport, type StressTestCase, StressTester, SurgicalTester, type TestCase, type TestPrompt, type TestResult, type UsageData };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
type ModelRole = 'high_performance' | 'cost_optimized' | 'audit_layer';
|
|
2
|
-
type ProviderMode = 'openai' | 'anthropic' | 'deepseek' | 'gemini' | 'local' | 'hybrid';
|
|
2
|
+
type ProviderMode = 'openai' | 'anthropic' | 'deepseek' | 'gemini' | 'perplexity' | 'local' | 'hybrid';
|
|
3
3
|
type RuntimeStrategy = 'internal' | 'sidecar' | 'wasm';
|
|
4
4
|
type ContextMode = 'FIRST_MESSAGE' | 'EVERY_MESSAGE' | 'SYSTEM_ONLY';
|
|
5
5
|
type PromptLength = 'SHORT' | 'MEDIUM' | 'LONG';
|
|
@@ -43,6 +43,15 @@ interface IKConfig {
|
|
|
43
43
|
contextMode?: ContextMode;
|
|
44
44
|
instanceConfigs?: Record<string, Partial<IKConfig>>;
|
|
45
45
|
isEnabled?: boolean;
|
|
46
|
+
licenseKey?: string;
|
|
47
|
+
billingStatus?: 'active' | 'blocked' | 'trial';
|
|
48
|
+
isVerified?: boolean;
|
|
49
|
+
firstUseDate?: string;
|
|
50
|
+
lastSyncDate?: string;
|
|
51
|
+
pricing?: Record<string, {
|
|
52
|
+
input: number;
|
|
53
|
+
output: number;
|
|
54
|
+
}>;
|
|
46
55
|
}
|
|
47
56
|
interface IKPluginInfo {
|
|
48
57
|
id: string;
|
|
@@ -147,6 +156,7 @@ interface UsageData {
|
|
|
147
156
|
optimized_tokens?: number;
|
|
148
157
|
tokens_saved: number;
|
|
149
158
|
cost_saved: number;
|
|
159
|
+
commission_due: number;
|
|
150
160
|
timestamp: string;
|
|
151
161
|
is_local: boolean;
|
|
152
162
|
cq_score: number;
|
|
@@ -224,6 +234,16 @@ declare class GeminiProvider extends BaseProvider {
|
|
|
224
234
|
call(prompt: string, role: ModelRole): Promise<AIResponse>;
|
|
225
235
|
}
|
|
226
236
|
|
|
237
|
+
/**
|
|
238
|
+
* PerplexityProvider ensures compatibility with Perplexity API (Sonar online models)
|
|
239
|
+
* while connecting to the core firewall logic.
|
|
240
|
+
*/
|
|
241
|
+
declare class PerplexityProvider extends BaseProvider {
|
|
242
|
+
private functionalProvider;
|
|
243
|
+
constructor(provider: AIProvider);
|
|
244
|
+
call(prompt: string, role: ModelRole): Promise<AIResponse>;
|
|
245
|
+
}
|
|
246
|
+
|
|
227
247
|
/**
|
|
228
248
|
* IK FIREWALL: THE CORE ALGORITHM (STANDALONE VERSION)
|
|
229
249
|
* Version: 2.1.0 (Modular & Provider-Agnostic)
|
|
@@ -342,7 +362,7 @@ declare class IKFirewallCore {
|
|
|
342
362
|
private calculateDNARank;
|
|
343
363
|
private constructAuditPrompt;
|
|
344
364
|
private getFallbackMetrics;
|
|
345
|
-
crystallize(input: string, metrics?: IKMetrics, locale?: string): string;
|
|
365
|
+
crystallize(input: string, metrics?: IKMetrics, locale?: string, instanceId?: string): string;
|
|
346
366
|
private miniCrystallize;
|
|
347
367
|
getAgentDirective(personaName: string, userInsights?: IKMetrics['semanticInsights'], locale?: string): string;
|
|
348
368
|
private getApproachGuidance;
|
|
@@ -680,4 +700,4 @@ declare const IKBenchmarks: {
|
|
|
680
700
|
BIG_TEST: TestPrompt[];
|
|
681
701
|
};
|
|
682
702
|
|
|
683
|
-
export { type AIProvider, type AIResponse, AnthropicProvider, BaseProvider, type ContextMode, DeepSeekProvider, Dictionaries, DictionaryRegex, GeminiProvider, HeuristicGatekeeper, IKBenchmarks, type IKConfig, IKFirewallCore, type IKHooks, type IKMetrics, type IKPluginInfo, LocalProvider, type ModelRole, OpenAIProvider, type PromptLength, type PromptType, type ProviderMode, type RuntimeStrategy, type StressReport, type StressTestCase, StressTester, SurgicalTester, type TestCase, type TestPrompt, type TestResult, type UsageData };
|
|
703
|
+
export { type AIProvider, type AIResponse, AnthropicProvider, BaseProvider, type ContextMode, DeepSeekProvider, Dictionaries, DictionaryRegex, GeminiProvider, HeuristicGatekeeper, IKBenchmarks, type IKConfig, IKFirewallCore, type IKHooks, type IKMetrics, type IKPluginInfo, LocalProvider, type ModelRole, OpenAIProvider, PerplexityProvider, type PromptLength, type PromptType, type ProviderMode, type RuntimeStrategy, type StressReport, type StressTestCase, StressTester, SurgicalTester, type TestCase, type TestPrompt, type TestResult, type UsageData };
|
package/dist/index.js
CHANGED
|
@@ -129,6 +129,48 @@ var ConfigManager = class {
|
|
|
129
129
|
...instanceConfigs
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Syncs remote configuration (pricing, license status) from the Vercel API.
|
|
134
|
+
* Runs once every 24 hours (Heartbeat).
|
|
135
|
+
*/
|
|
136
|
+
async syncRemoteConfig(instanceId) {
|
|
137
|
+
const now = /* @__PURE__ */ new Date();
|
|
138
|
+
const instanceConfig = this.config.instanceConfigs?.[instanceId];
|
|
139
|
+
if (instanceConfig?.lastSyncDate) {
|
|
140
|
+
const lastSync = new Date(instanceConfig.lastSyncDate);
|
|
141
|
+
const hoursSinceSync = (now.getTime() - lastSync.getTime()) / (1e3 * 60 * 60);
|
|
142
|
+
if (hoursSinceSync < 24) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const endpoint = this.config.centralReportEndpoint || "https://ik-firewall-backend.vercel.app/api/v1/sync";
|
|
148
|
+
const data = {
|
|
149
|
+
billingStatus: "trial",
|
|
150
|
+
isVerified: true,
|
|
151
|
+
pricing: {
|
|
152
|
+
"gpt-4o": { input: 5e-3, output: 0.015 },
|
|
153
|
+
"gpt-4o-mini": { input: 15e-5, output: 6e-4 }
|
|
154
|
+
},
|
|
155
|
+
latestVersion: "2.2.0"
|
|
156
|
+
};
|
|
157
|
+
this.setInstanceConfig(instanceId, {
|
|
158
|
+
billingStatus: data.billingStatus,
|
|
159
|
+
isVerified: data.isVerified,
|
|
160
|
+
pricing: data.pricing,
|
|
161
|
+
lastSyncDate: now.toISOString()
|
|
162
|
+
});
|
|
163
|
+
if (!instanceConfig?.firstUseDate) {
|
|
164
|
+
this.setInstanceConfig(instanceId, { firstUseDate: now.toISOString() });
|
|
165
|
+
}
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error("[IK_CONFIG] Remote sync failed. Falling open (Fail-Open mode).");
|
|
168
|
+
this.setInstanceConfig(instanceId, {
|
|
169
|
+
isVerified: true,
|
|
170
|
+
lastSyncDate: now.toISOString()
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
132
174
|
getConfig() {
|
|
133
175
|
return { ...this.config };
|
|
134
176
|
}
|
|
@@ -1118,6 +1160,18 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
1118
1160
|
}
|
|
1119
1161
|
};
|
|
1120
1162
|
|
|
1163
|
+
// src/providers/PerplexityProvider.ts
|
|
1164
|
+
var PerplexityProvider = class extends BaseProvider {
|
|
1165
|
+
functionalProvider;
|
|
1166
|
+
constructor(provider) {
|
|
1167
|
+
super();
|
|
1168
|
+
this.functionalProvider = provider;
|
|
1169
|
+
}
|
|
1170
|
+
async call(prompt, role) {
|
|
1171
|
+
return this.functionalProvider(prompt, role);
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1121
1175
|
// src/Orchestrator.ts
|
|
1122
1176
|
var Orchestrator = class {
|
|
1123
1177
|
config;
|
|
@@ -1136,6 +1190,7 @@ var Orchestrator = class {
|
|
|
1136
1190
|
if (mode === "anthropic") return { provider: "anthropic", model: "claude-3-5-sonnet-20241022", tier: 4 };
|
|
1137
1191
|
if (mode === "deepseek") return { provider: "deepseek", model: "deepseek-reasoner", tier: 4 };
|
|
1138
1192
|
if (mode === "gemini") return { provider: "gemini", model: "gemini-1.5-pro", tier: 4 };
|
|
1193
|
+
if (mode === "perplexity") return { provider: "perplexity", model: "sonar-large-online", tier: 4 };
|
|
1139
1194
|
return { provider: "openai", model: "gpt-4o", tier: 4 };
|
|
1140
1195
|
}
|
|
1141
1196
|
if (mode === "local") {
|
|
@@ -1162,6 +1217,13 @@ var Orchestrator = class {
|
|
|
1162
1217
|
tier: isHighComplexity ? 3 : 2
|
|
1163
1218
|
};
|
|
1164
1219
|
}
|
|
1220
|
+
if (mode === "perplexity") {
|
|
1221
|
+
return {
|
|
1222
|
+
provider: "perplexity",
|
|
1223
|
+
model: isHighComplexity ? "sonar-large-online" : "sonar-small-online",
|
|
1224
|
+
tier: isHighComplexity ? 3 : 2
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1165
1227
|
if (mode === "cloud" || mode === "openai") {
|
|
1166
1228
|
return {
|
|
1167
1229
|
provider: "openai",
|
|
@@ -1228,7 +1290,7 @@ var Orchestrator = class {
|
|
|
1228
1290
|
};
|
|
1229
1291
|
|
|
1230
1292
|
// src/UsageTracker.ts
|
|
1231
|
-
var UsageTracker = class
|
|
1293
|
+
var UsageTracker = class {
|
|
1232
1294
|
buffer = [];
|
|
1233
1295
|
MAX_BUFFER_SIZE = 1;
|
|
1234
1296
|
// Immediate reporting for Edge/Stateless environments
|
|
@@ -1250,8 +1312,10 @@ var UsageTracker = class _UsageTracker {
|
|
|
1250
1312
|
async logInteraction(params) {
|
|
1251
1313
|
const { instanceId, model, inputTokens, outputTokens, optimizedTokens = 0, cqScore, routingPath, clientOrigin, trace } = params;
|
|
1252
1314
|
const tokensSaved = optimizedTokens > 0 ? inputTokens - optimizedTokens : 0;
|
|
1253
|
-
const
|
|
1254
|
-
const
|
|
1315
|
+
const instanceConfig = this.config.getConfig().instanceConfigs?.[instanceId];
|
|
1316
|
+
const remotePricing = instanceConfig?.pricing?.[model] || { input: 5e-3, output: 0.015 };
|
|
1317
|
+
const costSaved = tokensSaved / 1e3 * remotePricing.input;
|
|
1318
|
+
const commissionDue = costSaved * 0.2;
|
|
1255
1319
|
const data = {
|
|
1256
1320
|
instanceId,
|
|
1257
1321
|
model_used: model,
|
|
@@ -1261,6 +1325,7 @@ var UsageTracker = class _UsageTracker {
|
|
|
1261
1325
|
optimized_tokens: optimizedTokens,
|
|
1262
1326
|
tokens_saved: tokensSaved,
|
|
1263
1327
|
cost_saved: Number(costSaved.toFixed(6)),
|
|
1328
|
+
commission_due: Number(commissionDue.toFixed(6)),
|
|
1264
1329
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1265
1330
|
is_local: model === "local",
|
|
1266
1331
|
cq_score: cqScore,
|
|
@@ -1280,7 +1345,6 @@ var UsageTracker = class _UsageTracker {
|
|
|
1280
1345
|
if (this.buffer.length === 0) return;
|
|
1281
1346
|
const endpoint = this.config.get("centralReportEndpoint");
|
|
1282
1347
|
if (!endpoint) {
|
|
1283
|
-
console.warn("[IK_TRACKER] No centralReportEndpoint defined. Clearing buffer to prevent memory leak.");
|
|
1284
1348
|
this.buffer = [];
|
|
1285
1349
|
return;
|
|
1286
1350
|
}
|
|
@@ -1295,10 +1359,13 @@ var UsageTracker = class _UsageTracker {
|
|
|
1295
1359
|
inputTokens: report.input_tokens,
|
|
1296
1360
|
outputTokens: report.output_tokens,
|
|
1297
1361
|
optimizedTokens: report.optimized_tokens,
|
|
1362
|
+
tokensSaved: report.tokens_saved,
|
|
1363
|
+
costSaved: report.cost_saved,
|
|
1364
|
+
commissionDue: report.commission_due,
|
|
1298
1365
|
cqScore: report.cq_score,
|
|
1299
1366
|
routingPath: report.routingPath,
|
|
1300
1367
|
clientOrigin: report.clientOrigin,
|
|
1301
|
-
|
|
1368
|
+
timestamp: report.timestamp
|
|
1302
1369
|
})
|
|
1303
1370
|
});
|
|
1304
1371
|
}
|
|
@@ -1406,6 +1473,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1406
1473
|
this.cloudProvider = new DeepSeekProvider(cloudProvider);
|
|
1407
1474
|
} else if (mode === "gemini") {
|
|
1408
1475
|
this.cloudProvider = new GeminiProvider(cloudProvider);
|
|
1476
|
+
} else if (mode === "perplexity") {
|
|
1477
|
+
this.cloudProvider = new PerplexityProvider(cloudProvider);
|
|
1409
1478
|
} else {
|
|
1410
1479
|
this.cloudProvider = new OpenAIProvider(cloudProvider);
|
|
1411
1480
|
}
|
|
@@ -1476,6 +1545,10 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1476
1545
|
available: !!process.env.GEMINI_API_KEY,
|
|
1477
1546
|
reason: !!process.env.GEMINI_API_KEY ? void 0 : "Missing GEMINI_API_KEY inside environment."
|
|
1478
1547
|
};
|
|
1548
|
+
providers["perplexity"] = {
|
|
1549
|
+
available: !!process.env.PERPLEXITY_API_KEY,
|
|
1550
|
+
reason: !!process.env.PERPLEXITY_API_KEY ? void 0 : "Missing PERPLEXITY_API_KEY inside environment."
|
|
1551
|
+
};
|
|
1479
1552
|
return providers;
|
|
1480
1553
|
}
|
|
1481
1554
|
/**
|
|
@@ -1520,6 +1593,14 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1520
1593
|
async analyze(input, provider, personaName = "professional", locale, instanceId) {
|
|
1521
1594
|
if (instanceId) {
|
|
1522
1595
|
this.configManager.ensureInstanceConfig(instanceId);
|
|
1596
|
+
await this.configManager.syncRemoteConfig(instanceId);
|
|
1597
|
+
}
|
|
1598
|
+
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
1599
|
+
if (instanceId && mergedConfig?.isVerified === false) {
|
|
1600
|
+
if (mergedConfig?.billingStatus === "blocked") {
|
|
1601
|
+
this.hooks?.onStatus?.("\u26A0\uFE0F [IK_FIREWALL] Subscription inactive. Optimization bypassed (Fail-Safe mode).");
|
|
1602
|
+
return this.getEmptyMetrics();
|
|
1603
|
+
}
|
|
1523
1604
|
}
|
|
1524
1605
|
let auditProvider = this.localProvider;
|
|
1525
1606
|
let overrideProvider = null;
|
|
@@ -1534,6 +1615,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1534
1615
|
overrideProvider = new DeepSeekProvider(provider);
|
|
1535
1616
|
} else if (mode === "gemini") {
|
|
1536
1617
|
overrideProvider = new GeminiProvider(provider);
|
|
1618
|
+
} else if (mode === "perplexity") {
|
|
1619
|
+
overrideProvider = new PerplexityProvider(provider);
|
|
1537
1620
|
} else {
|
|
1538
1621
|
overrideProvider = new OpenAIProvider(provider);
|
|
1539
1622
|
}
|
|
@@ -1552,18 +1635,20 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1552
1635
|
const ei = (input.match(/[,;.:-]/g) || []).length / (input.split(" ").length || 1);
|
|
1553
1636
|
let requiresAuditOverride = false;
|
|
1554
1637
|
let boundaryMetrics = { boundaryScore: 0, requiresHumanIntervention: false };
|
|
1555
|
-
if (this.getConfig()
|
|
1556
|
-
boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig()
|
|
1557
|
-
if (boundaryMetrics
|
|
1638
|
+
if (this.getConfig()?.safeMode) {
|
|
1639
|
+
boundaryMetrics = this.gatekeeper.evaluateBoundaryCommunication(input, this.getConfig()?.customBoundaryKeywords);
|
|
1640
|
+
if (boundaryMetrics?.requiresHumanIntervention) {
|
|
1558
1641
|
requiresAuditOverride = true;
|
|
1559
1642
|
}
|
|
1560
1643
|
}
|
|
1561
1644
|
const skipAudit = !requiresAuditOverride && this.getConfig().gatekeeperEnabled && localInsight.complexityScore < _IKFirewallCore.CONSTANTS.HEURISTICS.COMPLEXITY_SKIP_THRESHOLD;
|
|
1562
1645
|
if (skipAudit) {
|
|
1563
1646
|
this.hooks?.onStatus?.("\u26A1 IK_GATEKEEPER: Simple request detected. Skipping Deep Audit.");
|
|
1564
|
-
const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight
|
|
1565
|
-
metrics2.semanticInsights
|
|
1566
|
-
|
|
1647
|
+
const metrics2 = this.createHeuristicMetrics(input, dm, ei, uniqueWords, localInsight?.intentMode);
|
|
1648
|
+
if (metrics2.semanticInsights) {
|
|
1649
|
+
metrics2.semanticInsights.boundaryScore = boundaryMetrics.boundaryScore;
|
|
1650
|
+
metrics2.semanticInsights.requiresHumanIntervention = boundaryMetrics.requiresHumanIntervention;
|
|
1651
|
+
}
|
|
1567
1652
|
this.hooks?.onAuditComplete?.(metrics2);
|
|
1568
1653
|
return metrics2;
|
|
1569
1654
|
}
|
|
@@ -1660,12 +1745,12 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1660
1745
|
this.configManager.ensureInstanceConfig(instanceId);
|
|
1661
1746
|
}
|
|
1662
1747
|
const activeConfig = this.configManager.getMergedConfig(instanceId, configOverride);
|
|
1663
|
-
const locale = activeConfig
|
|
1748
|
+
const locale = activeConfig?.locale || "en";
|
|
1664
1749
|
const cqScore = this.orchestrator.calculateCQ(input);
|
|
1665
1750
|
let isAuditTask = false;
|
|
1666
|
-
if (activeConfig
|
|
1667
|
-
const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig
|
|
1668
|
-
if (boundaryResult
|
|
1751
|
+
if (activeConfig?.safeMode) {
|
|
1752
|
+
const boundaryResult = this.gatekeeper.evaluateBoundaryCommunication(input, activeConfig?.customBoundaryKeywords);
|
|
1753
|
+
if (boundaryResult?.requiresHumanIntervention) {
|
|
1669
1754
|
isAuditTask = true;
|
|
1670
1755
|
}
|
|
1671
1756
|
}
|
|
@@ -1683,6 +1768,8 @@ var IKFirewallCore = class _IKFirewallCore {
|
|
|
1683
1768
|
overrideProvider = new DeepSeekProvider(provider);
|
|
1684
1769
|
} else if (mode === "gemini") {
|
|
1685
1770
|
overrideProvider = new GeminiProvider(provider);
|
|
1771
|
+
} else if (mode === "perplexity") {
|
|
1772
|
+
overrideProvider = new PerplexityProvider(provider);
|
|
1686
1773
|
} else {
|
|
1687
1774
|
overrideProvider = new OpenAIProvider(provider);
|
|
1688
1775
|
}
|
|
@@ -1885,7 +1972,11 @@ Any action outside this scope MUST be rejected and flagged as a boundary violati
|
|
|
1885
1972
|
inputLength
|
|
1886
1973
|
};
|
|
1887
1974
|
}
|
|
1888
|
-
crystallize(input, metrics, locale = "en") {
|
|
1975
|
+
crystallize(input, metrics, locale = "en", instanceId) {
|
|
1976
|
+
const mergedConfig = this.configManager.getMergedConfig(instanceId);
|
|
1977
|
+
if (instanceId && mergedConfig?.isVerified === false) {
|
|
1978
|
+
return input;
|
|
1979
|
+
}
|
|
1889
1980
|
const archetype = metrics?.semanticInsights?.archetype || "DYNAMIC";
|
|
1890
1981
|
const tolerance = metrics?.semanticInsights?.ambiguityTolerance || 0.5;
|
|
1891
1982
|
const blueprint = metrics?.semanticInsights?.conceptualBlueprint;
|
|
@@ -2408,6 +2499,7 @@ export {
|
|
|
2408
2499
|
IKFirewallCore,
|
|
2409
2500
|
LocalProvider,
|
|
2410
2501
|
OpenAIProvider,
|
|
2502
|
+
PerplexityProvider,
|
|
2411
2503
|
StressTester,
|
|
2412
2504
|
SurgicalTester
|
|
2413
2505
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ik-firewall/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The core IK Firewall engine for semantic-driven AI optimization.",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -8,18 +8,20 @@
|
|
|
8
8
|
"types": "./dist/index.d.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
11
12
|
"import": "./dist/index.js",
|
|
12
|
-
"require": "./dist/index.cjs"
|
|
13
|
-
"types": "./dist/index.d.ts"
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
14
|
}
|
|
15
15
|
},
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"scripts"
|
|
19
19
|
],
|
|
20
|
+
"api_endpoint": "https://ik-firewall-backend.vercel.app/api/v1",
|
|
20
21
|
"scripts": {
|
|
21
22
|
"prepare": "npm run build",
|
|
22
23
|
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
24
|
+
"build:wasm": "cd wasm-core && wasm-pack build --target nodejs",
|
|
23
25
|
"dev": "tsup src/index.ts --format cjs,esm --watch --dts",
|
|
24
26
|
"lint": "eslint src/**/*.ts",
|
|
25
27
|
"test": "jest",
|
|
@@ -35,7 +37,7 @@
|
|
|
35
37
|
"optimization"
|
|
36
38
|
],
|
|
37
39
|
"author": "Stefan Vasic",
|
|
38
|
-
"license": "
|
|
40
|
+
"license": "BSL-1.1",
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"@types/node": "^25.0.10",
|
|
41
43
|
"tsup": "^8.0.0",
|
package/scripts/setup-runtime.js
CHANGED
|
@@ -1,44 +1,83 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
+
import readline from 'node:readline';
|
|
4
5
|
|
|
5
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
6
7
|
const __dirname = path.dirname(__filename);
|
|
7
8
|
|
|
8
9
|
// Constants
|
|
9
10
|
const BIN_DIR = path.join(__dirname, '..', '.bin');
|
|
10
|
-
const
|
|
11
|
-
const
|
|
11
|
+
const REGISTRY_DIR = path.join(process.cwd(), '.ik-adapter');
|
|
12
|
+
const REGISTRY_FILE = path.join(REGISTRY_DIR, 'registry.json');
|
|
13
|
+
|
|
14
|
+
async function askEmail() {
|
|
15
|
+
if (process.env.IK_EMAIL) return process.env.IK_EMAIL;
|
|
16
|
+
|
|
17
|
+
const rl = readline.createInterface({
|
|
18
|
+
input: process.stdin,
|
|
19
|
+
output: process.stdout
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
const prompt = (query) => new Promise((resolve) => rl.question(query, resolve));
|
|
23
|
+
|
|
24
|
+
let email = "";
|
|
25
|
+
while (!email || !email.includes('@')) {
|
|
26
|
+
email = await prompt('\nš§ IK_FIREWALL: [MANDATORY] Please enter your email to activate your account: ');
|
|
27
|
+
if (!email || !email.includes('@')) {
|
|
28
|
+
console.log('ā ļø Invalid email. Email is required for license generation.');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
rl.close();
|
|
32
|
+
return email;
|
|
33
|
+
}
|
|
12
34
|
|
|
13
35
|
async function setup() {
|
|
14
|
-
|
|
15
|
-
|
|
36
|
+
// Vercel / Netlify / AWS Lambda often have read-only file systems
|
|
37
|
+
if (process.env.VERCEL || process.env.RENDER || process.env.AWS_LAMBDA_FUNCTION_NAME) {
|
|
38
|
+
console.log('\nāļø IK_FIREWALL: Read-only Serverless environment detected.');
|
|
39
|
+
console.log('š” NOTE: Registry & Local Binary setup will be bypassed. Ensure you set "centralReportEndpoint" via code config.');
|
|
16
40
|
return;
|
|
17
41
|
}
|
|
18
|
-
console.log('š IK_FIREWALL: Initiating Zero-Config Runtime Setup...');
|
|
42
|
+
console.log('\nš IK_FIREWALL: Initiating Zero-Config Runtime Setup...');
|
|
19
43
|
|
|
20
|
-
// 1. Create .bin
|
|
21
|
-
|
|
22
|
-
fs.
|
|
23
|
-
|
|
44
|
+
// 1. Create .bin and .ik-adapter directories
|
|
45
|
+
[BIN_DIR, REGISTRY_DIR].forEach(dir => {
|
|
46
|
+
if (!fs.existsSync(dir)) {
|
|
47
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// 2. Initialize Trial Registry
|
|
52
|
+
if (!fs.existsSync(REGISTRY_FILE)) {
|
|
53
|
+
const email = await askEmail();
|
|
54
|
+
const initialRegistry = {
|
|
55
|
+
"default": {
|
|
56
|
+
"licenseKey": "TRIAL-" + Math.random().toString(36).substring(7).toUpperCase(),
|
|
57
|
+
"billingStatus": "trial",
|
|
58
|
+
"isVerified": true,
|
|
59
|
+
"firstUseDate": new Date().toISOString(),
|
|
60
|
+
"ownerEmail": email,
|
|
61
|
+
"isEnabled": true
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
fs.writeFileSync(REGISTRY_FILE, JSON.stringify(initialRegistry, null, 2));
|
|
65
|
+
console.log(`⨠Trial activated for: ${email}`);
|
|
24
66
|
}
|
|
25
67
|
|
|
26
|
-
//
|
|
68
|
+
// 3. Detect OS & Architecture
|
|
27
69
|
const platform = process.platform;
|
|
28
70
|
const arch = process.arch;
|
|
29
71
|
console.log(`š Detected environment: ${platform}-${arch}`);
|
|
30
72
|
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
console.log(
|
|
34
|
-
console.log(
|
|
35
|
-
|
|
36
|
-
// Create a helper dev script in package.json context or similar
|
|
37
|
-
console.log('\nš¦ IK-Runtime environment prepared.');
|
|
38
|
-
console.log('⨠IK Adapter is now ready for local escalation testing!');
|
|
73
|
+
// 4. Usage Tips
|
|
74
|
+
console.log(`\nš¦ IK-Runtime environment prepared.`);
|
|
75
|
+
console.log('š” TIP: For local optimization (Sidecar), use "npm run start-ai".');
|
|
76
|
+
console.log('š ļø DEV: If building locally, you can use the Node.js Emulator: node scripts/runtime-emulator.js');
|
|
77
|
+
console.log('⨠IK Adapter is now ready for production-grade AI protection!\n');
|
|
39
78
|
}
|
|
40
79
|
|
|
41
80
|
setup().catch(err => {
|
|
42
81
|
console.error('ā IK_FIREWALL Setup Failed:', err.message);
|
|
43
|
-
process.exit(
|
|
82
|
+
process.exit(0); // Don't block install on setup error
|
|
44
83
|
});
|