@hasna/connectors 1.3.25 → 1.3.26
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/bin/index.js +606 -170
- package/bin/mcp.js +633 -197
- package/bin/serve.js +654 -222
- package/dist/core/connectors/gmail.d.ts +5 -0
- package/dist/index.js +595 -163
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -1909,7 +1909,7 @@ var package_default;
|
|
|
1909
1909
|
var init_package = __esm(() => {
|
|
1910
1910
|
package_default = {
|
|
1911
1911
|
name: "@hasna/connectors",
|
|
1912
|
-
version: "1.3.
|
|
1912
|
+
version: "1.3.26",
|
|
1913
1913
|
description: "Open source connector library - Install API connectors with a single command",
|
|
1914
1914
|
type: "module",
|
|
1915
1915
|
bin: {
|
|
@@ -2052,7 +2052,7 @@ var CONNECTOR_NAME_RE, OPERATION_NAME_RE;
|
|
|
2052
2052
|
var init_connector = __esm(() => {
|
|
2053
2053
|
init_errors();
|
|
2054
2054
|
CONNECTOR_NAME_RE = /^[a-z0-9-]+$/;
|
|
2055
|
-
OPERATION_NAME_RE = /^[
|
|
2055
|
+
OPERATION_NAME_RE = /^[A-Za-z0-9:._-]+$/;
|
|
2056
2056
|
});
|
|
2057
2057
|
|
|
2058
2058
|
// src/core/registry.ts
|
|
@@ -6913,38 +6913,100 @@ Commands:
|
|
|
6913
6913
|
});
|
|
6914
6914
|
});
|
|
6915
6915
|
|
|
6916
|
-
// src/core/connectors/
|
|
6916
|
+
// src/core/connectors/gmail.ts
|
|
6917
6917
|
import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
6918
6918
|
import { homedir } from "os";
|
|
6919
6919
|
import { basename, join as join2 } from "path";
|
|
6920
|
-
async function
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6920
|
+
async function modifyMessage(profile, messageId, addLabelIds, removeLabelIds) {
|
|
6921
|
+
return requestJson(profile, `/users/me/messages/${encodeURIComponent(messageId)}/modify`, {}, {
|
|
6922
|
+
method: "POST",
|
|
6923
|
+
body: {
|
|
6924
|
+
addLabelIds: addLabelIds ?? [],
|
|
6925
|
+
removeLabelIds: removeLabelIds ?? []
|
|
6926
|
+
}
|
|
6927
|
+
});
|
|
6924
6928
|
}
|
|
6925
|
-
async function
|
|
6926
|
-
|
|
6929
|
+
async function replyToMessage(profile, messageId, input) {
|
|
6930
|
+
const original = await requestJson(profile, `/users/me/messages/${encodeURIComponent(messageId)}`, { format: "full" });
|
|
6931
|
+
const headers = headersToObject(original.payload?.headers ?? []);
|
|
6932
|
+
const subject = normalizeReplySubject(headers.Subject ?? headers.subject ?? "");
|
|
6933
|
+
const to = headers.From ?? headers.from ?? "";
|
|
6934
|
+
const messageIdHeader = headers["Message-ID"] ?? headers["Message-Id"] ?? headers["message-id"] ?? "";
|
|
6935
|
+
const references = [headers.References ?? headers.references, messageIdHeader].filter(Boolean).join(" ");
|
|
6936
|
+
const raw = buildRawEmail({
|
|
6937
|
+
to,
|
|
6938
|
+
cc: normalizeStringArray(input.cc),
|
|
6939
|
+
bcc: normalizeStringArray(input.bcc),
|
|
6940
|
+
subject,
|
|
6941
|
+
body: input.body,
|
|
6942
|
+
isHtml: Boolean(input.html ?? input.isHtml),
|
|
6943
|
+
inReplyTo: messageIdHeader,
|
|
6944
|
+
references
|
|
6945
|
+
});
|
|
6946
|
+
return requestJson(profile, "/users/me/messages/send", {}, {
|
|
6947
|
+
method: "POST",
|
|
6948
|
+
body: {
|
|
6949
|
+
raw: Buffer.from(raw).toString("base64url"),
|
|
6950
|
+
threadId: original.threadId
|
|
6951
|
+
}
|
|
6952
|
+
});
|
|
6927
6953
|
}
|
|
6928
|
-
async function
|
|
6954
|
+
async function downloadAttachments(profile, input) {
|
|
6955
|
+
const messageId = getMessageId(input);
|
|
6956
|
+
const outputDir = input.dir ?? input.outputDir ?? join2(configDirs()[0], "attachments", messageId);
|
|
6957
|
+
mkdirSync(outputDir, { recursive: true });
|
|
6958
|
+
const attachments = input.attachmentId && input.filename ? [{
|
|
6959
|
+
attachmentId: input.attachmentId,
|
|
6960
|
+
filename: input.filename,
|
|
6961
|
+
mimeType: input.mimeType ?? "application/octet-stream",
|
|
6962
|
+
size: 0
|
|
6963
|
+
}] : collectAttachments((await requestJson(profile, `/users/me/messages/${encodeURIComponent(messageId)}`, { format: "full" })).payload);
|
|
6964
|
+
const downloaded = [];
|
|
6965
|
+
for (const attachment of attachments) {
|
|
6966
|
+
const data = await requestJson(profile, `/users/me/messages/${encodeURIComponent(messageId)}/attachments/${encodeURIComponent(attachment.attachmentId)}`, {});
|
|
6967
|
+
const filename = safeFilename(attachment.filename);
|
|
6968
|
+
const path = join2(outputDir, filename);
|
|
6969
|
+
const buffer = Buffer.from(data.data, "base64url");
|
|
6970
|
+
writeFileSync(path, buffer);
|
|
6971
|
+
downloaded.push({
|
|
6972
|
+
filename,
|
|
6973
|
+
path,
|
|
6974
|
+
size: buffer.length,
|
|
6975
|
+
mimeType: attachment.mimeType
|
|
6976
|
+
});
|
|
6977
|
+
}
|
|
6978
|
+
return downloaded;
|
|
6979
|
+
}
|
|
6980
|
+
async function requestJson(profile, path, params, options = {}) {
|
|
6929
6981
|
const token = await getValidAccessToken(profile);
|
|
6930
|
-
const url = new URL(`${
|
|
6982
|
+
const url = new URL(`${GMAIL_API_BASE}${path}`);
|
|
6931
6983
|
for (const [key, value] of Object.entries(params)) {
|
|
6932
6984
|
if (value !== undefined && value !== null && value !== "")
|
|
6933
|
-
url.searchParams.
|
|
6985
|
+
url.searchParams.append(key, String(value));
|
|
6934
6986
|
}
|
|
6935
|
-
const response = await fetch(url, {
|
|
6987
|
+
const response = await fetch(url, {
|
|
6988
|
+
method: options.method ?? "GET",
|
|
6989
|
+
headers: {
|
|
6990
|
+
Authorization: `Bearer ${token}`,
|
|
6991
|
+
Accept: "application/json",
|
|
6992
|
+
...options.body ? { "Content-Type": "application/json" } : {}
|
|
6993
|
+
},
|
|
6994
|
+
body: options.body ? JSON.stringify(options.body) : undefined
|
|
6995
|
+
});
|
|
6996
|
+
const text = await response.text();
|
|
6997
|
+
const data = text ? JSON.parse(text) : {};
|
|
6936
6998
|
if (!response.ok) {
|
|
6937
|
-
const
|
|
6938
|
-
throw new Error(`
|
|
6999
|
+
const error = data;
|
|
7000
|
+
throw new Error(`Gmail request failed (${response.status}): ${error.error?.message ?? response.statusText}`);
|
|
6939
7001
|
}
|
|
6940
|
-
return
|
|
7002
|
+
return data;
|
|
6941
7003
|
}
|
|
6942
7004
|
async function getValidAccessToken(profile) {
|
|
6943
|
-
if (process.env.
|
|
6944
|
-
return process.env.
|
|
7005
|
+
if (process.env.GMAIL_ACCESS_TOKEN)
|
|
7006
|
+
return process.env.GMAIL_ACCESS_TOKEN;
|
|
6945
7007
|
const tokens = loadTokens(profile);
|
|
6946
7008
|
if (!tokens?.accessToken && !tokens?.refreshToken) {
|
|
6947
|
-
throw new Error(`
|
|
7009
|
+
throw new Error(`Gmail profile "${profile}" is not authenticated. Run: connectors auth gmail`);
|
|
6948
7010
|
}
|
|
6949
7011
|
if (tokens.accessToken && (!tokens.expiresAt || Date.now() < tokens.expiresAt - REFRESH_BUFFER_MS))
|
|
6950
7012
|
return tokens.accessToken;
|
|
@@ -6955,9 +7017,9 @@ async function getValidAccessToken(profile) {
|
|
|
6955
7017
|
async function refreshAccessToken(profile, currentTokens) {
|
|
6956
7018
|
const credentials = loadCredentials(profile);
|
|
6957
7019
|
if (!credentials.clientId || !credentials.clientSecret)
|
|
6958
|
-
throw new Error("
|
|
7020
|
+
throw new Error("Gmail OAuth credentials are not configured. Run: connectors auth gmail");
|
|
6959
7021
|
if (!currentTokens.refreshToken)
|
|
6960
|
-
throw new Error(`
|
|
7022
|
+
throw new Error(`Gmail profile "${profile}" has no refresh token. Run: connectors auth gmail`);
|
|
6961
7023
|
const response = await fetch(TOKEN_URL, {
|
|
6962
7024
|
method: "POST",
|
|
6963
7025
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
@@ -6970,7 +7032,7 @@ async function refreshAccessToken(profile, currentTokens) {
|
|
|
6970
7032
|
});
|
|
6971
7033
|
const data = await response.json().catch(() => ({}));
|
|
6972
7034
|
if (!response.ok || !data.access_token)
|
|
6973
|
-
throw new Error(`
|
|
7035
|
+
throw new Error(`Gmail token refresh failed: ${data.error_description || data.error || response.statusText}`);
|
|
6974
7036
|
const tokens = {
|
|
6975
7037
|
accessToken: data.access_token,
|
|
6976
7038
|
refreshToken: currentTokens.refreshToken,
|
|
@@ -6997,8 +7059,8 @@ function listProfiles() {
|
|
|
6997
7059
|
return Array.from(profiles).sort((a, b) => a.localeCompare(b));
|
|
6998
7060
|
}
|
|
6999
7061
|
function loadCredentials(profile) {
|
|
7000
|
-
const envClientId = process.env.GOOGLE_CLIENT_ID;
|
|
7001
|
-
const envClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
7062
|
+
const envClientId = process.env.GMAIL_CLIENT_ID ?? process.env.GOOGLE_CLIENT_ID;
|
|
7063
|
+
const envClientSecret = process.env.GMAIL_CLIENT_SECRET ?? process.env.GOOGLE_CLIENT_SECRET;
|
|
7002
7064
|
if (envClientId && envClientSecret)
|
|
7003
7065
|
return { clientId: envClientId, clientSecret: envClientSecret };
|
|
7004
7066
|
for (const baseDir of configDirs()) {
|
|
@@ -7029,11 +7091,11 @@ function saveTokens(profile, tokens) {
|
|
|
7029
7091
|
writeFileSync(join2(profileDir, "tokens.json"), JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
7030
7092
|
}
|
|
7031
7093
|
function configDirs() {
|
|
7032
|
-
const explicit = process.env.
|
|
7094
|
+
const explicit = process.env.HASNA_GMAIL_CONNECTOR_DIR ?? process.env.GMAIL_CONNECTOR_DIR;
|
|
7033
7095
|
if (explicit)
|
|
7034
7096
|
return [explicit];
|
|
7035
7097
|
const baseDir = process.env.HASNA_CONNECTORS_DIR ?? join2(homedir(), ".hasna", "connectors");
|
|
7036
|
-
return [join2(baseDir, "connect-
|
|
7098
|
+
return [join2(baseDir, "connect-gmail"), join2(baseDir, "gmail")];
|
|
7037
7099
|
}
|
|
7038
7100
|
function readJson(path) {
|
|
7039
7101
|
if (!existsSync2(path))
|
|
@@ -7044,6 +7106,378 @@ function readJson(path) {
|
|
|
7044
7106
|
return null;
|
|
7045
7107
|
}
|
|
7046
7108
|
}
|
|
7109
|
+
function getMessageId(input) {
|
|
7110
|
+
const id = input.messageId ?? (input.args?.[0] != null ? String(input.args[0]) : undefined);
|
|
7111
|
+
if (!id)
|
|
7112
|
+
throw new Error("Gmail messageId is required");
|
|
7113
|
+
return id;
|
|
7114
|
+
}
|
|
7115
|
+
function headersToObject(headers) {
|
|
7116
|
+
const out = {};
|
|
7117
|
+
for (const header of headers)
|
|
7118
|
+
out[header.name] = header.value;
|
|
7119
|
+
return out;
|
|
7120
|
+
}
|
|
7121
|
+
function extractBody(message, preferHtml = false) {
|
|
7122
|
+
if (!message.payload)
|
|
7123
|
+
return "";
|
|
7124
|
+
const targetType = preferHtml ? "text/html" : "text/plain";
|
|
7125
|
+
const parts = [];
|
|
7126
|
+
collectTextParts(message.payload, parts);
|
|
7127
|
+
return parts.find((part) => part.mimeType === targetType)?.data ?? parts.find((part) => part.mimeType.startsWith("text/"))?.data ?? "";
|
|
7128
|
+
}
|
|
7129
|
+
function collectTextParts(part, results) {
|
|
7130
|
+
const mimeType = (part.mimeType ?? "").split(";")[0].trim().toLowerCase();
|
|
7131
|
+
if (part.body?.data && mimeType.startsWith("text/")) {
|
|
7132
|
+
results.push({ mimeType, data: Buffer.from(part.body.data, "base64url").toString("utf8") });
|
|
7133
|
+
}
|
|
7134
|
+
for (const child of part.parts ?? [])
|
|
7135
|
+
collectTextParts(child, results);
|
|
7136
|
+
}
|
|
7137
|
+
function collectAttachments(part, attachments = []) {
|
|
7138
|
+
if (!part)
|
|
7139
|
+
return attachments;
|
|
7140
|
+
if (part.body?.attachmentId && part.filename) {
|
|
7141
|
+
attachments.push({
|
|
7142
|
+
attachmentId: part.body.attachmentId,
|
|
7143
|
+
filename: part.filename,
|
|
7144
|
+
mimeType: part.mimeType ?? "application/octet-stream",
|
|
7145
|
+
size: part.body.size ?? 0,
|
|
7146
|
+
partId: part.partId
|
|
7147
|
+
});
|
|
7148
|
+
}
|
|
7149
|
+
for (const child of part.parts ?? [])
|
|
7150
|
+
collectAttachments(child, attachments);
|
|
7151
|
+
return attachments;
|
|
7152
|
+
}
|
|
7153
|
+
function normalizeStringArray(value) {
|
|
7154
|
+
if (!value)
|
|
7155
|
+
return [];
|
|
7156
|
+
return Array.isArray(value) ? value : value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
7157
|
+
}
|
|
7158
|
+
function normalizeReplySubject(subject) {
|
|
7159
|
+
return subject.toLowerCase().startsWith("re:") ? subject : `Re: ${subject}`;
|
|
7160
|
+
}
|
|
7161
|
+
function buildRawEmail(input) {
|
|
7162
|
+
const headers = [
|
|
7163
|
+
`To: ${input.to}`,
|
|
7164
|
+
input.cc.length ? `Cc: ${input.cc.join(", ")}` : "",
|
|
7165
|
+
input.bcc.length ? `Bcc: ${input.bcc.join(", ")}` : "",
|
|
7166
|
+
`Subject: ${input.subject}`,
|
|
7167
|
+
input.inReplyTo ? `In-Reply-To: ${input.inReplyTo}` : "",
|
|
7168
|
+
input.references ? `References: ${input.references}` : "",
|
|
7169
|
+
"MIME-Version: 1.0",
|
|
7170
|
+
`Content-Type: ${input.isHtml ? "text/html" : "text/plain"}; charset=UTF-8`
|
|
7171
|
+
].filter(Boolean);
|
|
7172
|
+
return `${headers.join(`\r
|
|
7173
|
+
`)}\r
|
|
7174
|
+
\r
|
|
7175
|
+
${input.body}`;
|
|
7176
|
+
}
|
|
7177
|
+
function safeFilename(filename) {
|
|
7178
|
+
return basename(filename.replace(/[\u00A0\u2000-\u200B\u202F\u205F\u3000]/g, " ")).replace(/[\/\\]/g, "_");
|
|
7179
|
+
}
|
|
7180
|
+
var GMAIL_API_BASE = "https://gmail.googleapis.com/gmail/v1", TOKEN_URL = "https://oauth2.googleapis.com/token", REFRESH_BUFFER_MS, listMessagesSchema, messageIdSchema, readMessageSchema, attachmentListSchema, attachmentDownloadSchema, historyListSchema, replySchema, gmailConnector;
|
|
7181
|
+
var init_gmail = __esm(() => {
|
|
7182
|
+
init_zod();
|
|
7183
|
+
init_connector();
|
|
7184
|
+
REFRESH_BUFFER_MS = 5 * 60 * 1000;
|
|
7185
|
+
listMessagesSchema = exports_external.object({
|
|
7186
|
+
max: exports_external.coerce.number().int().positive().max(500).optional(),
|
|
7187
|
+
maxResults: exports_external.coerce.number().int().positive().max(500).optional(),
|
|
7188
|
+
pageToken: exports_external.string().optional(),
|
|
7189
|
+
query: exports_external.string().optional(),
|
|
7190
|
+
q: exports_external.string().optional(),
|
|
7191
|
+
label: exports_external.string().optional(),
|
|
7192
|
+
labelIds: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional(),
|
|
7193
|
+
includeSpamTrash: exports_external.boolean().optional()
|
|
7194
|
+
});
|
|
7195
|
+
messageIdSchema = exports_external.object({
|
|
7196
|
+
args: exports_external.array(exports_external.union([exports_external.string(), exports_external.number(), exports_external.boolean()])).optional(),
|
|
7197
|
+
messageId: exports_external.string().optional()
|
|
7198
|
+
});
|
|
7199
|
+
readMessageSchema = messageIdSchema.extend({
|
|
7200
|
+
body: exports_external.boolean().optional(),
|
|
7201
|
+
html: exports_external.boolean().optional(),
|
|
7202
|
+
format: exports_external.enum(["full", "metadata", "minimal", "raw"]).optional()
|
|
7203
|
+
});
|
|
7204
|
+
attachmentListSchema = messageIdSchema;
|
|
7205
|
+
attachmentDownloadSchema = messageIdSchema.extend({
|
|
7206
|
+
attachmentId: exports_external.string().optional(),
|
|
7207
|
+
filename: exports_external.string().optional(),
|
|
7208
|
+
mimeType: exports_external.string().optional(),
|
|
7209
|
+
dir: exports_external.string().optional(),
|
|
7210
|
+
outputDir: exports_external.string().optional()
|
|
7211
|
+
});
|
|
7212
|
+
historyListSchema = exports_external.object({
|
|
7213
|
+
startHistoryId: exports_external.string(),
|
|
7214
|
+
historyTypes: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional(),
|
|
7215
|
+
labelId: exports_external.string().optional(),
|
|
7216
|
+
maxResults: exports_external.coerce.number().int().positive().max(500).optional(),
|
|
7217
|
+
pageToken: exports_external.string().optional()
|
|
7218
|
+
});
|
|
7219
|
+
replySchema = messageIdSchema.extend({
|
|
7220
|
+
body: exports_external.string(),
|
|
7221
|
+
html: exports_external.boolean().optional(),
|
|
7222
|
+
isHtml: exports_external.boolean().optional(),
|
|
7223
|
+
cc: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional(),
|
|
7224
|
+
bcc: exports_external.union([exports_external.string(), exports_external.array(exports_external.string())]).optional()
|
|
7225
|
+
});
|
|
7226
|
+
gmailConnector = defineConnector({
|
|
7227
|
+
meta: {
|
|
7228
|
+
name: "gmail",
|
|
7229
|
+
displayName: "Gmail",
|
|
7230
|
+
description: "Profile-aware Gmail mailbox operations for sync, labels, attachments, history, and replies.",
|
|
7231
|
+
category: "communication",
|
|
7232
|
+
tags: ["google", "gmail", "email", "mailbox"]
|
|
7233
|
+
},
|
|
7234
|
+
auth: {
|
|
7235
|
+
type: "oauth2",
|
|
7236
|
+
supportsProfiles: true,
|
|
7237
|
+
fields: [
|
|
7238
|
+
{ key: "clientId", env: "GMAIL_CLIENT_ID", label: "OAuth client ID" },
|
|
7239
|
+
{ key: "clientSecret", env: "GMAIL_CLIENT_SECRET", label: "OAuth client secret", secret: true }
|
|
7240
|
+
]
|
|
7241
|
+
},
|
|
7242
|
+
createContext: ({ profile }) => ({ profile: profile || "default" }),
|
|
7243
|
+
operations: {
|
|
7244
|
+
"profiles.list": {
|
|
7245
|
+
summary: "List configured Gmail profiles.",
|
|
7246
|
+
execute: () => ({ profiles: listProfiles() })
|
|
7247
|
+
},
|
|
7248
|
+
"profile.get": {
|
|
7249
|
+
summary: "Get the authenticated Gmail profile.",
|
|
7250
|
+
execute: async ({ context }) => requestJson(context.profile, "/users/me/profile", {})
|
|
7251
|
+
},
|
|
7252
|
+
"messages.list": {
|
|
7253
|
+
summary: "List Gmail messages.",
|
|
7254
|
+
inputSchema: listMessagesSchema,
|
|
7255
|
+
execute: async ({ context }, input) => {
|
|
7256
|
+
const labelIds = normalizeStringArray(input.labelIds ?? input.label);
|
|
7257
|
+
return requestJson(context.profile, "/users/me/messages", {
|
|
7258
|
+
maxResults: input.maxResults ?? input.max ?? 50,
|
|
7259
|
+
pageToken: input.pageToken,
|
|
7260
|
+
q: input.q ?? input.query,
|
|
7261
|
+
labelIds: labelIds.length > 0 ? labelIds.join(",") : undefined,
|
|
7262
|
+
includeSpamTrash: input.includeSpamTrash
|
|
7263
|
+
});
|
|
7264
|
+
}
|
|
7265
|
+
},
|
|
7266
|
+
"messages.read": {
|
|
7267
|
+
summary: "Read a Gmail message with optional extracted body.",
|
|
7268
|
+
inputSchema: readMessageSchema,
|
|
7269
|
+
execute: async ({ context }, input) => {
|
|
7270
|
+
const messageId = getMessageId(input);
|
|
7271
|
+
const message = await requestJson(context.profile, `/users/me/messages/${encodeURIComponent(messageId)}`, { format: input.format ?? "full" });
|
|
7272
|
+
const headers = headersToObject(message.payload?.headers ?? []);
|
|
7273
|
+
return {
|
|
7274
|
+
...message,
|
|
7275
|
+
from: headers.From ?? headers.from ?? "",
|
|
7276
|
+
to: headers.To ?? headers.to ?? "",
|
|
7277
|
+
cc: headers.Cc ?? headers.cc ?? "",
|
|
7278
|
+
subject: headers.Subject ?? headers.subject ?? "",
|
|
7279
|
+
date: headers.Date ?? headers.date ?? "",
|
|
7280
|
+
body: input.body ? extractBody(message, Boolean(input.html)) : undefined,
|
|
7281
|
+
size: message.sizeEstimate
|
|
7282
|
+
};
|
|
7283
|
+
}
|
|
7284
|
+
},
|
|
7285
|
+
"messages.getRaw": {
|
|
7286
|
+
summary: "Read raw base64url Gmail message content.",
|
|
7287
|
+
inputSchema: messageIdSchema,
|
|
7288
|
+
execute: async ({ context }, input) => {
|
|
7289
|
+
const messageId = getMessageId(input);
|
|
7290
|
+
return requestJson(context.profile, `/users/me/messages/${encodeURIComponent(messageId)}`, { format: "raw" });
|
|
7291
|
+
}
|
|
7292
|
+
},
|
|
7293
|
+
"messages.mark-read": {
|
|
7294
|
+
summary: "Mark a message as read.",
|
|
7295
|
+
inputSchema: messageIdSchema,
|
|
7296
|
+
execute: async ({ context }, input) => modifyMessage(context.profile, getMessageId(input), undefined, ["UNREAD"])
|
|
7297
|
+
},
|
|
7298
|
+
"messages.mark-unread": {
|
|
7299
|
+
summary: "Mark a message as unread.",
|
|
7300
|
+
inputSchema: messageIdSchema,
|
|
7301
|
+
execute: async ({ context }, input) => modifyMessage(context.profile, getMessageId(input), ["UNREAD"], undefined)
|
|
7302
|
+
},
|
|
7303
|
+
"messages.archive": {
|
|
7304
|
+
summary: "Archive a message by removing the INBOX label.",
|
|
7305
|
+
inputSchema: messageIdSchema,
|
|
7306
|
+
execute: async ({ context }, input) => modifyMessage(context.profile, getMessageId(input), undefined, ["INBOX"])
|
|
7307
|
+
},
|
|
7308
|
+
"messages.star": {
|
|
7309
|
+
summary: "Star a message.",
|
|
7310
|
+
inputSchema: messageIdSchema,
|
|
7311
|
+
execute: async ({ context }, input) => modifyMessage(context.profile, getMessageId(input), ["STARRED"], undefined)
|
|
7312
|
+
},
|
|
7313
|
+
"messages.reply": {
|
|
7314
|
+
summary: "Reply to a Gmail message in the same thread.",
|
|
7315
|
+
inputSchema: replySchema,
|
|
7316
|
+
execute: async ({ context }, input) => replyToMessage(context.profile, getMessageId(input), input)
|
|
7317
|
+
},
|
|
7318
|
+
"attachments.list": {
|
|
7319
|
+
summary: "List Gmail message attachments.",
|
|
7320
|
+
inputSchema: attachmentListSchema,
|
|
7321
|
+
execute: async ({ context }, input) => {
|
|
7322
|
+
const message = await requestJson(context.profile, `/users/me/messages/${encodeURIComponent(getMessageId(input))}`, { format: "full" });
|
|
7323
|
+
return collectAttachments(message.payload);
|
|
7324
|
+
}
|
|
7325
|
+
},
|
|
7326
|
+
"attachments.download": {
|
|
7327
|
+
summary: "Download one or all Gmail message attachments to disk.",
|
|
7328
|
+
inputSchema: attachmentDownloadSchema,
|
|
7329
|
+
execute: async ({ context }, input) => downloadAttachments(context.profile, input)
|
|
7330
|
+
},
|
|
7331
|
+
"labels.list": {
|
|
7332
|
+
summary: "List Gmail labels.",
|
|
7333
|
+
execute: async ({ context }) => requestJson(context.profile, "/users/me/labels", {})
|
|
7334
|
+
},
|
|
7335
|
+
"history.list": {
|
|
7336
|
+
summary: "List Gmail mailbox history from a history id.",
|
|
7337
|
+
inputSchema: historyListSchema,
|
|
7338
|
+
execute: async ({ context }, input) => requestJson(context.profile, "/users/me/history", {
|
|
7339
|
+
startHistoryId: input.startHistoryId,
|
|
7340
|
+
historyTypes: normalizeStringArray(input.historyTypes).join(",") || undefined,
|
|
7341
|
+
labelId: input.labelId,
|
|
7342
|
+
maxResults: input.maxResults,
|
|
7343
|
+
pageToken: input.pageToken
|
|
7344
|
+
})
|
|
7345
|
+
}
|
|
7346
|
+
}
|
|
7347
|
+
});
|
|
7348
|
+
});
|
|
7349
|
+
|
|
7350
|
+
// src/core/connectors/googledrive.ts
|
|
7351
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
7352
|
+
import { homedir as homedir2 } from "os";
|
|
7353
|
+
import { basename as basename2, join as join3 } from "path";
|
|
7354
|
+
async function requestJson2(profile, path, params) {
|
|
7355
|
+
const response = await request(profile, path, params);
|
|
7356
|
+
const text = await response.text();
|
|
7357
|
+
return text ? JSON.parse(text) : {};
|
|
7358
|
+
}
|
|
7359
|
+
async function requestBinary(profile, path, params) {
|
|
7360
|
+
return (await request(profile, path, params)).arrayBuffer();
|
|
7361
|
+
}
|
|
7362
|
+
async function request(profile, path, params) {
|
|
7363
|
+
const token = await getValidAccessToken2(profile);
|
|
7364
|
+
const url = new URL(`${DRIVE_API_BASE}${path}`);
|
|
7365
|
+
for (const [key, value] of Object.entries(params)) {
|
|
7366
|
+
if (value !== undefined && value !== null && value !== "")
|
|
7367
|
+
url.searchParams.set(key, String(value));
|
|
7368
|
+
}
|
|
7369
|
+
const response = await fetch(url, { headers: { Authorization: `Bearer ${token}`, Accept: "application/json" } });
|
|
7370
|
+
if (!response.ok) {
|
|
7371
|
+
const body = await response.text().catch(() => "");
|
|
7372
|
+
throw new Error(`Google Drive request failed (${response.status}): ${extractGoogleError(body) || response.statusText}`);
|
|
7373
|
+
}
|
|
7374
|
+
return response;
|
|
7375
|
+
}
|
|
7376
|
+
async function getValidAccessToken2(profile) {
|
|
7377
|
+
if (process.env.GOOGLE_ACCESS_TOKEN)
|
|
7378
|
+
return process.env.GOOGLE_ACCESS_TOKEN;
|
|
7379
|
+
const tokens = loadTokens2(profile);
|
|
7380
|
+
if (!tokens?.accessToken && !tokens?.refreshToken) {
|
|
7381
|
+
throw new Error(`Google Drive profile "${profile}" is not authenticated. Run: connectors auth googledrive`);
|
|
7382
|
+
}
|
|
7383
|
+
if (tokens.accessToken && (!tokens.expiresAt || Date.now() < tokens.expiresAt - REFRESH_BUFFER_MS2))
|
|
7384
|
+
return tokens.accessToken;
|
|
7385
|
+
if (!tokens.refreshToken)
|
|
7386
|
+
return tokens.accessToken ?? "";
|
|
7387
|
+
return (await refreshAccessToken2(profile, tokens)).accessToken ?? "";
|
|
7388
|
+
}
|
|
7389
|
+
async function refreshAccessToken2(profile, currentTokens) {
|
|
7390
|
+
const credentials = loadCredentials2(profile);
|
|
7391
|
+
if (!credentials.clientId || !credentials.clientSecret)
|
|
7392
|
+
throw new Error("Google Drive OAuth credentials are not configured. Run: connectors auth googledrive");
|
|
7393
|
+
if (!currentTokens.refreshToken)
|
|
7394
|
+
throw new Error(`Google Drive profile "${profile}" has no refresh token. Run: connectors auth googledrive`);
|
|
7395
|
+
const response = await fetch(TOKEN_URL2, {
|
|
7396
|
+
method: "POST",
|
|
7397
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
7398
|
+
body: new URLSearchParams({
|
|
7399
|
+
client_id: credentials.clientId,
|
|
7400
|
+
client_secret: credentials.clientSecret,
|
|
7401
|
+
refresh_token: currentTokens.refreshToken,
|
|
7402
|
+
grant_type: "refresh_token"
|
|
7403
|
+
})
|
|
7404
|
+
});
|
|
7405
|
+
const data = await response.json().catch(() => ({}));
|
|
7406
|
+
if (!response.ok || !data.access_token)
|
|
7407
|
+
throw new Error(`Google Drive token refresh failed: ${data.error_description || data.error || response.statusText}`);
|
|
7408
|
+
const tokens = {
|
|
7409
|
+
accessToken: data.access_token,
|
|
7410
|
+
refreshToken: currentTokens.refreshToken,
|
|
7411
|
+
expiresAt: Date.now() + (data.expires_in ?? 3600) * 1000,
|
|
7412
|
+
tokenType: data.token_type ?? currentTokens.tokenType,
|
|
7413
|
+
scope: data.scope ?? currentTokens.scope
|
|
7414
|
+
};
|
|
7415
|
+
saveTokens2(profile, tokens);
|
|
7416
|
+
return tokens;
|
|
7417
|
+
}
|
|
7418
|
+
function listProfiles2() {
|
|
7419
|
+
const profiles = new Set;
|
|
7420
|
+
for (const baseDir of configDirs2()) {
|
|
7421
|
+
const profilesDir = join3(baseDir, "profiles");
|
|
7422
|
+
if (!existsSync3(profilesDir))
|
|
7423
|
+
continue;
|
|
7424
|
+
for (const entry of readdirSync2(profilesDir, { withFileTypes: true })) {
|
|
7425
|
+
if (entry.isDirectory())
|
|
7426
|
+
profiles.add(entry.name);
|
|
7427
|
+
if (entry.isFile() && entry.name.endsWith(".json"))
|
|
7428
|
+
profiles.add(basename2(entry.name, ".json"));
|
|
7429
|
+
}
|
|
7430
|
+
}
|
|
7431
|
+
return Array.from(profiles).sort((a, b) => a.localeCompare(b));
|
|
7432
|
+
}
|
|
7433
|
+
function loadCredentials2(profile) {
|
|
7434
|
+
const envClientId = process.env.GOOGLE_CLIENT_ID;
|
|
7435
|
+
const envClientSecret = process.env.GOOGLE_CLIENT_SECRET;
|
|
7436
|
+
if (envClientId && envClientSecret)
|
|
7437
|
+
return { clientId: envClientId, clientSecret: envClientSecret };
|
|
7438
|
+
for (const baseDir of configDirs2()) {
|
|
7439
|
+
const credentials = {
|
|
7440
|
+
...readJson2(join3(baseDir, "credentials.json")),
|
|
7441
|
+
...readJson2(join3(baseDir, "profiles", profile, "config.json"))
|
|
7442
|
+
};
|
|
7443
|
+
if (credentials.clientId || credentials.clientSecret)
|
|
7444
|
+
return credentials;
|
|
7445
|
+
}
|
|
7446
|
+
return {};
|
|
7447
|
+
}
|
|
7448
|
+
function loadTokens2(profile) {
|
|
7449
|
+
for (const baseDir of configDirs2()) {
|
|
7450
|
+
const fromProfile = readJson2(join3(baseDir, "profiles", profile, "tokens.json"));
|
|
7451
|
+
if (fromProfile)
|
|
7452
|
+
return fromProfile;
|
|
7453
|
+
const flat = readJson2(join3(baseDir, "profiles", `${profile}.json`));
|
|
7454
|
+
if (flat)
|
|
7455
|
+
return flat.tokens ?? (flat.accessToken || flat.refreshToken ? flat : null);
|
|
7456
|
+
}
|
|
7457
|
+
return null;
|
|
7458
|
+
}
|
|
7459
|
+
function saveTokens2(profile, tokens) {
|
|
7460
|
+
const baseDir = configDirs2().find((dir) => existsSync3(dir)) ?? configDirs2()[0];
|
|
7461
|
+
const profileDir = join3(baseDir, "profiles", profile);
|
|
7462
|
+
mkdirSync2(profileDir, { recursive: true });
|
|
7463
|
+
writeFileSync2(join3(profileDir, "tokens.json"), JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
7464
|
+
}
|
|
7465
|
+
function configDirs2() {
|
|
7466
|
+
const explicit = process.env.HASNA_GOOGLE_DRIVE_CONNECTOR_DIR ?? process.env.GOOGLE_DRIVE_CONNECTOR_DIR;
|
|
7467
|
+
if (explicit)
|
|
7468
|
+
return [explicit];
|
|
7469
|
+
const baseDir = process.env.HASNA_CONNECTORS_DIR ?? join3(homedir2(), ".hasna", "connectors");
|
|
7470
|
+
return [join3(baseDir, "connect-googledrive"), join3(baseDir, "googledrive")];
|
|
7471
|
+
}
|
|
7472
|
+
function readJson2(path) {
|
|
7473
|
+
if (!existsSync3(path))
|
|
7474
|
+
return null;
|
|
7475
|
+
try {
|
|
7476
|
+
return JSON.parse(readFileSync2(path, "utf8"));
|
|
7477
|
+
} catch {
|
|
7478
|
+
return null;
|
|
7479
|
+
}
|
|
7480
|
+
}
|
|
7047
7481
|
function defaultExportMimeType(googleMimeType) {
|
|
7048
7482
|
if (googleMimeType.endsWith(".document"))
|
|
7049
7483
|
return DEFAULT_EXPORT_FORMATS.document;
|
|
@@ -7068,11 +7502,11 @@ function extractGoogleError(body) {
|
|
|
7068
7502
|
return body;
|
|
7069
7503
|
}
|
|
7070
7504
|
}
|
|
7071
|
-
var DRIVE_API_BASE = "https://www.googleapis.com/drive/v3",
|
|
7505
|
+
var DRIVE_API_BASE = "https://www.googleapis.com/drive/v3", TOKEN_URL2 = "https://oauth2.googleapis.com/token", REFRESH_BUFFER_MS2, DEFAULT_FILE_FIELDS, DEFAULT_EXPORT_FORMATS, EXPORT_EXTENSIONS, listFilesSchema, listDrivesSchema, fileIdSchema, downloadSchema, googleDriveConnector;
|
|
7072
7506
|
var init_googledrive = __esm(() => {
|
|
7073
7507
|
init_zod();
|
|
7074
7508
|
init_connector();
|
|
7075
|
-
|
|
7509
|
+
REFRESH_BUFFER_MS2 = 5 * 60 * 1000;
|
|
7076
7510
|
DEFAULT_FILE_FIELDS = [
|
|
7077
7511
|
"id",
|
|
7078
7512
|
"name",
|
|
@@ -7153,12 +7587,12 @@ var init_googledrive = __esm(() => {
|
|
|
7153
7587
|
operations: {
|
|
7154
7588
|
"profiles.list": {
|
|
7155
7589
|
summary: "List configured Google Drive profiles.",
|
|
7156
|
-
execute: () => ({ profiles:
|
|
7590
|
+
execute: () => ({ profiles: listProfiles2() })
|
|
7157
7591
|
},
|
|
7158
7592
|
"files.list": {
|
|
7159
7593
|
summary: "List Google Drive files.",
|
|
7160
7594
|
inputSchema: listFilesSchema,
|
|
7161
|
-
execute: async ({ context }, input) =>
|
|
7595
|
+
execute: async ({ context }, input) => requestJson2(context.profile, "/files", {
|
|
7162
7596
|
pageSize: input.pageSize ?? 1000,
|
|
7163
7597
|
pageToken: input.pageToken,
|
|
7164
7598
|
q: input.q,
|
|
@@ -7173,7 +7607,7 @@ var init_googledrive = __esm(() => {
|
|
|
7173
7607
|
"files.get": {
|
|
7174
7608
|
summary: "Get Google Drive file metadata.",
|
|
7175
7609
|
inputSchema: fileIdSchema,
|
|
7176
|
-
execute: async ({ context }, input) =>
|
|
7610
|
+
execute: async ({ context }, input) => requestJson2(context.profile, `/files/${encodeURIComponent(input.fileId)}`, {
|
|
7177
7611
|
fields: input.fields ?? DEFAULT_FILE_FIELDS,
|
|
7178
7612
|
supportsAllDrives: true
|
|
7179
7613
|
})
|
|
@@ -7182,7 +7616,7 @@ var init_googledrive = __esm(() => {
|
|
|
7182
7616
|
summary: "Download or export a Google Drive file as base64 content.",
|
|
7183
7617
|
inputSchema: downloadSchema,
|
|
7184
7618
|
execute: async ({ context }, input) => {
|
|
7185
|
-
const file = input.file ?? await
|
|
7619
|
+
const file = input.file ?? await requestJson2(context.profile, `/files/${encodeURIComponent(input.fileId)}`, { fields: DEFAULT_FILE_FIELDS, supportsAllDrives: true });
|
|
7186
7620
|
const exportMimeType = file.mimeType.startsWith("application/vnd.google-apps.") ? input.exportMimeType ?? defaultExportMimeType(file.mimeType) : undefined;
|
|
7187
7621
|
const data = await requestBinary(context.profile, exportMimeType ? `/files/${encodeURIComponent(file.id)}/export` : `/files/${encodeURIComponent(file.id)}`, exportMimeType ? { mimeType: exportMimeType, supportsAllDrives: true } : { alt: "media", supportsAllDrives: true });
|
|
7188
7622
|
const mimeType = exportMimeType ?? file.mimeType ?? "application/octet-stream";
|
|
@@ -7196,7 +7630,7 @@ var init_googledrive = __esm(() => {
|
|
|
7196
7630
|
"drives.list": {
|
|
7197
7631
|
summary: "List Google shared drives.",
|
|
7198
7632
|
inputSchema: listDrivesSchema,
|
|
7199
|
-
execute: async ({ context }, input) =>
|
|
7633
|
+
execute: async ({ context }, input) => requestJson2(context.profile, "/drives", {
|
|
7200
7634
|
pageSize: input.pageSize ?? 100,
|
|
7201
7635
|
pageToken: input.pageToken,
|
|
7202
7636
|
q: input.q
|
|
@@ -7279,27 +7713,27 @@ __export(exports_dist, {
|
|
|
7279
7713
|
import { createRequire } from "module";
|
|
7280
7714
|
import { Database } from "bun:sqlite";
|
|
7281
7715
|
import {
|
|
7282
|
-
existsSync as
|
|
7283
|
-
mkdirSync as
|
|
7284
|
-
readdirSync as
|
|
7716
|
+
existsSync as existsSync4,
|
|
7717
|
+
mkdirSync as mkdirSync3,
|
|
7718
|
+
readdirSync as readdirSync3,
|
|
7285
7719
|
copyFileSync
|
|
7286
7720
|
} from "fs";
|
|
7287
|
-
import { homedir as
|
|
7288
|
-
import { join as
|
|
7289
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as
|
|
7721
|
+
import { homedir as homedir3 } from "os";
|
|
7722
|
+
import { join as join4, relative } from "path";
|
|
7723
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync22, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
7290
7724
|
import { homedir as homedir22 } from "os";
|
|
7291
7725
|
import { join as join22 } from "path";
|
|
7292
7726
|
import { readdirSync as readdirSync22, existsSync as existsSync32 } from "fs";
|
|
7293
7727
|
import { join as join32 } from "path";
|
|
7294
|
-
import { homedir as
|
|
7728
|
+
import { homedir as homedir32 } from "os";
|
|
7295
7729
|
import { hostname } from "os";
|
|
7296
|
-
import { existsSync as
|
|
7730
|
+
import { existsSync as existsSync42, readFileSync as readFileSync22 } from "fs";
|
|
7297
7731
|
import { homedir as homedir4 } from "os";
|
|
7298
|
-
import { join as
|
|
7299
|
-
import { existsSync as existsSync5, readdirSync as
|
|
7732
|
+
import { join as join42 } from "path";
|
|
7733
|
+
import { existsSync as existsSync5, readdirSync as readdirSync32 } from "fs";
|
|
7300
7734
|
import { join as join5 } from "path";
|
|
7301
7735
|
import { join as join6, dirname as dirname2 } from "path";
|
|
7302
|
-
import { existsSync as existsSync6, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as
|
|
7736
|
+
import { existsSync as existsSync6, writeFileSync as writeFileSync22, unlinkSync, mkdirSync as mkdirSync32 } from "fs";
|
|
7303
7737
|
import { homedir as homedir5, platform } from "os";
|
|
7304
7738
|
function __accessProp2(key) {
|
|
7305
7739
|
return this[key];
|
|
@@ -8182,33 +8616,33 @@ function custom2(check, _params = {}, fatal) {
|
|
|
8182
8616
|
return ZodAny2.create();
|
|
8183
8617
|
}
|
|
8184
8618
|
function getDataDir(serviceName) {
|
|
8185
|
-
const dir =
|
|
8186
|
-
|
|
8619
|
+
const dir = join4(HASNA_DIR, serviceName);
|
|
8620
|
+
mkdirSync3(dir, { recursive: true });
|
|
8187
8621
|
return dir;
|
|
8188
8622
|
}
|
|
8189
8623
|
function getDbPath(serviceName) {
|
|
8190
8624
|
const dir = getDataDir(serviceName);
|
|
8191
|
-
return
|
|
8625
|
+
return join4(dir, `${serviceName}.db`);
|
|
8192
8626
|
}
|
|
8193
8627
|
function migrateDotfile(serviceName) {
|
|
8194
|
-
const legacyDir =
|
|
8195
|
-
const newDir =
|
|
8196
|
-
if (!
|
|
8628
|
+
const legacyDir = join4(homedir3(), `.${serviceName}`);
|
|
8629
|
+
const newDir = join4(HASNA_DIR, serviceName);
|
|
8630
|
+
if (!existsSync4(legacyDir))
|
|
8197
8631
|
return [];
|
|
8198
|
-
if (
|
|
8632
|
+
if (existsSync4(newDir))
|
|
8199
8633
|
return [];
|
|
8200
|
-
|
|
8634
|
+
mkdirSync3(newDir, { recursive: true });
|
|
8201
8635
|
const migrated = [];
|
|
8202
8636
|
copyDirRecursive(legacyDir, newDir, legacyDir, migrated);
|
|
8203
8637
|
return migrated;
|
|
8204
8638
|
}
|
|
8205
8639
|
function copyDirRecursive(src, dest, root, migrated) {
|
|
8206
|
-
const entries =
|
|
8640
|
+
const entries = readdirSync3(src, { withFileTypes: true });
|
|
8207
8641
|
for (const entry of entries) {
|
|
8208
|
-
const srcPath =
|
|
8209
|
-
const destPath =
|
|
8642
|
+
const srcPath = join4(src, entry.name);
|
|
8643
|
+
const destPath = join4(dest, entry.name);
|
|
8210
8644
|
if (entry.isDirectory()) {
|
|
8211
|
-
|
|
8645
|
+
mkdirSync3(destPath, { recursive: true });
|
|
8212
8646
|
copyDirRecursive(srcPath, destPath, root, migrated);
|
|
8213
8647
|
} else {
|
|
8214
8648
|
copyFileSync(srcPath, destPath);
|
|
@@ -8217,10 +8651,10 @@ function copyDirRecursive(src, dest, root, migrated) {
|
|
|
8217
8651
|
}
|
|
8218
8652
|
}
|
|
8219
8653
|
function hasLegacyDotfile(serviceName) {
|
|
8220
|
-
return
|
|
8654
|
+
return existsSync4(join4(homedir3(), `.${serviceName}`));
|
|
8221
8655
|
}
|
|
8222
8656
|
function getHasnaDir() {
|
|
8223
|
-
|
|
8657
|
+
mkdirSync3(HASNA_DIR, { recursive: true });
|
|
8224
8658
|
return HASNA_DIR;
|
|
8225
8659
|
}
|
|
8226
8660
|
function getConfigDir() {
|
|
@@ -8234,7 +8668,7 @@ function getCloudConfig() {
|
|
|
8234
8668
|
return CloudConfigSchema.parse({});
|
|
8235
8669
|
}
|
|
8236
8670
|
try {
|
|
8237
|
-
const raw =
|
|
8671
|
+
const raw = readFileSync3(CONFIG_PATH, "utf-8");
|
|
8238
8672
|
return CloudConfigSchema.parse(JSON.parse(raw));
|
|
8239
8673
|
} catch {
|
|
8240
8674
|
return CloudConfigSchema.parse({});
|
|
@@ -8242,7 +8676,7 @@ function getCloudConfig() {
|
|
|
8242
8676
|
}
|
|
8243
8677
|
function saveCloudConfig(config) {
|
|
8244
8678
|
mkdirSync22(CONFIG_DIR, { recursive: true });
|
|
8245
|
-
|
|
8679
|
+
writeFileSync3(CONFIG_PATH, JSON.stringify(config, null, 2) + `
|
|
8246
8680
|
`, "utf-8");
|
|
8247
8681
|
}
|
|
8248
8682
|
function getConnectionString(dbName) {
|
|
@@ -8272,7 +8706,7 @@ function isSyncExcludedTable(table) {
|
|
|
8272
8706
|
return SYNC_EXCLUDED_TABLE_PATTERNS.some((p) => p.test(table));
|
|
8273
8707
|
}
|
|
8274
8708
|
function discoverServices() {
|
|
8275
|
-
const dataDir = join32(
|
|
8709
|
+
const dataDir = join32(homedir32(), ".hasna");
|
|
8276
8710
|
if (!existsSync32(dataDir))
|
|
8277
8711
|
return [];
|
|
8278
8712
|
try {
|
|
@@ -8294,7 +8728,7 @@ function discoverSyncableServices() {
|
|
|
8294
8728
|
return local.filter((s) => pgSet.has(s));
|
|
8295
8729
|
}
|
|
8296
8730
|
function getServiceDbPath(service) {
|
|
8297
|
-
const dataDir = join32(
|
|
8731
|
+
const dataDir = join32(homedir32(), ".hasna", service);
|
|
8298
8732
|
if (!existsSync32(dataDir))
|
|
8299
8733
|
return null;
|
|
8300
8734
|
const candidates = [
|
|
@@ -9230,7 +9664,7 @@ function resetAllSyncMeta(db) {
|
|
|
9230
9664
|
}
|
|
9231
9665
|
function getAutoSyncConfig() {
|
|
9232
9666
|
try {
|
|
9233
|
-
if (!
|
|
9667
|
+
if (!existsSync42(AUTO_SYNC_CONFIG_PATH)) {
|
|
9234
9668
|
return { ...DEFAULT_AUTO_SYNC_CONFIG };
|
|
9235
9669
|
}
|
|
9236
9670
|
const raw = JSON.parse(readFileSync22(AUTO_SYNC_CONFIG_PATH, "utf-8"));
|
|
@@ -9348,7 +9782,7 @@ function discoverSyncableServices2() {
|
|
|
9348
9782
|
const hasnaDir = getHasnaDir();
|
|
9349
9783
|
const services = [];
|
|
9350
9784
|
try {
|
|
9351
|
-
const entries =
|
|
9785
|
+
const entries = readdirSync32(hasnaDir, { withFileTypes: true });
|
|
9352
9786
|
for (const entry of entries) {
|
|
9353
9787
|
if (!entry.isDirectory())
|
|
9354
9788
|
continue;
|
|
@@ -9518,7 +9952,7 @@ function createLaunchdPlist(intervalMinutes) {
|
|
|
9518
9952
|
async function registerLaunchd(intervalMinutes) {
|
|
9519
9953
|
const plistPath = getLaunchdPlistPath();
|
|
9520
9954
|
const plistDir = dirname2(plistPath);
|
|
9521
|
-
|
|
9955
|
+
mkdirSync32(plistDir, { recursive: true });
|
|
9522
9956
|
try {
|
|
9523
9957
|
await Bun.spawn(["launchctl", "unload", plistPath]).exited;
|
|
9524
9958
|
} catch {}
|
|
@@ -9569,7 +10003,7 @@ WantedBy=timers.target
|
|
|
9569
10003
|
}
|
|
9570
10004
|
async function registerSystemd(intervalMinutes) {
|
|
9571
10005
|
const dir = getSystemdDir();
|
|
9572
|
-
|
|
10006
|
+
mkdirSync32(dir, { recursive: true });
|
|
9573
10007
|
writeFileSync22(join6(dir, `${SERVICE_NAME}.service`), createSystemdService());
|
|
9574
10008
|
writeFileSync22(join6(dir, `${SERVICE_NAME}.timer`), createSystemdTimer(intervalMinutes));
|
|
9575
10009
|
await Bun.spawn(["systemctl", "--user", "daemon-reload"]).exited;
|
|
@@ -9594,7 +10028,7 @@ async function registerSyncSchedule(intervalMinutes) {
|
|
|
9594
10028
|
if (intervalMinutes <= 0) {
|
|
9595
10029
|
throw new Error("Interval must be a positive number of minutes.");
|
|
9596
10030
|
}
|
|
9597
|
-
|
|
10031
|
+
mkdirSync32(CONFIG_DIR2, { recursive: true });
|
|
9598
10032
|
if (platform() === "darwin") {
|
|
9599
10033
|
await registerLaunchd(intervalMinutes);
|
|
9600
10034
|
} else {
|
|
@@ -18168,7 +18602,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
18168
18602
|
init_external2();
|
|
18169
18603
|
});
|
|
18170
18604
|
init_dotfile = __esm2(() => {
|
|
18171
|
-
HASNA_DIR =
|
|
18605
|
+
HASNA_DIR = join4(homedir3(), ".hasna");
|
|
18172
18606
|
});
|
|
18173
18607
|
exports_config = {};
|
|
18174
18608
|
__export2(exports_config, {
|
|
@@ -18264,7 +18698,7 @@ See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode de
|
|
|
18264
18698
|
init_adapter();
|
|
18265
18699
|
init_config();
|
|
18266
18700
|
init_discover();
|
|
18267
|
-
AUTO_SYNC_CONFIG_PATH =
|
|
18701
|
+
AUTO_SYNC_CONFIG_PATH = join42(homedir4(), ".hasna", "cloud", "config.json");
|
|
18268
18702
|
DEFAULT_AUTO_SYNC_CONFIG = {
|
|
18269
18703
|
auto_sync_on_start: true,
|
|
18270
18704
|
auto_sync_on_stop: true
|
|
@@ -18476,12 +18910,12 @@ var init_database = __esm(() => {
|
|
|
18476
18910
|
// src/core/connectors/imessage.ts
|
|
18477
18911
|
import {
|
|
18478
18912
|
existsSync as existsSync9,
|
|
18479
|
-
mkdirSync as
|
|
18480
|
-
readFileSync as
|
|
18481
|
-
readdirSync as
|
|
18913
|
+
mkdirSync as mkdirSync5,
|
|
18914
|
+
readFileSync as readFileSync4,
|
|
18915
|
+
readdirSync as readdirSync5,
|
|
18482
18916
|
rmSync,
|
|
18483
18917
|
statSync as statSync2,
|
|
18484
|
-
writeFileSync as
|
|
18918
|
+
writeFileSync as writeFileSync4
|
|
18485
18919
|
} from "fs";
|
|
18486
18920
|
import { join as join9 } from "path";
|
|
18487
18921
|
function buildRootHelp(specs) {
|
|
@@ -18539,15 +18973,15 @@ function getCurrentProfile() {
|
|
|
18539
18973
|
return "default";
|
|
18540
18974
|
}
|
|
18541
18975
|
try {
|
|
18542
|
-
return
|
|
18976
|
+
return readFileSync4(currentProfileFile, "utf-8").trim() || "default";
|
|
18543
18977
|
} catch {
|
|
18544
18978
|
return "default";
|
|
18545
18979
|
}
|
|
18546
18980
|
}
|
|
18547
18981
|
function setCurrentProfile(profile) {
|
|
18548
18982
|
const configDir = getConfigDir2();
|
|
18549
|
-
|
|
18550
|
-
|
|
18983
|
+
mkdirSync5(configDir, { recursive: true });
|
|
18984
|
+
writeFileSync4(join9(configDir, "current_profile"), profile);
|
|
18551
18985
|
}
|
|
18552
18986
|
function getFlatProfilePath(profile) {
|
|
18553
18987
|
return join9(getProfilesDir(), `${profile}.json`);
|
|
@@ -18557,7 +18991,7 @@ function getDirectoryProfilePath(profile) {
|
|
|
18557
18991
|
}
|
|
18558
18992
|
function loadJsonFile(path) {
|
|
18559
18993
|
try {
|
|
18560
|
-
return JSON.parse(
|
|
18994
|
+
return JSON.parse(readFileSync4(path, "utf-8"));
|
|
18561
18995
|
} catch {
|
|
18562
18996
|
return {};
|
|
18563
18997
|
}
|
|
@@ -18582,8 +19016,8 @@ function loadProfile(profile = getCurrentProfile()) {
|
|
|
18582
19016
|
}
|
|
18583
19017
|
function writeProfile(profile, config) {
|
|
18584
19018
|
const profilesDir = getProfilesDir();
|
|
18585
|
-
|
|
18586
|
-
|
|
19019
|
+
mkdirSync5(profilesDir, { recursive: true });
|
|
19020
|
+
writeFileSync4(getFlatProfilePath(profile), JSON.stringify(config, null, 2) + `
|
|
18587
19021
|
`);
|
|
18588
19022
|
}
|
|
18589
19023
|
function profileExists(profile) {
|
|
@@ -18592,14 +19026,14 @@ function profileExists(profile) {
|
|
|
18592
19026
|
}
|
|
18593
19027
|
return existsSync9(getFlatProfilePath(profile)) || existsSync9(join9(getProfilesDir(), profile));
|
|
18594
19028
|
}
|
|
18595
|
-
function
|
|
19029
|
+
function listProfiles3() {
|
|
18596
19030
|
const profilesDir = getProfilesDir();
|
|
18597
19031
|
const seen = new Set(["default"]);
|
|
18598
19032
|
if (!existsSync9(profilesDir)) {
|
|
18599
19033
|
return [...seen];
|
|
18600
19034
|
}
|
|
18601
19035
|
try {
|
|
18602
|
-
for (const entry of
|
|
19036
|
+
for (const entry of readdirSync5(profilesDir)) {
|
|
18603
19037
|
const fullPath = join9(profilesDir, entry);
|
|
18604
19038
|
const stat = statSync2(fullPath);
|
|
18605
19039
|
if (stat.isDirectory()) {
|
|
@@ -18921,7 +19355,7 @@ async function sendMessage(context, input) {
|
|
|
18921
19355
|
direction: "outbound"
|
|
18922
19356
|
});
|
|
18923
19357
|
}
|
|
18924
|
-
async function
|
|
19358
|
+
async function replyToMessage2(context, input) {
|
|
18925
19359
|
const payload = await bridgeRequest(context, "/messages/reply", {
|
|
18926
19360
|
method: "POST",
|
|
18927
19361
|
body: {
|
|
@@ -19035,7 +19469,7 @@ async function runProfileCommand2(args, context) {
|
|
|
19035
19469
|
switch (subcommand) {
|
|
19036
19470
|
case "list": {
|
|
19037
19471
|
const current = getCurrentProfile();
|
|
19038
|
-
const profiles =
|
|
19472
|
+
const profiles = listProfiles3();
|
|
19039
19473
|
return successOutput({ current, profiles }, context.format, () => profiles.map((profile) => `${profile}${profile === current ? " (active)" : ""}`).join(`
|
|
19040
19474
|
`));
|
|
19041
19475
|
}
|
|
@@ -19209,7 +19643,7 @@ async function runMessageCommand(args, context) {
|
|
|
19209
19643
|
if (!conversationId || !text) {
|
|
19210
19644
|
return failure2("Usage: connect-imessage message reply --conversation <id> --text <text>");
|
|
19211
19645
|
}
|
|
19212
|
-
return successOutput(await
|
|
19646
|
+
return successOutput(await replyToMessage2(resolved, {
|
|
19213
19647
|
conversationId,
|
|
19214
19648
|
text,
|
|
19215
19649
|
replyToMessageId: asString2(options.replyTo),
|
|
@@ -19487,7 +19921,7 @@ var init_imessage = __esm(() => {
|
|
|
19487
19921
|
summary: "Reply to an existing conversation through the bridge",
|
|
19488
19922
|
inputSchema: messageReplyInputSchema,
|
|
19489
19923
|
async execute({ context }, input) {
|
|
19490
|
-
return
|
|
19924
|
+
return replyToMessage2(context, input);
|
|
19491
19925
|
}
|
|
19492
19926
|
}
|
|
19493
19927
|
},
|
|
@@ -20431,10 +20865,12 @@ var INTERNAL_CONNECTOR_DEFINITIONS, INTERNAL_CONNECTOR_REGISTRY;
|
|
|
20431
20865
|
var init_builtins = __esm(() => {
|
|
20432
20866
|
init_registry();
|
|
20433
20867
|
init_github();
|
|
20868
|
+
init_gmail();
|
|
20434
20869
|
init_googledrive();
|
|
20435
20870
|
init_imessage();
|
|
20436
20871
|
init_stripe();
|
|
20437
20872
|
INTERNAL_CONNECTOR_DEFINITIONS = [
|
|
20873
|
+
gmailConnector,
|
|
20438
20874
|
githubConnector,
|
|
20439
20875
|
googleDriveConnector,
|
|
20440
20876
|
imessageConnector,
|
|
@@ -26576,7 +27012,7 @@ __export(exports_registry, {
|
|
|
26576
27012
|
CONNECTORS: () => CONNECTORS,
|
|
26577
27013
|
CATEGORIES: () => CATEGORIES
|
|
26578
27014
|
});
|
|
26579
|
-
import { existsSync as existsSync11, readFileSync as
|
|
27015
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5 } from "fs";
|
|
26580
27016
|
import { join as join11, dirname as dirname5 } from "path";
|
|
26581
27017
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
26582
27018
|
function getConnectorsByCategory(category) {
|
|
@@ -26748,7 +27184,7 @@ function loadConnectorVersions() {
|
|
|
26748
27184
|
try {
|
|
26749
27185
|
const pkgPath = join11(connectorsDir, `connect-${connector.name}`, "package.json");
|
|
26750
27186
|
if (existsSync11(pkgPath)) {
|
|
26751
|
-
const pkg = JSON.parse(
|
|
27187
|
+
const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
|
|
26752
27188
|
connector.version = pkg.version || "0.0.0";
|
|
26753
27189
|
continue;
|
|
26754
27190
|
}
|
|
@@ -28471,7 +28907,7 @@ __export(exports_installer, {
|
|
|
28471
28907
|
getConnectorDocs: () => getConnectorDocs,
|
|
28472
28908
|
connectorExists: () => connectorExists
|
|
28473
28909
|
});
|
|
28474
|
-
import { existsSync as existsSync12, mkdirSync as
|
|
28910
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync5, readdirSync as readdirSync6, statSync as statSync3, rmSync as rmSync2 } from "fs";
|
|
28475
28911
|
import { join as join12, dirname as dirname6 } from "path";
|
|
28476
28912
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
28477
28913
|
function resolveConnectorsDir() {
|
|
@@ -28501,7 +28937,7 @@ function loadEnablementManifest(targetDir) {
|
|
|
28501
28937
|
return null;
|
|
28502
28938
|
}
|
|
28503
28939
|
try {
|
|
28504
|
-
const raw = JSON.parse(
|
|
28940
|
+
const raw = JSON.parse(readFileSync6(manifestPath, "utf-8"));
|
|
28505
28941
|
if (!Array.isArray(raw.connectors)) {
|
|
28506
28942
|
return null;
|
|
28507
28943
|
}
|
|
@@ -28520,7 +28956,7 @@ function getLegacyInstalledConnectors(targetDir) {
|
|
|
28520
28956
|
if (!existsSync12(connectorsDir)) {
|
|
28521
28957
|
return [];
|
|
28522
28958
|
}
|
|
28523
|
-
return
|
|
28959
|
+
return readdirSync6(connectorsDir).filter((entry) => {
|
|
28524
28960
|
const fullPath = join12(connectorsDir, entry);
|
|
28525
28961
|
return entry.startsWith("connect-") && statSync3(fullPath).isDirectory();
|
|
28526
28962
|
}).map((entry) => entry.replace("connect-", "")).sort();
|
|
@@ -28546,18 +28982,18 @@ ${connectorList}
|
|
|
28546
28982
|
|
|
28547
28983
|
export type EnabledConnectorName = typeof enabledConnectors[number];
|
|
28548
28984
|
`;
|
|
28549
|
-
|
|
28985
|
+
writeFileSync5(indexPath, content);
|
|
28550
28986
|
}
|
|
28551
28987
|
function writeEnablementManifest(targetDir, connectors18) {
|
|
28552
28988
|
const connectorsDir = getProjectConnectorsDir(targetDir);
|
|
28553
|
-
|
|
28989
|
+
mkdirSync6(connectorsDir, { recursive: true });
|
|
28554
28990
|
const manifest = {
|
|
28555
28991
|
version: 1,
|
|
28556
28992
|
mode: "internal",
|
|
28557
28993
|
updatedAt: new Date().toISOString(),
|
|
28558
28994
|
connectors: [...new Set(connectors18.map((value) => normalizeConnectorName(value)))].sort()
|
|
28559
28995
|
};
|
|
28560
|
-
|
|
28996
|
+
writeFileSync5(getEnablementManifestPath(targetDir), JSON.stringify(manifest, null, 2) + `
|
|
28561
28997
|
`);
|
|
28562
28998
|
updateConnectorsIndex(connectorsDir, manifest.connectors);
|
|
28563
28999
|
}
|
|
@@ -28637,7 +29073,7 @@ function getConnectorDocs(name) {
|
|
|
28637
29073
|
const connectorPath = getConnectorPath(normalizedName);
|
|
28638
29074
|
const claudeMdPath = join12(connectorPath, "CLAUDE.md");
|
|
28639
29075
|
if (existsSync12(claudeMdPath)) {
|
|
28640
|
-
return parseConnectorDocs(
|
|
29076
|
+
return parseConnectorDocs(readFileSync6(claudeMdPath, "utf-8"));
|
|
28641
29077
|
}
|
|
28642
29078
|
const internalDocs = getInternalConnectorDefinition(normalizedName)?.docsMarkdown;
|
|
28643
29079
|
if (internalDocs) {
|
|
@@ -28696,10 +29132,10 @@ var init_installer = __esm(() => {
|
|
|
28696
29132
|
// src/lib/lock.ts
|
|
28697
29133
|
import { openSync, closeSync, unlinkSync as unlinkSync2, existsSync as existsSync13, statSync as statSync5 } from "fs";
|
|
28698
29134
|
import { join as join14 } from "path";
|
|
28699
|
-
import { mkdirSync as
|
|
29135
|
+
import { mkdirSync as mkdirSync7 } from "fs";
|
|
28700
29136
|
function lockPath(connector) {
|
|
28701
29137
|
const dir = join14(getConnectorsHome(), `connect-${connector}`);
|
|
28702
|
-
|
|
29138
|
+
mkdirSync7(dir, { recursive: true });
|
|
28703
29139
|
return join14(dir, ".write.lock");
|
|
28704
29140
|
}
|
|
28705
29141
|
function isStale(path) {
|
|
@@ -28760,7 +29196,7 @@ var init_lock = __esm(() => {
|
|
|
28760
29196
|
});
|
|
28761
29197
|
|
|
28762
29198
|
// src/server/auth.ts
|
|
28763
|
-
import { existsSync as existsSync14, readFileSync as
|
|
29199
|
+
import { existsSync as existsSync14, readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync8, readdirSync as readdirSync8, rmSync as rmSync3, statSync as statSync6 } from "fs";
|
|
28764
29200
|
import { randomBytes } from "crypto";
|
|
28765
29201
|
import { join as join15 } from "path";
|
|
28766
29202
|
function getAuthType(name) {
|
|
@@ -28783,7 +29219,7 @@ function getCurrentProfile2(name) {
|
|
|
28783
29219
|
const currentProfileFile = join15(configDir, "current_profile");
|
|
28784
29220
|
if (existsSync14(currentProfileFile)) {
|
|
28785
29221
|
try {
|
|
28786
|
-
return
|
|
29222
|
+
return readFileSync7(currentProfileFile, "utf-8").trim() || "default";
|
|
28787
29223
|
} catch {
|
|
28788
29224
|
return "default";
|
|
28789
29225
|
}
|
|
@@ -28798,13 +29234,13 @@ function loadProfileConfig(name) {
|
|
|
28798
29234
|
const profileFile = join15(configDir, "profiles", `${profile}.json`);
|
|
28799
29235
|
if (existsSync14(profileFile)) {
|
|
28800
29236
|
try {
|
|
28801
|
-
flatConfig = JSON.parse(
|
|
29237
|
+
flatConfig = JSON.parse(readFileSync7(profileFile, "utf-8"));
|
|
28802
29238
|
} catch {}
|
|
28803
29239
|
}
|
|
28804
29240
|
const profileDirConfig = join15(configDir, "profiles", profile, "config.json");
|
|
28805
29241
|
if (existsSync14(profileDirConfig)) {
|
|
28806
29242
|
try {
|
|
28807
|
-
dirConfig = JSON.parse(
|
|
29243
|
+
dirConfig = JSON.parse(readFileSync7(profileDirConfig, "utf-8"));
|
|
28808
29244
|
} catch {}
|
|
28809
29245
|
}
|
|
28810
29246
|
if (Object.keys(flatConfig).length === 0 && Object.keys(dirConfig).length === 0) {
|
|
@@ -28812,13 +29248,13 @@ function loadProfileConfig(name) {
|
|
|
28812
29248
|
}
|
|
28813
29249
|
return { ...flatConfig, ...dirConfig };
|
|
28814
29250
|
}
|
|
28815
|
-
function
|
|
29251
|
+
function loadTokens3(name) {
|
|
28816
29252
|
const configDir = getConnectorConfigDir(name);
|
|
28817
29253
|
const profile = getCurrentProfile2(name);
|
|
28818
29254
|
const tokensFile = join15(configDir, "profiles", profile, "tokens.json");
|
|
28819
29255
|
if (existsSync14(tokensFile)) {
|
|
28820
29256
|
try {
|
|
28821
|
-
return JSON.parse(
|
|
29257
|
+
return JSON.parse(readFileSync7(tokensFile, "utf-8"));
|
|
28822
29258
|
} catch {
|
|
28823
29259
|
return null;
|
|
28824
29260
|
}
|
|
@@ -28857,7 +29293,7 @@ function getAuthStatus(name) {
|
|
|
28857
29293
|
const authType = getAuthType(name);
|
|
28858
29294
|
const docs = getConnectorDocs(name);
|
|
28859
29295
|
const oauthConfig = authType === "oauth" ? getOAuthConfig(name) : {};
|
|
28860
|
-
const tokens = authType === "oauth" ?
|
|
29296
|
+
const tokens = authType === "oauth" ? loadTokens3(name) : null;
|
|
28861
29297
|
const profileConfig = authType === "oauth" ? loadProfileConfig(name) : {};
|
|
28862
29298
|
const envVars = (docs?.envVars || []).map((v) => ({
|
|
28863
29299
|
variable: v.variable,
|
|
@@ -28907,15 +29343,15 @@ function _saveApiKey(name, key, field) {
|
|
|
28907
29343
|
const keyField = field || guessKeyField(name);
|
|
28908
29344
|
if (keyField === "clientId" || keyField === "clientSecret") {
|
|
28909
29345
|
const credentialsFile = join15(configDir, "credentials.json");
|
|
28910
|
-
|
|
29346
|
+
mkdirSync8(configDir, { recursive: true });
|
|
28911
29347
|
let creds = {};
|
|
28912
29348
|
if (existsSync14(credentialsFile)) {
|
|
28913
29349
|
try {
|
|
28914
|
-
creds = JSON.parse(
|
|
29350
|
+
creds = JSON.parse(readFileSync7(credentialsFile, "utf-8"));
|
|
28915
29351
|
} catch {}
|
|
28916
29352
|
}
|
|
28917
29353
|
creds[keyField] = key;
|
|
28918
|
-
|
|
29354
|
+
writeFileSync6(credentialsFile, JSON.stringify(creds, null, 2));
|
|
28919
29355
|
return;
|
|
28920
29356
|
}
|
|
28921
29357
|
const profileFile = join15(configDir, "profiles", `${profile}.json`);
|
|
@@ -28923,10 +29359,10 @@ function _saveApiKey(name, key, field) {
|
|
|
28923
29359
|
if (existsSync14(profileFile)) {
|
|
28924
29360
|
let config = {};
|
|
28925
29361
|
try {
|
|
28926
|
-
config = JSON.parse(
|
|
29362
|
+
config = JSON.parse(readFileSync7(profileFile, "utf-8"));
|
|
28927
29363
|
} catch {}
|
|
28928
29364
|
config[keyField] = key;
|
|
28929
|
-
|
|
29365
|
+
writeFileSync6(profileFile, JSON.stringify(config, null, 2));
|
|
28930
29366
|
return;
|
|
28931
29367
|
}
|
|
28932
29368
|
if (existsSync14(profileDir)) {
|
|
@@ -28934,15 +29370,15 @@ function _saveApiKey(name, key, field) {
|
|
|
28934
29370
|
let config = {};
|
|
28935
29371
|
if (existsSync14(configFile)) {
|
|
28936
29372
|
try {
|
|
28937
|
-
config = JSON.parse(
|
|
29373
|
+
config = JSON.parse(readFileSync7(configFile, "utf-8"));
|
|
28938
29374
|
} catch {}
|
|
28939
29375
|
}
|
|
28940
29376
|
config[keyField] = key;
|
|
28941
|
-
|
|
29377
|
+
writeFileSync6(configFile, JSON.stringify(config, null, 2));
|
|
28942
29378
|
return;
|
|
28943
29379
|
}
|
|
28944
|
-
|
|
28945
|
-
|
|
29380
|
+
mkdirSync8(profileDir, { recursive: true });
|
|
29381
|
+
writeFileSync6(join15(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
|
|
28946
29382
|
}
|
|
28947
29383
|
function guessKeyField(name) {
|
|
28948
29384
|
const docs = getConnectorDocs(name);
|
|
@@ -28963,7 +29399,7 @@ function getOAuthConfig(name) {
|
|
|
28963
29399
|
const credentialsFile = join15(configDir, "credentials.json");
|
|
28964
29400
|
if (existsSync14(credentialsFile)) {
|
|
28965
29401
|
try {
|
|
28966
|
-
const creds = JSON.parse(
|
|
29402
|
+
const creds = JSON.parse(readFileSync7(credentialsFile, "utf-8"));
|
|
28967
29403
|
return { clientId: creds.clientId, clientSecret: creds.clientSecret };
|
|
28968
29404
|
} catch {}
|
|
28969
29405
|
}
|
|
@@ -29043,16 +29479,16 @@ function saveOAuthTokens(name, tokens) {
|
|
|
29043
29479
|
const configDir = getConnectorConfigDir(name);
|
|
29044
29480
|
const profile = getCurrentProfile2(name);
|
|
29045
29481
|
const profileDir = join15(configDir, "profiles", profile);
|
|
29046
|
-
|
|
29482
|
+
mkdirSync8(profileDir, { recursive: true });
|
|
29047
29483
|
const tokensFile = join15(profileDir, "tokens.json");
|
|
29048
|
-
|
|
29484
|
+
writeFileSync6(tokensFile, JSON.stringify(tokens, null, 2), { mode: 384 });
|
|
29049
29485
|
}
|
|
29050
29486
|
async function refreshOAuthToken(name) {
|
|
29051
29487
|
return withWriteLock(name, () => _refreshOAuthToken(name));
|
|
29052
29488
|
}
|
|
29053
29489
|
async function _refreshOAuthToken(name) {
|
|
29054
29490
|
const oauthConfig = getOAuthConfig(name);
|
|
29055
|
-
const currentTokens =
|
|
29491
|
+
const currentTokens = loadTokens3(name);
|
|
29056
29492
|
if (!oauthConfig.clientId || !oauthConfig.clientSecret) {
|
|
29057
29493
|
throw new Error("OAuth credentials not configured for " + name);
|
|
29058
29494
|
}
|
|
@@ -29085,14 +29521,14 @@ async function _refreshOAuthToken(name) {
|
|
|
29085
29521
|
saveOAuthTokens(name, tokens);
|
|
29086
29522
|
return tokens;
|
|
29087
29523
|
}
|
|
29088
|
-
function
|
|
29524
|
+
function listProfiles4(name) {
|
|
29089
29525
|
const configDir = getConnectorConfigDir(name);
|
|
29090
29526
|
const profilesDir = join15(configDir, "profiles");
|
|
29091
29527
|
if (!existsSync14(profilesDir))
|
|
29092
29528
|
return ["default"];
|
|
29093
29529
|
const seen = new Set;
|
|
29094
29530
|
try {
|
|
29095
|
-
const entries =
|
|
29531
|
+
const entries = readdirSync8(profilesDir);
|
|
29096
29532
|
for (const entry of entries) {
|
|
29097
29533
|
const fullPath = join15(profilesDir, entry);
|
|
29098
29534
|
const stat = statSync6(fullPath);
|
|
@@ -29108,8 +29544,8 @@ function listProfiles3(name) {
|
|
|
29108
29544
|
}
|
|
29109
29545
|
function switchProfile(name, profile) {
|
|
29110
29546
|
const configDir = getConnectorConfigDir(name);
|
|
29111
|
-
|
|
29112
|
-
|
|
29547
|
+
mkdirSync8(configDir, { recursive: true });
|
|
29548
|
+
writeFileSync6(join15(configDir, "current_profile"), profile);
|
|
29113
29549
|
}
|
|
29114
29550
|
function deleteProfile2(name, profile) {
|
|
29115
29551
|
if (profile === "default")
|
|
@@ -29388,7 +29824,7 @@ var init_rate = __esm(() => {
|
|
|
29388
29824
|
});
|
|
29389
29825
|
|
|
29390
29826
|
// src/lib/llm.ts
|
|
29391
|
-
import { existsSync as existsSync15, readFileSync as
|
|
29827
|
+
import { existsSync as existsSync15, readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync9 } from "fs";
|
|
29392
29828
|
import { join as join16 } from "path";
|
|
29393
29829
|
function getLlmConfigPath() {
|
|
29394
29830
|
return join16(getConnectorsHome(), "llm.json");
|
|
@@ -29398,15 +29834,15 @@ function getLlmConfig() {
|
|
|
29398
29834
|
if (!existsSync15(path))
|
|
29399
29835
|
return null;
|
|
29400
29836
|
try {
|
|
29401
|
-
return JSON.parse(
|
|
29837
|
+
return JSON.parse(readFileSync8(path, "utf-8"));
|
|
29402
29838
|
} catch {
|
|
29403
29839
|
return null;
|
|
29404
29840
|
}
|
|
29405
29841
|
}
|
|
29406
29842
|
function saveLlmConfig(config) {
|
|
29407
29843
|
const dir = getConnectorsHome();
|
|
29408
|
-
|
|
29409
|
-
|
|
29844
|
+
mkdirSync9(dir, { recursive: true });
|
|
29845
|
+
writeFileSync7(getLlmConfigPath(), JSON.stringify(config, null, 2));
|
|
29410
29846
|
}
|
|
29411
29847
|
function setLlmStrip(enabled) {
|
|
29412
29848
|
const config = getLlmConfig();
|
|
@@ -29844,7 +30280,7 @@ var init_workflow_runner = __esm(() => {
|
|
|
29844
30280
|
});
|
|
29845
30281
|
|
|
29846
30282
|
// src/lib/runner.ts
|
|
29847
|
-
import { existsSync as existsSync16, readdirSync as
|
|
30283
|
+
import { existsSync as existsSync16, readdirSync as readdirSync9 } from "fs";
|
|
29848
30284
|
import { join as join17, dirname as dirname7 } from "path";
|
|
29849
30285
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
29850
30286
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -29898,7 +30334,7 @@ function buildEnvWithCredentials(connectorName, baseEnv) {
|
|
|
29898
30334
|
}
|
|
29899
30335
|
if (getAuthType(connectorName) === "oauth") {
|
|
29900
30336
|
const oauthConfig = getOAuthConfig(connectorName);
|
|
29901
|
-
const tokens =
|
|
30337
|
+
const tokens = loadTokens3(connectorName);
|
|
29902
30338
|
for (const { variable } of getEnvVars(connectorName)) {
|
|
29903
30339
|
if (env[variable])
|
|
29904
30340
|
continue;
|
|
@@ -30106,8 +30542,8 @@ var exports_serve = {};
|
|
|
30106
30542
|
__export(exports_serve, {
|
|
30107
30543
|
startServer: () => startServer
|
|
30108
30544
|
});
|
|
30109
|
-
import { existsSync as existsSync17, readdirSync as
|
|
30110
|
-
import { join as join18, dirname as dirname8, extname, basename as
|
|
30545
|
+
import { existsSync as existsSync17, readdirSync as readdirSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync10 } from "fs";
|
|
30546
|
+
import { join as join18, dirname as dirname8, extname, basename as basename3 } from "path";
|
|
30111
30547
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
30112
30548
|
function logActivity(action, connector, detail) {
|
|
30113
30549
|
activityLog.unshift({ action, connector, timestamp: Date.now(), detail });
|
|
@@ -30656,13 +31092,13 @@ ${result.stderr}`;
|
|
|
30656
31092
|
if (!isValidConnectorName(name))
|
|
30657
31093
|
return json({ error: "Invalid connector name" }, 400, port);
|
|
30658
31094
|
try {
|
|
30659
|
-
const profiles =
|
|
31095
|
+
const profiles = listProfiles4(name);
|
|
30660
31096
|
const configDir = join18(getConnectorsHome(), name.startsWith("connect-") ? name : `connect-${name}`);
|
|
30661
31097
|
const currentProfileFile = join18(configDir, "current_profile");
|
|
30662
31098
|
let current = "default";
|
|
30663
31099
|
if (existsSync17(currentProfileFile)) {
|
|
30664
31100
|
try {
|
|
30665
|
-
current =
|
|
31101
|
+
current = readFileSync9(currentProfileFile, "utf-8").trim() || "default";
|
|
30666
31102
|
} catch {}
|
|
30667
31103
|
}
|
|
30668
31104
|
return json({ current, profiles }, 200, port);
|
|
@@ -30712,7 +31148,7 @@ ${result.stderr}`;
|
|
|
30712
31148
|
const connectDir = getConnectorsHome();
|
|
30713
31149
|
const result = {};
|
|
30714
31150
|
if (existsSync17(connectDir)) {
|
|
30715
|
-
const entries =
|
|
31151
|
+
const entries = readdirSync10(connectDir, { withFileTypes: true });
|
|
30716
31152
|
for (const entry of entries) {
|
|
30717
31153
|
if (!entry.isDirectory() || !entry.name.startsWith("connect-"))
|
|
30718
31154
|
continue;
|
|
@@ -30721,12 +31157,12 @@ ${result.stderr}`;
|
|
|
30721
31157
|
if (!existsSync17(profilesDir))
|
|
30722
31158
|
continue;
|
|
30723
31159
|
const profiles = {};
|
|
30724
|
-
const profileEntries =
|
|
31160
|
+
const profileEntries = readdirSync10(profilesDir, { withFileTypes: true });
|
|
30725
31161
|
for (const pEntry of profileEntries) {
|
|
30726
31162
|
if (pEntry.isFile() && pEntry.name.endsWith(".json")) {
|
|
30727
|
-
const profileName =
|
|
31163
|
+
const profileName = basename3(pEntry.name, ".json");
|
|
30728
31164
|
try {
|
|
30729
|
-
const config = JSON.parse(
|
|
31165
|
+
const config = JSON.parse(readFileSync9(join18(profilesDir, pEntry.name), "utf-8"));
|
|
30730
31166
|
profiles[profileName] = config;
|
|
30731
31167
|
} catch {}
|
|
30732
31168
|
}
|
|
@@ -30734,7 +31170,7 @@ ${result.stderr}`;
|
|
|
30734
31170
|
const configPath = join18(profilesDir, pEntry.name, "config.json");
|
|
30735
31171
|
if (existsSync17(configPath)) {
|
|
30736
31172
|
try {
|
|
30737
|
-
const config = JSON.parse(
|
|
31173
|
+
const config = JSON.parse(readFileSync9(configPath, "utf-8"));
|
|
30738
31174
|
profiles[pEntry.name] = config;
|
|
30739
31175
|
} catch {}
|
|
30740
31176
|
}
|
|
@@ -30780,9 +31216,9 @@ ${result.stderr}`;
|
|
|
30780
31216
|
for (const [profileName, config] of Object.entries(data.profiles)) {
|
|
30781
31217
|
if (!config || typeof config !== "object")
|
|
30782
31218
|
continue;
|
|
30783
|
-
|
|
31219
|
+
mkdirSync10(profilesDir, { recursive: true });
|
|
30784
31220
|
const profileFile = join18(profilesDir, `${profileName}.json`);
|
|
30785
|
-
|
|
31221
|
+
writeFileSync8(profileFile, JSON.stringify(config, null, 2));
|
|
30786
31222
|
imported++;
|
|
30787
31223
|
}
|
|
30788
31224
|
}
|
|
@@ -32402,7 +32838,7 @@ init_registry2();
|
|
|
32402
32838
|
init_installer();
|
|
32403
32839
|
import { render } from "ink";
|
|
32404
32840
|
import chalk2 from "chalk";
|
|
32405
|
-
import { readdirSync as
|
|
32841
|
+
import { readdirSync as readdirSync7, statSync as statSync4 } from "fs";
|
|
32406
32842
|
import { join as join13, relative as relative2 } from "path";
|
|
32407
32843
|
import { createInterface } from "readline";
|
|
32408
32844
|
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
@@ -32417,7 +32853,7 @@ var PRESETS = {
|
|
|
32417
32853
|
};
|
|
32418
32854
|
function listFilesRecursive(dir, base = dir) {
|
|
32419
32855
|
const files = [];
|
|
32420
|
-
for (const entry of
|
|
32856
|
+
for (const entry of readdirSync7(dir)) {
|
|
32421
32857
|
const fullPath = join13(dir, entry);
|
|
32422
32858
|
if (statSync4(fullPath).isDirectory()) {
|
|
32423
32859
|
files.push(...listFilesRecursive(fullPath, base));
|
|
@@ -33089,7 +33525,7 @@ init_installer();
|
|
|
33089
33525
|
init_auth();
|
|
33090
33526
|
init_database();
|
|
33091
33527
|
import chalk4 from "chalk";
|
|
33092
|
-
import { existsSync as existsSync18, readdirSync as
|
|
33528
|
+
import { existsSync as existsSync18, readdirSync as readdirSync11, statSync as statSync7, readFileSync as readFileSync10 } from "fs";
|
|
33093
33529
|
import { join as join19 } from "path";
|
|
33094
33530
|
function registerCommands3(program2) {
|
|
33095
33531
|
program2.command("status").option("--json", "Output as JSON", false).description("Show auth status of all configured connectors (project + global)").action((options) => {
|
|
@@ -33104,7 +33540,7 @@ function registerCommands3(program2) {
|
|
|
33104
33540
|
let profile = "default";
|
|
33105
33541
|
if (existsSync18(currentProfileFile)) {
|
|
33106
33542
|
try {
|
|
33107
|
-
profile =
|
|
33543
|
+
profile = readFileSync10(currentProfileFile, "utf-8").trim() || "default";
|
|
33108
33544
|
} catch {}
|
|
33109
33545
|
}
|
|
33110
33546
|
let expiryLabel = null;
|
|
@@ -33142,7 +33578,7 @@ function registerCommands3(program2) {
|
|
|
33142
33578
|
}
|
|
33143
33579
|
if (existsSync18(configDir)) {
|
|
33144
33580
|
try {
|
|
33145
|
-
const globalDirs =
|
|
33581
|
+
const globalDirs = readdirSync11(configDir).filter((f) => {
|
|
33146
33582
|
if (!f.startsWith("connect-"))
|
|
33147
33583
|
return false;
|
|
33148
33584
|
if (f.startsWith("connect-zzztest"))
|
|
@@ -33361,7 +33797,7 @@ init_registry2();
|
|
|
33361
33797
|
init_auth();
|
|
33362
33798
|
init_database();
|
|
33363
33799
|
import chalk5 from "chalk";
|
|
33364
|
-
import { existsSync as existsSync19, readdirSync as
|
|
33800
|
+
import { existsSync as existsSync19, readdirSync as readdirSync12, statSync as statSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync9, mkdirSync as mkdirSync11 } from "fs";
|
|
33365
33801
|
import { join as join20 } from "path";
|
|
33366
33802
|
import { homedir as homedir8 } from "os";
|
|
33367
33803
|
import { createInterface as createInterface2 } from "readline";
|
|
@@ -33415,7 +33851,7 @@ function redactSecrets(obj) {
|
|
|
33415
33851
|
return obj;
|
|
33416
33852
|
}
|
|
33417
33853
|
function getOAuthTokenState(name) {
|
|
33418
|
-
const tokens =
|
|
33854
|
+
const tokens = loadTokens3(name);
|
|
33419
33855
|
if (!tokens?.accessToken && !tokens?.refreshToken) {
|
|
33420
33856
|
return { hasTokens: false, expired: false };
|
|
33421
33857
|
}
|
|
@@ -33734,7 +34170,7 @@ Open this URL to authenticate:
|
|
|
33734
34170
|
const configuredNames = [];
|
|
33735
34171
|
try {
|
|
33736
34172
|
if (existsSync19(connectorsHome)) {
|
|
33737
|
-
const entries =
|
|
34173
|
+
const entries = readdirSync12(connectorsHome).filter((e) => e.startsWith("connect-") && statSync8(join20(connectorsHome, e)).isDirectory());
|
|
33738
34174
|
for (const entry of entries) {
|
|
33739
34175
|
const profilesDir = join20(connectorsHome, entry, "profiles");
|
|
33740
34176
|
if (existsSync19(profilesDir)) {
|
|
@@ -33789,7 +34225,7 @@ Open this URL to authenticate:
|
|
|
33789
34225
|
const connectDir = getConnectorsHome();
|
|
33790
34226
|
const result = {};
|
|
33791
34227
|
if (existsSync19(connectDir)) {
|
|
33792
|
-
for (const entry of
|
|
34228
|
+
for (const entry of readdirSync12(connectDir)) {
|
|
33793
34229
|
const entryPath = join20(connectDir, entry);
|
|
33794
34230
|
if (!statSync8(entryPath).isDirectory() || !entry.startsWith("connect-"))
|
|
33795
34231
|
continue;
|
|
@@ -33798,7 +34234,7 @@ Open this URL to authenticate:
|
|
|
33798
34234
|
const credentialsPath = join20(entryPath, "credentials.json");
|
|
33799
34235
|
if (existsSync19(credentialsPath)) {
|
|
33800
34236
|
try {
|
|
33801
|
-
credentials = JSON.parse(
|
|
34237
|
+
credentials = JSON.parse(readFileSync11(credentialsPath, "utf-8"));
|
|
33802
34238
|
} catch {}
|
|
33803
34239
|
}
|
|
33804
34240
|
const profilesDir = join20(entryPath, "profiles");
|
|
@@ -33806,11 +34242,11 @@ Open this URL to authenticate:
|
|
|
33806
34242
|
continue;
|
|
33807
34243
|
const profiles = {};
|
|
33808
34244
|
if (existsSync19(profilesDir)) {
|
|
33809
|
-
for (const pEntry of
|
|
34245
|
+
for (const pEntry of readdirSync12(profilesDir)) {
|
|
33810
34246
|
const pPath = join20(profilesDir, pEntry);
|
|
33811
34247
|
if (statSync8(pPath).isFile() && pEntry.endsWith(".json")) {
|
|
33812
34248
|
try {
|
|
33813
|
-
profiles[pEntry.replace(/\.json$/, "")] = JSON.parse(
|
|
34249
|
+
profiles[pEntry.replace(/\.json$/, "")] = JSON.parse(readFileSync11(pPath, "utf-8"));
|
|
33814
34250
|
} catch {}
|
|
33815
34251
|
} else if (statSync8(pPath).isDirectory()) {
|
|
33816
34252
|
const configPath = join20(pPath, "config.json");
|
|
@@ -33818,12 +34254,12 @@ Open this URL to authenticate:
|
|
|
33818
34254
|
let merged = {};
|
|
33819
34255
|
if (existsSync19(configPath)) {
|
|
33820
34256
|
try {
|
|
33821
|
-
merged = { ...merged, ...JSON.parse(
|
|
34257
|
+
merged = { ...merged, ...JSON.parse(readFileSync11(configPath, "utf-8")) };
|
|
33822
34258
|
} catch {}
|
|
33823
34259
|
}
|
|
33824
34260
|
if (existsSync19(tokensPath)) {
|
|
33825
34261
|
try {
|
|
33826
|
-
merged = { ...merged, ...JSON.parse(
|
|
34262
|
+
merged = { ...merged, ...JSON.parse(readFileSync11(tokensPath, "utf-8")) };
|
|
33827
34263
|
} catch {}
|
|
33828
34264
|
}
|
|
33829
34265
|
if (Object.keys(merged).length > 0)
|
|
@@ -33844,7 +34280,7 @@ Open this URL to authenticate:
|
|
|
33844
34280
|
}
|
|
33845
34281
|
const exportData = JSON.stringify(exportPayload, null, 2);
|
|
33846
34282
|
if (options.output) {
|
|
33847
|
-
|
|
34283
|
+
writeFileSync9(options.output, exportData);
|
|
33848
34284
|
console.log(chalk5.green(`\u2713 Exported to ${options.output}`));
|
|
33849
34285
|
} else {
|
|
33850
34286
|
console.log(exportData);
|
|
@@ -33867,7 +34303,7 @@ Open this URL to authenticate:
|
|
|
33867
34303
|
process.exit(1);
|
|
33868
34304
|
return;
|
|
33869
34305
|
}
|
|
33870
|
-
raw =
|
|
34306
|
+
raw = readFileSync11(file, "utf-8");
|
|
33871
34307
|
}
|
|
33872
34308
|
let data;
|
|
33873
34309
|
try {
|
|
@@ -33897,8 +34333,8 @@ Open this URL to authenticate:
|
|
|
33897
34333
|
continue;
|
|
33898
34334
|
const connectorDir = join20(connectDir, `connect-${connectorName}`);
|
|
33899
34335
|
if (connData.credentials && typeof connData.credentials === "object") {
|
|
33900
|
-
|
|
33901
|
-
|
|
34336
|
+
mkdirSync11(connectorDir, { recursive: true });
|
|
34337
|
+
writeFileSync9(join20(connectorDir, "credentials.json"), JSON.stringify(connData.credentials, null, 2));
|
|
33902
34338
|
imported++;
|
|
33903
34339
|
}
|
|
33904
34340
|
if (!connData.profiles || typeof connData.profiles !== "object")
|
|
@@ -33907,8 +34343,8 @@ Open this URL to authenticate:
|
|
|
33907
34343
|
for (const [profileName, config] of Object.entries(connData.profiles)) {
|
|
33908
34344
|
if (!config || typeof config !== "object")
|
|
33909
34345
|
continue;
|
|
33910
|
-
|
|
33911
|
-
|
|
34346
|
+
mkdirSync11(profilesDir, { recursive: true });
|
|
34347
|
+
writeFileSync9(join20(profilesDir, `${profileName}.json`), JSON.stringify(config, null, 2));
|
|
33912
34348
|
imported++;
|
|
33913
34349
|
}
|
|
33914
34350
|
}
|
|
@@ -33929,7 +34365,7 @@ Open this URL to authenticate:
|
|
|
33929
34365
|
}
|
|
33930
34366
|
return;
|
|
33931
34367
|
}
|
|
33932
|
-
const entries =
|
|
34368
|
+
const entries = readdirSync12(oldBase).filter((name) => {
|
|
33933
34369
|
if (!name.startsWith("connect-"))
|
|
33934
34370
|
return false;
|
|
33935
34371
|
try {
|
|
@@ -33969,9 +34405,9 @@ Open this URL to authenticate:
|
|
|
33969
34405
|
}
|
|
33970
34406
|
if (!options.dryRun) {
|
|
33971
34407
|
const parentDir = join20(destPath, "..");
|
|
33972
|
-
|
|
33973
|
-
const content =
|
|
33974
|
-
|
|
34408
|
+
mkdirSync11(parentDir, { recursive: true });
|
|
34409
|
+
const content = readFileSync11(srcPath);
|
|
34410
|
+
writeFileSync9(destPath, content);
|
|
33975
34411
|
}
|
|
33976
34412
|
copiedFiles.push(relFile);
|
|
33977
34413
|
}
|
|
@@ -34037,7 +34473,7 @@ init_installer();
|
|
|
34037
34473
|
init_auth();
|
|
34038
34474
|
init_database();
|
|
34039
34475
|
import chalk6 from "chalk";
|
|
34040
|
-
import { existsSync as existsSync20, readdirSync as
|
|
34476
|
+
import { existsSync as existsSync20, readdirSync as readdirSync13, statSync as statSync9, readFileSync as readFileSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
34041
34477
|
import { join as join21 } from "path";
|
|
34042
34478
|
|
|
34043
34479
|
// src/lib/test-endpoints.ts
|
|
@@ -34425,7 +34861,7 @@ complete -F _connectors connectors`);
|
|
|
34425
34861
|
`) + `
|
|
34426
34862
|
`;
|
|
34427
34863
|
if (options.output) {
|
|
34428
|
-
|
|
34864
|
+
writeFileSync10(options.output, output);
|
|
34429
34865
|
console.log(chalk6.green(`\u2713 Written to ${options.output} (${vars.length} variables)`));
|
|
34430
34866
|
} else {
|
|
34431
34867
|
console.log(output);
|
|
@@ -34472,14 +34908,14 @@ Available presets:
|
|
|
34472
34908
|
let profile = "default";
|
|
34473
34909
|
if (existsSync20(currentProfileFile)) {
|
|
34474
34910
|
try {
|
|
34475
|
-
profile =
|
|
34911
|
+
profile = readFileSync12(currentProfileFile, "utf-8").trim() || "default";
|
|
34476
34912
|
} catch {}
|
|
34477
34913
|
}
|
|
34478
34914
|
connectorDetails.push({ name, configured: auth.configured, authType: auth.type, profile, source: "project" });
|
|
34479
34915
|
}
|
|
34480
34916
|
if (existsSync20(configDir)) {
|
|
34481
34917
|
try {
|
|
34482
|
-
const globalDirs =
|
|
34918
|
+
const globalDirs = readdirSync13(configDir).filter((f) => {
|
|
34483
34919
|
if (!f.startsWith("connect-"))
|
|
34484
34920
|
return false;
|
|
34485
34921
|
try {
|
|
@@ -34501,7 +34937,7 @@ Available presets:
|
|
|
34501
34937
|
let profile = "default";
|
|
34502
34938
|
if (existsSync20(currentProfileFile)) {
|
|
34503
34939
|
try {
|
|
34504
|
-
profile =
|
|
34940
|
+
profile = readFileSync12(currentProfileFile, "utf-8").trim() || "default";
|
|
34505
34941
|
} catch {}
|
|
34506
34942
|
}
|
|
34507
34943
|
connectorDetails.push({ name, configured: true, authType: auth.type, profile, source: "global" });
|
|
@@ -34620,13 +35056,13 @@ Testing connector credentials...
|
|
|
34620
35056
|
const currentProfileFile = join21(connectorConfigDir, "current_profile");
|
|
34621
35057
|
if (existsSync20(currentProfileFile)) {
|
|
34622
35058
|
try {
|
|
34623
|
-
currentProfile =
|
|
35059
|
+
currentProfile = readFileSync12(currentProfileFile, "utf-8").trim() || "default";
|
|
34624
35060
|
} catch {}
|
|
34625
35061
|
}
|
|
34626
35062
|
const tokensFile = join21(connectorConfigDir, "profiles", currentProfile, "tokens.json");
|
|
34627
35063
|
if (existsSync20(tokensFile)) {
|
|
34628
35064
|
try {
|
|
34629
|
-
const tokens = JSON.parse(
|
|
35065
|
+
const tokens = JSON.parse(readFileSync12(tokensFile, "utf-8"));
|
|
34630
35066
|
const isExpired = tokens.expiresAt && Date.now() >= tokens.expiresAt - 60000;
|
|
34631
35067
|
if (isExpired && tokens.refreshToken) {
|
|
34632
35068
|
try {
|
|
@@ -34647,7 +35083,7 @@ Testing connector credentials...
|
|
|
34647
35083
|
const profileFile = join21(connectorConfigDir, "profiles", `${currentProfile}.json`);
|
|
34648
35084
|
if (existsSync20(profileFile)) {
|
|
34649
35085
|
try {
|
|
34650
|
-
const config = JSON.parse(
|
|
35086
|
+
const config = JSON.parse(readFileSync12(profileFile, "utf-8"));
|
|
34651
35087
|
apiKey = Object.values(config).find((v) => typeof v === "string" && v.length > 0);
|
|
34652
35088
|
} catch {}
|
|
34653
35089
|
}
|
|
@@ -34656,7 +35092,7 @@ Testing connector credentials...
|
|
|
34656
35092
|
const profileDirConfig = join21(connectorConfigDir, "profiles", currentProfile, "config.json");
|
|
34657
35093
|
if (existsSync20(profileDirConfig)) {
|
|
34658
35094
|
try {
|
|
34659
|
-
const config = JSON.parse(
|
|
35095
|
+
const config = JSON.parse(readFileSync12(profileDirConfig, "utf-8"));
|
|
34660
35096
|
apiKey = Object.values(config).find((v) => typeof v === "string" && v.length > 0);
|
|
34661
35097
|
} catch {}
|
|
34662
35098
|
}
|