Skip to content

Commit 22a2f3b

Browse files
committed
feat: added rewrite and compose demos
1 parent 58c8c1d commit 22a2f3b

File tree

9 files changed

+1423
-46
lines changed

9 files changed

+1423
-46
lines changed

src/app.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ function configureApiSecurity(app: OpenAPIHono, tokenConfig: string) {
3333
path === '/api/sentiment-demo' ||
3434
path === '/api/keywords-demo' ||
3535
path === '/api/email-reply-demo' ||
36+
path === '/api/rewrite-demo' ||
37+
path === '/api/compose-demo' ||
3638
path === '/api/translate-demo' ||
3739
path === '/api/meeting-notes-demo' ||
3840
path === '/api/asktext-demo' ||
@@ -44,6 +46,8 @@ function configureApiSecurity(app: OpenAPIHono, tokenConfig: string) {
4446
path === '/api/v1/sentiment-demo' ||
4547
path === '/api/v1/keywords-demo' ||
4648
path === '/api/v1/email-reply-demo' ||
49+
path === '/api/v1/rewrite-demo' ||
50+
path === '/api/v1/compose-demo' ||
4751
path === '/api/v1/translate-demo' ||
4852
path === '/api/v1/meeting-notes-demo' ||
4953
path === '/api/v1/asktext-demo' ||

src/config/models.json

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,65 +3,64 @@
33
"ollama": {
44
"enabled": true,
55
"models": [
6-
{ "name": "llama3.2:latest", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply", "translate"], "notes": "Meta Llama 3.2 general-purpose model." },
7-
{ "name": "qwen2.5-coder:latest", "capabilities": ["summarize", "planning", "keywords", "emailReply"], "notes": "Qwen 2.5 coder-optimized variant for code tasks." },
8-
{ "name": "gemma2:2b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply", "meetingNotes"], "notes": "Gemma 2 small variant for lightweight tasks." },
9-
{ "name": "gemma3:4b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply", "askText", "translate", "meetingNotes"], "notes": "Gemma 3 small variant for lightweight tasks with Q&A support." },
10-
{ "name": "qwen2.5:0.5b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 0.5B parameter model for ultra-light workloads." },
11-
{ "name": "qwen2.5:1.5b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 1.5B parameter model; balanced speed/quality." },
12-
{ "name": "qwen2.5:3b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate"], "notes": "Qwen 2.5 3B parameter model for stronger quality." },
13-
{ "name": "qwen2.5:7b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 7B parameter model for higher quality." },
14-
{ "name": "llama3.2:1b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 1B tiny variant for edge/light usage." },
15-
{ "name": "llama3.2:3b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 3B small variant." },
16-
{ "name": "gemma3:270m", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply"], "notes": "Gemma 3 270M instruct tuned; great for ultra-fast summarization on CPU." }
6+
{ "name": "llama3.2:latest", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply", "translate"], "notes": "Meta Llama 3.2 general-purpose model." },
7+
{ "name": "qwen2.5-coder:latest", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "emailReply"], "notes": "Qwen 2.5 coder-optimized variant for code tasks." },
8+
{ "name": "gemma2:2b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply", "meetingNotes"], "notes": "Gemma 2 small variant for lightweight tasks." },
9+
{ "name": "gemma3:4b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply", "askText", "translate", "meetingNotes"], "notes": "Gemma 3 small variant for lightweight tasks with Q&A support." },
10+
{ "name": "qwen2.5:0.5b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 0.5B parameter model for ultra-light workloads." },
11+
{ "name": "qwen2.5:1.5b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 1.5B parameter model; balanced speed/quality." },
12+
{ "name": "qwen2.5:3b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate"], "notes": "Qwen 2.5 3B parameter model for stronger quality." },
13+
{ "name": "qwen2.5:7b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "emailReply"], "notes": "Qwen 2.5 7B parameter model for higher quality." },
14+
{ "name": "llama3.2:1b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 1B tiny variant for edge/light usage." },
15+
{ "name": "llama3.2:3b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 3B small variant." },
16+
{ "name": "gemma3:270m", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply"], "notes": "Gemma 3 270M instruct tuned; great for ultra-fast summarization on CPU." }
1717
]
1818
},
1919
"lmstudio": {
2020
"enabled": true,
2121
"models": [
22-
{ "name": "gemma-3-270m-it", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply"], "notes": "Gemma 3 270M instruct tuned; great for ultra-fast summarization on CPU." },
23-
{ "name": "llama-3.2-3b-instruct", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 3B instruct; strong small model for summarization." }
22+
{ "name": "gemma-3-270m-it", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply"], "notes": "Gemma 3 270M instruct tuned; great for ultra-fast summarization on CPU." },
23+
{ "name": "llama-3.2-3b-instruct", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Llama 3.2 3B instruct; strong small model for summarization." }
2424
]
2525
},
2626
"openai": {
2727
"enabled": true,
2828
"models": [
29-
{ "name": "gpt-4o-mini", "capabilities": ["summarize", "planning", "keywords", "sentiment", "vision", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI multimodal small model with vision support." },
30-
{ "name": "gpt-4.1-nano", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI lightweight model for fast, low-cost text tasks." },
31-
{ "name": "gpt-5-mini", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen mini model with Q&A capabilities." },
32-
{ "name": "gpt-5-nano", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen nano model with Q&A capabilities." },
33-
{ "name": "gpt-5", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen model with Q&A capabilities." },
34-
{ "name": "gpt-4o", "capabilities": ["summarize", "planning", "keywords", "sentiment", "vision", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen vision model with Q&A capabilities." }
29+
{ "name": "gpt-4o-mini", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "vision", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI multimodal small model with vision support." },
30+
{ "name": "gpt-4.1-nano", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI lightweight model for fast, low-cost text tasks." },
31+
{ "name": "gpt-5-mini", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen mini model with Q&A capabilities." },
32+
{ "name": "gpt-5-nano", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen nano model with Q&A capabilities." },
33+
{ "name": "gpt-5", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen model with Q&A capabilities." },
34+
{ "name": "gpt-4o", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "vision", "emailReply", "translate", "meetingNotes"], "notes": "OpenAI next-gen vision model with Q&A capabilities." }
3535
]
3636
},
3737
"openrouter": {
3838
"enabled": true,
3939
"models": [
40-
{ "name": "anthropic/claude-3.5-sonnet", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Claude 3.5 Sonnet via OpenRouter; strong reasoning." },
41-
{ "name": "openai/gpt-4o-mini", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT-4o mini." },
42-
{ "name": "google/gemini-2.0-flash-lite-001", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Google Gemini 2.0 Flash Lite via OpenRouter with Q&A capabilities." },
43-
{ "name": "google/gemini-2.5-flash-lite", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Google Gemini 2.5 Flash Lite via OpenRouter with 1M token context window for large document Q&A." },
44-
{ "name": "openai/gpt-oss-20b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT OSS 20B" },
45-
{ "name": "openai/gpt-oss-120b", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT OSS 120B" }
40+
{ "name": "anthropic/claude-3.5-sonnet", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Claude 3.5 Sonnet via OpenRouter; strong reasoning." },
41+
{ "name": "openai/gpt-4o-mini", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT-4o mini." },
42+
{ "name": "google/gemini-2.0-flash-lite-001", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Google Gemini 2.0 Flash Lite via OpenRouter with Q&A capabilities." },
43+
{ "name": "google/gemini-2.5-flash-lite", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Google Gemini 2.5 Flash Lite via OpenRouter with 1M token context window for large document Q&A." },
44+
{ "name": "openai/gpt-oss-20b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT OSS 20B" },
45+
{ "name": "openai/gpt-oss-120b", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "OpenRouter proxy to GPT OSS 120B" }
4646
]
4747
},
4848
"anthropic": {
4949
"enabled": true,
5050
"models": [
51-
{ "name": "claude-3-haiku-20240307", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Anthropic Claude 3 Haiku; fast and cost-effective with Q&A support." }
51+
{ "name": "claude-3-haiku-20240307", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Anthropic Claude 3 Haiku; fast and cost-effective with Q&A support." }
5252
]
5353
},
5454
"aigateway": {
5555
"enabled": true,
5656
"models": [
57-
{ "name": "openai/gpt-5-nano", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "GPT-5 nano is a high throughput model that excels at simple instruction or classification tasks." },
58-
{ "name": "gemini-2.0-flash-lite-preview-02-05", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Gemini 2.0 Flash Lite Preview 02-05" },
59-
{ "name": "mistral-small-2503", "capabilities": ["summarize", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Mistral Small" }
57+
{ "name": "openai/gpt-5-nano", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "GPT-5 nano is a high throughput model that excels at simple instruction or classification tasks." },
58+
{ "name": "gemini-2.0-flash-lite-preview-02-05", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Gemini 2.0 Flash Lite Preview 02-05" },
59+
{ "name": "mistral-small-2503", "capabilities": ["summarize", "rewrite", "compose", "planning", "keywords", "sentiment", "askText", "emailReply", "translate", "meetingNotes"], "notes": "Mistral Small" }
6060

6161

6262
]
6363
}
6464
}
6565
}
6666

67-

src/config/models.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import * as path from 'path'
33

44
export type ModelCapability =
55
| 'summarize'
6+
| 'rewrite'
7+
| 'compose'
68
| 'keywords'
79
| 'sentiment'
810
| 'planning'
@@ -66,4 +68,3 @@ export function getModelsCatalogByProvider(): Record<string, ProviderModelConfig
6668
return result
6769
}
6870

69-

src/routes/v1/demos/composeDemo.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { OpenAPIHono, createRoute } from '@hono/zod-openapi'
2+
import { readFileSync } from 'fs'
3+
import { join } from 'path'
4+
5+
const router = new OpenAPIHono()
6+
7+
const demoRoute = createRoute({
8+
method: 'get',
9+
path: '/',
10+
responses: {
11+
200: {
12+
description: 'Returns the Compose demo page.',
13+
content: {
14+
'text/html': {
15+
schema: { type: 'string' }
16+
}
17+
}
18+
}
19+
},
20+
tags: ['Demos']
21+
})
22+
23+
function getComposeDemoHtml() {
24+
const templatePath = join(process.cwd(), 'src', 'templates', 'composeDemo.html')
25+
return readFileSync(templatePath, 'utf-8')
26+
}
27+
28+
router.openapi(demoRoute, (c) => c.html(getComposeDemoHtml()))
29+
30+
export default {
31+
handler: router,
32+
mountPath: 'compose-demo'
33+
}
34+

src/routes/v1/demos/rewriteDemo.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { OpenAPIHono, createRoute } from '@hono/zod-openapi'
2+
import { readFileSync } from 'fs'
3+
import { join } from 'path'
4+
5+
const router = new OpenAPIHono()
6+
7+
const demoRoute = createRoute({
8+
method: 'get',
9+
path: '/',
10+
responses: {
11+
200: {
12+
description: 'Returns the Rewrite demo page.',
13+
content: {
14+
'text/html': {
15+
schema: { type: 'string' }
16+
}
17+
}
18+
}
19+
},
20+
tags: ['Demos']
21+
})
22+
23+
function getRewriteDemoHtml() {
24+
const templatePath = join(process.cwd(), 'src', 'templates', 'rewriteDemo.html')
25+
return readFileSync(templatePath, 'utf-8')
26+
}
27+
28+
router.openapi(demoRoute, (c) => c.html(getRewriteDemoHtml()))
29+
30+
export default {
31+
handler: router,
32+
mountPath: 'rewrite-demo'
33+
}
34+

src/routes/v1/services.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,27 +62,29 @@ const modelsSchema = z.object({
6262
available: z.boolean()
6363
})
6464

65-
const capabilityEnum = z.enum(['summarize', 'keywords', 'sentiment', 'emailReply', 'vision', 'askText', 'translate', 'meetingNotes', 'planning'])
65+
const capabilityEnum = z.enum(['summarize', 'rewrite', 'compose', 'keywords', 'sentiment', 'emailReply', 'vision', 'askText', 'translate', 'meetingNotes', 'planning'])
6666
const byProviderSchema = z.record(z.array(z.string()))
6767
const providerViewSchema = z.record(z.array(z.object({
6868
name: z.string(),
6969
capabilities: z.array(capabilityEnum),
7070
notes: z.string().optional()
7171
})))
72-
const modelsGuidanceSchema = z.object({
73-
source: z.literal('config'),
74-
byCapability: z.object({
75-
summarize: byProviderSchema,
76-
keywords: byProviderSchema,
77-
sentiment: byProviderSchema,
78-
emailReply: byProviderSchema,
79-
planning: byProviderSchema,
80-
vision: byProviderSchema,
81-
askText: byProviderSchema,
82-
translate: byProviderSchema,
83-
meetingNotes: byProviderSchema,
72+
const modelsGuidanceSchema = z.object({
73+
source: z.literal('config'),
74+
byCapability: z.object({
75+
summarize: byProviderSchema,
76+
rewrite: byProviderSchema,
77+
compose: byProviderSchema,
78+
keywords: byProviderSchema,
79+
sentiment: byProviderSchema,
80+
emailReply: byProviderSchema,
81+
planning: byProviderSchema,
82+
vision: byProviderSchema,
83+
askText: byProviderSchema,
84+
translate: byProviderSchema,
85+
meetingNotes: byProviderSchema,
86+
})
8487
})
85-
})
8688

8789
async function handleServiceStatus(c: Context) {
8890
try {
@@ -102,6 +104,8 @@ async function handleGetModels(c: Context) {
102104
if (source === 'config') {
103105
const byCapability = {
104106
summarize: getModelsByCapability('summarize'),
107+
rewrite: getModelsByCapability('rewrite'),
108+
compose: getModelsByCapability('compose'),
105109
keywords: getModelsByCapability('keywords'),
106110
sentiment: getModelsByCapability('sentiment'),
107111
emailReply: getModelsByCapability('emailReply'),
@@ -276,4 +280,3 @@ export default {
276280
mountPath: 'services'
277281
}
278282

279-

0 commit comments

Comments
 (0)