@agent-native/dispatch 0.6.1 → 0.8.0
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 +38 -1
- package/dist/actions/apply-dream-proposal.d.ts +3 -0
- package/dist/actions/apply-dream-proposal.d.ts.map +1 -0
- package/dist/actions/apply-dream-proposal.js +11 -0
- package/dist/actions/apply-dream-proposal.js.map +1 -0
- package/dist/actions/create-dream-report.d.ts +3 -0
- package/dist/actions/create-dream-report.d.ts.map +1 -0
- package/dist/actions/create-dream-report.js +67 -0
- package/dist/actions/create-dream-report.js.map +1 -0
- package/dist/actions/create-pylon-ticket.d.ts +3 -0
- package/dist/actions/create-pylon-ticket.d.ts.map +1 -0
- package/dist/actions/create-pylon-ticket.js +94 -0
- package/dist/actions/create-pylon-ticket.js.map +1 -0
- package/dist/actions/create-vault-grant.js +1 -1
- package/dist/actions/create-vault-grant.js.map +1 -1
- package/dist/actions/create-vault-secret.d.ts.map +1 -1
- package/dist/actions/create-vault-secret.js +4 -3
- package/dist/actions/create-vault-secret.js.map +1 -1
- package/dist/actions/create-workspace-resource.js +3 -3
- package/dist/actions/create-workspace-resource.js.map +1 -1
- package/dist/actions/delete-workspace-resource.js +1 -1
- package/dist/actions/delete-workspace-resource.js.map +1 -1
- package/dist/actions/ensure-dream-job.d.ts +3 -0
- package/dist/actions/ensure-dream-job.d.ts.map +1 -0
- package/dist/actions/ensure-dream-job.js +73 -0
- package/dist/actions/ensure-dream-job.js.map +1 -0
- package/dist/actions/get-dream-settings.d.ts +3 -0
- package/dist/actions/get-dream-settings.d.ts.map +1 -0
- package/dist/actions/get-dream-settings.js +11 -0
- package/dist/actions/get-dream-settings.js.map +1 -0
- package/dist/actions/get-dream.d.ts +3 -0
- package/dist/actions/get-dream.d.ts.map +1 -0
- package/dist/actions/get-dream.js +13 -0
- package/dist/actions/get-dream.js.map +1 -0
- package/dist/actions/get-vault-access-settings.d.ts +3 -0
- package/dist/actions/get-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/get-vault-access-settings.js +10 -0
- package/dist/actions/get-vault-access-settings.js.map +1 -0
- package/dist/actions/get-workspace-resource-effective-context.d.ts +3 -0
- package/dist/actions/get-workspace-resource-effective-context.d.ts.map +1 -0
- package/dist/actions/get-workspace-resource-effective-context.js +27 -0
- package/dist/actions/get-workspace-resource-effective-context.js.map +1 -0
- package/dist/actions/grant-vault-secrets-to-app.js +1 -1
- package/dist/actions/grant-vault-secrets-to-app.js.map +1 -1
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +38 -4
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-dream-candidates.d.ts +3 -0
- package/dist/actions/list-dream-candidates.d.ts.map +1 -0
- package/dist/actions/list-dream-candidates.js +68 -0
- package/dist/actions/list-dream-candidates.js.map +1 -0
- package/dist/actions/list-dreams.d.ts +3 -0
- package/dist/actions/list-dreams.d.ts.map +1 -0
- package/dist/actions/list-dreams.js +17 -0
- package/dist/actions/list-dreams.js.map +1 -0
- package/dist/actions/list-integrations-catalog.js +1 -1
- package/dist/actions/list-integrations-catalog.js.map +1 -1
- package/dist/actions/list-vault-grants.js +1 -1
- package/dist/actions/list-vault-grants.js.map +1 -1
- package/dist/actions/list-workspace-apps.d.ts.map +1 -1
- package/dist/actions/list-workspace-apps.js +5 -1
- package/dist/actions/list-workspace-apps.js.map +1 -1
- package/dist/actions/list-workspace-resources-for-app.d.ts +3 -0
- package/dist/actions/list-workspace-resources-for-app.d.ts.map +1 -0
- package/dist/actions/list-workspace-resources-for-app.js +12 -0
- package/dist/actions/list-workspace-resources-for-app.js.map +1 -0
- package/dist/actions/list-workspace-resources.js +1 -1
- package/dist/actions/list-workspace-resources.js.map +1 -1
- package/dist/actions/navigate.d.ts +1 -0
- package/dist/actions/navigate.d.ts.map +1 -1
- package/dist/actions/navigate.js +2 -1
- package/dist/actions/navigate.js.map +1 -1
- package/dist/actions/preview-dream-proposal.d.ts +3 -0
- package/dist/actions/preview-dream-proposal.d.ts.map +1 -0
- package/dist/actions/preview-dream-proposal.js +13 -0
- package/dist/actions/preview-dream-proposal.js.map +1 -0
- package/dist/actions/preview-workspace-resource-change.d.ts +3 -0
- package/dist/actions/preview-workspace-resource-change.d.ts.map +1 -0
- package/dist/actions/preview-workspace-resource-change.js +24 -0
- package/dist/actions/preview-workspace-resource-change.js.map +1 -0
- package/dist/actions/reject-dream-proposal.d.ts +3 -0
- package/dist/actions/reject-dream-proposal.d.ts.map +1 -0
- package/dist/actions/reject-dream-proposal.js +12 -0
- package/dist/actions/reject-dream-proposal.js.map +1 -0
- package/dist/actions/restore-starter-workspace-resources.d.ts +3 -0
- package/dist/actions/restore-starter-workspace-resources.d.ts.map +1 -0
- package/dist/actions/restore-starter-workspace-resources.js +14 -0
- package/dist/actions/restore-starter-workspace-resources.js.map +1 -0
- package/dist/actions/send-code-agent-remote-command.d.ts +3 -0
- package/dist/actions/send-code-agent-remote-command.d.ts.map +1 -0
- package/dist/actions/send-code-agent-remote-command.js +53 -0
- package/dist/actions/send-code-agent-remote-command.js.map +1 -0
- package/dist/actions/set-dream-settings.d.ts +3 -0
- package/dist/actions/set-dream-settings.d.ts.map +1 -0
- package/dist/actions/set-dream-settings.js +41 -0
- package/dist/actions/set-dream-settings.js.map +1 -0
- package/dist/actions/set-vault-access-settings.d.ts +3 -0
- package/dist/actions/set-vault-access-settings.d.ts.map +1 -0
- package/dist/actions/set-vault-access-settings.js +13 -0
- package/dist/actions/set-vault-access-settings.js.map +1 -0
- package/dist/actions/start-workspace-app-creation.d.ts.map +1 -1
- package/dist/actions/start-workspace-app-creation.js +6 -0
- package/dist/actions/start-workspace-app-creation.js.map +1 -1
- package/dist/actions/sync-vault-to-app.js +1 -1
- package/dist/actions/sync-vault-to-app.js.map +1 -1
- package/dist/actions/update-workspace-app-metadata.d.ts +3 -0
- package/dist/actions/update-workspace-app-metadata.d.ts.map +1 -0
- package/dist/actions/update-workspace-app-metadata.js +30 -0
- package/dist/actions/update-workspace-app-metadata.js.map +1 -0
- package/dist/actions/update-workspace-resource.js +1 -1
- package/dist/actions/update-workspace-resource.js.map +1 -1
- package/dist/actions/view-screen.d.ts.map +1 -1
- package/dist/actions/view-screen.js +77 -4
- package/dist/actions/view-screen.js.map +1 -1
- package/dist/components/app-keys-popover.js +16 -5
- package/dist/components/app-keys-popover.js.map +1 -1
- package/dist/components/approval-value-block.d.ts +7 -0
- package/dist/components/approval-value-block.d.ts.map +1 -0
- package/dist/components/approval-value-block.js +22 -0
- package/dist/components/approval-value-block.js.map +1 -0
- package/dist/components/create-app-popover.d.ts.map +1 -1
- package/dist/components/create-app-popover.js +41 -16
- package/dist/components/create-app-popover.js.map +1 -1
- package/dist/components/dispatch-shell.d.ts +4 -4
- package/dist/components/dispatch-shell.d.ts.map +1 -1
- package/dist/components/dispatch-shell.js +6 -6
- package/dist/components/dispatch-shell.js.map +1 -1
- package/dist/components/layout/Layout.d.ts.map +1 -1
- package/dist/components/layout/Layout.js +18 -4
- 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 +2 -2
- package/dist/components/messaging-setup-panel.js.map +1 -1
- package/dist/components/ui/chart.d.ts +1 -1
- package/dist/components/workspace-app-card.d.ts.map +1 -1
- package/dist/components/workspace-app-card.js +63 -3
- package/dist/components/workspace-app-card.js.map +1 -1
- package/dist/components/workspace-resource-effective-stack.d.ts +11 -0
- package/dist/components/workspace-resource-effective-stack.d.ts.map +1 -0
- package/dist/components/workspace-resource-effective-stack.js +59 -0
- package/dist/components/workspace-resource-effective-stack.js.map +1 -0
- package/dist/components/workspace-resource-impact-preview.d.ts +9 -0
- package/dist/components/workspace-resource-impact-preview.d.ts.map +1 -0
- package/dist/components/workspace-resource-impact-preview.js +39 -0
- package/dist/components/workspace-resource-impact-preview.js.map +1 -0
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +59 -0
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/schema.d.ts +714 -0
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/schema.js +44 -2
- package/dist/db/schema.js.map +1 -1
- package/dist/hooks/use-navigation-state.d.ts +3 -0
- package/dist/hooks/use-navigation-state.d.ts.map +1 -1
- package/dist/hooks/use-navigation-state.js +35 -8
- package/dist/hooks/use-navigation-state.js.map +1 -1
- package/dist/lib/catch-all-target.d.ts +2 -0
- package/dist/lib/catch-all-target.d.ts.map +1 -0
- package/dist/lib/catch-all-target.js +95 -0
- package/dist/lib/catch-all-target.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +5 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/lib/workspace-apps.d.ts +9 -0
- package/dist/lib/workspace-apps.d.ts.map +1 -1
- package/dist/lib/workspace-apps.js.map +1 -1
- 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.d.ts +2 -2
- package/dist/routes/pages/$appId.d.ts.map +1 -1
- package/dist/routes/pages/$appId.js +17 -8
- package/dist/routes/pages/$appId.js.map +1 -1
- package/dist/routes/pages/approval.d.ts.map +1 -1
- package/dist/routes/pages/approval.js +4 -1
- package/dist/routes/pages/approval.js.map +1 -1
- package/dist/routes/pages/approvals.js +1 -1
- package/dist/routes/pages/approvals.js.map +1 -1
- package/dist/routes/pages/dream-settings.d.ts +34 -0
- package/dist/routes/pages/dream-settings.d.ts.map +1 -0
- package/dist/routes/pages/dream-settings.js +68 -0
- package/dist/routes/pages/dream-settings.js.map +1 -0
- package/dist/routes/pages/dreams.d.ts +5 -0
- package/dist/routes/pages/dreams.d.ts.map +1 -0
- package/dist/routes/pages/dreams.js +435 -0
- package/dist/routes/pages/dreams.js.map +1 -0
- package/dist/routes/pages/integrations.d.ts.map +1 -1
- package/dist/routes/pages/integrations.js +20 -15
- package/dist/routes/pages/integrations.js.map +1 -1
- package/dist/routes/pages/new-app.js +1 -1
- package/dist/routes/pages/new-app.js.map +1 -1
- package/dist/routes/pages/overview.d.ts.map +1 -1
- package/dist/routes/pages/overview.js +5 -1
- package/dist/routes/pages/overview.js.map +1 -1
- package/dist/routes/pages/vault.d.ts.map +1 -1
- package/dist/routes/pages/vault.js +23 -5
- 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 +187 -35
- package/dist/routes/pages/workspace.js.map +1 -1
- package/dist/server/lib/app-creation-store.d.ts +13 -0
- package/dist/server/lib/app-creation-store.d.ts.map +1 -1
- package/dist/server/lib/app-creation-store.js +298 -11
- package/dist/server/lib/app-creation-store.js.map +1 -1
- package/dist/server/lib/dispatch-integrations.d.ts +1 -1
- package/dist/server/lib/dispatch-integrations.d.ts.map +1 -1
- package/dist/server/lib/dispatch-integrations.js +9 -4
- package/dist/server/lib/dispatch-integrations.js.map +1 -1
- package/dist/server/lib/dispatch-remote-commands.d.ts +83 -0
- package/dist/server/lib/dispatch-remote-commands.d.ts.map +1 -0
- package/dist/server/lib/dispatch-remote-commands.js +256 -0
- package/dist/server/lib/dispatch-remote-commands.js.map +1 -0
- package/dist/server/lib/dispatch-store.d.ts +26 -0
- package/dist/server/lib/dispatch-store.d.ts.map +1 -1
- package/dist/server/lib/dispatch-store.js +17 -1
- package/dist/server/lib/dispatch-store.js.map +1 -1
- package/dist/server/lib/dreams-store.d.ts +398 -0
- package/dist/server/lib/dreams-store.d.ts.map +1 -0
- package/dist/server/lib/dreams-store.js +2330 -0
- package/dist/server/lib/dreams-store.js.map +1 -0
- package/dist/server/lib/env-config.d.ts.map +1 -1
- package/dist/server/lib/env-config.js +5 -0
- package/dist/server/lib/env-config.js.map +1 -1
- package/dist/server/lib/onboarding-steps.d.ts +12 -0
- package/dist/server/lib/onboarding-steps.d.ts.map +1 -0
- package/dist/server/lib/onboarding-steps.js +47 -0
- package/dist/server/lib/onboarding-steps.js.map +1 -0
- package/dist/server/lib/thread-debug-store.d.ts +2 -2
- package/dist/server/lib/vault-store.d.ts +55 -0
- package/dist/server/lib/vault-store.d.ts.map +1 -1
- package/dist/server/lib/vault-store.js +210 -41
- package/dist/server/lib/vault-store.js.map +1 -1
- package/dist/server/lib/workspace-resources-store.d.ts +181 -17
- package/dist/server/lib/workspace-resources-store.d.ts.map +1 -1
- package/dist/server/lib/workspace-resources-store.js +737 -108
- package/dist/server/lib/workspace-resources-store.js.map +1 -1
- package/dist/server/plugins/agent-chat.d.ts.map +1 -1
- package/dist/server/plugins/agent-chat.js +2 -1
- package/dist/server/plugins/agent-chat.js.map +1 -1
- package/dist/server/plugins/core-routes.d.ts.map +1 -1
- package/dist/server/plugins/core-routes.js +4 -0
- package/dist/server/plugins/core-routes.js.map +1 -1
- package/dist/server/plugins/integrations.js +2 -2
- package/dist/server/plugins/integrations.js.map +1 -1
- package/package.json +15 -11
- package/src/actions/apply-dream-proposal.ts +12 -0
- package/src/actions/create-dream-report.ts +76 -0
- package/src/actions/create-pylon-ticket.ts +109 -0
- package/src/actions/create-vault-grant.ts +1 -1
- package/src/actions/create-vault-secret.ts +4 -3
- package/src/actions/create-workspace-resource.ts +3 -3
- package/src/actions/delete-workspace-resource.ts +1 -1
- package/src/actions/ensure-dream-job.ts +76 -0
- package/src/actions/get-dream-settings.ts +12 -0
- package/src/actions/get-dream.ts +14 -0
- package/src/actions/get-vault-access-settings.ts +11 -0
- package/src/actions/get-workspace-resource-effective-context.ts +34 -0
- package/src/actions/grant-vault-secrets-to-app.ts +1 -1
- package/src/actions/index.spec.ts +26 -0
- package/src/actions/index.ts +39 -4
- package/src/actions/list-dream-candidates.ts +77 -0
- package/src/actions/list-dreams.ts +17 -0
- package/src/actions/list-integrations-catalog.ts +1 -1
- package/src/actions/list-vault-grants.ts +1 -1
- package/src/actions/list-workspace-apps.ts +5 -1
- package/src/actions/list-workspace-resources-for-app.ts +13 -0
- package/src/actions/list-workspace-resources.ts +1 -1
- package/src/actions/navigate.ts +2 -1
- package/src/actions/preview-dream-proposal.ts +14 -0
- package/src/actions/preview-workspace-resource-change.ts +25 -0
- package/src/actions/reject-dream-proposal.ts +12 -0
- package/src/actions/restore-starter-workspace-resources.ts +17 -0
- package/src/actions/send-code-agent-remote-command.ts +59 -0
- package/src/actions/set-dream-settings.spec.ts +81 -0
- package/src/actions/set-dream-settings.ts +44 -0
- package/src/actions/set-vault-access-settings.ts +16 -0
- package/src/actions/start-workspace-app-creation.ts +8 -0
- package/src/actions/sync-vault-to-app.ts +1 -1
- package/src/actions/update-workspace-app-metadata.ts +32 -0
- package/src/actions/update-workspace-resource.ts +1 -1
- package/src/actions/view-screen.ts +94 -3
- package/src/components/app-keys-popover.tsx +23 -7
- package/src/components/approval-value-block.spec.tsx +59 -0
- package/src/components/approval-value-block.tsx +33 -0
- package/src/components/create-app-popover.tsx +50 -16
- package/src/components/dispatch-shell.tsx +16 -15
- package/src/components/layout/Layout.tsx +19 -5
- package/src/components/messaging-setup-panel.tsx +54 -39
- package/src/components/workspace-app-card.tsx +268 -1
- package/src/components/workspace-resource-effective-stack.spec.tsx +125 -0
- package/src/components/workspace-resource-effective-stack.tsx +141 -0
- package/src/components/workspace-resource-impact-preview.spec.tsx +147 -0
- package/src/components/workspace-resource-impact-preview.tsx +116 -0
- package/src/db/migrations.ts +59 -0
- package/src/db/schema.ts +46 -2
- package/src/hooks/use-navigation-state.ts +34 -9
- package/src/lib/catch-all-target.spec.ts +218 -0
- package/src/lib/catch-all-target.ts +99 -0
- package/src/lib/utils.ts +6 -1
- package/src/lib/workspace-apps.ts +9 -0
- package/src/routes/index.ts +1 -0
- package/src/routes/pages/$appId.tsx +21 -8
- package/src/routes/pages/approval.tsx +14 -1
- package/src/routes/pages/approvals.tsx +1 -1
- package/src/routes/pages/dream-settings.spec.ts +130 -0
- package/src/routes/pages/dream-settings.ts +103 -0
- package/src/routes/pages/dreams.tsx +1828 -0
- package/src/routes/pages/integrations.tsx +57 -18
- package/src/routes/pages/new-app.tsx +1 -1
- package/src/routes/pages/overview.tsx +11 -3
- package/src/routes/pages/vault.tsx +76 -9
- package/src/routes/pages/workspace.tsx +577 -97
- package/src/server/lib/app-creation-store.spec.ts +61 -2
- package/src/server/lib/app-creation-store.ts +389 -13
- package/src/server/lib/dispatch-integrations.ts +10 -3
- package/src/server/lib/dispatch-remote-commands.spec.ts +167 -0
- package/src/server/lib/dispatch-remote-commands.ts +375 -0
- package/src/server/lib/dispatch-store.ts +37 -1
- package/src/server/lib/dreams-store.spec.ts +1492 -0
- package/src/server/lib/dreams-store.ts +3168 -0
- package/src/server/lib/env-config.ts +5 -0
- package/src/server/lib/onboarding-steps.ts +49 -0
- package/src/server/lib/vault-store.spec.ts +69 -0
- package/src/server/lib/vault-store.ts +266 -49
- package/src/server/lib/workspace-resource-approval-lifecycle.spec.ts +236 -0
- package/src/server/lib/workspace-resources-store.spec.ts +1106 -0
- package/src/server/lib/workspace-resources-store.ts +1001 -134
- package/src/server/plugins/agent-chat.ts +2 -1
- package/src/server/plugins/core-routes.ts +5 -0
- package/src/server/plugins/integrations.ts +2 -2
- package/dist/actions/sync-workspace-resources-to-all.d.ts +0 -3
- package/dist/actions/sync-workspace-resources-to-all.d.ts.map +0 -1
- package/dist/actions/sync-workspace-resources-to-all.js +0 -9
- package/dist/actions/sync-workspace-resources-to-all.js.map +0 -1
- package/dist/actions/sync-workspace-resources-to-app.d.ts +0 -3
- package/dist/actions/sync-workspace-resources-to-app.d.ts.map +0 -1
- package/dist/actions/sync-workspace-resources-to-app.js +0 -11
- package/dist/actions/sync-workspace-resources-to-app.js.map +0 -1
- package/src/actions/sync-workspace-resources-to-all.ts +0 -10
- package/src/actions/sync-workspace-resources-to-app.ts +0 -12
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import type {
|
|
3
|
+
IncomingMessage,
|
|
4
|
+
PlatformAdapter,
|
|
5
|
+
} from "@agent-native/core/server";
|
|
6
|
+
import {
|
|
7
|
+
handleRemoteCodeCommand,
|
|
8
|
+
parseTelegramCodeCommand,
|
|
9
|
+
type RemoteCodeCommandEnvelope,
|
|
10
|
+
} from "./dispatch-remote-commands.js";
|
|
11
|
+
|
|
12
|
+
function telegramIncoming(text: string, rawText = text): IncomingMessage {
|
|
13
|
+
return {
|
|
14
|
+
platform: "telegram",
|
|
15
|
+
externalThreadId: "chat-123",
|
|
16
|
+
text,
|
|
17
|
+
senderId: "user-1",
|
|
18
|
+
senderName: "User One",
|
|
19
|
+
platformContext: { chatId: 123, messageId: 456, rawText },
|
|
20
|
+
timestamp: 1710000000000,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const adapter = {
|
|
25
|
+
platform: "telegram",
|
|
26
|
+
label: "Telegram",
|
|
27
|
+
} as PlatformAdapter;
|
|
28
|
+
|
|
29
|
+
describe("parseTelegramCodeCommand", () => {
|
|
30
|
+
it("parses a prompt as a create command", () => {
|
|
31
|
+
expect(
|
|
32
|
+
parseTelegramCodeCommand(
|
|
33
|
+
telegramIncoming(
|
|
34
|
+
"fix the failing tests",
|
|
35
|
+
"/code fix the failing tests",
|
|
36
|
+
),
|
|
37
|
+
),
|
|
38
|
+
).toEqual({ type: "create", prompt: "fix the failing tests" });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("parses run management commands", () => {
|
|
42
|
+
expect(
|
|
43
|
+
parseTelegramCodeCommand(telegramIncoming("list", "/code list")),
|
|
44
|
+
).toEqual({
|
|
45
|
+
type: "list",
|
|
46
|
+
});
|
|
47
|
+
expect(
|
|
48
|
+
parseTelegramCodeCommand(telegramIncoming("status 2", "/code status 2")),
|
|
49
|
+
).toEqual({ type: "status", runRef: "2" });
|
|
50
|
+
expect(
|
|
51
|
+
parseTelegramCodeCommand(
|
|
52
|
+
telegramIncoming(
|
|
53
|
+
"continue run_123 add docs",
|
|
54
|
+
"/code continue run_123 add docs",
|
|
55
|
+
),
|
|
56
|
+
),
|
|
57
|
+
).toEqual({ type: "continue", runRef: "run_123", text: "add docs" });
|
|
58
|
+
expect(
|
|
59
|
+
parseTelegramCodeCommand(
|
|
60
|
+
telegramIncoming("approve req_1", "/code approve req_1"),
|
|
61
|
+
),
|
|
62
|
+
).toEqual({ type: "approve", approvalId: "req_1" });
|
|
63
|
+
expect(
|
|
64
|
+
parseTelegramCodeCommand(
|
|
65
|
+
telegramIncoming("deny req_1", "/code deny req_1"),
|
|
66
|
+
),
|
|
67
|
+
).toEqual({ type: "deny", approvalId: "req_1" });
|
|
68
|
+
expect(
|
|
69
|
+
parseTelegramCodeCommand(telegramIncoming("stop 1", "/code stop 1")),
|
|
70
|
+
).toEqual({
|
|
71
|
+
type: "stop",
|
|
72
|
+
runRef: "1",
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("does not hijack Telegram messages after the adapter strips other commands", () => {
|
|
77
|
+
expect(
|
|
78
|
+
parseTelegramCodeCommand({
|
|
79
|
+
platform: "telegram",
|
|
80
|
+
text: "list",
|
|
81
|
+
platformContext: {},
|
|
82
|
+
}),
|
|
83
|
+
).toBeNull();
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe("handleRemoteCodeCommand", () => {
|
|
88
|
+
it("routes code commands to the remote relay with owner and source context", async () => {
|
|
89
|
+
const relay = vi.fn(async () => ({
|
|
90
|
+
ok: true,
|
|
91
|
+
runId: "run_123",
|
|
92
|
+
hostOnline: true,
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
const result = await handleRemoteCodeCommand(
|
|
96
|
+
telegramIncoming("ship it", "/code ship it"),
|
|
97
|
+
adapter,
|
|
98
|
+
{
|
|
99
|
+
resolveOwner: () => "owner@example.test",
|
|
100
|
+
relay,
|
|
101
|
+
},
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
expect(result).toEqual({
|
|
105
|
+
handled: true,
|
|
106
|
+
responseText: "Queued code run (run_123).",
|
|
107
|
+
});
|
|
108
|
+
expect(relay).toHaveBeenCalledWith({
|
|
109
|
+
kind: "code-agent",
|
|
110
|
+
ownerEmail: "owner@example.test",
|
|
111
|
+
command: { type: "create", prompt: "ship it" },
|
|
112
|
+
source: {
|
|
113
|
+
platform: "telegram",
|
|
114
|
+
externalThreadId: "chat-123",
|
|
115
|
+
senderId: "user-1",
|
|
116
|
+
senderName: "User One",
|
|
117
|
+
messageId: "456",
|
|
118
|
+
timestamp: 1710000000000,
|
|
119
|
+
},
|
|
120
|
+
} satisfies RemoteCodeCommandEnvelope);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("keeps offline hosts pending without pretending the run is active", async () => {
|
|
124
|
+
const result = await handleRemoteCodeCommand(
|
|
125
|
+
telegramIncoming("fix it", "/code fix it"),
|
|
126
|
+
adapter,
|
|
127
|
+
{
|
|
128
|
+
resolveOwner: () => "owner@example.test",
|
|
129
|
+
relay: async () => ({
|
|
130
|
+
ok: true,
|
|
131
|
+
commandId: "cmd_123",
|
|
132
|
+
hostOnline: false,
|
|
133
|
+
hostStatus: "asleep",
|
|
134
|
+
}),
|
|
135
|
+
},
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
expect(result).toEqual({
|
|
139
|
+
handled: true,
|
|
140
|
+
responseText:
|
|
141
|
+
"Queued code run (cmd_123). Your computer looks offline or asleep, so it will pick this up when it wakes.",
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("formats recent run lists compactly", async () => {
|
|
146
|
+
const result = await handleRemoteCodeCommand(
|
|
147
|
+
telegramIncoming("list", "/code list"),
|
|
148
|
+
adapter,
|
|
149
|
+
{
|
|
150
|
+
resolveOwner: () => "owner@example.test",
|
|
151
|
+
relay: async () => ({
|
|
152
|
+
ok: true,
|
|
153
|
+
runs: [
|
|
154
|
+
{ id: "run_a", title: "Fix auth", status: "running" },
|
|
155
|
+
{ id: "run_b", title: "Add docs", status: "completed" },
|
|
156
|
+
],
|
|
157
|
+
}),
|
|
158
|
+
},
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
expect(result).toEqual({
|
|
162
|
+
handled: true,
|
|
163
|
+
responseText:
|
|
164
|
+
"Recent code-agent runs:\n1. Fix auth — running (run_a)\n2. Add docs — completed (run_b)",
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
});
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
IncomingMessage,
|
|
3
|
+
PlatformAdapter,
|
|
4
|
+
} from "@agent-native/core/server";
|
|
5
|
+
|
|
6
|
+
export type RemoteCodeCommand =
|
|
7
|
+
| { type: "create"; prompt: string }
|
|
8
|
+
| { type: "list" }
|
|
9
|
+
| { type: "status"; runRef?: string }
|
|
10
|
+
| { type: "continue"; runRef: string; text: string }
|
|
11
|
+
| { type: "approve"; approvalId: string }
|
|
12
|
+
| { type: "deny"; approvalId: string }
|
|
13
|
+
| { type: "stop"; runRef: string }
|
|
14
|
+
| { type: "help"; reason?: string };
|
|
15
|
+
|
|
16
|
+
export interface RemoteCodeCommandEnvelope {
|
|
17
|
+
kind: "code-agent";
|
|
18
|
+
ownerEmail: string;
|
|
19
|
+
command: Exclude<RemoteCodeCommand, { type: "help" }>;
|
|
20
|
+
source: {
|
|
21
|
+
platform: string;
|
|
22
|
+
externalThreadId: string;
|
|
23
|
+
senderId?: string;
|
|
24
|
+
senderName?: string;
|
|
25
|
+
messageId?: string;
|
|
26
|
+
timestamp: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface RemoteCodeRunSummary {
|
|
31
|
+
id?: string;
|
|
32
|
+
runId?: string;
|
|
33
|
+
title?: string;
|
|
34
|
+
prompt?: string;
|
|
35
|
+
status?: string;
|
|
36
|
+
updatedAt?: string | number | Date;
|
|
37
|
+
createdAt?: string | number | Date;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface RemoteCodeCommandResult {
|
|
41
|
+
ok?: boolean;
|
|
42
|
+
status?: string;
|
|
43
|
+
hostOnline?: boolean;
|
|
44
|
+
hostStatus?: string;
|
|
45
|
+
commandId?: string;
|
|
46
|
+
requestId?: string;
|
|
47
|
+
runId?: string;
|
|
48
|
+
run?: RemoteCodeRunSummary;
|
|
49
|
+
runs?: RemoteCodeRunSummary[];
|
|
50
|
+
message?: string;
|
|
51
|
+
error?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type RemoteCodeCommandRelay = (
|
|
55
|
+
envelope: RemoteCodeCommandEnvelope,
|
|
56
|
+
) => Promise<RemoteCodeCommandResult>;
|
|
57
|
+
|
|
58
|
+
export interface HandleRemoteCodeCommandOptions {
|
|
59
|
+
resolveOwner: () => Promise<string> | string;
|
|
60
|
+
relay?: RemoteCodeCommandRelay;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const CODE_COMMAND_RE = /^\/code(?:@[a-zA-Z0-9_]+)?(?:\s+|$)/i;
|
|
64
|
+
|
|
65
|
+
export function parseTelegramCodeCommand(
|
|
66
|
+
incoming: Pick<IncomingMessage, "platform" | "text" | "platformContext">,
|
|
67
|
+
): RemoteCodeCommand | null {
|
|
68
|
+
if (incoming.platform !== "telegram") return null;
|
|
69
|
+
|
|
70
|
+
const rawText = rawTelegramText(incoming);
|
|
71
|
+
if (!rawText || !CODE_COMMAND_RE.test(rawText)) return null;
|
|
72
|
+
|
|
73
|
+
return parseCodeCommandBody(rawText.replace(CODE_COMMAND_RE, "").trim());
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function handleRemoteCodeCommand(
|
|
77
|
+
incoming: IncomingMessage,
|
|
78
|
+
_adapter: PlatformAdapter,
|
|
79
|
+
options: HandleRemoteCodeCommandOptions,
|
|
80
|
+
): Promise<{ handled: true; responseText?: string } | { handled: false }> {
|
|
81
|
+
const command = parseTelegramCodeCommand(incoming);
|
|
82
|
+
if (!command) return { handled: false };
|
|
83
|
+
|
|
84
|
+
if (command.type === "help") {
|
|
85
|
+
return { handled: true, responseText: formatCodeCommandHelp(command) };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const ownerEmail = await options.resolveOwner();
|
|
90
|
+
const envelope = createRemoteCodeCommandEnvelope(
|
|
91
|
+
incoming,
|
|
92
|
+
ownerEmail,
|
|
93
|
+
command,
|
|
94
|
+
);
|
|
95
|
+
const relay = options.relay ?? enqueueRemoteCodeCommand;
|
|
96
|
+
const result = await relay(envelope);
|
|
97
|
+
return {
|
|
98
|
+
handled: true,
|
|
99
|
+
responseText: formatRemoteCodeCommandResult(command, result),
|
|
100
|
+
};
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return {
|
|
103
|
+
handled: true,
|
|
104
|
+
responseText:
|
|
105
|
+
error instanceof Error
|
|
106
|
+
? `I couldn't route that code command: ${error.message}`
|
|
107
|
+
: "I couldn't route that code command.",
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function createRemoteCodeCommandEnvelope(
|
|
113
|
+
incoming: IncomingMessage,
|
|
114
|
+
ownerEmail: string,
|
|
115
|
+
command: Exclude<RemoteCodeCommand, { type: "help" }>,
|
|
116
|
+
): RemoteCodeCommandEnvelope {
|
|
117
|
+
return {
|
|
118
|
+
kind: "code-agent",
|
|
119
|
+
ownerEmail,
|
|
120
|
+
command,
|
|
121
|
+
source: {
|
|
122
|
+
platform: incoming.platform,
|
|
123
|
+
externalThreadId: incoming.externalThreadId,
|
|
124
|
+
senderId: incoming.senderId,
|
|
125
|
+
senderName: incoming.senderName,
|
|
126
|
+
messageId: contextString(incoming.platformContext.messageId),
|
|
127
|
+
timestamp: incoming.timestamp,
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export async function enqueueRemoteCodeCommand(
|
|
133
|
+
envelope: RemoteCodeCommandEnvelope,
|
|
134
|
+
): Promise<RemoteCodeCommandResult> {
|
|
135
|
+
const helperResult = await tryCoreRemoteCommandHelper(envelope);
|
|
136
|
+
if (helperResult) return helperResult;
|
|
137
|
+
|
|
138
|
+
const endpoint = `${resolveRemoteRelayBaseUrl()}/_agent-native/integrations/remote/enqueue`;
|
|
139
|
+
const response = await fetch(endpoint, {
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: { "Content-Type": "application/json" },
|
|
142
|
+
body: JSON.stringify(envelope),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
let body: unknown = null;
|
|
146
|
+
try {
|
|
147
|
+
body = await response.json();
|
|
148
|
+
} catch {
|
|
149
|
+
body = null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
const message =
|
|
154
|
+
typeof body === "object" && body && "error" in body
|
|
155
|
+
? String((body as { error?: unknown }).error)
|
|
156
|
+
: `remote relay returned ${response.status}`;
|
|
157
|
+
throw new Error(message);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return normalizeRemoteCodeCommandResult(body);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function formatRemoteCodeCommandResult(
|
|
164
|
+
command: Exclude<RemoteCodeCommand, { type: "help" }>,
|
|
165
|
+
result: RemoteCodeCommandResult,
|
|
166
|
+
): string {
|
|
167
|
+
if (result.message?.trim()) return result.message.trim();
|
|
168
|
+
if (result.error?.trim())
|
|
169
|
+
return `Code command failed: ${result.error.trim()}`;
|
|
170
|
+
|
|
171
|
+
if (command.type === "list") return formatRunList(result.runs ?? []);
|
|
172
|
+
if (command.type === "status") return formatStatus(command, result);
|
|
173
|
+
|
|
174
|
+
const id =
|
|
175
|
+
result.runId ||
|
|
176
|
+
result.run?.runId ||
|
|
177
|
+
result.run?.id ||
|
|
178
|
+
result.commandId ||
|
|
179
|
+
result.requestId;
|
|
180
|
+
const suffix = id ? ` (${id})` : "";
|
|
181
|
+
const offline = isOfflineOrSleeping(result);
|
|
182
|
+
|
|
183
|
+
if (command.type === "create") {
|
|
184
|
+
return offline
|
|
185
|
+
? `Queued code run${suffix}. Your computer looks offline or asleep, so it will pick this up when it wakes.`
|
|
186
|
+
: `Queued code run${suffix}.`;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (command.type === "continue") {
|
|
190
|
+
return offline
|
|
191
|
+
? `Queued follow-up for ${command.runRef}. Your computer looks offline or asleep, so it will pick this up when it wakes.`
|
|
192
|
+
: `Queued follow-up for ${command.runRef}.`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (command.type === "approve") {
|
|
196
|
+
return `Approved code-agent request ${command.approvalId}.`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (command.type === "deny") {
|
|
200
|
+
return `Denied code-agent request ${command.approvalId}.`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (command.type === "stop") {
|
|
204
|
+
return offline
|
|
205
|
+
? `Queued stop request for ${command.runRef}. Your computer looks offline or asleep, so it will receive the stop request when it wakes.`
|
|
206
|
+
: `Stop requested for ${command.runRef}.`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return "Code command routed.";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function parseCodeCommandBody(body: string): RemoteCodeCommand {
|
|
213
|
+
if (!body) return { type: "help" };
|
|
214
|
+
|
|
215
|
+
const [verbRaw = "", ...restParts] = body.split(/\s+/);
|
|
216
|
+
const verb = verbRaw.toLowerCase();
|
|
217
|
+
const rest = restParts.join(" ").trim();
|
|
218
|
+
|
|
219
|
+
if (verb === "help") return { type: "help" };
|
|
220
|
+
if (verb === "list") return { type: "list" };
|
|
221
|
+
if (verb === "status") {
|
|
222
|
+
return rest ? { type: "status", runRef: rest } : { type: "status" };
|
|
223
|
+
}
|
|
224
|
+
if (verb === "continue") {
|
|
225
|
+
const { first, rest: text } = splitFirst(rest);
|
|
226
|
+
if (!first || !text) {
|
|
227
|
+
return { type: "help", reason: "continue needs a run id and text" };
|
|
228
|
+
}
|
|
229
|
+
return { type: "continue", runRef: first, text };
|
|
230
|
+
}
|
|
231
|
+
if (verb === "approve") {
|
|
232
|
+
return rest
|
|
233
|
+
? { type: "approve", approvalId: rest }
|
|
234
|
+
: { type: "help", reason: "approve needs a request id" };
|
|
235
|
+
}
|
|
236
|
+
if (verb === "deny") {
|
|
237
|
+
return rest
|
|
238
|
+
? { type: "deny", approvalId: rest }
|
|
239
|
+
: { type: "help", reason: "deny needs a request id" };
|
|
240
|
+
}
|
|
241
|
+
if (verb === "stop") {
|
|
242
|
+
return rest
|
|
243
|
+
? { type: "stop", runRef: rest }
|
|
244
|
+
: { type: "help", reason: "stop needs a run id or list index" };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return { type: "create", prompt: body };
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function rawTelegramText(
|
|
251
|
+
incoming: Pick<IncomingMessage, "text" | "platformContext">,
|
|
252
|
+
): string | null {
|
|
253
|
+
const context = incoming.platformContext;
|
|
254
|
+
return (
|
|
255
|
+
contextString(context.rawText) ||
|
|
256
|
+
contextString(context.originalText) ||
|
|
257
|
+
contextString(context.messageText) ||
|
|
258
|
+
(CODE_COMMAND_RE.test(incoming.text) ? incoming.text : null)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function formatCodeCommandHelp(
|
|
263
|
+
command?: Extract<RemoteCodeCommand, { type: "help" }>,
|
|
264
|
+
): string {
|
|
265
|
+
const prefix = command?.reason ? `${command.reason}.\n\n` : "";
|
|
266
|
+
return `${prefix}Use /code <prompt>, /code list, /code status [run], /code continue <run> <text>, /code approve <id>, /code deny <id>, or /code stop <run>.`;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function formatRunList(runs: RemoteCodeRunSummary[]): string {
|
|
270
|
+
if (!runs.length) return "No recent code-agent runs found.";
|
|
271
|
+
const lines = runs.slice(0, 8).map((run, index) => {
|
|
272
|
+
const id = run.runId || run.id || "unknown";
|
|
273
|
+
const title = run.title || run.prompt || "Untitled run";
|
|
274
|
+
const status = run.status || "unknown";
|
|
275
|
+
return `${index + 1}. ${title} — ${status} (${id})`;
|
|
276
|
+
});
|
|
277
|
+
return `Recent code-agent runs:\n${lines.join("\n")}`;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function formatStatus(
|
|
281
|
+
command: Extract<RemoteCodeCommand, { type: "status" }>,
|
|
282
|
+
result: RemoteCodeCommandResult,
|
|
283
|
+
): string {
|
|
284
|
+
const run = result.run;
|
|
285
|
+
const hostStatus =
|
|
286
|
+
result.hostStatus || (result.hostOnline ? "online" : "offline");
|
|
287
|
+
if (!run) {
|
|
288
|
+
const target = command.runRef ? ` for ${command.runRef}` : "";
|
|
289
|
+
return `Code-agent host is ${hostStatus}${target}.`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const id = run.runId || run.id || command.runRef || "unknown";
|
|
293
|
+
const title = run.title || run.prompt || "Untitled run";
|
|
294
|
+
const status = run.status || result.status || "unknown";
|
|
295
|
+
const updated = formatDate(run.updatedAt || run.createdAt);
|
|
296
|
+
return [
|
|
297
|
+
`Code run ${id}: ${status}`,
|
|
298
|
+
`Task: ${title}`,
|
|
299
|
+
`Host: ${hostStatus}`,
|
|
300
|
+
updated ? `Updated: ${updated}` : "",
|
|
301
|
+
]
|
|
302
|
+
.filter(Boolean)
|
|
303
|
+
.join("\n");
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function isOfflineOrSleeping(result: RemoteCodeCommandResult): boolean {
|
|
307
|
+
if (result.hostOnline === false) return true;
|
|
308
|
+
const status = result.hostStatus?.toLowerCase();
|
|
309
|
+
return status === "offline" || status === "asleep" || status === "sleeping";
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function splitFirst(value: string): { first: string; rest: string } {
|
|
313
|
+
const trimmed = value.trim();
|
|
314
|
+
const match = trimmed.match(/^(\S+)(?:\s+([\s\S]+))?$/);
|
|
315
|
+
return { first: match?.[1] || "", rest: match?.[2]?.trim() || "" };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function contextString(value: unknown): string | undefined {
|
|
319
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
320
|
+
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
321
|
+
return undefined;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function formatDate(value: RemoteCodeRunSummary["updatedAt"]): string | null {
|
|
325
|
+
if (!value) return null;
|
|
326
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
327
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
328
|
+
return date.toISOString();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
async function tryCoreRemoteCommandHelper(
|
|
332
|
+
envelope: RemoteCodeCommandEnvelope,
|
|
333
|
+
): Promise<RemoteCodeCommandResult | null> {
|
|
334
|
+
const core = (await import("@agent-native/core/server")) as Record<
|
|
335
|
+
string,
|
|
336
|
+
unknown
|
|
337
|
+
>;
|
|
338
|
+
const helper =
|
|
339
|
+
core.enqueueRemoteCommand ||
|
|
340
|
+
core.enqueueIntegrationRemoteCommand ||
|
|
341
|
+
core.enqueueRemoteIntegrationCommand;
|
|
342
|
+
if (typeof helper !== "function") return null;
|
|
343
|
+
return normalizeRemoteCodeCommandResult(await helper(envelope));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function normalizeRemoteCodeCommandResult(
|
|
347
|
+
value: unknown,
|
|
348
|
+
): RemoteCodeCommandResult {
|
|
349
|
+
if (!value || typeof value !== "object") return { ok: true };
|
|
350
|
+
const result = value as RemoteCodeCommandResult;
|
|
351
|
+
return {
|
|
352
|
+
ok: result.ok,
|
|
353
|
+
status: contextString(result.status),
|
|
354
|
+
hostOnline:
|
|
355
|
+
typeof result.hostOnline === "boolean" ? result.hostOnline : undefined,
|
|
356
|
+
hostStatus: contextString(result.hostStatus),
|
|
357
|
+
commandId: contextString(result.commandId),
|
|
358
|
+
requestId: contextString(result.requestId),
|
|
359
|
+
runId: contextString(result.runId),
|
|
360
|
+
run: result.run,
|
|
361
|
+
runs: Array.isArray(result.runs) ? result.runs : undefined,
|
|
362
|
+
message: contextString(result.message),
|
|
363
|
+
error: contextString(result.error),
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function resolveRemoteRelayBaseUrl(): string {
|
|
368
|
+
const raw =
|
|
369
|
+
process.env.WEBHOOK_BASE_URL ||
|
|
370
|
+
process.env.APP_URL ||
|
|
371
|
+
process.env.URL ||
|
|
372
|
+
"http://localhost:3000";
|
|
373
|
+
if (/^https?:\/\//i.test(raw)) return raw.replace(/\/$/, "");
|
|
374
|
+
return `https://${raw.replace(/\/$/, "")}`;
|
|
375
|
+
}
|
|
@@ -423,7 +423,7 @@ async function notifyApprovers(requestId: string, summary: string) {
|
|
|
423
423
|
}).catch(() => {});
|
|
424
424
|
}
|
|
425
425
|
|
|
426
|
-
async function createApprovalRequest(input: {
|
|
426
|
+
export async function createApprovalRequest(input: {
|
|
427
427
|
changeType: string;
|
|
428
428
|
targetType: string;
|
|
429
429
|
targetId?: string | null;
|
|
@@ -564,6 +564,42 @@ async function applyApprovedRequest(request: DispatchApprovalRequest) {
|
|
|
564
564
|
request.reviewedBy || currentOwnerEmail(),
|
|
565
565
|
);
|
|
566
566
|
}
|
|
567
|
+
if (request.changeType === "dream-proposal.apply") {
|
|
568
|
+
const { applyApprovedDreamProposal } = await import("./dreams-store.js");
|
|
569
|
+
return applyApprovedDreamProposal(
|
|
570
|
+
payload.proposalId,
|
|
571
|
+
request.reviewedBy || currentOwnerEmail(),
|
|
572
|
+
requestCtx,
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
if (request.changeType === "workspace-resource.create") {
|
|
576
|
+
const { applyWorkspaceResourceCreate } =
|
|
577
|
+
await import("./workspace-resources-store.js");
|
|
578
|
+
return applyWorkspaceResourceCreate(
|
|
579
|
+
payload.input,
|
|
580
|
+
request.reviewedBy || currentOwnerEmail(),
|
|
581
|
+
requestCtx,
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
if (request.changeType === "workspace-resource.update") {
|
|
585
|
+
const { applyWorkspaceResourceUpdate } =
|
|
586
|
+
await import("./workspace-resources-store.js");
|
|
587
|
+
return applyWorkspaceResourceUpdate(
|
|
588
|
+
payload.id,
|
|
589
|
+
payload.input,
|
|
590
|
+
request.reviewedBy || currentOwnerEmail(),
|
|
591
|
+
requestCtx,
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
if (request.changeType === "workspace-resource.delete") {
|
|
595
|
+
const { applyWorkspaceResourceDelete } =
|
|
596
|
+
await import("./workspace-resources-store.js");
|
|
597
|
+
return applyWorkspaceResourceDelete(
|
|
598
|
+
payload.id,
|
|
599
|
+
request.reviewedBy || currentOwnerEmail(),
|
|
600
|
+
requestCtx,
|
|
601
|
+
);
|
|
602
|
+
}
|
|
567
603
|
throw new Error(`Unsupported approval request type: ${request.changeType}`);
|
|
568
604
|
}
|
|
569
605
|
|