@okrlinkhub/agent-factory 0.2.12 → 0.2.14
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/README.md +2 -0
- package/dist/client/index.d.ts +36 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +81 -2
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +126 -4
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/config.d.ts.map +1 -1
- package/dist/component/config.js +5 -0
- package/dist/component/config.js.map +1 -1
- package/dist/component/lib.d.ts +1 -1
- package/dist/component/lib.d.ts.map +1 -1
- package/dist/component/lib.js +1 -1
- package/dist/component/lib.js.map +1 -1
- package/dist/component/queue.d.ts +113 -4
- package/dist/component/queue.d.ts.map +1 -1
- package/dist/component/queue.js +565 -10
- package/dist/component/queue.js.map +1 -1
- package/dist/component/schema.d.ts +99 -29
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +49 -4
- package/dist/component/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +82 -2
- package/src/component/_generated/component.ts +168 -4
- package/src/component/config.ts +5 -0
- package/src/component/lib.test.ts +175 -0
- package/src/component/lib.ts +3 -0
- package/src/component/queue.ts +662 -10
- package/src/component/schema.ts +64 -12
package/dist/component/queue.js
CHANGED
|
@@ -42,6 +42,20 @@ const bridgeRuntimeConfigValidator = v.object({
|
|
|
42
42
|
serviceKey: v.union(v.null(), v.string()),
|
|
43
43
|
serviceKeySecretRef: v.union(v.null(), v.string()),
|
|
44
44
|
});
|
|
45
|
+
const messageRuntimeConfigValidator = v.object({
|
|
46
|
+
systemPrompt: v.optional(v.string()),
|
|
47
|
+
});
|
|
48
|
+
const globalSkillStatusValidator = v.union(v.literal("active"), v.literal("disabled"));
|
|
49
|
+
const globalSkillReleaseChannelValidator = v.union(v.literal("stable"), v.literal("canary"));
|
|
50
|
+
const globalSkillModuleFormatValidator = v.union(v.literal("esm"), v.literal("cjs"));
|
|
51
|
+
const globalSkillManifestItemValidator = v.object({
|
|
52
|
+
slug: v.string(),
|
|
53
|
+
version: v.string(),
|
|
54
|
+
moduleFormat: globalSkillModuleFormatValidator,
|
|
55
|
+
entryPoint: v.string(),
|
|
56
|
+
sourceJs: v.string(),
|
|
57
|
+
sha256: v.string(),
|
|
58
|
+
});
|
|
45
59
|
const BRIDGE_SECRET_REFS = {
|
|
46
60
|
serviceKey: "agent-bridge.serviceKey",
|
|
47
61
|
baseUrl: "agent-bridge.baseUrl",
|
|
@@ -49,6 +63,10 @@ const BRIDGE_SECRET_REFS = {
|
|
|
49
63
|
serviceId: "agent-bridge.serviceId",
|
|
50
64
|
appKey: "agent-bridge.appKey",
|
|
51
65
|
};
|
|
66
|
+
const RUNTIME_CONFIG_KEYS = {
|
|
67
|
+
provider: "provider",
|
|
68
|
+
message: "message",
|
|
69
|
+
};
|
|
52
70
|
export const enqueueMessage = mutation({
|
|
53
71
|
args: {
|
|
54
72
|
conversationId: v.string(),
|
|
@@ -63,6 +81,10 @@ export const enqueueMessage = mutation({
|
|
|
63
81
|
returns: v.id("messageQueue"),
|
|
64
82
|
handler: async (ctx, args) => {
|
|
65
83
|
const nowMs = args.nowMs ?? Date.now();
|
|
84
|
+
const messageRuntimeConfigRow = await ctx.db
|
|
85
|
+
.query("runtimeConfig")
|
|
86
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
87
|
+
.unique();
|
|
66
88
|
const profile = await ctx.db
|
|
67
89
|
.query("agentProfiles")
|
|
68
90
|
.withIndex("by_agentKey", (q) => q.eq("agentKey", args.agentKey))
|
|
@@ -82,6 +104,7 @@ export const enqueueMessage = mutation({
|
|
|
82
104
|
}
|
|
83
105
|
const payload = {
|
|
84
106
|
...args.payload,
|
|
107
|
+
messageText: appendSystemPromptToMessage(args.payload.messageText, messageRuntimeConfigRow?.messageConfig?.systemPrompt),
|
|
85
108
|
providerUserId: providerUserIdStr,
|
|
86
109
|
metadata: {
|
|
87
110
|
...(args.payload.metadata ?? {}),
|
|
@@ -188,9 +211,9 @@ export const upsertAgentProfile = mutation({
|
|
|
188
211
|
agentKey: v.string(),
|
|
189
212
|
providerUserId: v.optional(v.string()),
|
|
190
213
|
version: v.string(),
|
|
191
|
-
soulMd: v.string(),
|
|
214
|
+
soulMd: v.optional(v.string()),
|
|
192
215
|
clientMd: v.optional(v.string()),
|
|
193
|
-
skills: v.array(v.string()),
|
|
216
|
+
skills: v.optional(v.array(v.string())),
|
|
194
217
|
secretsRef: v.array(v.string()),
|
|
195
218
|
bridgeConfig: v.optional(bridgeProfileConfigValidator),
|
|
196
219
|
enabled: v.boolean(),
|
|
@@ -211,6 +234,74 @@ export const upsertAgentProfile = mutation({
|
|
|
211
234
|
return existing._id;
|
|
212
235
|
},
|
|
213
236
|
});
|
|
237
|
+
export const clearDeprecatedAgentProfileFields = mutation({
|
|
238
|
+
args: {
|
|
239
|
+
dryRun: v.optional(v.boolean()),
|
|
240
|
+
},
|
|
241
|
+
returns: v.object({
|
|
242
|
+
dryRun: v.boolean(),
|
|
243
|
+
scanned: v.number(),
|
|
244
|
+
updated: v.number(),
|
|
245
|
+
unchanged: v.number(),
|
|
246
|
+
clearedProviderUserId: v.number(),
|
|
247
|
+
clearedSoulMd: v.number(),
|
|
248
|
+
clearedClientMd: v.number(),
|
|
249
|
+
clearedSkills: v.number(),
|
|
250
|
+
updatedAgentKeys: v.array(v.string()),
|
|
251
|
+
}),
|
|
252
|
+
handler: async (ctx, args) => {
|
|
253
|
+
const profiles = await ctx.db.query("agentProfiles").collect();
|
|
254
|
+
const dryRun = args.dryRun ?? false;
|
|
255
|
+
let updated = 0;
|
|
256
|
+
let clearedProviderUserId = 0;
|
|
257
|
+
let clearedSoulMd = 0;
|
|
258
|
+
let clearedClientMd = 0;
|
|
259
|
+
let clearedSkills = 0;
|
|
260
|
+
const updatedAgentKeys = [];
|
|
261
|
+
for (const profile of profiles) {
|
|
262
|
+
const patch = {};
|
|
263
|
+
let shouldPatch = false;
|
|
264
|
+
if (profile.providerUserId !== undefined) {
|
|
265
|
+
patch.providerUserId = undefined;
|
|
266
|
+
clearedProviderUserId += 1;
|
|
267
|
+
shouldPatch = true;
|
|
268
|
+
}
|
|
269
|
+
if (profile.soulMd !== undefined) {
|
|
270
|
+
patch.soulMd = undefined;
|
|
271
|
+
clearedSoulMd += 1;
|
|
272
|
+
shouldPatch = true;
|
|
273
|
+
}
|
|
274
|
+
if (profile.clientMd !== undefined) {
|
|
275
|
+
patch.clientMd = undefined;
|
|
276
|
+
clearedClientMd += 1;
|
|
277
|
+
shouldPatch = true;
|
|
278
|
+
}
|
|
279
|
+
if (profile.skills !== undefined) {
|
|
280
|
+
patch.skills = undefined;
|
|
281
|
+
clearedSkills += 1;
|
|
282
|
+
shouldPatch = true;
|
|
283
|
+
}
|
|
284
|
+
if (!shouldPatch)
|
|
285
|
+
continue;
|
|
286
|
+
updated += 1;
|
|
287
|
+
updatedAgentKeys.push(profile.agentKey);
|
|
288
|
+
if (!dryRun) {
|
|
289
|
+
await ctx.db.patch(profile._id, patch);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
dryRun,
|
|
294
|
+
scanned: profiles.length,
|
|
295
|
+
updated,
|
|
296
|
+
unchanged: profiles.length - updated,
|
|
297
|
+
clearedProviderUserId,
|
|
298
|
+
clearedSoulMd,
|
|
299
|
+
clearedClientMd,
|
|
300
|
+
clearedSkills,
|
|
301
|
+
updatedAgentKeys,
|
|
302
|
+
};
|
|
303
|
+
},
|
|
304
|
+
});
|
|
214
305
|
export const importPlaintextSecret = mutation({
|
|
215
306
|
args: {
|
|
216
307
|
secretRef: v.string(),
|
|
@@ -295,9 +386,9 @@ export const getProviderRuntimeConfig = internalQuery({
|
|
|
295
386
|
handler: async (ctx) => {
|
|
296
387
|
const row = await ctx.db
|
|
297
388
|
.query("runtimeConfig")
|
|
298
|
-
.withIndex("by_key", (q) => q.eq("key",
|
|
389
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.provider))
|
|
299
390
|
.unique();
|
|
300
|
-
if (!row) {
|
|
391
|
+
if (!row?.providerConfig) {
|
|
301
392
|
return null;
|
|
302
393
|
}
|
|
303
394
|
return row.providerConfig;
|
|
@@ -313,11 +404,11 @@ export const upsertProviderRuntimeConfig = internalMutation({
|
|
|
313
404
|
const nowMs = args.nowMs ?? Date.now();
|
|
314
405
|
const existing = await ctx.db
|
|
315
406
|
.query("runtimeConfig")
|
|
316
|
-
.withIndex("by_key", (q) => q.eq("key",
|
|
407
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.provider))
|
|
317
408
|
.unique();
|
|
318
409
|
if (!existing) {
|
|
319
410
|
await ctx.db.insert("runtimeConfig", {
|
|
320
|
-
key:
|
|
411
|
+
key: RUNTIME_CONFIG_KEYS.provider,
|
|
321
412
|
providerConfig: args.providerConfig,
|
|
322
413
|
updatedAt: nowMs,
|
|
323
414
|
});
|
|
@@ -336,9 +427,9 @@ export const providerRuntimeConfig = query({
|
|
|
336
427
|
handler: async (ctx) => {
|
|
337
428
|
const row = await ctx.db
|
|
338
429
|
.query("runtimeConfig")
|
|
339
|
-
.withIndex("by_key", (q) => q.eq("key",
|
|
430
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.provider))
|
|
340
431
|
.unique();
|
|
341
|
-
if (!row) {
|
|
432
|
+
if (!row?.providerConfig) {
|
|
342
433
|
return null;
|
|
343
434
|
}
|
|
344
435
|
return row.providerConfig;
|
|
@@ -354,11 +445,11 @@ export const setProviderRuntimeConfig = mutation({
|
|
|
354
445
|
const nowMs = args.nowMs ?? Date.now();
|
|
355
446
|
const existing = await ctx.db
|
|
356
447
|
.query("runtimeConfig")
|
|
357
|
-
.withIndex("by_key", (q) => q.eq("key",
|
|
448
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.provider))
|
|
358
449
|
.unique();
|
|
359
450
|
if (!existing) {
|
|
360
451
|
await ctx.db.insert("runtimeConfig", {
|
|
361
|
-
key:
|
|
452
|
+
key: RUNTIME_CONFIG_KEYS.provider,
|
|
362
453
|
providerConfig: args.providerConfig,
|
|
363
454
|
updatedAt: nowMs,
|
|
364
455
|
});
|
|
@@ -371,6 +462,438 @@ export const setProviderRuntimeConfig = mutation({
|
|
|
371
462
|
return null;
|
|
372
463
|
},
|
|
373
464
|
});
|
|
465
|
+
export const getMessageRuntimeConfig = internalQuery({
|
|
466
|
+
args: {},
|
|
467
|
+
returns: v.union(v.null(), messageRuntimeConfigValidator),
|
|
468
|
+
handler: async (ctx) => {
|
|
469
|
+
const row = await ctx.db
|
|
470
|
+
.query("runtimeConfig")
|
|
471
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
472
|
+
.unique();
|
|
473
|
+
if (!row?.messageConfig) {
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
return row.messageConfig;
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
export const upsertMessageRuntimeConfig = internalMutation({
|
|
480
|
+
args: {
|
|
481
|
+
messageConfig: messageRuntimeConfigValidator,
|
|
482
|
+
nowMs: v.optional(v.number()),
|
|
483
|
+
},
|
|
484
|
+
returns: v.null(),
|
|
485
|
+
handler: async (ctx, args) => {
|
|
486
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
487
|
+
const normalizedMessageConfig = normalizeMessageRuntimeConfig(args.messageConfig);
|
|
488
|
+
const existing = await ctx.db
|
|
489
|
+
.query("runtimeConfig")
|
|
490
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
491
|
+
.unique();
|
|
492
|
+
if (normalizedMessageConfig === null) {
|
|
493
|
+
if (existing) {
|
|
494
|
+
await ctx.db.delete(existing._id);
|
|
495
|
+
}
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
if (!existing) {
|
|
499
|
+
await ctx.db.insert("runtimeConfig", {
|
|
500
|
+
key: RUNTIME_CONFIG_KEYS.message,
|
|
501
|
+
messageConfig: normalizedMessageConfig,
|
|
502
|
+
updatedAt: nowMs,
|
|
503
|
+
});
|
|
504
|
+
return null;
|
|
505
|
+
}
|
|
506
|
+
await ctx.db.patch(existing._id, {
|
|
507
|
+
messageConfig: normalizedMessageConfig,
|
|
508
|
+
updatedAt: nowMs,
|
|
509
|
+
});
|
|
510
|
+
return null;
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
export const messageRuntimeConfig = query({
|
|
514
|
+
args: {},
|
|
515
|
+
returns: v.union(v.null(), messageRuntimeConfigValidator),
|
|
516
|
+
handler: async (ctx) => {
|
|
517
|
+
const row = await ctx.db
|
|
518
|
+
.query("runtimeConfig")
|
|
519
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
520
|
+
.unique();
|
|
521
|
+
if (!row?.messageConfig) {
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
return row.messageConfig;
|
|
525
|
+
},
|
|
526
|
+
});
|
|
527
|
+
export const setMessageRuntimeConfig = mutation({
|
|
528
|
+
args: {
|
|
529
|
+
messageConfig: messageRuntimeConfigValidator,
|
|
530
|
+
nowMs: v.optional(v.number()),
|
|
531
|
+
},
|
|
532
|
+
returns: v.null(),
|
|
533
|
+
handler: async (ctx, args) => {
|
|
534
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
535
|
+
const normalizedMessageConfig = normalizeMessageRuntimeConfig(args.messageConfig);
|
|
536
|
+
const existing = await ctx.db
|
|
537
|
+
.query("runtimeConfig")
|
|
538
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
539
|
+
.unique();
|
|
540
|
+
if (normalizedMessageConfig === null) {
|
|
541
|
+
if (existing) {
|
|
542
|
+
await ctx.db.delete(existing._id);
|
|
543
|
+
}
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
if (!existing) {
|
|
547
|
+
await ctx.db.insert("runtimeConfig", {
|
|
548
|
+
key: RUNTIME_CONFIG_KEYS.message,
|
|
549
|
+
messageConfig: normalizedMessageConfig,
|
|
550
|
+
updatedAt: nowMs,
|
|
551
|
+
});
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
await ctx.db.patch(existing._id, {
|
|
555
|
+
messageConfig: normalizedMessageConfig,
|
|
556
|
+
updatedAt: nowMs,
|
|
557
|
+
});
|
|
558
|
+
return null;
|
|
559
|
+
},
|
|
560
|
+
});
|
|
561
|
+
export const deployGlobalSkill = mutation({
|
|
562
|
+
args: {
|
|
563
|
+
slug: v.string(),
|
|
564
|
+
displayName: v.optional(v.string()),
|
|
565
|
+
description: v.optional(v.string()),
|
|
566
|
+
version: v.string(),
|
|
567
|
+
sourceJs: v.string(),
|
|
568
|
+
entryPoint: v.optional(v.string()),
|
|
569
|
+
moduleFormat: v.optional(globalSkillModuleFormatValidator),
|
|
570
|
+
releaseChannel: v.optional(globalSkillReleaseChannelValidator),
|
|
571
|
+
actor: v.optional(v.string()),
|
|
572
|
+
nowMs: v.optional(v.number()),
|
|
573
|
+
},
|
|
574
|
+
returns: v.object({
|
|
575
|
+
skillId: v.id("globalSkills"),
|
|
576
|
+
versionId: v.id("globalSkillVersions"),
|
|
577
|
+
releaseId: v.id("globalSkillReleases"),
|
|
578
|
+
slug: v.string(),
|
|
579
|
+
version: v.string(),
|
|
580
|
+
sha256: v.string(),
|
|
581
|
+
releaseChannel: globalSkillReleaseChannelValidator,
|
|
582
|
+
}),
|
|
583
|
+
handler: async (ctx, args) => {
|
|
584
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
585
|
+
const slug = args.slug.trim().toLowerCase();
|
|
586
|
+
const version = args.version.trim();
|
|
587
|
+
const entryPoint = (args.entryPoint ?? "default").trim();
|
|
588
|
+
const releaseChannel = args.releaseChannel ?? "stable";
|
|
589
|
+
const moduleFormat = args.moduleFormat ?? "esm";
|
|
590
|
+
const actor = args.actor?.trim() || "system";
|
|
591
|
+
const sourceJs = args.sourceJs.trim();
|
|
592
|
+
if (!/^[a-z0-9][a-z0-9-_]{1,127}$/.test(slug)) {
|
|
593
|
+
throw new Error("Invalid skill slug. Use lowercase letters, numbers, '-' and '_'.");
|
|
594
|
+
}
|
|
595
|
+
if (!/^\d+\.\d+\.\d+(?:[-+][A-Za-z0-9.-]+)?$/.test(version)) {
|
|
596
|
+
throw new Error("Invalid skill version. Use semantic versioning format.");
|
|
597
|
+
}
|
|
598
|
+
if (sourceJs.length < 16) {
|
|
599
|
+
throw new Error("Skill source is too short.");
|
|
600
|
+
}
|
|
601
|
+
if (sourceJs.length > 200_000) {
|
|
602
|
+
throw new Error("Skill source too large (max 200KB).");
|
|
603
|
+
}
|
|
604
|
+
if (!entryPoint) {
|
|
605
|
+
throw new Error("entryPoint is required.");
|
|
606
|
+
}
|
|
607
|
+
const sha256 = await computeSha256Hex(sourceJs);
|
|
608
|
+
const existingSkill = await ctx.db
|
|
609
|
+
.query("globalSkills")
|
|
610
|
+
.withIndex("by_slug", (q) => q.eq("slug", slug))
|
|
611
|
+
.unique();
|
|
612
|
+
const skillId = existingSkill?._id ??
|
|
613
|
+
(await ctx.db.insert("globalSkills", {
|
|
614
|
+
slug,
|
|
615
|
+
displayName: args.displayName?.trim() || slug,
|
|
616
|
+
description: args.description?.trim(),
|
|
617
|
+
status: "active",
|
|
618
|
+
createdBy: actor,
|
|
619
|
+
updatedBy: actor,
|
|
620
|
+
createdAt: nowMs,
|
|
621
|
+
updatedAt: nowMs,
|
|
622
|
+
}));
|
|
623
|
+
if (existingSkill) {
|
|
624
|
+
await ctx.db.patch(skillId, {
|
|
625
|
+
displayName: args.displayName?.trim() || existingSkill.displayName,
|
|
626
|
+
description: args.description !== undefined ? args.description.trim() : existingSkill.description,
|
|
627
|
+
status: "active",
|
|
628
|
+
updatedBy: actor,
|
|
629
|
+
updatedAt: nowMs,
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
const existingVersion = await ctx.db
|
|
633
|
+
.query("globalSkillVersions")
|
|
634
|
+
.withIndex("by_skillId_and_version", (q) => q.eq("skillId", skillId).eq("version", version))
|
|
635
|
+
.unique();
|
|
636
|
+
let versionId = existingVersion?._id;
|
|
637
|
+
if (!existingVersion) {
|
|
638
|
+
versionId = await ctx.db.insert("globalSkillVersions", {
|
|
639
|
+
skillId,
|
|
640
|
+
version,
|
|
641
|
+
moduleFormat,
|
|
642
|
+
entryPoint,
|
|
643
|
+
sourceJs,
|
|
644
|
+
sha256,
|
|
645
|
+
createdBy: actor,
|
|
646
|
+
createdAt: nowMs,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
else if (existingVersion.sha256 !== sha256) {
|
|
650
|
+
throw new Error(`Skill ${slug}@${version} already exists with a different source.`);
|
|
651
|
+
}
|
|
652
|
+
const activeReleases = await ctx.db
|
|
653
|
+
.query("globalSkillReleases")
|
|
654
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skillId).eq("releaseChannel", releaseChannel).eq("isActive", true))
|
|
655
|
+
.collect();
|
|
656
|
+
for (const release of activeReleases) {
|
|
657
|
+
await ctx.db.patch(release._id, { isActive: false });
|
|
658
|
+
}
|
|
659
|
+
const releaseId = await ctx.db.insert("globalSkillReleases", {
|
|
660
|
+
skillId,
|
|
661
|
+
versionId: versionId,
|
|
662
|
+
releaseChannel,
|
|
663
|
+
isActive: true,
|
|
664
|
+
activatedBy: actor,
|
|
665
|
+
activatedAt: nowMs,
|
|
666
|
+
});
|
|
667
|
+
return {
|
|
668
|
+
skillId,
|
|
669
|
+
versionId: versionId,
|
|
670
|
+
releaseId,
|
|
671
|
+
slug,
|
|
672
|
+
version,
|
|
673
|
+
sha256,
|
|
674
|
+
releaseChannel,
|
|
675
|
+
};
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
export const listGlobalSkills = query({
|
|
679
|
+
args: {
|
|
680
|
+
releaseChannel: v.optional(globalSkillReleaseChannelValidator),
|
|
681
|
+
status: v.optional(globalSkillStatusValidator),
|
|
682
|
+
limit: v.optional(v.number()),
|
|
683
|
+
},
|
|
684
|
+
returns: v.array(v.object({
|
|
685
|
+
skillId: v.id("globalSkills"),
|
|
686
|
+
slug: v.string(),
|
|
687
|
+
displayName: v.string(),
|
|
688
|
+
description: v.optional(v.string()),
|
|
689
|
+
status: globalSkillStatusValidator,
|
|
690
|
+
updatedAt: v.number(),
|
|
691
|
+
activeRelease: v.union(v.null(), v.object({
|
|
692
|
+
releaseId: v.id("globalSkillReleases"),
|
|
693
|
+
versionId: v.id("globalSkillVersions"),
|
|
694
|
+
version: v.string(),
|
|
695
|
+
sha256: v.string(),
|
|
696
|
+
moduleFormat: globalSkillModuleFormatValidator,
|
|
697
|
+
entryPoint: v.string(),
|
|
698
|
+
releaseChannel: globalSkillReleaseChannelValidator,
|
|
699
|
+
activatedAt: v.number(),
|
|
700
|
+
})),
|
|
701
|
+
})),
|
|
702
|
+
handler: async (ctx, args) => {
|
|
703
|
+
const releaseChannel = args.releaseChannel ?? "stable";
|
|
704
|
+
const limit = Math.max(1, Math.min(args.limit ?? 200, 500));
|
|
705
|
+
const skills = args.status !== undefined
|
|
706
|
+
? await ctx.db
|
|
707
|
+
.query("globalSkills")
|
|
708
|
+
.withIndex("by_status", (q) => q.eq("status", args.status))
|
|
709
|
+
.take(limit)
|
|
710
|
+
: await ctx.db.query("globalSkills").take(limit);
|
|
711
|
+
const sortedSkills = [...skills].sort((a, b) => a.slug.localeCompare(b.slug));
|
|
712
|
+
const out = [];
|
|
713
|
+
for (const skill of sortedSkills) {
|
|
714
|
+
const activeRelease = await ctx.db
|
|
715
|
+
.query("globalSkillReleases")
|
|
716
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", releaseChannel).eq("isActive", true))
|
|
717
|
+
.first();
|
|
718
|
+
let activeReleaseRow = null;
|
|
719
|
+
if (activeRelease) {
|
|
720
|
+
const version = await ctx.db.get(activeRelease.versionId);
|
|
721
|
+
if (version) {
|
|
722
|
+
activeReleaseRow = {
|
|
723
|
+
releaseId: activeRelease._id,
|
|
724
|
+
versionId: version._id,
|
|
725
|
+
version: version.version,
|
|
726
|
+
sha256: version.sha256,
|
|
727
|
+
moduleFormat: version.moduleFormat,
|
|
728
|
+
entryPoint: version.entryPoint,
|
|
729
|
+
releaseChannel: activeRelease.releaseChannel,
|
|
730
|
+
activatedAt: activeRelease.activatedAt,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
out.push({
|
|
735
|
+
skillId: skill._id,
|
|
736
|
+
slug: skill.slug,
|
|
737
|
+
displayName: skill.displayName,
|
|
738
|
+
description: skill.description,
|
|
739
|
+
status: skill.status,
|
|
740
|
+
updatedAt: skill.updatedAt,
|
|
741
|
+
activeRelease: activeReleaseRow,
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
return out;
|
|
745
|
+
},
|
|
746
|
+
});
|
|
747
|
+
export const getWorkerGlobalSkillsManifest = query({
|
|
748
|
+
args: {
|
|
749
|
+
workspaceId: v.optional(v.string()),
|
|
750
|
+
workerId: v.optional(v.string()),
|
|
751
|
+
releaseChannel: v.optional(globalSkillReleaseChannelValidator),
|
|
752
|
+
},
|
|
753
|
+
returns: v.object({
|
|
754
|
+
manifestVersion: v.string(),
|
|
755
|
+
generatedAt: v.number(),
|
|
756
|
+
releaseChannel: globalSkillReleaseChannelValidator,
|
|
757
|
+
workspaceId: v.string(),
|
|
758
|
+
skills: v.array(globalSkillManifestItemValidator),
|
|
759
|
+
}),
|
|
760
|
+
handler: async (ctx, args) => {
|
|
761
|
+
const nowMs = Date.now();
|
|
762
|
+
const releaseChannel = args.releaseChannel ?? "stable";
|
|
763
|
+
const activeSkills = await ctx.db
|
|
764
|
+
.query("globalSkills")
|
|
765
|
+
.withIndex("by_status", (q) => q.eq("status", "active"))
|
|
766
|
+
.collect();
|
|
767
|
+
const sortedSkills = [...activeSkills].sort((a, b) => a.slug.localeCompare(b.slug));
|
|
768
|
+
const manifestSkills = [];
|
|
769
|
+
for (const skill of sortedSkills) {
|
|
770
|
+
const activeRelease = await ctx.db
|
|
771
|
+
.query("globalSkillReleases")
|
|
772
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", releaseChannel).eq("isActive", true))
|
|
773
|
+
.first();
|
|
774
|
+
if (!activeRelease)
|
|
775
|
+
continue;
|
|
776
|
+
const version = await ctx.db.get(activeRelease.versionId);
|
|
777
|
+
if (!version)
|
|
778
|
+
continue;
|
|
779
|
+
manifestSkills.push({
|
|
780
|
+
slug: skill.slug,
|
|
781
|
+
version: version.version,
|
|
782
|
+
moduleFormat: version.moduleFormat,
|
|
783
|
+
entryPoint: version.entryPoint,
|
|
784
|
+
sourceJs: version.sourceJs,
|
|
785
|
+
sha256: version.sha256,
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
manifestSkills.sort((a, b) => {
|
|
789
|
+
if (a.slug !== b.slug)
|
|
790
|
+
return a.slug.localeCompare(b.slug);
|
|
791
|
+
return a.version.localeCompare(b.version);
|
|
792
|
+
});
|
|
793
|
+
const fingerprintSeed = manifestSkills
|
|
794
|
+
.map((row) => `${row.slug}@${row.version}:${row.sha256}`)
|
|
795
|
+
.join("|");
|
|
796
|
+
const manifestVersion = await computeSha256Hex(fingerprintSeed || "empty");
|
|
797
|
+
return {
|
|
798
|
+
manifestVersion,
|
|
799
|
+
generatedAt: nowMs,
|
|
800
|
+
releaseChannel,
|
|
801
|
+
workspaceId: args.workspaceId ?? "default",
|
|
802
|
+
skills: manifestSkills,
|
|
803
|
+
};
|
|
804
|
+
},
|
|
805
|
+
});
|
|
806
|
+
export const setGlobalSkillStatus = mutation({
|
|
807
|
+
args: {
|
|
808
|
+
slug: v.string(),
|
|
809
|
+
status: globalSkillStatusValidator,
|
|
810
|
+
actor: v.optional(v.string()),
|
|
811
|
+
nowMs: v.optional(v.number()),
|
|
812
|
+
},
|
|
813
|
+
returns: v.object({
|
|
814
|
+
updated: v.boolean(),
|
|
815
|
+
slug: v.string(),
|
|
816
|
+
status: globalSkillStatusValidator,
|
|
817
|
+
}),
|
|
818
|
+
handler: async (ctx, args) => {
|
|
819
|
+
const slug = args.slug.trim().toLowerCase();
|
|
820
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
821
|
+
const actor = args.actor?.trim() || "system";
|
|
822
|
+
const skill = await ctx.db
|
|
823
|
+
.query("globalSkills")
|
|
824
|
+
.withIndex("by_slug", (q) => q.eq("slug", slug))
|
|
825
|
+
.unique();
|
|
826
|
+
if (!skill) {
|
|
827
|
+
return { updated: false, slug, status: args.status };
|
|
828
|
+
}
|
|
829
|
+
await ctx.db.patch(skill._id, {
|
|
830
|
+
status: args.status,
|
|
831
|
+
updatedBy: actor,
|
|
832
|
+
updatedAt: nowMs,
|
|
833
|
+
});
|
|
834
|
+
return { updated: true, slug, status: args.status };
|
|
835
|
+
},
|
|
836
|
+
});
|
|
837
|
+
export const deleteGlobalSkill = mutation({
|
|
838
|
+
args: {
|
|
839
|
+
slug: v.string(),
|
|
840
|
+
},
|
|
841
|
+
returns: v.object({
|
|
842
|
+
deleted: v.boolean(),
|
|
843
|
+
slug: v.string(),
|
|
844
|
+
deletedVersions: v.number(),
|
|
845
|
+
deletedReleases: v.number(),
|
|
846
|
+
}),
|
|
847
|
+
handler: async (ctx, args) => {
|
|
848
|
+
const slug = args.slug.trim().toLowerCase();
|
|
849
|
+
const skill = await ctx.db
|
|
850
|
+
.query("globalSkills")
|
|
851
|
+
.withIndex("by_slug", (q) => q.eq("slug", slug))
|
|
852
|
+
.unique();
|
|
853
|
+
if (!skill) {
|
|
854
|
+
return { deleted: false, slug, deletedVersions: 0, deletedReleases: 0 };
|
|
855
|
+
}
|
|
856
|
+
const stableActiveReleases = await ctx.db
|
|
857
|
+
.query("globalSkillReleases")
|
|
858
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", "stable").eq("isActive", true))
|
|
859
|
+
.collect();
|
|
860
|
+
const stableInactiveReleases = await ctx.db
|
|
861
|
+
.query("globalSkillReleases")
|
|
862
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", "stable").eq("isActive", false))
|
|
863
|
+
.collect();
|
|
864
|
+
const canaryActiveReleases = await ctx.db
|
|
865
|
+
.query("globalSkillReleases")
|
|
866
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", "canary").eq("isActive", true))
|
|
867
|
+
.collect();
|
|
868
|
+
const canaryInactiveReleases = await ctx.db
|
|
869
|
+
.query("globalSkillReleases")
|
|
870
|
+
.withIndex("by_skillId_and_releaseChannel_and_isActive", (q) => q.eq("skillId", skill._id).eq("releaseChannel", "canary").eq("isActive", false))
|
|
871
|
+
.collect();
|
|
872
|
+
const allReleases = [
|
|
873
|
+
...stableActiveReleases,
|
|
874
|
+
...stableInactiveReleases,
|
|
875
|
+
...canaryActiveReleases,
|
|
876
|
+
...canaryInactiveReleases,
|
|
877
|
+
];
|
|
878
|
+
const versions = await ctx.db
|
|
879
|
+
.query("globalSkillVersions")
|
|
880
|
+
.withIndex("by_skillId_and_createdAt", (q) => q.eq("skillId", skill._id))
|
|
881
|
+
.collect();
|
|
882
|
+
for (const release of allReleases) {
|
|
883
|
+
await ctx.db.delete(release._id);
|
|
884
|
+
}
|
|
885
|
+
for (const version of versions) {
|
|
886
|
+
await ctx.db.delete(version._id);
|
|
887
|
+
}
|
|
888
|
+
await ctx.db.delete(skill._id);
|
|
889
|
+
return {
|
|
890
|
+
deleted: true,
|
|
891
|
+
slug,
|
|
892
|
+
deletedVersions: versions.length,
|
|
893
|
+
deletedReleases: allReleases.length,
|
|
894
|
+
};
|
|
895
|
+
},
|
|
896
|
+
});
|
|
374
897
|
export const generateMediaUploadUrl = mutation({
|
|
375
898
|
args: {},
|
|
376
899
|
returns: v.object({
|
|
@@ -1334,6 +1857,31 @@ async function resolveBridgeRuntimeConfig(ctx, profile) {
|
|
|
1334
1857
|
serviceKeySecretRef,
|
|
1335
1858
|
};
|
|
1336
1859
|
}
|
|
1860
|
+
function appendSystemPromptToMessage(messageText, systemPrompt) {
|
|
1861
|
+
const normalizedSystemPrompt = normalizeSystemPrompt(systemPrompt);
|
|
1862
|
+
if (normalizedSystemPrompt === null) {
|
|
1863
|
+
return messageText;
|
|
1864
|
+
}
|
|
1865
|
+
const normalizedMessageText = messageText.trimEnd();
|
|
1866
|
+
if (normalizedMessageText.length === 0) {
|
|
1867
|
+
return normalizedSystemPrompt;
|
|
1868
|
+
}
|
|
1869
|
+
return `${normalizedMessageText}\n\n${normalizedSystemPrompt}`;
|
|
1870
|
+
}
|
|
1871
|
+
function normalizeMessageRuntimeConfig(messageConfig) {
|
|
1872
|
+
const systemPrompt = normalizeSystemPrompt(messageConfig?.systemPrompt);
|
|
1873
|
+
if (systemPrompt === null) {
|
|
1874
|
+
return null;
|
|
1875
|
+
}
|
|
1876
|
+
return { systemPrompt };
|
|
1877
|
+
}
|
|
1878
|
+
function normalizeSystemPrompt(systemPrompt) {
|
|
1879
|
+
if (typeof systemPrompt !== "string") {
|
|
1880
|
+
return null;
|
|
1881
|
+
}
|
|
1882
|
+
const normalizedSystemPrompt = systemPrompt.trim();
|
|
1883
|
+
return normalizedSystemPrompt.length > 0 ? normalizedSystemPrompt : null;
|
|
1884
|
+
}
|
|
1337
1885
|
function getBridgeSecretRefsForProfile(agentKey, bridgeConfig) {
|
|
1338
1886
|
if (!bridgeConfig?.enabled) {
|
|
1339
1887
|
return [];
|
|
@@ -1375,6 +1923,13 @@ function fingerprintConversationDelta(deltaContext) {
|
|
|
1375
1923
|
}
|
|
1376
1924
|
return `f${(hash >>> 0).toString(16)}`;
|
|
1377
1925
|
}
|
|
1926
|
+
async function computeSha256Hex(input) {
|
|
1927
|
+
const bytes = new TextEncoder().encode(input);
|
|
1928
|
+
const digest = await crypto.subtle.digest("SHA-256", bytes);
|
|
1929
|
+
return Array.from(new Uint8Array(digest))
|
|
1930
|
+
.map((value) => value.toString(16).padStart(2, "0"))
|
|
1931
|
+
.join("");
|
|
1932
|
+
}
|
|
1378
1933
|
function encryptSecretValue(plaintext) {
|
|
1379
1934
|
const units = Array.from(plaintext);
|
|
1380
1935
|
return units
|