mirror of
https://github.com/hanzoai/extension.git
synced 2026-10-31 21:57:06 +00:00
Office, Outlook, PDF, Clio, Meetings, Google Workspace and Salesforce defaulted to zen-1, Teams offered zen-eco-3b, zen-mini-8b and zen-4b, and JetBrains defaulted to claude-3-5-sonnet-20241022 with a fallback list of retired upstream ids. None of those are in api.hanzo.ai/v1/models, so a first request on each of them named a model the gateway does not serve. zen5 is the id the catalog itself marks as the default: catalog.hanzo.ai /v1/pricing lists it as "Zen5 (Default)", "the everyday Zen5 chat model", and nineteen other surfaces here already defaulted to it. Teams now offers the catalog's Zen 5 family with zen5 first. JetBrains preselects zen5 when the live list carries it, and offers only zen5 when it cannot load the list, rather than a fabricated one. Claude-Session: https://claude.ai/code/session_01Dc8DXc3fEQCRHUa6XWK4Ku
107 lines
3.7 KiB
TypeScript
107 lines
3.7 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { ActionId, PROMPT_INPUT_ID } from '@hanzo/cards';
|
|
import {
|
|
dispatch,
|
|
selectedModel,
|
|
promptText,
|
|
type SubmitData,
|
|
} from '../src/dispatch';
|
|
|
|
// Build a submit payload the way an Adaptive Card returns one: `data.action`
|
|
// plus the input fields keyed by their card ids.
|
|
function submit(action: string, extra: SubmitData = {}): SubmitData {
|
|
return { action, ...extra };
|
|
}
|
|
|
|
describe('selectedModel / promptText', () => {
|
|
it('reads the model picker value by ActionId.ModelSelect', () => {
|
|
expect(selectedModel({ [ActionId.ModelSelect]: 'zen5' })).toBe('zen5');
|
|
expect(selectedModel({})).toBeUndefined();
|
|
expect(selectedModel({ [ActionId.ModelSelect]: '' })).toBeUndefined();
|
|
});
|
|
|
|
it('reads and trims the prompt input by PROMPT_INPUT_ID', () => {
|
|
expect(promptText({ [PROMPT_INPUT_ID]: ' hi ' })).toBe('hi');
|
|
expect(promptText({ [PROMPT_INPUT_ID]: ' ' })).toBeUndefined();
|
|
expect(promptText({})).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
describe('dispatch', () => {
|
|
it('routes the sign-in action', () => {
|
|
expect(dispatch(submit(ActionId.SignIn))).toEqual({ kind: 'sign_in' });
|
|
});
|
|
|
|
it('routes a model select carrying the picker value', () => {
|
|
const data = submit(ActionId.ModelSelect, { [ActionId.ModelSelect]: 'zen5-mini' });
|
|
expect(dispatch(data)).toEqual({ kind: 'model_select', model: 'zen5-mini' });
|
|
});
|
|
|
|
it('treats a model select with no value as unknown', () => {
|
|
expect(dispatch(submit(ActionId.ModelSelect))).toEqual({
|
|
kind: 'unknown',
|
|
action: ActionId.ModelSelect,
|
|
});
|
|
});
|
|
|
|
it('routes a prompt submit with the input text and selected model', () => {
|
|
const data = submit(ActionId.PromptSubmit, {
|
|
[PROMPT_INPUT_ID]: 'Explain OIDC',
|
|
[ActionId.ModelSelect]: 'zen5',
|
|
});
|
|
expect(dispatch(data)).toEqual({
|
|
kind: 'prompt',
|
|
prompt: 'Explain OIDC',
|
|
model: 'zen5',
|
|
});
|
|
});
|
|
|
|
it('routes a prompt submit without a model when none selected', () => {
|
|
const data = submit(ActionId.PromptSubmit, { [PROMPT_INPUT_ID]: 'hello' });
|
|
expect(dispatch(data)).toEqual({ kind: 'prompt', prompt: 'hello' });
|
|
});
|
|
|
|
it('treats an empty prompt submit as unknown', () => {
|
|
const data = submit(ActionId.PromptSubmit, { [PROMPT_INPUT_ID]: ' ' });
|
|
expect(dispatch(data)).toEqual({ kind: 'unknown', action: ActionId.PromptSubmit });
|
|
});
|
|
|
|
it('routes a quick action from the prefixed action id and chip field', () => {
|
|
// @hanzo/cards emits `hanzo_quick_action:<chip>` with data.chip = <chip>.
|
|
const action = `${ActionId.QuickAction}:summarize`;
|
|
const data = submit(action, { chip: 'summarize' });
|
|
expect(dispatch(data)).toEqual({ kind: 'quick_action', chip: 'summarize' });
|
|
});
|
|
|
|
it('derives the chip from the action suffix when data.chip is absent', () => {
|
|
const action = `${ActionId.QuickAction}:draft`;
|
|
expect(dispatch(submit(action))).toEqual({ kind: 'quick_action', chip: 'draft' });
|
|
});
|
|
|
|
it('carries the prompt and model along with a quick action', () => {
|
|
const action = `${ActionId.QuickAction}:action_items`;
|
|
const data = submit(action, {
|
|
chip: 'action_items',
|
|
[PROMPT_INPUT_ID]: 'focus on blockers',
|
|
[ActionId.ModelSelect]: 'zen5-flash',
|
|
});
|
|
expect(dispatch(data)).toEqual({
|
|
kind: 'quick_action',
|
|
chip: 'action_items',
|
|
prompt: 'focus on blockers',
|
|
model: 'zen5-flash',
|
|
});
|
|
});
|
|
|
|
it('returns unknown for an unrecognized action', () => {
|
|
expect(dispatch(submit('something_else'))).toEqual({
|
|
kind: 'unknown',
|
|
action: 'something_else',
|
|
});
|
|
});
|
|
|
|
it('returns unknown with no action for an empty payload', () => {
|
|
expect(dispatch({})).toEqual({ kind: 'unknown' });
|
|
});
|
|
});
|