@okrlinkhub/agent-factory 2.0.0 → 2.0.1
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/client/index.d.ts +38 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +174 -36
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/component.d.ts +138 -8
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/identity.d.ts +5 -5
- package/dist/component/pushing.d.ts +30 -30
- package/dist/component/queue.d.ts +125 -51
- package/dist/component/queue.d.ts.map +1 -1
- package/dist/component/queue.js +128 -14
- package/dist/component/queue.js.map +1 -1
- package/dist/component/scheduler.d.ts +13 -13
- package/dist/component/scheduler.js +4 -0
- package/dist/component/scheduler.js.map +1 -1
- package/dist/component/schema.d.ts +164 -80
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +29 -0
- package/dist/component/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +302 -42
- package/src/component/_generated/component.ts +164 -14
- package/src/component/lib.test.ts +132 -0
- package/src/component/queue.ts +185 -20
- package/src/component/scheduler.ts +4 -0
- package/src/component/schema.ts +46 -0
package/src/component/queue.ts
CHANGED
|
@@ -25,6 +25,30 @@ const queueStatusValidator = v.union(
|
|
|
25
25
|
v.literal("dead_letter"),
|
|
26
26
|
);
|
|
27
27
|
|
|
28
|
+
const telegramAttachmentKindValidator = v.union(
|
|
29
|
+
v.literal("photo"),
|
|
30
|
+
v.literal("video"),
|
|
31
|
+
v.literal("audio"),
|
|
32
|
+
v.literal("voice"),
|
|
33
|
+
v.literal("document"),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
const telegramAttachmentStatusValidator = v.union(
|
|
37
|
+
v.literal("ready"),
|
|
38
|
+
v.literal("expired"),
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const telegramAttachmentValidator = v.object({
|
|
42
|
+
kind: telegramAttachmentKindValidator,
|
|
43
|
+
status: telegramAttachmentStatusValidator,
|
|
44
|
+
storageId: v.id("_storage"),
|
|
45
|
+
telegramFileId: v.string(),
|
|
46
|
+
fileName: v.optional(v.string()),
|
|
47
|
+
mimeType: v.optional(v.string()),
|
|
48
|
+
sizeBytes: v.optional(v.number()),
|
|
49
|
+
expiresAt: v.number(),
|
|
50
|
+
});
|
|
51
|
+
|
|
28
52
|
const queuePayloadValidator = v.object({
|
|
29
53
|
provider: v.string(),
|
|
30
54
|
providerUserId: v.string(),
|
|
@@ -32,6 +56,7 @@ const queuePayloadValidator = v.object({
|
|
|
32
56
|
externalMessageId: v.optional(v.string()),
|
|
33
57
|
rawUpdateJson: v.optional(v.string()),
|
|
34
58
|
metadata: v.optional(v.record(v.string(), v.string())),
|
|
59
|
+
attachments: v.optional(v.array(telegramAttachmentValidator)),
|
|
35
60
|
});
|
|
36
61
|
|
|
37
62
|
const snapshotReasonValidator = v.union(
|
|
@@ -155,6 +180,7 @@ const workerSpawnOpenClawEnvValidator = v.object({
|
|
|
155
180
|
|
|
156
181
|
const messageRuntimeConfigValidator = v.object({
|
|
157
182
|
systemPrompt: v.optional(v.string()),
|
|
183
|
+
telegramAttachmentRetentionMs: v.optional(v.number()),
|
|
158
184
|
});
|
|
159
185
|
|
|
160
186
|
const globalSkillStatusValidator = v.union(v.literal("active"), v.literal("disabled"));
|
|
@@ -192,6 +218,8 @@ const RUNTIME_CONFIG_KEYS = {
|
|
|
192
218
|
message: "message",
|
|
193
219
|
} as const;
|
|
194
220
|
|
|
221
|
+
const DEFAULT_TELEGRAM_ATTACHMENT_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
222
|
+
|
|
195
223
|
export const enqueueMessage = mutation({
|
|
196
224
|
args: {
|
|
197
225
|
conversationId: v.string(),
|
|
@@ -533,6 +561,33 @@ export const getMessageRuntimeConfig = internalQuery({
|
|
|
533
561
|
},
|
|
534
562
|
});
|
|
535
563
|
|
|
564
|
+
export const getTelegramIngressRuntimeConfig = internalQuery({
|
|
565
|
+
args: {
|
|
566
|
+
agentKey: v.string(),
|
|
567
|
+
},
|
|
568
|
+
returns: v.object({
|
|
569
|
+
botToken: v.union(v.null(), v.string()),
|
|
570
|
+
attachmentRetentionMs: v.number(),
|
|
571
|
+
}),
|
|
572
|
+
handler: async (ctx, args) => {
|
|
573
|
+
const profile = await ctx.db
|
|
574
|
+
.query("agentProfiles")
|
|
575
|
+
.withIndex("by_agentKey", (q) => q.eq("agentKey", args.agentKey))
|
|
576
|
+
.unique();
|
|
577
|
+
const botToken = profile ? await resolveActiveTelegramBotToken(ctx, profile.secretsRef) : null;
|
|
578
|
+
const row = await ctx.db
|
|
579
|
+
.query("runtimeConfig")
|
|
580
|
+
.withIndex("by_key", (q) => q.eq("key", RUNTIME_CONFIG_KEYS.message))
|
|
581
|
+
.unique();
|
|
582
|
+
return {
|
|
583
|
+
botToken,
|
|
584
|
+
attachmentRetentionMs: resolveTelegramAttachmentRetentionMs(
|
|
585
|
+
row?.messageConfig?.telegramAttachmentRetentionMs,
|
|
586
|
+
),
|
|
587
|
+
};
|
|
588
|
+
},
|
|
589
|
+
});
|
|
590
|
+
|
|
536
591
|
export const upsertMessageRuntimeConfig = internalMutation({
|
|
537
592
|
args: {
|
|
538
593
|
messageConfig: messageRuntimeConfigValidator,
|
|
@@ -1694,22 +1749,7 @@ export const getHydrationBundleForClaimedJob = query({
|
|
|
1694
1749
|
.withIndex("by_conversationId", (q) => q.eq("conversationId", message.conversationId))
|
|
1695
1750
|
.first();
|
|
1696
1751
|
|
|
1697
|
-
|
|
1698
|
-
const telegramSecretRefs = profile.secretsRef.filter(
|
|
1699
|
-
(ref) => ref === "telegram.botToken" || ref.startsWith("telegram.botToken."),
|
|
1700
|
-
);
|
|
1701
|
-
for (const telegramSecretRef of telegramSecretRefs) {
|
|
1702
|
-
const activeSecret = await ctx.db
|
|
1703
|
-
.query("secrets")
|
|
1704
|
-
.withIndex("by_secretRef_and_active", (q) =>
|
|
1705
|
-
q.eq("secretRef", telegramSecretRef).eq("active", true),
|
|
1706
|
-
)
|
|
1707
|
-
.unique();
|
|
1708
|
-
if (activeSecret) {
|
|
1709
|
-
telegramBotToken = decryptSecretValue(activeSecret.encryptedValue, activeSecret.algorithm);
|
|
1710
|
-
break;
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1752
|
+
const telegramBotToken = await resolveActiveTelegramBotToken(ctx, profile.secretsRef);
|
|
1713
1753
|
|
|
1714
1754
|
const contextHistory =
|
|
1715
1755
|
conversationCache && conversationCache.snapshotKey === snapshotKey
|
|
@@ -2424,6 +2464,49 @@ export const expireOldDataSnapshots = internalMutation({
|
|
|
2424
2464
|
},
|
|
2425
2465
|
});
|
|
2426
2466
|
|
|
2467
|
+
export const expireOldTelegramAttachments = internalMutation({
|
|
2468
|
+
args: {
|
|
2469
|
+
nowMs: v.optional(v.number()),
|
|
2470
|
+
limit: v.optional(v.number()),
|
|
2471
|
+
},
|
|
2472
|
+
returns: v.number(),
|
|
2473
|
+
handler: async (ctx, args) => {
|
|
2474
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
2475
|
+
const limit = args.limit ?? 100;
|
|
2476
|
+
const rows = await ctx.db
|
|
2477
|
+
.query("messageAttachments")
|
|
2478
|
+
.withIndex("by_status_and_expiresAt", (q) =>
|
|
2479
|
+
q.eq("status", "ready").lte("expiresAt", nowMs),
|
|
2480
|
+
)
|
|
2481
|
+
.take(limit);
|
|
2482
|
+
for (const row of rows) {
|
|
2483
|
+
await ctx.db.patch(row._id, {
|
|
2484
|
+
status: "expired",
|
|
2485
|
+
});
|
|
2486
|
+
const message = await ctx.db.get(row.messageId);
|
|
2487
|
+
if (message?.payload.attachments?.length) {
|
|
2488
|
+
await ctx.db.patch(message._id, {
|
|
2489
|
+
payload: {
|
|
2490
|
+
...message.payload,
|
|
2491
|
+
attachments: message.payload.attachments.map((attachment) =>
|
|
2492
|
+
attachment.storageId === row.storageId
|
|
2493
|
+
? {
|
|
2494
|
+
...attachment,
|
|
2495
|
+
status: "expired" as const,
|
|
2496
|
+
}
|
|
2497
|
+
: attachment,
|
|
2498
|
+
),
|
|
2499
|
+
},
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2502
|
+
await (ctx.storage as { delete?: (storageId: Id<"_storage">) => Promise<void> }).delete?.(
|
|
2503
|
+
row.storageId,
|
|
2504
|
+
);
|
|
2505
|
+
}
|
|
2506
|
+
return rows.length;
|
|
2507
|
+
},
|
|
2508
|
+
});
|
|
2509
|
+
|
|
2427
2510
|
export const getWorkerStats = query({
|
|
2428
2511
|
args: {},
|
|
2429
2512
|
returns: v.object({
|
|
@@ -2638,6 +2721,16 @@ async function enqueueMessageRecord(
|
|
|
2638
2721
|
externalMessageId?: string;
|
|
2639
2722
|
rawUpdateJson?: string;
|
|
2640
2723
|
metadata?: Record<string, string>;
|
|
2724
|
+
attachments?: Array<{
|
|
2725
|
+
kind: "photo" | "video" | "audio" | "voice" | "document";
|
|
2726
|
+
status: "ready" | "expired";
|
|
2727
|
+
storageId: Id<"_storage">;
|
|
2728
|
+
telegramFileId: string;
|
|
2729
|
+
fileName?: string;
|
|
2730
|
+
mimeType?: string;
|
|
2731
|
+
sizeBytes?: number;
|
|
2732
|
+
expiresAt: number;
|
|
2733
|
+
}>;
|
|
2641
2734
|
};
|
|
2642
2735
|
priority?: number;
|
|
2643
2736
|
scheduledFor?: number;
|
|
@@ -2709,6 +2802,23 @@ async function enqueueMessageRecord(
|
|
|
2709
2802
|
attempts: 0,
|
|
2710
2803
|
maxAttempts: args.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,
|
|
2711
2804
|
});
|
|
2805
|
+
for (const attachment of payload.attachments ?? []) {
|
|
2806
|
+
await ctx.db.insert("messageAttachments", {
|
|
2807
|
+
messageId,
|
|
2808
|
+
conversationId: args.conversationId,
|
|
2809
|
+
agentKey: args.agentKey,
|
|
2810
|
+
provider: payload.provider,
|
|
2811
|
+
kind: attachment.kind,
|
|
2812
|
+
status: attachment.status,
|
|
2813
|
+
storageId: attachment.storageId,
|
|
2814
|
+
telegramFileId: attachment.telegramFileId,
|
|
2815
|
+
fileName: attachment.fileName,
|
|
2816
|
+
mimeType: attachment.mimeType,
|
|
2817
|
+
sizeBytes: attachment.sizeBytes,
|
|
2818
|
+
createdAt: nowMs,
|
|
2819
|
+
expiresAt: attachment.expiresAt,
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2712
2822
|
try {
|
|
2713
2823
|
await ctx.scheduler.runAfter(0, (internal.scheduler as any).reconcileWorkerPoolFromEnqueue, {
|
|
2714
2824
|
workspaceId: "default",
|
|
@@ -2970,13 +3080,27 @@ function dedupeMessagesById<T extends { _id: string }>(messages: Array<T>): Arra
|
|
|
2970
3080
|
}
|
|
2971
3081
|
|
|
2972
3082
|
function normalizeMessageRuntimeConfig(
|
|
2973
|
-
messageConfig:
|
|
2974
|
-
|
|
3083
|
+
messageConfig:
|
|
3084
|
+
| {
|
|
3085
|
+
systemPrompt?: string;
|
|
3086
|
+
telegramAttachmentRetentionMs?: number;
|
|
3087
|
+
}
|
|
3088
|
+
| null
|
|
3089
|
+
| undefined,
|
|
3090
|
+
): { systemPrompt?: string; telegramAttachmentRetentionMs?: number } | null {
|
|
2975
3091
|
const systemPrompt = normalizeSystemPrompt(messageConfig?.systemPrompt);
|
|
2976
|
-
|
|
3092
|
+
const telegramAttachmentRetentionMs = normalizeTelegramAttachmentRetentionMs(
|
|
3093
|
+
messageConfig?.telegramAttachmentRetentionMs,
|
|
3094
|
+
);
|
|
3095
|
+
if (systemPrompt === null && telegramAttachmentRetentionMs === undefined) {
|
|
2977
3096
|
return null;
|
|
2978
3097
|
}
|
|
2979
|
-
return {
|
|
3098
|
+
return {
|
|
3099
|
+
...(systemPrompt === null ? {} : { systemPrompt }),
|
|
3100
|
+
...(telegramAttachmentRetentionMs === undefined
|
|
3101
|
+
? {}
|
|
3102
|
+
: { telegramAttachmentRetentionMs }),
|
|
3103
|
+
};
|
|
2980
3104
|
}
|
|
2981
3105
|
|
|
2982
3106
|
function normalizeSystemPrompt(systemPrompt?: string | null): string | null {
|
|
@@ -2987,6 +3111,47 @@ function normalizeSystemPrompt(systemPrompt?: string | null): string | null {
|
|
|
2987
3111
|
return normalizedSystemPrompt.length > 0 ? normalizedSystemPrompt : null;
|
|
2988
3112
|
}
|
|
2989
3113
|
|
|
3114
|
+
function normalizeTelegramAttachmentRetentionMs(
|
|
3115
|
+
retentionMs?: number | null,
|
|
3116
|
+
): number | undefined {
|
|
3117
|
+
if (typeof retentionMs !== "number" || !Number.isFinite(retentionMs)) {
|
|
3118
|
+
return undefined;
|
|
3119
|
+
}
|
|
3120
|
+
const normalizedRetentionMs = Math.floor(retentionMs);
|
|
3121
|
+
if (normalizedRetentionMs <= 0) {
|
|
3122
|
+
return undefined;
|
|
3123
|
+
}
|
|
3124
|
+
return normalizedRetentionMs;
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3127
|
+
function resolveTelegramAttachmentRetentionMs(retentionMs?: number | null): number {
|
|
3128
|
+
return (
|
|
3129
|
+
normalizeTelegramAttachmentRetentionMs(retentionMs) ??
|
|
3130
|
+
DEFAULT_TELEGRAM_ATTACHMENT_RETENTION_MS
|
|
3131
|
+
);
|
|
3132
|
+
}
|
|
3133
|
+
|
|
3134
|
+
async function resolveActiveTelegramBotToken(
|
|
3135
|
+
ctx: QueryCtx,
|
|
3136
|
+
secretRefs: Array<string>,
|
|
3137
|
+
): Promise<string | null> {
|
|
3138
|
+
const telegramSecretRefs = secretRefs.filter(
|
|
3139
|
+
(ref) => ref === "telegram.botToken" || ref.startsWith("telegram.botToken."),
|
|
3140
|
+
);
|
|
3141
|
+
for (const telegramSecretRef of telegramSecretRefs) {
|
|
3142
|
+
const activeSecret = await ctx.db
|
|
3143
|
+
.query("secrets")
|
|
3144
|
+
.withIndex("by_secretRef_and_active", (q) =>
|
|
3145
|
+
q.eq("secretRef", telegramSecretRef).eq("active", true),
|
|
3146
|
+
)
|
|
3147
|
+
.unique();
|
|
3148
|
+
if (activeSecret) {
|
|
3149
|
+
return decryptSecretValue(activeSecret.encryptedValue, activeSecret.algorithm);
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
return null;
|
|
3153
|
+
}
|
|
3154
|
+
|
|
2990
3155
|
async function buildGlobalSkillMaterialization(skill: {
|
|
2991
3156
|
slug: string;
|
|
2992
3157
|
version: string;
|
|
@@ -206,6 +206,10 @@ async function runReconcileWorkerPool(
|
|
|
206
206
|
nowMs,
|
|
207
207
|
limit: 100,
|
|
208
208
|
});
|
|
209
|
+
await ctx.runMutation((internal.queue as any).expireOldTelegramAttachments, {
|
|
210
|
+
nowMs,
|
|
211
|
+
limit: 100,
|
|
212
|
+
});
|
|
209
213
|
|
|
210
214
|
return {
|
|
211
215
|
activeWorkers: cycle.activeWorkers,
|
package/src/component/schema.ts
CHANGED
|
@@ -72,6 +72,26 @@ export default defineSchema({
|
|
|
72
72
|
externalMessageId: v.optional(v.string()),
|
|
73
73
|
rawUpdateJson: v.optional(v.string()),
|
|
74
74
|
metadata: v.optional(v.record(v.string(), v.string())),
|
|
75
|
+
attachments: v.optional(
|
|
76
|
+
v.array(
|
|
77
|
+
v.object({
|
|
78
|
+
kind: v.union(
|
|
79
|
+
v.literal("photo"),
|
|
80
|
+
v.literal("video"),
|
|
81
|
+
v.literal("audio"),
|
|
82
|
+
v.literal("voice"),
|
|
83
|
+
v.literal("document"),
|
|
84
|
+
),
|
|
85
|
+
status: v.union(v.literal("ready"), v.literal("expired")),
|
|
86
|
+
storageId: v.id("_storage"),
|
|
87
|
+
telegramFileId: v.string(),
|
|
88
|
+
fileName: v.optional(v.string()),
|
|
89
|
+
mimeType: v.optional(v.string()),
|
|
90
|
+
sizeBytes: v.optional(v.number()),
|
|
91
|
+
expiresAt: v.number(),
|
|
92
|
+
}),
|
|
93
|
+
),
|
|
94
|
+
),
|
|
75
95
|
}),
|
|
76
96
|
status: v.union(
|
|
77
97
|
v.literal("queued"),
|
|
@@ -152,11 +172,37 @@ export default defineSchema({
|
|
|
152
172
|
messageConfig: v.optional(
|
|
153
173
|
v.object({
|
|
154
174
|
systemPrompt: v.optional(v.string()),
|
|
175
|
+
telegramAttachmentRetentionMs: v.optional(v.number()),
|
|
155
176
|
}),
|
|
156
177
|
),
|
|
157
178
|
updatedAt: v.number(),
|
|
158
179
|
}).index("by_key", ["key"]),
|
|
159
180
|
|
|
181
|
+
messageAttachments: defineTable({
|
|
182
|
+
messageId: v.id("messageQueue"),
|
|
183
|
+
conversationId: v.string(),
|
|
184
|
+
agentKey: v.string(),
|
|
185
|
+
provider: v.string(),
|
|
186
|
+
kind: v.union(
|
|
187
|
+
v.literal("photo"),
|
|
188
|
+
v.literal("video"),
|
|
189
|
+
v.literal("audio"),
|
|
190
|
+
v.literal("voice"),
|
|
191
|
+
v.literal("document"),
|
|
192
|
+
),
|
|
193
|
+
status: v.union(v.literal("ready"), v.literal("expired")),
|
|
194
|
+
storageId: v.id("_storage"),
|
|
195
|
+
telegramFileId: v.string(),
|
|
196
|
+
fileName: v.optional(v.string()),
|
|
197
|
+
mimeType: v.optional(v.string()),
|
|
198
|
+
sizeBytes: v.optional(v.number()),
|
|
199
|
+
createdAt: v.number(),
|
|
200
|
+
expiresAt: v.number(),
|
|
201
|
+
})
|
|
202
|
+
.index("by_messageId", ["messageId"])
|
|
203
|
+
.index("by_status_and_expiresAt", ["status", "expiresAt"])
|
|
204
|
+
.index("by_conversationId_and_createdAt", ["conversationId", "createdAt"]),
|
|
205
|
+
|
|
160
206
|
dataSnapshots: defineTable({
|
|
161
207
|
workspaceId: v.string(),
|
|
162
208
|
agentKey: v.string(),
|