Skip to content

Commit

Permalink
Combine all schema when all agent switching methods are off (#769)
Browse files Browse the repository at this point in the history
- If embedding, inline and search switching are off, we will try to
combine all the active schema into one single prompt.
- For now, we will error out if there are type name or action name that
conflicts between the schemas.
- Require the translator keep track of the `actionName` -> `schemaName`
mapping. The steps to translate the request will keep track of the
translator the action is from so that it can resolve the schema name
after finalizing. (This will allow us to do mix and match later).

Additionally:
- Refactor TypeAgentTranslator construction to be more flexible by
passing in the inject/switch action config instead of the state to
compute it internally.
- Skip the translation optimization of using embedding to choose a
subset of action to prompt first when we retry the same schema during
the translation in the case where LLM want to look at other actions from
the same schema, removing the need to do an explicit pass without
optimization on multiple actions.
- Fix the @ command error output to use the default color instead of
black which could lead to "black on black".
  • Loading branch information
curtisman authored Mar 1, 2025
1 parent 75c60f9 commit 6af59f7
Show file tree
Hide file tree
Showing 19 changed files with 388 additions and 336 deletions.
4 changes: 2 additions & 2 deletions ts/packages/commonUtils/src/jsonTranslator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ export function createJsonTranslatorFromSchemaDef<T extends object>(

export interface TypeAgentJsonValidator<T extends object>
extends TypeChatJsonValidator<T> {
getSchemaText: () => string;
getTypeName: () => string;
getSchemaText(): string;
getTypeName(): string;
validate(jsonObject: object): Result<T>;
getJsonSchema?: () => CompletionJsonSchema | undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function createActionConfigProvider(
return config;
},
getActionConfigs() {
return Object.entries(actionConfigs);
return Object.values(actionConfigs);
},
getActionSchemaFileForConfig(actionConfig: ActionConfig) {
return actionSchemaFileCache.getActionSchemaFile(actionConfig);
Expand All @@ -64,5 +64,7 @@ export async function createActionConfigProvider(
export function getSchemaNamesForActionConfigProvider(
provider: ActionConfigProvider,
): string[] {
return provider.getActionConfigs().map(([name]) => name);
return provider
.getActionConfigs()
.map((actionConfig) => actionConfig.schemaName);
}
4 changes: 2 additions & 2 deletions ts/packages/dispatcher/src/command/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ async function parseCommand(
} catch (e: any) {
const command = getParsedCommand(result);
throw new Error(
`${e.message}\n\n${chalk.black(getUsage(command, result.descriptor))}`,
`${e.message}\n\n${chalk.reset(getUsage(command, result.descriptor))}`,
);
}
}
Expand All @@ -219,7 +219,7 @@ async function parseCommand(
: `'${result.suffix}' is not a subcommand for '@${command}'.`;

throw new Error(
`${message}\n\n${chalk.black(getHandlerTableUsage(result.table, command, context))}`,
`${message}\n\n${chalk.reset(getHandlerTableUsage(result.table, command, context))}`,
);
}

Expand Down
7 changes: 5 additions & 2 deletions ts/packages/dispatcher/src/command/handlerUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@

import { ActionContext } from "@typeagent/agent-sdk";
import { CommandHandlerContext } from "../context/commandHandlerContext.js";
import { CommandHandlerTable } from "@typeagent/agent-sdk/helpers/command";
import {
CommandHandlerNoParams,
CommandHandlerTable,
} from "@typeagent/agent-sdk/helpers/command";
import { displaySuccess } from "@typeagent/agent-sdk/helpers/display";

export function getToggleCommandHandlers(
Expand All @@ -12,7 +15,7 @@ export function getToggleCommandHandlers(
context: ActionContext<CommandHandlerContext>,
enable: boolean,
) => Promise<void>,
) {
): Record<string, CommandHandlerNoParams> {
return {
on: {
description: `Turn on ${name}`,
Expand Down
6 changes: 1 addition & 5 deletions ts/packages/dispatcher/src/context/appAgentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,7 @@ export class AppAgentManager implements ActionConfigProvider {
return Array.from(this.actionConfigs.keys());
}
public getActionConfigs() {
return Array.from(this.actionConfigs.entries());
}

public getInjectedSchemaForActionName(actionName: string) {
return this.injectedSchemaForActionName.get(actionName);
return Array.from(this.actionConfigs.values());
}

public getAppAgent(appAgentName: string): AppAgent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const debugExplain = registerDebug("typeagent:explain");

async function canTranslateWithoutContext(
requestAction: RequestAction,
usedTranslators: Map<string, TypeAgentTranslator<object>>,
usedTranslators: Map<string, TypeAgentTranslator>,
logger?: Logger,
) {
if (requestAction.history === undefined) {
Expand All @@ -60,15 +60,15 @@ async function canTranslateWithoutContext(
if (!result.success) {
throw new Error("Failed to translate without history context");
}
const newActions = result.data as TranslatedAction;
const newActions = result.data;
const count = isMultipleAction(newActions)
? newActions.parameters.requests.length
: 1;

if (count !== oldActions.length) {
throw new Error("Action count mismatch without context");
}
translations.set(translatorName, result.data as TranslatedAction);
translations.set(translatorName, result.data);
}

let index = 0;
Expand All @@ -85,8 +85,17 @@ async function canTranslateWithoutContext(
} else {
newAction = newTranslatedActions;
}
const schemaName = usedTranslators
.get(translatorName)!
.getSchemaName(newAction.actionName);
if (schemaName === undefined) {
// Should not happen
throw new Error(
`Internal Error: Unable to match schema name for action '${newAction.actionName}'`,
);
}
newActions.push({
translatorName,
translatorName: schemaName,
...newAction,
});
}
Expand Down Expand Up @@ -156,7 +165,7 @@ function getExplainerOptions(
}

if (hasAdditionalInstructions(requestAction.history)) {
// Translation with additional instructions are not cachable.
// Translation with additional instructions are not cacheable.
return undefined;
}

Expand All @@ -168,7 +177,7 @@ function getExplainerOptions(
return undefined;
}

const usedTranslators = new Map<string, TypeAgentTranslator<object>>();
const usedTranslators = new Map<string, TypeAgentTranslator>();
const actions = requestAction.actions;
for (const { action } of actions) {
if (isUnknownAction(action)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ export async function executeHistoryAction(
) {
const historyAction = action as HistoryAction;
switch (historyAction.actionName) {
case "delete":
case "deleteHistory":
const deleteAction = historyAction as DeleteHistoryAction;
await processCommandNoLock(
`@history delete ${deleteAction.parameters.messageNumber}`,
context.sessionContext.agentContext,
);
break;
case "clear":
case "clearHistory":
await processCommandNoLock(
`@history clear`,
context.sessionContext.agentContext,
);
break;
case "list":
case "listHistory":
await processCommandNoLock(
`@history list`,
context.sessionContext.agentContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,20 @@ export async function executeNotificationAction(
) {
const notificationAction = action as NotificationAction;
switch (notificationAction.actionName) {
case "show":
case "showNotifications":
const showAction = notificationAction as ShowNotificationsAction;
await processCommandNoLock(
`@notify show ${showAction.parameters.filter}`,
context.sessionContext.agentContext,
);
break;
case "summary":
case "showNotificationSummary":
await processCommandNoLock(
`@notify info`,
context.sessionContext.agentContext,
);
break;
case "clear":
case "clearNotifications":
await processCommandNoLock(
`@notify clear`,
context.sessionContext.agentContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,24 @@ export async function executeSessionAction(
context: ActionContext<CommandHandlerContext>,
) {
switch (action.actionName) {
case "new":
case "newSession":
await processCommandNoLock(
`@session new ${action.parameters.name ?? ""}`,
context.sessionContext.agentContext,
);
break;
case "list":
case "listSession":
await processCommandNoLock(
"@session list",
context.sessionContext.agentContext,
);
break;
case "showInfo":
case "showSessionInfo":
await processCommandNoLock(
"@session info",
context.sessionContext.agentContext,
);
break;
case "toggleHistory":
await processCommandNoLock(
`@session history ${action.parameters.enable ? "on" : "off"}`,
context.sessionContext.agentContext,
);
break;
default:
throw new Error(
`Invalid action name: ${(action as TypeAgentAction).actionName}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ const configTranslationCommandHandlers: CommandHandlerTable = {
},
),
search: getToggleHandlerTable(
"inject inline switch",
"search switch",
async (context, enable: boolean) => {
await changeContextConfig(
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ export type HistoryAction =

// Shows the chat history
export type ListHistoryAction = {
actionName: "list";
actionName: "listHistory";
};

// Clears the chat history
export type ClearHistoryAction = {
actionName: "clear";
actionName: "clearHistory";
};

// Deletes a specific message from the chat history
export type DeleteHistoryAction = {
actionName: "delete";
actionName: "deleteHistory";
parameters: {
messageNumber: number;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type NotificationAction =

// Shows notifications based on the supplied filter
export type ShowNotificationsAction = {
actionName: "show";
actionName: "showNotifications";
parameters: {
filter: NotificationFilter;
};
Expand All @@ -18,10 +18,10 @@ export type NotificationFilter = "all" | "unread";

// Shows notification summary
export type ShowNotificationSummaryAction = {
actionName: "summary";
actionName: "showNotificationSummary";
};

// Clears the notifications
export type ClearNotificationsAction = {
actionName: "clear";
actionName: "clearNotifications";
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,24 @@
// Licensed under the MIT License.

export type SessionAction =
| NewAction
| ListAction
| ShowInfoAction
| ToggleHistoryAction;
| NewSessionAction
| ListSessionAction
| ShowSessionInfoAction;

// Create a new session.
export type NewAction = {
actionName: "new";
export type NewSessionAction = {
actionName: "newSession";
parameters: {
name?: string;
};
};

// List all sessions.
export type ListAction = {
actionName: "list";
export type ListSessionAction = {
actionName: "listSession";
};

// Show information about a session.
export type ShowInfoAction = {
actionName: "showInfo";
};

// Toggle history flag for the session.
export type ToggleHistoryAction = {
actionName: "toggleHistory";
parameters: {
enable: boolean;
};
export type ShowSessionInfoAction = {
actionName: "showSessionInfo";
};
5 changes: 1 addition & 4 deletions ts/packages/dispatcher/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ export { getAssistantSelectionSchemas } from "./translation/unknownSwitcher.js";
export { getActionSchema } from "./translation/actionSchemaFileCache.js";
export { getFullSchemaText } from "./translation/agentTranslators.js";

export {
loadAgentJsonTranslator,
getAppAgentName,
} from "./translation/agentTranslators.js";
export { getAppAgentName } from "./translation/agentTranslators.js";
export { createSchemaInfoProvider } from "./translation/actionSchemaFileCache.js";
export {
createActionConfigProvider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ import { ActionConfig } from "./actionConfig.js";
export interface ActionConfigProvider {
tryGetActionConfig(schemaName: string): ActionConfig | undefined;
getActionConfig(schemaName: string): ActionConfig;
getActionConfigs(): [string, ActionConfig][];
getActionConfigs(): ActionConfig[];
getActionSchemaFileForConfig(config: ActionConfig): ActionSchemaFile;
}
Loading

0 comments on commit 6af59f7

Please sign in to comment.