@insforge/mcp 1.2.8 → 1.2.10-dev.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/{chunk-DZ5W3BSP.js → chunk-3HMBKVW5.js} +755 -77
- package/dist/http-server.js +10 -4
- package/dist/index.js +1 -1
- package/package.json +6 -3
|
@@ -41,17 +41,40 @@ ${JSON.stringify(data, null, 2)}`;
|
|
|
41
41
|
|
|
42
42
|
// src/shared/usage-tracker.ts
|
|
43
43
|
import fetch from "node-fetch";
|
|
44
|
+
var PLATFORM_API_BASE = "https://api.insforge.dev";
|
|
45
|
+
function parseAppKey(apiBaseUrl) {
|
|
46
|
+
try {
|
|
47
|
+
const url = new URL(apiBaseUrl);
|
|
48
|
+
const match = url.hostname.match(/^([^.]+)\.[^.]+\.insforge\.app$/);
|
|
49
|
+
return match ? match[1] : null;
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
44
54
|
var UsageTracker = class {
|
|
45
55
|
apiBaseUrl;
|
|
46
56
|
apiKey;
|
|
47
|
-
|
|
57
|
+
agentConnectedReported = false;
|
|
58
|
+
projectId;
|
|
59
|
+
accessToken;
|
|
60
|
+
isRemote;
|
|
61
|
+
constructor(apiBaseUrl, apiKey, options) {
|
|
48
62
|
this.apiBaseUrl = apiBaseUrl;
|
|
49
63
|
this.apiKey = apiKey;
|
|
64
|
+
this.projectId = options?.projectId;
|
|
65
|
+
this.accessToken = options?.accessToken;
|
|
66
|
+
this.isRemote = options?.isRemote ?? false;
|
|
50
67
|
}
|
|
51
68
|
async trackUsage(toolName, success = true) {
|
|
52
69
|
if (!this.apiKey) {
|
|
53
70
|
return;
|
|
54
71
|
}
|
|
72
|
+
if (!this.agentConnectedReported) {
|
|
73
|
+
this.agentConnectedReported = true;
|
|
74
|
+
this.reportAgentConnected().catch((error) => {
|
|
75
|
+
console.error("Failed to report agent-connected:", error);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
55
78
|
try {
|
|
56
79
|
const payload = {
|
|
57
80
|
tool_name: toolName,
|
|
@@ -70,6 +93,27 @@ var UsageTracker = class {
|
|
|
70
93
|
console.error("Failed to track usage:", error);
|
|
71
94
|
}
|
|
72
95
|
}
|
|
96
|
+
async reportAgentConnected() {
|
|
97
|
+
const body = {};
|
|
98
|
+
const headers = { "Content-Type": "application/json" };
|
|
99
|
+
if (this.isRemote && this.projectId && this.projectId !== "legacy") {
|
|
100
|
+
body.project_id = this.projectId;
|
|
101
|
+
if (this.accessToken) {
|
|
102
|
+
headers["Authorization"] = `Bearer ${this.accessToken}`;
|
|
103
|
+
}
|
|
104
|
+
} else {
|
|
105
|
+
const appKey = parseAppKey(this.apiBaseUrl);
|
|
106
|
+
if (!appKey) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
body.app_key = appKey;
|
|
110
|
+
}
|
|
111
|
+
await fetch(`${PLATFORM_API_BASE}/tracking/v1/agent-connected`, {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers,
|
|
114
|
+
body: JSON.stringify(body)
|
|
115
|
+
});
|
|
116
|
+
}
|
|
73
117
|
};
|
|
74
118
|
|
|
75
119
|
// src/shared/tools/docs.ts
|
|
@@ -394,6 +438,12 @@ var storageBucketSchema = z5.object({
|
|
|
394
438
|
public: z5.boolean(),
|
|
395
439
|
createdAt: z5.string()
|
|
396
440
|
});
|
|
441
|
+
var storageConfigSchema = z5.object({
|
|
442
|
+
id: z5.string().uuid(),
|
|
443
|
+
maxFileSizeMb: z5.number().int().positive(),
|
|
444
|
+
createdAt: z5.string(),
|
|
445
|
+
updatedAt: z5.string()
|
|
446
|
+
});
|
|
397
447
|
|
|
398
448
|
// node_modules/@insforge/shared-schemas/dist/storage-api.schema.js
|
|
399
449
|
import { z as z6 } from "zod";
|
|
@@ -440,6 +490,9 @@ var confirmUploadRequestSchema = z6.object({
|
|
|
440
490
|
contentType: z6.string().optional(),
|
|
441
491
|
etag: z6.string().optional()
|
|
442
492
|
});
|
|
493
|
+
var updateStorageConfigRequestSchema = z6.object({
|
|
494
|
+
maxFileSizeMb: z6.number().int().min(1, "Must be at least 1 MB").max(200, "Must be at most 200 MB")
|
|
495
|
+
});
|
|
443
496
|
|
|
444
497
|
// node_modules/@insforge/shared-schemas/dist/auth.schema.js
|
|
445
498
|
import { z as z7 } from "zod";
|
|
@@ -497,6 +550,7 @@ var oAuthConfigSchema = z7.object({
|
|
|
497
550
|
updatedAt: z7.string()
|
|
498
551
|
// PostgreSQL timestamp
|
|
499
552
|
});
|
|
553
|
+
var allowedRedirectUrlsRegex = /^(?:(?:https?:\/\/)(?:(?:\*\.)?[^\s/:?#]+|\[[0-9A-Fa-f:.]+\])(?::\d+)?(?:\/[^\s]*)?|(?!(?:https?|javascript|data|file|vbscript):)[a-zA-Z][a-zA-Z0-9+.-]*:(?:\/\/[^\s/]+(?:\/[^\s]*)?|\/[^\s]*))$/i;
|
|
500
554
|
var authConfigSchema = z7.object({
|
|
501
555
|
id: z7.string().uuid(),
|
|
502
556
|
requireEmailVerification: z7.boolean(),
|
|
@@ -507,12 +561,34 @@ var authConfigSchema = z7.object({
|
|
|
507
561
|
requireSpecialChar: z7.boolean(),
|
|
508
562
|
verifyEmailMethod: verificationMethodSchema,
|
|
509
563
|
resetPasswordMethod: verificationMethodSchema,
|
|
510
|
-
|
|
564
|
+
allowedRedirectUrls: z7.array(z7.string().regex(allowedRedirectUrlsRegex, { message: "Invalid URL or wildcard URL" })).optional().nullable(),
|
|
511
565
|
createdAt: z7.string(),
|
|
512
566
|
// PostgreSQL timestamp
|
|
513
567
|
updatedAt: z7.string()
|
|
514
568
|
// PostgreSQL timestamp
|
|
515
569
|
});
|
|
570
|
+
var smtpConfigSchema = z7.object({
|
|
571
|
+
id: z7.string().uuid(),
|
|
572
|
+
enabled: z7.boolean(),
|
|
573
|
+
host: z7.string(),
|
|
574
|
+
port: z7.number().int(),
|
|
575
|
+
username: z7.string(),
|
|
576
|
+
hasPassword: z7.boolean(),
|
|
577
|
+
// Never expose actual password
|
|
578
|
+
senderEmail: z7.string(),
|
|
579
|
+
senderName: z7.string(),
|
|
580
|
+
minIntervalSeconds: z7.number().int().min(0),
|
|
581
|
+
createdAt: z7.string(),
|
|
582
|
+
updatedAt: z7.string()
|
|
583
|
+
});
|
|
584
|
+
var emailTemplateSchema = z7.object({
|
|
585
|
+
id: z7.string().uuid(),
|
|
586
|
+
templateType: z7.string(),
|
|
587
|
+
subject: z7.string(),
|
|
588
|
+
bodyHtml: z7.string(),
|
|
589
|
+
createdAt: z7.string(),
|
|
590
|
+
updatedAt: z7.string()
|
|
591
|
+
});
|
|
516
592
|
var tokenPayloadSchema = z7.object({
|
|
517
593
|
sub: userIdSchema,
|
|
518
594
|
// Subject (user ID)
|
|
@@ -523,6 +599,16 @@ var tokenPayloadSchema = z7.object({
|
|
|
523
599
|
exp: z7.number().optional()
|
|
524
600
|
// Expiration
|
|
525
601
|
});
|
|
602
|
+
var customOAuthKeySchema = z7.string().min(1).max(64).regex(/^[a-z0-9_-]+$/, "Key must contain only lowercase letters, numbers, hyphens, and underscores");
|
|
603
|
+
var customOAuthConfigSchema = z7.object({
|
|
604
|
+
id: z7.string().uuid(),
|
|
605
|
+
key: customOAuthKeySchema,
|
|
606
|
+
name: z7.string().min(1),
|
|
607
|
+
discoveryEndpoint: z7.string().url(),
|
|
608
|
+
clientId: z7.string().min(1),
|
|
609
|
+
createdAt: z7.string(),
|
|
610
|
+
updatedAt: z7.string()
|
|
611
|
+
});
|
|
526
612
|
|
|
527
613
|
// node_modules/@insforge/shared-schemas/dist/auth-api.schema.js
|
|
528
614
|
import { z as z8 } from "zod";
|
|
@@ -530,19 +616,20 @@ var paginationSchema = z8.object({
|
|
|
530
616
|
limit: z8.string().optional(),
|
|
531
617
|
offset: z8.string().optional()
|
|
532
618
|
});
|
|
533
|
-
var authOptionsSchema = z8.object({
|
|
534
|
-
emailRedirectTo: z8.string().url().optional()
|
|
535
|
-
}).optional();
|
|
536
619
|
var createUserRequestSchema = z8.object({
|
|
537
620
|
email: emailSchema,
|
|
538
621
|
password: passwordSchema,
|
|
539
622
|
name: nameSchema.optional(),
|
|
540
|
-
|
|
623
|
+
redirectTo: z8.string().url().optional(),
|
|
624
|
+
autoConfirm: z8.boolean().optional()
|
|
541
625
|
});
|
|
542
626
|
var createSessionRequestSchema = z8.object({
|
|
543
627
|
email: emailSchema,
|
|
544
628
|
password: passwordSchema
|
|
545
629
|
});
|
|
630
|
+
var refreshSessionRequestSchema = z8.object({
|
|
631
|
+
refreshToken: z8.string().min(1, "refreshToken is required")
|
|
632
|
+
});
|
|
546
633
|
var exchangeAdminSessionRequestSchema = z8.object({
|
|
547
634
|
code: z8.string()
|
|
548
635
|
});
|
|
@@ -557,20 +644,19 @@ var updateProfileRequestSchema = z8.object({
|
|
|
557
644
|
});
|
|
558
645
|
var sendVerificationEmailRequestSchema = z8.object({
|
|
559
646
|
email: emailSchema,
|
|
560
|
-
|
|
647
|
+
redirectTo: z8.string().url().optional()
|
|
561
648
|
});
|
|
562
649
|
var verifyEmailRequestSchema = z8.object({
|
|
563
|
-
email: emailSchema
|
|
564
|
-
otp: z8.string().
|
|
565
|
-
}).refine((data) => data.email || data.otp, {
|
|
566
|
-
message: "Either email or otp must be provided"
|
|
650
|
+
email: emailSchema,
|
|
651
|
+
otp: z8.string().regex(/^\d{6}$/, "OTP code must be a 6-digit numeric code")
|
|
567
652
|
});
|
|
568
653
|
var sendResetPasswordEmailRequestSchema = z8.object({
|
|
569
|
-
email: emailSchema
|
|
654
|
+
email: emailSchema,
|
|
655
|
+
redirectTo: z8.string().url().optional()
|
|
570
656
|
});
|
|
571
657
|
var exchangeResetPasswordTokenRequestSchema = z8.object({
|
|
572
658
|
email: emailSchema,
|
|
573
|
-
code: z8.string().
|
|
659
|
+
code: z8.string().regex(/^\d{6}$/, "Reset password code must be a 6-digit numeric code")
|
|
574
660
|
});
|
|
575
661
|
var resetPasswordRequestSchema = z8.object({
|
|
576
662
|
newPassword: passwordSchema,
|
|
@@ -580,7 +666,6 @@ var createUserResponseSchema = z8.object({
|
|
|
580
666
|
user: userSchema.optional(),
|
|
581
667
|
accessToken: z8.string().nullable(),
|
|
582
668
|
requireEmailVerification: z8.boolean().optional(),
|
|
583
|
-
redirectTo: z8.string().url().optional(),
|
|
584
669
|
csrfToken: z8.string().nullable().optional(),
|
|
585
670
|
refreshToken: z8.string().optional()
|
|
586
671
|
// For mobile/desktop clients (no cookies)
|
|
@@ -588,7 +673,6 @@ var createUserResponseSchema = z8.object({
|
|
|
588
673
|
var createSessionResponseSchema = z8.object({
|
|
589
674
|
user: userSchema,
|
|
590
675
|
accessToken: z8.string(),
|
|
591
|
-
redirectTo: z8.string().url().optional(),
|
|
592
676
|
csrfToken: z8.string().nullable().optional(),
|
|
593
677
|
refreshToken: z8.string().optional()
|
|
594
678
|
// For mobile/desktop clients (no cookies)
|
|
@@ -596,7 +680,6 @@ var createSessionResponseSchema = z8.object({
|
|
|
596
680
|
var verifyEmailResponseSchema = z8.object({
|
|
597
681
|
user: userSchema,
|
|
598
682
|
accessToken: z8.string(),
|
|
599
|
-
redirectTo: z8.string().url().optional(),
|
|
600
683
|
csrfToken: z8.string().nullable().optional(),
|
|
601
684
|
refreshToken: z8.string().optional()
|
|
602
685
|
// For mobile/desktop clients (no cookies)
|
|
@@ -676,19 +759,49 @@ var updateAuthConfigRequestSchema = authConfigSchema.omit({
|
|
|
676
759
|
}).partial();
|
|
677
760
|
var getPublicAuthConfigResponseSchema = z8.object({
|
|
678
761
|
oAuthProviders: z8.array(oAuthProvidersSchema),
|
|
762
|
+
customOAuthProviders: z8.array(customOAuthKeySchema),
|
|
679
763
|
...authConfigSchema.omit({
|
|
680
764
|
id: true,
|
|
681
765
|
updatedAt: true,
|
|
682
766
|
createdAt: true,
|
|
683
|
-
|
|
767
|
+
allowedRedirectUrls: true
|
|
684
768
|
}).shape
|
|
685
769
|
});
|
|
770
|
+
var upsertSmtpConfigRequestSchema = z8.object({
|
|
771
|
+
enabled: z8.boolean(),
|
|
772
|
+
host: z8.string().min(1, "SMTP host is required"),
|
|
773
|
+
port: z8.union([z8.literal(25), z8.literal(465), z8.literal(587), z8.literal(2525)], {
|
|
774
|
+
errorMap: () => ({ message: "Port must be one of: 25, 465, 587, 2525" })
|
|
775
|
+
}),
|
|
776
|
+
username: z8.string().min(1, "SMTP username is required"),
|
|
777
|
+
password: z8.string().min(1, "SMTP password is required").optional(),
|
|
778
|
+
senderEmail: z8.string().email("Invalid sender email"),
|
|
779
|
+
senderName: z8.string().min(1, "Sender name is required"),
|
|
780
|
+
minIntervalSeconds: z8.number().int().min(0).default(60)
|
|
781
|
+
});
|
|
782
|
+
var updateEmailTemplateRequestSchema = z8.object({
|
|
783
|
+
subject: z8.string().min(1, "Subject is required"),
|
|
784
|
+
bodyHtml: z8.string().min(1, "Template body is required")
|
|
785
|
+
});
|
|
786
|
+
var listEmailTemplatesResponseSchema = z8.object({
|
|
787
|
+
data: z8.array(emailTemplateSchema)
|
|
788
|
+
});
|
|
686
789
|
var authErrorResponseSchema = z8.object({
|
|
687
790
|
error: z8.string(),
|
|
688
791
|
message: z8.string(),
|
|
689
792
|
statusCode: z8.number().int(),
|
|
690
793
|
nextActions: z8.string().optional()
|
|
691
794
|
});
|
|
795
|
+
var createCustomOAuthConfigRequestSchema = customOAuthConfigSchema.omit({ id: true, createdAt: true, updatedAt: true }).extend({
|
|
796
|
+
clientSecret: z8.string().min(1, "Client secret is required")
|
|
797
|
+
});
|
|
798
|
+
var updateCustomOAuthConfigRequestSchema = customOAuthConfigSchema.omit({ id: true, key: true, createdAt: true, updatedAt: true }).extend({
|
|
799
|
+
clientSecret: z8.string().min(1).optional()
|
|
800
|
+
}).partial();
|
|
801
|
+
var listCustomOAuthConfigsResponseSchema = z8.object({
|
|
802
|
+
data: z8.array(customOAuthConfigSchema),
|
|
803
|
+
count: z8.number()
|
|
804
|
+
});
|
|
692
805
|
|
|
693
806
|
// node_modules/@insforge/shared-schemas/dist/metadata.schema.js
|
|
694
807
|
import { z as z11 } from "zod";
|
|
@@ -718,6 +831,9 @@ var realtimeMessageSchema = z9.object({
|
|
|
718
831
|
whDeliveredCount: z9.number().int().min(0),
|
|
719
832
|
createdAt: z9.string().datetime()
|
|
720
833
|
});
|
|
834
|
+
var realtimeConfigSchema = z9.object({
|
|
835
|
+
retentionDays: z9.number().int().positive().nullable()
|
|
836
|
+
});
|
|
721
837
|
var subscribeChannelPayloadSchema = z9.object({
|
|
722
838
|
channel: z9.string().min(1)
|
|
723
839
|
// The resolved channel instance, e.g., "order:123"
|
|
@@ -803,7 +919,8 @@ var messageStatsResponseSchema = z10.object({
|
|
|
803
919
|
topEvents: z10.array(z10.object({
|
|
804
920
|
eventName: z10.string(),
|
|
805
921
|
count: z10.number().int().min(0)
|
|
806
|
-
}))
|
|
922
|
+
})),
|
|
923
|
+
retentionDays: realtimeConfigSchema.shape.retentionDays
|
|
807
924
|
});
|
|
808
925
|
var rlsPolicySchema = z10.object({
|
|
809
926
|
policyName: z10.string(),
|
|
@@ -883,6 +1000,9 @@ var databasePasswordInfoSchema = z11.object({
|
|
|
883
1000
|
var apiKeyResponseSchema = z11.object({
|
|
884
1001
|
apiKey: z11.string()
|
|
885
1002
|
});
|
|
1003
|
+
var projectIdResponseSchema = z11.object({
|
|
1004
|
+
projectId: z11.string().nullable()
|
|
1005
|
+
});
|
|
886
1006
|
|
|
887
1007
|
// node_modules/@insforge/shared-schemas/dist/ai.schema.js
|
|
888
1008
|
import { z as z12 } from "zod";
|
|
@@ -975,12 +1095,42 @@ var contentSchema = z13.union([
|
|
|
975
1095
|
audioContentSchema,
|
|
976
1096
|
fileContentSchema
|
|
977
1097
|
]);
|
|
1098
|
+
var toolFunctionSchema = z13.object({
|
|
1099
|
+
name: z13.string(),
|
|
1100
|
+
description: z13.string().optional(),
|
|
1101
|
+
parameters: z13.record(z13.unknown()).optional()
|
|
1102
|
+
});
|
|
1103
|
+
var toolSchema = z13.object({
|
|
1104
|
+
type: z13.literal("function"),
|
|
1105
|
+
function: toolFunctionSchema
|
|
1106
|
+
});
|
|
1107
|
+
var toolChoiceSchema = z13.union([
|
|
1108
|
+
z13.enum(["auto", "none", "required"]),
|
|
1109
|
+
z13.object({
|
|
1110
|
+
type: z13.literal("function"),
|
|
1111
|
+
function: z13.object({ name: z13.string() })
|
|
1112
|
+
})
|
|
1113
|
+
]);
|
|
1114
|
+
var toolCallSchema = z13.object({
|
|
1115
|
+
id: z13.string(),
|
|
1116
|
+
type: z13.literal("function"),
|
|
1117
|
+
function: z13.object({
|
|
1118
|
+
name: z13.string(),
|
|
1119
|
+
arguments: z13.string()
|
|
1120
|
+
})
|
|
1121
|
+
});
|
|
978
1122
|
var chatMessageSchema = z13.object({
|
|
979
|
-
role: z13.enum(["user", "assistant", "system"]),
|
|
1123
|
+
role: z13.enum(["user", "assistant", "system", "tool"]),
|
|
980
1124
|
// New format: content can be string or array of content parts (OpenAI-compatible)
|
|
981
|
-
content: z13.union([z13.string(), z13.array(contentSchema)]),
|
|
1125
|
+
content: z13.union([z13.string(), z13.array(contentSchema)]).nullable(),
|
|
982
1126
|
// Legacy format: separate images field (deprecated but supported for backward compatibility)
|
|
983
|
-
images: z13.array(z13.object({ url: z13.string() })).optional()
|
|
1127
|
+
images: z13.array(z13.object({ url: z13.string() })).optional(),
|
|
1128
|
+
// Tool calls made by the assistant
|
|
1129
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1130
|
+
tool_calls: z13.array(toolCallSchema).optional(),
|
|
1131
|
+
// Tool call ID for tool response messages
|
|
1132
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1133
|
+
tool_call_id: z13.string().optional()
|
|
984
1134
|
});
|
|
985
1135
|
var webSearchPluginSchema = z13.object({
|
|
986
1136
|
enabled: z13.boolean(),
|
|
@@ -1020,7 +1170,13 @@ var chatCompletionRequestSchema = z13.object({
|
|
|
1020
1170
|
fileParser: fileParserPluginSchema.optional(),
|
|
1021
1171
|
// Thinking/Reasoning mode: Enable extended reasoning capabilities
|
|
1022
1172
|
// Appends ":thinking" to the model ID for chain-of-thought reasoning
|
|
1023
|
-
thinking: z13.boolean().optional()
|
|
1173
|
+
thinking: z13.boolean().optional(),
|
|
1174
|
+
// Tool calling: Define functions the AI can call
|
|
1175
|
+
tools: z13.array(toolSchema).optional(),
|
|
1176
|
+
// Tool choice: Control whether/which tool is called ('auto', 'none', 'required', or specific function)
|
|
1177
|
+
toolChoice: toolChoiceSchema.optional(),
|
|
1178
|
+
// Parallel tool calls: Allow the model to call multiple tools in parallel
|
|
1179
|
+
parallelToolCalls: z13.boolean().optional()
|
|
1024
1180
|
});
|
|
1025
1181
|
var urlCitationAnnotationSchema = z13.object({
|
|
1026
1182
|
type: z13.literal("url_citation"),
|
|
@@ -1046,6 +1202,9 @@ var fileAnnotationSchema = z13.object({
|
|
|
1046
1202
|
var annotationSchema = z13.union([urlCitationAnnotationSchema, fileAnnotationSchema]);
|
|
1047
1203
|
var chatCompletionResponseSchema = z13.object({
|
|
1048
1204
|
text: z13.string(),
|
|
1205
|
+
// Tool calls from the assistant (present when the model invokes tools)
|
|
1206
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
1207
|
+
tool_calls: z13.array(toolCallSchema).optional(),
|
|
1049
1208
|
// Annotations from web search or file parsing (can be URL citations or file annotations)
|
|
1050
1209
|
annotations: z13.array(annotationSchema).optional(),
|
|
1051
1210
|
metadata: z13.object({
|
|
@@ -1135,6 +1294,15 @@ var getAIUsageSummaryRequestSchema = z13.object({
|
|
|
1135
1294
|
startDate: z13.string().datetime().optional(),
|
|
1136
1295
|
endDate: z13.string().datetime().optional()
|
|
1137
1296
|
});
|
|
1297
|
+
var keySourceSchema = z13.enum(["byok", "cloud", "env", "unconfigured"]);
|
|
1298
|
+
var gatewayConfigResponseSchema = z13.object({
|
|
1299
|
+
keySource: keySourceSchema,
|
|
1300
|
+
hasByokKey: z13.boolean(),
|
|
1301
|
+
maskedKey: z13.string().optional()
|
|
1302
|
+
});
|
|
1303
|
+
var setGatewayBYOKKeyRequestSchema = z13.object({
|
|
1304
|
+
apiKey: z13.string().min(1, "API key is required")
|
|
1305
|
+
});
|
|
1138
1306
|
|
|
1139
1307
|
// node_modules/@insforge/shared-schemas/dist/logs.schema.js
|
|
1140
1308
|
import { z as z14 } from "zod";
|
|
@@ -1165,6 +1333,16 @@ var logStatsSchema = z14.object({
|
|
|
1165
1333
|
count: z14.number(),
|
|
1166
1334
|
lastActivity: z14.string()
|
|
1167
1335
|
});
|
|
1336
|
+
var buildLogEntrySchema = z14.object({
|
|
1337
|
+
level: z14.string(),
|
|
1338
|
+
message: z14.string()
|
|
1339
|
+
});
|
|
1340
|
+
var getBuildLogsResponseSchema = z14.object({
|
|
1341
|
+
deploymentId: z14.string(),
|
|
1342
|
+
status: z14.enum(["pending", "success", "failed"]),
|
|
1343
|
+
logs: z14.array(buildLogEntrySchema),
|
|
1344
|
+
createdAt: z14.string()
|
|
1345
|
+
});
|
|
1168
1346
|
|
|
1169
1347
|
// node_modules/@insforge/shared-schemas/dist/logs-api.schema.js
|
|
1170
1348
|
import { z as z15 } from "zod";
|
|
@@ -1240,7 +1418,19 @@ var listFunctionsResponseSchema = z17.object({
|
|
|
1240
1418
|
functions: z17.array(functionSchema),
|
|
1241
1419
|
runtime: z17.object({
|
|
1242
1420
|
status: z17.enum(["running", "unavailable"])
|
|
1243
|
-
})
|
|
1421
|
+
}),
|
|
1422
|
+
deploymentUrl: z17.string().nullable().optional()
|
|
1423
|
+
});
|
|
1424
|
+
var deploymentResultSchema = z17.object({
|
|
1425
|
+
id: z17.string(),
|
|
1426
|
+
status: z17.enum(["success", "failed"]),
|
|
1427
|
+
url: z17.string().nullable(),
|
|
1428
|
+
buildLogs: z17.array(z17.string()).optional()
|
|
1429
|
+
});
|
|
1430
|
+
var functionResponseSchema = z17.object({
|
|
1431
|
+
success: z17.boolean(),
|
|
1432
|
+
function: functionSchema,
|
|
1433
|
+
deployment: deploymentResultSchema.nullable().optional()
|
|
1244
1434
|
});
|
|
1245
1435
|
|
|
1246
1436
|
// node_modules/@insforge/shared-schemas/dist/cloud-events.schema.js
|
|
@@ -1280,6 +1470,9 @@ var showContactModalEventSchema = z18.object({
|
|
|
1280
1470
|
var showConnectOverlayEventSchema = z18.object({
|
|
1281
1471
|
type: z18.literal("SHOW_CONNECT_OVERLAY")
|
|
1282
1472
|
});
|
|
1473
|
+
var showPlanModalEventSchema = z18.object({
|
|
1474
|
+
type: z18.literal("SHOW_PLAN_MODAL")
|
|
1475
|
+
});
|
|
1283
1476
|
var authorizationCodeEventSchema = z18.object({
|
|
1284
1477
|
type: z18.literal("AUTHORIZATION_CODE"),
|
|
1285
1478
|
code: z18.string()
|
|
@@ -1288,6 +1481,51 @@ var routeChangeEventSchema = z18.object({
|
|
|
1288
1481
|
type: z18.literal("ROUTE_CHANGE"),
|
|
1289
1482
|
path: z18.string()
|
|
1290
1483
|
});
|
|
1484
|
+
var requestProjectInfoEventSchema = z18.object({
|
|
1485
|
+
type: z18.literal("REQUEST_PROJECT_INFO")
|
|
1486
|
+
});
|
|
1487
|
+
var projectInfoEventSchema = z18.object({
|
|
1488
|
+
type: z18.literal("PROJECT_INFO"),
|
|
1489
|
+
name: z18.string(),
|
|
1490
|
+
instanceType: z18.string(),
|
|
1491
|
+
region: z18.string(),
|
|
1492
|
+
latestVersion: z18.string().optional()
|
|
1493
|
+
});
|
|
1494
|
+
var requestInstanceInfoEventSchema = z18.object({
|
|
1495
|
+
type: z18.literal("REQUEST_INSTANCE_INFO")
|
|
1496
|
+
});
|
|
1497
|
+
var instanceInfoEventSchema = z18.object({
|
|
1498
|
+
type: z18.literal("INSTANCE_INFO"),
|
|
1499
|
+
currentInstanceType: z18.string(),
|
|
1500
|
+
planName: z18.string(),
|
|
1501
|
+
computeCredits: z18.number(),
|
|
1502
|
+
currentOrgComputeCost: z18.number(),
|
|
1503
|
+
instanceTypes: z18.array(z18.object({
|
|
1504
|
+
id: z18.string(),
|
|
1505
|
+
name: z18.string(),
|
|
1506
|
+
cpu: z18.string(),
|
|
1507
|
+
ram: z18.string(),
|
|
1508
|
+
pricePerHour: z18.number(),
|
|
1509
|
+
pricePerMonth: z18.number()
|
|
1510
|
+
})),
|
|
1511
|
+
projects: z18.array(z18.object({
|
|
1512
|
+
name: z18.string(),
|
|
1513
|
+
instanceType: z18.string(),
|
|
1514
|
+
monthlyCost: z18.number(),
|
|
1515
|
+
isCurrent: z18.boolean(),
|
|
1516
|
+
status: z18.string()
|
|
1517
|
+
}))
|
|
1518
|
+
});
|
|
1519
|
+
var requestInstanceTypeChangeEventSchema = z18.object({
|
|
1520
|
+
type: z18.literal("REQUEST_INSTANCE_TYPE_CHANGE"),
|
|
1521
|
+
instanceType: z18.string()
|
|
1522
|
+
});
|
|
1523
|
+
var instanceTypeChangeResultEventSchema = z18.object({
|
|
1524
|
+
type: z18.literal("INSTANCE_TYPE_CHANGE_RESULT"),
|
|
1525
|
+
success: z18.boolean(),
|
|
1526
|
+
instanceType: z18.string().optional(),
|
|
1527
|
+
error: z18.string().optional()
|
|
1528
|
+
});
|
|
1291
1529
|
var cloudEventSchema = z18.discriminatedUnion("type", [
|
|
1292
1530
|
appRouteChangeEventSchema,
|
|
1293
1531
|
authSuccessEventSchema,
|
|
@@ -1299,8 +1537,15 @@ var cloudEventSchema = z18.discriminatedUnion("type", [
|
|
|
1299
1537
|
navigateToUsageSchema,
|
|
1300
1538
|
showContactModalEventSchema,
|
|
1301
1539
|
showConnectOverlayEventSchema,
|
|
1540
|
+
showPlanModalEventSchema,
|
|
1302
1541
|
authorizationCodeEventSchema,
|
|
1303
|
-
routeChangeEventSchema
|
|
1542
|
+
routeChangeEventSchema,
|
|
1543
|
+
requestProjectInfoEventSchema,
|
|
1544
|
+
projectInfoEventSchema,
|
|
1545
|
+
requestInstanceInfoEventSchema,
|
|
1546
|
+
instanceInfoEventSchema,
|
|
1547
|
+
requestInstanceTypeChangeEventSchema,
|
|
1548
|
+
instanceTypeChangeResultEventSchema
|
|
1304
1549
|
]);
|
|
1305
1550
|
|
|
1306
1551
|
// node_modules/@insforge/shared-schemas/dist/docs.schema.js
|
|
@@ -1336,8 +1581,6 @@ var docTypeSchema = z19.enum([
|
|
|
1336
1581
|
"storage-sdk",
|
|
1337
1582
|
"functions-sdk",
|
|
1338
1583
|
"ai-integration-sdk",
|
|
1339
|
-
"auth-components-react",
|
|
1340
|
-
"auth-components-nextjs",
|
|
1341
1584
|
"real-time",
|
|
1342
1585
|
"deployment"
|
|
1343
1586
|
]).describe(`
|
|
@@ -1347,8 +1590,6 @@ var docTypeSchema = z19.enum([
|
|
|
1347
1590
|
"storage-sdk" (file storage),
|
|
1348
1591
|
"functions-sdk" (edge functions),
|
|
1349
1592
|
"auth-sdk" (direct SDK methods for custom auth flows),
|
|
1350
|
-
"auth-components-react" (authentication components for React+Vite applications),
|
|
1351
|
-
"auth-components-nextjs" (authentication components for Next.js applications),
|
|
1352
1593
|
"ai-integration-sdk" (AI features),
|
|
1353
1594
|
"real-time" (real-time pub/sub through WebSockets),
|
|
1354
1595
|
"deployment" (deploy frontend applications via MCP tool)
|
|
@@ -1375,9 +1616,9 @@ var sendEmailResponseSchema = z20.object({});
|
|
|
1375
1616
|
import { z as z21 } from "zod";
|
|
1376
1617
|
var deploymentStatusSchema = z21.enum([
|
|
1377
1618
|
"WAITING",
|
|
1378
|
-
// Record created, waiting for
|
|
1619
|
+
// Record created, waiting for source zip upload or direct file registration/content
|
|
1379
1620
|
"UPLOADING",
|
|
1380
|
-
//
|
|
1621
|
+
// File uploads or Vercel deployment creation are in progress
|
|
1381
1622
|
"QUEUED",
|
|
1382
1623
|
// Vercel: deployment queued
|
|
1383
1624
|
"BUILDING",
|
|
@@ -1414,11 +1655,47 @@ var envVarSchema = z22.object({
|
|
|
1414
1655
|
key: z22.string(),
|
|
1415
1656
|
value: z22.string()
|
|
1416
1657
|
});
|
|
1658
|
+
var deploymentFilePathSchema = z22.string().min(1, "path is required").max(2048, "path is too long").refine((value) => !value.includes("\0"), "path cannot contain null bytes").refine((value) => !value.includes("\\"), "path must use forward slashes").refine((value) => !value.startsWith("/"), "path must be relative").refine((value) => value.split("/").every((part) => part !== "" && part !== "." && part !== ".."), "path cannot contain empty, current, or parent directory segments");
|
|
1659
|
+
var deploymentManifestFileEntrySchema = z22.object({
|
|
1660
|
+
path: deploymentFilePathSchema,
|
|
1661
|
+
sha: z22.string().regex(/^[a-f0-9]{40}$/i, "sha must be a SHA-1 hex digest"),
|
|
1662
|
+
size: z22.number().int().nonnegative()
|
|
1663
|
+
});
|
|
1664
|
+
var deploymentManifestFileSchema = deploymentManifestFileEntrySchema.extend({
|
|
1665
|
+
fileId: z22.string().uuid(),
|
|
1666
|
+
uploadedAt: z22.string().datetime().nullable()
|
|
1667
|
+
});
|
|
1417
1668
|
var createDeploymentResponseSchema = z22.object({
|
|
1418
1669
|
id: z22.string().uuid(),
|
|
1419
1670
|
uploadUrl: z22.string().url(),
|
|
1420
1671
|
uploadFields: z22.record(z22.string())
|
|
1421
|
-
|
|
1672
|
+
});
|
|
1673
|
+
var createDirectDeploymentResponseSchema = z22.object({
|
|
1674
|
+
id: z22.string().uuid(),
|
|
1675
|
+
status: deploymentSchema.shape.status
|
|
1676
|
+
});
|
|
1677
|
+
var createDeploymentManifestRequestSchema = z22.object({
|
|
1678
|
+
files: z22.array(deploymentManifestFileEntrySchema).min(1)
|
|
1679
|
+
}).superRefine(({ files }, ctx) => {
|
|
1680
|
+
const firstSeenByPath = /* @__PURE__ */ new Map();
|
|
1681
|
+
files.forEach((file, index) => {
|
|
1682
|
+
const existingIndex = firstSeenByPath.get(file.path);
|
|
1683
|
+
if (existingIndex !== void 0) {
|
|
1684
|
+
ctx.addIssue({
|
|
1685
|
+
code: z22.ZodIssueCode.custom,
|
|
1686
|
+
message: "duplicate file path",
|
|
1687
|
+
path: ["files", index, "path"]
|
|
1688
|
+
});
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
firstSeenByPath.set(file.path, index);
|
|
1692
|
+
});
|
|
1693
|
+
});
|
|
1694
|
+
var createDeploymentManifestResponseSchema = z22.object({
|
|
1695
|
+
files: z22.array(deploymentManifestFileSchema)
|
|
1696
|
+
});
|
|
1697
|
+
var uploadDeploymentFileResponseSchema = deploymentManifestFileSchema.extend({
|
|
1698
|
+
uploadedAt: z22.string().datetime()
|
|
1422
1699
|
});
|
|
1423
1700
|
var startDeploymentRequestSchema = z22.object({
|
|
1424
1701
|
projectSettings: projectSettingsSchema.optional(),
|
|
@@ -1433,6 +1710,96 @@ var listDeploymentsResponseSchema = z22.object({
|
|
|
1433
1710
|
total: z22.number()
|
|
1434
1711
|
})
|
|
1435
1712
|
});
|
|
1713
|
+
var deploymentEnvVarSchema = z22.object({
|
|
1714
|
+
id: z22.string(),
|
|
1715
|
+
// Vercel env var ID (needed for delete/get)
|
|
1716
|
+
key: z22.string(),
|
|
1717
|
+
type: z22.enum(["plain", "encrypted", "secret", "sensitive", "system"]),
|
|
1718
|
+
updatedAt: z22.number().optional()
|
|
1719
|
+
// Unix timestamp (milliseconds)
|
|
1720
|
+
});
|
|
1721
|
+
var deploymentEnvVarWithValueSchema = z22.object({
|
|
1722
|
+
id: z22.string(),
|
|
1723
|
+
key: z22.string(),
|
|
1724
|
+
value: z22.string(),
|
|
1725
|
+
type: z22.enum(["plain", "encrypted", "secret", "sensitive", "system"]),
|
|
1726
|
+
updatedAt: z22.number().optional()
|
|
1727
|
+
});
|
|
1728
|
+
var listEnvVarsResponseSchema = z22.object({
|
|
1729
|
+
envVars: z22.array(deploymentEnvVarSchema)
|
|
1730
|
+
});
|
|
1731
|
+
var getEnvVarResponseSchema = z22.object({
|
|
1732
|
+
envVar: deploymentEnvVarWithValueSchema
|
|
1733
|
+
});
|
|
1734
|
+
var upsertEnvVarRequestSchema = z22.object({
|
|
1735
|
+
key: z22.string().trim().min(1, "key is required"),
|
|
1736
|
+
value: z22.string()
|
|
1737
|
+
});
|
|
1738
|
+
var upsertEnvVarsRequestSchema = z22.object({
|
|
1739
|
+
envVars: z22.array(upsertEnvVarRequestSchema).min(1)
|
|
1740
|
+
}).superRefine(({ envVars }, ctx) => {
|
|
1741
|
+
const firstSeenByKey = /* @__PURE__ */ new Map();
|
|
1742
|
+
envVars.forEach((envVar, index) => {
|
|
1743
|
+
const existingIndex = firstSeenByKey.get(envVar.key);
|
|
1744
|
+
if (existingIndex !== void 0) {
|
|
1745
|
+
ctx.addIssue({
|
|
1746
|
+
code: z22.ZodIssueCode.custom,
|
|
1747
|
+
message: "duplicate environment variable key",
|
|
1748
|
+
path: ["envVars", index, "key"]
|
|
1749
|
+
});
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
firstSeenByKey.set(envVar.key, index);
|
|
1753
|
+
});
|
|
1754
|
+
});
|
|
1755
|
+
var upsertEnvVarResponseSchema = z22.object({
|
|
1756
|
+
success: z22.literal(true),
|
|
1757
|
+
message: z22.string()
|
|
1758
|
+
});
|
|
1759
|
+
var upsertEnvVarsResponseSchema = z22.object({
|
|
1760
|
+
success: z22.literal(true),
|
|
1761
|
+
message: z22.string(),
|
|
1762
|
+
count: z22.number().int().positive()
|
|
1763
|
+
});
|
|
1764
|
+
var deleteEnvVarResponseSchema = z22.object({
|
|
1765
|
+
success: z22.literal(true),
|
|
1766
|
+
message: z22.string()
|
|
1767
|
+
});
|
|
1768
|
+
var updateSlugRequestSchema = z22.object({
|
|
1769
|
+
slug: z22.string().trim().min(3, "slug must be at least 3 characters").max(63, "slug must be at most 63 characters").regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/, "slug must be lowercase alphanumeric with hyphens, not starting or ending with hyphen").nullable()
|
|
1770
|
+
});
|
|
1771
|
+
var updateSlugResponseSchema = z22.object({
|
|
1772
|
+
success: z22.boolean(),
|
|
1773
|
+
slug: z22.string().nullable(),
|
|
1774
|
+
domain: z22.string().nullable()
|
|
1775
|
+
});
|
|
1776
|
+
var deploymentMetadataResponseSchema = z22.object({
|
|
1777
|
+
currentDeploymentId: z22.string().uuid().nullable(),
|
|
1778
|
+
defaultDomainUrl: z22.string().nullable(),
|
|
1779
|
+
customDomainUrl: z22.string().nullable()
|
|
1780
|
+
});
|
|
1781
|
+
var domainVerificationRecordSchema = z22.object({
|
|
1782
|
+
type: z22.string(),
|
|
1783
|
+
domain: z22.string(),
|
|
1784
|
+
value: z22.string()
|
|
1785
|
+
});
|
|
1786
|
+
var customDomainSchema = z22.object({
|
|
1787
|
+
domain: z22.string(),
|
|
1788
|
+
apexDomain: z22.string(),
|
|
1789
|
+
verified: z22.boolean(),
|
|
1790
|
+
misconfigured: z22.boolean(),
|
|
1791
|
+
verification: z22.array(domainVerificationRecordSchema),
|
|
1792
|
+
cnameTarget: z22.string().nullable(),
|
|
1793
|
+
aRecordValue: z22.string().nullable()
|
|
1794
|
+
});
|
|
1795
|
+
var addCustomDomainRequestSchema = z22.object({
|
|
1796
|
+
domain: z22.string().trim().min(1, "Domain is required").regex(/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/i, "Invalid domain format (e.g. myapp.com or www.myapp.com)").refine((domain) => !domain.toLowerCase().endsWith(".insforge.site"), {
|
|
1797
|
+
message: "Domains ending with .insforge.site are reserved by InsForge"
|
|
1798
|
+
})
|
|
1799
|
+
});
|
|
1800
|
+
var listCustomDomainsResponseSchema = z22.object({
|
|
1801
|
+
domains: z22.array(customDomainSchema)
|
|
1802
|
+
});
|
|
1436
1803
|
|
|
1437
1804
|
// node_modules/@insforge/shared-schemas/dist/schedules.schema.js
|
|
1438
1805
|
import { z as z23 } from "zod";
|
|
@@ -2273,23 +2640,320 @@ function registerFunctionTools(ctx) {
|
|
|
2273
2640
|
// src/shared/tools/deployment.ts
|
|
2274
2641
|
import { z as z29 } from "zod";
|
|
2275
2642
|
import fetch6 from "node-fetch";
|
|
2643
|
+
import { createHash } from "crypto";
|
|
2276
2644
|
import { promises as fs3, createWriteStream, createReadStream } from "fs";
|
|
2277
2645
|
import { tmpdir as tmpdir2 } from "os";
|
|
2278
|
-
import { join as join2 } from "path";
|
|
2646
|
+
import { join as join2, relative, sep } from "path";
|
|
2279
2647
|
import archiver from "archiver";
|
|
2280
2648
|
import FormData2 from "form-data";
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2649
|
+
var DIRECT_DEPLOYMENT_MIN_VERSION = "2.0.5";
|
|
2650
|
+
var EXCLUDED_DEPLOYMENT_SEGMENTS = /* @__PURE__ */ new Set(["node_modules", ".git", ".next", "dist", "build", ".insforge"]);
|
|
2651
|
+
var DirectDeploymentUnsupportedError = class extends Error {
|
|
2652
|
+
constructor() {
|
|
2653
|
+
super("Direct deployment endpoints are not available on this backend");
|
|
2654
|
+
this.name = "DirectDeploymentUnsupportedError";
|
|
2284
2655
|
}
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2656
|
+
};
|
|
2657
|
+
function isAbsoluteSourcePath(sourceDirectory) {
|
|
2658
|
+
return sourceDirectory.startsWith("/") || /^[a-zA-Z]:[/\\]/.test(sourceDirectory);
|
|
2659
|
+
}
|
|
2660
|
+
function supportsDirectDeploymentVersion(backendVersion) {
|
|
2661
|
+
const cleanVersion = backendVersion.replace(/^v/, "").split("-")[0];
|
|
2662
|
+
const [major = 0, minor = 0, patch = 0] = cleanVersion.split(".").map(Number);
|
|
2663
|
+
const [minMajor, minMinor, minPatch] = DIRECT_DEPLOYMENT_MIN_VERSION.split(".").map(Number);
|
|
2664
|
+
if (major !== minMajor) return major > minMajor;
|
|
2665
|
+
if (minor !== minMinor) return minor > minMinor;
|
|
2666
|
+
return patch >= minPatch;
|
|
2667
|
+
}
|
|
2668
|
+
function shouldExcludeDeploymentPath(normalizedName) {
|
|
2669
|
+
const segments = normalizedName.split("/");
|
|
2670
|
+
if (segments.some((segment) => segment === ".env" || segment.startsWith(".env."))) {
|
|
2671
|
+
return true;
|
|
2672
|
+
}
|
|
2673
|
+
if (segments.some((segment) => EXCLUDED_DEPLOYMENT_SEGMENTS.has(segment))) {
|
|
2674
|
+
return true;
|
|
2675
|
+
}
|
|
2676
|
+
return normalizedName === ".DS_Store" || normalizedName.endsWith("/.DS_Store") || normalizedName.endsWith(".log");
|
|
2677
|
+
}
|
|
2678
|
+
function normalizeRelativePath(rootDirectory, absolutePath) {
|
|
2679
|
+
return relative(rootDirectory, absolutePath).split(sep).join("/").replace(/\\/g, "/");
|
|
2680
|
+
}
|
|
2681
|
+
async function hashFile(filePath) {
|
|
2682
|
+
const hash = createHash("sha1");
|
|
2683
|
+
let size = 0;
|
|
2684
|
+
for await (const chunk of createReadStream(filePath)) {
|
|
2685
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
2686
|
+
size += buffer.length;
|
|
2687
|
+
hash.update(buffer);
|
|
2688
|
+
}
|
|
2689
|
+
return { sha: hash.digest("hex"), size };
|
|
2690
|
+
}
|
|
2691
|
+
function parseCreateDeploymentResponse(obj) {
|
|
2692
|
+
const result = createDeploymentResponseSchema.safeParse(obj);
|
|
2693
|
+
if (!result.success) {
|
|
2694
|
+
throw new Error("Unexpected response format from deployments endpoint");
|
|
2695
|
+
}
|
|
2696
|
+
return result.data;
|
|
2697
|
+
}
|
|
2698
|
+
function parseCreateDirectDeploymentResponse(obj) {
|
|
2699
|
+
const result = createDirectDeploymentResponseSchema.safeParse(obj);
|
|
2700
|
+
if (!result.success) {
|
|
2701
|
+
throw new Error("Unexpected response format from direct deployments endpoint");
|
|
2702
|
+
}
|
|
2703
|
+
return result.data;
|
|
2704
|
+
}
|
|
2705
|
+
function parseCreateDeploymentManifestResponse(obj) {
|
|
2706
|
+
const result = createDeploymentManifestResponseSchema.safeParse(obj);
|
|
2707
|
+
if (!result.success) {
|
|
2708
|
+
throw new Error("Unexpected response format from deployment manifest endpoint");
|
|
2709
|
+
}
|
|
2710
|
+
return result.data;
|
|
2711
|
+
}
|
|
2712
|
+
async function collectDeploymentFiles(sourceDirectory) {
|
|
2713
|
+
const files = [];
|
|
2714
|
+
async function walk(currentDirectory) {
|
|
2715
|
+
const entries = await fs3.readdir(currentDirectory, { withFileTypes: true });
|
|
2716
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
2717
|
+
for (const entry of entries) {
|
|
2718
|
+
const absolutePath = join2(currentDirectory, entry.name);
|
|
2719
|
+
const normalizedPath = normalizeRelativePath(sourceDirectory, absolutePath);
|
|
2720
|
+
if (!normalizedPath || shouldExcludeDeploymentPath(normalizedPath)) {
|
|
2721
|
+
continue;
|
|
2722
|
+
}
|
|
2723
|
+
if (entry.isDirectory()) {
|
|
2724
|
+
await walk(absolutePath);
|
|
2725
|
+
continue;
|
|
2726
|
+
}
|
|
2727
|
+
if (!entry.isFile()) {
|
|
2728
|
+
continue;
|
|
2729
|
+
}
|
|
2730
|
+
const { sha, size } = await hashFile(absolutePath);
|
|
2731
|
+
files.push({
|
|
2732
|
+
absolutePath,
|
|
2733
|
+
path: normalizedPath,
|
|
2734
|
+
sha,
|
|
2735
|
+
size
|
|
2736
|
+
});
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
await walk(sourceDirectory);
|
|
2740
|
+
return files;
|
|
2741
|
+
}
|
|
2742
|
+
function buildStartBody(input) {
|
|
2743
|
+
const startBody = {};
|
|
2744
|
+
if (input.projectSettings) startBody.projectSettings = input.projectSettings;
|
|
2745
|
+
if (input.envVars) startBody.envVars = input.envVars;
|
|
2746
|
+
if (input.meta) startBody.meta = input.meta;
|
|
2747
|
+
return startBody;
|
|
2748
|
+
}
|
|
2749
|
+
async function createDirectDeploymentSession(API_BASE_URL, apiKey) {
|
|
2750
|
+
const response = await fetch6(`${API_BASE_URL}/api/deployments/direct`, {
|
|
2751
|
+
method: "POST",
|
|
2752
|
+
headers: {
|
|
2753
|
+
"x-api-key": apiKey,
|
|
2754
|
+
"Content-Type": "application/json"
|
|
2755
|
+
}
|
|
2756
|
+
});
|
|
2757
|
+
if (response.status === 404) {
|
|
2758
|
+
throw new DirectDeploymentUnsupportedError();
|
|
2759
|
+
}
|
|
2760
|
+
const result = await handleApiResponse(response);
|
|
2761
|
+
return parseCreateDirectDeploymentResponse(result);
|
|
2762
|
+
}
|
|
2763
|
+
async function createDeploymentManifest(API_BASE_URL, apiKey, deploymentId, files) {
|
|
2764
|
+
const response = await fetch6(`${API_BASE_URL}/api/deployments/${encodeURIComponent(deploymentId)}/manifest`, {
|
|
2765
|
+
method: "POST",
|
|
2766
|
+
headers: {
|
|
2767
|
+
"x-api-key": apiKey,
|
|
2768
|
+
"Content-Type": "application/json"
|
|
2769
|
+
},
|
|
2770
|
+
body: JSON.stringify({ files })
|
|
2771
|
+
});
|
|
2772
|
+
if (response.status === 404) {
|
|
2773
|
+
throw new DirectDeploymentUnsupportedError();
|
|
2774
|
+
}
|
|
2775
|
+
const result = await handleApiResponse(response);
|
|
2776
|
+
return parseCreateDeploymentManifestResponse(result);
|
|
2777
|
+
}
|
|
2778
|
+
async function uploadDeploymentFileContent(API_BASE_URL, apiKey, deploymentId, file, localFile) {
|
|
2779
|
+
const response = await fetch6(
|
|
2780
|
+
`${API_BASE_URL}/api/deployments/${encodeURIComponent(deploymentId)}/files/${encodeURIComponent(file.fileId)}/content`,
|
|
2781
|
+
{
|
|
2782
|
+
method: "PUT",
|
|
2783
|
+
headers: {
|
|
2784
|
+
"x-api-key": apiKey,
|
|
2785
|
+
"Content-Type": "application/octet-stream",
|
|
2786
|
+
"Content-Length": String(localFile.size)
|
|
2787
|
+
},
|
|
2788
|
+
body: createReadStream(localFile.absolutePath)
|
|
2789
|
+
}
|
|
2790
|
+
);
|
|
2791
|
+
if (response.status === 404) {
|
|
2792
|
+
throw new DirectDeploymentUnsupportedError();
|
|
2793
|
+
}
|
|
2794
|
+
await handleApiResponse(response);
|
|
2795
|
+
}
|
|
2796
|
+
async function startDeployment(API_BASE_URL, apiKey, deploymentId, startBody) {
|
|
2797
|
+
const response = await fetch6(`${API_BASE_URL}/api/deployments/${encodeURIComponent(deploymentId)}/start`, {
|
|
2798
|
+
method: "POST",
|
|
2799
|
+
headers: {
|
|
2800
|
+
"x-api-key": apiKey,
|
|
2801
|
+
"Content-Type": "application/json"
|
|
2802
|
+
},
|
|
2803
|
+
body: JSON.stringify(startBody)
|
|
2804
|
+
});
|
|
2805
|
+
return handleApiResponse(response);
|
|
2806
|
+
}
|
|
2807
|
+
async function deployDirect(API_BASE_URL, apiKey, sourceDirectory, startBody) {
|
|
2808
|
+
const files = await collectDeploymentFiles(sourceDirectory);
|
|
2809
|
+
if (files.length === 0) {
|
|
2810
|
+
throw new Error("No deployable files found in source directory after applying exclusions.");
|
|
2811
|
+
}
|
|
2812
|
+
const createResult = await createDirectDeploymentSession(API_BASE_URL, apiKey);
|
|
2813
|
+
const deploymentId = String(createResult.id);
|
|
2814
|
+
const manifest = await createDeploymentManifest(
|
|
2815
|
+
API_BASE_URL,
|
|
2816
|
+
apiKey,
|
|
2817
|
+
deploymentId,
|
|
2818
|
+
files.map(({ path, sha, size }) => ({ path, sha, size }))
|
|
2819
|
+
);
|
|
2820
|
+
const localFilesByPath = new Map(files.map((file) => [file.path, file]));
|
|
2821
|
+
for (const manifestFile of manifest.files) {
|
|
2822
|
+
const localFile = localFilesByPath.get(manifestFile.path);
|
|
2823
|
+
if (!localFile) {
|
|
2824
|
+
throw new Error(`Manifest response included unknown file path: ${manifestFile.path}`);
|
|
2825
|
+
}
|
|
2826
|
+
await uploadDeploymentFileContent(API_BASE_URL, apiKey, deploymentId, manifestFile, localFile);
|
|
2827
|
+
}
|
|
2828
|
+
const startResult = await startDeployment(API_BASE_URL, apiKey, deploymentId, startBody);
|
|
2829
|
+
return { deploymentId, fileCount: files.length, startResult };
|
|
2830
|
+
}
|
|
2831
|
+
function buildRemoteDirectUploadInstructions(API_BASE_URL, sourceDirectory, deploymentId) {
|
|
2832
|
+
const escapedDir = shellEsc(sourceDirectory);
|
|
2833
|
+
const apiBaseUrlJson = JSON.stringify(API_BASE_URL);
|
|
2834
|
+
const deploymentIdJson = JSON.stringify(deploymentId);
|
|
2835
|
+
return `Deployment prepared successfully using direct upload. Deployment ID: ${deploymentId}
|
|
2836
|
+
|
|
2837
|
+
Please execute the following command locally from a shell that has INSFORGE_API_KEY set, then call the \`start-deployment\` tool with the deployment ID printed by the script.
|
|
2838
|
+
|
|
2839
|
+
\`\`\`bash
|
|
2840
|
+
cd ${escapedDir}
|
|
2841
|
+
INSFORGE_API_KEY="\${INSFORGE_API_KEY:?Set INSFORGE_API_KEY to your InsForge API key}" node --input-type=module <<'NODE'
|
|
2842
|
+
const { createHash } = await import('node:crypto');
|
|
2843
|
+
const { createReadStream } = await import('node:fs');
|
|
2844
|
+
const fs = await import('node:fs/promises');
|
|
2845
|
+
const path = await import('node:path');
|
|
2846
|
+
|
|
2847
|
+
const API_BASE_URL = ${apiBaseUrlJson};
|
|
2848
|
+
const API_KEY = process.env.INSFORGE_API_KEY;
|
|
2849
|
+
const deploymentId = ${deploymentIdJson};
|
|
2850
|
+
const EXCLUDED_SEGMENTS = new Set(['node_modules', '.git', '.next', 'dist', 'build', '.insforge']);
|
|
2851
|
+
|
|
2852
|
+
function shouldExcludeDeploymentPath(normalizedName) {
|
|
2853
|
+
const segments = normalizedName.split('/');
|
|
2854
|
+
if (segments.some((segment) => segment === '.env' || segment.startsWith('.env.'))) return true;
|
|
2855
|
+
if (segments.some((segment) => EXCLUDED_SEGMENTS.has(segment))) return true;
|
|
2856
|
+
return normalizedName === '.DS_Store' || normalizedName.endsWith('/.DS_Store') || normalizedName.endsWith('.log');
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
async function readJsonResponse(response) {
|
|
2860
|
+
const text = await response.text();
|
|
2861
|
+
const data = text ? JSON.parse(text) : null;
|
|
2862
|
+
if (!response.ok) {
|
|
2863
|
+
throw new Error(data?.message || data?.error || \`Request failed with status \${response.status}\`);
|
|
2864
|
+
}
|
|
2865
|
+
return data;
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
async function api(pathname, init = {}) {
|
|
2869
|
+
const headers = {
|
|
2870
|
+
'x-api-key': API_KEY,
|
|
2871
|
+
...(init.headers || {}),
|
|
2872
|
+
};
|
|
2873
|
+
const response = await fetch(\`\${API_BASE_URL}\${pathname}\`, { ...init, headers });
|
|
2874
|
+
return readJsonResponse(response);
|
|
2875
|
+
}
|
|
2876
|
+
|
|
2877
|
+
async function hashFile(filePath) {
|
|
2878
|
+
const hash = createHash('sha1');
|
|
2879
|
+
let size = 0;
|
|
2880
|
+
for await (const chunk of createReadStream(filePath)) {
|
|
2881
|
+
size += chunk.length;
|
|
2882
|
+
hash.update(chunk);
|
|
2883
|
+
}
|
|
2884
|
+
return { sha: hash.digest('hex'), size };
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
async function collectFiles(rootDirectory) {
|
|
2888
|
+
const files = [];
|
|
2889
|
+
|
|
2890
|
+
async function walk(currentDirectory) {
|
|
2891
|
+
const entries = await fs.readdir(currentDirectory, { withFileTypes: true });
|
|
2892
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
2893
|
+
|
|
2894
|
+
for (const entry of entries) {
|
|
2895
|
+
const absolutePath = path.join(currentDirectory, entry.name);
|
|
2896
|
+
const normalizedPath = path.relative(rootDirectory, absolutePath).split(path.sep).join('/').replace(/\\\\/g, '/');
|
|
2897
|
+
|
|
2898
|
+
if (!normalizedPath || shouldExcludeDeploymentPath(normalizedPath)) continue;
|
|
2899
|
+
if (entry.isDirectory()) {
|
|
2900
|
+
await walk(absolutePath);
|
|
2901
|
+
continue;
|
|
2902
|
+
}
|
|
2903
|
+
if (!entry.isFile()) continue;
|
|
2904
|
+
|
|
2905
|
+
const { sha, size } = await hashFile(absolutePath);
|
|
2906
|
+
files.push({ absolutePath, path: normalizedPath, sha, size });
|
|
2907
|
+
}
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
await walk(rootDirectory);
|
|
2911
|
+
return files;
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
const rootDirectory = process.cwd();
|
|
2915
|
+
const localFiles = await collectFiles(rootDirectory);
|
|
2916
|
+
if (localFiles.length === 0) throw new Error('No deployable files found after applying exclusions.');
|
|
2917
|
+
|
|
2918
|
+
const manifest = await api(\`/api/deployments/\${encodeURIComponent(deploymentId)}/manifest\`, {
|
|
2919
|
+
method: 'POST',
|
|
2920
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2921
|
+
body: JSON.stringify({
|
|
2922
|
+
files: localFiles.map(({ path, sha, size }) => ({ path, sha, size })),
|
|
2923
|
+
}),
|
|
2924
|
+
});
|
|
2925
|
+
|
|
2926
|
+
const localFilesByPath = new Map(localFiles.map((file) => [file.path, file]));
|
|
2927
|
+
for (const remoteFile of manifest.files) {
|
|
2928
|
+
const localFile = localFilesByPath.get(remoteFile.path);
|
|
2929
|
+
if (!localFile) throw new Error(\`Manifest response included unknown path: \${remoteFile.path}\`);
|
|
2930
|
+
|
|
2931
|
+
const uploadResponse = await fetch(
|
|
2932
|
+
\`\${API_BASE_URL}/api/deployments/\${encodeURIComponent(deploymentId)}/files/\${encodeURIComponent(remoteFile.fileId)}/content\`,
|
|
2933
|
+
{
|
|
2934
|
+
method: 'PUT',
|
|
2935
|
+
headers: {
|
|
2936
|
+
'x-api-key': API_KEY,
|
|
2937
|
+
'Content-Type': 'application/octet-stream',
|
|
2938
|
+
'Content-Length': String(localFile.size),
|
|
2939
|
+
},
|
|
2940
|
+
body: createReadStream(localFile.absolutePath),
|
|
2941
|
+
duplex: 'half',
|
|
2942
|
+
}
|
|
2943
|
+
);
|
|
2944
|
+
await readJsonResponse(uploadResponse);
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
console.log(\`Deployment files uploaded. Deployment ID: \${deploymentId}\`);
|
|
2948
|
+
console.log(\`Uploaded \${localFiles.length} files through the direct deployment proxy.\`);
|
|
2949
|
+
NODE
|
|
2950
|
+
\`\`\`
|
|
2951
|
+
|
|
2952
|
+
After the script succeeds, call the \`start-deployment\` tool with the printed deployment ID.`;
|
|
2290
2953
|
}
|
|
2291
2954
|
function registerDeploymentTools(ctx) {
|
|
2292
|
-
const { API_BASE_URL, isRemote, registerTool, withUsageTracking, getApiKey, addBackgroundContext } = ctx;
|
|
2955
|
+
const { API_BASE_URL, backendVersion, isRemote, registerTool, withUsageTracking, getApiKey, addBackgroundContext } = ctx;
|
|
2956
|
+
const supportsDirectDeployment = supportsDirectDeploymentVersion(backendVersion);
|
|
2293
2957
|
registerTool(
|
|
2294
2958
|
"get-container-logs",
|
|
2295
2959
|
"Get latest logs from a specific container/service. Use this to help debug problems with your app.",
|
|
@@ -2329,14 +2993,13 @@ function registerDeploymentTools(ctx) {
|
|
|
2329
2993
|
if (isRemote) {
|
|
2330
2994
|
registerTool(
|
|
2331
2995
|
"create-deployment",
|
|
2332
|
-
"Prepare a deployment
|
|
2996
|
+
"Prepare a deployment upload. For backends v2.0.5 and newer, returns direct file upload commands. Older backends use the legacy zip upload flow. After uploading, call the start-deployment tool to trigger the build.",
|
|
2333
2997
|
{
|
|
2334
2998
|
sourceDirectory: z29.string().describe('Absolute path to the source directory containing files to deploy (e.g., /Users/name/project). Do not use relative paths like "."')
|
|
2335
2999
|
},
|
|
2336
3000
|
withUsageTracking("create-deployment", async ({ sourceDirectory }) => {
|
|
2337
3001
|
try {
|
|
2338
|
-
|
|
2339
|
-
if (!isAbsolutePath) {
|
|
3002
|
+
if (!isAbsoluteSourcePath(sourceDirectory)) {
|
|
2340
3003
|
return {
|
|
2341
3004
|
content: [{
|
|
2342
3005
|
type: "text",
|
|
@@ -2345,6 +3008,21 @@ function registerDeploymentTools(ctx) {
|
|
|
2345
3008
|
isError: true
|
|
2346
3009
|
};
|
|
2347
3010
|
}
|
|
3011
|
+
if (supportsDirectDeployment) {
|
|
3012
|
+
try {
|
|
3013
|
+
const createResult2 = await createDirectDeploymentSession(API_BASE_URL, getApiKey());
|
|
3014
|
+
return {
|
|
3015
|
+
content: [{
|
|
3016
|
+
type: "text",
|
|
3017
|
+
text: buildRemoteDirectUploadInstructions(API_BASE_URL, sourceDirectory, String(createResult2.id))
|
|
3018
|
+
}]
|
|
3019
|
+
};
|
|
3020
|
+
} catch (error) {
|
|
3021
|
+
if (!(error instanceof DirectDeploymentUnsupportedError)) {
|
|
3022
|
+
throw error;
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
2348
3026
|
const createResponse = await fetch6(`${API_BASE_URL}/api/deployments`, {
|
|
2349
3027
|
method: "POST",
|
|
2350
3028
|
headers: {
|
|
@@ -2352,10 +3030,7 @@ function registerDeploymentTools(ctx) {
|
|
|
2352
3030
|
"Content-Type": "application/json"
|
|
2353
3031
|
}
|
|
2354
3032
|
});
|
|
2355
|
-
const createResult = await handleApiResponse(createResponse);
|
|
2356
|
-
if (!isCreateDeploymentResponse(createResult)) {
|
|
2357
|
-
throw new Error("Unexpected response format from deployments endpoint");
|
|
2358
|
-
}
|
|
3033
|
+
const createResult = parseCreateDeploymentResponse(await handleApiResponse(createResponse));
|
|
2359
3034
|
const { id: deploymentId, uploadUrl, uploadFields } = createResult;
|
|
2360
3035
|
const esc = shellEsc;
|
|
2361
3036
|
const curlFields = Object.entries(uploadFields).map(([key, value]) => `-F ${esc(`${key}=${value}`)}`).join(" \\\n ");
|
|
@@ -2367,7 +3042,7 @@ Please execute the following commands locally, then call the \`start-deployment\
|
|
|
2367
3042
|
|
|
2368
3043
|
## Step 1: Zip the source directory
|
|
2369
3044
|
\`\`\`bash
|
|
2370
|
-
cd ${escapedDir} && zip -r ${tmpZip} . -x "node_modules/*" ".git/*" ".next/*" ".env" "
|
|
3045
|
+
cd ${escapedDir} && zip -r ${tmpZip} . -x "node_modules/*" ".git/*" ".next/*" ".env*" "dist/*" "build/*" ".insforge/*" ".DS_Store" "*.log"
|
|
2371
3046
|
\`\`\`
|
|
2372
3047
|
|
|
2373
3048
|
## Step 2: Upload the zip file
|
|
@@ -2436,15 +3111,14 @@ Run each step in order. If any step fails, do not proceed to the next step.`;
|
|
|
2436
3111
|
} else {
|
|
2437
3112
|
registerTool(
|
|
2438
3113
|
"create-deployment",
|
|
2439
|
-
"Deploy source code from a directory.
|
|
3114
|
+
"Deploy source code from a directory. Uses direct file upload for backends v2.0.5 and newer, with legacy zip upload fallback for older projects.",
|
|
2440
3115
|
{
|
|
2441
3116
|
sourceDirectory: z29.string().describe('Absolute path to the source directory containing files to deploy (e.g., /Users/name/project or C:\\Users\\name\\project). Do not use relative paths like "."'),
|
|
2442
3117
|
...startDeploymentRequestSchema.shape
|
|
2443
3118
|
},
|
|
2444
3119
|
withUsageTracking("create-deployment", async ({ sourceDirectory, projectSettings, envVars, meta }) => {
|
|
2445
3120
|
try {
|
|
2446
|
-
|
|
2447
|
-
if (!isAbsolutePath) {
|
|
3121
|
+
if (!isAbsoluteSourcePath(sourceDirectory)) {
|
|
2448
3122
|
return {
|
|
2449
3123
|
content: [{
|
|
2450
3124
|
type: "text",
|
|
@@ -2474,6 +3148,26 @@ Run each step in order. If any step fails, do not proceed to the next step.`;
|
|
|
2474
3148
|
};
|
|
2475
3149
|
}
|
|
2476
3150
|
const resolvedSourceDir = sourceDirectory;
|
|
3151
|
+
const startBody = buildStartBody({ projectSettings, envVars, meta });
|
|
3152
|
+
if (supportsDirectDeployment) {
|
|
3153
|
+
try {
|
|
3154
|
+
const { fileCount, startResult: startResult2 } = await deployDirect(API_BASE_URL, getApiKey(), resolvedSourceDir, startBody);
|
|
3155
|
+
return await addBackgroundContext({
|
|
3156
|
+
content: [{
|
|
3157
|
+
type: "text",
|
|
3158
|
+
text: formatSuccessMessage("Deployment started", startResult2) + `
|
|
3159
|
+
|
|
3160
|
+
Uploaded ${fileCount} files through the direct deployment proxy.
|
|
3161
|
+
|
|
3162
|
+
Note: You can check deployment status by querying the system.deployments table.`
|
|
3163
|
+
}]
|
|
3164
|
+
});
|
|
3165
|
+
} catch (error) {
|
|
3166
|
+
if (!(error instanceof DirectDeploymentUnsupportedError)) {
|
|
3167
|
+
throw error;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
}
|
|
2477
3171
|
const createResponse = await fetch6(`${API_BASE_URL}/api/deployments`, {
|
|
2478
3172
|
method: "POST",
|
|
2479
3173
|
headers: {
|
|
@@ -2481,10 +3175,7 @@ Run each step in order. If any step fails, do not proceed to the next step.`;
|
|
|
2481
3175
|
"Content-Type": "application/json"
|
|
2482
3176
|
}
|
|
2483
3177
|
});
|
|
2484
|
-
const createResult = await handleApiResponse(createResponse);
|
|
2485
|
-
if (!isCreateDeploymentResponse(createResult)) {
|
|
2486
|
-
throw new Error("Unexpected response format from deployments endpoint");
|
|
2487
|
-
}
|
|
3178
|
+
const createResult = parseCreateDeploymentResponse(await handleApiResponse(createResponse));
|
|
2488
3179
|
const { id: deploymentId, uploadUrl, uploadFields } = createResult;
|
|
2489
3180
|
const tmpZipPath = join2(tmpdir2(), `insforge-deploy-${deploymentId}.zip`);
|
|
2490
3181
|
try {
|
|
@@ -2494,15 +3185,9 @@ Run each step in order. If any step fails, do not proceed to the next step.`;
|
|
|
2494
3185
|
output.on("close", resolve);
|
|
2495
3186
|
output.on("error", reject);
|
|
2496
3187
|
archive.on("error", reject);
|
|
2497
|
-
const excludePatterns = ["node_modules", ".git", ".next", ".env", ".env.local", "dist", "build", ".DS_Store"];
|
|
2498
3188
|
archive.directory(resolvedSourceDir, false, (entry) => {
|
|
2499
3189
|
const normalizedName = entry.name.replace(/\\/g, "/");
|
|
2500
|
-
|
|
2501
|
-
if (normalizedName.startsWith(pattern + "/") || normalizedName === pattern || normalizedName.endsWith("/" + pattern) || normalizedName.includes("/" + pattern + "/")) {
|
|
2502
|
-
return false;
|
|
2503
|
-
}
|
|
2504
|
-
}
|
|
2505
|
-
if (normalizedName.endsWith(".log")) return false;
|
|
3190
|
+
if (shouldExcludeDeploymentPath(normalizedName)) return false;
|
|
2506
3191
|
return entry;
|
|
2507
3192
|
});
|
|
2508
3193
|
archive.pipe(output);
|
|
@@ -2530,19 +3215,7 @@ Run each step in order. If any step fails, do not proceed to the next step.`;
|
|
|
2530
3215
|
} finally {
|
|
2531
3216
|
await fs3.rm(tmpZipPath, { force: true }).catch(() => void 0);
|
|
2532
3217
|
}
|
|
2533
|
-
const
|
|
2534
|
-
if (projectSettings) startBody.projectSettings = projectSettings;
|
|
2535
|
-
if (envVars) startBody.envVars = envVars;
|
|
2536
|
-
if (meta) startBody.meta = meta;
|
|
2537
|
-
const startResponse = await fetch6(`${API_BASE_URL}/api/deployments/${encodeURIComponent(deploymentId)}/start`, {
|
|
2538
|
-
method: "POST",
|
|
2539
|
-
headers: {
|
|
2540
|
-
"x-api-key": getApiKey(),
|
|
2541
|
-
"Content-Type": "application/json"
|
|
2542
|
-
},
|
|
2543
|
-
body: JSON.stringify(startBody)
|
|
2544
|
-
});
|
|
2545
|
-
const startResult = await handleApiResponse(startResponse);
|
|
3218
|
+
const startResult = await startDeployment(API_BASE_URL, getApiKey(), deploymentId, startBody);
|
|
2546
3219
|
return await addBackgroundContext({
|
|
2547
3220
|
content: [{
|
|
2548
3221
|
type: "text",
|
|
@@ -2628,7 +3301,11 @@ async function registerInsforgeTools(server, config = {}) {
|
|
|
2628
3301
|
const GLOBAL_API_KEY = config.apiKey || process.env.API_KEY || "";
|
|
2629
3302
|
const API_BASE_URL = config.apiBaseUrl || process.env.API_BASE_URL || "http://localhost:7130";
|
|
2630
3303
|
const isRemote = config.mode === "remote";
|
|
2631
|
-
const usageTracker = new UsageTracker(API_BASE_URL, GLOBAL_API_KEY
|
|
3304
|
+
const usageTracker = new UsageTracker(API_BASE_URL, GLOBAL_API_KEY, {
|
|
3305
|
+
projectId: config.projectId,
|
|
3306
|
+
accessToken: config.accessToken,
|
|
3307
|
+
isRemote
|
|
3308
|
+
});
|
|
2632
3309
|
let backendVersion;
|
|
2633
3310
|
try {
|
|
2634
3311
|
backendVersion = await fetchBackendVersion(API_BASE_URL);
|
|
@@ -2711,6 +3388,7 @@ ${result.content}`
|
|
|
2711
3388
|
};
|
|
2712
3389
|
const ctx = {
|
|
2713
3390
|
API_BASE_URL,
|
|
3391
|
+
backendVersion,
|
|
2714
3392
|
isRemote,
|
|
2715
3393
|
registerTool,
|
|
2716
3394
|
withUsageTracking,
|
package/dist/http-server.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
registerInsforgeTools
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3HMBKVW5.js";
|
|
5
5
|
|
|
6
6
|
// src/http/server.ts
|
|
7
7
|
import "dotenv/config";
|
|
@@ -98,7 +98,9 @@ var SessionManager = class {
|
|
|
98
98
|
const toolsConfig = await registerInsforgeTools(server, {
|
|
99
99
|
apiKey: sessionData.apiKey,
|
|
100
100
|
apiBaseUrl: sessionData.apiBaseUrl,
|
|
101
|
-
mode: "remote"
|
|
101
|
+
mode: "remote",
|
|
102
|
+
projectId: sessionData.projectId,
|
|
103
|
+
accessToken: sessionData.oauthTokenHash
|
|
102
104
|
});
|
|
103
105
|
await server.connect(transport);
|
|
104
106
|
const fullSessionData = {
|
|
@@ -186,7 +188,9 @@ var SessionManager = class {
|
|
|
186
188
|
await registerInsforgeTools(server, {
|
|
187
189
|
apiKey: sessionData.apiKey,
|
|
188
190
|
apiBaseUrl: sessionData.apiBaseUrl,
|
|
189
|
-
mode: "remote"
|
|
191
|
+
mode: "remote",
|
|
192
|
+
projectId: sessionData.projectId,
|
|
193
|
+
accessToken: sessionData.oauthTokenHash
|
|
190
194
|
});
|
|
191
195
|
await server.connect(transport);
|
|
192
196
|
this.runtimeSessions.set(sessionId, { server, transport, transportType: "streamable" });
|
|
@@ -210,7 +214,9 @@ var SessionManager = class {
|
|
|
210
214
|
const toolsConfig = await registerInsforgeTools(server, {
|
|
211
215
|
apiKey: sessionData.apiKey,
|
|
212
216
|
apiBaseUrl: sessionData.apiBaseUrl,
|
|
213
|
-
mode: "remote"
|
|
217
|
+
mode: "remote",
|
|
218
|
+
projectId: sessionData.projectId,
|
|
219
|
+
accessToken: sessionData.oauthTokenHash
|
|
214
220
|
});
|
|
215
221
|
await server.connect(transport);
|
|
216
222
|
const fullSessionData = {
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@insforge/mcp",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.10-dev.0",
|
|
4
4
|
"description": "MCP (Model Context Protocol) server for Insforge backend-as-a-service",
|
|
5
5
|
"mcpName": "io.github.InsForge/insforge-mcp",
|
|
6
6
|
"type": "module",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"server.json"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@insforge/shared-schemas": "1.1.
|
|
48
|
+
"@insforge/shared-schemas": "1.1.48",
|
|
49
49
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
50
50
|
"archiver": "^7.0.1",
|
|
51
51
|
"commander": "^14.0.0",
|
|
@@ -61,6 +61,9 @@
|
|
|
61
61
|
"brace-expansion": "^5.0.5",
|
|
62
62
|
"glob": "^10.5.0",
|
|
63
63
|
"minimatch": "^9.0.7",
|
|
64
|
+
"@hono/node-server": "^1.19.13",
|
|
65
|
+
"hono": "^4.12.12",
|
|
66
|
+
"lodash": "^4.18.0",
|
|
64
67
|
"rollup": "^4.59.0"
|
|
65
68
|
},
|
|
66
69
|
"devDependencies": {
|
|
@@ -78,7 +81,7 @@
|
|
|
78
81
|
"tsx": "^4.7.0",
|
|
79
82
|
"typescript": "^5.3.3",
|
|
80
83
|
"typescript-eslint": "^8.57.1",
|
|
81
|
-
"vite": "^8.0.
|
|
84
|
+
"vite": "^8.0.5",
|
|
82
85
|
"vitest": "^4.1.0"
|
|
83
86
|
}
|
|
84
87
|
}
|