@kraken-ai/platform 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-PPT6GGYL.js → chunk-SL6WL3X6.js} +243 -67
- package/dist/chunk-SL6WL3X6.js.map +1 -0
- package/dist/cli.js +1102 -374
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +415 -240
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1072 -368
- package/dist/index.d.ts +1072 -368
- package/dist/index.js +183 -172
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +219 -45
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +264 -28
- package/dist/server.d.ts +264 -28
- package/dist/server.js +15 -20
- package/dist/server.js.map +1 -1
- package/package.json +20 -16
- package/dist/chunk-PPT6GGYL.js.map +0 -1
- package/dist/types-_lfbhFJH.d.cts +0 -451
- package/dist/types-_lfbhFJH.d.ts +0 -451
package/dist/cli.js
CHANGED
|
@@ -1,39 +1,328 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import
|
|
4
|
+
import { execFile } from "child_process";
|
|
5
|
+
import { promisify } from "util";
|
|
6
|
+
import * as z11 from "zod";
|
|
7
|
+
|
|
8
|
+
// src/internal/secret-string.ts
|
|
9
|
+
import { inspect } from "util";
|
|
10
|
+
var SecretString = class {
|
|
11
|
+
#value;
|
|
12
|
+
constructor(value) {
|
|
13
|
+
this.#value = value;
|
|
14
|
+
}
|
|
15
|
+
unmasked() {
|
|
16
|
+
return this.#value;
|
|
17
|
+
}
|
|
18
|
+
toJSON() {
|
|
19
|
+
return "[REDACTED]";
|
|
20
|
+
}
|
|
21
|
+
toString() {
|
|
22
|
+
return "[REDACTED]";
|
|
23
|
+
}
|
|
24
|
+
[Symbol.toPrimitive]() {
|
|
25
|
+
return "[REDACTED]";
|
|
26
|
+
}
|
|
27
|
+
[inspect.custom]() {
|
|
28
|
+
return "SecretString([REDACTED])";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
var unwrapSecret = (value) => value instanceof SecretString ? value.unmasked() : value;
|
|
32
|
+
|
|
33
|
+
// src/cli/api-keys.ts
|
|
34
|
+
var DURATION_RE = /^(\d+)(h|d|y)$/;
|
|
35
|
+
var parseDuration = (input) => {
|
|
36
|
+
const match = DURATION_RE.exec(input);
|
|
37
|
+
if (!match) return null;
|
|
38
|
+
const amount = Number(match[1]);
|
|
39
|
+
const unit = match[2];
|
|
40
|
+
const now = /* @__PURE__ */ new Date();
|
|
41
|
+
switch (unit) {
|
|
42
|
+
case "h":
|
|
43
|
+
return new Date(now.getTime() + amount * 36e5);
|
|
44
|
+
case "d":
|
|
45
|
+
return new Date(now.getTime() + amount * 864e5);
|
|
46
|
+
case "y":
|
|
47
|
+
return new Date(now.getTime() + amount * 365.25 * 864e5);
|
|
48
|
+
default:
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var VALID_ENVIRONMENTS = /* @__PURE__ */ new Set(["dev", "staging", "prod"]);
|
|
53
|
+
var getAuthHeaders = (apiKey) => {
|
|
54
|
+
const secret = new SecretString(apiKey);
|
|
55
|
+
return { Authorization: `Bearer ${unwrapSecret(secret)}`, "Content-Type": "application/json" };
|
|
56
|
+
};
|
|
57
|
+
var collectErrorMessages = (err) => {
|
|
58
|
+
const parts = [];
|
|
59
|
+
let current = err;
|
|
60
|
+
while (current instanceof Error) {
|
|
61
|
+
if (current.message) parts.push(current.message);
|
|
62
|
+
current = current.cause;
|
|
63
|
+
}
|
|
64
|
+
return parts.join(": ");
|
|
65
|
+
};
|
|
66
|
+
var formatNetworkError = (err, baseUrl) => {
|
|
67
|
+
const msg = collectErrorMessages(err);
|
|
68
|
+
if (msg.includes("unknown scheme")) {
|
|
69
|
+
return `Invalid platform URL "${baseUrl}" \u2014 must start with https:// (or http:// for local dev).
|
|
70
|
+
Run \`kraken login\` to update your credentials.`;
|
|
71
|
+
}
|
|
72
|
+
if (msg.includes("ECONNREFUSED")) {
|
|
73
|
+
return `Could not connect to ${baseUrl} \u2014 is the platform running?
|
|
74
|
+
Check the URL or run \`kraken login\` to update it.`;
|
|
75
|
+
}
|
|
76
|
+
if (msg.includes("ENOTFOUND")) {
|
|
77
|
+
return `Could not resolve hostname for ${baseUrl} \u2014 check the URL.
|
|
78
|
+
Run \`kraken login\` to update your credentials.`;
|
|
79
|
+
}
|
|
80
|
+
if (msg.includes("abort") || msg.includes("TIMEOUT")) {
|
|
81
|
+
return `Request to ${baseUrl} timed out.
|
|
82
|
+
Check your network connection or try again.`;
|
|
83
|
+
}
|
|
84
|
+
return `Could not reach ${baseUrl}. Check that the platform is running and the URL is correct.
|
|
85
|
+
Run \`kraken login\` to update your credentials.`;
|
|
86
|
+
};
|
|
87
|
+
var normalizeBaseUrl = (baseUrl) => {
|
|
88
|
+
if (!/^https?:\/\//.test(baseUrl)) {
|
|
89
|
+
return `https://${baseUrl}`;
|
|
90
|
+
}
|
|
91
|
+
return baseUrl;
|
|
92
|
+
};
|
|
93
|
+
var fetchApi = async (deps, url, baseUrl, init) => {
|
|
94
|
+
const normalizedBase = normalizeBaseUrl(baseUrl);
|
|
95
|
+
const normalizedUrl = baseUrl !== normalizedBase ? url.replace(baseUrl, normalizedBase) : url;
|
|
96
|
+
try {
|
|
97
|
+
return await deps.fetch(normalizedUrl, init);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
deps.log(`Error: ${formatNetworkError(err, normalizedBase)}`);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
var handleCreate = async (parsed, deps) => {
|
|
104
|
+
const creds = deps.loadCredentials();
|
|
105
|
+
if (!creds?.apiKey || !creds?.baseUrl) {
|
|
106
|
+
deps.log("Error: not logged in. Run `kraken login` first.");
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
const name = parsed.flags.name;
|
|
110
|
+
if (!name) {
|
|
111
|
+
deps.log(
|
|
112
|
+
"Error: --name is required.\n Usage: kraken api-keys create --name <name> [--env dev] [--expires 90d]"
|
|
113
|
+
);
|
|
114
|
+
return 1;
|
|
115
|
+
}
|
|
116
|
+
const environment = parsed.flags.env ?? "dev";
|
|
117
|
+
if (!VALID_ENVIRONMENTS.has(environment)) {
|
|
118
|
+
deps.log(`Error: invalid environment "${environment}". Must be one of: dev, staging, prod.`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
let expiresAt;
|
|
122
|
+
if (parsed.flags.expires) {
|
|
123
|
+
const date = parseDuration(parsed.flags.expires);
|
|
124
|
+
if (!date) {
|
|
125
|
+
deps.log(
|
|
126
|
+
`Error: invalid duration "${parsed.flags.expires}". Use format like 90d, 24h, or 1y.`
|
|
127
|
+
);
|
|
128
|
+
return 1;
|
|
129
|
+
}
|
|
130
|
+
expiresAt = date.toISOString();
|
|
131
|
+
}
|
|
132
|
+
const res = await fetchApi(deps, `${creds.baseUrl}/api/v1/api-keys`, creds.baseUrl, {
|
|
133
|
+
method: "POST",
|
|
134
|
+
headers: getAuthHeaders(creds.apiKey),
|
|
135
|
+
body: JSON.stringify({ name, environment, expiresAt })
|
|
136
|
+
});
|
|
137
|
+
if (!res) return 1;
|
|
138
|
+
if (!res.ok) {
|
|
139
|
+
const body = await res.json();
|
|
140
|
+
deps.log(`Error: ${body.error ?? `request failed (${String(res.status)})`}`);
|
|
141
|
+
return 1;
|
|
142
|
+
}
|
|
143
|
+
const data = await res.json();
|
|
144
|
+
deps.log(`
|
|
145
|
+
API Key created successfully.
|
|
146
|
+
`);
|
|
147
|
+
deps.log(` Name: ${data.name}`);
|
|
148
|
+
deps.log(` Env: ${data.environment}`);
|
|
149
|
+
deps.log(` Key: ${data.key}`);
|
|
150
|
+
if (data.expiresAt) {
|
|
151
|
+
deps.log(` Expires: ${data.expiresAt}`);
|
|
152
|
+
}
|
|
153
|
+
deps.log(`
|
|
154
|
+
Copy this key now \u2014 it will not be shown again.
|
|
155
|
+
`);
|
|
156
|
+
return 0;
|
|
157
|
+
};
|
|
158
|
+
var handleList = async (parsed, deps) => {
|
|
159
|
+
const creds = deps.loadCredentials();
|
|
160
|
+
if (!creds?.apiKey || !creds?.baseUrl) {
|
|
161
|
+
deps.log("Error: not logged in. Run `kraken login` first.");
|
|
162
|
+
return 1;
|
|
163
|
+
}
|
|
164
|
+
const envFilter = parsed.flags.env;
|
|
165
|
+
const query = envFilter ? `?environment=${encodeURIComponent(envFilter)}` : "";
|
|
166
|
+
const res = await fetchApi(deps, `${creds.baseUrl}/api/v1/api-keys${query}`, creds.baseUrl, {
|
|
167
|
+
headers: getAuthHeaders(creds.apiKey)
|
|
168
|
+
});
|
|
169
|
+
if (!res) return 1;
|
|
170
|
+
if (!res.ok) {
|
|
171
|
+
const body = await res.json();
|
|
172
|
+
deps.log(`Error: ${body.error ?? `request failed (${String(res.status)})`}`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
const keys = await res.json();
|
|
176
|
+
if (keys.length === 0) {
|
|
177
|
+
deps.log("No API keys found. Create one with: kraken api-keys create --name <name>");
|
|
178
|
+
return 0;
|
|
179
|
+
}
|
|
180
|
+
deps.log("\n API Keys:\n");
|
|
181
|
+
deps.log(
|
|
182
|
+
" ID Name Env Key Created Last Used Expires"
|
|
183
|
+
);
|
|
184
|
+
deps.log(` ${"\u2500".repeat(150)}`);
|
|
185
|
+
for (const k of keys) {
|
|
186
|
+
const expired = k.expired ? " (expired)" : "";
|
|
187
|
+
const lastUsed = k.lastUsed ? k.lastUsed.slice(0, 10) : "never";
|
|
188
|
+
const expires = k.expiresAt ? `${k.expiresAt.slice(0, 10)}${expired}` : "never";
|
|
189
|
+
deps.log(
|
|
190
|
+
` ${k.id} ${k.name.padEnd(16)}${k.environment.padEnd(10)}${k.prefix.padEnd(23)}${k.createdAt.slice(0, 10).padEnd(20)}${lastUsed.padEnd(20)}${expires}`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
deps.log("");
|
|
194
|
+
return 0;
|
|
195
|
+
};
|
|
196
|
+
var handleRevoke = async (parsed, deps) => {
|
|
197
|
+
const creds = deps.loadCredentials();
|
|
198
|
+
if (!creds?.apiKey || !creds?.baseUrl) {
|
|
199
|
+
deps.log("Error: not logged in. Run `kraken login` first.");
|
|
200
|
+
return 1;
|
|
201
|
+
}
|
|
202
|
+
const id = parsed.positional[1];
|
|
203
|
+
if (!id) {
|
|
204
|
+
deps.log("Error: key ID is required.\n Usage: kraken api-keys revoke <id>");
|
|
205
|
+
return 1;
|
|
206
|
+
}
|
|
207
|
+
const res = await fetchApi(
|
|
208
|
+
deps,
|
|
209
|
+
`${creds.baseUrl}/api/v1/api-keys/${encodeURIComponent(id)}`,
|
|
210
|
+
creds.baseUrl,
|
|
211
|
+
{
|
|
212
|
+
method: "DELETE",
|
|
213
|
+
headers: getAuthHeaders(creds.apiKey)
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
if (!res) return 1;
|
|
217
|
+
if (res.status === 404) {
|
|
218
|
+
deps.log("Error: API key not found.");
|
|
219
|
+
return 1;
|
|
220
|
+
}
|
|
221
|
+
if (!res.ok) {
|
|
222
|
+
const body = await res.json();
|
|
223
|
+
deps.log(`Error: ${body.error ?? `request failed (${String(res.status)})`}`);
|
|
224
|
+
return 1;
|
|
225
|
+
}
|
|
226
|
+
deps.log("API key revoked successfully.");
|
|
227
|
+
return 0;
|
|
228
|
+
};
|
|
229
|
+
var handleApiKeys = async (parsed, deps) => {
|
|
230
|
+
const subcommand = parsed.positional[0];
|
|
231
|
+
switch (subcommand) {
|
|
232
|
+
case "create":
|
|
233
|
+
return handleCreate(parsed, deps);
|
|
234
|
+
case "list":
|
|
235
|
+
return handleList(parsed, deps);
|
|
236
|
+
case "revoke":
|
|
237
|
+
return handleRevoke(parsed, deps);
|
|
238
|
+
default:
|
|
239
|
+
deps.log(
|
|
240
|
+
`kraken api-keys \u2014 Manage API keys
|
|
241
|
+
|
|
242
|
+
Commands:
|
|
243
|
+
create --name <name> [--env dev] [--expires 90d] Create a new API key
|
|
244
|
+
list [--env dev|staging|prod] List API keys
|
|
245
|
+
revoke <id> Revoke an API key
|
|
246
|
+
`
|
|
247
|
+
);
|
|
248
|
+
return 0;
|
|
249
|
+
}
|
|
250
|
+
};
|
|
5
251
|
|
|
6
252
|
// src/cli/codegen.ts
|
|
7
253
|
import fs from "fs";
|
|
8
254
|
import path from "path";
|
|
9
255
|
|
|
10
|
-
//
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
256
|
+
// ../../../private-packages/platform-core/dist/qualified-name.js
|
|
257
|
+
var parse = (qualified) => {
|
|
258
|
+
const slashIndex = qualified.indexOf("/");
|
|
259
|
+
if (slashIndex === -1) {
|
|
260
|
+
throw new Error(`Expected qualified name with "/" separator, got: "${qualified}"`);
|
|
261
|
+
}
|
|
262
|
+
if (qualified.indexOf("/", slashIndex + 1) !== -1) {
|
|
263
|
+
throw new Error(`Expected exactly one "/" in qualified name, got: "${qualified}"`);
|
|
264
|
+
}
|
|
265
|
+
const repoName = qualified.slice(0, slashIndex);
|
|
266
|
+
const primitiveName = qualified.slice(slashIndex + 1);
|
|
267
|
+
if (!repoName || !primitiveName) {
|
|
268
|
+
throw new Error(`Both repo and primitive segments must be non-empty, got: "${qualified}"`);
|
|
269
|
+
}
|
|
270
|
+
return { repoName, primitiveName };
|
|
16
271
|
};
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
var cyan = code(36, 39);
|
|
23
|
-
var warn = (msg) => {
|
|
24
|
-
process.stderr.write(` ${dim("[kraken-ai:")} ${yellow("warn")}${dim("]")} ${msg}
|
|
25
|
-
`);
|
|
272
|
+
var isQualified = (name) => {
|
|
273
|
+
const slashIndex = name.indexOf("/");
|
|
274
|
+
if (slashIndex === -1 || slashIndex === 0 || slashIndex === name.length - 1)
|
|
275
|
+
return false;
|
|
276
|
+
return name.indexOf("/", slashIndex + 1) === -1;
|
|
26
277
|
};
|
|
27
278
|
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
var
|
|
279
|
+
// ../../../private-packages/platform-core/dist/types/environment.js
|
|
280
|
+
import * as z from "zod";
|
|
281
|
+
var environmentSchema = z.enum(["dev", "staging", "prod"]);
|
|
282
|
+
|
|
283
|
+
// ../../../private-packages/platform-core/dist/types/identity.js
|
|
284
|
+
import * as z2 from "zod";
|
|
285
|
+
var jitPolicySchema = z2.enum(["auto-approve", "policy-based", "require-approval"]);
|
|
286
|
+
var identityConfigSchema = z2.object({
|
|
287
|
+
basePermissions: z2.array(z2.string()),
|
|
288
|
+
requestablePermissions: z2.array(z2.string()).optional(),
|
|
289
|
+
jitPolicy: jitPolicySchema.optional(),
|
|
290
|
+
maxJitDurationMinutes: z2.number().int().positive().optional()
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// ../../../private-packages/platform-core/dist/types/notifications.js
|
|
294
|
+
import * as z3 from "zod";
|
|
295
|
+
var notificationConfigSchema = z3.object({
|
|
296
|
+
slack: z3.string().optional(),
|
|
297
|
+
onSuccess: z3.boolean().optional(),
|
|
298
|
+
onFailure: z3.boolean().optional(),
|
|
299
|
+
onTimeout: z3.boolean().optional()
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// ../../../private-packages/platform-core/dist/types/platform-agent.js
|
|
303
|
+
import * as z7 from "zod";
|
|
304
|
+
|
|
305
|
+
// ../../../private-packages/platform-core/dist/validate.js
|
|
306
|
+
var PRIMITIVE_NAME_REGEX = /^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$/;
|
|
307
|
+
var isValidPrimitiveName = (name) => name.length === 1 ? /^[a-z0-9]$/.test(name) : PRIMITIVE_NAME_REGEX.test(name);
|
|
31
308
|
var SKILL_NAME_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,62}[a-zA-Z0-9]$/;
|
|
32
309
|
var isValidSkillName = (basename) => basename.length === 1 ? /^[a-zA-Z0-9]$/.test(basename) : SKILL_NAME_REGEX.test(basename);
|
|
33
310
|
var isValidSkillId = (id) => {
|
|
34
311
|
const base = id.endsWith(".md") ? id.slice(0, -3) : id;
|
|
35
312
|
return isValidSkillName(base);
|
|
36
313
|
};
|
|
314
|
+
var isValidQualifiedName = (name) => {
|
|
315
|
+
if (!isQualified(name))
|
|
316
|
+
return false;
|
|
317
|
+
const { repoName, primitiveName } = parse(name);
|
|
318
|
+
return isValidPrimitiveName(repoName) && isValidPrimitiveName(primitiveName);
|
|
319
|
+
};
|
|
320
|
+
var isValidQualifiedSkillId = (id) => {
|
|
321
|
+
if (!isQualified(id))
|
|
322
|
+
return false;
|
|
323
|
+
const { repoName, primitiveName } = parse(id);
|
|
324
|
+
return isValidPrimitiveName(repoName) && isValidSkillId(primitiveName);
|
|
325
|
+
};
|
|
37
326
|
var TOOL_NAME_REGEX = /^[a-z][a-z0-9_-]{0,62}[a-z0-9]$/;
|
|
38
327
|
var isValidToolName = (name) => name.length === 1 ? /^[a-z]$/.test(name) : TOOL_NAME_REGEX.test(name);
|
|
39
328
|
var PROPERTY_NAME_REGEX = /^[a-zA-Z_$][a-zA-Z0-9_$]{0,254}$/;
|
|
@@ -47,38 +336,168 @@ var FORBIDDEN_PROPS = /* @__PURE__ */ new Set([
|
|
|
47
336
|
"__lookupSetter__"
|
|
48
337
|
]);
|
|
49
338
|
var isValidPropertyName = (name) => PROPERTY_NAME_REGEX.test(name) && !FORBIDDEN_PROPS.has(name);
|
|
339
|
+
|
|
340
|
+
// ../../../private-packages/platform-core/dist/types/resources.js
|
|
341
|
+
import * as z4 from "zod";
|
|
342
|
+
var resourceLimitsSchema = z4.object({
|
|
343
|
+
maxTokens: z4.number().int().positive().optional(),
|
|
344
|
+
maxCostUsd: z4.number().positive().optional(),
|
|
345
|
+
timeoutSeconds: z4.number().int().positive().optional()
|
|
346
|
+
});
|
|
347
|
+
var retryPolicySchema = z4.object({
|
|
348
|
+
maxAttempts: z4.number().int().min(1).optional(),
|
|
349
|
+
backoffSeconds: z4.number().positive().optional()
|
|
350
|
+
});
|
|
351
|
+
var concurrencyPolicySchema = z4.object({
|
|
352
|
+
maxParallelRuns: z4.number().int().min(1).optional()
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// ../../../private-packages/platform-core/dist/types/team.js
|
|
356
|
+
import * as z5 from "zod";
|
|
357
|
+
var teamConfigSchema = z5.object({
|
|
358
|
+
members: z5.array(z5.string()).min(1),
|
|
359
|
+
maxConcurrentWorkers: z5.number().int().min(1).optional(),
|
|
360
|
+
maxTokenBudgetPerWorker: z5.number().int().positive().optional(),
|
|
361
|
+
maxDurationPerWorker: z5.number().positive().optional()
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
// ../../../private-packages/platform-core/dist/types/trigger.js
|
|
365
|
+
import * as z6 from "zod";
|
|
366
|
+
var cronTriggerSchema = z6.object({
|
|
367
|
+
type: z6.literal("cron"),
|
|
368
|
+
expression: z6.string(),
|
|
369
|
+
timezone: z6.string().optional()
|
|
370
|
+
});
|
|
371
|
+
var webhookTriggerSchema = z6.object({
|
|
372
|
+
type: z6.literal("webhook"),
|
|
373
|
+
path: z6.string().startsWith("/"),
|
|
374
|
+
method: z6.enum(["POST", "GET"]).optional()
|
|
375
|
+
});
|
|
376
|
+
var eventTriggerSchema = z6.object({
|
|
377
|
+
type: z6.literal("event"),
|
|
378
|
+
source: z6.string(),
|
|
379
|
+
event: z6.string()
|
|
380
|
+
});
|
|
381
|
+
var apiTriggerSchema = z6.object({ type: z6.literal("api") });
|
|
382
|
+
var manualTriggerSchema = z6.object({ type: z6.literal("manual") });
|
|
383
|
+
var triggerConfigSchema = z6.discriminatedUnion("type", [
|
|
384
|
+
cronTriggerSchema,
|
|
385
|
+
webhookTriggerSchema,
|
|
386
|
+
eventTriggerSchema,
|
|
387
|
+
apiTriggerSchema,
|
|
388
|
+
manualTriggerSchema
|
|
389
|
+
]);
|
|
390
|
+
|
|
391
|
+
// ../../../private-packages/platform-core/dist/types/platform-agent.js
|
|
392
|
+
var thinkingLevelSchema = z7.enum(["low", "medium", "high"]);
|
|
393
|
+
var logLevelSchema = z7.enum(["silent", "debug", "info", "warn", "error"]);
|
|
394
|
+
var agentDefinitionSchema = z7.object({
|
|
395
|
+
name: z7.string().min(1),
|
|
396
|
+
model: z7.string().min(1),
|
|
397
|
+
instructions: z7.string().min(1),
|
|
398
|
+
description: z7.string().optional(),
|
|
399
|
+
skills: z7.array(z7.string()).optional(),
|
|
400
|
+
temperature: z7.number().min(0).max(2).optional(),
|
|
401
|
+
allowTemperatureOverride: z7.boolean().optional(),
|
|
402
|
+
maxOutputTokens: z7.number().int().positive().optional(),
|
|
403
|
+
thinkingLevel: thinkingLevelSchema.optional(),
|
|
404
|
+
logLevel: logLevelSchema.optional()
|
|
405
|
+
}).strict();
|
|
406
|
+
var platformAgentConfigSchema = z7.object({
|
|
407
|
+
agent: agentDefinitionSchema,
|
|
408
|
+
connectors: z7.array(z7.string()).optional(),
|
|
409
|
+
triggers: z7.array(triggerConfigSchema),
|
|
410
|
+
identity: identityConfigSchema.optional(),
|
|
411
|
+
resources: resourceLimitsSchema.optional(),
|
|
412
|
+
retries: retryPolicySchema.optional(),
|
|
413
|
+
concurrency: concurrencyPolicySchema.optional(),
|
|
414
|
+
team: teamConfigSchema.optional(),
|
|
415
|
+
notifications: notificationConfigSchema.optional(),
|
|
416
|
+
environment: environmentSchema.optional(),
|
|
417
|
+
actions: z7.array(z7.string()).optional()
|
|
418
|
+
}).strict().superRefine((data, ctx) => {
|
|
419
|
+
for (const member of data.team?.members ?? []) {
|
|
420
|
+
const valid = isQualified(member) ? isValidQualifiedName(member) : isValidPrimitiveName(member);
|
|
421
|
+
if (!valid) {
|
|
422
|
+
ctx.addIssue({
|
|
423
|
+
code: z7.ZodIssueCode.custom,
|
|
424
|
+
path: ["team", "members"],
|
|
425
|
+
message: `Invalid team member name: "${member}"`
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
for (const connector of data.connectors ?? []) {
|
|
430
|
+
const valid = isQualified(connector) ? isValidQualifiedName(connector) : isValidPrimitiveName(connector);
|
|
431
|
+
if (!valid) {
|
|
432
|
+
ctx.addIssue({
|
|
433
|
+
code: z7.ZodIssueCode.custom,
|
|
434
|
+
path: ["connectors"],
|
|
435
|
+
message: `Invalid connector name: "${connector}"`
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
for (const skill of data.agent.skills ?? []) {
|
|
440
|
+
const valid = isQualified(skill) ? isValidQualifiedSkillId(skill) : isValidSkillId(skill);
|
|
441
|
+
if (!valid) {
|
|
442
|
+
ctx.addIssue({
|
|
443
|
+
code: z7.ZodIssueCode.custom,
|
|
444
|
+
path: ["agent", "skills"],
|
|
445
|
+
message: `Invalid skill ID: "${skill}"`
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
for (const action of data.actions ?? []) {
|
|
450
|
+
const valid = isQualified(action) ? isValidQualifiedName(action) : isValidPrimitiveName(action);
|
|
451
|
+
if (!valid) {
|
|
452
|
+
ctx.addIssue({
|
|
453
|
+
code: z7.ZodIssueCode.custom,
|
|
454
|
+
path: ["actions"],
|
|
455
|
+
message: `Invalid action name: "${action}"`
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// ../../../private-packages/platform-core/dist/types/skill.js
|
|
462
|
+
import * as z8 from "zod";
|
|
463
|
+
var platformSkillInputSchema = z8.object({
|
|
464
|
+
name: z8.string().min(1),
|
|
465
|
+
description: z8.string().optional()
|
|
466
|
+
}).strict();
|
|
467
|
+
|
|
468
|
+
// src/cli/validate.ts
|
|
50
469
|
var MAX_SCHEMA_DEPTH = 20;
|
|
51
470
|
var MAX_OBJECT_BREADTH = 200;
|
|
52
471
|
var validateSchemaBundle = (bundle) => {
|
|
53
472
|
for (const agent of bundle.agents) {
|
|
54
|
-
|
|
473
|
+
assertValidPrimitive("agent id", agent.id);
|
|
55
474
|
validateJsonSchemaProperties("agent input schema", agent.input, 0);
|
|
56
475
|
validateJsonSchemaProperties("agent output schema", agent.output, 0);
|
|
57
476
|
if (agent.actions) {
|
|
58
477
|
for (const [actionName, actionSchema] of Object.entries(agent.actions)) {
|
|
59
|
-
|
|
478
|
+
assertValidPrimitive("agent action name", actionName);
|
|
60
479
|
validateJsonSchemaProperties("agent action schema", actionSchema, 0);
|
|
61
480
|
}
|
|
62
481
|
}
|
|
63
482
|
}
|
|
64
483
|
for (const query of bundle.queries) {
|
|
65
|
-
|
|
484
|
+
assertValidPrimitive("query name", query.name);
|
|
66
485
|
validateJsonSchemaProperties("query params schema", query.params, 0);
|
|
67
486
|
for (const col of query.columns) {
|
|
68
487
|
assertValidProperty("query column name", col.name);
|
|
69
488
|
}
|
|
70
489
|
}
|
|
71
490
|
for (const connector of bundle.connectors) {
|
|
72
|
-
|
|
491
|
+
assertValidPrimitive("connector id", connector.id);
|
|
73
492
|
for (const tool of connector.tools) {
|
|
74
493
|
assertValidTool("connector tool name", tool.name);
|
|
75
494
|
validateJsonSchemaProperties("connector tool parameters", tool.parameters, 0);
|
|
76
495
|
}
|
|
77
496
|
}
|
|
78
497
|
for (const pipeline of bundle.pipelines) {
|
|
79
|
-
|
|
498
|
+
assertValidPrimitive("pipeline name", pipeline.pipeline);
|
|
80
499
|
for (const query of pipeline.queries) {
|
|
81
|
-
|
|
500
|
+
assertValidPrimitive("pipeline query name", query.name);
|
|
82
501
|
validatePipelineSchema("pipeline query params", query.params, 0);
|
|
83
502
|
validatePipelineSchema("pipeline query returns", query.returns, 0);
|
|
84
503
|
}
|
|
@@ -86,32 +505,34 @@ var validateSchemaBundle = (bundle) => {
|
|
|
86
505
|
for (const skill of bundle.skills) {
|
|
87
506
|
assertValidSkill("skill id", skill.id);
|
|
88
507
|
}
|
|
508
|
+
for (const action of bundle.actions) {
|
|
509
|
+
assertValidPrimitive("action id", action.id);
|
|
510
|
+
validateJsonSchemaProperties("action schema", action.schema, 0);
|
|
511
|
+
}
|
|
89
512
|
};
|
|
90
|
-
var
|
|
91
|
-
if (!
|
|
513
|
+
var assertValidPrimitive = (label, value) => {
|
|
514
|
+
if (!isValidPrimitiveName(value) && !isValidQualifiedName(value)) {
|
|
92
515
|
throw new Error(
|
|
93
|
-
`Invalid remote schema: ${
|
|
516
|
+
`Invalid remote schema: ${label} "${value}". Must match ${PRIMITIVE_NAME_REGEX} or repo/primitive format`
|
|
94
517
|
);
|
|
95
518
|
}
|
|
96
519
|
};
|
|
97
|
-
var assertValidTool = (
|
|
520
|
+
var assertValidTool = (label, value) => {
|
|
98
521
|
if (!isValidToolName(value)) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
`Invalid remote schema: ${entityType} "${value}". Must match ${TOOL_NAME_REGEX}`
|
|
101
|
-
);
|
|
522
|
+
throw new Error(`Invalid remote schema: ${label} "${value}". Must match ${TOOL_NAME_REGEX}`);
|
|
102
523
|
}
|
|
103
524
|
};
|
|
104
|
-
var assertValidProperty = (
|
|
525
|
+
var assertValidProperty = (label, value) => {
|
|
105
526
|
if (!isValidPropertyName(value)) {
|
|
106
527
|
throw new Error(
|
|
107
|
-
`Invalid remote schema: ${
|
|
528
|
+
`Invalid remote schema: ${label} "${value}". Must match ${PROPERTY_NAME_REGEX} and not be a forbidden property`
|
|
108
529
|
);
|
|
109
530
|
}
|
|
110
531
|
};
|
|
111
|
-
var assertValidSkill = (
|
|
112
|
-
if (!isValidSkillId(value)) {
|
|
532
|
+
var assertValidSkill = (label, value) => {
|
|
533
|
+
if (!isValidSkillId(value) && !isValidQualifiedSkillId(value)) {
|
|
113
534
|
throw new Error(
|
|
114
|
-
`Invalid remote schema: ${
|
|
535
|
+
`Invalid remote schema: ${label} "${value}". Must match ${SKILL_NAME_REGEX} (with optional .md extension) or repo/skill format`
|
|
115
536
|
);
|
|
116
537
|
}
|
|
117
538
|
};
|
|
@@ -197,14 +618,10 @@ var generateTypes = (schemas, projectRoot) => {
|
|
|
197
618
|
if (!fs.existsSync(outDir)) {
|
|
198
619
|
fs.mkdirSync(outDir, { recursive: true });
|
|
199
620
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
"Migrated: removed .kraken-ai/pipelines.ts. Pipeline schemas now in pipelines.json + pipelines.d.ts."
|
|
205
|
-
);
|
|
206
|
-
}
|
|
207
|
-
fs.writeFileSync(path.join(outDir, "agents.d.ts"), generateAgentsDts(schemas.agents));
|
|
621
|
+
fs.writeFileSync(
|
|
622
|
+
path.join(outDir, "agents.d.ts"),
|
|
623
|
+
generateAgentsDts(schemas.agents, schemas.actions)
|
|
624
|
+
);
|
|
208
625
|
fs.writeFileSync(path.join(outDir, "queries.d.ts"), generateQueriesDts(schemas.queries));
|
|
209
626
|
const connectorsDtsPath = path.join(outDir, "connectors.d.ts");
|
|
210
627
|
if (schemas.connectors.length > 0) {
|
|
@@ -212,13 +629,20 @@ var generateTypes = (schemas, projectRoot) => {
|
|
|
212
629
|
} else if (fs.existsSync(connectorsDtsPath)) {
|
|
213
630
|
fs.rmSync(connectorsDtsPath);
|
|
214
631
|
}
|
|
632
|
+
const actionsDtsPath = path.join(outDir, "actions.d.ts");
|
|
633
|
+
if (schemas.actions.length > 0) {
|
|
634
|
+
fs.writeFileSync(actionsDtsPath, generateActionsDts(schemas.actions));
|
|
635
|
+
} else if (fs.existsSync(actionsDtsPath)) {
|
|
636
|
+
fs.rmSync(actionsDtsPath);
|
|
637
|
+
}
|
|
215
638
|
fs.writeFileSync(path.join(outDir, "pipelines.json"), generatePipelinesJson(schemas.pipelines));
|
|
216
639
|
fs.writeFileSync(path.join(outDir, "pipelines.d.ts"), generatePipelinesDts(schemas.pipelines));
|
|
217
640
|
const platformTypesDtsPath = path.join(outDir, "platform-types.d.ts");
|
|
218
641
|
const platformTypesDts = generatePlatformTypesDts(
|
|
219
642
|
schemas.agents,
|
|
220
643
|
schemas.connectors,
|
|
221
|
-
schemas.skills
|
|
644
|
+
schemas.skills,
|
|
645
|
+
schemas.actions
|
|
222
646
|
);
|
|
223
647
|
if (platformTypesDts) {
|
|
224
648
|
fs.writeFileSync(platformTypesDtsPath, platformTypesDts);
|
|
@@ -229,21 +653,25 @@ var generateTypes = (schemas, projectRoot) => {
|
|
|
229
653
|
path.join(outDir, "index.d.ts"),
|
|
230
654
|
generateIndexDts(
|
|
231
655
|
schemas.connectors.length > 0,
|
|
656
|
+
schemas.actions.length > 0,
|
|
232
657
|
schemas.pipelines.length > 0,
|
|
233
658
|
platformTypesDts != null
|
|
234
659
|
)
|
|
235
660
|
);
|
|
236
661
|
fs.writeFileSync(path.join(outDir, "manifest.json"), JSON.stringify(schemas, null, 2));
|
|
237
662
|
};
|
|
238
|
-
var generateAgentsDts = (agents) => {
|
|
663
|
+
var generateAgentsDts = (agents, actions) => {
|
|
664
|
+
const actionsByName = new Map(actions.map((a) => [a.name, a]));
|
|
239
665
|
const entries = agents.map((a) => {
|
|
240
666
|
const input = jsonSchemaToTsType(a.input);
|
|
241
667
|
const output = jsonSchemaToTsType(a.output);
|
|
242
|
-
const
|
|
668
|
+
const hasInlineActions = a.actions && Object.keys(a.actions).length > 0;
|
|
669
|
+
const agentActions = hasInlineActions ? a.actions : buildAgentActionsFromRefs(a, actionsByName);
|
|
670
|
+
const actionsType = generateActionsType(agentActions);
|
|
243
671
|
return ` "${a.id}": {
|
|
244
672
|
input: ${input}
|
|
245
673
|
output: ${output}
|
|
246
|
-
actions: ${
|
|
674
|
+
actions: ${actionsType}
|
|
247
675
|
}`;
|
|
248
676
|
}).join("\n");
|
|
249
677
|
return [
|
|
@@ -258,6 +686,19 @@ var generateAgentsDts = (agents) => {
|
|
|
258
686
|
``
|
|
259
687
|
].join("\n");
|
|
260
688
|
};
|
|
689
|
+
var buildAgentActionsFromRefs = (agent, actionsByName) => {
|
|
690
|
+
const actionNames = agent.config?.actions;
|
|
691
|
+
if (!actionNames || actionNames.length === 0) return void 0;
|
|
692
|
+
const result = {};
|
|
693
|
+
for (const name of actionNames) {
|
|
694
|
+
const bareName = name.includes("/") ? name.slice(name.indexOf("/") + 1) : name;
|
|
695
|
+
const actionSchema = actionsByName.get(bareName) ?? actionsByName.get(name);
|
|
696
|
+
if (actionSchema) {
|
|
697
|
+
result[name] = actionSchema.schema;
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
701
|
+
};
|
|
261
702
|
var generateActionsType = (actions) => {
|
|
262
703
|
if (!actions || Object.keys(actions).length === 0) {
|
|
263
704
|
return "Record<string, never>";
|
|
@@ -265,6 +706,20 @@ var generateActionsType = (actions) => {
|
|
|
265
706
|
const entries = Object.entries(actions).map(([name, schema]) => `"${name}": ${jsonSchemaToTsType(schema)}`).join("; ");
|
|
266
707
|
return `{ ${entries} }`;
|
|
267
708
|
};
|
|
709
|
+
var generateActionsDts = (actions) => {
|
|
710
|
+
const entries = actions.map((a) => ` "${a.name}": ${jsonSchemaToTsType(a.schema)}`).join("\n");
|
|
711
|
+
return [
|
|
712
|
+
`// Auto-generated by \`kraken generate\` \u2014 do not edit manually`,
|
|
713
|
+
`export {};`,
|
|
714
|
+
``,
|
|
715
|
+
`declare module "@kraken-ai/platform" {`,
|
|
716
|
+
` interface ActionRegistry {`,
|
|
717
|
+
entries,
|
|
718
|
+
` }`,
|
|
719
|
+
`}`,
|
|
720
|
+
``
|
|
721
|
+
].join("\n");
|
|
722
|
+
};
|
|
268
723
|
var generateQueriesDts = (queries) => {
|
|
269
724
|
const entries = queries.map((q) => {
|
|
270
725
|
const params = jsonSchemaToTsType(q.params);
|
|
@@ -301,7 +756,7 @@ ${entries}
|
|
|
301
756
|
}
|
|
302
757
|
`;
|
|
303
758
|
};
|
|
304
|
-
var generateIndexDts = (hasConnectors, hasPipelines, hasPlatformTypes) => {
|
|
759
|
+
var generateIndexDts = (hasConnectors, hasActions, hasPipelines, hasPlatformTypes) => {
|
|
305
760
|
let content = `// Auto-generated by \`kraken generate\` \u2014 do not edit manually
|
|
306
761
|
|
|
307
762
|
/// <reference path="./agents.d.ts" />
|
|
@@ -309,6 +764,10 @@ export type { QueryRegistry } from "./queries"
|
|
|
309
764
|
`;
|
|
310
765
|
if (hasConnectors) {
|
|
311
766
|
content += `export type { ConnectorId, ConnectorTools } from "./connectors"
|
|
767
|
+
`;
|
|
768
|
+
}
|
|
769
|
+
if (hasActions) {
|
|
770
|
+
content += `/// <reference path="./actions.d.ts" />
|
|
312
771
|
`;
|
|
313
772
|
}
|
|
314
773
|
if (hasPipelines) {
|
|
@@ -321,7 +780,7 @@ export type { QueryRegistry } from "./queries"
|
|
|
321
780
|
}
|
|
322
781
|
return content;
|
|
323
782
|
};
|
|
324
|
-
var generatePlatformTypesDts = (agents, connectors, skills) => {
|
|
783
|
+
var generatePlatformTypesDts = (agents, connectors, skills, actions) => {
|
|
325
784
|
const entries = [];
|
|
326
785
|
if (agents.length > 0) {
|
|
327
786
|
const ids = agents.map((a) => `"${a.id}"`).join(" | ");
|
|
@@ -335,6 +794,10 @@ var generatePlatformTypesDts = (agents, connectors, skills) => {
|
|
|
335
794
|
const ids = skills.map((s) => `"${s.id}"`).join(" | ");
|
|
336
795
|
entries.push(` skillId: ${ids};`);
|
|
337
796
|
}
|
|
797
|
+
if (actions.length > 0) {
|
|
798
|
+
const ids = actions.map((a) => `"${a.name}"`).join(" | ");
|
|
799
|
+
entries.push(` actionId: ${ids};`);
|
|
800
|
+
}
|
|
338
801
|
if (entries.length === 0) return null;
|
|
339
802
|
return [
|
|
340
803
|
`// Auto-generated by \`kraken generate\` \u2014 do not edit manually`,
|
|
@@ -514,168 +977,127 @@ var clearCredentials = () => {
|
|
|
514
977
|
|
|
515
978
|
// src/cli/discover.ts
|
|
516
979
|
import fs3 from "fs";
|
|
980
|
+
import { createRequire } from "module";
|
|
517
981
|
import path3 from "path";
|
|
518
982
|
import { pathToFileURL } from "url";
|
|
519
|
-
import * as
|
|
520
|
-
|
|
521
|
-
// src/agents/types/action.ts
|
|
522
|
-
import * as z from "zod";
|
|
523
|
-
var actionVariantConfigSchema = z.object({
|
|
524
|
-
schema: z.record(z.string(), z.unknown()),
|
|
525
|
-
webhook: z.string().url().optional(),
|
|
526
|
-
hasHandler: z.boolean()
|
|
527
|
-
});
|
|
528
|
-
var actionsConfigSchema = z.object({
|
|
529
|
-
variants: z.record(z.string(), actionVariantConfigSchema)
|
|
530
|
-
}).strict();
|
|
531
|
-
|
|
532
|
-
// src/agents/types/environment.ts
|
|
533
|
-
import * as z2 from "zod";
|
|
534
|
-
var environmentSchema = z2.enum(["dev", "staging", "prod"]);
|
|
535
|
-
|
|
536
|
-
// src/agents/types/identity.ts
|
|
537
|
-
import * as z3 from "zod";
|
|
538
|
-
var jitPolicySchema = z3.enum(["auto-approve", "policy-based", "require-approval"]);
|
|
539
|
-
var identityConfigSchema = z3.object({
|
|
540
|
-
basePermissions: z3.array(z3.string()),
|
|
541
|
-
requestablePermissions: z3.array(z3.string()).optional(),
|
|
542
|
-
jitPolicy: jitPolicySchema.optional(),
|
|
543
|
-
maxJitDurationMinutes: z3.number().int().positive().optional()
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// src/agents/types/notifications.ts
|
|
547
|
-
import * as z4 from "zod";
|
|
548
|
-
var notificationConfigSchema = z4.object({
|
|
549
|
-
slack: z4.string().optional(),
|
|
550
|
-
onSuccess: z4.boolean().optional(),
|
|
551
|
-
onFailure: z4.boolean().optional(),
|
|
552
|
-
onTimeout: z4.boolean().optional()
|
|
553
|
-
});
|
|
983
|
+
import * as z9 from "zod";
|
|
554
984
|
|
|
555
|
-
// src/
|
|
556
|
-
|
|
985
|
+
// src/cli/log.ts
|
|
986
|
+
var supportsColor = !("NO_COLOR" in process.env) && process.env.FORCE_COLOR !== "0" && (process.stderr.isTTY ?? false);
|
|
987
|
+
var code = (open, close) => {
|
|
988
|
+
const openStr = `\x1B[${open}m`;
|
|
989
|
+
const closeStr = `\x1B[${close}m`;
|
|
990
|
+
return (s) => supportsColor ? `${openStr}${s}${closeStr}` : s;
|
|
991
|
+
};
|
|
992
|
+
var bold = code(1, 22);
|
|
993
|
+
var dim = code(2, 22);
|
|
994
|
+
var red = code(31, 39);
|
|
995
|
+
var yellow = code(33, 39);
|
|
996
|
+
var green = code(32, 39);
|
|
997
|
+
var cyan = code(36, 39);
|
|
998
|
+
var warn = (msg) => {
|
|
999
|
+
process.stderr.write(` ${dim("[kraken-ai:")} ${yellow("warn")}${dim("]")} ${msg}
|
|
1000
|
+
`);
|
|
1001
|
+
};
|
|
557
1002
|
|
|
558
|
-
// src/
|
|
559
|
-
|
|
560
|
-
var
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
1003
|
+
// src/cli/discover.ts
|
|
1004
|
+
var MANIFEST_START = "---KRAKEN-MANIFEST-START---";
|
|
1005
|
+
var MANIFEST_END = "---KRAKEN-MANIFEST-END---";
|
|
1006
|
+
var skillEntrySchema = z9.object({
|
|
1007
|
+
name: z9.string().min(1),
|
|
1008
|
+
path: z9.string().min(1),
|
|
1009
|
+
content: z9.string()
|
|
564
1010
|
});
|
|
565
|
-
var
|
|
566
|
-
|
|
567
|
-
|
|
1011
|
+
var toolSpecSchema = z9.object({
|
|
1012
|
+
name: z9.string(),
|
|
1013
|
+
description: z9.string(),
|
|
1014
|
+
parameters: z9.record(z9.string(), z9.unknown()).default({}),
|
|
1015
|
+
annotations: z9.object({
|
|
1016
|
+
readOnlyHint: z9.boolean().optional(),
|
|
1017
|
+
destructiveHint: z9.boolean().optional(),
|
|
1018
|
+
idempotentHint: z9.boolean().optional()
|
|
1019
|
+
}).optional()
|
|
568
1020
|
});
|
|
569
|
-
var
|
|
570
|
-
|
|
1021
|
+
var resourceSpecSchema = z9.object({
|
|
1022
|
+
name: z9.string(),
|
|
1023
|
+
uri: z9.string(),
|
|
1024
|
+
description: z9.string(),
|
|
1025
|
+
mimeType: z9.string().optional()
|
|
571
1026
|
});
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
1027
|
+
var promptSpecSchema = z9.object({
|
|
1028
|
+
name: z9.string(),
|
|
1029
|
+
description: z9.string(),
|
|
1030
|
+
arguments: z9.array(
|
|
1031
|
+
z9.object({
|
|
1032
|
+
name: z9.string(),
|
|
1033
|
+
description: z9.string().optional(),
|
|
1034
|
+
required: z9.boolean().optional()
|
|
1035
|
+
})
|
|
1036
|
+
).optional()
|
|
580
1037
|
});
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
timezone: z7.string().optional()
|
|
588
|
-
});
|
|
589
|
-
var webhookTriggerSchema = z7.object({
|
|
590
|
-
type: z7.literal("webhook"),
|
|
591
|
-
path: z7.string().startsWith("/"),
|
|
592
|
-
method: z7.enum(["POST", "GET"]).optional()
|
|
593
|
-
});
|
|
594
|
-
var eventTriggerSchema = z7.object({
|
|
595
|
-
type: z7.literal("event"),
|
|
596
|
-
source: z7.string(),
|
|
597
|
-
event: z7.string()
|
|
1038
|
+
var connectorEntrySchema = z9.object({
|
|
1039
|
+
name: z9.string().min(1),
|
|
1040
|
+
path: z9.string().min(1),
|
|
1041
|
+
toolSpecs: z9.array(toolSpecSchema).default([]),
|
|
1042
|
+
resourceSpecs: z9.array(resourceSpecSchema).default([]),
|
|
1043
|
+
promptSpecs: z9.array(promptSpecSchema).default([])
|
|
598
1044
|
});
|
|
599
|
-
var
|
|
600
|
-
var manualTriggerSchema = z7.object({ type: z7.literal("manual") });
|
|
601
|
-
var triggerConfigSchema = z7.discriminatedUnion("type", [
|
|
602
|
-
cronTriggerSchema,
|
|
603
|
-
webhookTriggerSchema,
|
|
604
|
-
eventTriggerSchema,
|
|
605
|
-
apiTriggerSchema,
|
|
606
|
-
manualTriggerSchema
|
|
607
|
-
]);
|
|
608
|
-
|
|
609
|
-
// src/agents/types/platform-agent.ts
|
|
610
|
-
var thinkingLevelSchema = z8.enum(["low", "medium", "high"]);
|
|
611
|
-
var logLevelSchema = z8.enum(["silent", "debug", "info", "warn", "error"]);
|
|
612
|
-
var agentDefinitionSchema = z8.object({
|
|
613
|
-
name: z8.string().min(1),
|
|
614
|
-
model: z8.string().min(1),
|
|
615
|
-
instructions: z8.string().min(1),
|
|
616
|
-
description: z8.string().optional(),
|
|
617
|
-
skills: z8.array(z8.string()).optional(),
|
|
618
|
-
temperature: z8.number().min(0).max(2).optional(),
|
|
619
|
-
allowTemperatureOverride: z8.boolean().optional(),
|
|
620
|
-
maxOutputTokens: z8.number().int().positive().optional(),
|
|
621
|
-
thinkingLevel: thinkingLevelSchema.optional(),
|
|
622
|
-
logLevel: logLevelSchema.optional()
|
|
623
|
-
}).strict();
|
|
624
|
-
var platformAgentConfigSchema = z8.object({
|
|
625
|
-
agent: agentDefinitionSchema,
|
|
626
|
-
connectors: z8.array(z8.string()).optional(),
|
|
627
|
-
triggers: z8.array(triggerConfigSchema),
|
|
628
|
-
identity: identityConfigSchema.optional(),
|
|
629
|
-
resources: resourceLimitsSchema.optional(),
|
|
630
|
-
retries: retryPolicySchema.optional(),
|
|
631
|
-
concurrency: concurrencyPolicySchema.optional(),
|
|
632
|
-
team: teamConfigSchema.optional(),
|
|
633
|
-
notifications: notificationConfigSchema.optional(),
|
|
634
|
-
environment: environmentSchema.optional(),
|
|
635
|
-
actions: actionsConfigSchema.optional()
|
|
636
|
-
}).strict();
|
|
637
|
-
|
|
638
|
-
// src/agents/types/skill.ts
|
|
639
|
-
import * as z9 from "zod";
|
|
640
|
-
var platformSkillInputSchema = z9.object({
|
|
1045
|
+
var agentEntrySchema = z9.object({
|
|
641
1046
|
name: z9.string().min(1),
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
// src/cli/discover.ts
|
|
646
|
-
var MANIFEST_START = "---KRAKEN-MANIFEST-START---";
|
|
647
|
-
var MANIFEST_END = "---KRAKEN-MANIFEST-END---";
|
|
648
|
-
var skillEntrySchema = z10.object({
|
|
649
|
-
name: z10.string().min(1),
|
|
650
|
-
path: z10.string().min(1),
|
|
651
|
-
content: z10.string()
|
|
1047
|
+
entryPoint: z9.string().min(1),
|
|
1048
|
+
config: platformAgentConfigSchema
|
|
652
1049
|
});
|
|
653
|
-
var
|
|
654
|
-
|
|
655
|
-
|
|
1050
|
+
var actionConfigSchema = z9.object({
|
|
1051
|
+
schema: z9.record(z9.string(), z9.unknown()),
|
|
1052
|
+
webhook: z9.string().url().optional(),
|
|
1053
|
+
hasHandler: z9.boolean()
|
|
656
1054
|
});
|
|
657
|
-
var
|
|
658
|
-
name:
|
|
659
|
-
entryPoint:
|
|
660
|
-
config:
|
|
1055
|
+
var actionEntrySchema = z9.object({
|
|
1056
|
+
name: z9.string().min(1),
|
|
1057
|
+
entryPoint: z9.string().min(1),
|
|
1058
|
+
config: actionConfigSchema
|
|
661
1059
|
});
|
|
662
|
-
var projectManifestSchema =
|
|
663
|
-
agents:
|
|
664
|
-
skills:
|
|
665
|
-
connectors:
|
|
1060
|
+
var projectManifestSchema = z9.object({
|
|
1061
|
+
agents: z9.array(agentEntrySchema),
|
|
1062
|
+
skills: z9.array(skillEntrySchema),
|
|
1063
|
+
connectors: z9.array(connectorEntrySchema),
|
|
1064
|
+
actions: z9.array(actionEntrySchema).default([])
|
|
666
1065
|
});
|
|
667
1066
|
var isTsxAvailable = () => process.env.NODE_OPTIONS?.includes("tsx") === true;
|
|
1067
|
+
var tsxLoaded = false;
|
|
1068
|
+
var ensureTsxLoader = async (projectRoot) => {
|
|
1069
|
+
if (isTsxAvailable() || tsxLoaded) return true;
|
|
1070
|
+
if (!fs3.existsSync(path3.join(projectRoot, "node_modules", "tsx"))) return false;
|
|
1071
|
+
try {
|
|
1072
|
+
const require2 = createRequire(path3.join(projectRoot, "package.json"));
|
|
1073
|
+
const tsxEsmPath = require2.resolve("tsx/esm");
|
|
1074
|
+
await import(pathToFileURL(tsxEsmPath).href);
|
|
1075
|
+
tsxLoaded = true;
|
|
1076
|
+
return true;
|
|
1077
|
+
} catch {
|
|
1078
|
+
return false;
|
|
1079
|
+
}
|
|
1080
|
+
};
|
|
668
1081
|
var isPlatformAgentExport = (value) => value != null && typeof value === "object" && value.__type === "PlatformAgent" && "config" in value;
|
|
669
1082
|
var discoverAgents = async (projectRoot) => {
|
|
670
1083
|
const distAgentsDir = path3.join(projectRoot, "dist", "agents");
|
|
671
1084
|
const useDistAgents = fs3.existsSync(distAgentsDir) && fs3.statSync(distAgentsDir).isDirectory();
|
|
672
|
-
const agentsDir = useDistAgents ? distAgentsDir : path3.join(projectRoot, "agents");
|
|
673
|
-
const agentsDirPrefix = useDistAgents ? "dist/agents" : "agents";
|
|
1085
|
+
const agentsDir = useDistAgents ? distAgentsDir : path3.join(projectRoot, "src", "agents");
|
|
1086
|
+
const agentsDirPrefix = useDistAgents ? "dist/agents" : "src/agents";
|
|
674
1087
|
if (!fs3.existsSync(agentsDir) || !fs3.statSync(agentsDir).isDirectory()) {
|
|
675
1088
|
return [];
|
|
676
1089
|
}
|
|
677
|
-
const tsxEnabled =
|
|
678
|
-
const
|
|
1090
|
+
const tsxEnabled = await ensureTsxLoader(projectRoot);
|
|
1091
|
+
const allFiles = fs3.readdirSync(agentsDir);
|
|
1092
|
+
const files = allFiles.filter((f) => f.endsWith(".js") || f.endsWith(".mjs") || tsxEnabled && f.endsWith(".ts")).sort();
|
|
1093
|
+
if (!tsxEnabled) {
|
|
1094
|
+
const skippedTs = allFiles.filter((f) => f.endsWith(".ts"));
|
|
1095
|
+
if (skippedTs.length > 0) {
|
|
1096
|
+
warn(
|
|
1097
|
+
`Found ${String(skippedTs.length)} .ts agent file(s) but tsx is not available. Install tsx as a devDependency or build your project first.`
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
679
1101
|
const seen = /* @__PURE__ */ new Map();
|
|
680
1102
|
for (const file of files) {
|
|
681
1103
|
const filePath = path3.join(agentsDir, file);
|
|
@@ -698,7 +1120,7 @@ var discoverAgents = async (projectRoot) => {
|
|
|
698
1120
|
};
|
|
699
1121
|
var MAX_SKILL_SIZE = 100 * 1024;
|
|
700
1122
|
var discoverSkills = (projectRoot) => {
|
|
701
|
-
const skillsDir = path3.join(projectRoot, "skills");
|
|
1123
|
+
const skillsDir = path3.join(projectRoot, "src", "skills");
|
|
702
1124
|
if (!fs3.existsSync(skillsDir) || !fs3.statSync(skillsDir).isDirectory()) {
|
|
703
1125
|
return [];
|
|
704
1126
|
}
|
|
@@ -706,41 +1128,111 @@ var discoverSkills = (projectRoot) => {
|
|
|
706
1128
|
const skills = [];
|
|
707
1129
|
for (const file of files) {
|
|
708
1130
|
if (!file.endsWith(".md")) {
|
|
709
|
-
warn(`Skipping skills/${file}: skill files must have a .md extension.`);
|
|
1131
|
+
warn(`Skipping src/skills/${file}: skill files must have a .md extension.`);
|
|
710
1132
|
continue;
|
|
711
1133
|
}
|
|
712
1134
|
const basename = file.replace(/\.md$/, "");
|
|
713
1135
|
if (!isValidSkillName(basename)) {
|
|
714
1136
|
warn(
|
|
715
|
-
`Skipping skills/${file}: name must match [a-zA-Z0-9-] (letters, digits, hyphens only).`
|
|
1137
|
+
`Skipping src/skills/${file}: name must match [a-zA-Z0-9-] (letters, digits, hyphens only).`
|
|
716
1138
|
);
|
|
717
1139
|
continue;
|
|
718
1140
|
}
|
|
719
1141
|
const filePath = path3.join(skillsDir, file);
|
|
720
1142
|
const stat = fs3.statSync(filePath);
|
|
721
1143
|
if (stat.size > MAX_SKILL_SIZE) {
|
|
722
|
-
warn(`Skipping skills/${file}: exceeds ${MAX_SKILL_SIZE} byte limit.`);
|
|
1144
|
+
warn(`Skipping src/skills/${file}: exceeds ${MAX_SKILL_SIZE} byte limit.`);
|
|
723
1145
|
continue;
|
|
724
1146
|
}
|
|
725
1147
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
726
|
-
skills.push({ name: file, path: `skills/${file}`, content });
|
|
1148
|
+
skills.push({ name: file, path: `src/skills/${file}`, content });
|
|
727
1149
|
}
|
|
728
1150
|
return skills;
|
|
729
1151
|
};
|
|
730
|
-
var
|
|
1152
|
+
var isPlatformConnectorExport = (value) => value != null && typeof value === "object" && value.__type === "PlatformConnector";
|
|
1153
|
+
var serializeToolParameters = (input) => {
|
|
1154
|
+
try {
|
|
1155
|
+
return z9.toJSONSchema(input, { target: "draft-2020-12" });
|
|
1156
|
+
} catch {
|
|
1157
|
+
warn("Failed to serialize tool parameters via z.toJSONSchema(); falling back to {}");
|
|
1158
|
+
return {};
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
var extractConnectorSpecs = (conn) => {
|
|
1162
|
+
const toolSpecs = [];
|
|
1163
|
+
if (conn.tools) {
|
|
1164
|
+
for (const [name, tool] of Object.entries(conn.tools)) {
|
|
1165
|
+
const spec = {
|
|
1166
|
+
name,
|
|
1167
|
+
description: tool.description,
|
|
1168
|
+
parameters: serializeToolParameters(tool.input)
|
|
1169
|
+
};
|
|
1170
|
+
if (tool.annotations) {
|
|
1171
|
+
const { readOnlyHint, destructiveHint, idempotentHint } = tool.annotations;
|
|
1172
|
+
if (readOnlyHint !== void 0 || destructiveHint !== void 0 || idempotentHint !== void 0) {
|
|
1173
|
+
spec.annotations = {
|
|
1174
|
+
...readOnlyHint !== void 0 ? { readOnlyHint } : {},
|
|
1175
|
+
...destructiveHint !== void 0 ? { destructiveHint } : {},
|
|
1176
|
+
...idempotentHint !== void 0 ? { idempotentHint } : {}
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
toolSpecs.push(spec);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
const resourceSpecs = [];
|
|
1184
|
+
if (conn.resources) {
|
|
1185
|
+
for (const [name, resource] of Object.entries(conn.resources)) {
|
|
1186
|
+
const spec = {
|
|
1187
|
+
name,
|
|
1188
|
+
uri: resource.uri,
|
|
1189
|
+
description: resource.description
|
|
1190
|
+
};
|
|
1191
|
+
if (resource.mimeType) {
|
|
1192
|
+
spec.mimeType = resource.mimeType;
|
|
1193
|
+
}
|
|
1194
|
+
resourceSpecs.push(spec);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
const promptSpecs = [];
|
|
1198
|
+
if (conn.prompts) {
|
|
1199
|
+
for (const [name, prompt] of Object.entries(conn.prompts)) {
|
|
1200
|
+
const spec = {
|
|
1201
|
+
name,
|
|
1202
|
+
description: prompt.description
|
|
1203
|
+
};
|
|
1204
|
+
if (prompt.arguments) {
|
|
1205
|
+
spec.arguments = [...prompt.arguments];
|
|
1206
|
+
}
|
|
1207
|
+
promptSpecs.push(spec);
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
return { toolSpecs, resourceSpecs, promptSpecs };
|
|
1211
|
+
};
|
|
1212
|
+
var findConnectorEntryPoint = (connDir, tsxEnabled) => {
|
|
1213
|
+
const candidates = ["index.js", "index.mjs"];
|
|
1214
|
+
if (tsxEnabled) candidates.push("index.ts");
|
|
1215
|
+
for (const candidate of candidates) {
|
|
1216
|
+
const filePath = path3.join(connDir, candidate);
|
|
1217
|
+
if (fs3.existsSync(filePath)) return filePath;
|
|
1218
|
+
}
|
|
1219
|
+
return void 0;
|
|
1220
|
+
};
|
|
1221
|
+
var discoverConnectors = async (projectRoot) => {
|
|
731
1222
|
const distConnectorsDir = path3.join(projectRoot, "dist", "connectors");
|
|
732
1223
|
const useDistConnectors = fs3.existsSync(distConnectorsDir) && fs3.statSync(distConnectorsDir).isDirectory();
|
|
733
|
-
const connectorsDir = useDistConnectors ? distConnectorsDir : path3.join(projectRoot, "connectors");
|
|
734
|
-
const connectorsDirPrefix = useDistConnectors ? "dist/connectors" : "connectors";
|
|
1224
|
+
const connectorsDir = useDistConnectors ? distConnectorsDir : path3.join(projectRoot, "src", "connectors");
|
|
1225
|
+
const connectorsDirPrefix = useDistConnectors ? "dist/connectors" : "src/connectors";
|
|
735
1226
|
if (!fs3.existsSync(connectorsDir) || !fs3.statSync(connectorsDir).isDirectory()) {
|
|
736
1227
|
return [];
|
|
737
1228
|
}
|
|
1229
|
+
const tsxEnabled = await ensureTsxLoader(projectRoot);
|
|
738
1230
|
const entries = fs3.readdirSync(connectorsDir, { withFileTypes: true });
|
|
739
1231
|
const connectors = [];
|
|
740
1232
|
for (const entry of entries) {
|
|
741
1233
|
if (!entry.isDirectory()) continue;
|
|
742
1234
|
const name = entry.name;
|
|
743
|
-
if (!
|
|
1235
|
+
if (!isValidPrimitiveName(name)) {
|
|
744
1236
|
warn(
|
|
745
1237
|
`Skipping ${connectorsDirPrefix}/${name}: name must match [a-z0-9-] (lowercase, digits, hyphens only).`
|
|
746
1238
|
);
|
|
@@ -755,23 +1247,109 @@ var discoverConnectors = (projectRoot) => {
|
|
|
755
1247
|
if (!hasPackageJson && !hasDockerfile && !hasIndexJs && !hasIndexMjs && !hasIndexTs) {
|
|
756
1248
|
continue;
|
|
757
1249
|
}
|
|
758
|
-
|
|
1250
|
+
const connectorPath = `${connectorsDirPrefix}/${name}/`;
|
|
1251
|
+
const entryPoint = findConnectorEntryPoint(connDir, tsxEnabled);
|
|
1252
|
+
if (!entryPoint) {
|
|
1253
|
+
connectors.push({
|
|
1254
|
+
name,
|
|
1255
|
+
path: connectorPath,
|
|
1256
|
+
toolSpecs: [],
|
|
1257
|
+
resourceSpecs: [],
|
|
1258
|
+
promptSpecs: []
|
|
1259
|
+
});
|
|
1260
|
+
continue;
|
|
1261
|
+
}
|
|
1262
|
+
try {
|
|
1263
|
+
const mod = await import(pathToFileURL(entryPoint).href);
|
|
1264
|
+
const exported = mod.default;
|
|
1265
|
+
if (isPlatformConnectorExport(exported)) {
|
|
1266
|
+
const specs = extractConnectorSpecs(exported);
|
|
1267
|
+
connectors.push({ name, path: connectorPath, ...specs });
|
|
1268
|
+
} else {
|
|
1269
|
+
connectors.push({
|
|
1270
|
+
name,
|
|
1271
|
+
path: connectorPath,
|
|
1272
|
+
toolSpecs: [],
|
|
1273
|
+
resourceSpecs: [],
|
|
1274
|
+
promptSpecs: []
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
} catch (err) {
|
|
1278
|
+
warn(
|
|
1279
|
+
`Skipping introspection for ${connectorsDirPrefix}/${name}: ${err instanceof Error ? err.message : String(err)}`
|
|
1280
|
+
);
|
|
1281
|
+
connectors.push({
|
|
1282
|
+
name,
|
|
1283
|
+
path: connectorPath,
|
|
1284
|
+
toolSpecs: [],
|
|
1285
|
+
resourceSpecs: [],
|
|
1286
|
+
promptSpecs: []
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
759
1289
|
}
|
|
760
1290
|
return connectors.sort((a, b) => a.name.localeCompare(b.name));
|
|
761
1291
|
};
|
|
1292
|
+
var isPlatformActionExport = (value) => value != null && typeof value === "object" && value.__type === "PlatformAction" && "name" in value && "config" in value;
|
|
1293
|
+
var discoverActions = async (projectRoot) => {
|
|
1294
|
+
const distActionsDir = path3.join(projectRoot, "dist", "actions");
|
|
1295
|
+
const useDistActions = fs3.existsSync(distActionsDir) && fs3.statSync(distActionsDir).isDirectory();
|
|
1296
|
+
const actionsDir = useDistActions ? distActionsDir : path3.join(projectRoot, "src", "actions");
|
|
1297
|
+
const actionsDirPrefix = useDistActions ? "dist/actions" : "src/actions";
|
|
1298
|
+
if (!fs3.existsSync(actionsDir) || !fs3.statSync(actionsDir).isDirectory()) {
|
|
1299
|
+
return [];
|
|
1300
|
+
}
|
|
1301
|
+
const tsxEnabled = await ensureTsxLoader(projectRoot);
|
|
1302
|
+
const allFiles = fs3.readdirSync(actionsDir);
|
|
1303
|
+
const files = allFiles.filter((f) => f.endsWith(".js") || f.endsWith(".mjs") || tsxEnabled && f.endsWith(".ts")).sort();
|
|
1304
|
+
if (!tsxEnabled) {
|
|
1305
|
+
const skippedTs = allFiles.filter((f) => f.endsWith(".ts"));
|
|
1306
|
+
if (skippedTs.length > 0) {
|
|
1307
|
+
warn(
|
|
1308
|
+
`Found ${String(skippedTs.length)} .ts action file(s) but tsx is not available. Install tsx as a devDependency or build your project first.`
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1313
|
+
for (const file of files) {
|
|
1314
|
+
const filePath = path3.join(actionsDir, file);
|
|
1315
|
+
try {
|
|
1316
|
+
const mod = await import(pathToFileURL(filePath).href);
|
|
1317
|
+
const exported = mod.default;
|
|
1318
|
+
if (isPlatformActionExport(exported) && !seen.has(exported.name)) {
|
|
1319
|
+
if (!isValidPrimitiveName(exported.name)) {
|
|
1320
|
+
warn(
|
|
1321
|
+
`Skipping ${actionsDirPrefix}/${file}: action name "${exported.name}" must match [a-z0-9-] (lowercase, digits, hyphens only).`
|
|
1322
|
+
);
|
|
1323
|
+
continue;
|
|
1324
|
+
}
|
|
1325
|
+
seen.set(exported.name, {
|
|
1326
|
+
name: exported.name,
|
|
1327
|
+
entryPoint: `${actionsDirPrefix}/${file}`,
|
|
1328
|
+
config: exported.config
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
} catch (err) {
|
|
1332
|
+
warn(
|
|
1333
|
+
`Skipping ${actionsDirPrefix}/${file}: ${err instanceof Error ? err.message : String(err)}`
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
return [...seen.values()];
|
|
1338
|
+
};
|
|
762
1339
|
var discoverProject = async (projectRoot) => {
|
|
763
1340
|
const discovered = await discoverAgents(projectRoot);
|
|
764
1341
|
const agents = [];
|
|
765
1342
|
for (const { config, entryPoint } of discovered) {
|
|
766
1343
|
const name = config.agent.name;
|
|
767
|
-
if (!
|
|
768
|
-
throw new Error(`Invalid agent name: "${name}". Names must match ${
|
|
1344
|
+
if (!isValidPrimitiveName(name)) {
|
|
1345
|
+
throw new Error(`Invalid agent name: "${name}". Names must match ${PRIMITIVE_NAME_REGEX}`);
|
|
769
1346
|
}
|
|
770
1347
|
agents.push({ name, entryPoint, config });
|
|
771
1348
|
}
|
|
772
1349
|
const skills = discoverSkills(projectRoot);
|
|
773
|
-
const connectors = discoverConnectors(projectRoot);
|
|
774
|
-
|
|
1350
|
+
const connectors = await discoverConnectors(projectRoot);
|
|
1351
|
+
const actions = await discoverActions(projectRoot);
|
|
1352
|
+
return { agents, skills, connectors, actions };
|
|
775
1353
|
};
|
|
776
1354
|
var emitManifest = (manifest) => {
|
|
777
1355
|
process.stdout.write(`${MANIFEST_START}
|
|
@@ -840,52 +1418,58 @@ var pick = async (label, items) => {
|
|
|
840
1418
|
};
|
|
841
1419
|
|
|
842
1420
|
// src/platform/types.ts
|
|
843
|
-
import * as
|
|
844
|
-
var jsonSchemaValue =
|
|
845
|
-
var agentSchemaValidator =
|
|
846
|
-
id:
|
|
847
|
-
name:
|
|
1421
|
+
import * as z10 from "zod";
|
|
1422
|
+
var jsonSchemaValue = z10.record(z10.string(), z10.unknown());
|
|
1423
|
+
var agentSchemaValidator = z10.object({
|
|
1424
|
+
id: z10.string(),
|
|
1425
|
+
name: z10.string(),
|
|
848
1426
|
input: jsonSchemaValue,
|
|
849
1427
|
output: jsonSchemaValue,
|
|
850
|
-
actions:
|
|
1428
|
+
actions: z10.record(z10.string(), jsonSchemaValue).optional()
|
|
851
1429
|
}).passthrough();
|
|
852
|
-
var queryColumnValidator =
|
|
853
|
-
name:
|
|
854
|
-
type:
|
|
855
|
-
description:
|
|
1430
|
+
var queryColumnValidator = z10.object({
|
|
1431
|
+
name: z10.string(),
|
|
1432
|
+
type: z10.string(),
|
|
1433
|
+
description: z10.string().optional()
|
|
856
1434
|
}).passthrough();
|
|
857
|
-
var querySchemaValidator =
|
|
858
|
-
name:
|
|
1435
|
+
var querySchemaValidator = z10.object({
|
|
1436
|
+
name: z10.string(),
|
|
859
1437
|
params: jsonSchemaValue,
|
|
860
|
-
columns:
|
|
1438
|
+
columns: z10.array(queryColumnValidator)
|
|
861
1439
|
}).passthrough();
|
|
862
|
-
var connectorToolValidator =
|
|
863
|
-
name:
|
|
864
|
-
description:
|
|
1440
|
+
var connectorToolValidator = z10.object({
|
|
1441
|
+
name: z10.string(),
|
|
1442
|
+
description: z10.string(),
|
|
865
1443
|
parameters: jsonSchemaValue
|
|
866
1444
|
}).passthrough();
|
|
867
|
-
var connectorSchemaValidator =
|
|
868
|
-
id:
|
|
869
|
-
tools:
|
|
1445
|
+
var connectorSchemaValidator = z10.object({
|
|
1446
|
+
id: z10.string(),
|
|
1447
|
+
tools: z10.array(connectorToolValidator)
|
|
870
1448
|
}).passthrough();
|
|
871
|
-
var skillSchemaValidator =
|
|
872
|
-
id:
|
|
873
|
-
name:
|
|
874
|
-
description:
|
|
1449
|
+
var skillSchemaValidator = z10.object({
|
|
1450
|
+
id: z10.string(),
|
|
1451
|
+
name: z10.string(),
|
|
1452
|
+
description: z10.string().optional()
|
|
875
1453
|
}).passthrough();
|
|
876
|
-
var
|
|
877
|
-
|
|
878
|
-
|
|
1454
|
+
var actionSchemaValidator = z10.object({
|
|
1455
|
+
id: z10.string(),
|
|
1456
|
+
name: z10.string(),
|
|
1457
|
+
schema: z10.record(z10.string(), z10.unknown()),
|
|
1458
|
+
hasHandler: z10.boolean()
|
|
1459
|
+
}).passthrough();
|
|
1460
|
+
var pipelineQuerySchemaValidator = z10.object({
|
|
1461
|
+
name: z10.string(),
|
|
1462
|
+
description: z10.string(),
|
|
879
1463
|
params: jsonSchemaValue,
|
|
880
1464
|
returns: jsonSchemaValue
|
|
881
1465
|
}).passthrough();
|
|
882
|
-
var pipelineSchemaValidator =
|
|
883
|
-
pipeline:
|
|
884
|
-
queries:
|
|
1466
|
+
var pipelineSchemaValidator = z10.object({
|
|
1467
|
+
pipeline: z10.string(),
|
|
1468
|
+
queries: z10.array(pipelineQuerySchemaValidator)
|
|
885
1469
|
}).passthrough();
|
|
886
1470
|
|
|
887
1471
|
// src/cli.ts
|
|
888
|
-
var COMMANDS = /* @__PURE__ */ new Set(["login", "generate", "logout", "discover", "
|
|
1472
|
+
var COMMANDS = /* @__PURE__ */ new Set(["login", "generate", "logout", "discover", "dev", "api-keys"]);
|
|
889
1473
|
var parseArgs = (args) => {
|
|
890
1474
|
const command = args[0];
|
|
891
1475
|
if (!command || command === "--help" || !COMMANDS.has(command)) {
|
|
@@ -915,16 +1499,15 @@ var parseArgs = (args) => {
|
|
|
915
1499
|
var runCommand = async (parsed, deps) => {
|
|
916
1500
|
switch (parsed.command) {
|
|
917
1501
|
case "login":
|
|
918
|
-
|
|
919
|
-
return 0;
|
|
1502
|
+
return handleLogin(parsed, deps);
|
|
920
1503
|
case "generate":
|
|
921
1504
|
return handleGenerate(parsed, deps);
|
|
922
1505
|
case "dev":
|
|
923
1506
|
return handleDev(parsed, deps);
|
|
1507
|
+
case "api-keys":
|
|
1508
|
+
return handleApiKeys(parsed, deps);
|
|
924
1509
|
case "discover":
|
|
925
1510
|
return handleDiscover(parsed, deps);
|
|
926
|
-
case "init":
|
|
927
|
-
return handleInit(parsed, deps);
|
|
928
1511
|
case "logout":
|
|
929
1512
|
handleLogout(deps);
|
|
930
1513
|
return 0;
|
|
@@ -935,29 +1518,131 @@ var runCommand = async (parsed, deps) => {
|
|
|
935
1518
|
return 0;
|
|
936
1519
|
}
|
|
937
1520
|
};
|
|
1521
|
+
var DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
1522
|
+
var LOGIN_TIMEOUT_MS = 16 * 60 * 1e3;
|
|
1523
|
+
var MAX_TRANSIENT_FAILURES = 3;
|
|
938
1524
|
var handleLogin = async (parsed, deps) => {
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
return;
|
|
1525
|
+
const baseUrl = parsed.flags.url ?? await deps.prompt("Platform URL: ");
|
|
1526
|
+
if (!baseUrl || !/^https?:\/\//.test(baseUrl)) {
|
|
1527
|
+
deps.log("Error: a valid HTTP(S) URL is required.");
|
|
1528
|
+
return 1;
|
|
944
1529
|
}
|
|
945
|
-
|
|
946
|
-
|
|
1530
|
+
let deviceCodeRes;
|
|
1531
|
+
try {
|
|
1532
|
+
const res = await deps.fetch(`${baseUrl}/api/cli/device-code`, { method: "POST" });
|
|
1533
|
+
if (!res.ok) {
|
|
1534
|
+
deps.log(`Error: device code request failed (HTTP ${String(res.status)})`);
|
|
1535
|
+
return 1;
|
|
1536
|
+
}
|
|
1537
|
+
deviceCodeRes = await res.json();
|
|
1538
|
+
} catch (err) {
|
|
1539
|
+
deps.log(
|
|
1540
|
+
`Error: could not reach ${baseUrl} \u2014 ${err instanceof Error ? err.message : String(err)}`
|
|
1541
|
+
);
|
|
1542
|
+
return 1;
|
|
1543
|
+
}
|
|
1544
|
+
const { deviceCode, verificationUri, userCode } = deviceCodeRes;
|
|
1545
|
+
if (!deviceCode || !verificationUri || !userCode || deviceCodeRes.interval == null) {
|
|
1546
|
+
deps.log("Error: invalid device code response from server.");
|
|
1547
|
+
return 1;
|
|
1548
|
+
}
|
|
1549
|
+
deps.log(`
|
|
1550
|
+
Your device code: ${bold(userCode)}
|
|
1551
|
+
`);
|
|
1552
|
+
deps.log(` Opening ${verificationUri}`);
|
|
1553
|
+
deps.log(` ${dim("If the browser doesn't open, visit the URL manually.")}
|
|
1554
|
+
`);
|
|
1555
|
+
void deps.openUrl(verificationUri).catch(() => {
|
|
1556
|
+
});
|
|
1557
|
+
let interval = deviceCodeRes.interval;
|
|
1558
|
+
const deadline = Date.now() + LOGIN_TIMEOUT_MS;
|
|
1559
|
+
let transientFailures = 0;
|
|
1560
|
+
while (Date.now() < deadline) {
|
|
1561
|
+
await sleep(interval * 1e3);
|
|
1562
|
+
let tokenRes;
|
|
1563
|
+
try {
|
|
1564
|
+
const res = await deps.fetch(`${baseUrl}/api/cli/token`, {
|
|
1565
|
+
method: "POST",
|
|
1566
|
+
headers: { "Content-Type": "application/json" },
|
|
1567
|
+
body: JSON.stringify({ deviceCode, grant_type: DEVICE_CODE_GRANT_TYPE })
|
|
1568
|
+
});
|
|
1569
|
+
if (res.status >= 500) {
|
|
1570
|
+
transientFailures++;
|
|
1571
|
+
if (transientFailures >= MAX_TRANSIENT_FAILURES) {
|
|
1572
|
+
deps.log("Error: server returned repeated errors. Please try again later.");
|
|
1573
|
+
return 1;
|
|
1574
|
+
}
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
1578
|
+
if (!contentType.includes("json")) {
|
|
1579
|
+
transientFailures++;
|
|
1580
|
+
if (transientFailures >= MAX_TRANSIENT_FAILURES) {
|
|
1581
|
+
deps.log("Error: server returned unexpected response format.");
|
|
1582
|
+
return 1;
|
|
1583
|
+
}
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
tokenRes = await res.json();
|
|
1587
|
+
transientFailures = 0;
|
|
1588
|
+
} catch {
|
|
1589
|
+
transientFailures++;
|
|
1590
|
+
if (transientFailures >= MAX_TRANSIENT_FAILURES) {
|
|
1591
|
+
deps.log("Error: could not reach server. Please check your network and try again.");
|
|
1592
|
+
return 1;
|
|
1593
|
+
}
|
|
1594
|
+
continue;
|
|
1595
|
+
}
|
|
1596
|
+
if (tokenRes.error === "authorization_pending") {
|
|
1597
|
+
continue;
|
|
1598
|
+
}
|
|
1599
|
+
if (tokenRes.error === "slow_down") {
|
|
1600
|
+
interval += 5;
|
|
1601
|
+
continue;
|
|
1602
|
+
}
|
|
1603
|
+
if (tokenRes.error === "access_denied") {
|
|
1604
|
+
deps.log("Authorization denied.");
|
|
1605
|
+
return 1;
|
|
1606
|
+
}
|
|
1607
|
+
if (tokenRes.error === "expired_token") {
|
|
1608
|
+
deps.log("Device code expired. Please run `kraken login` again.");
|
|
1609
|
+
return 1;
|
|
1610
|
+
}
|
|
1611
|
+
if (tokenRes.accessToken) {
|
|
1612
|
+
deps.saveCredentials({ apiKey: tokenRes.accessToken, baseUrl });
|
|
1613
|
+
const who = tokenRes.user?.email ? ` as ${tokenRes.user.email}` : "";
|
|
1614
|
+
deps.log(`Logged in${who}. Credentials saved.`);
|
|
1615
|
+
return 0;
|
|
1616
|
+
}
|
|
1617
|
+
deps.log(`Error: ${tokenRes.error ?? "unknown error"}`);
|
|
1618
|
+
return 1;
|
|
1619
|
+
}
|
|
1620
|
+
deps.log("Error: login timed out. Please try again.");
|
|
1621
|
+
return 1;
|
|
947
1622
|
};
|
|
1623
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
948
1624
|
var emptySchemaBundle = {
|
|
949
1625
|
agents: [],
|
|
950
1626
|
queries: [],
|
|
951
1627
|
connectors: [],
|
|
952
1628
|
pipelines: [],
|
|
953
|
-
skills: []
|
|
1629
|
+
skills: [],
|
|
1630
|
+
actions: []
|
|
954
1631
|
};
|
|
955
1632
|
var fetchRemoteSchemas = async (creds, deps) => {
|
|
956
|
-
const
|
|
1633
|
+
const apiKey = new SecretString(creds.apiKey);
|
|
1634
|
+
const headers = { Authorization: `Bearer ${unwrapSecret(apiKey)}` };
|
|
957
1635
|
const controller = new AbortController();
|
|
958
1636
|
const timeout = setTimeout(() => controller.abort(), 1e4);
|
|
959
1637
|
try {
|
|
960
|
-
const endpoints = [
|
|
1638
|
+
const endpoints = [
|
|
1639
|
+
"agents",
|
|
1640
|
+
"queries",
|
|
1641
|
+
"connectors",
|
|
1642
|
+
"pipelines",
|
|
1643
|
+
"skills",
|
|
1644
|
+
"actions"
|
|
1645
|
+
];
|
|
961
1646
|
const responses = await Promise.all(
|
|
962
1647
|
endpoints.map(
|
|
963
1648
|
(ep) => deps.fetch(`${creds.baseUrl}/api/v1/schema/${ep}`, { headers, signal: controller.signal }).then(async (res) => {
|
|
@@ -968,26 +1653,27 @@ var fetchRemoteSchemas = async (creds, deps) => {
|
|
|
968
1653
|
}).catch(() => null)
|
|
969
1654
|
)
|
|
970
1655
|
);
|
|
971
|
-
const [agentsRes, queriesRes, connectorsRes, pipelinesRes, skillsRes] = responses;
|
|
1656
|
+
const [agentsRes, queriesRes, connectorsRes, pipelinesRes, skillsRes, actionsRes] = responses;
|
|
972
1657
|
const allFailed = responses.every((r) => !r?.ok);
|
|
973
1658
|
if (allFailed) {
|
|
974
1659
|
warn(`Could not reach platform at ${creds.baseUrl}. Generating from local definitions only.`);
|
|
975
|
-
return emptySchemaBundle;
|
|
1660
|
+
return { bundle: emptySchemaBundle, reachable: false };
|
|
976
1661
|
}
|
|
977
|
-
const agents = parseEndpointData(agentsRes,
|
|
978
|
-
const queries = parseEndpointData(queriesRes,
|
|
1662
|
+
const agents = parseEndpointData(agentsRes, z11.array(agentSchemaValidator), "agents");
|
|
1663
|
+
const queries = parseEndpointData(queriesRes, z11.array(querySchemaValidator), "queries");
|
|
979
1664
|
const connectors = parseEndpointData(
|
|
980
1665
|
connectorsRes,
|
|
981
|
-
|
|
1666
|
+
z11.array(connectorSchemaValidator),
|
|
982
1667
|
"connectors"
|
|
983
1668
|
);
|
|
984
1669
|
const pipelines = parseEndpointData(
|
|
985
1670
|
pipelinesRes,
|
|
986
|
-
|
|
1671
|
+
z11.array(pipelineSchemaValidator),
|
|
987
1672
|
"pipelines"
|
|
988
1673
|
);
|
|
989
|
-
const skills = parseEndpointData(skillsRes,
|
|
990
|
-
|
|
1674
|
+
const skills = parseEndpointData(skillsRes, z11.array(skillSchemaValidator), "skills");
|
|
1675
|
+
const actions = parseEndpointData(actionsRes, z11.array(actionSchemaValidator), "actions");
|
|
1676
|
+
return { bundle: { agents, queries, connectors, pipelines, skills, actions }, reachable: true };
|
|
991
1677
|
} finally {
|
|
992
1678
|
clearTimeout(timeout);
|
|
993
1679
|
}
|
|
@@ -998,24 +1684,85 @@ var parseEndpointData = (res, validator, endpointName) => {
|
|
|
998
1684
|
const result = validator.safeParse(data);
|
|
999
1685
|
if (!result.success) {
|
|
1000
1686
|
throw new Error(
|
|
1001
|
-
`Invalid remote schema from ${endpointName} endpoint: ${
|
|
1687
|
+
`Invalid remote schema from ${endpointName} endpoint: ${z11.prettifyError(result.error)}`
|
|
1002
1688
|
);
|
|
1003
1689
|
}
|
|
1004
1690
|
return result.data;
|
|
1005
1691
|
};
|
|
1006
|
-
var
|
|
1007
|
-
|
|
1008
|
-
const
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1692
|
+
var execFileAsync = promisify(execFile);
|
|
1693
|
+
var parseGitRemoteFullName = (url) => {
|
|
1694
|
+
const match = url.match(/[:/]([^/:]+\/[^/.]+?)(?:\.git)?\s*$/);
|
|
1695
|
+
return match?.[1] ?? null;
|
|
1696
|
+
};
|
|
1697
|
+
var getGitRemoteFullName = async (cwd) => {
|
|
1698
|
+
try {
|
|
1699
|
+
const { stdout } = await execFileAsync("git", ["remote", "get-url", "origin"], { cwd });
|
|
1700
|
+
return parseGitRemoteFullName(stdout.trim());
|
|
1701
|
+
} catch {
|
|
1702
|
+
return null;
|
|
1703
|
+
}
|
|
1704
|
+
};
|
|
1705
|
+
var resolveRepoName = async (fullName, creds, deps) => {
|
|
1706
|
+
const apiKey = new SecretString(creds.apiKey);
|
|
1707
|
+
try {
|
|
1708
|
+
const res = await deps.fetch(
|
|
1709
|
+
`${creds.baseUrl}/api/v1/schema/repo-name?fullName=${encodeURIComponent(fullName)}`,
|
|
1710
|
+
{ headers: { Authorization: `Bearer ${unwrapSecret(apiKey)}` } }
|
|
1711
|
+
);
|
|
1712
|
+
if (!res.ok) return null;
|
|
1713
|
+
const data = await res.json();
|
|
1714
|
+
return data.name;
|
|
1715
|
+
} catch {
|
|
1716
|
+
return null;
|
|
1717
|
+
}
|
|
1718
|
+
};
|
|
1719
|
+
var mergeLocalAndRemote = (local, remote, repoName) => {
|
|
1720
|
+
const localAgentNames = new Set(local.agents.map((a) => a.name));
|
|
1721
|
+
const localConnectorNames = new Set(local.connectors.map((c) => c.name));
|
|
1722
|
+
const localSkillNames = new Set(local.skills.map((s) => s.name));
|
|
1723
|
+
const localActionNames = new Set(local.actions.map((a) => a.name));
|
|
1724
|
+
const localAgents = local.agents.map((a) => ({
|
|
1725
|
+
id: a.name,
|
|
1726
|
+
name: a.name,
|
|
1727
|
+
input: {},
|
|
1728
|
+
output: {},
|
|
1729
|
+
config: a.config
|
|
1730
|
+
}));
|
|
1731
|
+
const localSkills = local.skills.map((s) => ({
|
|
1732
|
+
id: s.name,
|
|
1733
|
+
name: s.name
|
|
1734
|
+
}));
|
|
1735
|
+
const localConnectors = local.connectors.map((c) => ({
|
|
1736
|
+
id: c.name,
|
|
1737
|
+
tools: []
|
|
1738
|
+
}));
|
|
1739
|
+
const localActions = local.actions.map((a) => ({
|
|
1740
|
+
id: a.name,
|
|
1741
|
+
name: a.name,
|
|
1742
|
+
schema: a.config.schema,
|
|
1743
|
+
hasHandler: a.config.hasHandler
|
|
1744
|
+
}));
|
|
1745
|
+
const isSameRepoLocal = (remoteId, localNames) => {
|
|
1746
|
+
const slashIdx = remoteId.indexOf("/");
|
|
1747
|
+
if (slashIdx === -1) return localNames.has(remoteId);
|
|
1748
|
+
const remoteRepo = remoteId.slice(0, slashIdx);
|
|
1749
|
+
const bareName = remoteId.slice(slashIdx + 1);
|
|
1750
|
+
if (!localNames.has(bareName)) return false;
|
|
1751
|
+
return repoName !== null && remoteRepo === repoName;
|
|
1752
|
+
};
|
|
1753
|
+
const remoteOnlyAgents = remote.agents.filter((a) => !isSameRepoLocal(a.id, localAgentNames));
|
|
1754
|
+
const remoteOnlyConnectors = remote.connectors.filter(
|
|
1755
|
+
(c) => !isSameRepoLocal(c.id, localConnectorNames)
|
|
1756
|
+
);
|
|
1757
|
+
const remoteOnlySkills = remote.skills.filter((s) => !isSameRepoLocal(s.id, localSkillNames));
|
|
1758
|
+
const remoteOnlyActions = remote.actions.filter((a) => !isSameRepoLocal(a.id, localActionNames));
|
|
1013
1759
|
return {
|
|
1014
|
-
agents: [...
|
|
1760
|
+
agents: [...localAgents, ...remoteOnlyAgents],
|
|
1015
1761
|
queries: remote.queries,
|
|
1016
|
-
connectors: [...
|
|
1762
|
+
connectors: [...localConnectors, ...remoteOnlyConnectors],
|
|
1017
1763
|
pipelines: remote.pipelines,
|
|
1018
|
-
skills: [...
|
|
1764
|
+
skills: [...localSkills, ...remoteOnlySkills],
|
|
1765
|
+
actions: [...localActions, ...remoteOnlyActions]
|
|
1019
1766
|
};
|
|
1020
1767
|
};
|
|
1021
1768
|
var handleGenerate = async (parsed, deps) => {
|
|
@@ -1029,22 +1776,30 @@ var handleGenerate = async (parsed, deps) => {
|
|
|
1029
1776
|
}
|
|
1030
1777
|
const creds = deps.loadCredentials();
|
|
1031
1778
|
let remote;
|
|
1779
|
+
let remoteReachable = false;
|
|
1780
|
+
let repoName = null;
|
|
1032
1781
|
if (creds?.apiKey && creds?.baseUrl) {
|
|
1033
1782
|
try {
|
|
1034
|
-
|
|
1783
|
+
const result = await fetchRemoteSchemas(creds, deps);
|
|
1784
|
+
remote = result.bundle;
|
|
1785
|
+
remoteReachable = result.reachable;
|
|
1035
1786
|
} catch (err) {
|
|
1036
1787
|
deps.log(
|
|
1037
1788
|
`Error fetching remote schemas: ${err instanceof Error ? err.message : String(err)}`
|
|
1038
1789
|
);
|
|
1039
1790
|
return 1;
|
|
1040
1791
|
}
|
|
1792
|
+
const fullName = await getGitRemoteFullName(outDir);
|
|
1793
|
+
if (fullName) {
|
|
1794
|
+
repoName = await resolveRepoName(fullName, creds, deps);
|
|
1795
|
+
}
|
|
1041
1796
|
} else {
|
|
1042
1797
|
warn(
|
|
1043
1798
|
"Not logged in. Generating from local definitions only. Run `kraken login` to sync with the platform."
|
|
1044
1799
|
);
|
|
1045
1800
|
remote = emptySchemaBundle;
|
|
1046
1801
|
}
|
|
1047
|
-
const bundle = mergeLocalAndRemote(manifest, remote);
|
|
1802
|
+
const bundle = mergeLocalAndRemote(manifest, remote, repoName);
|
|
1048
1803
|
if ("check" in parsed.flags) {
|
|
1049
1804
|
const { mkdtempSync, readFileSync, rmSync } = await import("fs");
|
|
1050
1805
|
const { join } = await import("path");
|
|
@@ -1061,11 +1816,10 @@ var handleGenerate = async (parsed, deps) => {
|
|
|
1061
1816
|
const files = [
|
|
1062
1817
|
"pipelines.json",
|
|
1063
1818
|
"pipelines.d.ts",
|
|
1064
|
-
"pipelines.ts",
|
|
1065
|
-
// stale file detection — should not exist after migration
|
|
1066
1819
|
"agents.d.ts",
|
|
1067
1820
|
"queries.d.ts",
|
|
1068
1821
|
"connectors.d.ts",
|
|
1822
|
+
"actions.d.ts",
|
|
1069
1823
|
"platform-types.d.ts",
|
|
1070
1824
|
"index.d.ts",
|
|
1071
1825
|
"manifest.json"
|
|
@@ -1097,9 +1851,49 @@ var handleGenerate = async (parsed, deps) => {
|
|
|
1097
1851
|
deps.log(`Error generating types: ${err instanceof Error ? err.message : String(err)}`);
|
|
1098
1852
|
return 1;
|
|
1099
1853
|
}
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
|
|
1854
|
+
const localNames = {
|
|
1855
|
+
agents: new Set(manifest.agents.map((a) => a.name)),
|
|
1856
|
+
connectors: new Set(manifest.connectors.map((c) => c.name)),
|
|
1857
|
+
skills: new Set(manifest.skills.map((s) => s.name)),
|
|
1858
|
+
actions: new Set(manifest.actions.map((a) => a.name))
|
|
1859
|
+
};
|
|
1860
|
+
const matchesLocalSummary = (remoteId, names) => {
|
|
1861
|
+
const slashIdx = remoteId.indexOf("/");
|
|
1862
|
+
if (slashIdx !== -1) {
|
|
1863
|
+
return names.has(remoteId.slice(slashIdx + 1));
|
|
1864
|
+
}
|
|
1865
|
+
return names.has(remoteId);
|
|
1866
|
+
};
|
|
1867
|
+
const remoteOnlyAgents = remote.agents.filter(
|
|
1868
|
+
(a) => !matchesLocalSummary(a.id, localNames.agents)
|
|
1869
|
+
);
|
|
1870
|
+
const remoteOnlyConnectors = remote.connectors.filter(
|
|
1871
|
+
(c) => !matchesLocalSummary(c.id, localNames.connectors)
|
|
1872
|
+
);
|
|
1873
|
+
const remoteOnlySkills = remote.skills.filter(
|
|
1874
|
+
(s) => !matchesLocalSummary(s.id, localNames.skills)
|
|
1875
|
+
);
|
|
1876
|
+
const remoteOnlyActions = remote.actions.filter(
|
|
1877
|
+
(a) => !matchesLocalSummary(a.id, localNames.actions)
|
|
1878
|
+
);
|
|
1879
|
+
const lines = [];
|
|
1880
|
+
lines.push(` ${dim("[kraken-ai]")} ${bold("Generated types:")}`);
|
|
1881
|
+
for (const a of manifest.agents) lines.push(` agent ${a.name}`);
|
|
1882
|
+
for (const a of remoteOnlyAgents) lines.push(` agent ${a.id} (remote)`);
|
|
1883
|
+
for (const c of manifest.connectors) lines.push(` connector ${c.name}`);
|
|
1884
|
+
for (const c of remoteOnlyConnectors) lines.push(` connector ${c.id} (remote)`);
|
|
1885
|
+
for (const s of manifest.skills) lines.push(` skill ${s.name}`);
|
|
1886
|
+
for (const s of remoteOnlySkills) lines.push(` skill ${s.id} (remote)`);
|
|
1887
|
+
for (const a of manifest.actions) lines.push(` action ${a.name}`);
|
|
1888
|
+
for (const a of remoteOnlyActions) lines.push(` action ${a.id} (remote)`);
|
|
1889
|
+
if (bundle.queries.length > 0) lines.push(` queries ${String(bundle.queries.length)}`);
|
|
1890
|
+
if (bundle.pipelines.length > 0) lines.push(` pipelines ${String(bundle.pipelines.length)}`);
|
|
1891
|
+
const hasRemote = remoteOnlyAgents.length + remoteOnlyConnectors.length + remoteOnlySkills.length + remoteOnlyActions.length > 0;
|
|
1892
|
+
if (!hasRemote && remoteReachable) {
|
|
1893
|
+
lines.push("");
|
|
1894
|
+
lines.push(" All platform entities are defined locally. No remote-only dependencies.");
|
|
1895
|
+
}
|
|
1896
|
+
deps.log(lines.join("\n"));
|
|
1103
1897
|
return 0;
|
|
1104
1898
|
};
|
|
1105
1899
|
var safeReadFile = (readFileSync, filePath) => {
|
|
@@ -1123,7 +1917,7 @@ var buildDevBootstrap = (fileUrl, file) => [
|
|
|
1123
1917
|
].join("\n");
|
|
1124
1918
|
var discoverAgentFiles = async () => {
|
|
1125
1919
|
const { readdirSync, existsSync } = await import("fs");
|
|
1126
|
-
const agentsDir = "agents";
|
|
1920
|
+
const agentsDir = "src/agents";
|
|
1127
1921
|
if (!existsSync(agentsDir)) return [];
|
|
1128
1922
|
return readdirSync(agentsDir).filter((f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".mjs")).sort();
|
|
1129
1923
|
};
|
|
@@ -1132,7 +1926,9 @@ var handleDev = async (parsed, deps) => {
|
|
|
1132
1926
|
if (!name) {
|
|
1133
1927
|
const agents = await discoverAgentFiles();
|
|
1134
1928
|
if (agents.length === 0) {
|
|
1135
|
-
deps.log(
|
|
1929
|
+
deps.log(
|
|
1930
|
+
"No agent files found in src/agents/. Create one or pass a name: kraken dev <agent>"
|
|
1931
|
+
);
|
|
1136
1932
|
return 1;
|
|
1137
1933
|
}
|
|
1138
1934
|
if (agents.length === 1) {
|
|
@@ -1144,7 +1940,7 @@ var handleDev = async (parsed, deps) => {
|
|
|
1144
1940
|
}
|
|
1145
1941
|
}
|
|
1146
1942
|
if (!name) return 1;
|
|
1147
|
-
const file = name.includes("/") ? name : `agents/${name}`;
|
|
1943
|
+
const file = name.includes("/") ? name : `src/agents/${name}`;
|
|
1148
1944
|
const { spawn } = await import("child_process");
|
|
1149
1945
|
const { resolve } = await import("path");
|
|
1150
1946
|
const { pathToFileURL: pathToFileURL2 } = await import("url");
|
|
@@ -1161,9 +1957,11 @@ var handleDev = async (parsed, deps) => {
|
|
|
1161
1957
|
var handleDiscover = async (parsed, deps) => {
|
|
1162
1958
|
const dir = parsed.flags.dir ?? process.cwd();
|
|
1163
1959
|
const manifest = await deps.discoverProject(dir);
|
|
1164
|
-
const total = manifest.agents.length + manifest.skills.length + manifest.connectors.length;
|
|
1960
|
+
const total = manifest.agents.length + manifest.skills.length + manifest.connectors.length + manifest.actions.length;
|
|
1165
1961
|
if (total === 0) {
|
|
1166
|
-
deps.log(
|
|
1962
|
+
deps.log(
|
|
1963
|
+
"No entities found in src/agents/, src/skills/, src/connectors/, or src/actions/ directories."
|
|
1964
|
+
);
|
|
1167
1965
|
return 1;
|
|
1168
1966
|
}
|
|
1169
1967
|
if ("emit" in parsed.flags) {
|
|
@@ -1173,89 +1971,6 @@ var handleDiscover = async (parsed, deps) => {
|
|
|
1173
1971
|
}
|
|
1174
1972
|
return 0;
|
|
1175
1973
|
};
|
|
1176
|
-
var handleInit = async (parsed, deps) => {
|
|
1177
|
-
const name = parsed.flags.name ?? await deps.prompt("Project name: ");
|
|
1178
|
-
if (!name) {
|
|
1179
|
-
deps.log("Error: project name is required.");
|
|
1180
|
-
return 1;
|
|
1181
|
-
}
|
|
1182
|
-
const { writeFileSync, mkdirSync } = await import("fs");
|
|
1183
|
-
const { join } = await import("path");
|
|
1184
|
-
const root = join(process.cwd(), name);
|
|
1185
|
-
mkdirSync(join(root, "agents"), { recursive: true });
|
|
1186
|
-
mkdirSync(join(root, "skills"), { recursive: true });
|
|
1187
|
-
mkdirSync(join(root, "connectors"), { recursive: true });
|
|
1188
|
-
writeFileSync(
|
|
1189
|
-
join(root, "package.json"),
|
|
1190
|
-
JSON.stringify(
|
|
1191
|
-
{
|
|
1192
|
-
name,
|
|
1193
|
-
private: true,
|
|
1194
|
-
type: "module",
|
|
1195
|
-
scripts: { build: "tsc" },
|
|
1196
|
-
dependencies: {
|
|
1197
|
-
"kraken-ai": "latest",
|
|
1198
|
-
"@kraken-ai/platform": "latest"
|
|
1199
|
-
},
|
|
1200
|
-
devDependencies: {
|
|
1201
|
-
typescript: "^5"
|
|
1202
|
-
}
|
|
1203
|
-
},
|
|
1204
|
-
null,
|
|
1205
|
-
2
|
|
1206
|
-
)
|
|
1207
|
-
);
|
|
1208
|
-
writeFileSync(
|
|
1209
|
-
join(root, "tsconfig.json"),
|
|
1210
|
-
JSON.stringify(
|
|
1211
|
-
{
|
|
1212
|
-
compilerOptions: {
|
|
1213
|
-
target: "ES2022",
|
|
1214
|
-
module: "NodeNext",
|
|
1215
|
-
moduleResolution: "nodenext",
|
|
1216
|
-
resolveJsonModule: true,
|
|
1217
|
-
strict: true,
|
|
1218
|
-
outDir: "dist",
|
|
1219
|
-
rootDir: ".",
|
|
1220
|
-
declaration: true,
|
|
1221
|
-
esModuleInterop: true,
|
|
1222
|
-
skipLibCheck: true
|
|
1223
|
-
},
|
|
1224
|
-
include: ["agents", "skills", "connectors"]
|
|
1225
|
-
},
|
|
1226
|
-
null,
|
|
1227
|
-
2
|
|
1228
|
-
)
|
|
1229
|
-
);
|
|
1230
|
-
writeFileSync(
|
|
1231
|
-
join(root, "agents", "my-agent.ts"),
|
|
1232
|
-
`import { definePlatformAgent } from "@kraken-ai/platform";
|
|
1233
|
-
|
|
1234
|
-
export default definePlatformAgent({
|
|
1235
|
-
agent: {
|
|
1236
|
-
name: "my-agent",
|
|
1237
|
-
model: "google/gemini-2.5-flash-preview-05-20",
|
|
1238
|
-
instructions: "You are a helpful assistant.",
|
|
1239
|
-
},
|
|
1240
|
-
triggers: [{ type: "manual" }],
|
|
1241
|
-
});
|
|
1242
|
-
`
|
|
1243
|
-
);
|
|
1244
|
-
writeFileSync(join(root, ".gitignore"), `node_modules/
|
|
1245
|
-
dist/
|
|
1246
|
-
.kraken-ai/
|
|
1247
|
-
data/
|
|
1248
|
-
.env
|
|
1249
|
-
`);
|
|
1250
|
-
deps.log(`Created project at ${root}/`);
|
|
1251
|
-
deps.log(`
|
|
1252
|
-
cd ${name}
|
|
1253
|
-
pnpm install
|
|
1254
|
-
kraken login
|
|
1255
|
-
kraken generate
|
|
1256
|
-
`);
|
|
1257
|
-
return 0;
|
|
1258
|
-
};
|
|
1259
1974
|
var handleLogout = (deps) => {
|
|
1260
1975
|
deps.clearCredentials();
|
|
1261
1976
|
deps.log("Credentials cleared.");
|
|
@@ -1267,23 +1982,20 @@ kraken \u2014 Kraken AI Platform CLI
|
|
|
1267
1982
|
|
|
1268
1983
|
Commands:
|
|
1269
1984
|
dev Run an agent locally with an interactive REPL
|
|
1270
|
-
[agent] Agent filename, e.g. researcher.ts (optional \u2014 picks from agents/ if omitted)
|
|
1985
|
+
[agent] Agent filename, e.g. researcher.ts (optional \u2014 picks from src/agents/ if omitted)
|
|
1271
1986
|
|
|
1272
|
-
login
|
|
1987
|
+
login Authenticate via browser-based device authorization
|
|
1273
1988
|
--url <platform-url> Platform instance URL
|
|
1274
|
-
|
|
1989
|
+
|
|
1990
|
+
api-keys Manage API keys for server-side SDK authentication
|
|
1991
|
+
create --name <name> [--expires 90d] Create a new API key
|
|
1992
|
+
list List all API keys
|
|
1993
|
+
revoke <id> Revoke an API key
|
|
1275
1994
|
|
|
1276
1995
|
generate Discover local entities and fetch remote schemas to generate types
|
|
1277
1996
|
--dir <path> Project root / output directory (default: cwd)
|
|
1278
1997
|
--check Check if types are up-to-date (exit 1 if stale)
|
|
1279
1998
|
|
|
1280
|
-
discover Scan agents/, skills/, connectors/ and output project manifest
|
|
1281
|
-
--dir <path> Project root (default: cwd)
|
|
1282
|
-
--emit Output with sentinel markers (for orchestrator)
|
|
1283
|
-
|
|
1284
|
-
init Create a new Kraken project
|
|
1285
|
-
--name <project-name> Project name
|
|
1286
|
-
|
|
1287
1999
|
logout Clear stored credentials
|
|
1288
2000
|
|
|
1289
2001
|
Environment variables:
|
|
@@ -1302,6 +2014,21 @@ var readlinePrompt = async (question) => {
|
|
|
1302
2014
|
});
|
|
1303
2015
|
});
|
|
1304
2016
|
};
|
|
2017
|
+
var openUrlImpl = async (url) => {
|
|
2018
|
+
if (!/^https?:\/\//.test(url)) return;
|
|
2019
|
+
const { platform } = await import("os");
|
|
2020
|
+
try {
|
|
2021
|
+
const p = platform();
|
|
2022
|
+
if (p === "darwin") {
|
|
2023
|
+
await execFileAsync("open", [url]);
|
|
2024
|
+
} else if (p === "win32") {
|
|
2025
|
+
await execFileAsync("cmd", ["/c", "start", "", url]);
|
|
2026
|
+
} else {
|
|
2027
|
+
await execFileAsync("xdg-open", [url]);
|
|
2028
|
+
}
|
|
2029
|
+
} catch {
|
|
2030
|
+
}
|
|
2031
|
+
};
|
|
1305
2032
|
var main = async () => {
|
|
1306
2033
|
const parsed = parseArgs(process.argv.slice(2));
|
|
1307
2034
|
const exitCode = await runCommand(parsed, {
|
|
@@ -1312,7 +2039,8 @@ var main = async () => {
|
|
|
1312
2039
|
discoverProject,
|
|
1313
2040
|
fetch: globalThis.fetch,
|
|
1314
2041
|
prompt: readlinePrompt,
|
|
1315
|
-
log: console.log
|
|
2042
|
+
log: console.log,
|
|
2043
|
+
openUrl: openUrlImpl
|
|
1316
2044
|
});
|
|
1317
2045
|
if (exitCode !== 0) process.exit(exitCode);
|
|
1318
2046
|
};
|