@vellumai/assistant 0.5.1 → 0.5.2
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 +54 -54
- package/docs/architecture/integrations.md +62 -67
- package/docs/credential-execution-service.md +3 -3
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +111 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
- package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
- package/src/__tests__/app-dir-path-guard.test.ts +78 -0
- package/src/__tests__/app-executors.test.ts +1 -291
- package/src/__tests__/app-git-history.test.ts +4 -4
- package/src/__tests__/app-routes-csp.test.ts +1 -0
- package/src/__tests__/app-store-dir-names.test.ts +426 -0
- package/src/__tests__/attachments-store.test.ts +169 -21
- package/src/__tests__/attachments.test.ts +115 -1
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/canonical-guardian-store.test.ts +38 -0
- package/src/__tests__/channel-reply-delivery.test.ts +55 -0
- package/src/__tests__/checker.test.ts +54 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/config-schema-cmd.test.ts +68 -21
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +149 -5
- package/src/__tests__/conversation-agent-loop.test.ts +290 -2
- package/src/__tests__/conversation-attachments.test.ts +17 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
- package/src/__tests__/conversation-disk-view.test.ts +810 -0
- package/src/__tests__/conversation-error.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +551 -0
- package/src/__tests__/conversation-fork-route.test.ts +386 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
- package/src/__tests__/conversation-media-retry.test.ts +8 -2
- package/src/__tests__/conversation-queue.test.ts +36 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
- package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
- package/src/__tests__/conversation-skill-tools.test.ts +4 -9
- package/src/__tests__/conversation-slash-commands.test.ts +149 -0
- package/src/__tests__/conversation-store.test.ts +24 -21
- package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
- package/src/__tests__/conversation-title-service.test.ts +137 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-vault-unit.test.ts +5 -10
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
- package/src/__tests__/diagnostics-export.test.ts +70 -1
- package/src/__tests__/first-greeting.test.ts +80 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
- package/src/__tests__/history-repair.test.ts +32 -10
- package/src/__tests__/http-conversation-lineage.test.ts +251 -0
- package/src/__tests__/image-source-path-reinject.test.ts +136 -0
- package/src/__tests__/llm-context-normalization.test.ts +1116 -0
- package/src/__tests__/llm-context-route-provider.test.ts +217 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
- package/src/__tests__/media-generate-image.test.ts +47 -94
- package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
- package/src/__tests__/memory-recall-quality.test.ts +5 -5
- package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
- package/src/__tests__/migration-export-http.test.ts +3 -1
- package/src/__tests__/migration-import-commit-http.test.ts +18 -4
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
- package/src/__tests__/mime-builder.test.ts +3 -2
- package/src/__tests__/non-member-access-request.test.ts +12 -1
- package/src/__tests__/notification-decision-identity.test.ts +52 -0
- package/src/__tests__/oauth-apps-routes.test.ts +103 -0
- package/src/__tests__/oauth-store.test.ts +115 -0
- package/src/__tests__/provider-error-scenarios.test.ts +1 -3
- package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
- package/src/__tests__/recording-handler.test.ts +17 -0
- package/src/__tests__/registry.test.ts +3 -8
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
- package/src/__tests__/schema-transforms.test.ts +165 -5
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -2
- package/src/__tests__/starter-task-flow.test.ts +1 -0
- package/src/__tests__/suggestion-routes.test.ts +443 -0
- package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
- package/src/__tests__/swarm-recursion.test.ts +1 -0
- package/src/__tests__/swarm-tool.test.ts +1 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
- package/src/__tests__/top-level-renderer.test.ts +22 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
- package/src/__tests__/web-fetch.test.ts +6 -2
- package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
- package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
- package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
- package/src/agent/attachments.ts +27 -1
- package/src/agent/loop.ts +29 -1
- package/src/avatar/traits-png-sync.ts +80 -25
- package/src/bundler/app-bundler.ts +4 -4
- package/src/calls/call-domain.ts +1 -0
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/commands/auth.ts +92 -0
- package/src/cli/commands/avatar.ts +7 -6
- package/src/cli/commands/config.ts +2 -0
- package/src/cli/commands/oauth/providers.ts +29 -0
- package/src/cli/program.ts +12 -0
- package/src/cli.ts +15 -48
- package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
- package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
- package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
- package/src/config/bundled-tool-registry.ts +2 -14
- package/src/config/feature-flag-registry.json +8 -0
- package/src/config/loader.ts +64 -0
- package/src/config/raw-config-utils.ts +30 -0
- package/src/config/schema-utils.ts +28 -7
- package/src/config/schema.ts +8 -0
- package/src/config/schemas/elevenlabs.ts +18 -0
- package/src/config/schemas/memory-lifecycle.ts +4 -2
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/services.ts +8 -6
- package/src/contacts/contact-store.ts +13 -6
- package/src/contacts/contacts-write.ts +0 -1
- package/src/context/window-manager.ts +13 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +48 -7
- package/src/daemon/conversation-agent-loop.ts +56 -19
- package/src/daemon/conversation-attachments.ts +18 -36
- package/src/daemon/conversation-error.ts +2 -1
- package/src/daemon/conversation-history.ts +18 -4
- package/src/daemon/conversation-lifecycle.ts +39 -15
- package/src/daemon/conversation-messaging.ts +70 -26
- package/src/daemon/conversation-process.ts +58 -34
- package/src/daemon/conversation-runtime-assembly.ts +21 -38
- package/src/daemon/conversation-slash.ts +121 -256
- package/src/daemon/conversation-surfaces.ts +143 -20
- package/src/daemon/conversation-tool-setup.ts +0 -6
- package/src/daemon/conversation-workspace.ts +21 -1
- package/src/daemon/conversation.ts +51 -29
- package/src/daemon/first-greeting.ts +35 -0
- package/src/daemon/handlers/config-embeddings.ts +148 -0
- package/src/daemon/handlers/config-model.ts +71 -26
- package/src/daemon/handlers/conversations.ts +0 -23
- package/src/daemon/handlers/recording.ts +26 -21
- package/src/daemon/host-cu-proxy.ts +2 -2
- package/src/daemon/lifecycle.ts +106 -64
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +19 -0
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/shared.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/upgrades.ts +23 -0
- package/src/daemon/server.ts +83 -12
- package/src/daemon/shutdown-handlers.ts +8 -5
- package/src/daemon/startup-error.ts +9 -0
- package/src/daemon/tool-side-effects.ts +11 -28
- package/src/events/tool-permission-telemetry-listener.ts +1 -3
- package/src/instrument.ts +0 -4
- package/src/media/app-icon-generator.ts +2 -2
- package/src/memory/app-git-service.ts +28 -16
- package/src/memory/app-store.ts +230 -41
- package/src/memory/attachments-store.ts +558 -130
- package/src/memory/conversation-attention-store.ts +70 -0
- package/src/memory/conversation-crud.ts +442 -3
- package/src/memory/conversation-directories.ts +125 -0
- package/src/memory/conversation-disk-view.ts +390 -0
- package/src/memory/conversation-key-store.ts +17 -5
- package/src/memory/conversation-queries.ts +5 -1
- package/src/memory/conversation-title-service.ts +21 -49
- package/src/memory/db-init.ts +28 -0
- package/src/memory/embedding-backend.ts +42 -53
- package/src/memory/embedding-gemini.test.ts +4 -4
- package/src/memory/embedding-local.ts +1 -3
- package/src/memory/embedding-ollama.ts +1 -3
- package/src/memory/embedding-openai.ts +1 -3
- package/src/memory/indexer.ts +9 -7
- package/src/memory/items-extractor.ts +42 -13
- package/src/memory/job-handlers/conversation-starters.ts +6 -1
- package/src/memory/job-handlers/embedding.test.ts +1 -4
- package/src/memory/llm-request-log-store.ts +100 -1
- package/src/memory/migrations/102-alter-table-columns.ts +5 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
- package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
- package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
- package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
- package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
- package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
- package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
- package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
- package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
- package/src/memory/migrations/index.ts +7 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +601 -2
- package/src/memory/retriever.ts +85 -9
- package/src/memory/schema/conversations.ts +6 -0
- package/src/memory/schema/infrastructure.ts +13 -7
- package/src/memory/schema/oauth.ts +6 -0
- package/src/messaging/providers/gmail/mime-builder.ts +3 -1
- package/src/notifications/copy-composer.ts +26 -0
- package/src/notifications/decision-engine.ts +14 -1
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +36 -0
- package/src/oauth/byo-connection.test.ts +1 -45
- package/src/oauth/byo-connection.ts +2 -8
- package/src/oauth/connect-orchestrator.ts +15 -11
- package/src/oauth/connection-resolver.test.ts +191 -0
- package/src/oauth/connection-resolver.ts +66 -38
- package/src/oauth/connection.ts +0 -1
- package/src/oauth/oauth-store.ts +97 -47
- package/src/oauth/platform-connection.test.ts +0 -1
- package/src/oauth/platform-connection.ts +11 -3
- package/src/oauth/seed-providers.ts +78 -3
- package/src/oauth/token-persistence.ts +16 -10
- package/src/permissions/checker.ts +71 -8
- package/src/prompts/templates/BOOTSTRAP.md +2 -0
- package/src/providers/anthropic/client.ts +8 -1
- package/src/providers/failover.ts +4 -1
- package/src/providers/gemini/client.ts +50 -0
- package/src/providers/model-catalog.ts +92 -0
- package/src/providers/model-intents.ts +29 -20
- package/src/providers/openai/client.ts +49 -0
- package/src/providers/types.ts +2 -0
- package/src/runtime/access-request-helper.ts +16 -7
- package/src/runtime/auth/credential-service.ts +3 -1
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/btw-sidechain.ts +101 -0
- package/src/runtime/channel-reply-delivery.ts +17 -1
- package/src/runtime/http-router.ts +3 -1
- package/src/runtime/http-server.ts +196 -141
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/migrations/vbundle-builder.ts +5 -1
- package/src/runtime/routes/access-request-decision.ts +41 -0
- package/src/runtime/routes/app-management-routes.ts +6 -3
- package/src/runtime/routes/app-routes.ts +7 -3
- package/src/runtime/routes/approval-routes.ts +1 -0
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
- package/src/runtime/routes/attachment-routes.ts +45 -15
- package/src/runtime/routes/btw-routes.ts +21 -61
- package/src/runtime/routes/conversation-management-routes.ts +68 -0
- package/src/runtime/routes/conversation-query-routes.ts +180 -10
- package/src/runtime/routes/conversation-routes.ts +222 -28
- package/src/runtime/routes/conversation-starter-routes.ts +9 -11
- package/src/runtime/routes/diagnostics-routes.ts +1 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
- package/src/runtime/routes/llm-context-normalization.ts +1199 -0
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/memory-item-routes.test.ts +34 -0
- package/src/runtime/routes/memory-item-routes.ts +4 -0
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/oauth-apps.ts +291 -0
- package/src/runtime/routes/secret-routes.ts +28 -1
- package/src/runtime/routes/settings-routes.ts +14 -0
- package/src/runtime/routes/trace-event-routes.ts +4 -1
- package/src/schedule/schedule-store.ts +9 -21
- package/src/security/secure-keys.ts +21 -0
- package/src/signals/bash.ts +1 -1
- package/src/swarm/backend-claude-code.ts +3 -6
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +3 -1
- package/src/tools/AGENTS.md +6 -10
- package/src/tools/apps/executors.ts +17 -232
- package/src/tools/claude-code/claude-code.ts +2 -3
- package/src/tools/credentials/vault.ts +7 -12
- package/src/tools/host-filesystem/read.ts +13 -10
- package/src/tools/network/__tests__/web-search.test.ts +4 -2
- package/src/tools/schedule/list.ts +2 -7
- package/src/tools/schema-transforms.ts +5 -0
- package/src/tools/shared/filesystem/format-diff.ts +2 -7
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/tool-manifest.ts +0 -6
- package/src/tools/ui-surface/definitions.ts +2 -2
- package/src/util/device-id.ts +28 -5
- package/src/util/platform.ts +6 -0
- package/src/util/pricing.ts +1 -0
- package/src/util/retry.ts +1 -3
- package/src/workspace/migrations/002-backfill-installation-id.ts +23 -12
- package/src/workspace/migrations/003-seed-device-id.ts +3 -4
- package/src/workspace/migrations/006-services-config.ts +5 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/top-level-renderer.ts +12 -0
- package/src/__tests__/asset-materialize-tool.test.ts +0 -523
- package/src/__tests__/asset-search-tool.test.ts +0 -536
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
- package/src/__tests__/media-visibility-policy.test.ts +0 -190
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
- package/src/daemon/media-visibility-policy.ts +0 -59
- package/src/tools/assets/materialize.ts +0 -248
- package/src/tools/assets/search.ts +0 -400
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getPlatformAssistantId,
|
|
5
|
+
getPlatformBaseUrl,
|
|
6
|
+
getPlatformOrganizationId,
|
|
7
|
+
getPlatformUserId,
|
|
8
|
+
} from "../../config/env.js";
|
|
9
|
+
import { resolveManagedProxyContext } from "../../providers/managed-proxy/context.js";
|
|
10
|
+
import { log } from "../logger.js";
|
|
11
|
+
import { shouldOutputJson, writeOutput } from "../output.js";
|
|
12
|
+
|
|
13
|
+
export function registerAuthCommand(program: Command): void {
|
|
14
|
+
const auth = program
|
|
15
|
+
.command("auth")
|
|
16
|
+
.description("Manage platform authentication and identity")
|
|
17
|
+
.option("--json", "Machine-readable compact JSON output");
|
|
18
|
+
|
|
19
|
+
auth.addHelpText(
|
|
20
|
+
"after",
|
|
21
|
+
`
|
|
22
|
+
The auth namespace manages the assistant's authentication state with the
|
|
23
|
+
Vellum platform. It provides commands to inspect identity and connection
|
|
24
|
+
status, helping diagnose configuration issues.
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
$ assistant auth info
|
|
28
|
+
$ assistant auth info --json`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// info
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
auth
|
|
36
|
+
.command("info")
|
|
37
|
+
.description("Show platform identity and authentication status")
|
|
38
|
+
.addHelpText(
|
|
39
|
+
"after",
|
|
40
|
+
`
|
|
41
|
+
Fields:
|
|
42
|
+
platformUrl The Vellum platform base URL this assistant connects to
|
|
43
|
+
assistantId This assistant's platform UUID (from PLATFORM_ASSISTANT_ID)
|
|
44
|
+
organizationId The organization this assistant belongs to (from PLATFORM_ORGANIZATION_ID)
|
|
45
|
+
userId The user who owns this assistant (from PLATFORM_USER_ID)
|
|
46
|
+
authenticated Whether all prerequisites for platform authentication are met
|
|
47
|
+
(platform URL and assistant API key both present)
|
|
48
|
+
|
|
49
|
+
When not authenticated, a message field provides guidance on next steps.
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
$ assistant auth info
|
|
53
|
+
$ assistant auth info --json`,
|
|
54
|
+
)
|
|
55
|
+
.action(async (_opts: Record<string, unknown>, cmd: Command) => {
|
|
56
|
+
const ctx = await resolveManagedProxyContext();
|
|
57
|
+
|
|
58
|
+
const platformUrl = getPlatformBaseUrl();
|
|
59
|
+
const assistantId = getPlatformAssistantId();
|
|
60
|
+
const organizationId = getPlatformOrganizationId();
|
|
61
|
+
const userId = getPlatformUserId();
|
|
62
|
+
const authenticated = ctx.enabled;
|
|
63
|
+
|
|
64
|
+
const result: Record<string, unknown> = {
|
|
65
|
+
platformUrl: platformUrl || null,
|
|
66
|
+
assistantId: assistantId || null,
|
|
67
|
+
organizationId: organizationId || null,
|
|
68
|
+
userId: userId || null,
|
|
69
|
+
authenticated,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
if (!authenticated) {
|
|
73
|
+
result.message = !platformUrl
|
|
74
|
+
? "Platform URL not configured. Run assistant config set platform.baseUrl <url>"
|
|
75
|
+
: "Assistant API key not found. Store one with: assistant keys set credential/vellum/assistant_api_key <key>";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
writeOutput(cmd, result);
|
|
79
|
+
|
|
80
|
+
if (!shouldOutputJson(cmd)) {
|
|
81
|
+
log.info(`Platform URL: ${platformUrl || "(not set)"}`);
|
|
82
|
+
log.info(`Assistant ID: ${assistantId || "(not set)"}`);
|
|
83
|
+
log.info(`Organization ID: ${organizationId || "(not set)"}`);
|
|
84
|
+
log.info(`User ID: ${userId || "(not set)"}`);
|
|
85
|
+
log.info(`Authenticated: ${authenticated ? "yes" : "no"}`);
|
|
86
|
+
if (!authenticated && result.message) {
|
|
87
|
+
log.info("");
|
|
88
|
+
log.info(result.message as string);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
@@ -38,7 +38,7 @@ The avatar system supports two modes:
|
|
|
38
38
|
Files are stored in ~/.vellum/workspace/data/avatar/:
|
|
39
39
|
character-traits.json Current trait selection (bodyShape, eyeStyle, color)
|
|
40
40
|
avatar-image.png Rendered PNG of the character
|
|
41
|
-
character-ascii.txt ASCII art representation
|
|
41
|
+
character-ascii.txt ASCII art representation (best-effort; may not be written)
|
|
42
42
|
|
|
43
43
|
Examples:
|
|
44
44
|
$ assistant avatar character update --body-shape blob --eye-style curious --color green
|
|
@@ -141,8 +141,8 @@ Examples:
|
|
|
141
141
|
.addHelpText(
|
|
142
142
|
"after",
|
|
143
143
|
`
|
|
144
|
-
Sets the three character traits and regenerates
|
|
145
|
-
|
|
144
|
+
Sets the three character traits and regenerates avatar files (PNG image,
|
|
145
|
+
traits JSON, and optionally ASCII art). Each trait value must be a valid ID from the
|
|
146
146
|
component set — use "assistant avatar character components" to list valid IDs.
|
|
147
147
|
|
|
148
148
|
The --body-shape flag sets the character silhouette. Valid values:
|
|
@@ -154,8 +154,9 @@ The --eye-style flag sets the eye expression. Valid values:
|
|
|
154
154
|
The --color flag sets the body fill color. Valid values:
|
|
155
155
|
green, orange, pink, purple, teal, yellow
|
|
156
156
|
|
|
157
|
-
On success, writes
|
|
158
|
-
|
|
157
|
+
On success, writes character-traits.json and avatar-image.png to
|
|
158
|
+
~/.vellum/workspace/data/avatar/. character-ascii.txt is written on a
|
|
159
|
+
best-effort basis and may be skipped if ASCII rendering fails.
|
|
159
160
|
|
|
160
161
|
Examples:
|
|
161
162
|
$ assistant avatar character update --body-shape blob --eye-style curious --color green
|
|
@@ -323,7 +324,7 @@ Examples:
|
|
|
323
324
|
}
|
|
324
325
|
|
|
325
326
|
const width = parseInt(opts.width, 10);
|
|
326
|
-
if (width < 1) {
|
|
327
|
+
if (!Number.isFinite(width) || width < 1) {
|
|
327
328
|
log.error(
|
|
328
329
|
`Invalid width: "${opts.width}". Must be a positive integer.`,
|
|
329
330
|
);
|
|
@@ -152,6 +152,7 @@ Examples:
|
|
|
152
152
|
if (!path) {
|
|
153
153
|
const jsonSchema = z.toJSONSchema(AssistantConfigSchema, {
|
|
154
154
|
unrepresentable: "any",
|
|
155
|
+
io: "input",
|
|
155
156
|
});
|
|
156
157
|
log.info(JSON.stringify(jsonSchema, null, 2));
|
|
157
158
|
return;
|
|
@@ -165,6 +166,7 @@ Examples:
|
|
|
165
166
|
|
|
166
167
|
const jsonSchema = z.toJSONSchema(subSchema, {
|
|
167
168
|
unrepresentable: "any",
|
|
169
|
+
io: "input",
|
|
168
170
|
});
|
|
169
171
|
log.info(JSON.stringify(jsonSchema, null, 2));
|
|
170
172
|
});
|
|
@@ -51,6 +51,11 @@ function parseProviderRow(row: ReturnType<typeof getProvider>) {
|
|
|
51
51
|
if (!row) return row;
|
|
52
52
|
return {
|
|
53
53
|
...row,
|
|
54
|
+
displayName: row.displayName ?? null,
|
|
55
|
+
description: row.description ?? null,
|
|
56
|
+
dashboardUrl: row.dashboardUrl ?? null,
|
|
57
|
+
clientIdPlaceholder: row.clientIdPlaceholder ?? null,
|
|
58
|
+
requiresClientSecret: row.requiresClientSecret ?? 1,
|
|
54
59
|
defaultScopes: row.defaultScopes ? JSON.parse(row.defaultScopes) : [],
|
|
55
60
|
scopePolicy: row.scopePolicy ? JSON.parse(row.scopePolicy) : {},
|
|
56
61
|
extraParams: row.extraParams ? JSON.parse(row.extraParams) : null,
|
|
@@ -203,6 +208,14 @@ Examples:
|
|
|
203
208
|
"--ping-url <url>",
|
|
204
209
|
"Health-check endpoint URL for token validation",
|
|
205
210
|
)
|
|
211
|
+
.option("--display-name <name>", "Display name for the provider")
|
|
212
|
+
.option("--description <text>", "Short description")
|
|
213
|
+
.option("--dashboard-url <url>", "Developer console URL")
|
|
214
|
+
.option("--client-id-placeholder <text>", "Placeholder for client ID field")
|
|
215
|
+
.option(
|
|
216
|
+
"--no-client-secret",
|
|
217
|
+
"Set requires_client_secret to false (default is true)",
|
|
218
|
+
)
|
|
206
219
|
.addHelpText(
|
|
207
220
|
"after",
|
|
208
221
|
`
|
|
@@ -220,6 +233,12 @@ Arguments (via options):
|
|
|
220
233
|
--ping-url Optional URL for a lightweight health-check endpoint.
|
|
221
234
|
Used by "connections ping" to validate that a stored token
|
|
222
235
|
is still functional (e.g. "https://api.example.com/user").
|
|
236
|
+
--display-name Optional human-readable display name for the provider.
|
|
237
|
+
--description Optional short description of the provider.
|
|
238
|
+
--dashboard-url Optional URL to the provider's developer console / dashboard.
|
|
239
|
+
--client-id-placeholder Optional placeholder text for the client ID input field.
|
|
240
|
+
--no-client-secret If set, marks the provider as not requiring a client secret
|
|
241
|
+
(sets requires_client_secret to 0). Default is true (1).
|
|
223
242
|
|
|
224
243
|
Registers a new OAuth provider configuration in the local store. This is
|
|
225
244
|
used for custom integrations not covered by the built-in provider seeds.
|
|
@@ -253,6 +272,11 @@ Examples:
|
|
|
253
272
|
tokenAuthMethod?: string;
|
|
254
273
|
callbackTransport?: string;
|
|
255
274
|
pingUrl?: string;
|
|
275
|
+
displayName?: string;
|
|
276
|
+
description?: string;
|
|
277
|
+
dashboardUrl?: string;
|
|
278
|
+
clientIdPlaceholder?: string;
|
|
279
|
+
clientSecret: boolean;
|
|
256
280
|
},
|
|
257
281
|
cmd: Command,
|
|
258
282
|
) => {
|
|
@@ -268,6 +292,11 @@ Examples:
|
|
|
268
292
|
tokenEndpointAuthMethod: opts.tokenAuthMethod,
|
|
269
293
|
callbackTransport: opts.callbackTransport,
|
|
270
294
|
pingUrl: opts.pingUrl,
|
|
295
|
+
displayName: opts.displayName,
|
|
296
|
+
description: opts.description,
|
|
297
|
+
dashboardUrl: opts.dashboardUrl,
|
|
298
|
+
clientIdPlaceholder: opts.clientIdPlaceholder,
|
|
299
|
+
requiresClientSecret: opts.clientSecret ? 1 : 0,
|
|
271
300
|
});
|
|
272
301
|
|
|
273
302
|
writeOutput(cmd, parseProviderRow(row));
|
package/src/cli/program.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { isEmailEnabled } from "../email/feature-gate.js";
|
|
|
5
5
|
import { registerHooksCommand } from "../hooks/cli.js";
|
|
6
6
|
import { APP_VERSION } from "../version.js";
|
|
7
7
|
import { registerAuditCommand } from "./commands/audit.js";
|
|
8
|
+
import { registerAuthCommand } from "./commands/auth.js";
|
|
8
9
|
import { registerAutonomyCommand } from "./commands/autonomy.js";
|
|
9
10
|
import { registerAvatarCommand } from "./commands/avatar.js";
|
|
10
11
|
import { registerBashCommand } from "./commands/bash.js";
|
|
@@ -39,6 +40,16 @@ export function buildCliProgram(): Command {
|
|
|
39
40
|
.description("Local AI assistant")
|
|
40
41
|
.version(APP_VERSION);
|
|
41
42
|
|
|
43
|
+
program.addHelpText(
|
|
44
|
+
"after",
|
|
45
|
+
`
|
|
46
|
+
Examples:
|
|
47
|
+
$ assistant auth info Show platform identity and auth status
|
|
48
|
+
$ assistant config list List all configuration values
|
|
49
|
+
$ assistant keys list List stored API keys
|
|
50
|
+
$ assistant doctor Run diagnostic checks`,
|
|
51
|
+
);
|
|
52
|
+
|
|
42
53
|
registerDefaultAction(program);
|
|
43
54
|
registerBashCommand(program);
|
|
44
55
|
registerConversationsCommand(program);
|
|
@@ -49,6 +60,7 @@ export function buildCliProgram(): Command {
|
|
|
49
60
|
registerTrustCommand(program);
|
|
50
61
|
registerMemoryCommand(program);
|
|
51
62
|
registerAuditCommand(program);
|
|
63
|
+
registerAuthCommand(program);
|
|
52
64
|
registerAvatarCommand(program);
|
|
53
65
|
registerDoctorCommand(program);
|
|
54
66
|
registerHooksCommand(program);
|
package/src/cli.ts
CHANGED
|
@@ -17,10 +17,6 @@ import {
|
|
|
17
17
|
updateDaemonText,
|
|
18
18
|
updateStatusText,
|
|
19
19
|
} from "./cli/main-screen.jsx";
|
|
20
|
-
import { loadRawConfig, saveRawConfig } from "./config/loader.js";
|
|
21
|
-
import { setServiceField } from "./config/raw-config-utils.js";
|
|
22
|
-
import { MODEL_TO_PROVIDER } from "./daemon/conversation-slash.js";
|
|
23
|
-
import { getModelInfo } from "./daemon/handlers/config-model.js";
|
|
24
20
|
import { renderHistoryContent } from "./daemon/handlers/shared.js";
|
|
25
21
|
import type {
|
|
26
22
|
ConfirmationRequest,
|
|
@@ -1030,7 +1026,7 @@ export async function startCli(): Promise<void> {
|
|
|
1030
1026
|
return;
|
|
1031
1027
|
}
|
|
1032
1028
|
|
|
1033
|
-
if (content === "/
|
|
1029
|
+
if (content === "/conversations") {
|
|
1034
1030
|
pendingSessionPick = true;
|
|
1035
1031
|
try {
|
|
1036
1032
|
const rows = listConversations(20);
|
|
@@ -1064,7 +1060,7 @@ export async function startCli(): Promise<void> {
|
|
|
1064
1060
|
return;
|
|
1065
1061
|
}
|
|
1066
1062
|
|
|
1067
|
-
if (content === "/copy-
|
|
1063
|
+
if (content === "/copy-conversation") {
|
|
1068
1064
|
try {
|
|
1069
1065
|
const mapping = getConversationByKey(conversationKey);
|
|
1070
1066
|
if (!mapping) {
|
|
@@ -1133,37 +1129,9 @@ export async function startCli(): Promise<void> {
|
|
|
1133
1129
|
}
|
|
1134
1130
|
|
|
1135
1131
|
if (content === "/model" || content.startsWith("/model ")) {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
const raw = loadRawConfig();
|
|
1140
|
-
const provider = MODEL_TO_PROVIDER[modelArg];
|
|
1141
|
-
setServiceField(raw, "inference", "model", modelArg);
|
|
1142
|
-
if (provider) setServiceField(raw, "inference", "provider", provider);
|
|
1143
|
-
saveRawConfig(raw);
|
|
1144
|
-
const existingProvider = (
|
|
1145
|
-
raw.services as Record<string, Record<string, unknown>>
|
|
1146
|
-
)?.inference?.provider as string | undefined;
|
|
1147
|
-
process.stdout.write(
|
|
1148
|
-
`\n Model: ${modelArg} (${provider ?? existingProvider})\n\n`,
|
|
1149
|
-
);
|
|
1150
|
-
} catch {
|
|
1151
|
-
process.stdout.write("[Failed to set model]\n");
|
|
1152
|
-
}
|
|
1153
|
-
} else {
|
|
1154
|
-
getModelInfo()
|
|
1155
|
-
.then((info) => {
|
|
1156
|
-
process.stdout.write(
|
|
1157
|
-
`\n Model: ${info.model} (${info.provider})\n\n`,
|
|
1158
|
-
);
|
|
1159
|
-
prompt();
|
|
1160
|
-
})
|
|
1161
|
-
.catch(() => {
|
|
1162
|
-
process.stdout.write("[Failed to get model info]\n");
|
|
1163
|
-
prompt();
|
|
1164
|
-
});
|
|
1165
|
-
return;
|
|
1166
|
-
}
|
|
1132
|
+
process.stdout.write(
|
|
1133
|
+
"\n The /model command has been removed. Use Settings to change your model and provider.\n\n",
|
|
1134
|
+
);
|
|
1167
1135
|
prompt();
|
|
1168
1136
|
return;
|
|
1169
1137
|
}
|
|
@@ -1295,27 +1263,26 @@ export async function startCli(): Promise<void> {
|
|
|
1295
1263
|
|
|
1296
1264
|
if (content === "/help") {
|
|
1297
1265
|
process.stdout.write("\n Available commands:\n");
|
|
1298
|
-
process.stdout.write(" /new
|
|
1266
|
+
process.stdout.write(" /new Start a new conversation\n");
|
|
1299
1267
|
process.stdout.write(
|
|
1300
|
-
" /conversations
|
|
1268
|
+
" /conversations Switch between conversations\n",
|
|
1301
1269
|
);
|
|
1302
|
-
process.stdout.write(" /clear
|
|
1303
|
-
process.stdout.write(" /
|
|
1304
|
-
process.stdout.write(" /history Show conversation history\n");
|
|
1270
|
+
process.stdout.write(" /clear Clear the screen\n");
|
|
1271
|
+
process.stdout.write(" /history Show conversation history\n");
|
|
1305
1272
|
process.stdout.write(
|
|
1306
|
-
" /undo
|
|
1273
|
+
" /undo Remove last message exchange\n",
|
|
1307
1274
|
);
|
|
1308
|
-
process.stdout.write(" /usage
|
|
1275
|
+
process.stdout.write(" /usage Show token usage and cost\n");
|
|
1309
1276
|
process.stdout.write(
|
|
1310
|
-
" /copy
|
|
1277
|
+
" /copy Copy last response to clipboard\n",
|
|
1311
1278
|
);
|
|
1312
1279
|
process.stdout.write(
|
|
1313
|
-
" /copy-code
|
|
1280
|
+
" /copy-code Copy last code block to clipboard\n",
|
|
1314
1281
|
);
|
|
1315
1282
|
process.stdout.write(
|
|
1316
|
-
" /copy-conversation
|
|
1283
|
+
" /copy-conversation Copy entire conversation to clipboard\n",
|
|
1317
1284
|
);
|
|
1318
|
-
process.stdout.write(" /help
|
|
1285
|
+
process.stdout.write(" /help Show this help\n");
|
|
1319
1286
|
process.stdout.write("\n");
|
|
1320
1287
|
prompt();
|
|
1321
1288
|
return;
|
|
@@ -18,6 +18,40 @@ You are an expert app builder and visual designer. When the user asks you to cre
|
|
|
18
18
|
|
|
19
19
|
**Design quality is delegated to the `frontend-design` skill.** That skill defines your aesthetic principles: typography, color strategy, motion, spatial composition, and visual detail. Follow it completely for every build. This skill (app-builder) handles the technical infrastructure: sandbox constraints, data bridge, widget API, app lifecycle, and interaction patterns.
|
|
20
20
|
|
|
21
|
+
## Filesystem Layout
|
|
22
|
+
|
|
23
|
+
Apps live under `~/.vellum/workspace/data/apps/`. Each app has a slug-based layout:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
~/.vellum/workspace/data/apps/
|
|
27
|
+
<slug>.json # App metadata
|
|
28
|
+
<slug>/ # App directory (contains all app files)
|
|
29
|
+
index.html # Main page (entry point rendered in WebView)
|
|
30
|
+
pages/ # Additional pages
|
|
31
|
+
records/ # Data records (one JSON file per record)
|
|
32
|
+
src/ # Source files (multifile TSX apps, formatVersion: 2)
|
|
33
|
+
dist/ # Compiled output (multifile TSX apps)
|
|
34
|
+
<slug>.preview # Preview image (auto-generated)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Metadata JSON (`<slug>.json`)
|
|
38
|
+
|
|
39
|
+
Fields: `id`, `name`, `description`, `icon`, `schemaJson`, `createdAt`, `updatedAt`, `formatVersion`, `dirName`.
|
|
40
|
+
|
|
41
|
+
**Important:** `htmlDefinition` and `pages` are NOT stored in the metadata JSON — they live as separate files inside the app directory (`index.html` and `pages/`).
|
|
42
|
+
|
|
43
|
+
### Records
|
|
44
|
+
|
|
45
|
+
Each record is a JSON file at `<slug>/records/<uuid>.json` with shape:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{ "id": "<uuid>", "appId": "<app-id>", "data": { ... }, "createdAt": "...", "updatedAt": "..." }
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Multifile TSX Apps
|
|
52
|
+
|
|
53
|
+
For `formatVersion: 2` apps, source files live under `src/` and compiled output under `dist/`. The build system compiles TSX → JS automatically when `app_refresh` is called.
|
|
54
|
+
|
|
21
55
|
## Workflow
|
|
22
56
|
|
|
23
57
|
### 1. Gather Requirements
|
|
@@ -44,7 +78,7 @@ You are an expert app builder and visual designer. When the user asks you to cre
|
|
|
44
78
|
|
|
45
79
|
**Only ask questions when the request is genuinely ambiguous** - e.g., "build me an app" with no indication of what kind. Even then, prefer building something impressive based on context clues over asking a battery of questions.
|
|
46
80
|
|
|
47
|
-
**When in doubt, build something impressive** and let the user refine
|
|
81
|
+
**When in doubt, build something impressive** and let the user refine. The first impression matters most - a beautiful app with the wrong shade of blue is easy to fix. A correct but ugly app is hard to come back from.
|
|
48
82
|
|
|
49
83
|
**There are no "quick" builds.** Every app, regardless of complexity, gets the full design treatment. A 3-field form and a 20-section dashboard get the same design care. The only difference is scope, not quality.
|
|
50
84
|
|
|
@@ -149,27 +183,27 @@ useEffect(() => {
|
|
|
149
183
|
}, []);
|
|
150
184
|
```
|
|
151
185
|
|
|
152
|
-
**File workflow:** Use `
|
|
186
|
+
**File workflow:** Use `file_write` for each source file. After writing all files, call `app_refresh` once to compile and refresh the UI.
|
|
153
187
|
|
|
154
188
|
**Allowed third-party packages:** `date-fns`, `chart.js`, `lodash-es`, `zod`, `clsx`, `lucide`. Import them directly - esbuild resolves them at build time. No CDN imports. Note: `lucide` is the vanilla JS icon library (not `lucide-react`). Use its `createElement` or `createIcons` API, or manually inline SVG - do not import JSX icon components.
|
|
155
189
|
|
|
156
|
-
**Example - creating a multi-file project
|
|
190
|
+
**Example - creating a multi-file project** (assuming app slug is `project-tracker`):
|
|
157
191
|
|
|
158
192
|
```
|
|
159
|
-
|
|
193
|
+
file_write("~/.vellum/workspace/data/apps/project-tracker/src/index.html", `<!DOCTYPE html>
|
|
160
194
|
<html lang="en">
|
|
161
195
|
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
162
196
|
<title>Project Tracker</title></head>
|
|
163
197
|
<body><div id="app"></div></body>
|
|
164
198
|
</html>`)
|
|
165
199
|
|
|
166
|
-
|
|
200
|
+
file_write("~/.vellum/workspace/data/apps/project-tracker/src/main.tsx", `import { render } from 'preact';
|
|
167
201
|
import { App } from './components/App';
|
|
168
202
|
import './styles.css';
|
|
169
203
|
|
|
170
204
|
render(<App />, document.getElementById('app')!);`)
|
|
171
205
|
|
|
172
|
-
|
|
206
|
+
file_write("~/.vellum/workspace/data/apps/project-tracker/src/components/App.tsx", `import { FunctionComponent } from 'preact';
|
|
173
207
|
import { useState, useEffect } from 'preact/hooks';
|
|
174
208
|
import { Header } from './Header';
|
|
175
209
|
|
|
@@ -188,7 +222,7 @@ export const App: FunctionComponent = () => {
|
|
|
188
222
|
);
|
|
189
223
|
};`)
|
|
190
224
|
|
|
191
|
-
|
|
225
|
+
file_write("~/.vellum/workspace/data/apps/project-tracker/src/components/Header.tsx", `import { FunctionComponent } from 'preact';
|
|
192
226
|
|
|
193
227
|
interface HeaderProps {
|
|
194
228
|
title: string;
|
|
@@ -202,9 +236,12 @@ export const Header: FunctionComponent<HeaderProps> = ({ title, count }) => (
|
|
|
202
236
|
</header>
|
|
203
237
|
);`)
|
|
204
238
|
|
|
205
|
-
|
|
239
|
+
file_write("~/.vellum/workspace/data/apps/project-tracker/src/styles.css", `.app { padding: var(--v-spacing-lg); }
|
|
206
240
|
.header { display: flex; justify-content: space-between; align-items: center; }
|
|
207
241
|
.badge { background: var(--v-accent); color: white; padding: var(--v-spacing-xs) var(--v-spacing-sm); border-radius: var(--v-radius-pill); }`)
|
|
242
|
+
|
|
243
|
+
# After all files are written, compile and refresh:
|
|
244
|
+
app_refresh(app_id)
|
|
208
245
|
```
|
|
209
246
|
|
|
210
247
|
**Technical constraints (multi-file):**
|
|
@@ -317,8 +354,6 @@ A CSS/JS widget library is auto-injected alongside the design system. Use these
|
|
|
317
354
|
| `.v-gradient-text` | Accent-colored gradient text |
|
|
318
355
|
| `.v-animate-in` | Staggered fade-in for children |
|
|
319
356
|
|
|
320
|
-
**Slideshow** (`.v-slideshow`): Presentation slide deck with transitions. Init with `vellum.widgets.slideshow()`. Slide helpers: `.v-slide`, `.v-slide-label`, `.v-slide-title`, `.v-slide-body`, `.v-slide-stats`, `.v-slide-stat`, `.v-slide-quote`, `.v-slide-list`, `.v-slide-columns`.
|
|
321
|
-
|
|
322
357
|
#### Widget JavaScript utilities
|
|
323
358
|
|
|
324
359
|
Interactive utilities at `window.vellum.widgets.*`:
|
|
@@ -384,19 +419,11 @@ vellum.widgets.toast("Saved!", "success", 4000); // Auto-dismiss notification
|
|
|
384
419
|
vellum.widgets.countdown("timer-el", "2025-12-31T00:00:00Z", {
|
|
385
420
|
onComplete: () => {},
|
|
386
421
|
});
|
|
387
|
-
vellum.widgets.slideshow("deck", {
|
|
388
|
-
transition: "fade",
|
|
389
|
-
showDots: true,
|
|
390
|
-
showArrows: true,
|
|
391
|
-
showCounter: true,
|
|
392
|
-
keyboard: true,
|
|
393
|
-
loop: true,
|
|
394
|
-
});
|
|
395
422
|
```
|
|
396
423
|
|
|
397
424
|
#### When to use widgets vs custom HTML
|
|
398
425
|
|
|
399
|
-
- **Use widgets** for standard patterns - tables, metrics, timelines, notifications
|
|
426
|
+
- **Use widgets** for standard patterns - tables, metrics, timelines, notifications
|
|
400
427
|
- **Use custom HTML** for novel or creative UIs - games, art tools, unique dashboards
|
|
401
428
|
- **Mix freely** - widgets compose well together and with custom elements
|
|
402
429
|
- **ALWAYS use `vellum.widgets.*` chart functions** instead of hand-coding SVG/CSS charts. They handle overflow clipping, bounds, scaling, and dark mode. Hand-coded charts break layouts.
|
|
@@ -490,7 +517,7 @@ Call `app_create` with:
|
|
|
490
517
|
- `name`: Short descriptive name
|
|
491
518
|
- `description`: One-sentence summary
|
|
492
519
|
- `schema_json`: JSON schema as string
|
|
493
|
-
- `html`: (optional) Complete HTML document as string for `index.html`. If omitted, a minimal scaffold is created - you can then write `index.html` and other files via `
|
|
520
|
+
- `html`: (optional) Complete HTML document as string for `index.html`. If omitted, a minimal scaffold is created - you can then write `index.html` and other files via `file_write`.
|
|
494
521
|
- `auto_open`: (optional, defaults to `true`) Shows an inline preview card in chat
|
|
495
522
|
- `preview`: Always include - `title` (required), `subtitle`, `description`, `icon` (image URL preferred, emoji fallback), `metrics` (up to 3 key-value pills)
|
|
496
523
|
|
|
@@ -503,12 +530,14 @@ The app is NOT opened in a workspace panel automatically - users open it via the
|
|
|
503
530
|
### 6. Handle Iteration
|
|
504
531
|
<!-- feature:app-builder-multifile:alt:end -->
|
|
505
532
|
|
|
506
|
-
When the user requests changes, prefer **`
|
|
533
|
+
When the user requests changes, prefer **`file_edit`** over rewriting the entire file.
|
|
507
534
|
|
|
508
|
-
- **`
|
|
509
|
-
- **`
|
|
510
|
-
- **`
|
|
511
|
-
-
|
|
535
|
+
- **`file_edit`** - preferred for targeted changes (styles, bugs, features). Provide the full file path (e.g. `~/.vellum/workspace/data/apps/<slug>/src/components/App.tsx`).
|
|
536
|
+
- **`file_write`** - for creating new files or full rewrites.
|
|
537
|
+
- **`app_refresh`** - call ONCE after all file changes are complete to trigger compilation and surface refresh.
|
|
538
|
+
- For metadata changes (`name`, `description`, `schemaJson`, etc.), edit the `<slug>.json` file directly with `file_edit`, then call `app_refresh`.
|
|
539
|
+
|
|
540
|
+
After making all file changes, call `app_refresh(app_id)` once to compile and refresh the UI. Do NOT call it after every individual file edit — batch your changes first.
|
|
512
541
|
|
|
513
542
|
Apps can have multiple files (`styles.css`, `app.js`, etc.). Link from `index.html` with standard tags.
|
|
514
543
|
|
|
@@ -524,7 +553,7 @@ Every app must meet these baselines:
|
|
|
524
553
|
|
|
525
554
|
## Presentation Slide Design
|
|
526
555
|
|
|
527
|
-
Slides are a different domain from apps. Skip app-specific patterns (contextual headers, search/filter, toast notifications, form validation, data bridge). Slides are static content.
|
|
556
|
+
Slides are a different domain from apps. Skip app-specific patterns (contextual headers, search/filter, toast notifications, form validation, data bridge). Slides are static content — build navigation and layouts with custom HTML/CSS.
|
|
528
557
|
|
|
529
558
|
**Key principles:**
|
|
530
559
|
|
|
@@ -535,8 +564,6 @@ Slides are a different domain from apps. Skip app-specific patterns (contextual
|
|
|
535
564
|
- Max 6 bullets per slide, max 3 sentences body text
|
|
536
565
|
- Never go below 15px for any visible text
|
|
537
566
|
|
|
538
|
-
Init with `vellum.widgets.slideshow()`. Use `.v-slide` with helpers: `.v-slide-label`, `.v-slide-title`, `.v-slide-body`, `.v-slide-stats`, `.v-slide-stat`, `.v-slide-quote`, `.v-slide-list`, `.v-slide-columns`.
|
|
539
|
-
|
|
540
567
|
## Error Handling
|
|
541
568
|
|
|
542
569
|
- All `window.vellum.data` calls must be wrapped in `try/catch` with user-friendly feedback.
|
|
@@ -544,6 +571,54 @@ Init with `vellum.widgets.slideshow()`. Use `.v-slide` with helpers: `.v-slide-l
|
|
|
544
571
|
- If the page loads with no data, show a designed empty state (`.v-empty-state`).
|
|
545
572
|
- For forms, show validation errors inline next to the relevant field.
|
|
546
573
|
|
|
574
|
+
## App Interaction Hooks
|
|
575
|
+
|
|
576
|
+
When building apps, proactively wire `sendAction` hooks so the assistant stays aware of meaningful user interactions. Two patterns are available:
|
|
577
|
+
|
|
578
|
+
### Reactive hooks
|
|
579
|
+
|
|
580
|
+
Reactive hooks trigger an assistant response. Use them for moments where the assistant's input adds value - selections that need explanation, completions worth celebrating, or submissions that benefit from feedback.
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
// User selects a city on a map — assistant can provide insights
|
|
584
|
+
window.vellum.sendAction('city_selected', { city: 'Tokyo' });
|
|
585
|
+
|
|
586
|
+
// User submits a form — assistant can confirm and suggest next steps
|
|
587
|
+
window.vellum.sendAction('form_submitted', { formId: 'signup', email: 'user@example.com' });
|
|
588
|
+
|
|
589
|
+
// User completes a level — assistant can congratulate and hint at what's next
|
|
590
|
+
window.vellum.sendAction('level_complete', { level: 5, score: 2400 });
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
### Silent hooks
|
|
594
|
+
|
|
595
|
+
Silent hooks accumulate state without interrupting the user. The state is automatically included as context when the next reactive hook fires.
|
|
596
|
+
|
|
597
|
+
```javascript
|
|
598
|
+
// User navigates to a new tab — no response needed, but assistant should know
|
|
599
|
+
window.vellum.sendAction('state_update', { currentView: 'forecast', city: 'Tokyo' });
|
|
600
|
+
|
|
601
|
+
// Score changes during gameplay — track silently
|
|
602
|
+
window.vellum.sendAction('state_update', { score: 1250, lives: 2 });
|
|
603
|
+
|
|
604
|
+
// User applies a filter — context for future questions
|
|
605
|
+
window.vellum.sendAction('state_update', { filter: 'last-30-days', sortBy: 'revenue' });
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### When to use reactive vs silent
|
|
609
|
+
|
|
610
|
+
Choose based on whether the assistant's response would genuinely help the user at that moment:
|
|
611
|
+
|
|
612
|
+
| App type | Silent (state accumulation) | Reactive (triggers response) |
|
|
613
|
+
|---|---|---|
|
|
614
|
+
| **Dashboards** | Tab navigation, filter changes, date range selection | Anomaly detected, threshold breached, data export complete |
|
|
615
|
+
| **Games** | Score updates, move tracking, timer ticks | Level complete, achievement unlocked, game over |
|
|
616
|
+
| **Forms & wizards** | Field focus, partial input, step navigation | Form submitted, validation failed on submit |
|
|
617
|
+
| **Trackers** | Incremental progress, status toggles, reordering | Milestone reached, streak achieved, all items complete |
|
|
618
|
+
| **Data explorers** | Sorting, paging, column toggling | Row selected for detail, comparison initiated |
|
|
619
|
+
|
|
620
|
+
Wire hooks during the initial build - don't wait for the user to ask. Apps that communicate state back to the assistant feel alive; apps that don't feel like static pages.
|
|
621
|
+
|
|
547
622
|
## Actionable UI
|
|
548
623
|
|
|
549
624
|
When the user wants to triage or bulk-act on items, generate an interactive UI with selectable items and action buttons.
|