Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ts/packages/aiclient/src/restClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { success, error, Result } from "typechat";
import registerDebug from "debug";

const debugUrl = registerDebug("typeagent:rest:url");
const debugHeader = registerDebug("typeagent:rest:header");

/**
Expand Down Expand Up @@ -255,6 +256,7 @@ async function fetchWithTimeout(
options?: RequestInit,
timeoutMs?: number,
): Promise<Response> {
debugUrl(url);
if (!timeoutMs || timeoutMs <= 0) {
return fetch(url, options);
}
Expand Down
8 changes: 6 additions & 2 deletions ts/packages/cache/src/cache/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class AgentCache {
}>;

private readonly logger: Logger | undefined;
public model?: string;
constructor(
public readonly explainerName: string,
private readonly getExplainerForTranslator: ExplainerFactory,
Expand Down Expand Up @@ -107,7 +108,10 @@ export class AgentCache {
}

private getExplainerForActions(actions: Actions) {
return this.getExplainerForTranslator(actions.action?.translatorName);
return this.getExplainerForTranslator(
actions.action?.translatorName,
this.model,
);
}

private async queueTask(
Expand Down Expand Up @@ -238,7 +242,7 @@ export class AgentCache {
}
}

public async correctExplaination(
public async correctExplanation(
requestAction: RequestAction,
explanation: object,
correction: string,
Expand Down
2 changes: 1 addition & 1 deletion ts/packages/cache/src/cache/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export class AgentCacheFactory {
const customFactory = this.getCustomExplainerFactory?.(explainerName);
const cache = new Map<string | undefined, GenericExplainer>();
const factory = (translator: string | undefined, model?: string) => {
const existing = cache.get(translator);
const existing = cache.get(`${translator ?? ""}|${model ?? ""}`);
if (existing) {
return existing;
}
Expand Down
1 change: 0 additions & 1 deletion ts/packages/commonUtils/src/jsonTranslator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ export function createJsonTranslatorFromSchemaDef<T extends object>(
constraintsValidator?: TypeChatConstraintsValidator<T>, // Optional
instructions?: PromptSection[],
model?: string | TypeChatLanguageModel, // optional
enableStreaming?: boolean,
) {
if (typeof model !== "object") {
model = ai.createChatModel(model, {
Expand Down
18 changes: 17 additions & 1 deletion ts/packages/dispatcher/src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,9 +287,25 @@ export function getSettingSummary(context: CommandHandlerContext) {
).values(),
);
prompt.push(" [", translators.join(""));
if (context.session.getConfig().models.translator !== "") {
prompt.push(
` (model: ${context.session.getConfig().models.translator})`,
);
}
if (context.agentCache.explainerName !== getDefaultExplainerName()) {
prompt.push(` (explainer: ${context.agentCache.explainerName})`);
prompt.push(` (explainer: ${context.agentCache.explainerName}`);
if (context.session.getConfig().models.explainer !== "") {
prompt.push(
` model: ${context.session.getConfig().models.translator}`,
);
}
prompt.push(")");
} else if (context.session.getConfig().models.explainer !== "") {
prompt.push(
` (explainer model: ${context.session.getConfig().models.explainer})`,
);
}

prompt.push("]");

return prompt.join("");
Expand Down
35 changes: 21 additions & 14 deletions ts/packages/dispatcher/src/handlers/common/commandHandlerContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export function getTranslator(
const config = context.session.getConfig();
const newTranslator = loadAgentJsonTranslator(
translatorName,
undefined,
config.models.translator,
config.switch.inline ? config.translators : undefined,
config.multipleActions,
);
Expand Down Expand Up @@ -276,6 +276,7 @@ export async function changeContextConfig(

if (
changed.translators ||
changed.models?.translator !== undefined ||
changed.switch?.inline ||
changed.multipleActions
) {
Expand Down Expand Up @@ -311,22 +312,28 @@ export async function changeContextConfig(

// cache and auto save are handled separately
if (changed.cache !== undefined) {
// the cache state is changed. Auto save is configured in configAgentCache as well.
// the cache state is changed.
// Auto save and model is configured in configAgentCache as well.
await configAgentCache(context.session, context.agentCache);
} else if (changed.autoSave !== undefined) {
// Make sure the cache has a file for a persisted session
if (changed.autoSave) {
if (context.session.cache) {
const cacheDataFilePath =
await context.session.ensureCacheDataFilePath();
await context.agentCache.constructionStore.save(
cacheDataFilePath,
);
} else {
if (changed.autoSave !== undefined) {
// Make sure the cache has a file for a persisted session
if (changed.autoSave) {
if (context.session.cache) {
const cacheDataFilePath =
await context.session.ensureCacheDataFilePath();
await context.agentCache.constructionStore.save(
cacheDataFilePath,
);
}
}
await context.agentCache.constructionStore.setAutoSave(
changed.autoSave,
);
}
if (changed.models?.explainer !== undefined) {
context.agentCache.model = changed.models.explainer;
}
await context.agentCache.constructionStore.setAutoSave(
changed.autoSave,
);
}

return changed;
Expand Down
187 changes: 140 additions & 47 deletions ts/packages/dispatcher/src/handlers/configCommandHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import { getServiceHostCommandHandlers } from "./serviceHost/serviceHostCommandH
import { getLocalWhisperCommandHandlers } from "./serviceHost/localWhisperCommandHandler.js";

import { parseRequestArgs } from "../utils/args.js";
import { simpleStarRegex } from "common-utils";
import { getChatModelNames, simpleStarRegex } from "common-utils";
import { openai as ai } from "aiclient";
import { SessionConfig } from "../session/session.js";
import chalk from "chalk";

function parseToggleTranslatorName(args: string[], action: boolean) {
const options: any = {};
Expand Down Expand Up @@ -69,68 +72,66 @@ function parseToggleTranslatorName(args: string[], action: boolean) {
return options;
}

class TranslatorCommandHandler implements CommandHandler {
public description = "Toggle translators";
public async run(request: string, context: CommandHandlerContext) {
const { args } = parseRequestArgs(request);
if (args.length < 1) {
context.requestIO.warn((log) => {
log("Usage: @config translator [-]<translator>]");
const translators = getTranslatorNames().join(", ");
log(` <translator>: ${translators}`);
});
return;
}
const enum AgentToggle {
Translator,
Action,
Agent,
}

const options = parseToggleTranslatorName(args, false);
const changed = await changeContextConfig(
{ translators: options },
context,
);
const AgentToggleDescription = [
"agent translators",
"agent actions",
"agents",
] as const;

const translators = changed.translators;
if (translators) {
context.requestIO.result((log) => {
log("Changes:");
for (const [name, value] of Object.entries(translators)) {
log(` ${name}: ${value ? "enabled" : "disabled"}`);
}
});
} else {
context.requestIO.warn("No change");
}
const AgentToggleCommand = ["translator", "action", "agent"] as const;

function getAgentToggleOptions(toggle: AgentToggle, options: any) {
switch (toggle) {
case AgentToggle.Translator:
return { translators: options };
case AgentToggle.Action:
return { actions: options };
case AgentToggle.Agent:
return { translators: options, actions: options };
}
}

class ActionCommandHandler implements CommandHandler {
public description = "Toggle translator actions";
class AgentToggleCommandHandler implements CommandHandler {
public description = `Toggle ${AgentToggleDescription[this.toggle]}`;
constructor(private toggle: AgentToggle) {}

public async run(request: string, context: CommandHandlerContext) {
const { args } = parseRequestArgs(request);
if (args.length < 1) {
context.requestIO.warn((log) => {
log("Usage: @config action [-]<translator>]");
log(
`Usage: @config ${AgentToggleCommand[this.toggle]} [-]<agent>]`,
);
const translators = getTranslatorNames().join(", ");
log(` <translator>: ${translators}`);
log(` <agent>: ${translators}`);
});
return;
}

const options = parseToggleTranslatorName(args, false);
const changed = await changeContextConfig(
{ actions: options },
getAgentToggleOptions(this.toggle, options),
context,
);

const actions = changed.actions;
if (actions) {
context.requestIO.result((log) => {
log("Changes:");
for (const [name, value] of Object.entries(actions)) {
log(` ${name}: ${value ? "enabled" : "disabled"}`);
}
});
} else {
const changedEntries = Object.entries(changed);
if (changedEntries.length === 0) {
context.requestIO.warn("No change");
} else {
const lines: string[] = [];
for (const [kind, options] of Object.entries(changed)) {
lines.push(`Changes (${kind}):`);
for (const [name, value] of Object.entries(options as any)) {
lines.push(` ${name}: ${value ? "enabled" : "disabled"}`);
}
}
context.requestIO.result(lines.join("\n"));
}
}
}
Expand All @@ -157,13 +158,106 @@ class ExplainerCommandHandler implements CommandHandler {
}
}

function getConfigModel(models: SessionConfig["models"], kind: string) {
if (!models.hasOwnProperty(kind)) {
throw new Error(
`Invalid model kind: ${kind}\nValid model kinds: ${Object.keys(models).join(", ")}`,
);
}
const model = models[kind as keyof typeof models];
const settings = ai.getChatModelSettings(model);
return `Current ${chalk.cyan(kind)} model: ${model ? model : "(default)"}\nURL:${settings.endpoint}`;
}

class ConfigModelShowCommandHandler implements CommandHandler {
public readonly description = "Show current model";
public async run(request: string, context: CommandHandlerContext) {
const models = context.session.getConfig().models;
const { args } = parseRequestArgs(request);
if (args.length > 1) {
throw new Error("Too many arguments.");
}
if (args.length === 1) {
context.requestIO.result(getConfigModel(models, args[0]));
} else {
context.requestIO.result(
Object.keys(models)
.map((kind) => getConfigModel(models, kind))
.join("\n"),
);
}
}
}

class ConfigModelSetCommandHandler implements CommandHandler {
public readonly description = "Set model";
public async run(request: string, context: CommandHandlerContext) {
const { args } = parseRequestArgs(request);
const models = context.session.getConfig().models;
if (args.length === 0) {
const newConfig = {
models: Object.fromEntries(
Object.keys(models).map((kind) => [kind, ""]),
),
};
await changeContextConfig(newConfig, context);
context.requestIO.result(`Reset to default model for all`);
return;
}

let kind = "translation";
let model = "";
if (args.length === 1) {
if (models.hasOwnProperty(args[0])) {
kind = args[0];
} else {
model = args[0];
}
} else {
kind = args[0];
model = args[1];
}

if (!models.hasOwnProperty(kind)) {
throw new Error(
`Invalid model kind: ${kind}\nValid model kinds: ${Object.keys(models).join(", ")}`,
);
}
const modelNames = getChatModelNames();
if (model === "") {
context.requestIO.result(`Reset to default model for ${kind}`);
} else if (!modelNames.includes(model)) {
context.requestIO.error(
`Invalid model name: ${model}\nValid model names: ${modelNames.join(", ")}`,
);
return;
}
await changeContextConfig(
{
models: {
[kind]: model,
},
},
context,
);
}
}

export function getConfigCommandHandlers(): HandlerTable {
return {
description: "Configuration commands",
defaultSubCommand: undefined,
commands: {
translator: new TranslatorCommandHandler(),
action: new ActionCommandHandler(),
translator: new AgentToggleCommandHandler(AgentToggle.Translator),
action: new AgentToggleCommandHandler(AgentToggle.Action),
agent: new AgentToggleCommandHandler(AgentToggle.Agent),
model: {
description: "Configure model",
defaultSubCommand: new ConfigModelShowCommandHandler(),
commands: {
show: new ConfigModelShowCommandHandler(),
set: new ConfigModelSetCommandHandler(),
},
},
multi: getToggleHandlerTable(
"multiple action translation",
async (context, enable: boolean) => {
Expand All @@ -175,7 +269,6 @@ export function getConfigCommandHandlers(): HandlerTable {
),
switch: {
description: "auto switch translator",
defaultSubCommand: undefined,
commands: {
...getToggleCommandHandlers(
"switch translator",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class CorrectCommandHandler implements CommandHandler {
if (context.lastExplanation === undefined) {
throw new Error("No last explanation to correct");
}
const result = await context.agentCache.correctExplaination(
const result = await context.agentCache.correctExplanation(
context.lastRequestAction,
context.lastExplanation,
input,
Expand Down
Loading