Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix folder rename input #1098

Merged
merged 5 commits into from
Jan 1, 2025
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
15 changes: 8 additions & 7 deletions common/requests/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,14 @@ export function trimResponseV2(
generated = generated.split(`${member.handle} :`).join(`${member.handle}:`)
}

if (bots) {
for (const bot of Object.values(bots)) {
if (!bot) continue
if (bot?._id === char._id) continue
endTokens.push(`${bot.name}:`)
}
}
/** Do not always add character names as stop tokens here */
// if (bots) {
// for (const bot of Object.values(bots)) {
// if (!bot) continue
// if (bot?._id === char._id) continue
// endTokens.push(`${bot.name}:`)
// }
// }

let index = -1
let trimmed = allEndTokens.concat(...endTokens).reduce((prev, endToken) => {
Expand Down
3 changes: 2 additions & 1 deletion common/types/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export type CustomUI = {
chatQuoteColor: string
}

export type MessageOption = 'edit' | 'regen' | 'trash' | 'fork' | 'prompt'
export type MessageOption = 'edit' | 'regen' | 'trash' | 'fork' | 'prompt' | 'schema-regen'

export type UISettings = {
theme: string
Expand Down Expand Up @@ -147,5 +147,6 @@ export const defaultUIsettings: UISettings = {
fork: { outer: false, pos: 2 },
regen: { outer: true, pos: 1 },
trash: { outer: false, pos: 4 },
'schema-regen': { outer: false, pos: 5 },
},
}
12 changes: 9 additions & 3 deletions srv/adapter/agnaistic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,15 @@ export const handleAgnaistic: ModelAdapter = async function* (opts) {

log.debug(`Prompt:\n${prompt}`)

const [submodel, override] = subPreset.subModel.split(',')

let params = [`type=text`, `id=${opts.user._id}`, `model=${submodel}`, `level=${level}`]
const [submodel, override = ''] = subPreset.subModel.split(',')

let params = [
`type=text`,
`id=${opts.user._id}`,
`model=${submodel}`,
`level=${level}`,
`sub_model=${override}`,
]
.filter((p) => !!p)
.join('&')

Expand Down
1 change: 1 addition & 0 deletions srv/adapter/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ export async function createChatStream(
lastMessage: opts.lastMessage,
imageData: opts.imageData,
jsonSchema: jsonSchema || opts.jsonSchema,
reschemaPrompt: opts.reschemaPrompt,
subscription,
encoder,
jsonValues: opts.jsonValues,
Expand Down
1 change: 1 addition & 0 deletions srv/adapter/payloads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ function getBasePayload(opts: AdapterProps, stops: string[] = []) {
lists: opts.lists,
previous: opts.previous,
json_schema_v2: ensureSafeSchema(json_schema),
reschema_prompt: opts.reschemaPrompt,
json_schema,
imageData: opts.imageData,
context_size: opts.contextSize,
Expand Down
2 changes: 2 additions & 0 deletions srv/adapter/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type GenerateRequestV2 = {
impersonate?: AppSchema.Character

jsonSchema?: JsonField[]
reschemaPrompt?: string
jsonValues?: Record<string, any>

/** Base64 */
Expand Down Expand Up @@ -122,6 +123,7 @@ export type AdapterProps = {
encoder?: TokenCounter

jsonSchema?: any
reschemaPrompt?: string
jsonValues: Record<string, any> | undefined

imageData?: string
Expand Down
24 changes: 24 additions & 0 deletions srv/api/billing/checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { v4 } from 'uuid'
import { config } from '../../config'
import { billingCmd, domain } from '../../domains'
import { subsCmd } from '../../domains/subs/cmd'
import { AppSchema } from '/common/types'

export const startCheckout = handle(async ({ body, userId }) => {
assertValid({ tierId: 'string', callback: 'string' }, body)
Expand Down Expand Up @@ -180,6 +181,10 @@ export const finishCheckout = handle(async ({ body, userId }) => {
subscriptionId: subscription.id,
})

if (user && subscription.id) {
await ensureOnlyActiveSubscription(user, subscription.id)
}

const config = await store.users.updateUser(userId, {
sub: {
tierId: agg.tierId,
Expand All @@ -205,3 +210,22 @@ export const finishCheckout = handle(async ({ body, userId }) => {
await billingCmd.cancel(body.sessionId, { userId })
}
})

async function ensureOnlyActiveSubscription(user: AppSchema.User, subscriptionId: string) {
// The user isn't an existing customer -- ignore
if (!user.billing?.customerId) return

const subs = await stripe.subscriptions
.list({ customer: user.billing.customerId, status: 'active' })
.then((res) => res.data)
.catch(() => [])

for (const sub of subs) {
if (sub.id !== subscriptionId) {
await subsCmd.cancelDuplicate(user._id, { subscriptionId, replacementId: subscriptionId })
await stripe.subscriptions.cancel(sub.id, {
cancellation_details: { comment: 'duplicate detected during checkout' },
})
}
}
}
8 changes: 8 additions & 0 deletions srv/domains/subs/agg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ export const subsAgg = createAggregate<SubsEvt, SubsAgg, 'subscriptions'>({
}
}

case 'cancelled-duplicate': {
return {
state: prev.state,
downgrade: prev.downgrade,
history,
}
}

case 'cancelled': {
const endAt = new Date(prev.periodStart)
endAt.setFullYear(meta.timestamp.getFullYear())
Expand Down
9 changes: 9 additions & 0 deletions srv/domains/subs/cmd.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,15 @@ export const subsCmd = createCommands<SubsEvt, SubsAgg, SubsCmd>(domain.subscrip

return { type: 'resumed' }
},

async cancelDuplicate(cmd, agg) {
return {
type: 'cancelled-duplicate',
subscriptionId: cmd.subscriptionId,
replacementId: cmd.replacementId,
}
},

async cancel(cmd, agg) {
if (agg.state !== 'active') {
throw new CommandError('Cannot cancel subscription - Subscription not active', 'NOT_ACTIVE')
Expand Down
2 changes: 2 additions & 0 deletions srv/domains/subs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type SubsEvt =
periodStart: string
}
| { type: 'cancelled' }
| { type: 'cancelled-duplicate'; subscriptionId: string; replacementId?: string }
| { type: 'upgraded'; tierId: string; priceId: string }
| { type: 'downgraded'; tierId: string; priceId: string; activeAt: string }
| { type: 'session-started'; sessionId: string; tierId: string }
Expand All @@ -36,6 +37,7 @@ export type SubsCmd =
productId: string
subscription: Stripe.Subscription
}
| { type: 'cancelDuplicate'; subscriptionId: string; replacementId?: string }
| { type: 'cancel' }
| { type: 'resume' }
| { type: 'upgrade'; tierId: string; priceId: string }
Expand Down
12 changes: 6 additions & 6 deletions web/pages/Character/components/CharacterFolderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -442,15 +442,15 @@ function getChildFolders(tree: FolderTree, path: string, sort: SortDirection) {
}

const ChangeFolder: Component<{ char?: AppSchema.Character; close: () => void }> = (props) => {
const [actual, setActual] = createSignal('/')
const [name, setName] = createSignal(props.char?.folder || '')
const actual = createMemo(() => toFolderSlug(name()))

createEffect(
on(
() => props.char,
() => {
if (!props.char) return

setActual(toFolderSlug(props.char.folder || '/'))
setName(props.char.folder || '/')
}
)
)
Expand Down Expand Up @@ -489,10 +489,10 @@ const ChangeFolder: Component<{ char?: AppSchema.Character; close: () => void }>
/>

<TextInput
helperMarkdown={`Folder names are 'normalized'.\nNoramlized name: ${actual()}`}
helperMarkdown={`Folder names are 'normalized'.\nNormalized name: ${actual()}`}
label="New Folder"
value={props.char?.folder || '/'}
onChange={(ev) => setActual(toFolderSlug(ev.currentTarget.value))}
value={name()}
onChange={(ev) => setName(ev.currentTarget.value)}
/>
</div>
</RootModal>
Expand Down
33 changes: 28 additions & 5 deletions web/pages/Chat/components/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
Zap,
Split,
MoreHorizontal,
Braces,
} from 'lucide-solid'
import {
Accessor,
Expand Down Expand Up @@ -548,10 +549,6 @@ const MessageOptions: Component<{
onRemove: () => void
showMore: Signal<boolean>
}> = (props) => {
const showInner = createMemo(() =>
Object.values(props.ui.msgOptsInline || {}).some((v) => !v?.outer)
)

const closer = (action: () => void) => {
return () => {
action()
Expand Down Expand Up @@ -617,6 +614,20 @@ const MessageOptions: Component<{
icon: RefreshCw,
},

'schema-regen': {
key: 'schema-regen',
class: 'refresh-btn',
label: 'Schema Regen',
outer: props.ui.msgOptsInline['schema-regen'],
show:
window.flags.reschema &&
((props.msg.json && props.last) ||
(props.msg.adapter === 'image' && !!props.msg.imagePrompt)) &&
!!props.msg.characterId,
onClick: () => !props.partial && retryJsonSchema(props.msg, props.msg),
icon: Braces,
},

trash: {
key: 'trash',
label: 'Delete',
Expand All @@ -632,6 +643,14 @@ const MessageOptions: Component<{
return items
})

const showInner = createMemo(() => {
for (const opt of Object.values(logic())) {
if (!opt.outer && opt.show) return true
}

return false
})

const order = createMemo(() => {
open()
logic()
Expand Down Expand Up @@ -736,7 +755,7 @@ const MessageOption: Component<{

<Show when={!props.outer}>
<Button
class={`${props.class || ''} w-full`}
class={`${props.class || ''} w-full min-w-max`}
schema={props.schema || 'secondary'}
onClick={props.onClick}
size="sm"
Expand All @@ -758,6 +777,10 @@ function retryMessage(original: AppSchema.ChatMessage, split: SplitMessage) {
}
}

function retryJsonSchema(original: AppSchema.ChatMessage, split: SplitMessage) {
msgStore.retrySchema(split.chatId, original._id)
}

function renderMessage(ctx: ContextState, text: string, isUser: boolean, adapter?: string) {
// Address unfortunate Showdown bug where spaces in code blocks are replaced with nbsp, except
// it also encodes the ampersand, which results in them actually being rendered as `&amp;nbsp;`
Expand Down
1 change: 1 addition & 0 deletions web/pages/Settings/UISettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const msgInlineLabels: Record<UI.MessageOption, string> = {
prompt: 'Prompt View',
fork: 'Fork',
trash: 'Delete',
'schema-regen': 'Retry Schema',
}

const UISettings: Component<{}> = () => {
Expand Down
39 changes: 29 additions & 10 deletions web/shared/CustomSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export type CustomOption = {
export const CustomSelect: Component<{
buttonLabel: string | JSX.Element | ((opt: CustomOption) => JSX.Element | string)
onSelect: (opt: CustomOption) => void
options: CustomOption[]
options?: CustomOption[]
categories?: Array<{ name: string; options: CustomOption[] }>
value: any

header?: JSX.Element
Expand Down Expand Up @@ -74,15 +75,33 @@ export const CustomSelect: Component<{
</div>
<RootModal show={open()} close={() => setOpen(false)} title={props.modalTitle}>
<div class="flex flex-col gap-4">
<div class="flex flex-wrap gap-2 pr-3">
<OptionList
header={props.header}
options={props.options}
onSelect={onSelect}
selected={props.selected}
search={props.search}
/>
</div>
<Show when={props.categories}>
<For each={props.categories}>
{(category) => (
<div class="flex flex-wrap gap-2 pr-3">
<div class="bold text-md">{category.name}</div>
<OptionList
header={props.header}
options={category.options}
onSelect={onSelect}
selected={props.selected}
search={props.search}
/>
</div>
)}
</For>
</Show>
<Show when={props.options}>
<div class="flex flex-wrap gap-2 pr-3">
<OptionList
header={props.header}
options={props.options!}
onSelect={onSelect}
selected={props.selected}
search={props.search}
/>
</div>
</Show>
</div>
</RootModal>
</div>
Expand Down
6 changes: 6 additions & 0 deletions web/shared/PersonaAttributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const PersonaAttributes: Component<{
if (key === 'text') {
squished.push(values)
} else {
if (!values.trim()) continue
squished.push(`${key}:\n${values}`)
}
}
Expand All @@ -82,6 +83,11 @@ const PersonaAttributes: Component<{
const text = props.state.find((s) => s.key === 'text')
if (!text) return

if (props.state.length === 1) {
props.setter([{ key: 'personality', values: props.state[0].values }])
return
}

let matching = true
for (const { values } of props.state) {
if (!text.values.includes(values)) matching = false
Expand Down
Loading
Loading