@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,225 +0,0 @@
|
|
|
1
|
-
import { createHash } from "crypto";
|
|
2
|
-
|
|
3
|
-
import { getPlatformBaseUrl } from "../config/env.js";
|
|
4
|
-
import { getConfig } from "../config/loader.js";
|
|
5
|
-
import { getSecureKey } from "../security/secure-keys.js";
|
|
6
|
-
import { getLogger } from "../util/logger.js";
|
|
7
|
-
import {
|
|
8
|
-
AVATAR_MAX_DECODED_BYTES,
|
|
9
|
-
AVATAR_MIME_ALLOWLIST,
|
|
10
|
-
AVATAR_PROMPT_MAX_LENGTH,
|
|
11
|
-
ManagedAvatarError,
|
|
12
|
-
type ManagedAvatarResponse,
|
|
13
|
-
VERTEX_IMAGE_DEFAULT_MODEL,
|
|
14
|
-
} from "./avatar-types.js";
|
|
15
|
-
|
|
16
|
-
const log = getLogger("managed-avatar-client");
|
|
17
|
-
|
|
18
|
-
export function getAssistantApiKey(): string | undefined {
|
|
19
|
-
return getSecureKey("credential:vellum:assistant_api_key");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function getManagedAvatarBaseUrl(): string {
|
|
23
|
-
const baseUrl = getConfig().platform.baseUrl || getPlatformBaseUrl();
|
|
24
|
-
return baseUrl.replace(/\/+$/, "");
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function isManagedAvailable(): boolean {
|
|
28
|
-
const apiKey = getAssistantApiKey();
|
|
29
|
-
const baseUrl = getManagedAvatarBaseUrl();
|
|
30
|
-
return !!apiKey && apiKey.length > 0 && !!baseUrl && baseUrl.length > 0;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export async function generateManagedAvatar(
|
|
34
|
-
prompt: string,
|
|
35
|
-
options?: { correlationId?: string; idempotencyKey?: string; model?: string },
|
|
36
|
-
): Promise<ManagedAvatarResponse> {
|
|
37
|
-
if (prompt.length > AVATAR_PROMPT_MAX_LENGTH) {
|
|
38
|
-
throw new ManagedAvatarError({
|
|
39
|
-
code: "validation_error",
|
|
40
|
-
subcode: "prompt_too_long",
|
|
41
|
-
detail: `Prompt exceeds maximum length of ${AVATAR_PROMPT_MAX_LENGTH} characters`,
|
|
42
|
-
retryable: false,
|
|
43
|
-
correlationId: options?.correlationId ?? crypto.randomUUID(),
|
|
44
|
-
statusCode: 0,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const apiKey = getAssistantApiKey();
|
|
49
|
-
if (!apiKey) {
|
|
50
|
-
throw new ManagedAvatarError({
|
|
51
|
-
code: "configuration_error",
|
|
52
|
-
subcode: "missing_api_key",
|
|
53
|
-
detail: "Assistant API key is not configured",
|
|
54
|
-
retryable: false,
|
|
55
|
-
correlationId: options?.correlationId ?? crypto.randomUUID(),
|
|
56
|
-
statusCode: 0,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const baseUrl = getManagedAvatarBaseUrl();
|
|
61
|
-
if (!baseUrl) {
|
|
62
|
-
throw new ManagedAvatarError({
|
|
63
|
-
code: "configuration_error",
|
|
64
|
-
subcode: "missing_base_url",
|
|
65
|
-
detail:
|
|
66
|
-
"Platform base URL is not configured. Set platform.baseUrl in config or PLATFORM_BASE_URL environment variable.",
|
|
67
|
-
retryable: false,
|
|
68
|
-
correlationId: options?.correlationId ?? crypto.randomUUID(),
|
|
69
|
-
statusCode: 0,
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const model = options?.model ?? VERTEX_IMAGE_DEFAULT_MODEL;
|
|
74
|
-
const url = `${baseUrl}/v1/runtime-proxy/vertex/v1/models/${model}:predict`;
|
|
75
|
-
const idempotencyKey = options?.idempotencyKey ?? crypto.randomUUID();
|
|
76
|
-
const correlationId = options?.correlationId ?? crypto.randomUUID();
|
|
77
|
-
|
|
78
|
-
const headers: Record<string, string> = {
|
|
79
|
-
Authorization: `Api-Key ${apiKey}`,
|
|
80
|
-
"Content-Type": "application/json",
|
|
81
|
-
"Idempotency-Key": idempotencyKey,
|
|
82
|
-
"X-Correlation-Id": correlationId,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
log.debug(
|
|
86
|
-
{ url, correlationId, model },
|
|
87
|
-
"Requesting managed avatar generation",
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
let response: Response;
|
|
91
|
-
try {
|
|
92
|
-
response = await fetch(url, {
|
|
93
|
-
method: "POST",
|
|
94
|
-
body: JSON.stringify({
|
|
95
|
-
instances: [{ prompt }],
|
|
96
|
-
parameters: {
|
|
97
|
-
sampleCount: 1,
|
|
98
|
-
aspectRatio: "1:1",
|
|
99
|
-
outputOptions: { mimeType: "image/png" },
|
|
100
|
-
},
|
|
101
|
-
}),
|
|
102
|
-
signal: AbortSignal.timeout(60_000),
|
|
103
|
-
headers,
|
|
104
|
-
});
|
|
105
|
-
} catch (err) {
|
|
106
|
-
const isTimeout =
|
|
107
|
-
err instanceof DOMException && err.name === "TimeoutError";
|
|
108
|
-
throw new ManagedAvatarError({
|
|
109
|
-
code: "avatar_generation_failed",
|
|
110
|
-
subcode: isTimeout ? "upstream_timeout" : "network_error",
|
|
111
|
-
detail: isTimeout
|
|
112
|
-
? "Request to avatar generation service timed out"
|
|
113
|
-
: `Network error: ${err instanceof Error ? err.message : String(err)}`,
|
|
114
|
-
retryable: true,
|
|
115
|
-
correlationId,
|
|
116
|
-
statusCode: 0,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!response.ok) {
|
|
121
|
-
let detail = `HTTP ${response.status}`;
|
|
122
|
-
try {
|
|
123
|
-
const text = await response.text();
|
|
124
|
-
if (text) detail = `HTTP ${response.status}: ${text}`;
|
|
125
|
-
} catch {
|
|
126
|
-
// ignore parse failures
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
throw new ManagedAvatarError({
|
|
130
|
-
code: "upstream_error",
|
|
131
|
-
subcode: "http_error",
|
|
132
|
-
detail,
|
|
133
|
-
retryable: response.status >= 500 || response.status === 429,
|
|
134
|
-
correlationId,
|
|
135
|
-
statusCode: response.status,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
const vertexBody = (await response.json()) as {
|
|
141
|
-
predictions: Array<{ bytesBase64Encoded: string; mimeType: string }>;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const prediction = vertexBody.predictions?.[0];
|
|
145
|
-
if (!prediction) {
|
|
146
|
-
throw new ManagedAvatarError({
|
|
147
|
-
code: "upstream_error",
|
|
148
|
-
subcode: "empty_predictions",
|
|
149
|
-
detail: "Vertex response contained no predictions",
|
|
150
|
-
retryable: false,
|
|
151
|
-
correlationId,
|
|
152
|
-
statusCode: 0,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const mimeType = prediction.mimeType;
|
|
157
|
-
const dataBase64 = prediction.bytesBase64Encoded;
|
|
158
|
-
|
|
159
|
-
if (!AVATAR_MIME_ALLOWLIST.has(mimeType)) {
|
|
160
|
-
throw new ManagedAvatarError({
|
|
161
|
-
code: "validation_error",
|
|
162
|
-
subcode: "disallowed_mime_type",
|
|
163
|
-
detail: `Response MIME type "${mimeType}" is not in the allowlist`,
|
|
164
|
-
retryable: false,
|
|
165
|
-
correlationId,
|
|
166
|
-
statusCode: 0,
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const padding = dataBase64.endsWith("==")
|
|
171
|
-
? 2
|
|
172
|
-
: dataBase64.endsWith("=")
|
|
173
|
-
? 1
|
|
174
|
-
: 0;
|
|
175
|
-
const estimatedDecodedBytes =
|
|
176
|
-
Math.ceil((dataBase64.length * 3) / 4) - padding;
|
|
177
|
-
if (estimatedDecodedBytes > AVATAR_MAX_DECODED_BYTES) {
|
|
178
|
-
throw new ManagedAvatarError({
|
|
179
|
-
code: "validation_error",
|
|
180
|
-
subcode: "oversized_image",
|
|
181
|
-
detail: `Response image size ${estimatedDecodedBytes} exceeds maximum of ${AVATAR_MAX_DECODED_BYTES} bytes`,
|
|
182
|
-
retryable: false,
|
|
183
|
-
correlationId,
|
|
184
|
-
statusCode: 0,
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const sha256 = createHash("sha256")
|
|
189
|
-
.update(Buffer.from(dataBase64, "base64"))
|
|
190
|
-
.digest("hex");
|
|
191
|
-
|
|
192
|
-
const body: ManagedAvatarResponse = {
|
|
193
|
-
image: {
|
|
194
|
-
mime_type: mimeType,
|
|
195
|
-
data_base64: dataBase64,
|
|
196
|
-
bytes: estimatedDecodedBytes,
|
|
197
|
-
sha256,
|
|
198
|
-
},
|
|
199
|
-
correlation_id: correlationId,
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
log.debug(
|
|
203
|
-
{
|
|
204
|
-
correlationId,
|
|
205
|
-
mimeType: body.image.mime_type,
|
|
206
|
-
bytes: body.image.bytes,
|
|
207
|
-
},
|
|
208
|
-
"Managed avatar generation succeeded",
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
return body;
|
|
212
|
-
} catch (err) {
|
|
213
|
-
if (err instanceof ManagedAvatarError) {
|
|
214
|
-
throw err;
|
|
215
|
-
}
|
|
216
|
-
throw new ManagedAvatarError({
|
|
217
|
-
code: "upstream_error",
|
|
218
|
-
subcode: "unparseable_response",
|
|
219
|
-
detail: `Failed to parse avatar generation response: ${err instanceof Error ? err.message : String(err)}`,
|
|
220
|
-
retryable: false,
|
|
221
|
-
correlationId,
|
|
222
|
-
statusCode: 0,
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|