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
11 changes: 11 additions & 0 deletions agents/__tests__/editor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ describe('editor agent', () => {
expect(glmEditor.model).toBe('z-ai/glm-5.1')
})

test('creates kimi editor', () => {
const kimiEditor = createCodeEditor({ model: 'kimi' })
expect(kimiEditor.model).toBe('moonshotai/kimi-k2.6')
})

test('creates minimax editor', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.model).toBe('minimax/minimax-m2.7')
Expand All @@ -84,6 +89,12 @@ describe('editor agent', () => {
expect(glmEditor.instructionsPrompt).not.toContain('</think>')
})

test('kimi editor does not include think tags in instructions', () => {
const kimiEditor = createCodeEditor({ model: 'kimi' })
expect(kimiEditor.instructionsPrompt).not.toContain('<think>')
expect(kimiEditor.instructionsPrompt).not.toContain('</think>')
})

test('minimax editor does not include think tags in instructions', () => {
const minimaxEditor = createCodeEditor({ model: 'minimax' })
expect(minimaxEditor.instructionsPrompt).not.toContain('<think>')
Expand Down
2 changes: 1 addition & 1 deletion agents/base2/base2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function createBase2(
const isFree = mode === 'free' || mode === 'lite'

const isSonnet = false
const model = isFree ? 'z-ai/glm-5.1' : 'anthropic/claude-opus-4.7'
const model = isFree ? 'moonshotai/kimi-k2.6' : 'anthropic/claude-opus-4.7'

return {
publisher,
Expand Down
2 changes: 1 addition & 1 deletion agents/editor/editor-lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createCodeEditor } from './editor'
import type { AgentDefinition } from '../types/agent-definition'

const definition: AgentDefinition = {
...createCodeEditor({ model: 'glm' }),
...createCodeEditor({ model: 'kimi' }),
id: 'editor-lite',
}
export default definition
6 changes: 4 additions & 2 deletions agents/editor/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { publisher } from '../constants'
import type { AgentDefinition } from '../types/agent-definition'

export const createCodeEditor = (options: {
model: 'gpt-5' | 'opus' | 'glm' | 'minimax'
model: 'gpt-5' | 'opus' | 'glm' | 'kimi' | 'minimax'
}): Omit<AgentDefinition, 'id'> => {
const { model } = options
return {
Expand All @@ -14,6 +14,8 @@ export const createCodeEditor = (options: {
? 'openai/gpt-5.1'
: options.model === 'minimax'
? 'minimax/minimax-m2.7'
: options.model === 'kimi'
? 'moonshotai/kimi-k2.6'
: options.model === 'glm'
? 'z-ai/glm-5.1'
: 'anthropic/claude-opus-4.7',
Expand Down Expand Up @@ -67,7 +69,7 @@ OR for new files or major rewrites:
}
</codebuff_tool_call>

${model === 'gpt-5' || model === 'glm' || model === 'minimax'
${model === 'gpt-5' || model === 'glm' || model === 'kimi' || model === 'minimax'
? ''
: `Before you start writing your implementation, you should use <think> tags to think about the best way to implement the changes.

Expand Down
2 changes: 1 addition & 1 deletion agents/reviewer/code-reviewer-lite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { createReviewer } from './code-reviewer'
const definition: SecretAgentDefinition = {
id: 'code-reviewer-lite',
publisher,
...createReviewer('z-ai/glm-5.1'),
...createReviewer('moonshotai/kimi-k2.6'),
}

export default definition
1 change: 1 addition & 0 deletions agents/types/agent-definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ export type ModelName =
// Other open source models
| 'moonshotai/kimi-k2'
| 'moonshotai/kimi-k2:nitro'
| 'moonshotai/kimi-k2.6'
| 'z-ai/glm-5'
| 'z-ai/glm-5.1'
| 'z-ai/glm-4.6'
Expand Down
9 changes: 3 additions & 6 deletions cli/src/chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const Chat = ({
})
const hasSubscription = subscriptionData?.hasSubscription ?? false

const { adData, recordImpression } = useGravityAd({
const { ads, recordImpression } = useGravityAd({
enabled: IS_FREEBUFF || !hasSubscription,
provider: 'gravity',
fallbackProvider: 'carbon',
Expand Down Expand Up @@ -1463,11 +1463,8 @@ export const Chat = ({
/>
)}

{adData && (IS_FREEBUFF || getAdsEnabled()) && (
<ChoiceAdBanner
ads={adData.variant === 'choice' ? adData.ads : [adData.ad]}
onImpression={recordImpression}
/>
{ads && (IS_FREEBUFF || getAdsEnabled()) && (
<ChoiceAdBanner ads={ads} onImpression={recordImpression} />
)}

{reviewMode ? (
Expand Down
8 changes: 4 additions & 4 deletions cli/src/components/freebuff-model-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { Button } from './button'
import {
FALLBACK_FREEBUFF_MODEL_ID,
FREEBUFF_GLM_MODEL_ID,
FREEBUFF_KIMI_MODEL_ID,
FREEBUFF_MODELS,
getFreebuffDeploymentAvailabilityLabel,
isFreebuffModelAvailable,
Expand All @@ -25,8 +25,8 @@ import {
import type { KeyEvent } from '@opentui/core'

const FREEBUFF_MODEL_SELECTOR_MODELS = [
...FREEBUFF_MODELS.filter((model) => model.id === FREEBUFF_GLM_MODEL_ID),
...FREEBUFF_MODELS.filter((model) => model.id !== FREEBUFF_GLM_MODEL_ID),
...FREEBUFF_MODELS.filter((model) => model.id === FREEBUFF_KIMI_MODEL_ID),
...FREEBUFF_MODELS.filter((model) => model.id !== FREEBUFF_KIMI_MODEL_ID),
]

/**
Expand Down Expand Up @@ -72,7 +72,7 @@ export const FreebuffModelSelector: React.FC = () => {
// unavailable (e.g. deployment hours close while the picker is open),
// swap to the always-available fallback so Enter doesn't POST a model
// the server will immediately reject. In-memory only — the user's saved
// preference (e.g. GLM) is preserved for the next launch.
// preference (e.g. Kimi) is preserved for the next launch.
if (
(session?.status === 'none' || !session) &&
!isFreebuffModelAvailable(selectedModel, new Date(now))
Expand Down
15 changes: 6 additions & 9 deletions cli/src/components/waiting-room-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const WaitingRoomScreen: React.FC<WaitingRoomScreenProps> = ({
// forceStart bypasses the "wait for first user message" gate inside the hook,
// which would otherwise block ads here since no conversation exists yet.
// Try Gravity first, then fall back to Carbon when Gravity doesn't fill.
const { adData, recordImpression } = useGravityAd({
const { ads, recordImpression } = useGravityAd({
enabled: true,
forceStart: true,
provider: 'gravity',
Expand Down Expand Up @@ -260,7 +260,7 @@ export const WaitingRoomScreen: React.FC<WaitingRoomScreenProps> = ({
<span>Elapsed </span>
{formatElapsed(elapsedMs)}
</text>
{/* Per-model session quota (e.g. GLM 5.1 caps at 5/12h). Only
{/* Per-model session quota (e.g. Kimi K2.6 caps at 5/12h). Only
rendered for rate-limited models so the Minimax queue stays
clutter-free. */}
{session.rateLimit && (
Expand Down Expand Up @@ -343,7 +343,7 @@ export const WaitingRoomScreen: React.FC<WaitingRoomScreenProps> = ({
</>
)}

{/* Per-model session quota exhausted (e.g. 5+ GLM sessions in the
{/* Per-model session quota exhausted (e.g. 5+ Kimi sessions in the
last 12h). Terminal for this run — the user can exit and come
back once the oldest session in the window rolls off. */}
{session?.status === 'rate_limited' && (
Expand All @@ -369,17 +369,14 @@ export const WaitingRoomScreen: React.FC<WaitingRoomScreenProps> = ({
</box>

{/* Ad banner pinned to the bottom, same look-and-feel as in chat. */}
{adData && (
{ads && (
<box style={{ flexShrink: 0 }}>
<ChoiceAdBanner
ads={adData.variant === 'choice' ? adData.ads : [adData.ad]}
onImpression={recordImpression}
/>
<ChoiceAdBanner ads={ads} onImpression={recordImpression} />
</box>
)}

{/* Horizontal separator (mirrors chat input divider style) */}
{!adData && (
{!ads && (
<text style={{ fg: theme.muted, flexShrink: 0 }}>
{'─'.repeat(terminalWidth)}
</text>
Expand Down
6 changes: 3 additions & 3 deletions cli/src/hooks/use-freebuff-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async function callSession(
return body
}
}
// 429 from POST is the per-model session-quota reject (e.g. too many GLM
// 429 from POST is the per-model session-quota reject (e.g. too many Kimi
// sessions in the last 12h). Terminal for the current poll — the CLI shows
// a screen explaining the limit and when the user can try again. The 429
// status (rather than 200) keeps older CLIs in their error path so they
Expand Down Expand Up @@ -442,9 +442,9 @@ export function useFreebuffSession(): UseFreebuffSessionResult {
}
if (next.status === 'model_unavailable') {
// Server says the requested model isn't available right now (e.g.
// GLM outside deployment hours). Flip to the always-available
// Kimi outside deployment hours). Flip to the always-available
// fallback for this run. In-memory only — `setSelectedModel`
// doesn't persist, so the user's saved preference (e.g. GLM)
// doesn't persist, so the user's saved preference (e.g. Kimi)
// is preserved for their next launch during deployment hours.
useFreebuffModelStore
.getState()
Expand Down
Loading
Loading