Skip to content

Commit

Permalink
CLI schema switch allow subschema granularity. (#795)
Browse files Browse the repository at this point in the history
  • Loading branch information
curtisman authored Mar 7, 2025
1 parent c0b5d91 commit e2470db
Show file tree
Hide file tree
Showing 15 changed files with 85 additions and 72 deletions.
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/data/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
getEmptyExplanationTestData,
getCacheFactory,
createActionConfigProvider,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { getInstanceDir } from "agent-dispatcher/helpers/data";
import chalk from "chalk";
Expand All @@ -25,7 +25,7 @@ const modelNames = await getChatModelNames();
const provider = await createActionConfigProvider(
getDefaultAppAgentProviders(getInstanceDir()),
);
const schemaNames = getSchemaNamesForActionConfigProvider(provider);
const schemaNames = getAllSchemaNames(provider);
export default class ExplanationDataAddCommand extends Command {
static args = {
request: Args.string({
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/data/stat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { CorrectionRecord } from "agent-cache";
import {
getCacheFactory,
readExplanationTestData,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
createActionConfigProvider,
} from "agent-dispatcher/internal";
import { getInstanceDir } from "agent-dispatcher/helpers/data";
Expand Down Expand Up @@ -142,7 +142,7 @@ function printStats(
console.log();
}

const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(
getDefaultAppAgentProviders(getInstanceDir()),
),
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/interactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createDispatcher, Dispatcher } from "agent-dispatcher";
import {
createActionConfigProvider,
getCacheFactory,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { getClientId, getInstanceDir } from "agent-dispatcher/helpers/data";
import {
Expand All @@ -24,7 +24,7 @@ import {
const modelNames = await getChatModelNames();
const instanceDir = getInstanceDir();
const defaultAppAgentProviders = getDefaultAppAgentProviders(instanceDir);
const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(defaultAppAgentProviders),
);
export default class Interactive extends Command {
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/run/explain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { RequestAction, fromJsonActions } from "agent-cache";
import {
createActionConfigProvider,
getCacheFactory,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { getClientId, getInstanceDir } from "agent-dispatcher/helpers/data";
import { getDefaultAppAgentProviders } from "default-agent-provider";
Expand All @@ -28,7 +28,7 @@ const testRequest = new RequestAction(

const instanceDir = getInstanceDir();
const defaultAgentProviders = getDefaultAppAgentProviders(instanceDir);
const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(defaultAgentProviders),
);

Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/run/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createDispatcher } from "agent-dispatcher";
import {
createActionConfigProvider,
getCacheFactory,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { getClientId, getInstanceDir } from "agent-dispatcher/helpers/data";
import { getDefaultAppAgentProviders } from "default-agent-provider";
Expand All @@ -17,7 +17,7 @@ import { readFileSync, existsSync } from "fs";
const modelNames = await getChatModelNames();
const instanceDir = getInstanceDir();
const defaultAppAgentProviders = getDefaultAppAgentProviders(instanceDir);
const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(defaultAppAgentProviders),
);
export default class RequestCommand extends Command {
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/run/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { getDefaultAppAgentProviders } from "default-agent-provider";
import { getChatModelNames } from "aiclient";
import {
createActionConfigProvider,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { withConsoleClientIO } from "agent-dispatcher/helpers/console";
import { getClientId, getInstanceDir } from "agent-dispatcher/helpers/data";

const modelNames = await getChatModelNames();
const instanceDir = getInstanceDir();
const defaultAppAgentProviders = getDefaultAppAgentProviders(instanceDir);
const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(defaultAppAgentProviders),
);

Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
getFullSchemaText,
getActionSchema,
createActionConfigProvider,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
} from "agent-dispatcher/internal";
import { getInstanceDir } from "agent-dispatcher/helpers/data";
import { generateSchemaTypeDefinition } from "action-schema";
Expand All @@ -17,7 +17,7 @@ import { getDefaultAppAgentProviders } from "default-agent-provider";
const provider = await createActionConfigProvider(
getDefaultAppAgentProviders(getInstanceDir()),
);
const schemaNames = getSchemaNamesForActionConfigProvider(provider);
const schemaNames = getAllSchemaNames(provider);

export default class Schema extends Command {
static description = "Show schema used by translators";
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/cli/src/commands/test/translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { fromJsonActions, toFullActions, FullAction } from "agent-cache";
import { createDispatcher } from "agent-dispatcher";
import {
readExplanationTestData,
getSchemaNamesForActionConfigProvider,
getAllSchemaNames,
createActionConfigProvider,
} from "agent-dispatcher/internal";
import { getInstanceDir } from "agent-dispatcher/helpers/data";
Expand Down Expand Up @@ -83,7 +83,7 @@ function summarizeResult(result: TestResultFile) {

const modelNames = await getChatModelNames();
const defaultAppAgentProviders = getDefaultAppAgentProviders(getInstanceDir());
const schemaNames = getSchemaNamesForActionConfigProvider(
const schemaNames = getAllSchemaNames(
await createActionConfigProvider(defaultAppAgentProviders),
);
const defaultRepeat = 5;
Expand Down
12 changes: 6 additions & 6 deletions ts/packages/defaultAgentProvider/src/defaultAgentProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import path from "node:path";
import fs from "node:fs";
import { getConfig, AppAgentConfig } from "./utils/config.js";

let builtinAppAgentProvider: AppAgentProvider | undefined;
export function getBuiltinAppAgentProvider(): AppAgentProvider {
if (builtinAppAgentProvider === undefined) {
builtinAppAgentProvider = createNpmAppAgentProvider(
let defaultAppAgentProvider: AppAgentProvider | undefined;
export function getDefaultAppAgentProvider(): AppAgentProvider {
if (defaultAppAgentProvider === undefined) {
defaultAppAgentProvider = createNpmAppAgentProvider(
getConfig().agents,
import.meta.url,
);
}
return builtinAppAgentProvider;
return defaultAppAgentProvider;
}

function getExternalAgentsConfigPath(instanceDir: string): string {
Expand All @@ -40,7 +40,7 @@ function getExternalAppAgentProvider(instanceDir: string): AppAgentProvider {
export function getDefaultAppAgentProviders(
instanceDir: string | undefined,
): AppAgentProvider[] {
const providers = [getBuiltinAppAgentProvider()];
const providers = [getDefaultAppAgentProvider()];
if (instanceDir !== undefined) {
providers.push(getExternalAppAgentProvider(instanceDir));
}
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/defaultAgentProvider/test/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// Licensed under the MIT License.

import { createDispatcher } from "agent-dispatcher";
import { getBuiltinAppAgentProvider } from "../src/defaultAgentProviders.js";
import { getDefaultAppAgentProvider } from "../src/defaultAgentProviders.js";

describe("AppAgentProvider", () => {
describe("Built-in Provider", () => {
it("startup and shutdown", async () => {
const dispatcher = await createDispatcher("test", {
appAgentProviders: [getBuiltinAppAgentProvider()],
appAgentProviders: [getDefaultAppAgentProvider()],
});
await dispatcher.close();
});
Expand Down
30 changes: 14 additions & 16 deletions ts/packages/dispatcher/src/agentProvider/agentProviderUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,32 @@ import { AppAgentManifest } from "@typeagent/agent-sdk";

async function getAppAgentManifests(
providers: AppAgentProvider[],
): Promise<Map<string, AppAgentManifest>> {
const appAgentConfigs = new Map<string, AppAgentManifest>();
): Promise<Record<string, AppAgentManifest>> {
const appAgentManifests: Record<string, AppAgentManifest> = {};
for (const provider of providers) {
for (const name of provider.getAppAgentNames()) {
const manifest = await provider.getAppAgentManifest(name);
appAgentConfigs.set(name, manifest);
appAgentManifests[name] = manifest;
}
}
return appAgentConfigs;
return appAgentManifests;
}

async function getActionConfigs(
providers: AppAgentProvider[],
): Promise<Record<string, ActionConfig>> {
function getActionConfigs(
appAgentManifests: Record<string, AppAgentManifest>,
): Record<string, ActionConfig> {
const configs = {};
const appAgentConfigs = await getAppAgentManifests(providers);
for (const [name, config] of appAgentConfigs.entries()) {
convertToActionConfig(name, config, configs);
for (const [name, manifest] of Object.entries(appAgentManifests)) {
convertToActionConfig(name, manifest, configs);
}
return configs;
}

export async function createActionConfigProvider(
providers: AppAgentProvider[],
): Promise<ActionConfigProvider> {
const actionConfigs = await getActionConfigs(providers);
const appAgentManifests = await getAppAgentManifests(providers);
const actionConfigs = await getActionConfigs(appAgentManifests);
const actionSchemaFileCache = new ActionSchemaFileCache();
const actionConfigProvider: ActionConfigProvider = {
tryGetActionConfig(schemaName: string) {
Expand All @@ -61,10 +61,8 @@ export async function createActionConfigProvider(
return actionConfigProvider;
}

export function getSchemaNamesForActionConfigProvider(
provider: ActionConfigProvider,
export function getSchemaNamesForAppAgentManifests(
appAgentManifests: Record<string, AppAgentManifest>,
): string[] {
return provider
.getActionConfigs()
.map((actionConfig) => actionConfig.schemaName);
return Object.keys(getActionConfigs(appAgentManifests));
}
35 changes: 19 additions & 16 deletions ts/packages/dispatcher/src/context/appAgentManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -693,16 +693,17 @@ export function getAppAgentStateSettings(
}
const result: AppAgentStateSettings = {};
if (typeof settings === "boolean" || Array.isArray(settings)) {
const entries = agents
.getAppAgentNames()
.map((name) => [
for (const key of appAgentStateKeys) {
const names =
key === "commands"
? agents.getAppAgentNames()
: agents.getSchemaNames();
const entries = names.map((name) => [
name,
typeof settings === "boolean"
? settings
: settings.includes(name),
: settings.includes(getAppAgentName(name)),
]);

for (const key of appAgentStateKeys) {
const state = Object.fromEntries(entries);
for (const name of alwaysEnabledAgents[key]) {
if (state[name] === false) {
Expand All @@ -719,16 +720,18 @@ export function getAppAgentStateSettings(
continue;
}
const alwaysEnabled = alwaysEnabledAgents[key];
const entries = agents
.getAppAgentNames()
.map((name) => [
name,
alwaysEnabled.includes(name)
? true
: typeof state === "boolean"
? state
: state.includes(name),
]);
const names =
key === "commands"
? agents.getAppAgentNames()
: agents.getSchemaNames();
const entries = names.map((name) => [
name,
alwaysEnabled.includes(name)
? true
: typeof state === "boolean"
? state
: state.includes(name),
]);
result[key] = Object.fromEntries(entries);
}
return Object.keys(result).length === 0 ? undefined : result;
Expand Down
4 changes: 2 additions & 2 deletions ts/packages/dispatcher/src/context/commandHandlerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import {
import registerDebug from "debug";
import path from "node:path";
import { createSchemaInfoProvider } from "../translation/actionSchemaFileCache.js";
import { createInlineAppAgentProvider } from "./inlineAgentProvider.js";
import { createBuiltinAppAgentProvider } from "./inlineAgentProvider.js";
import { CommandResult } from "../dispatcher.js";
import { DispatcherName } from "./dispatcher/dispatcherUtils.js";
import lockfile from "proper-lockfile";
Expand Down Expand Up @@ -268,7 +268,7 @@ async function addAppAgentProviders(
}
}

const inlineAppProvider = createInlineAppAgentProvider(context);
const inlineAppProvider = createBuiltinAppAgentProvider(context);
await context.agents.addProvider(inlineAppProvider, embeddingCache);

if (appAgentProviders) {
Expand Down
34 changes: 24 additions & 10 deletions ts/packages/dispatcher/src/context/inlineAgentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,28 @@ import {
} from "./dispatcher/dispatcherAgent.js";
import { AppAgentProvider } from "../agentProvider/agentProvider.js";
import { systemAgent, systemManifest } from "./system/systemAgent.js";
import { getSchemaNamesForAppAgentManifests } from "../agentProvider/agentProviderUtils.js";
import { ActionConfigProvider } from "../translation/actionConfigProvider.js";

const inlineHandlers: Record<string, AppAgent> = {
const builtinAgents: Record<string, AppAgent> = {
dispatcher: dispatcherAgent,
system: systemAgent,
};

export const inlineAgentManifests: Record<string, AppAgentManifest> = {
const builtinAgentManifest: Record<string, AppAgentManifest> = {
dispatcher: dispatcherManifest,
system: systemManifest,
};

export function createInlineAppAgentProvider(
context?: CommandHandlerContext,
export function createBuiltinAppAgentProvider(
context: CommandHandlerContext,
): AppAgentProvider {
return {
getAppAgentNames() {
return Object.keys(inlineAgentManifests);
return Object.keys(builtinAgentManifest);
},
async getAppAgentManifest(appAgentName: string) {
const manifest = inlineAgentManifests[appAgentName];
const manifest = builtinAgentManifest[appAgentName];
if (manifest === undefined) {
throw new Error(`Invalid app agent: ${appAgentName}`);
}
Expand All @@ -38,17 +40,29 @@ export function createInlineAppAgentProvider(
if (context === undefined) {
throw new Error("Context is required to load inline agent");
}
const handlers = inlineHandlers[appAgentName];
if (handlers === undefined) {
const agent = builtinAgents[appAgentName];
if (agent === undefined) {
throw new Error(`Invalid app agent: ${appAgentName}`);
}
return { ...handlers, initializeAgentContext: async () => context };
return { ...agent, initializeAgentContext: async () => context };
},
unloadAppAgent(appAgentName: string) {
// Inline agents are always loaded
if (inlineAgentManifests[appAgentName] === undefined) {
if (builtinAgentManifest[appAgentName] === undefined) {
throw new Error(`Invalid app agent: ${appAgentName}`);
}
},
};
}

const builtinSchemaNames =
getSchemaNamesForAppAgentManifests(builtinAgentManifest);

export function getAllSchemaNames(provider: ActionConfigProvider): string[] {
return [
...builtinSchemaNames,
...provider
.getActionConfigs()
.map((actionConfig) => actionConfig.schemaName),
];
}
6 changes: 2 additions & 4 deletions ts/packages/dispatcher/src/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ export { getFullSchemaText } from "./translation/agentTranslators.js";

export { getAppAgentName } from "./translation/agentTranslators.js";
export { createSchemaInfoProvider } from "./translation/actionSchemaFileCache.js";
export {
createActionConfigProvider,
getSchemaNamesForActionConfigProvider,
} from "./agentProvider/agentProviderUtils.js";
export { createActionConfigProvider } from "./agentProvider/agentProviderUtils.js";
export { getAllSchemaNames } from "./context/inlineAgentProvider.js";

export type { ChatHistoryInput } from "./context/system/handlers/historyCommandHandler.js";

0 comments on commit e2470db

Please sign in to comment.