@vellumai/assistant 0.4.49 → 0.4.51
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 +24 -33
- package/README.md +3 -3
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/keychain-broker.md +6 -6
- package/docs/architecture/memory.md +180 -119
- package/knip.json +32 -0
- package/package.json +3 -2
- package/src/__tests__/agent-loop.test.ts +3 -1
- package/src/__tests__/anthropic-provider.test.ts +114 -23
- package/src/__tests__/approval-cascade.test.ts +1 -15
- package/src/__tests__/approval-routes-http.test.ts +2 -0
- package/src/__tests__/assistant-feature-flag-guard.test.ts +0 -23
- package/src/__tests__/btw-routes.test.ts +61 -5
- package/src/__tests__/canonical-guardian-store.test.ts +95 -0
- package/src/__tests__/checker.test.ts +13 -0
- package/src/__tests__/config-schema.test.ts +1 -68
- package/src/__tests__/config-watcher.test.ts +8 -0
- package/src/__tests__/context-memory-e2e.test.ts +11 -100
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +8 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/credential-security-e2e.test.ts +1 -0
- package/src/__tests__/credential-security-invariants.test.ts +8 -7
- package/src/__tests__/credential-vault-unit.test.ts +23 -18
- package/src/__tests__/credential-vault.test.ts +30 -18
- package/src/__tests__/credentials-cli.test.ts +257 -82
- package/src/__tests__/cu-unified-flow.test.ts +532 -0
- package/src/__tests__/date-context.test.ts +93 -77
- package/src/__tests__/deterministic-verification-control-plane.test.ts +64 -0
- package/src/__tests__/guardian-routing-invariants.test.ts +93 -0
- package/src/__tests__/history-repair.test.ts +245 -0
- package/src/__tests__/host-cu-proxy.test.ts +165 -3
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/inbound-invite-redemption.test.ts +36 -7
- package/src/__tests__/integration-status.test.ts +31 -30
- package/src/__tests__/invite-redemption-service.test.ts +166 -13
- package/src/__tests__/invite-routes-http.test.ts +166 -5
- package/src/__tests__/keychain-broker-client.test.ts +4 -4
- package/src/__tests__/list-messages-attachments.test.ts +193 -0
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +56 -18
- package/src/__tests__/memory-lifecycle-e2e.test.ts +244 -387
- package/src/__tests__/memory-recall-quality.test.ts +244 -407
- package/src/__tests__/memory-regressions.experimental.test.ts +126 -101
- package/src/__tests__/memory-regressions.test.ts +477 -2841
- package/src/__tests__/memory-retrieval.benchmark.test.ts +33 -150
- package/src/__tests__/memory-upsert-concurrency.test.ts +5 -244
- package/src/__tests__/mime-builder.test.ts +28 -0
- package/src/__tests__/native-web-search.test.ts +1 -0
- package/src/__tests__/oauth-cli.test.ts +824 -31
- package/src/__tests__/oauth-provider-profiles.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +363 -17
- package/src/__tests__/qdrant-collection-migration.test.ts +53 -8
- package/src/__tests__/registry.test.ts +0 -1
- package/src/__tests__/relay-server.test.ts +55 -1
- package/src/__tests__/schedule-tools.test.ts +32 -0
- package/src/__tests__/script-proxy-certs.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +183 -0
- package/src/__tests__/secure-keys.test.ts +78 -18
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/session-abort-tool-results.test.ts +1 -14
- package/src/__tests__/session-agent-loop-overflow.test.ts +1583 -0
- package/src/__tests__/session-agent-loop.test.ts +19 -15
- package/src/__tests__/session-confirmation-signals.test.ts +1 -15
- package/src/__tests__/session-error.test.ts +124 -2
- package/src/__tests__/session-history-web-search.test.ts +918 -0
- package/src/__tests__/session-pre-run-repair.test.ts +1 -14
- package/src/__tests__/session-provider-retry-repair.test.ts +25 -28
- package/src/__tests__/session-queue.test.ts +37 -27
- package/src/__tests__/session-runtime-assembly.test.ts +54 -0
- package/src/__tests__/session-slash-known.test.ts +1 -15
- package/src/__tests__/session-slash-queue.test.ts +1 -15
- package/src/__tests__/session-slash-unknown.test.ts +1 -15
- package/src/__tests__/session-workspace-cache-state.test.ts +3 -33
- package/src/__tests__/session-workspace-injection.test.ts +3 -37
- package/src/__tests__/session-workspace-tool-tracking.test.ts +3 -37
- package/src/__tests__/skills-install-extract.test.ts +93 -0
- package/src/__tests__/skills.test.ts +2 -2
- package/src/__tests__/skillssh-registry.test.ts +451 -0
- package/src/__tests__/slack-channel-config.test.ts +10 -8
- package/src/__tests__/trust-store.test.ts +15 -0
- package/src/__tests__/twilio-config.test.ts +11 -10
- package/src/__tests__/twilio-provider.test.ts +9 -4
- package/src/__tests__/voice-invite-redemption.test.ts +85 -5
- package/src/agent/ax-tree-compaction.test.ts +51 -0
- package/src/agent/loop.ts +39 -12
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-request-resolvers.ts +14 -2
- package/src/bundler/compiler-tools.ts +66 -2
- package/src/calls/call-domain.ts +134 -3
- package/src/calls/call-store.ts +6 -0
- package/src/calls/relay-server.ts +44 -6
- package/src/calls/relay-setup-router.ts +17 -1
- package/src/calls/twilio-config.ts +5 -4
- package/src/calls/twilio-provider.ts +14 -9
- package/src/calls/twilio-rest.ts +10 -7
- package/src/calls/types.ts +3 -1
- package/src/cli/commands/config.ts +14 -9
- package/src/cli/commands/contacts.ts +3 -0
- package/src/cli/commands/credentials.ts +170 -174
- package/src/cli/commands/doctor.ts +11 -8
- package/src/cli/commands/keys.ts +9 -9
- package/src/cli/commands/mcp.ts +46 -59
- package/src/cli/commands/memory.ts +16 -165
- package/src/cli/commands/oauth/apps.ts +68 -10
- package/src/cli/commands/oauth/connections.ts +475 -105
- package/src/cli/commands/oauth/index.ts +3 -3
- package/src/cli/commands/oauth/providers.ts +18 -4
- package/src/cli/commands/sessions.ts +5 -2
- package/src/cli/commands/skills.ts +173 -1
- package/src/cli/http-client.ts +0 -20
- package/src/cli/main-screen.tsx +2 -2
- package/src/cli/program.ts +5 -6
- package/src/cli.ts +20 -22
- package/src/config/__tests__/feature-flag-registry-bundled.test.ts +39 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +1 -1
- package/src/config/bundled-skills/computer-use/tools/computer-use-observe.ts +12 -0
- package/src/config/bundled-skills/contacts/SKILL.md +35 -11
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +1 -1
- package/src/config/bundled-skills/gmail/SKILL.md +1 -1
- package/src/config/bundled-skills/gmail/TOOLS.json +52 -0
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +13 -3
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +9 -2
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +9 -2
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +5 -1
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +5 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +20 -0
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +2 -1
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +8 -2
- package/src/config/bundled-skills/messaging/SKILL.md +1 -1
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-sender-digest.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +7 -5
- package/src/config/bundled-skills/slack/tools/shared.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-add-reaction.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-channel-details.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-delete-message.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-edit-message.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-leave-channel.ts +1 -1
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +1 -1
- package/src/config/bundled-tool-registry.ts +2 -5
- package/src/config/loader.ts +6 -42
- package/src/config/schema.ts +1 -12
- package/src/config/schemas/memory-lifecycle.ts +0 -9
- package/src/config/schemas/memory-processing.ts +0 -180
- package/src/config/schemas/memory-retrieval.ts +32 -104
- package/src/config/schemas/memory.ts +0 -10
- package/src/config/types.ts +0 -4
- package/src/contacts/contact-store.ts +39 -2
- package/src/contacts/contacts-write.ts +9 -0
- package/src/context/window-manager.ts +4 -1
- package/src/daemon/config-watcher.ts +55 -2
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +114 -31
- package/src/daemon/handlers/config-ingress.ts +2 -2
- package/src/daemon/handlers/config-slack-channel.ts +59 -39
- package/src/daemon/handlers/config-telegram.ts +23 -14
- package/src/daemon/handlers/session-history.ts +1 -358
- package/src/daemon/handlers/sessions.ts +18 -13
- package/src/daemon/handlers/shared.ts +3 -17
- package/src/daemon/handlers/skills.ts +20 -1
- package/src/daemon/history-repair.ts +72 -8
- package/src/daemon/host-cu-proxy.ts +55 -26
- package/src/daemon/lifecycle.ts +39 -4
- package/src/daemon/mcp-reload-service.ts +2 -2
- package/src/daemon/message-types/computer-use.ts +1 -12
- package/src/daemon/message-types/memory.ts +4 -16
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/sessions.ts +4 -42
- package/src/daemon/server.ts +6 -1
- package/src/daemon/session-agent-loop-handlers.ts +38 -0
- package/src/daemon/session-agent-loop.ts +334 -48
- package/src/daemon/session-error.ts +89 -6
- package/src/daemon/session-history.ts +17 -7
- package/src/daemon/session-media-retry.ts +6 -2
- package/src/daemon/session-memory.ts +69 -149
- package/src/daemon/session-process.ts +10 -1
- package/src/daemon/session-runtime-assembly.ts +49 -19
- package/src/daemon/session-slash.ts +3 -5
- package/src/daemon/session-surfaces.ts +4 -1
- package/src/daemon/session-tool-setup.ts +7 -1
- package/src/daemon/session.ts +12 -2
- package/src/email/providers/index.ts +2 -2
- package/src/instrument.ts +61 -1
- package/src/media/avatar-router.ts +1 -1
- package/src/memory/admin.ts +2 -191
- package/src/memory/canonical-guardian-store.ts +38 -2
- package/src/memory/conversation-crud.ts +0 -33
- package/src/memory/conversation-queries.ts +25 -83
- package/src/memory/db-init.ts +32 -0
- package/src/memory/embedding-backend.ts +84 -8
- package/src/memory/embedding-types.ts +9 -1
- package/src/memory/indexer.ts +7 -46
- package/src/memory/invite-store.ts +19 -0
- package/src/memory/items-extractor.ts +274 -76
- package/src/memory/job-handlers/backfill.ts +2 -127
- package/src/memory/job-handlers/cleanup.ts +2 -16
- package/src/memory/job-handlers/extraction.ts +2 -138
- package/src/memory/job-handlers/index-maintenance.ts +1 -6
- package/src/memory/job-handlers/summarization.ts +3 -148
- package/src/memory/job-utils.ts +21 -59
- package/src/memory/jobs-store.ts +1 -159
- package/src/memory/jobs-worker.ts +9 -52
- package/src/memory/migrations/104-core-indexes.ts +3 -3
- package/src/memory/migrations/149-oauth-tables.ts +2 -0
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +98 -0
- package/src/memory/migrations/151-oauth-providers-ping-url.ts +11 -0
- package/src/memory/migrations/152-memory-item-supersession.ts +44 -0
- package/src/memory/migrations/153-drop-entity-tables.ts +15 -0
- package/src/memory/migrations/154-drop-fts.ts +20 -0
- package/src/memory/migrations/155-drop-conflicts.ts +7 -0
- package/src/memory/migrations/156-call-session-invite-metadata.ts +24 -0
- package/src/memory/migrations/157-invite-contact-id.ts +104 -0
- package/src/memory/migrations/index.ts +8 -0
- package/src/memory/migrations/registry.ts +6 -0
- package/src/memory/qdrant-client.ts +148 -51
- package/src/memory/raw-query.ts +1 -1
- package/src/memory/retriever.test.ts +294 -273
- package/src/memory/retriever.ts +421 -645
- package/src/memory/schema/calls.ts +2 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/memory-core.ts +3 -48
- package/src/memory/schema/oauth.ts +2 -0
- package/src/memory/search/formatting.ts +263 -176
- package/src/memory/search/lexical.ts +1 -254
- package/src/memory/search/ranking.ts +0 -455
- package/src/memory/search/semantic.ts +100 -14
- package/src/memory/search/staleness.ts +47 -0
- package/src/memory/search/tier-classifier.ts +21 -0
- package/src/memory/search/types.ts +15 -77
- package/src/memory/task-memory-cleanup.ts +4 -6
- package/src/messaging/provider.ts +1 -1
- package/src/messaging/providers/gmail/adapter.ts +1 -1
- package/src/messaging/providers/gmail/mime-builder.ts +17 -7
- package/src/messaging/providers/telegram-bot/adapter.ts +17 -8
- package/src/messaging/providers/whatsapp/adapter.ts +13 -9
- package/src/messaging/registry.ts +9 -5
- package/src/oauth/byo-connection.test.ts +40 -25
- package/src/oauth/connect-orchestrator.ts +4 -10
- package/src/oauth/connection-resolver.ts +20 -6
- package/src/oauth/manual-token-connection.ts +5 -5
- package/src/oauth/oauth-store.ts +183 -31
- package/src/oauth/platform-connection.test.ts +1 -1
- package/src/oauth/provider-behaviors.ts +503 -4
- package/src/oauth/seed-providers.ts +214 -8
- package/src/oauth/token-persistence.ts +31 -16
- package/src/permissions/defaults.ts +1 -0
- package/src/permissions/trust-store.ts +23 -1
- package/src/playbooks/playbook-compiler.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -2
- package/src/providers/anthropic/client.ts +56 -126
- package/src/providers/types.ts +7 -1
- package/src/runtime/AGENTS.md +9 -0
- package/src/runtime/auth/route-policy.ts +6 -3
- package/src/runtime/channel-readiness-service.ts +48 -40
- package/src/runtime/guardian-reply-router.ts +24 -22
- package/src/runtime/http-server.ts +2 -2
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/invite-redemption-service.ts +72 -12
- package/src/runtime/invite-service.ts +43 -0
- package/src/runtime/middleware/twilio-validation.ts +1 -1
- package/src/runtime/pending-interactions.ts +2 -2
- package/src/runtime/routes/brain-graph-routes.ts +10 -90
- package/src/runtime/routes/btw-routes.ts +10 -5
- package/src/runtime/routes/conversation-routes.ts +56 -11
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +21 -12
- package/src/runtime/routes/integrations/slack/channel.ts +2 -2
- package/src/runtime/routes/integrations/telegram.ts +2 -2
- package/src/runtime/routes/integrations/twilio.ts +17 -17
- package/src/runtime/routes/invite-routes.ts +29 -4
- package/src/runtime/routes/memory-item-routes.test.ts +754 -0
- package/src/runtime/routes/memory-item-routes.ts +503 -0
- package/src/runtime/routes/secret-routes.ts +17 -0
- package/src/runtime/routes/session-management-routes.ts +3 -3
- package/src/runtime/routes/settings-routes.ts +3 -3
- package/src/runtime/routes/trust-rules-routes.ts +14 -0
- package/src/runtime/routes/workspace-routes.ts +9 -4
- package/src/runtime/routes/workspace-utils.ts +8 -2
- package/src/schedule/integration-status.ts +26 -19
- package/src/security/keychain-broker-client.ts +17 -4
- package/src/security/oauth2.ts +6 -7
- package/src/security/secure-keys.ts +44 -19
- package/src/security/token-manager.ts +46 -39
- package/src/services/vercel-deploy.ts +0 -24
- package/src/signals/confirm.ts +78 -0
- package/src/signals/mcp-reload.ts +18 -0
- package/src/skills/catalog-install.ts +74 -18
- package/src/skills/skillssh-registry.ts +503 -0
- package/src/tools/assets/search.ts +5 -1
- package/src/tools/computer-use/definitions.ts +0 -10
- package/src/tools/computer-use/registry.ts +1 -1
- package/src/tools/credentials/vault.ts +22 -7
- package/src/tools/memory/definitions.ts +4 -13
- package/src/tools/memory/handlers.test.ts +83 -103
- package/src/tools/memory/handlers.ts +50 -85
- package/src/tools/network/script-proxy/session-manager.ts +8 -8
- package/src/tools/schedule/create.ts +10 -3
- package/src/tools/schedule/update.ts +8 -1
- package/src/tools/skills/load.ts +25 -2
- package/src/watcher/provider-types.ts +1 -1
- package/src/watcher/providers/github.ts +1 -1
- package/src/watcher/providers/gmail.ts +3 -3
- package/src/watcher/providers/google-calendar.ts +3 -3
- package/src/watcher/providers/linear.ts +1 -1
- package/src/__tests__/clarification-resolver.test.ts +0 -193
- package/src/__tests__/conflict-intent-tokenization.test.ts +0 -160
- package/src/__tests__/conflict-policy.test.ts +0 -269
- package/src/__tests__/conflict-store.test.ts +0 -372
- package/src/__tests__/contradiction-checker.test.ts +0 -361
- package/src/__tests__/entity-extractor.test.ts +0 -211
- package/src/__tests__/entity-search.test.ts +0 -1117
- package/src/__tests__/profile-compiler.test.ts +0 -392
- package/src/__tests__/session-conflict-gate.test.ts +0 -1228
- package/src/__tests__/session-profile-injection.test.ts +0 -557
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +0 -25
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +0 -66
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +0 -211
- package/src/daemon/session-conflict-gate.ts +0 -167
- package/src/daemon/session-dynamic-profile.ts +0 -77
- package/src/memory/clarification-resolver.ts +0 -417
- package/src/memory/conflict-intent.ts +0 -205
- package/src/memory/conflict-policy.ts +0 -127
- package/src/memory/conflict-store.ts +0 -410
- package/src/memory/contradiction-checker.ts +0 -508
- package/src/memory/entity-extractor.ts +0 -535
- package/src/memory/format-recall.ts +0 -47
- package/src/memory/fts-reconciler.ts +0 -165
- package/src/memory/job-handlers/conflict.ts +0 -200
- package/src/memory/profile-compiler.ts +0 -195
- package/src/memory/recall-cache.ts +0 -117
- package/src/memory/search/entity.ts +0 -535
- package/src/memory/search/query-expansion.test.ts +0 -70
- package/src/memory/search/query-expansion.ts +0 -118
- package/src/runtime/routes/mcp-routes.ts +0 -20
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { credentialKey } from "../../security/credential-key.js";
|
|
10
10
|
import {
|
|
11
11
|
deleteSecureKeyAsync,
|
|
12
|
-
|
|
12
|
+
getSecureKeyAsync,
|
|
13
13
|
setSecureKeyAsync,
|
|
14
14
|
} from "../../security/secure-keys.js";
|
|
15
15
|
import {
|
|
@@ -28,21 +28,6 @@ import { shouldOutputJson, writeOutput } from "../output.js";
|
|
|
28
28
|
// Shared helpers
|
|
29
29
|
// ---------------------------------------------------------------------------
|
|
30
30
|
|
|
31
|
-
/**
|
|
32
|
-
* Parse a `service:field` name string. Returns the parsed pair or undefined
|
|
33
|
-
* if the format is invalid (no colon or empty segments).
|
|
34
|
-
*/
|
|
35
|
-
function parseCredentialName(
|
|
36
|
-
name: string,
|
|
37
|
-
): { service: string; field: string } | undefined {
|
|
38
|
-
const colonIndex = name.indexOf(":");
|
|
39
|
-
if (colonIndex <= 0 || colonIndex >= name.length - 1) return undefined;
|
|
40
|
-
return {
|
|
41
|
-
service: name.slice(0, colonIndex),
|
|
42
|
-
field: name.slice(colonIndex + 1),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
31
|
/**
|
|
47
32
|
* Scrub a secret value for display. Shows `****` + last 4 characters for
|
|
48
33
|
* secrets longer than 4 chars, `****` for secrets 4 chars or fewer, and
|
|
@@ -177,15 +162,15 @@ export function registerCredentialsCommand(program: Command): void {
|
|
|
177
162
|
credential.addHelpText(
|
|
178
163
|
"after",
|
|
179
164
|
`
|
|
180
|
-
Credentials are identified by
|
|
165
|
+
Credentials are identified by --service and --field flags, matching the
|
|
181
166
|
storage convention used internally (credential/{service}/{field}):
|
|
182
167
|
|
|
183
|
-
twilio
|
|
184
|
-
twilio
|
|
185
|
-
telegram
|
|
186
|
-
slack_channel
|
|
187
|
-
github
|
|
188
|
-
agentmail
|
|
168
|
+
--service twilio --field account_sid Twilio account SID
|
|
169
|
+
--service twilio --field auth_token Twilio auth token
|
|
170
|
+
--service telegram --field bot_token Telegram bot token
|
|
171
|
+
--service slack_channel --field bot_token Slack channel bot token
|
|
172
|
+
--service github --field token GitHub personal access token
|
|
173
|
+
--service agentmail --field api_key AgentMail API key
|
|
189
174
|
|
|
190
175
|
Secrets are stored in AES-256-GCM encrypted storage. Metadata (policy,
|
|
191
176
|
timestamps, labels) is tracked separately and never contains secret values.
|
|
@@ -193,9 +178,9 @@ timestamps, labels) is tracked separately and never contains secret values.
|
|
|
193
178
|
Examples:
|
|
194
179
|
$ assistant credentials list
|
|
195
180
|
$ assistant credentials list --search twilio
|
|
196
|
-
$ assistant credentials set twilio
|
|
197
|
-
$ assistant credentials inspect twilio
|
|
198
|
-
$ assistant credentials delete twilio
|
|
181
|
+
$ assistant credentials set --service twilio --field account_sid AC1234567890
|
|
182
|
+
$ assistant credentials inspect --service twilio --field account_sid
|
|
183
|
+
$ assistant credentials delete --service twilio --field auth_token`,
|
|
199
184
|
);
|
|
200
185
|
|
|
201
186
|
// -------------------------------------------------------------------------
|
|
@@ -228,7 +213,7 @@ Examples:
|
|
|
228
213
|
$ assistant credentials list --search bot_token
|
|
229
214
|
$ assistant credentials list --json`,
|
|
230
215
|
)
|
|
231
|
-
.action((opts: { search?: string }, cmd: Command) => {
|
|
216
|
+
.action(async (opts: { search?: string }, cmd: Command) => {
|
|
232
217
|
try {
|
|
233
218
|
let allMetadata = listCredentialMetadata();
|
|
234
219
|
|
|
@@ -262,11 +247,15 @@ Examples:
|
|
|
262
247
|
}
|
|
263
248
|
}
|
|
264
249
|
|
|
265
|
-
const credentials =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
250
|
+
const credentials = await Promise.all(
|
|
251
|
+
allMetadata.map(async (m) => {
|
|
252
|
+
const secret = await getSecureKeyAsync(
|
|
253
|
+
credentialKey(m.service, m.field),
|
|
254
|
+
);
|
|
255
|
+
const connection = connectionsByProvider.get(m.service);
|
|
256
|
+
return buildCredentialOutput(m, secret, connection);
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
270
259
|
|
|
271
260
|
writeOutput(cmd, { ok: true, credentials });
|
|
272
261
|
|
|
@@ -293,8 +282,13 @@ Examples:
|
|
|
293
282
|
// -------------------------------------------------------------------------
|
|
294
283
|
|
|
295
284
|
credential
|
|
296
|
-
.command("set <
|
|
285
|
+
.command("set <value>")
|
|
297
286
|
.description("Store a secret and create or update its metadata")
|
|
287
|
+
.requiredOption(
|
|
288
|
+
"--service <service>",
|
|
289
|
+
"Service namespace (e.g. integration:google)",
|
|
290
|
+
)
|
|
291
|
+
.requiredOption("--field <field>", "Field name (e.g. client_secret)")
|
|
298
292
|
.option("--label <label>", 'Human-friendly label (e.g. "prod", "work")')
|
|
299
293
|
.option("--description <description>", "What this credential is used for")
|
|
300
294
|
.option(
|
|
@@ -305,22 +299,22 @@ Examples:
|
|
|
305
299
|
"after",
|
|
306
300
|
`
|
|
307
301
|
Arguments:
|
|
308
|
-
name Credential name in service:field format (e.g. twilio:account_sid)
|
|
309
302
|
value The secret value to store
|
|
310
303
|
|
|
311
304
|
If the credential already exists, the secret is overwritten and metadata is
|
|
312
305
|
updated with any provided flags. Omitted flags leave existing metadata intact.
|
|
313
306
|
|
|
314
307
|
Examples:
|
|
315
|
-
$ assistant credentials set twilio
|
|
316
|
-
$ assistant credentials set fal
|
|
317
|
-
$ assistant credentials set github
|
|
308
|
+
$ assistant credentials set --service twilio --field account_sid AC1234567890
|
|
309
|
+
$ assistant credentials set --service fal --field api_key key_live_abc --label "fal-prod" --description "Image generation"
|
|
310
|
+
$ assistant credentials set --service github --field token ghp_abc --allowed-tools "bash,host_bash"`,
|
|
318
311
|
)
|
|
319
312
|
.action(
|
|
320
313
|
async (
|
|
321
|
-
name: string,
|
|
322
314
|
value: string,
|
|
323
315
|
opts: {
|
|
316
|
+
service: string;
|
|
317
|
+
field: string;
|
|
324
318
|
label?: string;
|
|
325
319
|
description?: string;
|
|
326
320
|
allowedTools?: string;
|
|
@@ -328,17 +322,7 @@ Examples:
|
|
|
328
322
|
cmd: Command,
|
|
329
323
|
) => {
|
|
330
324
|
try {
|
|
331
|
-
const
|
|
332
|
-
if (!parsed) {
|
|
333
|
-
writeOutput(cmd, {
|
|
334
|
-
ok: false,
|
|
335
|
-
error: `Invalid credential name "${name}". Expected service:field format (e.g. twilio:account_sid)`,
|
|
336
|
-
});
|
|
337
|
-
process.exitCode = 1;
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
const { service, field } = parsed;
|
|
325
|
+
const { service, field } = opts;
|
|
342
326
|
const storageKey = credentialKey(service, field);
|
|
343
327
|
|
|
344
328
|
assertMetadataWritable();
|
|
@@ -347,7 +331,7 @@ Examples:
|
|
|
347
331
|
if (!stored) {
|
|
348
332
|
writeOutput(cmd, {
|
|
349
333
|
ok: false,
|
|
350
|
-
error: `Failed to store secret for ${
|
|
334
|
+
error: `Failed to store secret for ${service}:${field}`,
|
|
351
335
|
});
|
|
352
336
|
process.exitCode = 1;
|
|
353
337
|
return;
|
|
@@ -388,34 +372,23 @@ Examples:
|
|
|
388
372
|
// -------------------------------------------------------------------------
|
|
389
373
|
|
|
390
374
|
credential
|
|
391
|
-
.command("delete
|
|
375
|
+
.command("delete")
|
|
392
376
|
.description("Remove a secret and its metadata from the vault")
|
|
377
|
+
.requiredOption("--service <service>", "Service namespace")
|
|
378
|
+
.requiredOption("--field <field>", "Field name")
|
|
393
379
|
.addHelpText(
|
|
394
380
|
"after",
|
|
395
381
|
`
|
|
396
|
-
Arguments:
|
|
397
|
-
name Credential name in service:field format (e.g. twilio:account_sid)
|
|
398
|
-
|
|
399
382
|
Deletes both the encrypted secret and all associated metadata (policy,
|
|
400
383
|
timestamps, injection templates). This action cannot be undone.
|
|
401
384
|
|
|
402
385
|
Examples:
|
|
403
|
-
$ assistant credentials delete twilio
|
|
404
|
-
$ assistant credentials delete github
|
|
386
|
+
$ assistant credentials delete --service twilio --field auth_token
|
|
387
|
+
$ assistant credentials delete --service github --field token`,
|
|
405
388
|
)
|
|
406
|
-
.action(async (
|
|
389
|
+
.action(async (opts: { service: string; field: string }, cmd: Command) => {
|
|
407
390
|
try {
|
|
408
|
-
const
|
|
409
|
-
if (!parsed) {
|
|
410
|
-
writeOutput(cmd, {
|
|
411
|
-
ok: false,
|
|
412
|
-
error: `Invalid credential name "${name}". Expected service:field format (e.g. twilio:account_sid)`,
|
|
413
|
-
});
|
|
414
|
-
process.exitCode = 1;
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const { service, field } = parsed;
|
|
391
|
+
const { service, field } = opts;
|
|
419
392
|
const storageKey = credentialKey(service, field);
|
|
420
393
|
|
|
421
394
|
assertMetadataWritable();
|
|
@@ -477,13 +450,15 @@ Examples:
|
|
|
477
450
|
// -------------------------------------------------------------------------
|
|
478
451
|
|
|
479
452
|
credential
|
|
480
|
-
.command("inspect
|
|
453
|
+
.command("inspect [id]")
|
|
481
454
|
.description("Show metadata and a masked preview of a stored credential")
|
|
455
|
+
.option("--service <service>", "Service namespace")
|
|
456
|
+
.option("--field <field>", "Field name")
|
|
482
457
|
.addHelpText(
|
|
483
458
|
"after",
|
|
484
459
|
`
|
|
485
460
|
Arguments:
|
|
486
|
-
|
|
461
|
+
id (optional) Credential UUID for lookup by ID
|
|
487
462
|
|
|
488
463
|
Shows everything known about a credential without revealing the secret value.
|
|
489
464
|
The secret is masked to show only the last 4 characters (e.g. ****c123).
|
|
@@ -491,160 +466,181 @@ The secret is masked to show only the last 4 characters (e.g. ****c123).
|
|
|
491
466
|
Displayed fields include: label, creation/update timestamps, allowed tools,
|
|
492
467
|
allowed domains, OAuth2 scopes, account info, and injection template count.
|
|
493
468
|
|
|
469
|
+
Use --service and --field to look up by service/field, or pass a UUID as a
|
|
470
|
+
positional argument. One of the two forms is required.
|
|
471
|
+
|
|
494
472
|
Examples:
|
|
495
|
-
$ assistant credentials inspect twilio
|
|
473
|
+
$ assistant credentials inspect --service twilio --field account_sid
|
|
496
474
|
$ assistant credentials inspect 7a3b1c2d-4e5f-6789-abcd-ef0123456789
|
|
497
|
-
$ assistant credentials inspect --json slack_channel
|
|
475
|
+
$ assistant credentials inspect --json --service slack_channel --field bot_token`,
|
|
498
476
|
)
|
|
499
|
-
.action(
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
477
|
+
.action(
|
|
478
|
+
async (
|
|
479
|
+
id: string | undefined,
|
|
480
|
+
opts: { service?: string; field?: string },
|
|
481
|
+
cmd: Command,
|
|
482
|
+
) => {
|
|
483
|
+
try {
|
|
484
|
+
let metadata: CredentialMetadata | undefined;
|
|
485
|
+
let storageKey: string;
|
|
486
|
+
let service: string | undefined;
|
|
487
|
+
let field: string | undefined;
|
|
488
|
+
|
|
489
|
+
if (opts.service && opts.field) {
|
|
490
|
+
service = opts.service;
|
|
491
|
+
field = opts.field;
|
|
492
|
+
metadata = getCredentialMetadata(service, field);
|
|
493
|
+
storageKey = credentialKey(service, field);
|
|
494
|
+
} else if (id) {
|
|
495
|
+
metadata = getCredentialMetadataById(id);
|
|
496
|
+
if (metadata) {
|
|
497
|
+
storageKey = credentialKey(metadata.service, metadata.field);
|
|
498
|
+
service = metadata.service;
|
|
499
|
+
field = metadata.field;
|
|
500
|
+
} else {
|
|
501
|
+
// No metadata found by UUID, and we can't determine the storage key
|
|
502
|
+
writeOutput(cmd, { ok: false, error: "Credential not found" });
|
|
503
|
+
process.exitCode = 1;
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
} else {
|
|
507
507
|
writeOutput(cmd, {
|
|
508
508
|
ok: false,
|
|
509
|
-
error:
|
|
509
|
+
error:
|
|
510
|
+
"Either --service and --field flags or a credential UUID is required",
|
|
510
511
|
});
|
|
511
512
|
process.exitCode = 1;
|
|
512
513
|
return;
|
|
513
514
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
metadata
|
|
518
|
-
if (metadata) {
|
|
519
|
-
storageKey = credentialKey(metadata.service, metadata.field);
|
|
520
|
-
} else {
|
|
521
|
-
// No metadata found by UUID, and we can't determine the storage key
|
|
515
|
+
|
|
516
|
+
const secret = await getSecureKeyAsync(storageKey);
|
|
517
|
+
|
|
518
|
+
if (!metadata && (secret == null || secret.length === 0)) {
|
|
522
519
|
writeOutput(cmd, { ok: false, error: "Credential not found" });
|
|
523
520
|
process.exitCode = 1;
|
|
524
521
|
return;
|
|
525
522
|
}
|
|
526
|
-
}
|
|
527
523
|
|
|
528
|
-
|
|
524
|
+
// If we have a secret but no metadata, we still need metadata for the output.
|
|
525
|
+
// This can happen if someone stored a key directly without going through the
|
|
526
|
+
// credential set command. Build a minimal output in that case.
|
|
527
|
+
if (!metadata) {
|
|
528
|
+
writeOutput(cmd, {
|
|
529
|
+
ok: true,
|
|
530
|
+
service: service,
|
|
531
|
+
field: field,
|
|
532
|
+
credentialId: null,
|
|
533
|
+
scrubbedValue: scrubSecret(secret),
|
|
534
|
+
hasSecret: secret != null && secret.length > 0,
|
|
535
|
+
alias: null,
|
|
536
|
+
usageDescription: null,
|
|
537
|
+
allowedTools: [],
|
|
538
|
+
allowedDomains: [],
|
|
539
|
+
createdAt: null,
|
|
540
|
+
updatedAt: null,
|
|
541
|
+
injectionTemplateCount: 0,
|
|
542
|
+
});
|
|
529
543
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
544
|
+
if (!shouldOutputJson(cmd)) {
|
|
545
|
+
log.info(` ${service}:${field}`);
|
|
546
|
+
log.info(` Value: ${scrubSecret(secret)}`);
|
|
547
|
+
log.info(" (no metadata record)");
|
|
548
|
+
}
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
535
551
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (!metadata) {
|
|
540
|
-
// We only get here for the service:field path where we have storageKey
|
|
541
|
-
// but no metadata record. Output what we can.
|
|
542
|
-
const parsed = parseCredentialName(name)!;
|
|
543
|
-
writeOutput(cmd, {
|
|
544
|
-
ok: true,
|
|
545
|
-
service: parsed.service,
|
|
546
|
-
field: parsed.field,
|
|
547
|
-
credentialId: null,
|
|
548
|
-
scrubbedValue: scrubSecret(secret),
|
|
549
|
-
hasSecret: secret != null && secret.length > 0,
|
|
550
|
-
alias: null,
|
|
551
|
-
usageDescription: null,
|
|
552
|
-
allowedTools: [],
|
|
553
|
-
allowedDomains: [],
|
|
554
|
-
createdAt: null,
|
|
555
|
-
updatedAt: null,
|
|
556
|
-
injectionTemplateCount: 0,
|
|
557
|
-
});
|
|
552
|
+
const connection = safeGetConnectionByProvider(metadata.service);
|
|
553
|
+
const output = buildCredentialOutput(metadata, secret, connection);
|
|
554
|
+
writeOutput(cmd, output);
|
|
558
555
|
|
|
559
556
|
if (!shouldOutputJson(cmd)) {
|
|
560
|
-
|
|
561
|
-
log.info(` Value: ${scrubSecret(secret)}`);
|
|
562
|
-
log.info(" (no metadata record)");
|
|
557
|
+
printCredentialHuman(output);
|
|
563
558
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
const output = buildCredentialOutput(metadata, secret, connection);
|
|
569
|
-
writeOutput(cmd, output);
|
|
570
|
-
|
|
571
|
-
if (!shouldOutputJson(cmd)) {
|
|
572
|
-
printCredentialHuman(output);
|
|
559
|
+
} catch (err) {
|
|
560
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
561
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
562
|
+
process.exitCode = 1;
|
|
573
563
|
}
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
writeOutput(cmd, { ok: false, error: message });
|
|
577
|
-
process.exitCode = 1;
|
|
578
|
-
}
|
|
579
|
-
});
|
|
564
|
+
},
|
|
565
|
+
);
|
|
580
566
|
|
|
581
567
|
// -------------------------------------------------------------------------
|
|
582
568
|
// reveal
|
|
583
569
|
// -------------------------------------------------------------------------
|
|
584
570
|
|
|
585
571
|
credential
|
|
586
|
-
.command("reveal
|
|
572
|
+
.command("reveal [id]")
|
|
587
573
|
.description("Print the plaintext value of a credential")
|
|
574
|
+
.option("--service <service>", "Service namespace")
|
|
575
|
+
.option("--field <field>", "Field name")
|
|
588
576
|
.addHelpText(
|
|
589
577
|
"after",
|
|
590
578
|
`
|
|
591
579
|
Arguments:
|
|
592
|
-
|
|
580
|
+
id (optional) Credential UUID for lookup by ID
|
|
593
581
|
|
|
594
582
|
Prints the raw secret value to stdout for piping into other tools. In JSON
|
|
595
583
|
mode the value is returned as {"ok": true, "value": "..."}. In human mode
|
|
596
584
|
only the bare secret is printed (no labels or decoration) so it can be
|
|
597
|
-
captured with shell substitution
|
|
585
|
+
captured with shell substitution.
|
|
586
|
+
|
|
587
|
+
Use --service and --field to look up by service/field, or pass a UUID as a
|
|
588
|
+
positional argument. One of the two forms is required.
|
|
598
589
|
|
|
599
590
|
Examples:
|
|
600
|
-
$ assistant credentials reveal twilio
|
|
591
|
+
$ assistant credentials reveal --service twilio --field auth_token
|
|
601
592
|
$ assistant credentials reveal 7a3b1c2d-4e5f-6789-abcd-ef0123456789
|
|
602
|
-
$ assistant credentials reveal --json twilio
|
|
603
|
-
$ export TWILIO_TOKEN=$(assistant credentials reveal twilio
|
|
593
|
+
$ assistant credentials reveal --json --service twilio --field account_sid
|
|
594
|
+
$ export TWILIO_TOKEN=$(assistant credentials reveal --service twilio --field auth_token)`,
|
|
604
595
|
)
|
|
605
|
-
.action(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
596
|
+
.action(
|
|
597
|
+
async (
|
|
598
|
+
id: string | undefined,
|
|
599
|
+
opts: { service?: string; field?: string },
|
|
600
|
+
cmd: Command,
|
|
601
|
+
) => {
|
|
602
|
+
try {
|
|
603
|
+
let storageKey: string;
|
|
604
|
+
|
|
605
|
+
if (opts.service && opts.field) {
|
|
606
|
+
storageKey = credentialKey(opts.service, opts.field);
|
|
607
|
+
} else if (id) {
|
|
608
|
+
const metadata = getCredentialMetadataById(id);
|
|
609
|
+
if (metadata) {
|
|
610
|
+
storageKey = credentialKey(metadata.service, metadata.field);
|
|
611
|
+
} else {
|
|
612
|
+
writeOutput(cmd, { ok: false, error: "Credential not found" });
|
|
613
|
+
process.exitCode = 1;
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
} else {
|
|
612
617
|
writeOutput(cmd, {
|
|
613
618
|
ok: false,
|
|
614
|
-
error:
|
|
619
|
+
error:
|
|
620
|
+
"Either --service and --field flags or a credential UUID is required",
|
|
615
621
|
});
|
|
616
622
|
process.exitCode = 1;
|
|
617
623
|
return;
|
|
618
624
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if (
|
|
623
|
-
storageKey = credentialKey(metadata.service, metadata.field);
|
|
624
|
-
} else {
|
|
625
|
+
|
|
626
|
+
const secret = await getSecureKeyAsync(storageKey);
|
|
627
|
+
|
|
628
|
+
if (secret == null || secret.length === 0) {
|
|
625
629
|
writeOutput(cmd, { ok: false, error: "Credential not found" });
|
|
626
630
|
process.exitCode = 1;
|
|
627
631
|
return;
|
|
628
632
|
}
|
|
629
|
-
}
|
|
630
633
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
634
|
+
if (shouldOutputJson(cmd)) {
|
|
635
|
+
writeOutput(cmd, { ok: true, value: secret });
|
|
636
|
+
} else {
|
|
637
|
+
process.stdout.write(secret + "\n");
|
|
638
|
+
}
|
|
639
|
+
} catch (err) {
|
|
640
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
641
|
+
writeOutput(cmd, { ok: false, error: message });
|
|
635
642
|
process.exitCode = 1;
|
|
636
|
-
return;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
if (shouldOutputJson(cmd)) {
|
|
640
|
-
writeOutput(cmd, { ok: true, value: secret });
|
|
641
|
-
} else {
|
|
642
|
-
process.stdout.write(secret + "\n");
|
|
643
643
|
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
writeOutput(cmd, { ok: false, error: message });
|
|
647
|
-
process.exitCode = 1;
|
|
648
|
-
}
|
|
649
|
-
});
|
|
644
|
+
},
|
|
645
|
+
);
|
|
650
646
|
}
|
|
@@ -3,8 +3,11 @@ import { existsSync, readFileSync, statSync } from "node:fs";
|
|
|
3
3
|
|
|
4
4
|
import type { Command } from "commander";
|
|
5
5
|
|
|
6
|
+
import { getRuntimeHttpPort } from "../../config/env.js";
|
|
6
7
|
import { loadRawConfig } from "../../config/loader.js";
|
|
7
8
|
import { shouldAutoStartDaemon } from "../../daemon/connection-policy.js";
|
|
9
|
+
import { isHttpHealthy } from "../../daemon/daemon-control.js";
|
|
10
|
+
import { getSecureKey } from "../../security/secure-keys.js";
|
|
8
11
|
import {
|
|
9
12
|
getDbPath,
|
|
10
13
|
getLogPath,
|
|
@@ -13,7 +16,6 @@ import {
|
|
|
13
16
|
getWorkspaceHooksDir,
|
|
14
17
|
getWorkspaceSkillsDir,
|
|
15
18
|
} from "../../util/platform.js";
|
|
16
|
-
import { getHttpBaseUrl, httpHealthCheck } from "../http-client.js";
|
|
17
19
|
import { log } from "../logger.js";
|
|
18
20
|
|
|
19
21
|
export function registerDoctorCommand(program: Command): void {
|
|
@@ -57,7 +59,7 @@ Examples:
|
|
|
57
59
|
log.info("Vellum Doctor\n");
|
|
58
60
|
|
|
59
61
|
// 0. Connection policy info
|
|
60
|
-
const httpUrl =
|
|
62
|
+
const httpUrl = `http://127.0.0.1:${getRuntimeHttpPort()}`;
|
|
61
63
|
const autostart = shouldAutoStartDaemon();
|
|
62
64
|
log.info(` HTTP: ${httpUrl}`);
|
|
63
65
|
log.info(` Autostart: ${autostart ? "enabled" : "disabled"}\n`);
|
|
@@ -82,28 +84,29 @@ Examples:
|
|
|
82
84
|
fireworks: "FIREWORKS_API_KEY",
|
|
83
85
|
openrouter: "OPENROUTER_API_KEY",
|
|
84
86
|
};
|
|
85
|
-
const configKey = (
|
|
86
|
-
provider
|
|
87
|
-
];
|
|
87
|
+
const configKey = getSecureKey(provider);
|
|
88
88
|
const envVar = providerEnvVar[provider];
|
|
89
89
|
const envKey = envVar ? process.env[envVar] : undefined;
|
|
90
|
+
const plaintextKey = (
|
|
91
|
+
raw.apiKeys as Record<string, string> | undefined
|
|
92
|
+
)?.[provider];
|
|
90
93
|
|
|
91
94
|
if (provider === "ollama") {
|
|
92
95
|
pass("Provider configured (Ollama; API key optional)");
|
|
93
|
-
} else if (envKey || configKey) {
|
|
96
|
+
} else if (envKey || configKey || plaintextKey) {
|
|
94
97
|
pass("API key configured");
|
|
95
98
|
} else {
|
|
96
99
|
fail(
|
|
97
100
|
"API key configured",
|
|
98
101
|
envVar
|
|
99
|
-
? `set ${envVar} or run: assistant
|
|
102
|
+
? `set ${envVar} or run: assistant keys set ${provider} <key>`
|
|
100
103
|
: `set API key for provider "${provider}"`,
|
|
101
104
|
);
|
|
102
105
|
}
|
|
103
106
|
|
|
104
107
|
// 3. Daemon reachable (HTTP health check)
|
|
105
108
|
try {
|
|
106
|
-
const healthy = await
|
|
109
|
+
const healthy = await isHttpHealthy();
|
|
107
110
|
if (healthy) {
|
|
108
111
|
pass("Assistant reachable");
|
|
109
112
|
} else {
|
package/src/cli/commands/keys.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { Command } from "commander";
|
|
|
2
2
|
|
|
3
3
|
import { API_KEY_PROVIDERS } from "../../config/loader.js";
|
|
4
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
deleteSecureKeyAsync,
|
|
6
|
+
getSecureKeyAsync,
|
|
7
|
+
setSecureKeyAsync,
|
|
8
8
|
} from "../../security/secure-keys.js";
|
|
9
9
|
import { log } from "../logger.js";
|
|
10
10
|
|
|
@@ -40,10 +40,10 @@ omitted from the output.
|
|
|
40
40
|
Examples:
|
|
41
41
|
$ assistant keys list`,
|
|
42
42
|
)
|
|
43
|
-
.action(() => {
|
|
43
|
+
.action(async () => {
|
|
44
44
|
const stored: string[] = [];
|
|
45
45
|
for (const provider of API_KEY_PROVIDERS) {
|
|
46
|
-
const value =
|
|
46
|
+
const value = await getSecureKeyAsync(provider);
|
|
47
47
|
if (value) stored.push(provider);
|
|
48
48
|
}
|
|
49
49
|
if (stored.length === 0) {
|
|
@@ -74,8 +74,8 @@ Examples:
|
|
|
74
74
|
$ assistant keys set openai sk-proj-xyz789
|
|
75
75
|
$ assistant keys set fireworks fw-abc123`,
|
|
76
76
|
)
|
|
77
|
-
.action((provider: string, key: string) => {
|
|
78
|
-
if (
|
|
77
|
+
.action(async (provider: string, key: string) => {
|
|
78
|
+
if (await setSecureKeyAsync(provider, key)) {
|
|
79
79
|
log.info(`Stored API key for "${provider}"`);
|
|
80
80
|
} else {
|
|
81
81
|
log.error(`Failed to store API key for "${provider}"`);
|
|
@@ -99,8 +99,8 @@ Examples:
|
|
|
99
99
|
$ assistant keys delete openai
|
|
100
100
|
$ assistant keys delete anthropic`,
|
|
101
101
|
)
|
|
102
|
-
.action((provider: string) => {
|
|
103
|
-
const result =
|
|
102
|
+
.action(async (provider: string) => {
|
|
103
|
+
const result = await deleteSecureKeyAsync(provider);
|
|
104
104
|
if (result === "deleted") {
|
|
105
105
|
log.info(`Deleted API key for "${provider}"`);
|
|
106
106
|
} else if (result === "error") {
|