@schuttdev/kon 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +95 -96
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -234,27 +234,37 @@ async function ensureDispatcher() {
|
|
|
234
234
|
}
|
|
235
235
|
return _dispatcher;
|
|
236
236
|
}
|
|
237
|
-
function createHttpClient(serverUrl, sessionToken) {
|
|
237
|
+
function createHttpClient(serverUrl, sessionToken, onAuthFailure) {
|
|
238
238
|
const baseUrl = serverUrl.replace(/\/$/, "");
|
|
239
|
+
let currentToken = sessionToken;
|
|
240
|
+
async function rawFetch(url, init) {
|
|
241
|
+
const dispatcher = await ensureDispatcher();
|
|
242
|
+
const fetchOpts = { ...init };
|
|
243
|
+
if (dispatcher) fetchOpts.dispatcher = dispatcher;
|
|
244
|
+
return fetch(url, fetchOpts);
|
|
245
|
+
}
|
|
246
|
+
function authHeaders() {
|
|
247
|
+
const h = {};
|
|
248
|
+
if (currentToken) h["Authorization"] = `Bearer ${currentToken}`;
|
|
249
|
+
return h;
|
|
250
|
+
}
|
|
239
251
|
async function request(path, init = {}) {
|
|
240
252
|
const headers = {
|
|
241
|
-
...init.headers ?? {}
|
|
253
|
+
...init.headers ?? {},
|
|
254
|
+
...authHeaders()
|
|
242
255
|
};
|
|
243
|
-
if (sessionToken) {
|
|
244
|
-
headers["Authorization"] = `Bearer ${sessionToken}`;
|
|
245
|
-
}
|
|
246
256
|
if (!headers["Content-Type"] && init.body && typeof init.body === "string") {
|
|
247
257
|
headers["Content-Type"] = "application/json";
|
|
248
258
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
259
|
+
let res = await rawFetch(`${baseUrl}${path}`, { ...init, headers });
|
|
260
|
+
if (res.status === 401 && onAuthFailure) {
|
|
261
|
+
const newToken = await onAuthFailure();
|
|
262
|
+
if (newToken) {
|
|
263
|
+
currentToken = newToken;
|
|
264
|
+
headers["Authorization"] = `Bearer ${newToken}`;
|
|
265
|
+
res = await rawFetch(`${baseUrl}${path}`, { ...init, headers });
|
|
266
|
+
}
|
|
256
267
|
}
|
|
257
|
-
const res = await fetch(`${baseUrl}${path}`, fetchOpts);
|
|
258
268
|
if (!res.ok) {
|
|
259
269
|
let errorBody;
|
|
260
270
|
try {
|
|
@@ -277,16 +287,20 @@ function createHttpClient(serverUrl, sessionToken) {
|
|
|
277
287
|
});
|
|
278
288
|
},
|
|
279
289
|
async delete(path) {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
headers
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
290
|
+
let res = await rawFetch(`${baseUrl}${path}`, {
|
|
291
|
+
method: "DELETE",
|
|
292
|
+
headers: authHeaders()
|
|
293
|
+
});
|
|
294
|
+
if (res.status === 401 && onAuthFailure) {
|
|
295
|
+
const newToken = await onAuthFailure();
|
|
296
|
+
if (newToken) {
|
|
297
|
+
currentToken = newToken;
|
|
298
|
+
res = await rawFetch(`${baseUrl}${path}`, {
|
|
299
|
+
method: "DELETE",
|
|
300
|
+
headers: authHeaders()
|
|
301
|
+
});
|
|
302
|
+
}
|
|
288
303
|
}
|
|
289
|
-
const res = await fetch(`${baseUrl}${path}`, fetchOpts);
|
|
290
304
|
if (!res.ok) {
|
|
291
305
|
let errorBody;
|
|
292
306
|
try {
|
|
@@ -297,20 +311,22 @@ function createHttpClient(serverUrl, sessionToken) {
|
|
|
297
311
|
}
|
|
298
312
|
},
|
|
299
313
|
async postMultipart(path, formData) {
|
|
300
|
-
|
|
301
|
-
if (sessionToken) {
|
|
302
|
-
headers["Authorization"] = `Bearer ${sessionToken}`;
|
|
303
|
-
}
|
|
304
|
-
const dispatcher = await ensureDispatcher();
|
|
305
|
-
const fetchOpts = {
|
|
314
|
+
let res = await rawFetch(`${baseUrl}${path}`, {
|
|
306
315
|
method: "POST",
|
|
307
|
-
headers,
|
|
316
|
+
headers: authHeaders(),
|
|
308
317
|
body: formData
|
|
309
|
-
};
|
|
310
|
-
if (
|
|
311
|
-
|
|
318
|
+
});
|
|
319
|
+
if (res.status === 401 && onAuthFailure) {
|
|
320
|
+
const newToken = await onAuthFailure();
|
|
321
|
+
if (newToken) {
|
|
322
|
+
currentToken = newToken;
|
|
323
|
+
res = await rawFetch(`${baseUrl}${path}`, {
|
|
324
|
+
method: "POST",
|
|
325
|
+
headers: authHeaders(),
|
|
326
|
+
body: formData
|
|
327
|
+
});
|
|
328
|
+
}
|
|
312
329
|
}
|
|
313
|
-
const res = await fetch(`${baseUrl}${path}`, fetchOpts);
|
|
314
330
|
if (!res.ok) {
|
|
315
331
|
let errorBody;
|
|
316
332
|
try {
|
|
@@ -322,16 +338,18 @@ function createHttpClient(serverUrl, sessionToken) {
|
|
|
322
338
|
return res.json();
|
|
323
339
|
},
|
|
324
340
|
async getRaw(path) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
341
|
+
let res = await rawFetch(`${baseUrl}${path}`, {
|
|
342
|
+
headers: authHeaders()
|
|
343
|
+
});
|
|
344
|
+
if (res.status === 401 && onAuthFailure) {
|
|
345
|
+
const newToken = await onAuthFailure();
|
|
346
|
+
if (newToken) {
|
|
347
|
+
currentToken = newToken;
|
|
348
|
+
res = await rawFetch(`${baseUrl}${path}`, {
|
|
349
|
+
headers: authHeaders()
|
|
350
|
+
});
|
|
351
|
+
}
|
|
333
352
|
}
|
|
334
|
-
const res = await fetch(`${baseUrl}${path}`, fetchOpts);
|
|
335
353
|
if (!res.ok) {
|
|
336
354
|
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
337
355
|
}
|
|
@@ -341,7 +359,7 @@ function createHttpClient(serverUrl, sessionToken) {
|
|
|
341
359
|
}
|
|
342
360
|
|
|
343
361
|
// ../cli/src/version.ts
|
|
344
|
-
var VERSION = "0.3.
|
|
362
|
+
var VERSION = "0.3.5";
|
|
345
363
|
|
|
346
364
|
// ../cli/src/connect.ts
|
|
347
365
|
async function connect(serverName) {
|
|
@@ -361,15 +379,26 @@ async function connect(serverName) {
|
|
|
361
379
|
throw new Error("No server configured. Run 'gigai pair' first.");
|
|
362
380
|
}
|
|
363
381
|
const { name, entry } = active;
|
|
382
|
+
const onAuthFailure = async () => {
|
|
383
|
+
try {
|
|
384
|
+
const result2 = await doRefreshSession(name, entry.server, entry.token);
|
|
385
|
+
return result2.sessionToken;
|
|
386
|
+
} catch {
|
|
387
|
+
return void 0;
|
|
388
|
+
}
|
|
389
|
+
};
|
|
364
390
|
if (entry.sessionToken && entry.sessionExpiresAt) {
|
|
365
391
|
if (Date.now() < entry.sessionExpiresAt - 5 * 60 * 1e3) {
|
|
366
392
|
const token = await checkAndUpdateServer(entry.server, entry.sessionToken, name, entry.token);
|
|
367
|
-
|
|
393
|
+
const http2 = createHttpClient(entry.server, token, onAuthFailure);
|
|
394
|
+
return { serverUrl: entry.server, sessionToken: token, http: http2 };
|
|
368
395
|
}
|
|
369
396
|
}
|
|
370
|
-
|
|
397
|
+
const result = await doRefreshSession(name, entry.server, entry.token);
|
|
398
|
+
const http = createHttpClient(entry.server, result.sessionToken, onAuthFailure);
|
|
399
|
+
return { serverUrl: entry.server, sessionToken: result.sessionToken, http };
|
|
371
400
|
}
|
|
372
|
-
async function
|
|
401
|
+
async function doRefreshSession(serverName, serverUrl, encryptedToken) {
|
|
373
402
|
const orgUuid = getOrgUUID();
|
|
374
403
|
const http = createHttpClient(serverUrl);
|
|
375
404
|
const res = await http.post("/auth/connect", {
|
|
@@ -1029,43 +1058,21 @@ if (firstArg && !firstArg.startsWith("-") && !KNOWN_COMMANDS.has(firstArg)) {
|
|
|
1029
1058
|
const toolName = firstArg;
|
|
1030
1059
|
const toolArgs = process.argv.slice(3);
|
|
1031
1060
|
try {
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
const
|
|
1036
|
-
if (
|
|
1037
|
-
const
|
|
1038
|
-
|
|
1039
|
-
const toolNames = (detail.mcpTools ?? []).map((t) => ` ${t.name} \u2014 ${t.description}`);
|
|
1040
|
-
console.log(`MCP tools for ${toolName}:
|
|
1061
|
+
const { http } = await connect();
|
|
1062
|
+
const { tool: detail } = await fetchToolDetail(http, toolName);
|
|
1063
|
+
if (detail.type === "mcp") {
|
|
1064
|
+
const mcpToolName = toolArgs[0];
|
|
1065
|
+
if (!mcpToolName) {
|
|
1066
|
+
const toolNames = (detail.mcpTools ?? []).map((t) => ` ${t.name} \u2014 ${t.description}`);
|
|
1067
|
+
console.log(`MCP tools for ${toolName}:
|
|
1041
1068
|
${toolNames.join("\n")}`);
|
|
1042
|
-
} else {
|
|
1043
|
-
const jsonArg = toolArgs.slice(1).join(" ");
|
|
1044
|
-
const args = jsonArg ? JSON.parse(jsonArg) : {};
|
|
1045
|
-
await execMcpTool(http, toolName, mcpToolName, args);
|
|
1046
|
-
}
|
|
1047
|
-
} else {
|
|
1048
|
-
await execTool(http, toolName, toolArgs);
|
|
1049
|
-
}
|
|
1050
|
-
};
|
|
1051
|
-
try {
|
|
1052
|
-
await runTool();
|
|
1053
|
-
} catch (e) {
|
|
1054
|
-
const msg = e.message;
|
|
1055
|
-
if (msg.includes("Invalid session") || msg.includes("Session expired") || msg.includes("Authorization")) {
|
|
1056
|
-
const config = await readConfig();
|
|
1057
|
-
const active = getActiveEntry(config);
|
|
1058
|
-
if (active) {
|
|
1059
|
-
const refreshed = await refreshSession(active.name, active.entry.server, active.entry.token);
|
|
1060
|
-
sessionToken = refreshed.sessionToken;
|
|
1061
|
-
http = createHttpClient(serverUrl, sessionToken);
|
|
1062
|
-
await runTool();
|
|
1063
|
-
} else {
|
|
1064
|
-
throw e;
|
|
1065
|
-
}
|
|
1066
1069
|
} else {
|
|
1067
|
-
|
|
1070
|
+
const jsonArg = toolArgs.slice(1).join(" ");
|
|
1071
|
+
const args = jsonArg ? JSON.parse(jsonArg) : {};
|
|
1072
|
+
await execMcpTool(http, toolName, mcpToolName, args);
|
|
1068
1073
|
}
|
|
1074
|
+
} else {
|
|
1075
|
+
await execTool(http, toolName, toolArgs);
|
|
1069
1076
|
}
|
|
1070
1077
|
} catch (e) {
|
|
1071
1078
|
console.error(`Error: ${e.message}`);
|
|
@@ -1098,8 +1105,7 @@ function runCitty() {
|
|
|
1098
1105
|
const listCommand = defineCommand({
|
|
1099
1106
|
meta: { name: "list", description: "List available tools" },
|
|
1100
1107
|
async run() {
|
|
1101
|
-
const {
|
|
1102
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1108
|
+
const { http } = await connect();
|
|
1103
1109
|
const tools = await fetchTools(http);
|
|
1104
1110
|
console.log(formatToolList(tools));
|
|
1105
1111
|
}
|
|
@@ -1110,8 +1116,7 @@ function runCitty() {
|
|
|
1110
1116
|
tool: { type: "positional", description: "Tool name", required: true }
|
|
1111
1117
|
},
|
|
1112
1118
|
async run({ args }) {
|
|
1113
|
-
const {
|
|
1114
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1119
|
+
const { http } = await connect();
|
|
1115
1120
|
const { tool } = await fetchToolDetail(http, args.tool);
|
|
1116
1121
|
console.log(formatToolDetail(tool));
|
|
1117
1122
|
}
|
|
@@ -1129,8 +1134,7 @@ function runCitty() {
|
|
|
1129
1134
|
file: { type: "positional", description: "File path", required: true }
|
|
1130
1135
|
},
|
|
1131
1136
|
async run({ args }) {
|
|
1132
|
-
const {
|
|
1133
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1137
|
+
const { http } = await connect();
|
|
1134
1138
|
await upload(http, args.file);
|
|
1135
1139
|
}
|
|
1136
1140
|
});
|
|
@@ -1141,8 +1145,7 @@ function runCitty() {
|
|
|
1141
1145
|
dest: { type: "positional", description: "Destination path", required: true }
|
|
1142
1146
|
},
|
|
1143
1147
|
async run({ args }) {
|
|
1144
|
-
const {
|
|
1145
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1148
|
+
const { http } = await connect();
|
|
1146
1149
|
await download(http, args.id, args.dest);
|
|
1147
1150
|
}
|
|
1148
1151
|
});
|
|
@@ -1155,8 +1158,7 @@ function runCitty() {
|
|
|
1155
1158
|
const skillCommand = defineCommand({
|
|
1156
1159
|
meta: { name: "skill", description: "Regenerate the skill zip with current tool details" },
|
|
1157
1160
|
async run() {
|
|
1158
|
-
const {
|
|
1159
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1161
|
+
const { http } = await connect();
|
|
1160
1162
|
const tools = await fetchTools(http);
|
|
1161
1163
|
console.log(`Fetching details for ${tools.length} tool(s)...`);
|
|
1162
1164
|
const toolDetails = await Promise.all(
|
|
@@ -1185,8 +1187,7 @@ Skill zip written to: ${outPath}`);
|
|
|
1185
1187
|
at: { type: "string", description: "Human-readable time (e.g. '9:00 AM tomorrow')" }
|
|
1186
1188
|
},
|
|
1187
1189
|
async run({ args }) {
|
|
1188
|
-
const {
|
|
1189
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1190
|
+
const { http } = await connect();
|
|
1190
1191
|
const rawArgs = process.argv.slice(4);
|
|
1191
1192
|
const positional = [];
|
|
1192
1193
|
let atValue = args.at;
|
|
@@ -1243,8 +1244,7 @@ Skill zip written to: ${outPath}`);
|
|
|
1243
1244
|
const cronListCommand = defineCommand({
|
|
1244
1245
|
meta: { name: "list", description: "List scheduled jobs" },
|
|
1245
1246
|
async run() {
|
|
1246
|
-
const {
|
|
1247
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1247
|
+
const { http } = await connect();
|
|
1248
1248
|
const res = await http.get("/cron");
|
|
1249
1249
|
if (res.jobs.length === 0) {
|
|
1250
1250
|
console.log("No scheduled jobs.");
|
|
@@ -1268,8 +1268,7 @@ Skill zip written to: ${outPath}`);
|
|
|
1268
1268
|
id: { type: "positional", description: "Job ID", required: true }
|
|
1269
1269
|
},
|
|
1270
1270
|
async run({ args }) {
|
|
1271
|
-
const {
|
|
1272
|
-
const http = createHttpClient(serverUrl, sessionToken);
|
|
1271
|
+
const { http } = await connect();
|
|
1273
1272
|
await http.delete(`/cron/${encodeURIComponent(args.id)}`);
|
|
1274
1273
|
console.log(`Removed: ${args.id}`);
|
|
1275
1274
|
}
|