@vellumai/assistant 0.4.45 → 0.4.48
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/ARCHITECTURE.md +6 -6
- package/docs/architecture/memory.md +1 -1
- package/docs/architecture/scheduling.md +2 -3
- package/docs/architecture/security.md +5 -5
- package/docs/trusted-contact-access.md +5 -6
- package/package.json +4 -1
- package/src/__tests__/avatar-e2e.test.ts +18 -219
- package/src/__tests__/avatar-generator.test.ts +5 -57
- package/src/__tests__/browser-fill-credential.test.ts +5 -2
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +2 -1
- package/src/__tests__/channel-readiness-routes.test.ts +20 -19
- package/src/__tests__/cli.test.ts +23 -0
- package/src/__tests__/credential-broker-browser-fill.test.ts +23 -22
- package/src/__tests__/credential-broker-server-use.test.ts +22 -21
- package/src/__tests__/credential-broker.test.ts +2 -1
- package/src/__tests__/credential-metadata-store.test.ts +240 -18
- package/src/__tests__/credential-resolve.test.ts +5 -4
- package/src/__tests__/credential-security-e2e.test.ts +8 -8
- package/src/__tests__/credential-security-invariants.test.ts +104 -7
- package/src/__tests__/credential-vault-unit.test.ts +22 -20
- package/src/__tests__/credential-vault.test.ts +284 -12
- package/src/__tests__/credentials-cli.test.ts +11 -6
- package/src/__tests__/gateway-only-enforcement.test.ts +4 -2
- package/src/__tests__/gemini-image-service.test.ts +75 -45
- package/src/__tests__/gemini-provider.test.ts +9 -6
- package/src/__tests__/guardian-action-conversation-turn.test.ts +1 -33
- package/src/__tests__/guardian-action-copy-generator.test.ts +0 -20
- package/src/__tests__/guardian-action-followup-executor.test.ts +1 -28
- package/src/__tests__/guardian-action-followup-store.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +35 -0
- package/src/__tests__/integration-status.test.ts +53 -21
- package/src/__tests__/managed-proxy-context.test.ts +5 -3
- package/src/__tests__/media-generate-image.test.ts +63 -2
- package/src/__tests__/media-reuse-story.e2e.test.ts +7 -3
- package/src/__tests__/messaging-send-tool.test.ts +4 -6
- package/src/__tests__/provider-fail-open-selection.test.ts +3 -1
- package/src/__tests__/provider-managed-proxy-integration.test.ts +70 -6
- package/src/__tests__/schedule-store.test.ts +1 -1
- package/src/__tests__/schema-transforms.test.ts +226 -0
- package/src/__tests__/script-proxy-injection-runtime.test.ts +23 -13
- package/src/__tests__/script-proxy-policy-runtime.test.ts +1 -1
- package/src/__tests__/script-proxy-session-manager.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +5 -3
- package/src/__tests__/session-messaging-secret-redirect.test.ts +5 -4
- package/src/__tests__/skills-uninstall.test.ts +2 -2
- package/src/__tests__/skills.test.ts +0 -9
- package/src/__tests__/slack-channel-config.test.ts +9 -8
- package/src/__tests__/slack-share-routes.test.ts +11 -6
- package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -0
- package/src/__tests__/twilio-config.test.ts +2 -1
- package/src/__tests__/twilio-provider.test.ts +4 -2
- package/src/__tests__/twilio-routes.test.ts +5 -4
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/AGENTS.md +1 -1
- package/src/calls/call-domain.ts +7 -4
- package/src/calls/twilio-config.ts +2 -1
- package/src/calls/twilio-provider.ts +2 -1
- package/src/calls/twilio-rest.ts +2 -2
- package/src/cli/commands/browser-relay.ts +40 -15
- package/src/cli/commands/credentials.ts +9 -8
- package/src/cli/commands/oauth.ts +1 -1
- package/src/cli.ts +3 -2
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -4
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +29 -32
- package/src/config/bundled-skills/gmail/SKILL.md +4 -4
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +54 -61
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +25 -28
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +14 -17
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +39 -44
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +61 -58
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +50 -49
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +11 -13
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +148 -146
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +175 -173
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +4 -7
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +71 -76
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +32 -38
- package/src/config/bundled-skills/google-calendar/SKILL.md +2 -2
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +70 -29
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +9 -10
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +5 -6
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +4 -5
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +14 -15
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +37 -37
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +4 -9
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +24 -3
- package/src/config/bundled-skills/messaging/SKILL.md +6 -6
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +62 -63
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +15 -16
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +6 -7
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +14 -15
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +4 -5
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +128 -128
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +33 -34
- package/src/config/bundled-skills/messaging/tools/shared.ts +11 -11
- package/src/config/bundled-skills/notifications/SKILL.md +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +5 -5
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/slack/tools/shared.ts +4 -10
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +15 -16
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +4 -5
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +95 -92
- package/src/config/loader.ts +6 -0
- package/src/daemon/computer-use-session.ts +7 -1
- package/src/daemon/guardian-action-generators.ts +4 -5
- package/src/daemon/handlers/config-slack-channel.ts +37 -20
- package/src/daemon/handlers/config-telegram.ts +33 -20
- package/src/daemon/lifecycle.ts +9 -1
- package/src/daemon/message-types/integrations.ts +1 -0
- package/src/daemon/ride-shotgun-handler.ts +3 -1
- package/src/daemon/session-messaging.ts +3 -1
- package/src/daemon/session-tool-setup.ts +18 -2
- package/src/daemon/session.ts +1 -1
- package/src/email/providers/index.ts +2 -1
- package/src/instrument.ts +15 -1
- package/src/media/app-icon-generator.ts +30 -4
- package/src/media/avatar-router.ts +28 -62
- package/src/media/gemini-image-service.ts +28 -2
- package/src/memory/canonical-guardian-store.ts +1 -1
- package/src/memory/guardian-action-store.ts +1 -1
- package/src/memory/schema/guardian.ts +1 -1
- package/src/messaging/provider.ts +16 -10
- package/src/messaging/providers/gmail/adapter.ts +40 -23
- package/src/messaging/providers/gmail/client.ts +203 -122
- package/src/messaging/providers/gmail/people-client.ts +26 -18
- package/src/messaging/providers/slack/adapter.ts +29 -19
- package/src/messaging/providers/slack/client.ts +265 -78
- package/src/messaging/providers/telegram-bot/adapter.ts +5 -4
- package/src/messaging/providers/whatsapp/adapter.ts +6 -3
- package/src/messaging/registry.ts +2 -1
- package/src/oauth/byo-connection.test.ts +436 -0
- package/src/oauth/byo-connection.ts +112 -0
- package/src/oauth/connect-orchestrator.ts +27 -0
- package/src/oauth/connection-resolver.ts +34 -0
- package/src/oauth/connection.ts +38 -0
- package/src/oauth/platform-connection.test.ts +163 -0
- package/src/oauth/platform-connection.ts +110 -0
- package/src/oauth/provider-base-urls.ts +21 -0
- package/src/oauth/provider-profiles.ts +1 -1
- package/src/oauth/token-persistence.ts +20 -20
- package/src/permissions/checker.ts +6 -1
- package/src/prompts/system-prompt.ts +52 -15
- package/src/prompts/templates/BOOTSTRAP.md +1 -1
- package/src/providers/gemini/client.ts +15 -6
- package/src/providers/managed-proxy/constants.ts +2 -2
- package/src/providers/managed-proxy/context.ts +5 -1
- package/src/providers/ratelimit.ts +17 -0
- package/src/providers/registry.ts +2 -2
- package/src/runtime/AGENTS.md +18 -1
- package/src/runtime/auth/route-policy.ts +1 -0
- package/src/runtime/channel-invite-transports/telegram.ts +2 -1
- package/src/runtime/channel-readiness-service.ts +168 -195
- package/src/runtime/channel-readiness-types.ts +4 -0
- package/src/runtime/guardian-action-conversation-turn.ts +1 -3
- package/src/runtime/guardian-action-followup-executor.ts +1 -2
- package/src/runtime/guardian-action-message-composer.ts +3 -23
- package/src/runtime/http-server.ts +9 -4
- package/src/runtime/http-types.ts +0 -1
- package/src/runtime/middleware/rate-limiter.ts +74 -20
- package/src/runtime/middleware/twilio-validation.ts +1 -3
- package/src/runtime/routes/channel-readiness-routes.ts +2 -0
- package/src/runtime/routes/diagnostics-routes.ts +11 -9
- package/src/runtime/routes/guardian-approval-interception.ts +20 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +71 -25
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -5
- package/src/runtime/routes/integrations/slack/share.ts +3 -2
- package/src/runtime/routes/integrations/twilio.ts +6 -5
- package/src/runtime/routes/secret-routes.ts +3 -2
- package/src/runtime/routes/settings-routes.ts +75 -17
- package/src/runtime/telegram-streaming-delivery.test.ts +132 -0
- package/src/runtime/telegram-streaming-delivery.ts +11 -1
- package/src/schedule/integration-status.ts +5 -4
- package/src/security/credential-key.ts +170 -0
- package/src/security/token-manager.ts +36 -7
- package/src/tools/apps/definitions.ts +0 -5
- package/src/tools/assets/materialize.ts +0 -5
- package/src/tools/assets/search.ts +0 -5
- package/src/tools/browser/headless-browser.ts +1 -67
- package/src/tools/claude-code/claude-code.ts +0 -5
- package/src/tools/computer-use/request-computer-control.ts +0 -5
- package/src/tools/credentials/broker.ts +6 -4
- package/src/tools/credentials/metadata-store.ts +72 -20
- package/src/tools/credentials/resolve.ts +2 -1
- package/src/tools/credentials/vault.ts +77 -16
- package/src/tools/filesystem/edit.ts +1 -6
- package/src/tools/filesystem/read.ts +0 -5
- package/src/tools/filesystem/write.ts +1 -6
- package/src/tools/host-filesystem/edit.ts +1 -6
- package/src/tools/host-filesystem/read.ts +1 -6
- package/src/tools/host-filesystem/write.ts +1 -6
- package/src/tools/mcp/mcp-tool-factory.ts +18 -1
- package/src/tools/memory/definitions.ts +0 -5
- package/src/tools/network/web-fetch.ts +0 -5
- package/src/tools/network/web-search.ts +0 -5
- package/src/tools/schema-transforms.ts +99 -0
- package/src/tools/skills/load.ts +0 -5
- package/src/tools/swarm/delegate.ts +0 -5
- package/src/tools/system/avatar-generator.ts +3 -44
- package/src/tools/ui-surface/definitions.ts +0 -15
- package/src/tools/watch/screen-watch.ts +0 -5
- package/src/version.ts +10 -0
- package/src/watcher/providers/github.ts +51 -52
- package/src/watcher/providers/gmail.ts +88 -80
- package/src/watcher/providers/google-calendar.ts +93 -86
- package/src/watcher/providers/linear.ts +87 -93
- package/src/__tests__/avatar-router.test.ts +0 -149
- package/src/__tests__/managed-avatar-client.test.ts +0 -337
- package/src/config/bundled-skills/doordash/SKILL.md +0 -170
- package/src/config/bundled-skills/doordash/__tests__/doordash-client.test.ts +0 -205
- package/src/config/bundled-skills/doordash/__tests__/doordash-session.test.ts +0 -74
- package/src/config/bundled-skills/doordash/doordash-cli.ts +0 -1081
- package/src/config/bundled-skills/doordash/doordash-entry.ts +0 -22
- package/src/config/bundled-skills/doordash/lib/cart-queries.ts +0 -787
- package/src/config/bundled-skills/doordash/lib/client.ts +0 -1069
- package/src/config/bundled-skills/doordash/lib/order-queries.ts +0 -85
- package/src/config/bundled-skills/doordash/lib/queries.ts +0 -28
- package/src/config/bundled-skills/doordash/lib/query-extractor.ts +0 -94
- package/src/config/bundled-skills/doordash/lib/search-queries.ts +0 -203
- package/src/config/bundled-skills/doordash/lib/session.ts +0 -96
- package/src/config/bundled-skills/doordash/lib/shared/errors.ts +0 -61
- package/src/config/bundled-skills/doordash/lib/shared/network-recorder.ts +0 -380
- package/src/config/bundled-skills/doordash/lib/shared/platform.ts +0 -55
- package/src/config/bundled-skills/doordash/lib/shared/recording-store.ts +0 -43
- package/src/config/bundled-skills/doordash/lib/shared/recording-types.ts +0 -49
- package/src/config/bundled-skills/doordash/lib/shared/truncate.ts +0 -6
- package/src/config/bundled-skills/doordash/lib/store-queries.ts +0 -246
- package/src/config/bundled-skills/doordash/lib/types.ts +0 -367
- package/src/media/avatar-types.ts +0 -53
- package/src/media/managed-avatar-client.ts +0 -225
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import { RateLimitError, SessionExpiredError } from "../lib/client.js";
|
|
4
|
-
|
|
5
|
-
describe("SessionExpiredError", () => {
|
|
6
|
-
it("is an instance of Error", () => {
|
|
7
|
-
const err = new SessionExpiredError("test reason");
|
|
8
|
-
expect(err).toBeInstanceOf(Error);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("has name set to SessionExpiredError", () => {
|
|
12
|
-
const err = new SessionExpiredError("test reason");
|
|
13
|
-
expect(err.name).toBe("SessionExpiredError");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("preserves the reason as the message", () => {
|
|
17
|
-
const err = new SessionExpiredError("DoorDash session has expired.");
|
|
18
|
-
expect(err.message).toBe("DoorDash session has expired.");
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("can be distinguished from plain Error via instanceof", () => {
|
|
22
|
-
const sessionErr = new SessionExpiredError("expired");
|
|
23
|
-
const plainErr = new Error("something else");
|
|
24
|
-
expect(sessionErr instanceof SessionExpiredError).toBe(true);
|
|
25
|
-
expect(plainErr instanceof SessionExpiredError).toBe(false);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it("produces a useful stack trace", () => {
|
|
29
|
-
const err = new SessionExpiredError("no session");
|
|
30
|
-
expect(err.stack).toBeDefined();
|
|
31
|
-
expect(err.stack).toContain("SessionExpiredError");
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe("expired session classification", () => {
|
|
36
|
-
// The CDP response handler in cdpFetch classifies certain HTTP statuses
|
|
37
|
-
// as session-expired. We test the classification logic by simulating
|
|
38
|
-
// the parsed response structure that cdpFetch evaluates.
|
|
39
|
-
|
|
40
|
-
function classifyResponse(parsed: Record<string, unknown>): Error {
|
|
41
|
-
// Mirrors the classification logic from cdpFetch (client.ts lines 188-200)
|
|
42
|
-
if (parsed.__error) {
|
|
43
|
-
if (parsed.__status === 401) {
|
|
44
|
-
return new SessionExpiredError("DoorDash session has expired.");
|
|
45
|
-
} else if (parsed.__status === 403) {
|
|
46
|
-
return new RateLimitError("DoorDash rate limit hit (HTTP 403).");
|
|
47
|
-
}
|
|
48
|
-
return new Error(
|
|
49
|
-
(parsed.__message as string) ??
|
|
50
|
-
`HTTP ${parsed.__status}: ${(parsed.__body as string) ?? ""}`,
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
return new Error("No error");
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
it("classifies HTTP 401 as SessionExpiredError", () => {
|
|
57
|
-
const err = classifyResponse({
|
|
58
|
-
__error: true,
|
|
59
|
-
__status: 401,
|
|
60
|
-
__body: "Unauthorized",
|
|
61
|
-
});
|
|
62
|
-
expect(err).toBeInstanceOf(SessionExpiredError);
|
|
63
|
-
expect(err.message).toBe("DoorDash session has expired.");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("classifies HTTP 403 as RateLimitError", () => {
|
|
67
|
-
const err = classifyResponse({
|
|
68
|
-
__error: true,
|
|
69
|
-
__status: 403,
|
|
70
|
-
__body: "Forbidden",
|
|
71
|
-
});
|
|
72
|
-
expect(err).toBeInstanceOf(RateLimitError);
|
|
73
|
-
expect(err.message).toBe("DoorDash rate limit hit (HTTP 403).");
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("classifies HTTP 500 as a generic Error, not session expired", () => {
|
|
77
|
-
const err = classifyResponse({
|
|
78
|
-
__error: true,
|
|
79
|
-
__status: 500,
|
|
80
|
-
__body: "Internal Server Error",
|
|
81
|
-
});
|
|
82
|
-
expect(err).not.toBeInstanceOf(SessionExpiredError);
|
|
83
|
-
expect(err.message).toBe("HTTP 500: Internal Server Error");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("classifies HTTP 429 as a generic Error", () => {
|
|
87
|
-
const err = classifyResponse({
|
|
88
|
-
__error: true,
|
|
89
|
-
__status: 429,
|
|
90
|
-
__body: "Rate limited",
|
|
91
|
-
});
|
|
92
|
-
expect(err).not.toBeInstanceOf(SessionExpiredError);
|
|
93
|
-
expect(err.message).toBe("HTTP 429: Rate limited");
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("uses __message when available", () => {
|
|
97
|
-
const err = classifyResponse({ __error: true, __message: "fetch failed" });
|
|
98
|
-
expect(err).not.toBeInstanceOf(SessionExpiredError);
|
|
99
|
-
expect(err.message).toBe("fetch failed");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("handles response with no __body or __message gracefully", () => {
|
|
103
|
-
const err = classifyResponse({ __error: true, __status: 502 });
|
|
104
|
-
expect(err).not.toBeInstanceOf(SessionExpiredError);
|
|
105
|
-
expect(err.message).toBe("HTTP 502: ");
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
describe("CDP failure scenarios", () => {
|
|
110
|
-
// These test the error conditions that cdpFetch can encounter:
|
|
111
|
-
// 1. CDP protocol error (msg.error present)
|
|
112
|
-
// 2. Empty CDP response (no value in result)
|
|
113
|
-
// 3. Timeout (30s)
|
|
114
|
-
// 4. WebSocket connection failure
|
|
115
|
-
|
|
116
|
-
// We can test the error construction logic without connecting to a real CDP
|
|
117
|
-
|
|
118
|
-
it("CDP protocol error produces a descriptive message", () => {
|
|
119
|
-
// Simulates the error path at client.ts line 143
|
|
120
|
-
const cdpError = { message: "Cannot find context with specified id" };
|
|
121
|
-
const err = new Error(`CDP error: ${cdpError.message}`);
|
|
122
|
-
expect(err.message).toBe(
|
|
123
|
-
"CDP error: Cannot find context with specified id",
|
|
124
|
-
);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("Empty CDP response produces a clear error", () => {
|
|
128
|
-
// Simulates the error path at client.ts line 149
|
|
129
|
-
const value = undefined;
|
|
130
|
-
const err = !value ? new Error("Empty CDP response") : null;
|
|
131
|
-
expect(err).not.toBeNull();
|
|
132
|
-
expect(err!.message).toBe("Empty CDP response");
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it("CDP timeout error message includes the timeout duration", () => {
|
|
136
|
-
// Simulates the timeout error at client.ts line 92
|
|
137
|
-
const err = new Error("CDP fetch timed out after 30s");
|
|
138
|
-
expect(err.message).toContain("30s");
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it("WebSocket connection failure produces SessionExpiredError", () => {
|
|
142
|
-
// Simulates ws.onerror at client.ts line 172
|
|
143
|
-
const err = new SessionExpiredError("CDP connection failed.");
|
|
144
|
-
expect(err).toBeInstanceOf(SessionExpiredError);
|
|
145
|
-
expect(err.message).toBe("CDP connection failed.");
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("findDoordashTab failure when CDP is unavailable", () => {
|
|
149
|
-
// Simulates findDoordashTab at client.ts line 67
|
|
150
|
-
const err = new SessionExpiredError(
|
|
151
|
-
"Chrome CDP not available. Run `vellum doordash refresh` first.",
|
|
152
|
-
);
|
|
153
|
-
expect(err).toBeInstanceOf(SessionExpiredError);
|
|
154
|
-
expect(err.message).toContain("Chrome CDP not available");
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("findDoordashTab failure when no tab is available", () => {
|
|
158
|
-
// Simulates findDoordashTab at client.ts line 76
|
|
159
|
-
const err = new SessionExpiredError(
|
|
160
|
-
"No Chrome tab available for DoorDash requests.",
|
|
161
|
-
);
|
|
162
|
-
expect(err).toBeInstanceOf(SessionExpiredError);
|
|
163
|
-
expect(err.message).toContain("No Chrome tab available");
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("requireSession throws SessionExpiredError when no session exists", () => {
|
|
167
|
-
// Simulates requireSession at client.ts line 56
|
|
168
|
-
const session = null;
|
|
169
|
-
const err = !session
|
|
170
|
-
? new SessionExpiredError("No DoorDash session found.")
|
|
171
|
-
: null;
|
|
172
|
-
expect(err).toBeInstanceOf(SessionExpiredError);
|
|
173
|
-
expect(err!.message).toBe("No DoorDash session found.");
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("GraphQL errors are joined with semicolons", () => {
|
|
177
|
-
// Simulates the error handling at client.ts lines 192-194
|
|
178
|
-
const errors = [
|
|
179
|
-
{ message: 'Field "x" not found' },
|
|
180
|
-
{ message: "Unauthorized" },
|
|
181
|
-
];
|
|
182
|
-
const msgs = errors.map((e) => e.message || JSON.stringify(e)).join("; ");
|
|
183
|
-
const err = new Error(`GraphQL errors: ${msgs}`);
|
|
184
|
-
expect(err.message).toBe(
|
|
185
|
-
'GraphQL errors: Field "x" not found; Unauthorized',
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it("GraphQL errors use JSON.stringify for errors without message", () => {
|
|
190
|
-
const errors = [{ extensions: { code: "INTERNAL_ERROR" } }];
|
|
191
|
-
const msgs = errors
|
|
192
|
-
.map((e) => (e as Record<string, unknown>).message || JSON.stringify(e))
|
|
193
|
-
.join("; ");
|
|
194
|
-
const err = new Error(`GraphQL errors: ${msgs}`);
|
|
195
|
-
expect(err.message).toContain("INTERNAL_ERROR");
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it("Empty GraphQL response throws", () => {
|
|
199
|
-
// Simulates client.ts lines 196-198
|
|
200
|
-
const data = undefined;
|
|
201
|
-
const err = !data ? new Error("Empty response from DoorDash API") : null;
|
|
202
|
-
expect(err).not.toBeNull();
|
|
203
|
-
expect(err!.message).toBe("Empty response from DoorDash API");
|
|
204
|
-
});
|
|
205
|
-
});
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
type DoorDashSession,
|
|
5
|
-
getCookieHeader,
|
|
6
|
-
getCsrfToken,
|
|
7
|
-
} from "../lib/session.js";
|
|
8
|
-
|
|
9
|
-
function makeCookie(
|
|
10
|
-
name: string,
|
|
11
|
-
value: string,
|
|
12
|
-
): {
|
|
13
|
-
name: string;
|
|
14
|
-
value: string;
|
|
15
|
-
domain: string;
|
|
16
|
-
path: string;
|
|
17
|
-
httpOnly: boolean;
|
|
18
|
-
secure: boolean;
|
|
19
|
-
} {
|
|
20
|
-
return {
|
|
21
|
-
name,
|
|
22
|
-
value,
|
|
23
|
-
domain: ".doordash.com",
|
|
24
|
-
path: "/",
|
|
25
|
-
httpOnly: false,
|
|
26
|
-
secure: false,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function makeSession(overrides?: Partial<DoorDashSession>): DoorDashSession {
|
|
31
|
-
return {
|
|
32
|
-
cookies: [
|
|
33
|
-
makeCookie("dd_session", "abc123"),
|
|
34
|
-
makeCookie("csrf_token", "tok456"),
|
|
35
|
-
],
|
|
36
|
-
importedAt: "2025-01-15T12:00:00.000Z",
|
|
37
|
-
recordingId: "rec-001",
|
|
38
|
-
...overrides,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
describe("DoorDash session helpers", () => {
|
|
43
|
-
describe("getCookieHeader", () => {
|
|
44
|
-
it("joins all cookies into a single header string", () => {
|
|
45
|
-
const session = makeSession();
|
|
46
|
-
const header = getCookieHeader(session);
|
|
47
|
-
expect(header).toBe("dd_session=abc123; csrf_token=tok456");
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it("returns empty string for a session with no cookies", () => {
|
|
51
|
-
const session = makeSession({ cookies: [] });
|
|
52
|
-
expect(getCookieHeader(session)).toBe("");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("handles a single cookie without trailing semicolons", () => {
|
|
56
|
-
const session = makeSession({ cookies: [makeCookie("a", "1")] });
|
|
57
|
-
expect(getCookieHeader(session)).toBe("a=1");
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
describe("getCsrfToken", () => {
|
|
62
|
-
it("extracts the csrf_token value when present", () => {
|
|
63
|
-
const session = makeSession();
|
|
64
|
-
expect(getCsrfToken(session)).toBe("tok456");
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("returns undefined when csrf_token is absent", () => {
|
|
68
|
-
const session = makeSession({
|
|
69
|
-
cookies: [makeCookie("dd_session", "abc123")],
|
|
70
|
-
});
|
|
71
|
-
expect(getCsrfToken(session)).toBeUndefined();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
});
|