@poolzin/pool-bot 2026.2.0 → 2026.2.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/agents/bash-tools.exec.js +76 -25
- package/dist/agents/cli-runner/helpers.js +9 -11
- package/dist/agents/identity.js +47 -7
- package/dist/agents/memory-search.js +25 -8
- package/dist/agents/model-selection.js +21 -0
- package/dist/agents/pi-embedded-block-chunker.js +117 -42
- package/dist/agents/pi-embedded-helpers/errors.js +183 -78
- package/dist/agents/pi-embedded-helpers.js +1 -1
- package/dist/agents/pi-embedded-runner/compact.js +1 -0
- package/dist/agents/pi-embedded-runner/model.js +61 -2
- package/dist/agents/pi-embedded-runner/run/attempt.js +21 -11
- package/dist/agents/pi-embedded-runner/run.js +199 -46
- package/dist/agents/pi-embedded-runner/system-prompt.js +10 -2
- package/dist/agents/pi-embedded-subscribe.js +118 -29
- package/dist/agents/pi-tools.js +10 -5
- package/dist/agents/poolbot-tools.js +15 -10
- package/dist/agents/sandbox-paths.js +31 -0
- package/dist/agents/session-tool-result-guard.js +94 -15
- package/dist/agents/shell-utils.js +51 -0
- package/dist/agents/skills/bundled-context.js +23 -0
- package/dist/agents/skills/bundled-dir.js +41 -7
- package/dist/agents/skills-install.js +60 -23
- package/dist/agents/subagent-announce.js +79 -34
- package/dist/agents/tool-policy.conformance.js +14 -0
- package/dist/agents/tool-policy.js +24 -0
- package/dist/agents/tools/cron-tool.js +166 -19
- package/dist/agents/tools/discord-actions-presence.js +78 -0
- package/dist/agents/tools/message-tool.js +56 -2
- package/dist/agents/tools/sessions-history-tool.js +69 -1
- package/dist/agents/tools/web-search.js +211 -42
- package/dist/agents/usage.js +23 -1
- package/dist/agents/workspace-run.js +67 -0
- package/dist/agents/workspace-templates.js +44 -0
- package/dist/auto-reply/command-auth.js +121 -6
- package/dist/auto-reply/envelope.js +50 -72
- package/dist/auto-reply/reply/commands-compact.js +1 -0
- package/dist/auto-reply/reply/commands-context-report.js +1 -0
- package/dist/auto-reply/reply/commands-context.js +1 -0
- package/dist/auto-reply/reply/commands-models.js +107 -60
- package/dist/auto-reply/reply/commands-ptt.js +171 -0
- package/dist/auto-reply/reply/get-reply-run.js +2 -1
- package/dist/auto-reply/reply/inbound-context.js +5 -1
- package/dist/auto-reply/reply/model-selection.js +3 -3
- package/dist/auto-reply/thinking.js +88 -43
- package/dist/browser/bridge-server.js +13 -0
- package/dist/browser/cdp.helpers.js +38 -24
- package/dist/browser/client-fetch.js +50 -7
- package/dist/browser/config.js +1 -10
- package/dist/browser/extension-relay.js +101 -40
- package/dist/browser/pw-ai.js +1 -1
- package/dist/browser/pw-session.js +143 -8
- package/dist/browser/pw-tools-core.interactions.js +125 -27
- package/dist/browser/pw-tools-core.responses.js +1 -1
- package/dist/browser/pw-tools-core.state.js +1 -1
- package/dist/browser/routes/agent.act.js +86 -41
- package/dist/browser/routes/dispatcher.js +4 -4
- package/dist/browser/screenshot.js +1 -1
- package/dist/browser/server.js +13 -0
- package/dist/build-info.json +3 -3
- package/dist/channels/reply-prefix.js +8 -1
- package/dist/cli/cron-cli/register.cron-add.js +61 -40
- package/dist/cli/cron-cli/register.cron-edit.js +60 -34
- package/dist/cli/cron-cli/shared.js +56 -41
- package/dist/cli/dns-cli.js +26 -14
- package/dist/cli/gateway-cli/register.js +37 -19
- package/dist/cli/memory-cli.js +5 -5
- package/dist/cli/parse-bytes.js +37 -0
- package/dist/cli/update-cli.js +173 -52
- package/dist/commands/agent.js +1 -0
- package/dist/commands/doctor-config-flow.js +61 -5
- package/dist/commands/doctor-state-migrations.js +1 -1
- package/dist/commands/health.js +1 -1
- package/dist/commands/model-allowlist.js +29 -0
- package/dist/commands/model-picker.js +2 -1
- package/dist/commands/models/list.status-command.js +43 -23
- package/dist/commands/models/shared.js +15 -0
- package/dist/commands/onboard-custom.js +384 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice-inference.js +35 -0
- package/dist/commands/onboard-non-interactive/local/auth-choice.js +6 -3
- package/dist/commands/onboard-skills.js +63 -38
- package/dist/commands/openai-model-default.js +41 -0
- package/dist/config/defaults.js +3 -2
- package/dist/config/paths.js +136 -35
- package/dist/config/plugin-auto-enable.js +21 -5
- package/dist/config/redact-snapshot.js +153 -0
- package/dist/config/schema.field-metadata.js +590 -0
- package/dist/config/schema.js +2 -2
- package/dist/config/sessions/store.js +291 -23
- package/dist/config/zod-schema.agent-defaults.js +3 -0
- package/dist/config/zod-schema.agent-runtime.js +13 -2
- package/dist/config/zod-schema.providers-core.js +142 -0
- package/dist/config/zod-schema.session.js +3 -0
- package/dist/cron/delivery.js +57 -0
- package/dist/cron/isolated-agent/delivery-target.js +18 -3
- package/dist/cron/isolated-agent/helpers.js +22 -5
- package/dist/cron/isolated-agent/run.js +171 -63
- package/dist/cron/isolated-agent/session.js +2 -0
- package/dist/cron/normalize.js +356 -28
- package/dist/cron/parse.js +10 -5
- package/dist/cron/run-log.js +35 -10
- package/dist/cron/schedule.js +41 -6
- package/dist/cron/service/jobs.js +208 -35
- package/dist/cron/service/ops.js +72 -16
- package/dist/cron/service/state.js +2 -0
- package/dist/cron/service/store.js +386 -14
- package/dist/cron/service/timer.js +390 -147
- package/dist/cron/session-reaper.js +86 -0
- package/dist/cron/store.js +23 -8
- package/dist/cron/validate-timestamp.js +43 -0
- package/dist/discord/monitor/agent-components.js +438 -0
- package/dist/discord/monitor/allow-list.js +28 -5
- package/dist/discord/monitor/gateway-registry.js +29 -0
- package/dist/discord/monitor/native-command.js +44 -23
- package/dist/discord/monitor/sender-identity.js +45 -0
- package/dist/discord/pluralkit.js +27 -0
- package/dist/discord/send.outbound.js +92 -5
- package/dist/discord/send.shared.js +60 -23
- package/dist/discord/targets.js +84 -1
- package/dist/entry.js +15 -9
- package/dist/extensionAPI.js +8 -0
- package/dist/gateway/control-ui.js +8 -1
- package/dist/gateway/hooks-mapping.js +3 -0
- package/dist/gateway/hooks.js +65 -0
- package/dist/gateway/net.js +96 -31
- package/dist/gateway/node-command-policy.js +50 -15
- package/dist/gateway/origin-check.js +56 -0
- package/dist/gateway/protocol/client-info.js +9 -0
- package/dist/gateway/protocol/index.js +9 -2
- package/dist/gateway/protocol/schema/agents-models-skills.js +71 -1
- package/dist/gateway/protocol/schema/cron.js +22 -10
- package/dist/gateway/protocol/schema/protocol-schemas.js +16 -2
- package/dist/gateway/protocol/schema/sessions.js +12 -0
- package/dist/gateway/server/hooks.js +1 -1
- package/dist/gateway/server-broadcast.js +26 -9
- package/dist/gateway/server-chat.js +112 -23
- package/dist/gateway/server-discovery-runtime.js +10 -2
- package/dist/gateway/server-http.js +109 -11
- package/dist/gateway/server-methods/agent-timestamp.js +60 -0
- package/dist/gateway/server-methods/agents.js +321 -2
- package/dist/gateway/server-methods/usage.js +559 -16
- package/dist/gateway/server-runtime-state.js +22 -8
- package/dist/gateway/server-startup-memory.js +16 -0
- package/dist/gateway/server.impl.js +5 -1
- package/dist/gateway/session-utils.fs.js +23 -25
- package/dist/gateway/session-utils.js +20 -10
- package/dist/gateway/sessions-patch.js +7 -22
- package/dist/gateway/test-helpers.server.js +35 -2
- package/dist/imessage/constants.js +2 -0
- package/dist/imessage/monitor/deliver.js +4 -1
- package/dist/imessage/monitor/monitor-provider.js +51 -1
- package/dist/infra/bonjour-discovery.js +131 -70
- package/dist/infra/control-ui-assets.js +134 -12
- package/dist/infra/errors.js +12 -0
- package/dist/infra/exec-approvals.js +266 -57
- package/dist/infra/format-time/format-datetime.js +79 -0
- package/dist/infra/format-time/format-duration.js +81 -0
- package/dist/infra/format-time/format-relative.js +80 -0
- package/dist/infra/heartbeat-runner.js +140 -49
- package/dist/infra/home-dir.js +54 -0
- package/dist/infra/net/fetch-guard.js +122 -0
- package/dist/infra/net/ssrf.js +65 -29
- package/dist/infra/outbound/abort.js +14 -0
- package/dist/infra/outbound/message-action-runner.js +77 -13
- package/dist/infra/outbound/outbound-session.js +143 -37
- package/dist/infra/poolbot-root.js +43 -1
- package/dist/infra/session-cost-usage.js +631 -41
- package/dist/infra/state-migrations.js +317 -47
- package/dist/infra/update-global.js +35 -0
- package/dist/infra/update-runner.js +149 -43
- package/dist/infra/warning-filter.js +65 -0
- package/dist/infra/widearea-dns.js +30 -9
- package/dist/logging/redact-identifier.js +12 -0
- package/dist/media/fetch.js +81 -58
- package/dist/media-understanding/apply.js +403 -3
- package/dist/media-understanding/attachments.js +38 -27
- package/dist/media-understanding/defaults.js +16 -0
- package/dist/media-understanding/providers/deepgram/audio.js +22 -14
- package/dist/media-understanding/providers/google/audio.js +24 -17
- package/dist/media-understanding/providers/google/video.js +24 -17
- package/dist/media-understanding/providers/image.js +2 -2
- package/dist/media-understanding/providers/index.js +4 -1
- package/dist/media-understanding/providers/openai/audio.js +22 -14
- package/dist/media-understanding/providers/shared.js +16 -11
- package/dist/media-understanding/providers/zai/index.js +6 -0
- package/dist/media-understanding/runner.js +158 -90
- package/dist/memory/batch-voyage.js +277 -0
- package/dist/memory/embeddings-voyage.js +75 -0
- package/dist/memory/embeddings.js +28 -16
- package/dist/memory/internal.js +101 -18
- package/dist/memory/manager.js +154 -48
- package/dist/memory/search-manager.js +173 -0
- package/dist/memory/session-files.js +9 -3
- package/dist/node-host/runner.js +34 -24
- package/dist/node-host/with-timeout.js +27 -0
- package/dist/plugins/commands.js +5 -1
- package/dist/plugins/config-state.js +86 -7
- package/dist/plugins/source-display.js +51 -0
- package/dist/process/exec.js +20 -2
- package/dist/routing/resolve-route.js +12 -0
- package/dist/routing/session-key.js +15 -0
- package/dist/runtime.js +2 -0
- package/dist/security/audit-extra.async.js +601 -0
- package/dist/security/audit-extra.js +2 -830
- package/dist/security/audit-extra.sync.js +505 -0
- package/dist/security/channel-metadata.js +34 -0
- package/dist/security/external-content.js +88 -6
- package/dist/security/skill-scanner.js +330 -0
- package/dist/sessions/session-key-utils.js +7 -0
- package/dist/signal/monitor/event-handler.js +80 -1
- package/dist/slack/monitor/media.js +85 -15
- package/dist/tailscale/detect.js +1 -2
- package/dist/telegram/bot/helpers.js +109 -28
- package/dist/telegram/bot-handlers.js +144 -3
- package/dist/telegram/bot-message-context.js +37 -10
- package/dist/telegram/bot-message-dispatch.js +48 -15
- package/dist/telegram/bot-native-commands.js +86 -29
- package/dist/telegram/bot.js +30 -29
- package/dist/telegram/model-buttons.js +163 -0
- package/dist/telegram/monitor.js +110 -85
- package/dist/telegram/send.js +129 -47
- package/dist/terminal/restore.js +45 -0
- package/dist/test-helpers/state-dir-env.js +16 -0
- package/dist/tts/tts.js +12 -6
- package/dist/tui/tui-session-actions.js +166 -54
- package/dist/utils/fetch-timeout.js +20 -0
- package/dist/utils/normalize-secret-input.js +19 -0
- package/dist/utils/transcript-tools.js +58 -0
- package/dist/utils.js +45 -14
- package/dist/version.js +42 -5
- package/package.json +1 -1
|
@@ -25,6 +25,7 @@ export const TelegramTopicSchema = z
|
|
|
25
25
|
export const TelegramGroupSchema = z
|
|
26
26
|
.object({
|
|
27
27
|
requireMention: z.boolean().optional(),
|
|
28
|
+
groupPolicy: GroupPolicySchema.optional(),
|
|
28
29
|
tools: ToolPolicySchema,
|
|
29
30
|
toolsBySender: ToolPolicyBySenderSchema,
|
|
30
31
|
skills: z.array(z.string()).optional(),
|
|
@@ -108,6 +109,7 @@ export const TelegramAccountSchemaBase = z
|
|
|
108
109
|
reactionLevel: z.enum(["off", "ack", "minimal", "extensive"]).optional(),
|
|
109
110
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
110
111
|
linkPreview: z.boolean().optional(),
|
|
112
|
+
responsePrefix: z.string().optional(),
|
|
111
113
|
})
|
|
112
114
|
.strict();
|
|
113
115
|
export const TelegramAccountSchema = TelegramAccountSchemaBase.superRefine((value, ctx) => {
|
|
@@ -131,6 +133,38 @@ export const TelegramConfigSchema = TelegramAccountSchemaBase.extend({
|
|
|
131
133
|
message: 'channels.telegram.dmPolicy="open" requires channels.telegram.allowFrom to include "*"',
|
|
132
134
|
});
|
|
133
135
|
validateTelegramCustomCommands(value, ctx);
|
|
136
|
+
const baseWebhookUrl = typeof value.webhookUrl === "string" ? value.webhookUrl.trim() : "";
|
|
137
|
+
const baseWebhookSecret = typeof value.webhookSecret === "string" ? value.webhookSecret.trim() : "";
|
|
138
|
+
if (baseWebhookUrl && !baseWebhookSecret) {
|
|
139
|
+
ctx.addIssue({
|
|
140
|
+
code: z.ZodIssueCode.custom,
|
|
141
|
+
message: "channels.telegram.webhookUrl requires channels.telegram.webhookSecret",
|
|
142
|
+
path: ["webhookSecret"],
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (!value.accounts) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
for (const [accountId, account] of Object.entries(value.accounts)) {
|
|
149
|
+
if (!account) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (account.enabled === false) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const accountWebhookUrl = typeof account.webhookUrl === "string" ? account.webhookUrl.trim() : "";
|
|
156
|
+
if (!accountWebhookUrl) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const accountSecret = typeof account.webhookSecret === "string" ? account.webhookSecret.trim() : "";
|
|
160
|
+
if (!accountSecret && !baseWebhookSecret) {
|
|
161
|
+
ctx.addIssue({
|
|
162
|
+
code: z.ZodIssueCode.custom,
|
|
163
|
+
message: "channels.telegram.accounts.*.webhookUrl requires channels.telegram.webhookSecret or channels.telegram.accounts.*.webhookSecret",
|
|
164
|
+
path: ["accounts", accountId, "webhookSecret"],
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
134
168
|
});
|
|
135
169
|
export const DiscordDmSchema = z
|
|
136
170
|
.object({
|
|
@@ -160,6 +194,7 @@ export const DiscordGuildChannelSchema = z
|
|
|
160
194
|
enabled: z.boolean().optional(),
|
|
161
195
|
users: z.array(z.union([z.string(), z.number()])).optional(),
|
|
162
196
|
systemPrompt: z.string().optional(),
|
|
197
|
+
includeThreadStarter: z.boolean().optional(),
|
|
163
198
|
autoThread: z.boolean().optional(),
|
|
164
199
|
})
|
|
165
200
|
.strict();
|
|
@@ -215,6 +250,7 @@ export const DiscordAccountSchema = z
|
|
|
215
250
|
events: z.boolean().optional(),
|
|
216
251
|
moderation: z.boolean().optional(),
|
|
217
252
|
channels: z.boolean().optional(),
|
|
253
|
+
presence: z.boolean().optional(),
|
|
218
254
|
})
|
|
219
255
|
.strict()
|
|
220
256
|
.optional(),
|
|
@@ -228,6 +264,7 @@ export const DiscordAccountSchema = z
|
|
|
228
264
|
approvers: z.array(z.union([z.string(), z.number()])).optional(),
|
|
229
265
|
agentFilter: z.array(z.string()).optional(),
|
|
230
266
|
sessionFilter: z.array(z.string()).optional(),
|
|
267
|
+
cleanupAfterResolve: z.boolean().optional(),
|
|
231
268
|
})
|
|
232
269
|
.strict()
|
|
233
270
|
.optional(),
|
|
@@ -238,6 +275,14 @@ export const DiscordAccountSchema = z
|
|
|
238
275
|
})
|
|
239
276
|
.strict()
|
|
240
277
|
.optional(),
|
|
278
|
+
pluralkit: z
|
|
279
|
+
.object({
|
|
280
|
+
enabled: z.boolean().optional(),
|
|
281
|
+
token: z.string().optional(),
|
|
282
|
+
})
|
|
283
|
+
.strict()
|
|
284
|
+
.optional(),
|
|
285
|
+
responsePrefix: z.string().optional(),
|
|
241
286
|
})
|
|
242
287
|
.strict();
|
|
243
288
|
export const DiscordConfigSchema = DiscordAccountSchema.extend({
|
|
@@ -303,6 +348,7 @@ export const GoogleChatAccountSchema = z
|
|
|
303
348
|
.optional(),
|
|
304
349
|
dm: GoogleChatDmSchema.optional(),
|
|
305
350
|
typingIndicator: z.enum(["none", "message", "reaction"]).optional(),
|
|
351
|
+
responsePrefix: z.string().optional(),
|
|
306
352
|
})
|
|
307
353
|
.strict();
|
|
308
354
|
export const GoogleChatConfigSchema = GoogleChatAccountSchema.extend({
|
|
@@ -410,6 +456,7 @@ export const SlackAccountSchema = z
|
|
|
410
456
|
dm: SlackDmSchema.optional(),
|
|
411
457
|
channels: z.record(z.string(), SlackChannelSchema.optional()).optional(),
|
|
412
458
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
459
|
+
responsePrefix: z.string().optional(),
|
|
413
460
|
})
|
|
414
461
|
.strict();
|
|
415
462
|
export const SlackConfigSchema = SlackAccountSchema.extend({
|
|
@@ -486,6 +533,7 @@ export const SignalAccountSchemaBase = z
|
|
|
486
533
|
.optional(),
|
|
487
534
|
reactionLevel: z.enum(["off", "ack", "minimal", "extensive"]).optional(),
|
|
488
535
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
536
|
+
responsePrefix: z.string().optional(),
|
|
489
537
|
})
|
|
490
538
|
.strict();
|
|
491
539
|
export const SignalAccountSchema = SignalAccountSchemaBase.superRefine((value, ctx) => {
|
|
@@ -508,6 +556,96 @@ export const SignalConfigSchema = SignalAccountSchemaBase.extend({
|
|
|
508
556
|
message: 'channels.signal.dmPolicy="open" requires channels.signal.allowFrom to include "*"',
|
|
509
557
|
});
|
|
510
558
|
});
|
|
559
|
+
export const IrcGroupSchema = z
|
|
560
|
+
.object({
|
|
561
|
+
requireMention: z.boolean().optional(),
|
|
562
|
+
tools: ToolPolicySchema,
|
|
563
|
+
toolsBySender: ToolPolicyBySenderSchema,
|
|
564
|
+
skills: z.array(z.string()).optional(),
|
|
565
|
+
enabled: z.boolean().optional(),
|
|
566
|
+
allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
567
|
+
systemPrompt: z.string().optional(),
|
|
568
|
+
})
|
|
569
|
+
.strict();
|
|
570
|
+
export const IrcNickServSchema = z
|
|
571
|
+
.object({
|
|
572
|
+
enabled: z.boolean().optional(),
|
|
573
|
+
service: z.string().optional(),
|
|
574
|
+
password: z.string().optional(),
|
|
575
|
+
passwordFile: z.string().optional(),
|
|
576
|
+
register: z.boolean().optional(),
|
|
577
|
+
registerEmail: z.string().optional(),
|
|
578
|
+
})
|
|
579
|
+
.strict();
|
|
580
|
+
export const IrcAccountSchemaBase = z
|
|
581
|
+
.object({
|
|
582
|
+
name: z.string().optional(),
|
|
583
|
+
capabilities: z.array(z.string()).optional(),
|
|
584
|
+
markdown: MarkdownConfigSchema,
|
|
585
|
+
enabled: z.boolean().optional(),
|
|
586
|
+
configWrites: z.boolean().optional(),
|
|
587
|
+
host: z.string().optional(),
|
|
588
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
589
|
+
tls: z.boolean().optional(),
|
|
590
|
+
nick: z.string().optional(),
|
|
591
|
+
username: z.string().optional(),
|
|
592
|
+
realname: z.string().optional(),
|
|
593
|
+
password: z.string().optional(),
|
|
594
|
+
passwordFile: z.string().optional(),
|
|
595
|
+
nickserv: IrcNickServSchema.optional(),
|
|
596
|
+
channels: z.array(z.string()).optional(),
|
|
597
|
+
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
|
598
|
+
allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
599
|
+
groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
600
|
+
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
|
601
|
+
groups: z.record(z.string(), IrcGroupSchema.optional()).optional(),
|
|
602
|
+
mentionPatterns: z.array(z.string()).optional(),
|
|
603
|
+
historyLimit: z.number().int().min(0).optional(),
|
|
604
|
+
dmHistoryLimit: z.number().int().min(0).optional(),
|
|
605
|
+
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
|
606
|
+
textChunkLimit: z.number().int().positive().optional(),
|
|
607
|
+
chunkMode: z.enum(["length", "newline"]).optional(),
|
|
608
|
+
blockStreaming: z.boolean().optional(),
|
|
609
|
+
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
|
610
|
+
mediaMaxMb: z.number().positive().optional(),
|
|
611
|
+
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
612
|
+
responsePrefix: z.string().optional(),
|
|
613
|
+
})
|
|
614
|
+
.strict();
|
|
615
|
+
export const IrcAccountSchema = IrcAccountSchemaBase.superRefine((value, ctx) => {
|
|
616
|
+
requireOpenAllowFrom({
|
|
617
|
+
policy: value.dmPolicy,
|
|
618
|
+
allowFrom: value.allowFrom,
|
|
619
|
+
ctx,
|
|
620
|
+
path: ["allowFrom"],
|
|
621
|
+
message: 'channels.irc.dmPolicy="open" requires channels.irc.allowFrom to include "*"',
|
|
622
|
+
});
|
|
623
|
+
if (value.nickserv?.register && !value.nickserv.registerEmail?.trim()) {
|
|
624
|
+
ctx.addIssue({
|
|
625
|
+
code: z.ZodIssueCode.custom,
|
|
626
|
+
path: ["nickserv", "registerEmail"],
|
|
627
|
+
message: "channels.irc.nickserv.register=true requires channels.irc.nickserv.registerEmail",
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
export const IrcConfigSchema = IrcAccountSchemaBase.extend({
|
|
632
|
+
accounts: z.record(z.string(), IrcAccountSchema.optional()).optional(),
|
|
633
|
+
}).superRefine((value, ctx) => {
|
|
634
|
+
requireOpenAllowFrom({
|
|
635
|
+
policy: value.dmPolicy,
|
|
636
|
+
allowFrom: value.allowFrom,
|
|
637
|
+
ctx,
|
|
638
|
+
path: ["allowFrom"],
|
|
639
|
+
message: 'channels.irc.dmPolicy="open" requires channels.irc.allowFrom to include "*"',
|
|
640
|
+
});
|
|
641
|
+
if (value.nickserv?.register && !value.nickserv.registerEmail?.trim()) {
|
|
642
|
+
ctx.addIssue({
|
|
643
|
+
code: z.ZodIssueCode.custom,
|
|
644
|
+
path: ["nickserv", "registerEmail"],
|
|
645
|
+
message: "channels.irc.nickserv.register=true requires channels.irc.nickserv.registerEmail",
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
});
|
|
511
649
|
export const IMessageAccountSchemaBase = z
|
|
512
650
|
.object({
|
|
513
651
|
name: z.string().optional(),
|
|
@@ -544,6 +682,7 @@ export const IMessageAccountSchemaBase = z
|
|
|
544
682
|
.optional())
|
|
545
683
|
.optional(),
|
|
546
684
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
685
|
+
responsePrefix: z.string().optional(),
|
|
547
686
|
})
|
|
548
687
|
.strict();
|
|
549
688
|
export const IMessageAccountSchema = IMessageAccountSchemaBase.superRefine((value, ctx) => {
|
|
@@ -615,6 +754,7 @@ export const BlueBubblesAccountSchemaBase = z
|
|
|
615
754
|
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
|
616
755
|
groups: z.record(z.string(), BlueBubblesGroupConfigSchema.optional()).optional(),
|
|
617
756
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
757
|
+
responsePrefix: z.string().optional(),
|
|
618
758
|
})
|
|
619
759
|
.strict();
|
|
620
760
|
export const BlueBubblesAccountSchema = BlueBubblesAccountSchemaBase.superRefine((value, ctx) => {
|
|
@@ -679,6 +819,7 @@ export const MSTeamsConfigSchema = z
|
|
|
679
819
|
chunkMode: z.enum(["length", "newline"]).optional(),
|
|
680
820
|
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
|
681
821
|
mediaAllowHosts: z.array(z.string()).optional(),
|
|
822
|
+
mediaAuthAllowHosts: z.array(z.string()).optional(),
|
|
682
823
|
requireMention: z.boolean().optional(),
|
|
683
824
|
historyLimit: z.number().int().min(0).optional(),
|
|
684
825
|
dmHistoryLimit: z.number().int().min(0).optional(),
|
|
@@ -690,6 +831,7 @@ export const MSTeamsConfigSchema = z
|
|
|
690
831
|
/** SharePoint site ID for file uploads in group chats/channels (e.g., "contoso.sharepoint.com,guid1,guid2") */
|
|
691
832
|
sharePointSiteId: z.string().optional(),
|
|
692
833
|
heartbeat: ChannelHeartbeatVisibilitySchema,
|
|
834
|
+
responsePrefix: z.string().optional(),
|
|
693
835
|
})
|
|
694
836
|
.strict()
|
|
695
837
|
.superRefine((value, ctx) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { ElevatedAllowFromSchema } from "./zod-schema.agent-runtime.js";
|
|
2
3
|
import { GroupChatSchema, InboundDebounceSchema, NativeCommandsSettingSchema, QueueSchema, TtsConfigSchema, } from "./zod-schema.core.js";
|
|
3
4
|
const SessionResetConfigSchema = z
|
|
4
5
|
.object({
|
|
@@ -94,6 +95,8 @@ export const CommandsSchema = z
|
|
|
94
95
|
debug: z.boolean().optional(),
|
|
95
96
|
restart: z.boolean().optional(),
|
|
96
97
|
useAccessGroups: z.boolean().optional(),
|
|
98
|
+
ownerAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
|
|
99
|
+
allowFrom: ElevatedAllowFromSchema.optional(),
|
|
97
100
|
})
|
|
98
101
|
.strict()
|
|
99
102
|
.optional()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
function normalizeChannel(value) {
|
|
2
|
+
if (typeof value !== "string") {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
const trimmed = value.trim().toLowerCase();
|
|
6
|
+
if (!trimmed) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return trimmed;
|
|
10
|
+
}
|
|
11
|
+
function normalizeTo(value) {
|
|
12
|
+
if (typeof value !== "string") {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
return trimmed ? trimmed : undefined;
|
|
17
|
+
}
|
|
18
|
+
export function resolveCronDeliveryPlan(job) {
|
|
19
|
+
const payload = job.payload.kind === "agentTurn" ? job.payload : null;
|
|
20
|
+
const delivery = job.delivery;
|
|
21
|
+
const hasDelivery = delivery && typeof delivery === "object";
|
|
22
|
+
const rawMode = hasDelivery ? delivery.mode : undefined;
|
|
23
|
+
const normalizedMode = typeof rawMode === "string" ? rawMode.trim().toLowerCase() : rawMode;
|
|
24
|
+
const mode = normalizedMode === "announce"
|
|
25
|
+
? "announce"
|
|
26
|
+
: normalizedMode === "none"
|
|
27
|
+
? "none"
|
|
28
|
+
: normalizedMode === "deliver"
|
|
29
|
+
? "announce"
|
|
30
|
+
: undefined;
|
|
31
|
+
const payloadChannel = normalizeChannel(payload?.channel);
|
|
32
|
+
const payloadTo = normalizeTo(payload?.to);
|
|
33
|
+
const deliveryChannel = normalizeChannel(delivery?.channel);
|
|
34
|
+
const deliveryTo = normalizeTo(delivery?.to);
|
|
35
|
+
const channel = deliveryChannel ?? payloadChannel ?? "last";
|
|
36
|
+
const to = deliveryTo ?? payloadTo;
|
|
37
|
+
if (hasDelivery) {
|
|
38
|
+
const resolvedMode = mode ?? "announce";
|
|
39
|
+
return {
|
|
40
|
+
mode: resolvedMode,
|
|
41
|
+
channel,
|
|
42
|
+
to,
|
|
43
|
+
source: "delivery",
|
|
44
|
+
requested: resolvedMode === "announce",
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const legacyMode = payload?.deliver === true ? "explicit" : payload?.deliver === false ? "off" : "auto";
|
|
48
|
+
const hasExplicitTarget = Boolean(to);
|
|
49
|
+
const requested = legacyMode === "explicit" || (legacyMode === "auto" && hasExplicitTarget);
|
|
50
|
+
return {
|
|
51
|
+
mode: requested ? "announce" : "none",
|
|
52
|
+
channel,
|
|
53
|
+
to,
|
|
54
|
+
source: "payload",
|
|
55
|
+
requested,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -5,6 +5,7 @@ import { resolveOutboundTarget, resolveSessionDeliveryTarget, } from "../../infr
|
|
|
5
5
|
export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
6
6
|
const requestedChannel = typeof jobPayload.channel === "string" ? jobPayload.channel : "last";
|
|
7
7
|
const explicitTo = typeof jobPayload.to === "string" ? jobPayload.to : undefined;
|
|
8
|
+
const allowMismatchedLastTo = requestedChannel === "last";
|
|
8
9
|
const sessionCfg = cfg.session;
|
|
9
10
|
const mainSessionKey = resolveAgentMainSessionKey({ cfg, agentId });
|
|
10
11
|
const storePath = resolveStorePath(sessionCfg?.store, { agentId });
|
|
@@ -14,7 +15,7 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
14
15
|
entry: main,
|
|
15
16
|
requestedChannel,
|
|
16
17
|
explicitTo,
|
|
17
|
-
allowMismatchedLastTo
|
|
18
|
+
allowMismatchedLastTo,
|
|
18
19
|
});
|
|
19
20
|
let fallbackChannel;
|
|
20
21
|
if (!preliminary.channel) {
|
|
@@ -32,15 +33,28 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
32
33
|
requestedChannel,
|
|
33
34
|
explicitTo,
|
|
34
35
|
fallbackChannel,
|
|
35
|
-
allowMismatchedLastTo
|
|
36
|
+
allowMismatchedLastTo,
|
|
36
37
|
mode: preliminary.mode,
|
|
37
38
|
})
|
|
38
39
|
: preliminary;
|
|
39
40
|
const channel = resolved.channel ?? fallbackChannel ?? DEFAULT_CHAT_CHANNEL;
|
|
40
41
|
const mode = resolved.mode;
|
|
41
42
|
const toCandidate = resolved.to;
|
|
43
|
+
// Only carry threadId when delivering to the same recipient as the session's
|
|
44
|
+
// last conversation. This prevents stale thread IDs (e.g. from a Telegram
|
|
45
|
+
// supergroup topic) from being sent to a different target (e.g. a private
|
|
46
|
+
// chat) where they would cause API errors.
|
|
47
|
+
const threadId = resolved.threadId && resolved.to && resolved.to === resolved.lastTo
|
|
48
|
+
? resolved.threadId
|
|
49
|
+
: undefined;
|
|
42
50
|
if (!toCandidate) {
|
|
43
|
-
return {
|
|
51
|
+
return {
|
|
52
|
+
channel,
|
|
53
|
+
to: undefined,
|
|
54
|
+
accountId: resolved.accountId,
|
|
55
|
+
threadId,
|
|
56
|
+
mode,
|
|
57
|
+
};
|
|
44
58
|
}
|
|
45
59
|
const docked = resolveOutboundTarget({
|
|
46
60
|
channel,
|
|
@@ -53,6 +67,7 @@ export async function resolveDeliveryTarget(cfg, agentId, jobPayload) {
|
|
|
53
67
|
channel,
|
|
54
68
|
to: docked.ok ? docked.to : undefined,
|
|
55
69
|
accountId: resolved.accountId,
|
|
70
|
+
threadId,
|
|
56
71
|
mode,
|
|
57
72
|
error: docked.ok ? undefined : docked.error,
|
|
58
73
|
};
|
|
@@ -2,24 +2,39 @@ import { DEFAULT_HEARTBEAT_ACK_MAX_CHARS, stripHeartbeatToken, } from "../../aut
|
|
|
2
2
|
import { truncateUtf16Safe } from "../../utils.js";
|
|
3
3
|
export function pickSummaryFromOutput(text) {
|
|
4
4
|
const clean = (text ?? "").trim();
|
|
5
|
-
if (!clean)
|
|
5
|
+
if (!clean) {
|
|
6
6
|
return undefined;
|
|
7
|
+
}
|
|
7
8
|
const limit = 2000;
|
|
8
9
|
return clean.length > limit ? `${truncateUtf16Safe(clean, limit)}…` : clean;
|
|
9
10
|
}
|
|
10
11
|
export function pickSummaryFromPayloads(payloads) {
|
|
11
12
|
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
12
13
|
const summary = pickSummaryFromOutput(payloads[i]?.text);
|
|
13
|
-
if (summary)
|
|
14
|
+
if (summary) {
|
|
14
15
|
return summary;
|
|
16
|
+
}
|
|
15
17
|
}
|
|
16
18
|
return undefined;
|
|
17
19
|
}
|
|
18
20
|
export function pickLastNonEmptyTextFromPayloads(payloads) {
|
|
19
21
|
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
20
22
|
const clean = (payloads[i]?.text ?? "").trim();
|
|
21
|
-
if (clean)
|
|
23
|
+
if (clean) {
|
|
22
24
|
return clean;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
export function pickLastDeliverablePayload(payloads) {
|
|
30
|
+
for (let i = payloads.length - 1; i >= 0; i--) {
|
|
31
|
+
const payload = payloads[i];
|
|
32
|
+
const text = (payload?.text ?? "").trim();
|
|
33
|
+
const hasMedia = Boolean(payload?.mediaUrl) || (payload?.mediaUrls?.length ?? 0) > 0;
|
|
34
|
+
const hasChannelData = Object.keys(payload?.channelData ?? {}).length > 0;
|
|
35
|
+
if (text || hasMedia || hasChannelData) {
|
|
36
|
+
return payload;
|
|
37
|
+
}
|
|
23
38
|
}
|
|
24
39
|
return undefined;
|
|
25
40
|
}
|
|
@@ -28,13 +43,15 @@ export function pickLastNonEmptyTextFromPayloads(payloads) {
|
|
|
28
43
|
* Returns true if delivery should be skipped because there's no real content.
|
|
29
44
|
*/
|
|
30
45
|
export function isHeartbeatOnlyResponse(payloads, ackMaxChars) {
|
|
31
|
-
if (payloads.length === 0)
|
|
46
|
+
if (payloads.length === 0) {
|
|
32
47
|
return true;
|
|
48
|
+
}
|
|
33
49
|
return payloads.every((payload) => {
|
|
34
50
|
// If there's media, we should deliver regardless of text content.
|
|
35
51
|
const hasMedia = (payload.mediaUrls?.length ?? 0) > 0 || Boolean(payload.mediaUrl);
|
|
36
|
-
if (hasMedia)
|
|
52
|
+
if (hasMedia) {
|
|
37
53
|
return false;
|
|
54
|
+
}
|
|
38
55
|
// Use heartbeat mode to check if text is just HEARTBEAT_OK or short ack.
|
|
39
56
|
const result = stripHeartbeatToken(payload.text, {
|
|
40
57
|
mode: "heartbeat",
|