mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(agents): carry the backend provider into persona templates
Corrects an earlier call to omit provider from the save-as-persona-template
port. On main the provider is NOT a top-level ManagedAgent field, but it is
NOT absent either — it lives in the backend union: a `{ type: "provider",
id }` backend carries the provider id, while a `{ type: "local" }` backend
has none.
- saveAsPersonaTemplateDialogState now derives provider from agent.backend
(providerForAgentBackend): a provider backend carries backend.id; a local
backend leaves it unset. A databricks agent promotes with its provider
instead of losing it.
- CreateAgentDialog's opt-in template mint mirrors this: it carries the
selected backend provider (runOn) when the agent runs on a provider.
Tests updated: provider carries from a provider backend; stays unset for a
local backend.
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
co-authored by
Taylor Ho
parent
65e41bbc48
commit
b6519f5f0e
@@ -443,6 +443,10 @@ export function CreateAgentDialog({
|
||||
runtime:
|
||||
selectedRuntimeId !== "custom" ? selectedRuntimeId : undefined,
|
||||
model: useMesh ? meshModelId.trim() || undefined : undefined,
|
||||
// Carry the backend provider when the agent runs on one ("Run on" is
|
||||
// a provider, not local). Mirrors what the agent input persists in
|
||||
// `backend.id`; local agents leave it unset.
|
||||
provider: isProviderMode ? runOn : undefined,
|
||||
envVars,
|
||||
};
|
||||
try {
|
||||
|
||||
@@ -259,6 +259,7 @@ function makeAgent(overrides = {}) {
|
||||
lastStoppedAt: null,
|
||||
lastExitCode: null,
|
||||
lastError: null,
|
||||
backend: { type: "local" },
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
@@ -316,12 +317,26 @@ test("saveAsPersonaTemplateDialogState carries name, prompt, model, and envVars"
|
||||
assert.deepEqual(state.initialValues.namePool, []);
|
||||
});
|
||||
|
||||
test("saveAsPersonaTemplateDialogState omits provider (no top-level field on ManagedAgent)", () => {
|
||||
// A ManagedAgent has no top-level provider, so there is nothing lossless to
|
||||
// carry — the builder must not invent one.
|
||||
const state = saveAsPersonaTemplateDialogState(makeAgent(), []);
|
||||
test("saveAsPersonaTemplateDialogState carries the provider id from a provider backend", () => {
|
||||
// A databricks/anthropic agent must promote with its provider, not lose it.
|
||||
// ManagedAgent has no top-level provider on main; it lives in backend.id.
|
||||
const state = saveAsPersonaTemplateDialogState(
|
||||
makeAgent({ backend: { type: "provider", id: "databricks", config: {} } }),
|
||||
[],
|
||||
);
|
||||
|
||||
assert.equal("provider" in state.initialValues, false);
|
||||
assert.equal(state.initialValues.provider, "databricks");
|
||||
});
|
||||
|
||||
test("saveAsPersonaTemplateDialogState leaves provider unset for a local backend", () => {
|
||||
// A local backend has no provider; the persona's provider is optional, so it
|
||||
// carries as undefined (auto-detect / provider-locked runtime).
|
||||
const state = saveAsPersonaTemplateDialogState(
|
||||
makeAgent({ backend: { type: "local" } }),
|
||||
[],
|
||||
);
|
||||
|
||||
assert.equal(state.initialValues.provider, undefined);
|
||||
});
|
||||
|
||||
test("saveAsPersonaTemplateDialogState tolerates null systemPrompt and model", () => {
|
||||
|
||||
@@ -76,21 +76,34 @@ function runtimeIdForAgentCommand(
|
||||
return match?.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the LLM provider id from a managed agent's backend so it can carry
|
||||
* into the persona template (a databricks/anthropic agent should promote with
|
||||
* its provider, not lose it). On `main` the provider is NOT a top-level field
|
||||
* on `ManagedAgent`; it lives in the backend union: a `"provider"` backend
|
||||
* carries the provider id, while a `"local"` backend has none. Returns
|
||||
* `undefined` for local backends — the persona's `provider` is optional, so an
|
||||
* absent provider just carries as unset (auto-detect / provider-locked runtime).
|
||||
*/
|
||||
function providerForAgentBackend(
|
||||
backend: ManagedAgent["backend"],
|
||||
): string | undefined {
|
||||
return backend.type === "provider" ? backend.id : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dialog state for the opt-in "Save as persona template" action on an existing
|
||||
* agent. Prefills the persona editor from the agent so the user reviews and
|
||||
* confirms before a persona template is created — nothing is minted silently.
|
||||
*
|
||||
* Near-lossless promote: name, system prompt, model, and env vars copy
|
||||
* straight across; the harness command reverse-maps to a runtime ID.
|
||||
* `namePool` is persona-only and starts empty — the user can fill it in the
|
||||
* same dialog (it's how a template bulk-adds bots later).
|
||||
* straight across; the harness command reverse-maps to a runtime ID and the
|
||||
* backend provider id carries into the persona's provider. `namePool` is
|
||||
* persona-only and starts empty — the user can fill it in the same dialog
|
||||
* (it's how a template bulk-adds bots later).
|
||||
*
|
||||
* Note: "persona template" is the UI name for what the backend calls a
|
||||
* `persona` (kind:30175). This builder produces a backend `CreatePersonaInput`.
|
||||
* `provider` is intentionally not carried: a `ManagedAgent` does not expose a
|
||||
* top-level provider field (it lives in backend/provider config), so there is
|
||||
* nothing lossless to copy here.
|
||||
*/
|
||||
export function saveAsPersonaTemplateDialogState(
|
||||
agent: ManagedAgent,
|
||||
@@ -106,6 +119,9 @@ export function saveAsPersonaTemplateDialogState(
|
||||
systemPrompt: agent.systemPrompt ?? "",
|
||||
runtime: runtimeIdForAgentCommand(agent.agentCommand, runtimes),
|
||||
model: agent.model ?? undefined,
|
||||
// Carry the provider from a `"provider"` backend; `"local"` backends
|
||||
// have none and leave it unset (see providerForAgentBackend).
|
||||
provider: providerForAgentBackend(agent.backend),
|
||||
// namePool is persona-only; start empty so the user fills it here.
|
||||
namePool: [],
|
||||
envVars: agent.envVars ?? {},
|
||||
|
||||
Reference in New Issue
Block a user