@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,33 +1,42 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Avatar generation router.
|
|
3
|
-
* Tries managed platform path if available, falls back to local Gemini.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
import { getConfig } from "../config/loader.js";
|
|
2
|
+
import {
|
|
3
|
+
buildManagedBaseUrl,
|
|
4
|
+
resolveManagedProxyContext,
|
|
5
|
+
} from "../providers/managed-proxy/context.js";
|
|
7
6
|
import { ConfigError, ProviderError } from "../util/errors.js";
|
|
8
|
-
import { getLogger } from "../util/logger.js";
|
|
9
|
-
import type { AvatarGenerationResult } from "./avatar-types.js";
|
|
10
|
-
import { generateImage } from "./gemini-image-service.js";
|
|
11
7
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
} from "./
|
|
8
|
+
generateImage,
|
|
9
|
+
type ImageGenCredentials,
|
|
10
|
+
} from "./gemini-image-service.js";
|
|
15
11
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
async function generateLocal(
|
|
12
|
+
export async function generateAvatar(
|
|
19
13
|
prompt: string,
|
|
20
|
-
|
|
21
|
-
): Promise<AvatarGenerationResult> {
|
|
14
|
+
): Promise<{ imageBase64: string; mimeType: string }> {
|
|
22
15
|
const config = getConfig();
|
|
23
16
|
const geminiKey = config.apiKeys.gemini ?? process.env.GEMINI_API_KEY;
|
|
24
|
-
|
|
17
|
+
|
|
18
|
+
let credentials: ImageGenCredentials | undefined;
|
|
19
|
+
if (geminiKey) {
|
|
20
|
+
credentials = { type: "direct", apiKey: geminiKey };
|
|
21
|
+
} else {
|
|
22
|
+
const managedBaseUrl = buildManagedBaseUrl("vertex");
|
|
23
|
+
if (managedBaseUrl) {
|
|
24
|
+
const ctx = resolveManagedProxyContext();
|
|
25
|
+
credentials = {
|
|
26
|
+
type: "managed-proxy",
|
|
27
|
+
assistantApiKey: ctx.assistantApiKey,
|
|
28
|
+
baseUrl: managedBaseUrl,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!credentials) {
|
|
25
34
|
throw new ConfigError(
|
|
26
35
|
"Gemini API key is not configured. Set it via `config set apiKeys.gemini <key>` or the GEMINI_API_KEY environment variable.",
|
|
27
36
|
);
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
const result = await generateImage(
|
|
39
|
+
const result = await generateImage(credentials, {
|
|
31
40
|
prompt,
|
|
32
41
|
mode: "generate",
|
|
33
42
|
model: config.imageGenModel,
|
|
@@ -36,7 +45,7 @@ async function generateLocal(
|
|
|
36
45
|
const image = result.images[0];
|
|
37
46
|
if (!image) {
|
|
38
47
|
throw new ProviderError(
|
|
39
|
-
"
|
|
48
|
+
"Gemini image generation returned no images.",
|
|
40
49
|
"gemini",
|
|
41
50
|
);
|
|
42
51
|
}
|
|
@@ -44,48 +53,5 @@ async function generateLocal(
|
|
|
44
53
|
return {
|
|
45
54
|
imageBase64: image.dataBase64,
|
|
46
55
|
mimeType: image.mimeType,
|
|
47
|
-
pathUsed: "local",
|
|
48
|
-
correlationId,
|
|
49
56
|
};
|
|
50
57
|
}
|
|
51
|
-
|
|
52
|
-
export async function routedGenerateAvatar(
|
|
53
|
-
prompt: string,
|
|
54
|
-
options?: { correlationId?: string; model?: string },
|
|
55
|
-
): Promise<AvatarGenerationResult> {
|
|
56
|
-
const correlationId = options?.correlationId;
|
|
57
|
-
const model = options?.model;
|
|
58
|
-
|
|
59
|
-
// Try managed platform path if available, fall back to local Gemini
|
|
60
|
-
if (isManagedAvailable()) {
|
|
61
|
-
try {
|
|
62
|
-
const managed = await generateManagedAvatar(prompt, {
|
|
63
|
-
correlationId,
|
|
64
|
-
model,
|
|
65
|
-
});
|
|
66
|
-
return {
|
|
67
|
-
imageBase64: managed.image.data_base64,
|
|
68
|
-
mimeType: managed.image.mime_type,
|
|
69
|
-
pathUsed: "managed",
|
|
70
|
-
correlationId: managed.correlation_id,
|
|
71
|
-
model,
|
|
72
|
-
};
|
|
73
|
-
} catch (err) {
|
|
74
|
-
const config = getConfig();
|
|
75
|
-
const geminiKey = config.apiKeys.gemini ?? process.env.GEMINI_API_KEY;
|
|
76
|
-
if (!geminiKey) {
|
|
77
|
-
log.warn(
|
|
78
|
-
{ err: err instanceof Error ? err.message : String(err) },
|
|
79
|
-
"Managed avatar generation failed and no local Gemini key configured; re-throwing",
|
|
80
|
-
);
|
|
81
|
-
throw err;
|
|
82
|
-
}
|
|
83
|
-
log.warn(
|
|
84
|
-
{ err: err instanceof Error ? err.message : String(err) },
|
|
85
|
-
"Managed avatar generation failed, falling back to local Gemini",
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return generateLocal(prompt, correlationId);
|
|
91
|
-
}
|
|
@@ -13,6 +13,21 @@ export interface ImageGenerationRequest {
|
|
|
13
13
|
variants?: number;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
/** Credentials for direct Gemini API access. */
|
|
17
|
+
export interface DirectCredentials {
|
|
18
|
+
type: "direct";
|
|
19
|
+
apiKey: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Credentials for managed proxy access via Vertex AI. */
|
|
23
|
+
export interface ManagedProxyCredentials {
|
|
24
|
+
type: "managed-proxy";
|
|
25
|
+
assistantApiKey: string;
|
|
26
|
+
baseUrl: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ImageGenCredentials = DirectCredentials | ManagedProxyCredentials;
|
|
30
|
+
|
|
16
31
|
export interface GeneratedImage {
|
|
17
32
|
mimeType: string;
|
|
18
33
|
dataBase64: string;
|
|
@@ -64,7 +79,7 @@ export function mapGeminiError(error: unknown): string {
|
|
|
64
79
|
// --- Core function ---
|
|
65
80
|
|
|
66
81
|
export async function generateImage(
|
|
67
|
-
|
|
82
|
+
credentials: ImageGenCredentials,
|
|
68
83
|
request: ImageGenerationRequest,
|
|
69
84
|
): Promise<ImageGenerationResult> {
|
|
70
85
|
const model =
|
|
@@ -74,7 +89,18 @@ export async function generateImage(
|
|
|
74
89
|
|
|
75
90
|
const variants = Math.max(1, Math.min(request.variants ?? 1, MAX_VARIANTS));
|
|
76
91
|
|
|
77
|
-
const client =
|
|
92
|
+
const client =
|
|
93
|
+
credentials.type === "managed-proxy"
|
|
94
|
+
? new GoogleGenAI({
|
|
95
|
+
vertexai: true,
|
|
96
|
+
project: "proxy",
|
|
97
|
+
location: "us-central1",
|
|
98
|
+
httpOptions: {
|
|
99
|
+
baseUrl: credentials.baseUrl,
|
|
100
|
+
headers: { Authorization: `Bearer ${credentials.assistantApiKey}` },
|
|
101
|
+
},
|
|
102
|
+
})
|
|
103
|
+
: new GoogleGenAI({ apiKey: credentials.apiKey });
|
|
78
104
|
|
|
79
105
|
// Build contents array — append a title request so the model's text
|
|
80
106
|
// response contains a short filename-safe title for the generated image.
|
|
@@ -551,7 +551,7 @@ export function listPendingCanonicalGuardianRequestsByDestinationConversation(
|
|
|
551
551
|
* This bridges inbound guardian replies (which arrive on a specific chat)
|
|
552
552
|
* back to their canonical request records. Unlike the conversation-based
|
|
553
553
|
* variant, this uses the chat-level addressing that channel transports
|
|
554
|
-
* (Telegram
|
|
554
|
+
* (Telegram) natively provide — critical for voice-originated
|
|
555
555
|
* `pending_question` requests that lack `guardianExternalUserId`.
|
|
556
556
|
*/
|
|
557
557
|
export function listPendingCanonicalGuardianRequestsByDestinationChat(
|
|
@@ -44,7 +44,7 @@ export type FollowupState =
|
|
|
44
44
|
| "completed"
|
|
45
45
|
| "declined"
|
|
46
46
|
| "failed";
|
|
47
|
-
export type FollowupAction = "call_back" | "
|
|
47
|
+
export type FollowupAction = "call_back" | "decline";
|
|
48
48
|
|
|
49
49
|
export interface GuardianActionRequest {
|
|
50
50
|
id: string;
|
|
@@ -27,7 +27,7 @@ export const guardianActionRequests = sqliteTable(
|
|
|
27
27
|
followupState: text("followup_state").notNull().default("none"), // none | awaiting_guardian_choice | dispatching | completed | declined | failed
|
|
28
28
|
lateAnswerText: text("late_answer_text"),
|
|
29
29
|
lateAnsweredAt: integer("late_answered_at"),
|
|
30
|
-
followupAction: text("followup_action"), // call_back |
|
|
30
|
+
followupAction: text("followup_action"), // call_back | decline
|
|
31
31
|
followupCompletedAt: integer("followup_completed_at"),
|
|
32
32
|
toolName: text("tool_name"), // tool identity for tool-approval requests
|
|
33
33
|
inputDigest: text("input_digest"), // canonical SHA-256 digest of tool input
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* implementing one adapter file + an OAuth setup skill.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { OAuthConnection } from "../oauth/connection.js";
|
|
8
9
|
import type {
|
|
9
10
|
ArchiveResult,
|
|
10
11
|
ConnectionInfo,
|
|
@@ -29,23 +30,25 @@ export interface MessagingProvider {
|
|
|
29
30
|
|
|
30
31
|
// ── Universal operations (every platform must implement) ──────────
|
|
31
32
|
|
|
32
|
-
testConnection(
|
|
33
|
+
testConnection(
|
|
34
|
+
connectionOrToken: OAuthConnection | string,
|
|
35
|
+
): Promise<ConnectionInfo>;
|
|
33
36
|
listConversations(
|
|
34
|
-
|
|
37
|
+
connectionOrToken: OAuthConnection | string,
|
|
35
38
|
options?: ListOptions,
|
|
36
39
|
): Promise<Conversation[]>;
|
|
37
40
|
getHistory(
|
|
38
|
-
|
|
41
|
+
connectionOrToken: OAuthConnection | string,
|
|
39
42
|
conversationId: string,
|
|
40
43
|
options?: HistoryOptions,
|
|
41
44
|
): Promise<Message[]>;
|
|
42
45
|
search(
|
|
43
|
-
|
|
46
|
+
connectionOrToken: OAuthConnection | string,
|
|
44
47
|
query: string,
|
|
45
48
|
options?: SearchOptions,
|
|
46
49
|
): Promise<SearchResult>;
|
|
47
50
|
sendMessage(
|
|
48
|
-
|
|
51
|
+
connectionOrToken: OAuthConnection | string,
|
|
49
52
|
conversationId: string,
|
|
50
53
|
text: string,
|
|
51
54
|
options?: SendOptions,
|
|
@@ -54,30 +57,33 @@ export interface MessagingProvider {
|
|
|
54
57
|
// ── Optional operations (platforms implement what they support) ───
|
|
55
58
|
|
|
56
59
|
getThreadReplies?(
|
|
57
|
-
|
|
60
|
+
connectionOrToken: OAuthConnection | string,
|
|
58
61
|
conversationId: string,
|
|
59
62
|
threadId: string,
|
|
60
63
|
options?: HistoryOptions,
|
|
61
64
|
): Promise<Message[]>;
|
|
62
65
|
markRead?(
|
|
63
|
-
|
|
66
|
+
connectionOrToken: OAuthConnection | string,
|
|
64
67
|
conversationId: string,
|
|
65
68
|
messageId?: string,
|
|
66
69
|
): Promise<void>;
|
|
67
70
|
|
|
68
71
|
/** Scan messages and group by sender for bulk cleanup (e.g. newsletter decluttering). */
|
|
69
72
|
senderDigest?(
|
|
70
|
-
|
|
73
|
+
connectionOrToken: OAuthConnection | string,
|
|
71
74
|
query: string,
|
|
72
75
|
options?: { maxMessages?: number; maxSenders?: number; pageToken?: string },
|
|
73
76
|
): Promise<SenderDigestResult>;
|
|
74
77
|
/** Archive messages matching a search query. */
|
|
75
|
-
archiveByQuery?(
|
|
78
|
+
archiveByQuery?(
|
|
79
|
+
connectionOrToken: OAuthConnection | string,
|
|
80
|
+
query: string,
|
|
81
|
+
): Promise<ArchiveResult>;
|
|
76
82
|
|
|
77
83
|
/**
|
|
78
84
|
* Override the default credential check used by getConnectedProviders().
|
|
79
85
|
* When present, the registry calls this instead of looking for
|
|
80
|
-
* credential
|
|
86
|
+
* credential/{credentialService}/access_token. Useful for providers
|
|
81
87
|
* that don't use OAuth (e.g. Telegram bot tokens stored under a
|
|
82
88
|
* non-standard key).
|
|
83
89
|
*/
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* and implements the MessagingProvider interface.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { OAuthConnection } from "../../../oauth/connection.js";
|
|
8
9
|
import type { MessagingProvider } from "../../provider.js";
|
|
9
10
|
import type {
|
|
10
11
|
ArchiveResult,
|
|
@@ -94,8 +95,11 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
94
95
|
"unsubscribe",
|
|
95
96
|
]),
|
|
96
97
|
|
|
97
|
-
async testConnection(
|
|
98
|
-
|
|
98
|
+
async testConnection(
|
|
99
|
+
connectionOrToken: OAuthConnection | string,
|
|
100
|
+
): Promise<ConnectionInfo> {
|
|
101
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
102
|
+
const profile = await gmail.getProfile(connection);
|
|
99
103
|
return {
|
|
100
104
|
connected: true,
|
|
101
105
|
user: profile.emailAddress,
|
|
@@ -108,11 +112,12 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
108
112
|
},
|
|
109
113
|
|
|
110
114
|
async listConversations(
|
|
111
|
-
|
|
115
|
+
connectionOrToken: OAuthConnection | string,
|
|
112
116
|
_options?: ListOptions,
|
|
113
117
|
): Promise<Conversation[]> {
|
|
118
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
114
119
|
// Gmail "conversations" are modeled as labels with unread counts
|
|
115
|
-
const labels = await gmail.listLabels(
|
|
120
|
+
const labels = await gmail.listLabels(connection);
|
|
116
121
|
const conversations: Conversation[] = [];
|
|
117
122
|
|
|
118
123
|
for (const label of labels) {
|
|
@@ -151,14 +156,15 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
151
156
|
},
|
|
152
157
|
|
|
153
158
|
async getHistory(
|
|
154
|
-
|
|
159
|
+
connectionOrToken: OAuthConnection | string,
|
|
155
160
|
conversationId: string,
|
|
156
161
|
options?: HistoryOptions,
|
|
157
162
|
): Promise<Message[]> {
|
|
163
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
158
164
|
// conversationId is a label ID — list messages in that label
|
|
159
165
|
const limit = options?.limit ?? 50;
|
|
160
166
|
const listResult = await gmail.listMessages(
|
|
161
|
-
|
|
167
|
+
connection,
|
|
162
168
|
undefined,
|
|
163
169
|
limit,
|
|
164
170
|
undefined,
|
|
@@ -168,7 +174,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
168
174
|
if (!listResult.messages?.length) return [];
|
|
169
175
|
|
|
170
176
|
const messages = await gmail.batchGetMessages(
|
|
171
|
-
|
|
177
|
+
connection,
|
|
172
178
|
listResult.messages.map((m) => m.id),
|
|
173
179
|
"full",
|
|
174
180
|
);
|
|
@@ -177,19 +183,20 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
177
183
|
},
|
|
178
184
|
|
|
179
185
|
async search(
|
|
180
|
-
|
|
186
|
+
connectionOrToken: OAuthConnection | string,
|
|
181
187
|
query: string,
|
|
182
188
|
options?: SearchOptions,
|
|
183
189
|
): Promise<SearchResult> {
|
|
190
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
184
191
|
const count = options?.count ?? 20;
|
|
185
|
-
const listResult = await gmail.listMessages(
|
|
192
|
+
const listResult = await gmail.listMessages(connection, query, count);
|
|
186
193
|
|
|
187
194
|
if (!listResult.messages?.length) {
|
|
188
195
|
return { total: 0, messages: [], hasMore: false };
|
|
189
196
|
}
|
|
190
197
|
|
|
191
198
|
const messages = await gmail.batchGetMessages(
|
|
192
|
-
|
|
199
|
+
connection,
|
|
193
200
|
listResult.messages.map((m) => m.id),
|
|
194
201
|
"full",
|
|
195
202
|
);
|
|
@@ -203,16 +210,17 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
203
210
|
},
|
|
204
211
|
|
|
205
212
|
async sendMessage(
|
|
206
|
-
|
|
213
|
+
connectionOrToken: OAuthConnection | string,
|
|
207
214
|
conversationId: string,
|
|
208
215
|
text: string,
|
|
209
216
|
options?: SendOptions,
|
|
210
217
|
): Promise<SendResult> {
|
|
218
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
211
219
|
// conversationId is the recipient email for Gmail
|
|
212
220
|
const to = conversationId;
|
|
213
221
|
const subject = options?.subject ?? "";
|
|
214
222
|
const msg = await gmail.sendMessage(
|
|
215
|
-
|
|
223
|
+
connection,
|
|
216
224
|
to,
|
|
217
225
|
subject,
|
|
218
226
|
text,
|
|
@@ -228,15 +236,16 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
228
236
|
},
|
|
229
237
|
|
|
230
238
|
async getThreadReplies(
|
|
231
|
-
|
|
239
|
+
connectionOrToken: OAuthConnection | string,
|
|
232
240
|
_conversationId: string,
|
|
233
241
|
threadId: string,
|
|
234
242
|
options?: HistoryOptions,
|
|
235
243
|
): Promise<Message[]> {
|
|
244
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
236
245
|
// Get all messages in a Gmail thread
|
|
237
246
|
const limit = options?.limit ?? 50;
|
|
238
247
|
const listResult = await gmail.listMessages(
|
|
239
|
-
|
|
248
|
+
connection,
|
|
240
249
|
`thread:${threadId}`,
|
|
241
250
|
limit,
|
|
242
251
|
);
|
|
@@ -244,7 +253,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
244
253
|
if (!listResult.messages?.length) return [];
|
|
245
254
|
|
|
246
255
|
const messages = await gmail.batchGetMessages(
|
|
247
|
-
|
|
256
|
+
connection,
|
|
248
257
|
listResult.messages.map((m) => m.id),
|
|
249
258
|
"full",
|
|
250
259
|
);
|
|
@@ -253,19 +262,23 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
253
262
|
},
|
|
254
263
|
|
|
255
264
|
async markRead(
|
|
256
|
-
|
|
265
|
+
connectionOrToken: OAuthConnection | string,
|
|
257
266
|
_conversationId: string,
|
|
258
267
|
messageId?: string,
|
|
259
268
|
): Promise<void> {
|
|
269
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
260
270
|
if (!messageId) return;
|
|
261
|
-
await gmail.modifyMessage(
|
|
271
|
+
await gmail.modifyMessage(connection, messageId, {
|
|
272
|
+
removeLabelIds: ["UNREAD"],
|
|
273
|
+
});
|
|
262
274
|
},
|
|
263
275
|
|
|
264
276
|
async senderDigest(
|
|
265
|
-
|
|
277
|
+
connectionOrToken: OAuthConnection | string,
|
|
266
278
|
query: string,
|
|
267
279
|
options?: { maxMessages?: number; maxSenders?: number; pageToken?: string },
|
|
268
280
|
): Promise<SenderDigestResult> {
|
|
281
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
269
282
|
const maxMessages = Math.min(options?.maxMessages ?? 5000, 5000);
|
|
270
283
|
const maxSenders = options?.maxSenders ?? 30;
|
|
271
284
|
const maxIdsPerSender = 5000;
|
|
@@ -285,7 +298,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
285
298
|
}
|
|
286
299
|
const pageSize = Math.min(100, maxMessages - allMessageIds.length);
|
|
287
300
|
const listResp = await gmail.listMessages(
|
|
288
|
-
|
|
301
|
+
connection,
|
|
289
302
|
query,
|
|
290
303
|
pageSize,
|
|
291
304
|
pageToken,
|
|
@@ -295,7 +308,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
295
308
|
allMessageIds.push(...ids);
|
|
296
309
|
fetchPromises.push(
|
|
297
310
|
gmail.batchGetMessages(
|
|
298
|
-
|
|
311
|
+
connection,
|
|
299
312
|
ids,
|
|
300
313
|
"metadata",
|
|
301
314
|
metadataHeaders,
|
|
@@ -409,7 +422,11 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
409
422
|
};
|
|
410
423
|
},
|
|
411
424
|
|
|
412
|
-
async archiveByQuery(
|
|
425
|
+
async archiveByQuery(
|
|
426
|
+
connectionOrToken: OAuthConnection | string,
|
|
427
|
+
query: string,
|
|
428
|
+
): Promise<ArchiveResult> {
|
|
429
|
+
const connection = connectionOrToken as OAuthConnection;
|
|
413
430
|
const maxMessages = 5000;
|
|
414
431
|
const batchModifyLimit = 1000;
|
|
415
432
|
|
|
@@ -419,7 +436,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
419
436
|
|
|
420
437
|
while (allMessageIds.length < maxMessages) {
|
|
421
438
|
const listResp = await gmail.listMessages(
|
|
422
|
-
|
|
439
|
+
connection,
|
|
423
440
|
query,
|
|
424
441
|
Math.min(500, maxMessages - allMessageIds.length),
|
|
425
442
|
pageToken,
|
|
@@ -441,7 +458,7 @@ export const gmailMessagingProvider: MessagingProvider = {
|
|
|
441
458
|
|
|
442
459
|
for (let i = 0; i < allMessageIds.length; i += batchModifyLimit) {
|
|
443
460
|
const chunk = allMessageIds.slice(i, i + batchModifyLimit);
|
|
444
|
-
await gmail.batchModifyMessages(
|
|
461
|
+
await gmail.batchModifyMessages(connection, chunk, {
|
|
445
462
|
removeLabelIds: ["INBOX"],
|
|
446
463
|
});
|
|
447
464
|
}
|