feat: improve AI chat - system prompt, tool output, context window display (#17769)
⚠️ **AI-generated PR — not ready for review** ⚠️ cc @FelixMalfait --- ## Changes ### System prompt improvements - Explicit skill-before-tools workflow to prevent the model from calling tools without loading the matching skill first - Data efficiency guidance (default small limits, use filters) - Pluralized `load_skill` → `load_skills` for consistency with `load_tools` ### Token usage reduction - Output serialization layer: strips null/undefined/empty values from tool results - Lowered default `find_*` limit from 100 → 10, max from 1000 → 100 ### System object tool generation - System objects (calendar events, messages, etc.) now generate AI tools - Only workflow-related and favorite-related objects are excluded ### Context window display fix - **Bug**: UI compared cumulative tokens (sum of all turns) against single-request context window → showed 100% after a few turns - **Fix**: Track `conversationSize` (last step's `inputTokens`) which represents the actual conversation history size sent to the model - New `conversationSize` column on thread entity with migration ### Workspace AI instructions - Support for custom workspace-level AI instructions --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
claude[bot] <41898282+claude[bot]@users.noreply.github.com>
parent
6c7c389785
commit
3216b634a3
@@ -23,6 +23,10 @@ import { BillingSubscriptionService } from 'src/engine/core-modules/billing/serv
|
||||
import { BillingUsageService } from 'src/engine/core-modules/billing/services/billing-usage.service';
|
||||
import { BillingService } from 'src/engine/core-modules/billing/services/billing.service';
|
||||
import { formatBillingDatabaseProductToGraphqlDTO } from 'src/engine/core-modules/billing/utils/format-database-product-to-graphql-dto.util';
|
||||
import {
|
||||
INTERNAL_CREDITS_PER_DISPLAY_CREDIT,
|
||||
toDisplayCredits,
|
||||
} from 'src/engine/core-modules/billing/utils/to-display-credits.util';
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
@@ -298,7 +302,17 @@ export class BillingResolver {
|
||||
async getMeteredProductsUsage(
|
||||
@AuthWorkspace() workspace: WorkspaceEntity,
|
||||
): Promise<BillingMeteredProductUsageOutput[]> {
|
||||
return await this.billingUsageService.getMeteredProductsUsage(workspace);
|
||||
const usageData =
|
||||
await this.billingUsageService.getMeteredProductsUsage(workspace);
|
||||
|
||||
return usageData.map((item) => ({
|
||||
...item,
|
||||
usedCredits: toDisplayCredits(item.usedCredits),
|
||||
grantedCredits: toDisplayCredits(item.grantedCredits),
|
||||
rolloverCredits: toDisplayCredits(item.rolloverCredits),
|
||||
totalGrantedCredits: toDisplayCredits(item.totalGrantedCredits),
|
||||
unitPriceCents: item.unitPriceCents * INTERNAL_CREDITS_PER_DISPLAY_CREDIT,
|
||||
}));
|
||||
}
|
||||
|
||||
@Mutation(() => BillingUpdateOutput)
|
||||
|
||||
+6
-6
@@ -1,4 +1,4 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
import { Field, Float, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { BillingProductKey } from 'src/engine/core-modules/billing/enums/billing-product-key.enum';
|
||||
|
||||
@@ -13,18 +13,18 @@ export class BillingMeteredProductUsageOutput {
|
||||
@Field(() => Date)
|
||||
periodEnd: Date;
|
||||
|
||||
@Field(() => Number)
|
||||
@Field(() => Float)
|
||||
usedCredits: number;
|
||||
|
||||
@Field(() => Number)
|
||||
@Field(() => Float)
|
||||
grantedCredits: number;
|
||||
|
||||
@Field(() => Number)
|
||||
@Field(() => Float)
|
||||
rolloverCredits: number;
|
||||
|
||||
@Field(() => Number)
|
||||
@Field(() => Float)
|
||||
totalGrantedCredits: number;
|
||||
|
||||
@Field(() => Number)
|
||||
@Field(() => Float)
|
||||
unitPriceCents: number;
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// Internal credits use micro-precision: $1 = 1,000,000 internal credits
|
||||
// Display credits are 1000x coarser: $1 = 1,000 display credits
|
||||
// This mirrors the "micro" pattern in payment systems (e.g. microdollars → dollars)
|
||||
export const INTERNAL_CREDITS_PER_DISPLAY_CREDIT = 1000;
|
||||
|
||||
// Converts internal (high-precision) credits to user-facing display credits.
|
||||
// Rounds to 1 decimal place for clean display (e.g. 7500 → 7.5).
|
||||
export const toDisplayCredits = (internalCredits: number): number =>
|
||||
Math.round((internalCredits / INTERNAL_CREDITS_PER_DISPLAY_CREDIT) * 10) / 10;
|
||||
Reference in New Issue
Block a user