Lifei/sub recipe desktop temp (#3576)

This commit is contained in:
Lifei Zhou
2025-07-24 23:37:24 +10:00
committed by GitHub
parent a52e11afc1
commit e682940929
14 changed files with 255 additions and 113 deletions
+58
View File
@@ -13,6 +13,39 @@
"version": "1.1.0"
},
"paths": {
"/agent/add_sub_recipes": {
"post": {
"tags": [
"super::routes::agent"
],
"operationId": "add_sub_recipes",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddSubRecipesRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "added sub recipes to agent successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddSubRecipesResponse"
}
}
}
},
"401": {
"description": "Unauthorized - invalid secret key"
}
}
}
},
"/agent/tools": {
"get": {
"tags": [
@@ -1033,6 +1066,31 @@
},
"components": {
"schemas": {
"AddSubRecipesRequest": {
"type": "object",
"required": [
"sub_recipes"
],
"properties": {
"sub_recipes": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SubRecipe"
}
}
}
},
"AddSubRecipesResponse": {
"type": "object",
"required": [
"success"
],
"properties": {
"success": {
"type": "boolean"
}
}
},
"Annotations": {
"type": "object",
"properties": {
+12 -1
View File
@@ -1,7 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts
import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
import type { GetToolsData, GetToolsResponse, ReadAllConfigData, ReadAllConfigResponse, BackupConfigData, BackupConfigResponse, GetExtensionsData, GetExtensionsResponse, AddExtensionData, AddExtensionResponse, RemoveExtensionData, RemoveExtensionResponse, InitConfigData, InitConfigResponse, UpsertPermissionsData, UpsertPermissionsResponse, ProvidersData, ProvidersResponse2, ReadConfigData, RecoverConfigData, RecoverConfigResponse, RemoveConfigData, RemoveConfigResponse, UpsertConfigData, UpsertConfigResponse, ValidateConfigData, ValidateConfigResponse, ConfirmPermissionData, ManageContextData, ManageContextResponse, CreateRecipeData, CreateRecipeResponse2, DecodeRecipeData, DecodeRecipeResponse2, EncodeRecipeData, EncodeRecipeResponse2, CreateScheduleData, CreateScheduleResponse, DeleteScheduleData, DeleteScheduleResponse, ListSchedulesData, ListSchedulesResponse2, UpdateScheduleData, UpdateScheduleResponse, InspectRunningJobData, InspectRunningJobResponse, KillRunningJobData, PauseScheduleData, PauseScheduleResponse, RunNowHandlerData, RunNowHandlerResponse, SessionsHandlerData, SessionsHandlerResponse, UnpauseScheduleData, UnpauseScheduleResponse, ListSessionsData, ListSessionsResponse, GetSessionHistoryData, GetSessionHistoryResponse } from './types.gen';
import type { AddSubRecipesData, AddSubRecipesResponse2, GetToolsData, GetToolsResponse, ReadAllConfigData, ReadAllConfigResponse, BackupConfigData, BackupConfigResponse, GetExtensionsData, GetExtensionsResponse, AddExtensionData, AddExtensionResponse, RemoveExtensionData, RemoveExtensionResponse, InitConfigData, InitConfigResponse, UpsertPermissionsData, UpsertPermissionsResponse, ProvidersData, ProvidersResponse2, ReadConfigData, RecoverConfigData, RecoverConfigResponse, RemoveConfigData, RemoveConfigResponse, UpsertConfigData, UpsertConfigResponse, ValidateConfigData, ValidateConfigResponse, ConfirmPermissionData, ManageContextData, ManageContextResponse, CreateRecipeData, CreateRecipeResponse2, DecodeRecipeData, DecodeRecipeResponse2, EncodeRecipeData, EncodeRecipeResponse2, CreateScheduleData, CreateScheduleResponse, DeleteScheduleData, DeleteScheduleResponse, ListSchedulesData, ListSchedulesResponse2, UpdateScheduleData, UpdateScheduleResponse, InspectRunningJobData, InspectRunningJobResponse, KillRunningJobData, PauseScheduleData, PauseScheduleResponse, RunNowHandlerData, RunNowHandlerResponse, SessionsHandlerData, SessionsHandlerResponse, UnpauseScheduleData, UnpauseScheduleResponse, ListSessionsData, ListSessionsResponse, GetSessionHistoryData, GetSessionHistoryResponse } from './types.gen';
import { client as _heyApiClient } from './client.gen';
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
@@ -18,6 +18,17 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends
meta?: Record<string, unknown>;
};
export const addSubRecipes = <ThrowOnError extends boolean = false>(options: Options<AddSubRecipesData, ThrowOnError>) => {
return (options.client ?? _heyApiClient).post<AddSubRecipesResponse2, unknown, ThrowOnError>({
url: '/agent/add_sub_recipes',
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers
}
});
};
export const getTools = <ThrowOnError extends boolean = false>(options?: Options<GetToolsData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).get<GetToolsResponse, unknown, ThrowOnError>({
url: '/agent/tools',
+31
View File
@@ -1,5 +1,13 @@
// This file is auto-generated by @hey-api/openapi-ts
export type AddSubRecipesRequest = {
sub_recipes: Array<SubRecipe>;
};
export type AddSubRecipesResponse = {
success: boolean;
};
export type Annotations = {
audience?: Array<Role>;
priority?: number;
@@ -777,6 +785,29 @@ export type UpsertPermissionsQuery = {
tool_permissions: Array<ToolPermission>;
};
export type AddSubRecipesData = {
body: AddSubRecipesRequest;
path?: never;
query?: never;
url: '/agent/add_sub_recipes';
};
export type AddSubRecipesErrors = {
/**
* Unauthorized - invalid secret key
*/
401: unknown;
};
export type AddSubRecipesResponses = {
/**
* added sub recipes to agent successfully
*/
200: AddSubRecipesResponse;
};
export type AddSubRecipesResponse2 = AddSubRecipesResponses[keyof AddSubRecipesResponses];
export type GetToolsData = {
body?: never;
path?: never;
-1
View File
@@ -197,7 +197,6 @@ if (process.platform === 'win32') {
const protocolUrl = commandLine.find((arg) => arg.startsWith('goose://'));
if (protocolUrl) {
const parsedUrl = new URL(protocolUrl);
// If it's a bot/recipe URL, handle it directly by creating a new window
if (parsedUrl.hostname === 'bot' || parsedUrl.hostname === 'recipe') {
app.whenReady().then(async () => {
@@ -0,0 +1,10 @@
import { addSubRecipes, SubRecipe } from '../api';
export async function addSubRecipesToAgent(subRecipes: SubRecipe[]) {
const add_sub_recipe_response = await addSubRecipes({ body: { sub_recipes: subRecipes } });
if (add_sub_recipe_response.error) {
console.warn(`Failed to add sub recipes: ${add_sub_recipe_response.error}`);
} else {
console.log('Added sub recipes');
}
}
+36 -13
View File
@@ -10,7 +10,13 @@ import { extractExtensionConfig } from '../components/settings/extensions/utils'
import type { ExtensionConfig, FixedExtensionEntry } from '../components/ConfigContext';
// TODO: remove when removing migration logic
import { toastService } from '../toasts';
import { ExtensionQuery, addExtension as apiAddExtension } from '../api';
import {
ExtensionQuery,
RecipeParameter,
SubRecipe,
addExtension as apiAddExtension,
} from '../api';
import { addSubRecipesToAgent } from '../recipe/add_sub_recipe_on_agent';
export interface Provider {
id: string; // Lowercase key (e.g., "openai")
@@ -71,15 +77,19 @@ const substituteParameters = (text: string, params: Record<string, string>): str
*/
export const updateSystemPromptWithParameters = async (
recipeParameters: Record<string, string>,
recipeConfig?: { instructions?: string | null }
recipeConfig?: {
instructions?: string | null;
sub_recipes?: SubRecipe[] | null;
parameters?: RecipeParameter[] | null;
}
): Promise<void> => {
const subRecipes = recipeConfig?.sub_recipes;
try {
const originalInstructions = recipeConfig?.instructions;
if (!originalInstructions) {
return;
}
// Substitute parameters in the instructions
const substitutedInstructions = substituteParameters(originalInstructions, recipeParameters);
@@ -103,6 +113,16 @@ export const updateSystemPromptWithParameters = async (
} catch (error) {
console.error('Error updating system prompt with parameters:', error);
}
if (subRecipes && subRecipes?.length > 0) {
for (const subRecipe of subRecipes) {
if (subRecipe.values) {
for (const key in subRecipe.values) {
subRecipe.values[key] = substituteParameters(subRecipe.values[key], recipeParameters);
}
}
}
await addSubRecipesToAgent(subRecipes);
}
};
/**
@@ -192,9 +212,16 @@ export const initializeSystem = async (
// Get recipeConfig directly here
const recipeConfig = window.appConfig?.get?.('recipe');
const botPrompt = (recipeConfig as { instructions?: string })?.instructions;
const recipe_instructions = (recipeConfig as { instructions?: string })?.instructions;
const responseConfig = (recipeConfig as { response?: { json_schema?: unknown } })?.response;
const subRecipes = (recipeConfig as { sub_recipes?: SubRecipe[] })?.sub_recipes;
const parameters = (recipeConfig as { parameters?: RecipeParameter[] })?.parameters;
const hasParameters = parameters && parameters?.length > 0;
const hasSubRecipes = subRecipes && subRecipes?.length > 0;
let prompt = desktopPrompt;
if (!hasParameters && recipe_instructions) {
prompt = `${desktopPromptBot}\nIMPORTANT instructions for you to operate as agent:\n${recipe_instructions}`;
}
// Extend the system prompt with desktop-specific information
const response = await fetch(getApiUrl('/agent/prompt'), {
method: 'POST',
@@ -203,21 +230,17 @@ export const initializeSystem = async (
'X-Secret-Key': getSecretKey(),
},
body: JSON.stringify({
extension: botPrompt
? `${desktopPromptBot}\nIMPORTANT instructions for you to operate as agent:\n${botPrompt}`
: desktopPrompt,
extension: prompt,
}),
});
if (!response.ok) {
console.warn(`Failed to extend system prompt: ${response.statusText}`);
} else {
console.log('Extended system prompt with desktop-specific information');
if (botPrompt) {
console.log('Added custom bot prompt to system prompt');
}
}
if (!hasParameters && hasSubRecipes) {
await addSubRecipesToAgent(subRecipes);
}
// Configure session with response config if present
if (responseConfig?.json_schema) {
const sessionConfigResponse = await fetch(getApiUrl('/agent/session_config'), {