@pellux/goodvibes-agent 0.1.117 → 1.0.1
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/CHANGELOG.md +20 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176093 -171065
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +159 -73
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +59 -39
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-knowledge-url-editor.ts +4 -11
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-local-library-args.ts +52 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +87 -99
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +118 -50
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -17
- package/src/input/commands/personas-runtime.ts +49 -59
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +63 -72
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +22 -4
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +18 -11
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/ui-openers.ts +3 -13
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +269 -69
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Tools and Commands
|
|
2
|
+
|
|
3
|
+
GoodVibes Agent is an operator assistant TUI. Its command set is centered on main-conversation assistant work, isolated Agent Knowledge, local memory/notes/routines/skills/personas, approvals, automation visibility, and explicit delegation to GoodVibes TUI for build work.
|
|
4
|
+
|
|
5
|
+
## Product Boundaries
|
|
6
|
+
|
|
7
|
+
- Normal chat stays in the main Agent conversation.
|
|
8
|
+
- Agent Knowledge uses only `/api/goodvibes-agent/knowledge/*`.
|
|
9
|
+
- Agent never falls back to default knowledge or arbitrary non-Agent knowledge spaces.
|
|
10
|
+
- Local memory, notes, routines, skills, and personas remain Agent-local until a stable shared registry contract exists.
|
|
11
|
+
- Runtime hosting is external. Agent connects to it and reports health; it does not start, stop, restart, or install it.
|
|
12
|
+
- Delegated review is not a default reasoning path. It is requested only when the user explicitly asks for build, implementation, fix, or review work.
|
|
13
|
+
- Code-building work is delegated to GoodVibes TUI through public shared-session/task contracts.
|
|
14
|
+
|
|
15
|
+
## TUI-First Operator Surface
|
|
16
|
+
|
|
17
|
+
The Agent workspace is the product surface. Slash commands are power-user routes inside the TUI, and package CLI subcommands are scriptable mirrors. New user-facing features should appear in the workspace first.
|
|
18
|
+
|
|
19
|
+
High-signal Agent TUI paths:
|
|
20
|
+
|
|
21
|
+
- `/help` for registry-driven command discovery.
|
|
22
|
+
- `/health` and `/auth` for runtime/auth/SDK diagnostics inside the TUI.
|
|
23
|
+
- `/model` and `/provider` for provider/model selection and visibility.
|
|
24
|
+
- `/agent` for the fullscreen operator workspace: setup, provider/model, Agent Knowledge, memory, notes, personas, skills, routines, channels, MCP/tools, secrets, voice/media, work state, automation, and build delegation.
|
|
25
|
+
- Agent Workspace -> Research for read-only web research, URL inspection, source triage, and explicit source-to-Agent-Knowledge handoff.
|
|
26
|
+
- Agent Workspace -> Notes for local source-triage notes, temporary decisions, and operator handoff. Notes do not write memory or Agent Knowledge by themselves; reviewed notes can prefill memory, skills, routines, personas, or an isolated Agent Knowledge URL ingest.
|
|
27
|
+
- `/knowledge` for isolated Agent Knowledge ask, search, status, source/node/issue inspection, connector inspection, and confirmed ingest/reindex actions.
|
|
28
|
+
- `/memory`, `/routines`, `/skills`, and `/personas` for Agent-local context and reusable operator behavior.
|
|
29
|
+
- `/plan` for Agent-owned workspace planning state in the main conversation.
|
|
30
|
+
- `/workplan` for durable task status over public work-plan routes.
|
|
31
|
+
- `/approvals` for pending approval visibility and explicit approval actions.
|
|
32
|
+
- `/schedule` for schedule visibility plus narrow explicit-user-action flows.
|
|
33
|
+
- `/channels` for channel readiness and one-message confirmed channel delivery.
|
|
34
|
+
- `/media` for media provider readiness and confirmed image/video artifact generation.
|
|
35
|
+
- `/delegate` for explicit build/fix/review handoff to GoodVibes TUI.
|
|
36
|
+
- `/mcp`, `/config`, `/settings`, and setup workspaces for Agent-local configuration.
|
|
37
|
+
|
|
38
|
+
The installed `goodvibes-agent` command launches the TUI by default. Subcommands such as `status`, `compat`, `knowledge ...`, `ask <question>`, and `search <query>` are secondary scriptable equivalents for diagnostics and automation over the same Agent workspace features.
|
|
39
|
+
|
|
40
|
+
Host-management and coding-first commands that would imply connected-host lifecycle ownership, separate Agent job creation, execution-isolation ownership, worktree control, or implicit delegated review must remain blocked, read-only, or delegation-only unless they are intentionally adapted to Agent policy.
|
|
41
|
+
|
|
42
|
+
The main composer supports inline context references. Type `@path/to/file`, `@path/to/folder`, or `@https://example.test/page` in a normal prompt to add bounded context for that turn. `!@path/to/file` remains the raw file-injection form. These references do not ingest anything into Agent Knowledge unless the user explicitly runs a Knowledge ingest action.
|
|
43
|
+
|
|
44
|
+
The Research workspace submits web research and URL inspection forms to the normal main conversation. These requests are read-only by default, may use connected web tools when the user asks, and do not ingest sources. Use confirmed Agent Knowledge ingest actions only after a source should become durable Agent-owned knowledge.
|
|
45
|
+
|
|
46
|
+
Local memory capture/add commands are explicit Agent-local actions. Deletes, imports/exports, record linking, review-state changes, and promotion across memory scopes require `--yes`.
|
|
47
|
+
|
|
48
|
+
## Agent Knowledge
|
|
49
|
+
|
|
50
|
+
`/knowledge ask <query>` asks the isolated Agent Knowledge environment for a source-backed answer through `/api/goodvibes-agent/knowledge/ask`.
|
|
51
|
+
|
|
52
|
+
`/knowledge search <query>` searches the same isolated Agent environment through `/api/goodvibes-agent/knowledge/search`.
|
|
53
|
+
|
|
54
|
+
`/knowledge ingest-url <url> --yes` ingests into Agent Knowledge through `/api/goodvibes-agent/knowledge/ingest/url`. Knowledge ingestion, imports, issue review, reindex, and consolidation are Agent-owned mutations and require `--yes`.
|
|
55
|
+
|
|
56
|
+
The Knowledge workspace exposes status, source library, connector review, ask, search, and confirmed ingest forms. Scriptable equivalents such as `goodvibes-agent knowledge list --kind sources|nodes|issues`, `goodvibes-agent knowledge get <id>`, `goodvibes-agent knowledge connectors`, and `goodvibes-agent knowledge map` are read-only CLI inspection paths over the same isolated Agent route family.
|
|
57
|
+
|
|
58
|
+
Workspace ingest forms are the primary user workflow. Scriptable equivalents such as `goodvibes-agent knowledge import-urls <path> --yes`, `goodvibes-agent knowledge import-bookmarks <path> --yes`, and `goodvibes-agent knowledge reindex --yes` are confirmed Agent Knowledge maintenance paths. They call only `/api/goodvibes-agent/knowledge/*`.
|
|
59
|
+
|
|
60
|
+
The Agent command layer rejects flags that would route knowledge work into another space, including `--space`, `--knowledge-space`, `--knowledge-space-id`, and `--include-all-spaces`. If Agent Knowledge is unavailable, the command fails closed instead of querying a default store.
|
|
61
|
+
|
|
62
|
+
## Media Artifacts
|
|
63
|
+
|
|
64
|
+
Agent Workspace -> Voice & Media is the primary media path. Use `Generate media` for a confirmed form that calls configured media providers and stores outputs as GoodVibes artifacts.
|
|
65
|
+
|
|
66
|
+
`/media providers` lists media provider readiness. `/media generate [--provider <id>] [--model <id>] [--mime <mime>] <prompt> --yes` is the power-user mirror for confirmed image/video generation. Media generation output returns artifact ids and metadata; it does not print inline base64 and does not write to default knowledge or non-Agent knowledge segments.
|
|
67
|
+
|
|
68
|
+
## Planning
|
|
69
|
+
|
|
70
|
+
`/plan` inspects or seeds Agent workspace planning state. The planning loop belongs to the main Agent conversation: the Agent asks focused questions, records decisions and gaps, and keeps execution separate until the user gives an explicit action.
|
|
71
|
+
|
|
72
|
+
The SDK planning service may expose a namespace such as `project:<projectId>` because that is the stable contract shape. In Agent UI and docs this is treated as a planning namespace, not as permission to query default knowledge or another product knowledge segment.
|
|
73
|
+
|
|
74
|
+
Use `/workplan` when the work already has concrete tasks and needs durable status tracking rather than another planning interview.
|
|
75
|
+
|
|
76
|
+
## Delegation
|
|
77
|
+
|
|
78
|
+
`/delegate` is for explicit build, fix, review, or implementation work. It sends a single delegated request to GoodVibes TUI/shared-session routes with the original user ask and execution intent. Agent does not create coding-role Agent jobs and does not run delegated review by default.
|
|
79
|
+
|
|
80
|
+
Use `/delegate --review` only when the user explicitly asks for review or when the delegated build/fix/review request explicitly calls for review.
|
|
81
|
+
|
|
82
|
+
## Approvals And Automation
|
|
83
|
+
|
|
84
|
+
Approvals and automation are safe by default:
|
|
85
|
+
|
|
86
|
+
- list/status views are read-only;
|
|
87
|
+
- mutating routes require exact commands and explicit confirmation such as `--yes`;
|
|
88
|
+
- no chat turn silently runs approval, schedule, or automation mutations;
|
|
89
|
+
- unavailable routes return structured errors rather than fallback behavior.
|
|
90
|
+
|
|
91
|
+
Workspace forms are the primary path for approval and automation actions:
|
|
92
|
+
|
|
93
|
+
- Agent Workspace -> Work & Approvals -> Approve request / Deny request / Cancel request
|
|
94
|
+
- Agent Workspace -> Automation -> Run job now / Pause job / Resume job
|
|
95
|
+
- Agent Workspace -> Automation -> Cancel run / Retry run / Run schedule now
|
|
96
|
+
|
|
97
|
+
Power-user slash mirrors are exact and confirmation-gated:
|
|
98
|
+
|
|
99
|
+
- `/approval approve <approval-id> [--note <text>] [--remember|--no-remember] --yes`
|
|
100
|
+
- `/approval deny <approval-id> [--note <text>] [--remember|--no-remember] --yes`
|
|
101
|
+
- `/approval cancel <approval-id> [--note <text>] [--remember|--no-remember] --yes`
|
|
102
|
+
- `/automation job run <job-id> --yes`
|
|
103
|
+
- `/automation job pause <job-id> --yes`
|
|
104
|
+
- `/automation job resume <job-id> --yes`
|
|
105
|
+
- `/automation run cancel <run-id> --yes`
|
|
106
|
+
- `/automation run retry <run-id> --yes`
|
|
107
|
+
- `/automation schedule run <schedule-id> --yes`
|
|
108
|
+
- `/schedule run <schedule-id> --yes`
|
|
109
|
+
|
|
110
|
+
Routine promotion is an explicit scheduling bridge: local routines stay local during normal use, and promotion creates a schedule only after a user runs the exact command with `--yes`. The generated scheduled prompt keeps Agent Knowledge isolated and forbids default knowledge or non-Agent knowledge fallback. Delivery is opt-in with explicit flags such as `--delivery-channel`, `--delivery-route`, `--delivery-webhook`, or `--delivery-link`; no delivery target is inferred from chat.
|
|
111
|
+
|
|
112
|
+
## Channels
|
|
113
|
+
|
|
114
|
+
Agent Workspace -> Channels is the primary channel path. It shows readiness, setup, account, policy, and status views without rendering secret values. `Send channel message` opens a confirmed form for one delivery target.
|
|
115
|
+
|
|
116
|
+
`/channels send --channel <surface[:route[:label]]> --message <text> --yes` sends one explicit message through configured delivery strategies. `--route`, `--webhook`, and `--link` are alternate one-target forms. Channel sends do not create routes, authorize accounts, manage connected-host hosting, use default knowledge, use non-Agent knowledge segments, create separate Agent jobs, or run delegated review.
|
|
117
|
+
|
|
118
|
+
## Related Docs
|
|
119
|
+
|
|
120
|
+
- [Getting started](getting-started.md)
|
|
121
|
+
- [Connected host](connected-host.md)
|
|
122
|
+
- [Knowledge, artifacts, and multimodal](knowledge-artifacts-and-multimodal.md)
|
|
123
|
+
- [Release and publishing](release-and-publishing.md)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Voice and Live TTS
|
|
2
|
+
|
|
3
|
+
GoodVibes Agent supports spoken turns as an Agent TUI feature. Text output remains primary; voice is an additional local playback path for a normal assistant turn.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
/tts <prompt>
|
|
9
|
+
/tts stop
|
|
10
|
+
/config tts
|
|
11
|
+
/config tts.provider
|
|
12
|
+
/config tts.voice
|
|
13
|
+
/config tts.llmProvider
|
|
14
|
+
/config tts.llmModel
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`/tts <prompt>` submits the prompt through the normal Agent conversation path. It uses the active chat provider/model unless a separate spoken-turn model override is configured.
|
|
18
|
+
|
|
19
|
+
`/tts stop` cancels queued spoken output and active playback without cancelling the text transcript.
|
|
20
|
+
|
|
21
|
+
`/config tts` opens the fullscreen configuration workspace for streaming provider, voice, and spoken-turn model routing.
|
|
22
|
+
|
|
23
|
+
## Playback Requirements
|
|
24
|
+
|
|
25
|
+
Live playback streams audio to a local player. Install one of:
|
|
26
|
+
|
|
27
|
+
- `mpv`;
|
|
28
|
+
- `ffplay`.
|
|
29
|
+
|
|
30
|
+
If neither player is on `PATH`, the Agent still submits and renders the normal text response. Audio is skipped with a concise status message.
|
|
31
|
+
|
|
32
|
+
## Provider Routing
|
|
33
|
+
|
|
34
|
+
Voice uses providers that advertise streaming TTS capability through the runtime. Agent does not hardcode provider behavior.
|
|
35
|
+
|
|
36
|
+
Useful setup path:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
/config tts.provider
|
|
40
|
+
/config tts.voice
|
|
41
|
+
/config tts.llmProvider
|
|
42
|
+
/config tts.llmModel
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Leaving `tts.voice` empty lets the provider choose its default voice.
|
|
46
|
+
|
|
47
|
+
## Knowledge Boundary
|
|
48
|
+
|
|
49
|
+
Spoken responses are conversation output. They are not automatically written to Agent Knowledge, local memory, default knowledge, or any other product segment.
|
|
50
|
+
|
|
51
|
+
If a spoken result should become durable, store it through an explicit Agent memory command or an Agent Knowledge ingestion path.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -22,10 +22,7 @@
|
|
|
22
22
|
"tsconfig.json",
|
|
23
23
|
"README.md",
|
|
24
24
|
"CHANGELOG.md",
|
|
25
|
-
"docs
|
|
26
|
-
"docs/getting-started.md",
|
|
27
|
-
"docs/connected-host.md",
|
|
28
|
-
"docs/release-and-publishing.md"
|
|
25
|
+
"docs/*.md"
|
|
29
26
|
],
|
|
30
27
|
"scripts": {
|
|
31
28
|
"dev": "bun run src/main.ts",
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ChannelDeliveryRequest,
|
|
3
|
+
ChannelDeliveryRouter,
|
|
4
|
+
ChannelDeliverySurfaceKind,
|
|
5
|
+
ChannelDeliveryTarget,
|
|
6
|
+
} from '@pellux/goodvibes-sdk/platform/channels';
|
|
7
|
+
|
|
8
|
+
type AgentChannelDeliveryRouter = Pick<ChannelDeliveryRouter, 'deliver' | 'listStrategies'>;
|
|
9
|
+
type AgentChannelDeliverySurfaceKind = ChannelDeliverySurfaceKind | 'telephony';
|
|
10
|
+
type AgentChannelDeliveryTarget = Omit<ChannelDeliveryTarget, 'surfaceKind'> & {
|
|
11
|
+
readonly surfaceKind?: AgentChannelDeliverySurfaceKind;
|
|
12
|
+
};
|
|
13
|
+
type AgentChannelDeliveryRequest = Omit<ChannelDeliveryRequest, 'target'> & {
|
|
14
|
+
readonly target: AgentChannelDeliveryTarget;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export interface AgentChannelDeliveryInput {
|
|
18
|
+
readonly message: string;
|
|
19
|
+
readonly title?: string;
|
|
20
|
+
readonly channel?: string;
|
|
21
|
+
readonly route?: string;
|
|
22
|
+
readonly webhook?: string;
|
|
23
|
+
readonly link?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AgentChannelDeliveryPreview {
|
|
27
|
+
readonly message: string;
|
|
28
|
+
readonly title: string;
|
|
29
|
+
readonly target: AgentChannelDeliveryTarget;
|
|
30
|
+
readonly request: AgentChannelDeliveryRequest;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface AgentChannelDeliveryResult {
|
|
34
|
+
readonly responseId?: string;
|
|
35
|
+
readonly message: string;
|
|
36
|
+
readonly title: string;
|
|
37
|
+
readonly target: AgentChannelDeliveryTarget;
|
|
38
|
+
readonly strategyCount: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const DELIVERY_SURFACE_KINDS: readonly AgentChannelDeliverySurfaceKind[] = [
|
|
42
|
+
'tui',
|
|
43
|
+
'web',
|
|
44
|
+
'slack',
|
|
45
|
+
'discord',
|
|
46
|
+
'ntfy',
|
|
47
|
+
'webhook',
|
|
48
|
+
'telegram',
|
|
49
|
+
'google-chat',
|
|
50
|
+
'signal',
|
|
51
|
+
'whatsapp',
|
|
52
|
+
'telephony',
|
|
53
|
+
'imessage',
|
|
54
|
+
'msteams',
|
|
55
|
+
'bluebubbles',
|
|
56
|
+
'mattermost',
|
|
57
|
+
'matrix',
|
|
58
|
+
'service',
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
function readText(value: string | undefined): string | undefined {
|
|
62
|
+
const trimmed = value?.trim();
|
|
63
|
+
return trimmed ? trimmed : undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isDeliverySurfaceKind(value: string): value is AgentChannelDeliverySurfaceKind {
|
|
67
|
+
return DELIVERY_SURFACE_KINDS.includes(value as AgentChannelDeliverySurfaceKind);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function parseChannelTarget(raw: string): AgentChannelDeliveryTarget {
|
|
71
|
+
const [surfaceKind = '', routeId, label] = raw.split(':');
|
|
72
|
+
if (!isDeliverySurfaceKind(surfaceKind)) {
|
|
73
|
+
throw new Error(`Unsupported delivery channel "${surfaceKind}".`);
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
kind: 'surface',
|
|
77
|
+
surfaceKind,
|
|
78
|
+
...(readText(routeId) ? { routeId: readText(routeId) } : {}),
|
|
79
|
+
...(readText(label) ? { label: readText(label) } : {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function parseRouteTarget(raw: string): AgentChannelDeliveryTarget {
|
|
84
|
+
const [routeId = '', label] = raw.split(':');
|
|
85
|
+
const normalizedRouteId = readText(routeId);
|
|
86
|
+
if (!normalizedRouteId) throw new Error('Route delivery target requires a route id.');
|
|
87
|
+
return {
|
|
88
|
+
kind: 'surface',
|
|
89
|
+
routeId: normalizedRouteId,
|
|
90
|
+
...(readText(label) ? { label: readText(label) } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function parseWebhookTarget(raw: string): AgentChannelDeliveryTarget {
|
|
95
|
+
const normalized = readText(raw);
|
|
96
|
+
if (!normalized) throw new Error('Webhook delivery target requires a URL.');
|
|
97
|
+
try {
|
|
98
|
+
const url = new URL(normalized);
|
|
99
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') throw new Error('bad protocol');
|
|
100
|
+
} catch {
|
|
101
|
+
throw new Error('Webhook delivery target must be a valid http(s) URL.');
|
|
102
|
+
}
|
|
103
|
+
return { kind: 'webhook', address: normalized };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function parseLinkTarget(raw: string): AgentChannelDeliveryTarget {
|
|
107
|
+
const normalized = readText(raw);
|
|
108
|
+
if (!normalized) throw new Error('Link delivery target requires a URL or label.');
|
|
109
|
+
return { kind: 'link', address: normalized };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function selectedTargetInputs(input: AgentChannelDeliveryInput): readonly string[] {
|
|
113
|
+
return [input.channel, input.route, input.webhook, input.link].map(readText).filter((value): value is string => Boolean(value));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function buildAgentChannelDeliveryPreview(input: AgentChannelDeliveryInput): AgentChannelDeliveryPreview {
|
|
117
|
+
const message = readText(input.message);
|
|
118
|
+
if (!message) throw new Error('Channel delivery message is required.');
|
|
119
|
+
const targets = selectedTargetInputs(input);
|
|
120
|
+
if (targets.length === 0) throw new Error('Choose one delivery target: channel, route, webhook, or link.');
|
|
121
|
+
if (targets.length > 1) throw new Error('Choose exactly one delivery target.');
|
|
122
|
+
|
|
123
|
+
const channel = readText(input.channel);
|
|
124
|
+
const route = readText(input.route);
|
|
125
|
+
const webhook = readText(input.webhook);
|
|
126
|
+
const link = readText(input.link);
|
|
127
|
+
const target = channel
|
|
128
|
+
? parseChannelTarget(channel)
|
|
129
|
+
: route
|
|
130
|
+
? parseRouteTarget(route)
|
|
131
|
+
: webhook
|
|
132
|
+
? parseWebhookTarget(webhook)
|
|
133
|
+
: parseLinkTarget(link ?? '');
|
|
134
|
+
const title = readText(input.title) ?? 'GoodVibes Agent message';
|
|
135
|
+
return {
|
|
136
|
+
message,
|
|
137
|
+
title,
|
|
138
|
+
target,
|
|
139
|
+
request: {
|
|
140
|
+
target,
|
|
141
|
+
body: message,
|
|
142
|
+
title,
|
|
143
|
+
jobId: 'agent-channel-send',
|
|
144
|
+
runId: `agent-channel-send-${Date.now()}`,
|
|
145
|
+
status: 'completed',
|
|
146
|
+
includeLinks: true,
|
|
147
|
+
metadata: {
|
|
148
|
+
product: 'goodvibes-agent',
|
|
149
|
+
source: 'agent-channel-send',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export async function deliverAgentChannelMessage(
|
|
156
|
+
router: AgentChannelDeliveryRouter,
|
|
157
|
+
input: AgentChannelDeliveryInput,
|
|
158
|
+
): Promise<AgentChannelDeliveryResult> {
|
|
159
|
+
const preview = buildAgentChannelDeliveryPreview(input);
|
|
160
|
+
const responseId = await router.deliver(preview.request as ChannelDeliveryRequest);
|
|
161
|
+
return {
|
|
162
|
+
responseId,
|
|
163
|
+
message: preview.message,
|
|
164
|
+
title: preview.title,
|
|
165
|
+
target: preview.target,
|
|
166
|
+
strategyCount: router.listStrategies().length,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function formatTarget(target: AgentChannelDeliveryTarget): string {
|
|
171
|
+
if (target.kind === 'surface') {
|
|
172
|
+
const base = target.surfaceKind ?? 'route';
|
|
173
|
+
const details = [
|
|
174
|
+
target.routeId ? `route ${target.routeId}` : '',
|
|
175
|
+
target.label ? `label ${target.label}` : '',
|
|
176
|
+
].filter(Boolean);
|
|
177
|
+
return `${base}${details.length > 0 ? ` (${details.join(', ')})` : ''}`;
|
|
178
|
+
}
|
|
179
|
+
return target.address ? `${target.kind} ${target.address}` : target.kind;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function formatAgentChannelDeliveryPreview(preview: AgentChannelDeliveryPreview, strategyCount: number): string {
|
|
183
|
+
return [
|
|
184
|
+
'Agent channel delivery preview',
|
|
185
|
+
` title ${preview.title}`,
|
|
186
|
+
` target ${formatTarget(preview.target)}`,
|
|
187
|
+
` strategies ${strategyCount}`,
|
|
188
|
+
` message ${preview.message}`,
|
|
189
|
+
' policy external delivery requires an explicit user request and confirmation',
|
|
190
|
+
].join('\n');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function formatAgentChannelDeliveryResult(result: AgentChannelDeliveryResult): string {
|
|
194
|
+
return [
|
|
195
|
+
'Agent channel delivery sent',
|
|
196
|
+
` title ${result.title}`,
|
|
197
|
+
` target ${formatTarget(result.target)}`,
|
|
198
|
+
` strategies ${result.strategyCount}`,
|
|
199
|
+
...(result.responseId ? [` response ${result.responseId}`] : []),
|
|
200
|
+
].join('\n');
|
|
201
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import type { ArtifactCreateInput, ArtifactDescriptor, ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
2
|
+
import type {
|
|
3
|
+
MediaArtifact,
|
|
4
|
+
MediaGenerationRequest,
|
|
5
|
+
MediaProvider,
|
|
6
|
+
MediaProviderRegistry,
|
|
7
|
+
} from '@pellux/goodvibes-sdk/platform/media';
|
|
8
|
+
|
|
9
|
+
export interface AgentMediaGenerationInput {
|
|
10
|
+
readonly prompt: string;
|
|
11
|
+
readonly providerId?: string;
|
|
12
|
+
readonly modelId?: string;
|
|
13
|
+
readonly outputMimeType?: string;
|
|
14
|
+
readonly options?: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface AgentGeneratedMediaArtifact {
|
|
18
|
+
readonly artifactId: string;
|
|
19
|
+
readonly mimeType: string;
|
|
20
|
+
readonly filename?: string;
|
|
21
|
+
readonly sizeBytes: number;
|
|
22
|
+
readonly sourceUri?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AgentMediaGenerationResult {
|
|
26
|
+
readonly providerId: string;
|
|
27
|
+
readonly artifacts: readonly AgentGeneratedMediaArtifact[];
|
|
28
|
+
readonly metadata: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function readText(value: string | undefined): string | undefined {
|
|
32
|
+
const trimmed = value?.trim();
|
|
33
|
+
return trimmed ? trimmed : undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function ensurePrompt(prompt: string): string {
|
|
37
|
+
const trimmed = prompt.trim();
|
|
38
|
+
if (!trimmed) throw new Error('Media generation prompt is required.');
|
|
39
|
+
return trimmed;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function findGenerationProvider(registry: MediaProviderRegistry, providerId: string | undefined): MediaProvider {
|
|
43
|
+
const provider = registry.findProvider('generate', readText(providerId));
|
|
44
|
+
if (!provider?.generate) {
|
|
45
|
+
const available = registry
|
|
46
|
+
.list()
|
|
47
|
+
.filter((entry) => entry.capabilities.includes('generate'))
|
|
48
|
+
.map((entry) => entry.id)
|
|
49
|
+
.join(', ');
|
|
50
|
+
throw new Error(providerId
|
|
51
|
+
? `Media generation provider is unavailable or not configured for generation: ${providerId}.`
|
|
52
|
+
: `No media generation provider is available${available ? `. Available providers: ${available}` : '.'}`);
|
|
53
|
+
}
|
|
54
|
+
return provider;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function filenameForArtifact(artifact: MediaArtifact, index: number): string {
|
|
58
|
+
if (readText(artifact.filename)) return artifact.filename as string;
|
|
59
|
+
if (artifact.mimeType.includes('video')) return `agent-generated-${index + 1}.mp4`;
|
|
60
|
+
if (artifact.mimeType.includes('image')) return `agent-generated-${index + 1}.png`;
|
|
61
|
+
return `agent-generated-${index + 1}`;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function artifactCreateInput(
|
|
65
|
+
providerId: string,
|
|
66
|
+
artifact: MediaArtifact,
|
|
67
|
+
index: number,
|
|
68
|
+
): ArtifactCreateInput {
|
|
69
|
+
const filename = filenameForArtifact(artifact, index);
|
|
70
|
+
const metadata = {
|
|
71
|
+
...artifact.metadata,
|
|
72
|
+
product: 'goodvibes-agent',
|
|
73
|
+
source: 'agent-media-generation',
|
|
74
|
+
providerId,
|
|
75
|
+
};
|
|
76
|
+
const common = {
|
|
77
|
+
mimeType: artifact.mimeType,
|
|
78
|
+
filename,
|
|
79
|
+
metadata,
|
|
80
|
+
};
|
|
81
|
+
if (readText(artifact.dataBase64)) {
|
|
82
|
+
return {
|
|
83
|
+
...common,
|
|
84
|
+
dataBase64: artifact.dataBase64,
|
|
85
|
+
sourceUri: artifact.uri,
|
|
86
|
+
acquisitionMode: 'inline-data',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (readText(artifact.uri)) {
|
|
90
|
+
return {
|
|
91
|
+
...common,
|
|
92
|
+
uri: artifact.uri,
|
|
93
|
+
sourceUri: artifact.uri,
|
|
94
|
+
acquisitionMode: 'remote-fetch',
|
|
95
|
+
fetchMode: 'public-only',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
throw new Error(`Generated media artifact ${index + 1} did not include inline data or a fetchable URI.`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function toGeneratedArtifact(descriptor: ArtifactDescriptor): AgentGeneratedMediaArtifact {
|
|
102
|
+
return {
|
|
103
|
+
artifactId: descriptor.id,
|
|
104
|
+
mimeType: descriptor.mimeType,
|
|
105
|
+
...(descriptor.filename ? { filename: descriptor.filename } : {}),
|
|
106
|
+
sizeBytes: descriptor.sizeBytes,
|
|
107
|
+
...(descriptor.sourceUri ? { sourceUri: descriptor.sourceUri } : {}),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function buildProviderRequest(input: AgentMediaGenerationInput): MediaGenerationRequest {
|
|
112
|
+
return {
|
|
113
|
+
prompt: ensurePrompt(input.prompt),
|
|
114
|
+
...(readText(input.outputMimeType) ? { outputMimeType: readText(input.outputMimeType) } : {}),
|
|
115
|
+
...(readText(input.modelId) ? { modelId: readText(input.modelId) } : {}),
|
|
116
|
+
...(input.options ? { options: input.options } : {}),
|
|
117
|
+
metadata: {
|
|
118
|
+
product: 'goodvibes-agent',
|
|
119
|
+
source: 'agent-media-generation',
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export async function generateAgentMedia(
|
|
125
|
+
registry: MediaProviderRegistry,
|
|
126
|
+
artifactStore: Pick<ArtifactStore, 'create'>,
|
|
127
|
+
input: AgentMediaGenerationInput,
|
|
128
|
+
): Promise<AgentMediaGenerationResult> {
|
|
129
|
+
const provider = findGenerationProvider(registry, input.providerId);
|
|
130
|
+
const generate = provider.generate;
|
|
131
|
+
if (!generate) throw new Error(`Media generation provider is unavailable or not configured for generation: ${provider.id}.`);
|
|
132
|
+
const generated = await generate(buildProviderRequest(input));
|
|
133
|
+
const artifacts: AgentGeneratedMediaArtifact[] = [];
|
|
134
|
+
for (const [index, artifact] of generated.artifacts.entries()) {
|
|
135
|
+
const descriptor = await artifactStore.create(artifactCreateInput(generated.providerId, artifact, index));
|
|
136
|
+
artifacts.push(toGeneratedArtifact(descriptor));
|
|
137
|
+
}
|
|
138
|
+
if (artifacts.length === 0) throw new Error(`Media provider ${generated.providerId} did not return artifacts.`);
|
|
139
|
+
return {
|
|
140
|
+
providerId: generated.providerId,
|
|
141
|
+
artifacts,
|
|
142
|
+
metadata: generated.metadata,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function formatAgentMediaGenerationResult(result: AgentMediaGenerationResult): string {
|
|
147
|
+
return [
|
|
148
|
+
'Agent media generated',
|
|
149
|
+
` provider ${result.providerId}`,
|
|
150
|
+
` artifacts ${result.artifacts.length}`,
|
|
151
|
+
...result.artifacts.map((artifact, index) => [
|
|
152
|
+
` ${index + 1}. ${artifact.artifactId}`,
|
|
153
|
+
` type ${artifact.mimeType}`,
|
|
154
|
+
` size ${artifact.sizeBytes} bytes`,
|
|
155
|
+
...(artifact.filename ? [` filename ${artifact.filename}`] : []),
|
|
156
|
+
...(artifact.sourceUri ? [` source ${artifact.sourceUri}`] : []),
|
|
157
|
+
].join('\n')),
|
|
158
|
+
].join('\n');
|
|
159
|
+
}
|