@agent-native/dispatch 0.13.9 → 0.13.11
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 +7 -28
- package/dist/actions/navigate.js +1 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/components/agents-panel.js +3 -3
- package/dist/components/agents-panel.js.map +1 -1
- package/dist/components/app-keys-popover.d.ts.map +1 -1
- package/dist/components/app-keys-popover.js +3 -3
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +2 -2
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-control-plane.d.ts.map +1 -1
- package/dist/components/dispatch-control-plane.js +19 -7
- package/dist/components/dispatch-control-plane.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +2 -2
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/layout/Header.js +2 -1
- package/dist/components/layout/Header.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +12 -5
- package/dist/components/layout/Layout.js.map +1 -1
- package/dist/components/messaging-setup-panel.d.ts.map +1 -1
- package/dist/components/messaging-setup-panel.js +4 -4
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/task-queue-health.d.ts +2 -0
- package/dist/components/task-queue-health.d.ts.map +1 -0
- package/dist/components/task-queue-health.js +49 -0
- package/dist/components/task-queue-health.js.map +1 -0
- package/dist/components/ui/accordion.js.map +1 -1
- package/dist/components/ui/alert-dialog.js +1 -1
- package/dist/components/ui/alert-dialog.js.map +1 -1
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/avatar.js.map +1 -1
- package/dist/components/ui/badge.js.map +1 -1
- package/dist/components/ui/breadcrumb.js.map +1 -1
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/calendar.js.map +1 -1
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/carousel.d.ts +2 -2
- package/dist/components/ui/carousel.d.ts.map +1 -1
- package/dist/components/ui/carousel.js +1 -1
- package/dist/components/ui/carousel.js.map +1 -1
- package/dist/components/ui/chart.js.map +1 -1
- package/dist/components/ui/checkbox.js.map +1 -1
- package/dist/components/ui/command.js +1 -1
- package/dist/components/ui/command.js.map +1 -1
- package/dist/components/ui/context-menu.js.map +1 -1
- package/dist/components/ui/dialog.js.map +1 -1
- package/dist/components/ui/drawer.js.map +1 -1
- package/dist/components/ui/dropdown-menu.js.map +1 -1
- package/dist/components/ui/form.js +1 -1
- package/dist/components/ui/form.js.map +1 -1
- package/dist/components/ui/hover-card.js.map +1 -1
- package/dist/components/ui/input-otp.js.map +1 -1
- package/dist/components/ui/input.js.map +1 -1
- package/dist/components/ui/label.js.map +1 -1
- package/dist/components/ui/menubar.js.map +1 -1
- package/dist/components/ui/navigation-menu.js.map +1 -1
- package/dist/components/ui/pagination.d.ts +1 -1
- package/dist/components/ui/pagination.d.ts.map +1 -1
- package/dist/components/ui/pagination.js +1 -1
- package/dist/components/ui/pagination.js.map +1 -1
- package/dist/components/ui/popover.js.map +1 -1
- package/dist/components/ui/progress.js.map +1 -1
- package/dist/components/ui/radio-group.js.map +1 -1
- package/dist/components/ui/resizable.js.map +1 -1
- package/dist/components/ui/scroll-area.js.map +1 -1
- package/dist/components/ui/select.js.map +1 -1
- package/dist/components/ui/separator.js.map +1 -1
- package/dist/components/ui/sheet.js.map +1 -1
- package/dist/components/ui/sidebar.d.ts +2 -2
- package/dist/components/ui/sidebar.d.ts.map +1 -1
- package/dist/components/ui/sidebar.js +6 -6
- package/dist/components/ui/sidebar.js.map +1 -1
- package/dist/components/ui/skeleton.js.map +1 -1
- package/dist/components/ui/slider.js.map +1 -1
- package/dist/components/ui/sonner.js.map +1 -1
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/switch.js.map +1 -1
- package/dist/components/ui/table.js.map +1 -1
- package/dist/components/ui/tabs.js.map +1 -1
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/components/ui/toast.js.map +1 -1
- package/dist/components/ui/toaster.js +1 -1
- package/dist/components/ui/toaster.js.map +1 -1
- package/dist/components/ui/toggle-group.js +1 -1
- package/dist/components/ui/toggle-group.js.map +1 -1
- package/dist/components/ui/toggle.js.map +1 -1
- package/dist/components/ui/tooltip.js.map +1 -1
- package/dist/components/ui/use-toast.d.ts.map +1 -1
- package/dist/components/ui/use-toast.js.map +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +10 -10
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-resource-effective-stack.js +1 -1
- package/dist/components/workspace-resource-effective-stack.js.map +1 -1
- package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -1
- package/dist/components/workspace-resource-impact-preview.js +2 -2
- package/dist/components/workspace-resource-impact-preview.js.map +1 -1
- package/dist/hooks/use-navigation-state.js +5 -0
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/hooks/use-toast.d.ts.map +1 -1
- package/dist/hooks/use-toast.js.map +1 -1
- package/dist/lib/automation-display.d.ts +13 -0
- package/dist/lib/automation-display.d.ts.map +1 -0
- package/dist/lib/automation-display.js +62 -0
- package/dist/lib/automation-display.js.map +1 -0
- package/dist/lib/task-queue.d.ts +19 -0
- package/dist/lib/task-queue.d.ts.map +1 -0
- package/dist/lib/task-queue.js +54 -0
- package/dist/lib/task-queue.js.map +1 -0
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +1 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/_index.js.map +1 -1
- package/dist/routes/pages/agents.d.ts.map +1 -1
- package/dist/routes/pages/agents.js +1 -1
- package/dist/routes/pages/agents.js.map +1 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/approvals.js.map +1 -1
- package/dist/routes/pages/apps.$appId.js.map +1 -1
- package/dist/routes/pages/apps.js.map +1 -1
- package/dist/routes/pages/audit.js.map +1 -1
- package/dist/routes/pages/automations.d.ts +5 -0
- package/dist/routes/pages/automations.d.ts.map +1 -0
- package/dist/routes/pages/automations.js +106 -0
- package/dist/routes/pages/automations.js.map +1 -0
- package/dist/routes/pages/chat.js.map +1 -1
- package/dist/routes/pages/destinations.d.ts.map +1 -1
- package/dist/routes/pages/destinations.js +31 -27
- package/dist/routes/pages/destinations.js.map +1 -1
- package/dist/routes/pages/dreams.d.ts.map +1 -1
- package/dist/routes/pages/dreams.js +1 -1
- package/dist/routes/pages/dreams.js.map +1 -1
- package/dist/routes/pages/identities.js.map +1 -1
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/messaging.js.map +1 -1
- package/dist/routes/pages/metrics.js.map +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/overview.d.ts +2 -2
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/settings.d.ts.map +1 -1
- package/dist/routes/pages/settings.js +2 -2
- package/dist/routes/pages/settings.js.map +1 -1
- package/dist/routes/pages/thread-debug.d.ts.map +1 -1
- package/dist/routes/pages/thread-debug.js +1 -1
- package/dist/routes/pages/thread-debug.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +1 -1
- package/dist/routes/pages/vault.js.map +1 -1
- package/dist/routes/pages/workspace.d.ts.map +1 -1
- package/dist/routes/pages/workspace.js +1 -1
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
- package/dist/server/lib/dispatch-integrations.js +39 -0
- package/dist/server/lib/dispatch-integrations.js.map +1 -1
- package/dist/server/lib/pre-auth-routing.d.ts.map +1 -1
- package/dist/server/lib/pre-auth-routing.js +1 -0
- package/dist/server/lib/pre-auth-routing.js.map +1 -1
- package/dist/server/plugins/integrations.d.ts.map +1 -1
- package/dist/server/plugins/integrations.js +12 -1
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +7 -7
- package/src/actions/navigate.ts +1 -1
- package/src/components/agents-panel.tsx +3 -3
- package/src/components/app-keys-popover.tsx +3 -7
- package/src/components/create-app-popover.tsx +2 -6
- package/src/components/dispatch-control-plane.tsx +48 -7
- package/src/components/dispatch-shell.tsx +2 -6
- package/src/components/layout/Header.tsx +2 -2
- package/src/components/layout/Layout.tsx +13 -15
- package/src/components/messaging-setup-panel.tsx +4 -8
- package/src/components/task-queue-health.tsx +166 -0
- package/src/components/ui/accordion.tsx +1 -1
- package/src/components/ui/alert-dialog.tsx +2 -2
- package/src/components/ui/alert.tsx +1 -1
- package/src/components/ui/avatar.tsx +1 -1
- package/src/components/ui/badge.tsx +1 -1
- package/src/components/ui/breadcrumb.tsx +1 -1
- package/src/components/ui/button.tsx +1 -1
- package/src/components/ui/calendar.tsx +2 -2
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/carousel.tsx +2 -2
- package/src/components/ui/chart.tsx +1 -1
- package/src/components/ui/checkbox.tsx +1 -1
- package/src/components/ui/command.tsx +2 -2
- package/src/components/ui/context-menu.tsx +1 -1
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/drawer.tsx +1 -1
- package/src/components/ui/dropdown-menu.tsx +1 -1
- package/src/components/ui/form.tsx +2 -2
- package/src/components/ui/hover-card.tsx +1 -1
- package/src/components/ui/input-otp.tsx +1 -1
- package/src/components/ui/input.tsx +1 -1
- package/src/components/ui/label.tsx +1 -1
- package/src/components/ui/menubar.tsx +1 -1
- package/src/components/ui/navigation-menu.tsx +1 -1
- package/src/components/ui/pagination.tsx +2 -2
- package/src/components/ui/popover.tsx +1 -1
- package/src/components/ui/progress.tsx +1 -1
- package/src/components/ui/radio-group.tsx +1 -1
- package/src/components/ui/resizable.tsx +1 -1
- package/src/components/ui/scroll-area.tsx +1 -1
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/separator.tsx +1 -1
- package/src/components/ui/sheet.tsx +1 -1
- package/src/components/ui/sidebar.tsx +8 -13
- package/src/components/ui/skeleton.tsx +1 -1
- package/src/components/ui/slider.tsx +1 -1
- package/src/components/ui/sonner.tsx +1 -1
- package/src/components/ui/spinner.tsx +1 -1
- package/src/components/ui/switch.tsx +1 -1
- package/src/components/ui/table.tsx +1 -1
- package/src/components/ui/tabs.tsx +1 -1
- package/src/components/ui/textarea.tsx +1 -1
- package/src/components/ui/toast.tsx +1 -1
- package/src/components/ui/toaster.tsx +2 -2
- package/src/components/ui/toggle-group.tsx +2 -2
- package/src/components/ui/toggle.tsx +1 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/components/ui/use-toast.ts +1 -1
- package/src/components/workspace-app-card.tsx +16 -20
- package/src/components/workspace-resource-effective-stack.tsx +2 -2
- package/src/components/workspace-resource-impact-preview.tsx +2 -3
- package/src/hooks/use-navigation-state.spec.ts +7 -0
- package/src/hooks/use-navigation-state.ts +4 -0
- package/src/hooks/use-toast.ts +1 -1
- package/src/lib/automation-display.spec.ts +95 -0
- package/src/lib/automation-display.ts +70 -0
- package/src/lib/task-queue.spec.ts +57 -0
- package/src/lib/task-queue.ts +72 -0
- package/src/routes/index.ts +1 -0
- package/src/routes/pages/$appId.tsx +6 -6
- package/src/routes/pages/_index.tsx +1 -1
- package/src/routes/pages/agents.tsx +8 -5
- package/src/routes/pages/approval.tsx +4 -4
- package/src/routes/pages/approvals.tsx +4 -4
- package/src/routes/pages/apps.$appId.tsx +5 -5
- package/src/routes/pages/apps.tsx +8 -8
- package/src/routes/pages/audit.tsx +1 -1
- package/src/routes/pages/automations.tsx +280 -0
- package/src/routes/pages/chat.tsx +1 -1
- package/src/routes/pages/destinations.tsx +163 -154
- package/src/routes/pages/dreams.tsx +22 -18
- package/src/routes/pages/identities.tsx +2 -2
- package/src/routes/pages/integrations.tsx +8 -8
- package/src/routes/pages/messaging.tsx +2 -2
- package/src/routes/pages/metrics.tsx +6 -6
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/overview.tsx +1 -1
- package/src/routes/pages/settings.tsx +37 -6
- package/src/routes/pages/thread-debug.tsx +14 -9
- package/src/routes/pages/vault.tsx +17 -12
- package/src/routes/pages/workspace.tsx +17 -12
- package/src/server/lib/dispatch-integrations.spec.ts +92 -1
- package/src/server/lib/dispatch-integrations.ts +48 -0
- package/src/server/lib/pre-auth-routing.ts +1 -0
- package/src/server/plugins/integrations.ts +13 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { useState } from "react";
|
|
15
15
|
import { toast } from "sonner";
|
|
16
16
|
|
|
17
|
-
import { DispatchShell } from "
|
|
17
|
+
import { DispatchShell } from "../../components/dispatch-shell";
|
|
18
18
|
import {
|
|
19
19
|
AlertDialog,
|
|
20
20
|
AlertDialogAction,
|
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
AlertDialogHeader,
|
|
26
26
|
AlertDialogTitle,
|
|
27
27
|
AlertDialogTrigger,
|
|
28
|
-
} from "
|
|
29
|
-
import { Badge } from "
|
|
30
|
-
import { Button } from "
|
|
28
|
+
} from "../../components/ui/alert-dialog";
|
|
29
|
+
import { Badge } from "../../components/ui/badge";
|
|
30
|
+
import { Button } from "../../components/ui/button";
|
|
31
31
|
import {
|
|
32
32
|
Dialog,
|
|
33
33
|
DialogContent,
|
|
@@ -36,20 +36,25 @@ import {
|
|
|
36
36
|
DialogHeader,
|
|
37
37
|
DialogTitle,
|
|
38
38
|
DialogTrigger,
|
|
39
|
-
} from "
|
|
40
|
-
import { Input } from "
|
|
41
|
-
import { Label } from "
|
|
39
|
+
} from "../../components/ui/dialog";
|
|
40
|
+
import { Input } from "../../components/ui/input";
|
|
41
|
+
import { Label } from "../../components/ui/label";
|
|
42
42
|
import {
|
|
43
43
|
Select,
|
|
44
44
|
SelectContent,
|
|
45
45
|
SelectItem,
|
|
46
46
|
SelectTrigger,
|
|
47
47
|
SelectValue,
|
|
48
|
-
} from "
|
|
49
|
-
import { Skeleton } from "
|
|
50
|
-
import { Switch } from "
|
|
51
|
-
import {
|
|
52
|
-
|
|
48
|
+
} from "../../components/ui/select";
|
|
49
|
+
import { Skeleton } from "../../components/ui/skeleton";
|
|
50
|
+
import { Switch } from "../../components/ui/switch";
|
|
51
|
+
import {
|
|
52
|
+
Tabs,
|
|
53
|
+
TabsContent,
|
|
54
|
+
TabsList,
|
|
55
|
+
TabsTrigger,
|
|
56
|
+
} from "../../components/ui/tabs";
|
|
57
|
+
import { Textarea } from "../../components/ui/textarea";
|
|
53
58
|
|
|
54
59
|
const PROVIDERS = [
|
|
55
60
|
"google",
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { useEffect, useState, type ReactNode } from "react";
|
|
18
18
|
import { toast } from "sonner";
|
|
19
19
|
|
|
20
|
-
import { DispatchShell } from "
|
|
20
|
+
import { DispatchShell } from "../../components/dispatch-shell";
|
|
21
21
|
import {
|
|
22
22
|
AlertDialog,
|
|
23
23
|
AlertDialogAction,
|
|
@@ -28,9 +28,9 @@ import {
|
|
|
28
28
|
AlertDialogHeader,
|
|
29
29
|
AlertDialogTitle,
|
|
30
30
|
AlertDialogTrigger,
|
|
31
|
-
} from "
|
|
32
|
-
import { Badge } from "
|
|
33
|
-
import { Button } from "
|
|
31
|
+
} from "../../components/ui/alert-dialog";
|
|
32
|
+
import { Badge } from "../../components/ui/badge";
|
|
33
|
+
import { Button } from "../../components/ui/button";
|
|
34
34
|
import {
|
|
35
35
|
Dialog,
|
|
36
36
|
DialogContent,
|
|
@@ -39,23 +39,28 @@ import {
|
|
|
39
39
|
DialogHeader,
|
|
40
40
|
DialogTitle,
|
|
41
41
|
DialogTrigger,
|
|
42
|
-
} from "
|
|
43
|
-
import { Input } from "
|
|
44
|
-
import { Label } from "
|
|
42
|
+
} from "../../components/ui/dialog";
|
|
43
|
+
import { Input } from "../../components/ui/input";
|
|
44
|
+
import { Label } from "../../components/ui/label";
|
|
45
45
|
import {
|
|
46
46
|
Select,
|
|
47
47
|
SelectContent,
|
|
48
48
|
SelectItem,
|
|
49
49
|
SelectTrigger,
|
|
50
50
|
SelectValue,
|
|
51
|
-
} from "
|
|
52
|
-
import { Skeleton } from "
|
|
53
|
-
import {
|
|
54
|
-
|
|
51
|
+
} from "../../components/ui/select";
|
|
52
|
+
import { Skeleton } from "../../components/ui/skeleton";
|
|
53
|
+
import {
|
|
54
|
+
Tabs,
|
|
55
|
+
TabsContent,
|
|
56
|
+
TabsList,
|
|
57
|
+
TabsTrigger,
|
|
58
|
+
} from "../../components/ui/tabs";
|
|
59
|
+
import { Textarea } from "../../components/ui/textarea";
|
|
55
60
|
import {
|
|
56
61
|
ImpactPreview,
|
|
57
62
|
workspaceResourceMutationMessage,
|
|
58
|
-
} from "
|
|
63
|
+
} from "../../components/workspace-resource-impact-preview";
|
|
59
64
|
|
|
60
65
|
export function meta() {
|
|
61
66
|
return [{ title: "Workspace Resources — Dispatch" }];
|
|
@@ -15,9 +15,13 @@ vi.mock("@agent-native/core/org", () => ({
|
|
|
15
15
|
resolveOrgIdForEmail: mocks.resolveOrgIdForEmail,
|
|
16
16
|
}));
|
|
17
17
|
|
|
18
|
-
import type {
|
|
18
|
+
import type {
|
|
19
|
+
IncomingMessage,
|
|
20
|
+
PlatformAdapter,
|
|
21
|
+
} from "@agent-native/core/server";
|
|
19
22
|
|
|
20
23
|
import {
|
|
24
|
+
beforeDispatchProcess,
|
|
21
25
|
identityKeyForIncoming,
|
|
22
26
|
resolveDispatchOwner,
|
|
23
27
|
} from "./dispatch-integrations.js";
|
|
@@ -54,6 +58,38 @@ function emailIncoming(
|
|
|
54
58
|
};
|
|
55
59
|
}
|
|
56
60
|
|
|
61
|
+
function telegramIncoming(
|
|
62
|
+
overrides: Partial<IncomingMessage> = {},
|
|
63
|
+
): IncomingMessage {
|
|
64
|
+
return {
|
|
65
|
+
platform: "telegram",
|
|
66
|
+
externalThreadId: "12345",
|
|
67
|
+
text: "ask analytics about traffic",
|
|
68
|
+
senderId: "777",
|
|
69
|
+
senderName: "Steve",
|
|
70
|
+
platformContext: { chatId: 12345, fromId: 777, rawText: "hello" },
|
|
71
|
+
timestamp: 1,
|
|
72
|
+
...overrides,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const noopAdapter: PlatformAdapter = {
|
|
77
|
+
platform: "telegram",
|
|
78
|
+
label: "Telegram",
|
|
79
|
+
getRequiredEnvKeys: () => [],
|
|
80
|
+
handleVerification: async () => ({ handled: false }),
|
|
81
|
+
verifyWebhook: async () => true,
|
|
82
|
+
parseIncomingMessage: async () => null,
|
|
83
|
+
sendResponse: async () => {},
|
|
84
|
+
formatAgentResponse: (text: string) => ({ text, platformContext: {} }),
|
|
85
|
+
getStatus: async () => ({
|
|
86
|
+
platform: "telegram",
|
|
87
|
+
label: "Telegram",
|
|
88
|
+
enabled: true,
|
|
89
|
+
configured: true,
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
|
|
57
93
|
beforeEach(() => {
|
|
58
94
|
mocks.resolveLinkedOwner.mockResolvedValue(null);
|
|
59
95
|
mocks.consumeLinkToken.mockResolvedValue("owner@example.test");
|
|
@@ -75,6 +111,10 @@ describe("identityKeyForIncoming", () => {
|
|
|
75
111
|
it("scopes Slack identities by team", () => {
|
|
76
112
|
expect(identityKeyForIncoming(slackIncoming())).toBe("T123:U123");
|
|
77
113
|
});
|
|
114
|
+
|
|
115
|
+
it("uses Telegram sender ids as link identities", () => {
|
|
116
|
+
expect(identityKeyForIncoming(telegramIncoming())).toBe("777");
|
|
117
|
+
});
|
|
78
118
|
});
|
|
79
119
|
|
|
80
120
|
describe("resolveDispatchOwner", () => {
|
|
@@ -184,3 +224,54 @@ describe("resolveDispatchOwner", () => {
|
|
|
184
224
|
).resolves.toBe("victim@member.test");
|
|
185
225
|
});
|
|
186
226
|
});
|
|
227
|
+
|
|
228
|
+
describe("beforeDispatchProcess", () => {
|
|
229
|
+
it("asks unlinked Telegram users to link before using org context", async () => {
|
|
230
|
+
vi.stubEnv("APP_URL", "https://dispatch.agent-native.test");
|
|
231
|
+
|
|
232
|
+
const result = await beforeDispatchProcess(telegramIncoming(), noopAdapter);
|
|
233
|
+
|
|
234
|
+
expect(result).toEqual({
|
|
235
|
+
handled: true,
|
|
236
|
+
responseText:
|
|
237
|
+
"Telegram is connected, but this Telegram account is not linked to an Agent-Native user yet. Tap https://dispatch.agent-native.test/identities, create a Telegram link token, then send `/link <token>` here. After that I can use your Builder.io org and connected apps.",
|
|
238
|
+
});
|
|
239
|
+
expect(mocks.resolveLinkedOwner).toHaveBeenCalledWith("telegram", "777", {
|
|
240
|
+
allowAnyOrgFallback: true,
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it("lets linked Telegram users proceed to normal agent processing", async () => {
|
|
245
|
+
mocks.resolveLinkedOwner.mockResolvedValueOnce("steve@builder.io");
|
|
246
|
+
|
|
247
|
+
await expect(
|
|
248
|
+
beforeDispatchProcess(telegramIncoming(), noopAdapter),
|
|
249
|
+
).resolves.toEqual({ handled: false });
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it("still consumes Telegram link commands before enforcing the link gate", async () => {
|
|
253
|
+
const result = await beforeDispatchProcess(
|
|
254
|
+
telegramIncoming({
|
|
255
|
+
text: "token-123",
|
|
256
|
+
platformContext: {
|
|
257
|
+
chatId: 12345,
|
|
258
|
+
fromId: 777,
|
|
259
|
+
rawText: "/link token-123",
|
|
260
|
+
},
|
|
261
|
+
}),
|
|
262
|
+
noopAdapter,
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
expect(result).toEqual({
|
|
266
|
+
handled: true,
|
|
267
|
+
responseText:
|
|
268
|
+
"Linked successfully. Future telegram messages will use owner@example.test's personal dispatch context.",
|
|
269
|
+
});
|
|
270
|
+
expect(mocks.consumeLinkToken).toHaveBeenCalledWith({
|
|
271
|
+
platform: "telegram",
|
|
272
|
+
token: "token-123",
|
|
273
|
+
externalUserId: "777",
|
|
274
|
+
externalUserName: "Steve",
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
|
|
3
3
|
import { resolveOrgIdForEmail } from "@agent-native/core/org";
|
|
4
|
+
import { withConfiguredAppBasePath } from "@agent-native/core/server";
|
|
4
5
|
import type {
|
|
5
6
|
IncomingMessage,
|
|
6
7
|
PlatformAdapter,
|
|
@@ -77,6 +78,40 @@ function configuredDefaultOwnerForIncoming(
|
|
|
77
78
|
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email) ? email : null;
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
function platformRequiresExplicitLink(incoming: IncomingMessage): boolean {
|
|
82
|
+
// Telegram does not provide a verified email address. Require an explicit
|
|
83
|
+
// identity link before it can act as a Builder/Agent-Native user.
|
|
84
|
+
return incoming.platform === "telegram";
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function configuredDispatchIdentitiesUrl(): string | null {
|
|
88
|
+
const raw =
|
|
89
|
+
process.env.WORKSPACE_GATEWAY_URL ||
|
|
90
|
+
process.env.APP_URL ||
|
|
91
|
+
process.env.URL ||
|
|
92
|
+
process.env.DEPLOY_URL ||
|
|
93
|
+
process.env.BETTER_AUTH_URL ||
|
|
94
|
+
"";
|
|
95
|
+
if (!raw.trim()) return null;
|
|
96
|
+
const base = /^https?:\/\//i.test(raw) ? raw : `https://${raw}`;
|
|
97
|
+
try {
|
|
98
|
+
return new URL(
|
|
99
|
+
"identities",
|
|
100
|
+
`${withConfiguredAppBasePath(base).replace(/\/+$/, "")}/`,
|
|
101
|
+
).toString();
|
|
102
|
+
} catch {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function formatTelegramLinkRequiredMessage(): string {
|
|
108
|
+
const identitiesUrl = configuredDispatchIdentitiesUrl();
|
|
109
|
+
const linkStep = identitiesUrl
|
|
110
|
+
? `Tap ${identitiesUrl}, create a Telegram link token, then send \`/link <token>\` here.`
|
|
111
|
+
: "Open Dispatch while signed in, create a Telegram link token, then send `/link <token>` here.";
|
|
112
|
+
return `Telegram is connected, but this Telegram account is not linked to an Agent-Native user yet. ${linkStep} After that I can use your Builder.io org and connected apps.`;
|
|
113
|
+
}
|
|
114
|
+
|
|
80
115
|
async function resolveSlackSenderProfile(
|
|
81
116
|
incoming: IncomingMessage,
|
|
82
117
|
): Promise<SlackSenderProfile> {
|
|
@@ -228,6 +263,19 @@ export async function beforeDispatchProcess(
|
|
|
228
263
|
contextString(incoming.platformContext.rawText) || trimmed;
|
|
229
264
|
const match = commandText.match(/^\/link(?:@\w+)?\s+([a-zA-Z0-9_-]+)$/);
|
|
230
265
|
if (!match) {
|
|
266
|
+
if (platformRequiresExplicitLink(incoming)) {
|
|
267
|
+
const owner = await resolveLinkedOwner(
|
|
268
|
+
incoming.platform,
|
|
269
|
+
identityKeyForIncoming(incoming),
|
|
270
|
+
{ allowAnyOrgFallback: true },
|
|
271
|
+
);
|
|
272
|
+
if (!owner) {
|
|
273
|
+
return {
|
|
274
|
+
handled: true,
|
|
275
|
+
responseText: formatTelegramLinkRequiredMessage(),
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
231
279
|
return handleRemoteCodeCommand(incoming, adapter, {
|
|
232
280
|
resolveOwner: () => resolveDispatchOwner(incoming),
|
|
233
281
|
});
|
|
@@ -7,6 +7,17 @@ import {
|
|
|
7
7
|
resolveDispatchOwner,
|
|
8
8
|
} from "../lib/dispatch-integrations.js";
|
|
9
9
|
|
|
10
|
+
const dispatchIntegrationActions = {
|
|
11
|
+
...dispatchActions,
|
|
12
|
+
// Messaging integrations should use the core call-agent tool for cross-app
|
|
13
|
+
// delegation because it queues A2A continuations when serverless budgets are
|
|
14
|
+
// tight. The MCP-facing ask_app action is still available outside this path.
|
|
15
|
+
ask_app: {
|
|
16
|
+
...dispatchActions.ask_app,
|
|
17
|
+
agentTool: false,
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
10
21
|
const DISPATCH_INTEGRATION_SYSTEM_PROMPT = `You are the central dispatch for this workspace, responding via a messaging platform integration (Slack, Telegram, email, etc.).
|
|
11
22
|
|
|
12
23
|
Default posture:
|
|
@@ -21,6 +32,7 @@ Default posture:
|
|
|
21
32
|
|
|
22
33
|
When a user asks for something:
|
|
23
34
|
- If it belongs to analytics, content, slides, clips, assets, etc., delegate via call-agent — do not re-implement the domain logic in dispatch.
|
|
35
|
+
- In messaging integrations, use call-agent for cross-app delegation; do not use ask_app.
|
|
24
36
|
- After call-agent returns an answer, RELAY IT DIRECTLY to the user with at most a one-line preface — do not rephrase, summarize, or add commentary. The downstream agent already crafted the answer; your job is delivery, not editing. This minimizes round-trips and keeps the user-visible reply fast.
|
|
25
37
|
- Exception: if the downstream agent reports a missing model/provider credential, do not name exact env vars, Vault keys, tokens, or secrets. Say the target app needs an LLM connection and recommend connecting Builder/managed LLM for that app; keep bring-your-own provider keys as a secondary option only if the user asks.
|
|
26
38
|
- If the user asks to create, build, make, scaffold, or generate an "agent" from Dispatch chat or by tagging @agent-native in Slack, email, or Telegram, first classify the ask. If it is a simple Dispatch-native behavior like a reminder, digest, monitor, routing rule, saved instruction, or recurring workflow, create or update the recurring job/resource/destination in Dispatch. If it is a robust unique product or teammate that needs its own UI, data model, actions, integrations, or domain workflow, treat it as a new workspace app and call start-workspace-app-creation.
|
|
@@ -49,7 +61,7 @@ const dispatchIntegrationsPlugin = async (nitroApp: any) => {
|
|
|
49
61
|
|
|
50
62
|
const plugin = createIntegrationsPlugin({
|
|
51
63
|
appId: "dispatch",
|
|
52
|
-
actions:
|
|
64
|
+
actions: dispatchIntegrationActions,
|
|
53
65
|
resolveOwner: resolveDispatchOwner,
|
|
54
66
|
beforeProcess: beforeDispatchProcess,
|
|
55
67
|
systemPrompt,
|