@curenorway/kode-mcp 1.2.0 → 1.3.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.js +519 -43
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -105,6 +105,16 @@ var KodeApiClient = class {
|
|
|
105
105
|
async getDeploymentStatus(siteId) {
|
|
106
106
|
return this.request(`/api/cdn/sites/${siteId}/deployments/status`);
|
|
107
107
|
}
|
|
108
|
+
// v2.3: Production enabled toggle
|
|
109
|
+
async setProductionEnabled(siteId, enabled, productionDomain) {
|
|
110
|
+
return this.request(`/api/cdn/sites/${siteId}/production`, {
|
|
111
|
+
method: "POST",
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
enabled,
|
|
114
|
+
productionDomain
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
}
|
|
108
118
|
// HTML operations
|
|
109
119
|
async fetchHtml(siteId, url) {
|
|
110
120
|
return this.request("/api/cdn/fetch-html", {
|
|
@@ -121,6 +131,16 @@ var KodeApiClient = class {
|
|
|
121
131
|
return false;
|
|
122
132
|
}
|
|
123
133
|
}
|
|
134
|
+
// Metadata operations
|
|
135
|
+
async analyzeScript(scriptId, options = {}) {
|
|
136
|
+
return this.request(`/api/cdn/scripts/${scriptId}/analyze`, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
body: JSON.stringify(options)
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
async getScriptMetadata(scriptId) {
|
|
142
|
+
return this.request(`/api/cdn/scripts/${scriptId}/metadata`);
|
|
143
|
+
}
|
|
124
144
|
};
|
|
125
145
|
|
|
126
146
|
// src/config.ts
|
|
@@ -274,7 +294,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
274
294
|
},
|
|
275
295
|
{
|
|
276
296
|
name: "kode_create_script",
|
|
277
|
-
description: "Create a new script
|
|
297
|
+
description: "Create a new script entry (metadata only). After creating, write the script file locally to .cure-kode-scripts/{name}.js and use kode_push to upload content. This keeps script content out of MCP context.",
|
|
278
298
|
inputSchema: {
|
|
279
299
|
type: "object",
|
|
280
300
|
properties: {
|
|
@@ -287,10 +307,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
287
307
|
enum: ["javascript", "css"],
|
|
288
308
|
description: "Script type"
|
|
289
309
|
},
|
|
290
|
-
content: {
|
|
291
|
-
type: "string",
|
|
292
|
-
description: "Script content (JavaScript or CSS code)"
|
|
293
|
-
},
|
|
294
310
|
scope: {
|
|
295
311
|
type: "string",
|
|
296
312
|
enum: ["global", "page-specific"],
|
|
@@ -298,15 +314,37 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
298
314
|
},
|
|
299
315
|
autoLoad: {
|
|
300
316
|
type: "boolean",
|
|
301
|
-
description: "Whether to auto-load the script. Default: true for global scripts, false for page-specific.
|
|
317
|
+
description: "Whether to auto-load the script. Default: true for global scripts, false for page-specific."
|
|
318
|
+
},
|
|
319
|
+
purpose: {
|
|
320
|
+
type: "string",
|
|
321
|
+
description: "Brief description of what the script does (for metadata)"
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
required: ["name", "type"]
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: "kode_push",
|
|
329
|
+
description: "Push local script files to Cure Kode. Reads files from .cure-kode-scripts/ folder and uploads to API. This is the proper way to sync code - never send script content through other MCP tools.",
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: "object",
|
|
332
|
+
properties: {
|
|
333
|
+
scriptSlug: {
|
|
334
|
+
type: "string",
|
|
335
|
+
description: 'Specific script slug to push (e.g., "map"). If omitted, pushes all changed scripts.'
|
|
336
|
+
},
|
|
337
|
+
force: {
|
|
338
|
+
type: "boolean",
|
|
339
|
+
description: "Force push even if content appears unchanged. Default: false"
|
|
302
340
|
}
|
|
303
341
|
},
|
|
304
|
-
required: [
|
|
342
|
+
required: []
|
|
305
343
|
}
|
|
306
344
|
},
|
|
307
345
|
{
|
|
308
346
|
name: "kode_update_script",
|
|
309
|
-
description: "Update
|
|
347
|
+
description: "Update script settings (NOT content). For content changes, edit the local file in .cure-kode-scripts/ and use kode_push. This tool is for metadata, scope, and autoLoad changes only.",
|
|
310
348
|
inputSchema: {
|
|
311
349
|
type: "object",
|
|
312
350
|
properties: {
|
|
@@ -314,10 +352,6 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
314
352
|
type: "string",
|
|
315
353
|
description: "Script slug or ID to update"
|
|
316
354
|
},
|
|
317
|
-
content: {
|
|
318
|
-
type: "string",
|
|
319
|
-
description: "New script content"
|
|
320
|
-
},
|
|
321
355
|
autoLoad: {
|
|
322
356
|
type: "boolean",
|
|
323
357
|
description: "Whether to auto-load the script. Set to true to load automatically, false for manual loading via CK.loadScript()."
|
|
@@ -327,9 +361,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
327
361
|
enum: ["global", "page-specific"],
|
|
328
362
|
description: "Change script scope. Note: changing to page-specific requires assigning to pages."
|
|
329
363
|
},
|
|
330
|
-
|
|
364
|
+
purpose: {
|
|
331
365
|
type: "string",
|
|
332
|
-
description: "
|
|
366
|
+
description: "Update the script purpose description (shown in Chrome Extension)"
|
|
367
|
+
},
|
|
368
|
+
regenerateSummary: {
|
|
369
|
+
type: "boolean",
|
|
370
|
+
description: "Re-analyze the script content and regenerate the AI summary. Useful after significant changes."
|
|
333
371
|
}
|
|
334
372
|
},
|
|
335
373
|
required: ["slug"]
|
|
@@ -379,7 +417,30 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
379
417
|
},
|
|
380
418
|
{
|
|
381
419
|
name: "kode_status",
|
|
382
|
-
description: "Get the current deployment status
|
|
420
|
+
description: "Get the current deployment status including production enabled state, staging and production environments.",
|
|
421
|
+
inputSchema: {
|
|
422
|
+
type: "object",
|
|
423
|
+
properties: {},
|
|
424
|
+
required: []
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
name: "kode_production_enable",
|
|
429
|
+
description: "Enable production environment for this site. Required before promoting to production. Sites start in staging-only mode by default.",
|
|
430
|
+
inputSchema: {
|
|
431
|
+
type: "object",
|
|
432
|
+
properties: {
|
|
433
|
+
productionDomain: {
|
|
434
|
+
type: "string",
|
|
435
|
+
description: 'Production domain (e.g., "example.com"). Optional - can be set later.'
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
required: []
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
{
|
|
442
|
+
name: "kode_production_disable",
|
|
443
|
+
description: "Disable production environment for this site. Production requests will return an empty script. Useful during development when only staging should be active.",
|
|
383
444
|
inputSchema: {
|
|
384
445
|
type: "object",
|
|
385
446
|
properties: {},
|
|
@@ -458,6 +519,38 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
458
519
|
required: []
|
|
459
520
|
}
|
|
460
521
|
},
|
|
522
|
+
{
|
|
523
|
+
name: "kode_analyze_script",
|
|
524
|
+
description: "Analyze a script's content and auto-generate metadata. Detects DOM selectors, event triggers, dependencies (GSAP, Swiper, etc.), and behavior patterns. Optionally saves the analysis to the script.",
|
|
525
|
+
inputSchema: {
|
|
526
|
+
type: "object",
|
|
527
|
+
properties: {
|
|
528
|
+
slug: {
|
|
529
|
+
type: "string",
|
|
530
|
+
description: "Script slug or ID to analyze"
|
|
531
|
+
},
|
|
532
|
+
saveToScript: {
|
|
533
|
+
type: "boolean",
|
|
534
|
+
description: "Save the generated metadata to the script. Default: false (preview only)"
|
|
535
|
+
}
|
|
536
|
+
},
|
|
537
|
+
required: ["slug"]
|
|
538
|
+
}
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
name: "kode_get_script_metadata",
|
|
542
|
+
description: "Get the metadata for a script, including detected DOM targets, triggers, dependencies, and AI summary. Useful for Chrome Extension visibility.",
|
|
543
|
+
inputSchema: {
|
|
544
|
+
type: "object",
|
|
545
|
+
properties: {
|
|
546
|
+
slug: {
|
|
547
|
+
type: "string",
|
|
548
|
+
description: "Script slug or ID to get metadata for"
|
|
549
|
+
}
|
|
550
|
+
},
|
|
551
|
+
required: ["slug"]
|
|
552
|
+
}
|
|
553
|
+
},
|
|
461
554
|
{
|
|
462
555
|
name: "kode_read_context",
|
|
463
556
|
description: "Read the project context file (.cure-kode/context.md). Contains current scripts, notes, and session history. ALWAYS call this before starting work on a Kode project.",
|
|
@@ -667,35 +760,155 @@ ${script.content}`
|
|
|
667
760
|
};
|
|
668
761
|
}
|
|
669
762
|
case "kode_create_script": {
|
|
670
|
-
const { name: scriptName, type,
|
|
763
|
+
const { name: scriptName, type, scope, autoLoad, purpose } = args;
|
|
671
764
|
const scriptScope = scope || "global";
|
|
672
765
|
const script = await client.createScript(siteId, {
|
|
673
766
|
name: scriptName,
|
|
674
767
|
slug: scriptName,
|
|
675
768
|
type,
|
|
676
|
-
content,
|
|
769
|
+
content: "",
|
|
770
|
+
// Empty - content comes from local files via kode_push
|
|
677
771
|
scope: scriptScope,
|
|
678
|
-
autoLoad
|
|
679
|
-
|
|
772
|
+
autoLoad,
|
|
773
|
+
metadata: purpose ? { purpose } : void 0
|
|
680
774
|
});
|
|
681
|
-
const
|
|
775
|
+
const scriptsDir = getScriptsDir();
|
|
776
|
+
const ext = type === "javascript" ? "js" : "css";
|
|
777
|
+
const localPath = scriptsDir ? `${scriptsDir}/${scriptName}.${ext}` : `.cure-kode-scripts/${scriptName}.${ext}`;
|
|
778
|
+
let responseText = `Created script "${script.name}" (${script.type})`;
|
|
779
|
+
responseText += `
|
|
780
|
+
Slug: ${script.slug}`;
|
|
781
|
+
responseText += `
|
|
782
|
+
Scope: ${script.scope}`;
|
|
783
|
+
responseText += `
|
|
784
|
+
Auto-load: ${script.auto_load ? "yes" : "no"}`;
|
|
785
|
+
if (purpose) responseText += `
|
|
786
|
+
Purpose: ${purpose}`;
|
|
787
|
+
responseText += `
|
|
788
|
+
|
|
789
|
+
Next steps:`;
|
|
790
|
+
responseText += `
|
|
791
|
+
1. Create file: ${localPath}`;
|
|
792
|
+
responseText += `
|
|
793
|
+
2. Write your ${type} code`;
|
|
794
|
+
responseText += `
|
|
795
|
+
3. Run kode_push to upload content`;
|
|
796
|
+
responseText += `
|
|
797
|
+
4. Run kode_deploy to make it live`;
|
|
682
798
|
return {
|
|
683
799
|
content: [
|
|
684
800
|
{
|
|
685
801
|
type: "text",
|
|
686
|
-
text:
|
|
687
|
-
Slug: ${script.slug}
|
|
688
|
-
Scope: ${script.scope}
|
|
689
|
-
Auto-load: ${autoLoadStatus}
|
|
690
|
-
Version: ${script.current_version}
|
|
691
|
-
|
|
692
|
-
Note: Run kode_deploy to make it live.`
|
|
802
|
+
text: responseText
|
|
693
803
|
}
|
|
694
804
|
]
|
|
695
805
|
};
|
|
696
806
|
}
|
|
807
|
+
case "kode_push": {
|
|
808
|
+
const { scriptSlug, force } = args;
|
|
809
|
+
const scriptsDir = getScriptsDir();
|
|
810
|
+
if (!scriptsDir || !fs2.existsSync(scriptsDir)) {
|
|
811
|
+
return {
|
|
812
|
+
content: [{
|
|
813
|
+
type: "text",
|
|
814
|
+
text: 'No .cure-kode-scripts/ folder found. Run "kode init" first or create the folder manually.'
|
|
815
|
+
}],
|
|
816
|
+
isError: true
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
const remoteScripts = await client.listScripts(siteId);
|
|
820
|
+
const localFiles = fs2.readdirSync(scriptsDir).filter((f) => f.endsWith(".js") || f.endsWith(".css"));
|
|
821
|
+
if (scriptSlug) {
|
|
822
|
+
const ext = remoteScripts.find((s) => s.slug === scriptSlug)?.type === "css" ? "css" : "js";
|
|
823
|
+
const fileName = `${scriptSlug}.${ext}`;
|
|
824
|
+
const filePath = path2.join(scriptsDir, fileName);
|
|
825
|
+
if (!fs2.existsSync(filePath)) {
|
|
826
|
+
return {
|
|
827
|
+
content: [{
|
|
828
|
+
type: "text",
|
|
829
|
+
text: `File not found: ${filePath}
|
|
830
|
+
|
|
831
|
+
Available files: ${localFiles.join(", ") || "(none)"}`
|
|
832
|
+
}],
|
|
833
|
+
isError: true
|
|
834
|
+
};
|
|
835
|
+
}
|
|
836
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
837
|
+
const remote = remoteScripts.find((s) => s.slug === scriptSlug);
|
|
838
|
+
if (!remote) {
|
|
839
|
+
return {
|
|
840
|
+
content: [{
|
|
841
|
+
type: "text",
|
|
842
|
+
text: `Script "${scriptSlug}" not found on server. Create it first with kode_create_script.`
|
|
843
|
+
}],
|
|
844
|
+
isError: true
|
|
845
|
+
};
|
|
846
|
+
}
|
|
847
|
+
if (!force && remote.content === content) {
|
|
848
|
+
return {
|
|
849
|
+
content: [{
|
|
850
|
+
type: "text",
|
|
851
|
+
text: `Script "${scriptSlug}" is already up to date (${content.length} chars). Use force: true to push anyway.`
|
|
852
|
+
}]
|
|
853
|
+
};
|
|
854
|
+
}
|
|
855
|
+
const updated = await client.updateScript(remote.id, {
|
|
856
|
+
content,
|
|
857
|
+
changeSummary: "Pushed via MCP"
|
|
858
|
+
});
|
|
859
|
+
return {
|
|
860
|
+
content: [{
|
|
861
|
+
type: "text",
|
|
862
|
+
text: `Pushed "${scriptSlug}": ${content.length} chars \u2192 v${updated.current_version}
|
|
863
|
+
|
|
864
|
+
Run kode_deploy to make changes live.`
|
|
865
|
+
}]
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
const results = [];
|
|
869
|
+
let pushedCount = 0;
|
|
870
|
+
let skippedCount = 0;
|
|
871
|
+
for (const file of localFiles) {
|
|
872
|
+
const slug = file.replace(/\.(js|css)$/, "");
|
|
873
|
+
const filePath = path2.join(scriptsDir, file);
|
|
874
|
+
const content = fs2.readFileSync(filePath, "utf-8");
|
|
875
|
+
const remote = remoteScripts.find((s) => s.slug === slug);
|
|
876
|
+
if (!remote) {
|
|
877
|
+
results.push(`\u26A0\uFE0F ${slug}: not on server (create with kode_create_script first)`);
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
if (!force && remote.content === content) {
|
|
881
|
+
skippedCount++;
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
try {
|
|
885
|
+
const updated = await client.updateScript(remote.id, {
|
|
886
|
+
content,
|
|
887
|
+
changeSummary: "Pushed via MCP"
|
|
888
|
+
});
|
|
889
|
+
results.push(`\u2713 ${slug}: ${content.length} chars \u2192 v${updated.current_version}`);
|
|
890
|
+
pushedCount++;
|
|
891
|
+
} catch (err) {
|
|
892
|
+
results.push(`\u2717 ${slug}: ${err instanceof Error ? err.message : "failed"}`);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
let responseText = `Push complete: ${pushedCount} updated, ${skippedCount} unchanged`;
|
|
896
|
+
if (results.length > 0) {
|
|
897
|
+
responseText += `
|
|
898
|
+
|
|
899
|
+
${results.join("\n")}`;
|
|
900
|
+
}
|
|
901
|
+
if (pushedCount > 0) {
|
|
902
|
+
responseText += `
|
|
903
|
+
|
|
904
|
+
Run kode_deploy to make changes live.`;
|
|
905
|
+
}
|
|
906
|
+
return {
|
|
907
|
+
content: [{ type: "text", text: responseText }]
|
|
908
|
+
};
|
|
909
|
+
}
|
|
697
910
|
case "kode_update_script": {
|
|
698
|
-
const { slug,
|
|
911
|
+
const { slug, autoLoad, scope, purpose, regenerateSummary } = args;
|
|
699
912
|
const scripts = await client.listScripts(siteId);
|
|
700
913
|
const script = scripts.find((s) => s.slug === slug || s.id === slug);
|
|
701
914
|
if (!script) {
|
|
@@ -704,24 +917,32 @@ Note: Run kode_deploy to make it live.`
|
|
|
704
917
|
isError: true
|
|
705
918
|
};
|
|
706
919
|
}
|
|
707
|
-
const updateData = {
|
|
708
|
-
|
|
920
|
+
const updateData = {
|
|
921
|
+
changeSummary: "Updated settings via MCP"
|
|
922
|
+
};
|
|
709
923
|
if (autoLoad !== void 0) updateData.autoLoad = autoLoad;
|
|
710
924
|
if (scope !== void 0) updateData.scope = scope;
|
|
711
|
-
updateData.
|
|
925
|
+
if (purpose !== void 0) updateData.metadata = { purpose };
|
|
926
|
+
if (regenerateSummary !== void 0) updateData.regenerateSummary = regenerateSummary;
|
|
712
927
|
const updated = await client.updateScript(script.id, updateData);
|
|
713
928
|
const changes = [];
|
|
714
|
-
if (
|
|
715
|
-
if (autoLoad !== void 0) changes.push(`auto_load \u2192 ${autoLoad}`);
|
|
929
|
+
if (autoLoad !== void 0) changes.push(`autoLoad \u2192 ${autoLoad}`);
|
|
716
930
|
if (scope !== void 0) changes.push(`scope \u2192 ${scope}`);
|
|
931
|
+
if (purpose !== void 0) changes.push(`purpose updated`);
|
|
932
|
+
if (regenerateSummary) changes.push("AI summary regenerated");
|
|
933
|
+
let responseText = `Updated script "${updated.name}"`;
|
|
934
|
+
if (changes.length > 0) {
|
|
935
|
+
responseText += `
|
|
936
|
+
Changes: ${changes.join(", ")}`;
|
|
937
|
+
}
|
|
938
|
+
responseText += `
|
|
939
|
+
|
|
940
|
+
To update content: edit local file and run kode_push`;
|
|
717
941
|
return {
|
|
718
942
|
content: [
|
|
719
943
|
{
|
|
720
944
|
type: "text",
|
|
721
|
-
text:
|
|
722
|
-
Changes: ${changes.join(", ")}
|
|
723
|
-
|
|
724
|
-
Note: Run kode_deploy to make changes live.`
|
|
945
|
+
text: responseText
|
|
725
946
|
}
|
|
726
947
|
]
|
|
727
948
|
};
|
|
@@ -752,19 +973,54 @@ Note: Run kode_deploy to make changes live.`
|
|
|
752
973
|
environment: environment || "staging",
|
|
753
974
|
notes: notes || "Deployed via MCP"
|
|
754
975
|
});
|
|
976
|
+
let responseText = `Deployment ${deployment.version} to ${deployment.environment}: ${deployment.status}`;
|
|
977
|
+
responseText += `
|
|
978
|
+
Started: ${deployment.started_at}`;
|
|
979
|
+
if (deployment.completed_at) {
|
|
980
|
+
responseText += `
|
|
981
|
+
Completed: ${deployment.completed_at}`;
|
|
982
|
+
}
|
|
983
|
+
const scriptSizes = deployment.stats?.scriptSizes;
|
|
984
|
+
if (scriptSizes && scriptSizes.length > 0) {
|
|
985
|
+
responseText += `
|
|
986
|
+
|
|
987
|
+
Scripts deployed (${scriptSizes.length}):`;
|
|
988
|
+
for (const s of scriptSizes) {
|
|
989
|
+
const flags = [
|
|
990
|
+
s.scope === "global" ? "G" : "P",
|
|
991
|
+
s.autoLoad ? "\u26A1" : "\u25CB"
|
|
992
|
+
].join("");
|
|
993
|
+
responseText += `
|
|
994
|
+
${s.slug} [${flags}]: ${s.contentSize} chars`;
|
|
995
|
+
if (s.contentSize === 0) {
|
|
996
|
+
responseText += " \u26A0\uFE0F EMPTY";
|
|
997
|
+
} else if (s.contentSize < 50 && s.scope === "global") {
|
|
998
|
+
responseText += " \u26A0\uFE0F very small";
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
755
1002
|
return {
|
|
756
1003
|
content: [
|
|
757
1004
|
{
|
|
758
1005
|
type: "text",
|
|
759
|
-
text:
|
|
760
|
-
Started: ${deployment.started_at}${deployment.completed_at ? `
|
|
761
|
-
Completed: ${deployment.completed_at}` : ""}`
|
|
1006
|
+
text: responseText
|
|
762
1007
|
}
|
|
763
1008
|
]
|
|
764
1009
|
};
|
|
765
1010
|
}
|
|
766
1011
|
case "kode_promote": {
|
|
767
1012
|
const status = await client.getDeploymentStatus(siteId);
|
|
1013
|
+
if (!status.productionEnabled) {
|
|
1014
|
+
return {
|
|
1015
|
+
content: [
|
|
1016
|
+
{
|
|
1017
|
+
type: "text",
|
|
1018
|
+
text: "Cannot promote: Production is not enabled for this site.\n\nRun kode_production_enable first to activate the production environment."
|
|
1019
|
+
}
|
|
1020
|
+
],
|
|
1021
|
+
isError: true
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
768
1024
|
if (!status.canPromote) {
|
|
769
1025
|
return {
|
|
770
1026
|
content: [
|
|
@@ -787,12 +1043,46 @@ Status: ${deployment.status}`
|
|
|
787
1043
|
]
|
|
788
1044
|
};
|
|
789
1045
|
}
|
|
1046
|
+
case "kode_production_enable": {
|
|
1047
|
+
const { productionDomain } = args;
|
|
1048
|
+
const result = await client.setProductionEnabled(siteId, true, productionDomain);
|
|
1049
|
+
let text = "Production environment enabled!\n\n";
|
|
1050
|
+
if (result.productionDomain) {
|
|
1051
|
+
text += `Domain: ${result.productionDomain}
|
|
1052
|
+
`;
|
|
1053
|
+
}
|
|
1054
|
+
text += "\nNext steps:\n";
|
|
1055
|
+
text += "1. Deploy to staging: kode_deploy\n";
|
|
1056
|
+
text += "2. Promote to production: kode_promote";
|
|
1057
|
+
return {
|
|
1058
|
+
content: [{ type: "text", text }]
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
case "kode_production_disable": {
|
|
1062
|
+
await client.setProductionEnabled(siteId, false);
|
|
1063
|
+
return {
|
|
1064
|
+
content: [
|
|
1065
|
+
{
|
|
1066
|
+
type: "text",
|
|
1067
|
+
text: "Production environment disabled.\n\nOnly staging is now active. Production domain requests will receive an empty script with a warning."
|
|
1068
|
+
}
|
|
1069
|
+
]
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
790
1072
|
case "kode_status": {
|
|
791
1073
|
const status = await client.getDeploymentStatus(siteId);
|
|
792
1074
|
const config = getConfig();
|
|
793
1075
|
let text = `Site: ${config?.siteName || "Unknown"}
|
|
794
1076
|
|
|
795
1077
|
`;
|
|
1078
|
+
const productionEnabled = status.productionEnabled ?? false;
|
|
1079
|
+
text += `PRODUCTION STATUS: ${productionEnabled ? "\u2713 Enabled" : "\u25CB Disabled (staging only)"}
|
|
1080
|
+
`;
|
|
1081
|
+
if (productionEnabled && status.productionDomain) {
|
|
1082
|
+
text += ` Domain: ${status.productionDomain}
|
|
1083
|
+
`;
|
|
1084
|
+
}
|
|
1085
|
+
text += "\n";
|
|
796
1086
|
text += `STAGING:
|
|
797
1087
|
`;
|
|
798
1088
|
if (status.staging.lastSuccessful) {
|
|
@@ -807,17 +1097,25 @@ Status: ${deployment.status}`
|
|
|
807
1097
|
text += `
|
|
808
1098
|
PRODUCTION:
|
|
809
1099
|
`;
|
|
810
|
-
if (
|
|
1100
|
+
if (!productionEnabled) {
|
|
1101
|
+
text += ` (Disabled - use kode_production_enable to activate)
|
|
1102
|
+
`;
|
|
1103
|
+
} else if (status.production.lastSuccessful) {
|
|
811
1104
|
text += ` Version: ${status.production.lastSuccessful.version}
|
|
812
1105
|
`;
|
|
813
1106
|
text += ` Deployed: ${status.production.lastSuccessful.completed_at}
|
|
814
1107
|
`;
|
|
815
1108
|
} else {
|
|
816
|
-
text += `
|
|
1109
|
+
text += ` Enabled, not yet deployed
|
|
817
1110
|
`;
|
|
818
1111
|
}
|
|
819
|
-
|
|
1112
|
+
if (productionEnabled) {
|
|
1113
|
+
text += `
|
|
820
1114
|
Can promote staging to production: ${status.canPromote ? "Yes" : "No"}`;
|
|
1115
|
+
} else {
|
|
1116
|
+
text += `
|
|
1117
|
+
Enable production first (kode_production_enable) before promoting.`;
|
|
1118
|
+
}
|
|
821
1119
|
return {
|
|
822
1120
|
content: [{ type: "text", text }]
|
|
823
1121
|
};
|
|
@@ -1002,6 +1300,184 @@ Embed code:
|
|
|
1002
1300
|
content: [{ type: "text", text }]
|
|
1003
1301
|
};
|
|
1004
1302
|
}
|
|
1303
|
+
case "kode_analyze_script": {
|
|
1304
|
+
const { slug, saveToScript } = args;
|
|
1305
|
+
const scripts = await client.listScripts(siteId);
|
|
1306
|
+
const script = scripts.find((s) => s.slug === slug || s.id === slug);
|
|
1307
|
+
if (!script) {
|
|
1308
|
+
return {
|
|
1309
|
+
content: [{ type: "text", text: `Script "${slug}" not found` }],
|
|
1310
|
+
isError: true
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
try {
|
|
1314
|
+
const result = await client.analyzeScript(script.id, { saveToScript });
|
|
1315
|
+
let text = `Script Analysis: ${script.name}
|
|
1316
|
+
|
|
1317
|
+
`;
|
|
1318
|
+
text += `Purpose: ${result.metadata.purpose || "(not detected)"}
|
|
1319
|
+
|
|
1320
|
+
`;
|
|
1321
|
+
if (result.metadata.triggers.length > 0) {
|
|
1322
|
+
text += `Triggers:
|
|
1323
|
+
`;
|
|
1324
|
+
for (const t of result.metadata.triggers) {
|
|
1325
|
+
text += ` - ${t.event}${t.selector ? ` on ${t.selector}` : ""}
|
|
1326
|
+
`;
|
|
1327
|
+
}
|
|
1328
|
+
text += "\n";
|
|
1329
|
+
}
|
|
1330
|
+
if (result.metadata.domTargets.length > 0) {
|
|
1331
|
+
text += `DOM Targets:
|
|
1332
|
+
`;
|
|
1333
|
+
for (const d of result.metadata.domTargets) {
|
|
1334
|
+
text += ` - ${d.selector} (${d.action})
|
|
1335
|
+
`;
|
|
1336
|
+
}
|
|
1337
|
+
text += "\n";
|
|
1338
|
+
}
|
|
1339
|
+
if (result.metadata.dependencies.length > 0) {
|
|
1340
|
+
text += `Dependencies:
|
|
1341
|
+
`;
|
|
1342
|
+
for (const dep of result.metadata.dependencies) {
|
|
1343
|
+
text += ` - ${dep.name}${dep.required ? " (required)" : ""}
|
|
1344
|
+
`;
|
|
1345
|
+
}
|
|
1346
|
+
text += "\n";
|
|
1347
|
+
}
|
|
1348
|
+
text += `Flags:
|
|
1349
|
+
`;
|
|
1350
|
+
text += ` - Modifies DOM: ${result.metadata.modifiesDom ? "Yes" : "No"}
|
|
1351
|
+
`;
|
|
1352
|
+
text += ` - Event listeners: ${result.metadata.addsEventListeners ? "Yes" : "No"}
|
|
1353
|
+
`;
|
|
1354
|
+
if (result.metadata.usesExternalApis) text += ` - Uses external APIs: Yes
|
|
1355
|
+
`;
|
|
1356
|
+
if (result.metadata.usesLocalStorage) text += ` - Uses localStorage: Yes
|
|
1357
|
+
`;
|
|
1358
|
+
if (result.metadata.usesCookies) text += ` - Uses cookies: Yes
|
|
1359
|
+
`;
|
|
1360
|
+
if (result.warnings.length > 0) {
|
|
1361
|
+
text += `
|
|
1362
|
+
Warnings:
|
|
1363
|
+
`;
|
|
1364
|
+
for (const w of result.warnings) {
|
|
1365
|
+
text += ` \u26A0\uFE0F ${w}
|
|
1366
|
+
`;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
if (result.suggestions.length > 0) {
|
|
1370
|
+
text += `
|
|
1371
|
+
Suggestions:
|
|
1372
|
+
`;
|
|
1373
|
+
for (const s of result.suggestions) {
|
|
1374
|
+
text += ` \u{1F4A1} ${s}
|
|
1375
|
+
`;
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
if (saveToScript) {
|
|
1379
|
+
text += `
|
|
1380
|
+
\u2713 Metadata saved to script. Run kode_deploy to update CDN.`;
|
|
1381
|
+
} else {
|
|
1382
|
+
text += `
|
|
1383
|
+
Use saveToScript: true to save this metadata to the script.`;
|
|
1384
|
+
}
|
|
1385
|
+
return {
|
|
1386
|
+
content: [{ type: "text", text }]
|
|
1387
|
+
};
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1390
|
+
return {
|
|
1391
|
+
content: [{ type: "text", text: `Failed to analyze script: ${message}` }],
|
|
1392
|
+
isError: true
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
case "kode_get_script_metadata": {
|
|
1397
|
+
const { slug } = args;
|
|
1398
|
+
const scripts = await client.listScripts(siteId);
|
|
1399
|
+
const script = scripts.find((s) => s.slug === slug || s.id === slug);
|
|
1400
|
+
if (!script) {
|
|
1401
|
+
return {
|
|
1402
|
+
content: [{ type: "text", text: `Script "${slug}" not found` }],
|
|
1403
|
+
isError: true
|
|
1404
|
+
};
|
|
1405
|
+
}
|
|
1406
|
+
try {
|
|
1407
|
+
const result = await client.getScriptMetadata(script.id);
|
|
1408
|
+
if (!result.metadata) {
|
|
1409
|
+
return {
|
|
1410
|
+
content: [{
|
|
1411
|
+
type: "text",
|
|
1412
|
+
text: `Script "${script.name}" has no metadata.
|
|
1413
|
+
|
|
1414
|
+
Use kode_analyze_script to generate metadata, or provide metadata when creating/updating the script.`
|
|
1415
|
+
}]
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
let text = `Metadata for: ${script.name}
|
|
1419
|
+
|
|
1420
|
+
`;
|
|
1421
|
+
if (result.metadata.purpose) {
|
|
1422
|
+
text += `Purpose: ${result.metadata.purpose}
|
|
1423
|
+
|
|
1424
|
+
`;
|
|
1425
|
+
}
|
|
1426
|
+
if (result.aiSummary) {
|
|
1427
|
+
text += `AI Summary: ${result.aiSummary}
|
|
1428
|
+
|
|
1429
|
+
`;
|
|
1430
|
+
}
|
|
1431
|
+
if (result.metadata.triggers.length > 0) {
|
|
1432
|
+
text += `Triggers:
|
|
1433
|
+
`;
|
|
1434
|
+
for (const t of result.metadata.triggers) {
|
|
1435
|
+
text += ` - ${t.event}${t.selector ? ` on ${t.selector}` : ""}
|
|
1436
|
+
`;
|
|
1437
|
+
}
|
|
1438
|
+
text += "\n";
|
|
1439
|
+
}
|
|
1440
|
+
if (result.metadata.domTargets.length > 0) {
|
|
1441
|
+
text += `DOM Targets:
|
|
1442
|
+
`;
|
|
1443
|
+
for (const d of result.metadata.domTargets) {
|
|
1444
|
+
text += ` - ${d.selector} (${d.action})
|
|
1445
|
+
`;
|
|
1446
|
+
}
|
|
1447
|
+
text += "\n";
|
|
1448
|
+
}
|
|
1449
|
+
if (result.metadata.dependencies.length > 0) {
|
|
1450
|
+
text += `Dependencies:
|
|
1451
|
+
`;
|
|
1452
|
+
for (const dep of result.metadata.dependencies) {
|
|
1453
|
+
text += ` - ${dep.name}${dep.required ? " (required)" : ""}
|
|
1454
|
+
`;
|
|
1455
|
+
}
|
|
1456
|
+
text += "\n";
|
|
1457
|
+
}
|
|
1458
|
+
text += `Flags:
|
|
1459
|
+
`;
|
|
1460
|
+
text += ` - AI Generated: ${result.aiGenerated ? "Yes" : "No"}
|
|
1461
|
+
`;
|
|
1462
|
+
text += ` - Modifies DOM: ${result.metadata.modifiesDom ? "Yes" : "No"}
|
|
1463
|
+
`;
|
|
1464
|
+
text += ` - Event listeners: ${result.metadata.addsEventListeners ? "Yes" : "No"}
|
|
1465
|
+
`;
|
|
1466
|
+
if (result.lastAnalyzed) {
|
|
1467
|
+
text += `
|
|
1468
|
+
Last analyzed: ${result.lastAnalyzed}`;
|
|
1469
|
+
}
|
|
1470
|
+
return {
|
|
1471
|
+
content: [{ type: "text", text }]
|
|
1472
|
+
};
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1475
|
+
return {
|
|
1476
|
+
content: [{ type: "text", text: `Failed to get metadata: ${message}` }],
|
|
1477
|
+
isError: true
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1005
1481
|
case "kode_read_context": {
|
|
1006
1482
|
const contextPath = getContextPath();
|
|
1007
1483
|
if (!contextPath) {
|