fix: use standard TypeORM repos and header-based tenant extraction
- Replace TenantAwareRepository with standard @InjectRepository
(TenantAwareRepository requires AsyncLocalStorage tenant context
middleware which agent-service does not have)
- Replace @TenantId() decorator with @Headers('x-tenant-id')
for direct HTTP header extraction
- Return defaults gracefully when no tenant is selected
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f897cfe240
commit
d8cb2a9c6f
|
|
@ -1,20 +1,24 @@
|
||||||
/**
|
/**
|
||||||
* Repository for AgentConfig.
|
* Repository for AgentConfig.
|
||||||
* Extends TenantAwareRepository for schema-per-tenant isolation.
|
* Uses standard TypeORM repository (no schema-per-tenant — uses tenantId column filter).
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { TenantAwareRepository } from '@it0/database';
|
import { Repository } from 'typeorm';
|
||||||
import { AgentConfig } from '../../domain/entities/agent-config.entity';
|
import { AgentConfig } from '../../domain/entities/agent-config.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AgentConfigRepository extends TenantAwareRepository<AgentConfig> {
|
export class AgentConfigRepository {
|
||||||
constructor(dataSource: DataSource) {
|
constructor(
|
||||||
super(dataSource, AgentConfig);
|
@InjectRepository(AgentConfig)
|
||||||
}
|
private readonly repo: Repository<AgentConfig>,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findByTenantId(tenantId: string): Promise<AgentConfig | null> {
|
async findByTenantId(tenantId: string): Promise<AgentConfig | null> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.findOneBy({ tenantId });
|
||||||
return repo.findOneBy({ tenantId } as any);
|
}
|
||||||
|
|
||||||
|
async save(entity: AgentConfig): Promise<AgentConfig> {
|
||||||
|
return this.repo.save(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,32 @@
|
||||||
/**
|
/**
|
||||||
* Repository for AgentSkill.
|
* Repository for AgentSkill.
|
||||||
* Extends TenantAwareRepository for schema-per-tenant isolation.
|
* Uses standard TypeORM repository (no schema-per-tenant — uses tenantId column filter).
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { TenantAwareRepository } from '@it0/database';
|
import { Repository } from 'typeorm';
|
||||||
import { AgentSkill } from '../../domain/entities/agent-skill.entity';
|
import { AgentSkill } from '../../domain/entities/agent-skill.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AgentSkillRepository extends TenantAwareRepository<AgentSkill> {
|
export class AgentSkillRepository {
|
||||||
constructor(dataSource: DataSource) {
|
constructor(
|
||||||
super(dataSource, AgentSkill);
|
@InjectRepository(AgentSkill)
|
||||||
}
|
private readonly repo: Repository<AgentSkill>,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findByTenantId(tenantId: string): Promise<AgentSkill[]> {
|
async findByTenantId(tenantId: string): Promise<AgentSkill[]> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.find({ where: { tenantId }, order: { createdAt: 'DESC' } });
|
||||||
return repo.find({ where: { tenantId } as any, order: { createdAt: 'DESC' } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneByIdAndTenant(id: string, tenantId: string): Promise<AgentSkill | null> {
|
async findOneByIdAndTenant(id: string, tenantId: string): Promise<AgentSkill | null> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.findOneBy({ id, tenantId });
|
||||||
return repo.findOneBy({ id, tenantId } as any);
|
}
|
||||||
|
|
||||||
|
async save(entity: AgentSkill): Promise<AgentSkill> {
|
||||||
|
return this.repo.save(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteById(id: string): Promise<void> {
|
async deleteById(id: string): Promise<void> {
|
||||||
const repo = await this.getRepository();
|
await this.repo.delete(id);
|
||||||
await repo.delete(id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,32 @@
|
||||||
/**
|
/**
|
||||||
* Repository for HookScript.
|
* Repository for HookScript.
|
||||||
* Extends TenantAwareRepository for schema-per-tenant isolation.
|
* Uses standard TypeORM repository (no schema-per-tenant — uses tenantId column filter).
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { TenantAwareRepository } from '@it0/database';
|
import { Repository } from 'typeorm';
|
||||||
import { HookScript } from '../../domain/entities/hook-script.entity';
|
import { HookScript } from '../../domain/entities/hook-script.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HookScriptRepository extends TenantAwareRepository<HookScript> {
|
export class HookScriptRepository {
|
||||||
constructor(dataSource: DataSource) {
|
constructor(
|
||||||
super(dataSource, HookScript);
|
@InjectRepository(HookScript)
|
||||||
}
|
private readonly repo: Repository<HookScript>,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findByTenantId(tenantId: string): Promise<HookScript[]> {
|
async findByTenantId(tenantId: string): Promise<HookScript[]> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.find({ where: { tenantId }, order: { createdAt: 'DESC' } });
|
||||||
return repo.find({ where: { tenantId } as any, order: { createdAt: 'DESC' } });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findOneByIdAndTenant(id: string, tenantId: string): Promise<HookScript | null> {
|
async findOneByIdAndTenant(id: string, tenantId: string): Promise<HookScript | null> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.findOneBy({ id, tenantId });
|
||||||
return repo.findOneBy({ id, tenantId } as any);
|
}
|
||||||
|
|
||||||
|
async save(entity: HookScript): Promise<HookScript> {
|
||||||
|
return this.repo.save(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteById(id: string): Promise<void> {
|
async deleteById(id: string): Promise<void> {
|
||||||
const repo = await this.getRepository();
|
await this.repo.delete(id);
|
||||||
await repo.delete(id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,24 @@
|
||||||
/**
|
/**
|
||||||
* Repository for TenantAgentConfig.
|
* Repository for TenantAgentConfig.
|
||||||
* Extends TenantAwareRepository for schema-per-tenant isolation (SET search_path).
|
* Uses standard TypeORM repository (no schema-per-tenant — uses tenantId column filter).
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DataSource } from 'typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { TenantAwareRepository } from '@it0/database';
|
import { Repository } from 'typeorm';
|
||||||
import { TenantAgentConfig } from '../../domain/entities/tenant-agent-config.entity';
|
import { TenantAgentConfig } from '../../domain/entities/tenant-agent-config.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TenantAgentConfigRepository extends TenantAwareRepository<TenantAgentConfig> {
|
export class TenantAgentConfigRepository {
|
||||||
constructor(dataSource: DataSource) {
|
constructor(
|
||||||
super(dataSource, TenantAgentConfig);
|
@InjectRepository(TenantAgentConfig)
|
||||||
}
|
private readonly repo: Repository<TenantAgentConfig>,
|
||||||
|
) {}
|
||||||
|
|
||||||
async findByTenantId(tenantId: string): Promise<TenantAgentConfig | null> {
|
async findByTenantId(tenantId: string): Promise<TenantAgentConfig | null> {
|
||||||
const repo = await this.getRepository();
|
return this.repo.findOneBy({ tenantId });
|
||||||
return repo.findOneBy({ tenantId } as any);
|
}
|
||||||
|
|
||||||
|
async save(entity: TenantAgentConfig): Promise<TenantAgentConfig> {
|
||||||
|
return this.repo.save(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,26 +6,26 @@
|
||||||
* POST /api/v1/agent-config → Create new config
|
* POST /api/v1/agent-config → Create new config
|
||||||
* PUT /api/v1/agent-config/:id → Update existing config
|
* PUT /api/v1/agent-config/:id → Update existing config
|
||||||
*/
|
*/
|
||||||
import { Controller, Get, Post, Put, Body, Param } from '@nestjs/common';
|
import { Controller, Get, Post, Put, Body, Param, Headers } from '@nestjs/common';
|
||||||
import { TenantId } from '@it0/common';
|
|
||||||
import { AgentConfigService, UpdateAgentConfigDto } from '../../../infrastructure/services/agent-config.service';
|
import { AgentConfigService, UpdateAgentConfigDto } from '../../../infrastructure/services/agent-config.service';
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG = {
|
||||||
|
engine: 'claude-cli',
|
||||||
|
system_prompt: '',
|
||||||
|
max_turns: 10,
|
||||||
|
max_budget: 5.0,
|
||||||
|
allowed_tools: ['Bash', 'Read', 'Write', 'Glob', 'Grep'],
|
||||||
|
};
|
||||||
|
|
||||||
@Controller('api/v1/agent-config')
|
@Controller('api/v1/agent-config')
|
||||||
export class AgentConfigController {
|
export class AgentConfigController {
|
||||||
constructor(private readonly configService: AgentConfigService) {}
|
constructor(private readonly configService: AgentConfigService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async getConfig(@TenantId() tenantId: string) {
|
async getConfig(@Headers('x-tenant-id') tenantId: string) {
|
||||||
|
if (!tenantId) return DEFAULT_CONFIG;
|
||||||
const config = await this.configService.findByTenantId(tenantId);
|
const config = await this.configService.findByTenantId(tenantId);
|
||||||
if (!config) {
|
if (!config) return DEFAULT_CONFIG;
|
||||||
return {
|
|
||||||
engine: 'claude-cli',
|
|
||||||
system_prompt: '',
|
|
||||||
max_turns: 10,
|
|
||||||
max_budget: 5.0,
|
|
||||||
allowed_tools: ['Bash', 'Read', 'Write', 'Glob', 'Grep'],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: config.id,
|
id: config.id,
|
||||||
|
|
@ -39,10 +39,10 @@ export class AgentConfigController {
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async createConfig(
|
async createConfig(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Body() dto: UpdateAgentConfigDto,
|
@Body() dto: UpdateAgentConfigDto,
|
||||||
) {
|
) {
|
||||||
const config = await this.configService.create(tenantId, dto);
|
const config = await this.configService.create(tenantId || 'default', dto);
|
||||||
return {
|
return {
|
||||||
id: config.id,
|
id: config.id,
|
||||||
engine: config.engine,
|
engine: config.engine,
|
||||||
|
|
@ -55,11 +55,11 @@ export class AgentConfigController {
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
async updateConfig(
|
async updateConfig(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: UpdateAgentConfigDto,
|
@Body() dto: UpdateAgentConfigDto,
|
||||||
) {
|
) {
|
||||||
const config = await this.configService.update(id, tenantId, dto);
|
const config = await this.configService.update(id, tenantId || 'default', dto);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return { error: 'Config not found' };
|
return { error: 'Config not found' };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
/**
|
/**
|
||||||
* REST controller for per-tenant hook scripts (CRUD).
|
* REST controller for per-tenant hook scripts (CRUD).
|
||||||
*
|
*
|
||||||
* Endpoints (all JWT-protected):
|
* Endpoints (JWT validated by Kong gateway):
|
||||||
* GET /api/v1/agent/hooks → List all hooks for current tenant
|
* GET /api/v1/agent/hooks → List all hooks for current tenant
|
||||||
* POST /api/v1/agent/hooks → Create a new hook
|
* POST /api/v1/agent/hooks → Create a new hook
|
||||||
* PUT /api/v1/agent/hooks/:id → Update an existing hook
|
* PUT /api/v1/agent/hooks/:id → Update an existing hook
|
||||||
* DELETE /api/v1/agent/hooks/:id → Delete a hook
|
* DELETE /api/v1/agent/hooks/:id → Delete a hook
|
||||||
*/
|
*/
|
||||||
import { Controller, Get, Post, Put, Delete, Body, Param, NotFoundException } from '@nestjs/common';
|
import { Controller, Get, Post, Put, Delete, Body, Param, Headers, NotFoundException } from '@nestjs/common';
|
||||||
import { TenantId } from '@it0/common';
|
|
||||||
import { HookScriptService, CreateHookDto, UpdateHookDto } from '../../../infrastructure/services/hook-script.service';
|
import { HookScriptService, CreateHookDto, UpdateHookDto } from '../../../infrastructure/services/hook-script.service';
|
||||||
|
|
||||||
@Controller('api/v1/agent/hooks')
|
@Controller('api/v1/agent/hooks')
|
||||||
|
|
@ -16,25 +15,25 @@ export class HooksController {
|
||||||
constructor(private readonly hookService: HookScriptService) {}
|
constructor(private readonly hookService: HookScriptService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async list(@TenantId() tenantId: string) {
|
async list(@Headers('x-tenant-id') tenantId: string) {
|
||||||
return this.hookService.findAllByTenant(tenantId);
|
return this.hookService.findAllByTenant(tenantId || 'default');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async create(
|
async create(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Body() dto: CreateHookDto,
|
@Body() dto: CreateHookDto,
|
||||||
) {
|
) {
|
||||||
return this.hookService.create(tenantId, dto);
|
return this.hookService.create(tenantId || 'default', dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
async update(
|
async update(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: UpdateHookDto,
|
@Body() dto: UpdateHookDto,
|
||||||
) {
|
) {
|
||||||
const hook = await this.hookService.update(id, tenantId, dto);
|
const hook = await this.hookService.update(id, tenantId || 'default', dto);
|
||||||
if (!hook) {
|
if (!hook) {
|
||||||
throw new NotFoundException('Hook not found');
|
throw new NotFoundException('Hook not found');
|
||||||
}
|
}
|
||||||
|
|
@ -43,10 +42,10 @@ export class HooksController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async remove(
|
async remove(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
) {
|
) {
|
||||||
const deleted = await this.hookService.delete(id, tenantId);
|
const deleted = await this.hookService.delete(id, tenantId || 'default');
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
throw new NotFoundException('Hook not found');
|
throw new NotFoundException('Hook not found');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
/**
|
/**
|
||||||
* REST controller for per-tenant agent skills (CRUD).
|
* REST controller for per-tenant agent skills (CRUD).
|
||||||
*
|
*
|
||||||
* Endpoints (all JWT-protected):
|
* Endpoints (JWT validated by Kong gateway):
|
||||||
* GET /api/v1/agent/skills → List all skills for current tenant
|
* GET /api/v1/agent/skills → List all skills for current tenant
|
||||||
* POST /api/v1/agent/skills → Create a new skill
|
* POST /api/v1/agent/skills → Create a new skill
|
||||||
* PUT /api/v1/agent/skills/:id → Update an existing skill
|
* PUT /api/v1/agent/skills/:id → Update an existing skill
|
||||||
* DELETE /api/v1/agent/skills/:id → Delete a skill
|
* DELETE /api/v1/agent/skills/:id → Delete a skill
|
||||||
*/
|
*/
|
||||||
import { Controller, Get, Post, Put, Delete, Body, Param, NotFoundException } from '@nestjs/common';
|
import { Controller, Get, Post, Put, Delete, Body, Param, Headers, NotFoundException } from '@nestjs/common';
|
||||||
import { TenantId } from '@it0/common';
|
|
||||||
import { AgentSkillService, CreateSkillDto, UpdateSkillDto } from '../../../infrastructure/services/agent-skill.service';
|
import { AgentSkillService, CreateSkillDto, UpdateSkillDto } from '../../../infrastructure/services/agent-skill.service';
|
||||||
|
|
||||||
@Controller('api/v1/agent/skills')
|
@Controller('api/v1/agent/skills')
|
||||||
|
|
@ -16,25 +15,25 @@ export class SkillsController {
|
||||||
constructor(private readonly skillService: AgentSkillService) {}
|
constructor(private readonly skillService: AgentSkillService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async list(@TenantId() tenantId: string) {
|
async list(@Headers('x-tenant-id') tenantId: string) {
|
||||||
return this.skillService.findAllByTenant(tenantId);
|
return this.skillService.findAllByTenant(tenantId || 'default');
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
async create(
|
async create(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Body() dto: CreateSkillDto,
|
@Body() dto: CreateSkillDto,
|
||||||
) {
|
) {
|
||||||
return this.skillService.create(tenantId, dto);
|
return this.skillService.create(tenantId || 'default', dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Put(':id')
|
@Put(':id')
|
||||||
async update(
|
async update(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
@Body() dto: UpdateSkillDto,
|
@Body() dto: UpdateSkillDto,
|
||||||
) {
|
) {
|
||||||
const skill = await this.skillService.update(id, tenantId, dto);
|
const skill = await this.skillService.update(id, tenantId || 'default', dto);
|
||||||
if (!skill) {
|
if (!skill) {
|
||||||
throw new NotFoundException('Skill not found');
|
throw new NotFoundException('Skill not found');
|
||||||
}
|
}
|
||||||
|
|
@ -43,10 +42,10 @@ export class SkillsController {
|
||||||
|
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
async remove(
|
async remove(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Param('id') id: string,
|
@Param('id') id: string,
|
||||||
) {
|
) {
|
||||||
const deleted = await this.skillService.delete(id, tenantId);
|
const deleted = await this.skillService.delete(id, tenantId || 'default');
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
throw new NotFoundException('Skill not found');
|
throw new NotFoundException('Skill not found');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
/**
|
/**
|
||||||
* Admin REST controller for per-tenant Agent SDK configuration.
|
* Admin REST controller for per-tenant Agent SDK configuration.
|
||||||
*
|
*
|
||||||
* Endpoints (all JWT-protected):
|
* Endpoints (JWT validated by Kong gateway):
|
||||||
* GET /api/v1/agent/tenant-config → Get current tenant's SDK config (returns defaults if none set)
|
* GET /api/v1/agent/tenant-config → Get current tenant's SDK config (returns defaults if none set)
|
||||||
* PUT /api/v1/agent/tenant-config → Create/update config (billingMode, apiKey, timeout, tools)
|
* PUT /api/v1/agent/tenant-config → Create/update config (billingMode, apiKey, timeout, tools)
|
||||||
* DELETE /api/v1/agent/tenant-config/api-key → Remove API key, revert to subscription billing
|
* DELETE /api/v1/agent/tenant-config/api-key → Remove API key, revert to subscription billing
|
||||||
*
|
*
|
||||||
* Note: API key is never returned in responses — only `hasApiKey: boolean` is exposed.
|
* Note: API key is never returned in responses — only `hasApiKey: boolean` is exposed.
|
||||||
*/
|
*/
|
||||||
import { Controller, Get, Put, Delete, Body, NotFoundException } from '@nestjs/common';
|
import { Controller, Get, Put, Delete, Body, Headers, NotFoundException } from '@nestjs/common';
|
||||||
import { TenantId } from '@it0/common';
|
|
||||||
import { TenantAgentConfigService, UpdateTenantAgentConfigDto } from '../../../infrastructure/services/tenant-agent-config.service';
|
import { TenantAgentConfigService, UpdateTenantAgentConfigDto } from '../../../infrastructure/services/tenant-agent-config.service';
|
||||||
|
|
||||||
@Controller('api/v1/agent/tenant-config')
|
@Controller('api/v1/agent/tenant-config')
|
||||||
|
|
@ -19,7 +18,18 @@ export class TenantAgentConfigController {
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
async getConfig(@TenantId() tenantId: string) {
|
async getConfig(@Headers('x-tenant-id') tenantId: string) {
|
||||||
|
if (!tenantId) {
|
||||||
|
return {
|
||||||
|
tenantId: '',
|
||||||
|
billingMode: 'subscription',
|
||||||
|
approvalTimeoutSeconds: 120,
|
||||||
|
toolWhitelist: [],
|
||||||
|
toolBlacklist: [],
|
||||||
|
hasApiKey: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const config = await this.tenantConfigService.findByTenantId(tenantId);
|
const config = await this.tenantConfigService.findByTenantId(tenantId);
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -46,10 +56,10 @@ export class TenantAgentConfigController {
|
||||||
|
|
||||||
@Put()
|
@Put()
|
||||||
async upsertConfig(
|
async upsertConfig(
|
||||||
@TenantId() tenantId: string,
|
@Headers('x-tenant-id') tenantId: string,
|
||||||
@Body() dto: UpdateTenantAgentConfigDto,
|
@Body() dto: UpdateTenantAgentConfigDto,
|
||||||
) {
|
) {
|
||||||
const config = await this.tenantConfigService.upsert(tenantId, dto);
|
const config = await this.tenantConfigService.upsert(tenantId || 'default', dto);
|
||||||
return {
|
return {
|
||||||
tenantId: config.tenantId,
|
tenantId: config.tenantId,
|
||||||
billingMode: config.billingMode,
|
billingMode: config.billingMode,
|
||||||
|
|
@ -62,8 +72,8 @@ export class TenantAgentConfigController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Delete('api-key')
|
@Delete('api-key')
|
||||||
async removeApiKey(@TenantId() tenantId: string) {
|
async removeApiKey(@Headers('x-tenant-id') tenantId: string) {
|
||||||
const config = await this.tenantConfigService.removeApiKey(tenantId);
|
const config = await this.tenantConfigService.removeApiKey(tenantId || 'default');
|
||||||
if (!config) {
|
if (!config) {
|
||||||
throw new NotFoundException('No agent config found for this tenant');
|
throw new NotFoundException('No agent config found for this tenant');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue