@open-mercato/ai-assistant 0.6.1-develop.3291.1.6fad645fd0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +30 -4
- package/dist/frontend/components/AiChatButton.js +3 -2
- package/dist/frontend/components/AiChatButton.js.map +2 -2
- package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-LOOP-001-006.spec.js +364 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-AGENT-LOOP-001-006.spec.js.map +7 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-RUNTIME-OVERRIDES-006-model-picker.spec.js +7 -7
- package/dist/modules/ai_assistant/__integration__/TC-AI-RUNTIME-OVERRIDES-006-model-picker.spec.js.map +2 -2
- package/dist/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.js +182 -0
- package/dist/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/loop-override/route.js +316 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/loop-override/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/models/route.js +8 -7
- package/dist/modules/ai_assistant/api/ai/agents/[agentId]/models/route.js.map +2 -2
- package/dist/modules/ai_assistant/api/ai/chat/route.js +43 -20
- package/dist/modules/ai_assistant/api/ai/chat/route.js.map +2 -2
- package/dist/modules/ai_assistant/api/settings/route.js +4 -3
- package/dist/modules/ai_assistant/api/settings/route.js.map +2 -2
- package/dist/modules/ai_assistant/api/usage/daily/route.js +111 -0
- package/dist/modules/ai_assistant/api/usage/daily/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/usage/sessions/[sessionId]/route.js +108 -0
- package/dist/modules/ai_assistant/api/usage/sessions/[sessionId]/route.js.map +7 -0
- package/dist/modules/ai_assistant/api/usage/sessions/route.js +153 -0
- package/dist/modules/ai_assistant/api/usage/sessions/route.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js +335 -38
- package/dist/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/allowlist/AiTenantAllowlistPageClient.js +2 -7
- package/dist/modules/ai_assistant/backend/config/ai-assistant/allowlist/AiTenantAllowlistPageClient.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js +44 -35
- package/dist/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.js.map +2 -2
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/AiUsageStatsPageClient.js +282 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/AiUsageStatsPageClient.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/page.js +10 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/page.js.map +7 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/page.meta.js +25 -0
- package/dist/modules/ai_assistant/backend/config/ai-assistant/usage/page.meta.js.map +7 -0
- package/dist/modules/ai_assistant/cli.js +12 -0
- package/dist/modules/ai_assistant/cli.js.map +2 -2
- package/dist/modules/ai_assistant/components/AiAssistantSettingsPageClient.js.map +1 -1
- package/dist/modules/ai_assistant/data/entities.js +177 -1
- package/dist/modules/ai_assistant/data/entities.js.map +2 -2
- package/dist/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.js +104 -2
- package/dist/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.js.map +2 -2
- package/dist/modules/ai_assistant/data/repositories/AiTokenUsageRepository.js +168 -0
- package/dist/modules/ai_assistant/data/repositories/AiTokenUsageRepository.js.map +7 -0
- package/dist/modules/ai_assistant/events.js +8 -0
- package/dist/modules/ai_assistant/events.js.map +2 -2
- package/dist/modules/ai_assistant/i18n/de.json +74 -1
- package/dist/modules/ai_assistant/i18n/en.json +74 -1
- package/dist/modules/ai_assistant/i18n/es.json +75 -2
- package/dist/modules/ai_assistant/i18n/pl.json +74 -1
- package/dist/modules/ai_assistant/lib/agent-policy.js.map +2 -2
- package/dist/modules/ai_assistant/lib/agent-runtime.js +588 -23
- package/dist/modules/ai_assistant/lib/agent-runtime.js.map +3 -3
- package/dist/modules/ai_assistant/lib/agent-tools.js +6 -1
- package/dist/modules/ai_assistant/lib/agent-tools.js.map +2 -2
- package/dist/modules/ai_assistant/lib/ai-agent-definition.js.map +2 -2
- package/dist/modules/ai_assistant/lib/model-factory.js +63 -22
- package/dist/modules/ai_assistant/lib/model-factory.js.map +2 -2
- package/dist/modules/ai_assistant/lib/token-usage-recorder.js +78 -0
- package/dist/modules/ai_assistant/lib/token-usage-recorder.js.map +7 -0
- package/dist/modules/ai_assistant/lib/usage-serialization.js +33 -0
- package/dist/modules/ai_assistant/lib/usage-serialization.js.map +7 -0
- package/dist/modules/ai_assistant/migrations/Migration20260508160000_ai_agent_loop_overrides.js +25 -0
- package/dist/modules/ai_assistant/migrations/Migration20260508160000_ai_agent_loop_overrides.js.map +7 -0
- package/dist/modules/ai_assistant/migrations/Migration20260508170000_ai_token_usage.js +88 -0
- package/dist/modules/ai_assistant/migrations/Migration20260508170000_ai_token_usage.js.map +7 -0
- package/dist/modules/ai_assistant/setup.js +34 -0
- package/dist/modules/ai_assistant/setup.js.map +2 -2
- package/dist/modules/ai_assistant/workers/ai-token-usage-prune.js +114 -0
- package/dist/modules/ai_assistant/workers/ai-token-usage-prune.js.map +7 -0
- package/generated/entities/ai_agent_runtime_override/index.ts +7 -0
- package/generated/entities/ai_token_usage_daily/index.ts +16 -0
- package/generated/entities/ai_token_usage_event/index.ts +19 -0
- package/generated/entities.ids.generated.ts +2 -0
- package/generated/entity-fields-registry.ts +47 -1
- package/package.json +15 -7
- package/src/frontend/components/AiChatButton.tsx +3 -2
- package/src/modules/ai_assistant/__integration__/TC-AI-AGENT-LOOP-001-006.spec.ts +521 -0
- package/src/modules/ai_assistant/__integration__/TC-AI-RUNTIME-OVERRIDES-006-model-picker.spec.ts +8 -8
- package/src/modules/ai_assistant/__integration__/TC-AI-TOKEN-USAGE-001-005.spec.ts +231 -0
- package/src/modules/ai_assistant/__tests__/events.test.ts +4 -3
- package/src/modules/ai_assistant/__tests__/settings-page-logic.test.ts +5 -5
- package/src/modules/ai_assistant/__tests__/token-usage-recorder.test.ts +109 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/loop-override/route.ts +388 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/models/__tests__/route.test.ts +5 -0
- package/src/modules/ai_assistant/api/ai/agents/[agentId]/models/route.ts +8 -7
- package/src/modules/ai_assistant/api/ai/chat/__tests__/route.test.ts +102 -5
- package/src/modules/ai_assistant/api/ai/chat/route.ts +55 -18
- package/src/modules/ai_assistant/api/settings/route.ts +5 -3
- package/src/modules/ai_assistant/api/usage/daily/__tests__/route.test.ts +159 -0
- package/src/modules/ai_assistant/api/usage/daily/route.ts +126 -0
- package/src/modules/ai_assistant/api/usage/sessions/[sessionId]/__tests__/route.test.ts +143 -0
- package/src/modules/ai_assistant/api/usage/sessions/[sessionId]/route.ts +130 -0
- package/src/modules/ai_assistant/api/usage/sessions/__tests__/route.test.ts +123 -0
- package/src/modules/ai_assistant/api/usage/sessions/route.ts +184 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/agents/AiAgentSettingsPageClient.tsx +372 -16
- package/src/modules/ai_assistant/backend/config/ai-assistant/allowlist/AiTenantAllowlistPageClient.tsx +1 -4
- package/src/modules/ai_assistant/backend/config/ai-assistant/playground/AiPlaygroundPageClient.tsx +26 -9
- package/src/modules/ai_assistant/backend/config/ai-assistant/usage/AiUsageStatsPageClient.tsx +469 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/usage/page.meta.ts +23 -0
- package/src/modules/ai_assistant/backend/config/ai-assistant/usage/page.tsx +12 -0
- package/src/modules/ai_assistant/cli.ts +18 -0
- package/src/modules/ai_assistant/components/AiAssistantSettingsPageClient.tsx +1 -1
- package/src/modules/ai_assistant/data/entities.ts +237 -0
- package/src/modules/ai_assistant/data/repositories/AiAgentRuntimeOverrideRepository.ts +135 -3
- package/src/modules/ai_assistant/data/repositories/AiTokenUsageRepository.ts +213 -0
- package/src/modules/ai_assistant/data/repositories/__tests__/AiAgentRuntimeOverrideRepository.test.ts +223 -0
- package/src/modules/ai_assistant/data/repositories/__tests__/AiTokenUsageRepository.test.ts +58 -0
- package/src/modules/ai_assistant/events.ts +8 -0
- package/src/modules/ai_assistant/i18n/de.json +74 -1
- package/src/modules/ai_assistant/i18n/en.json +74 -1
- package/src/modules/ai_assistant/i18n/es.json +75 -2
- package/src/modules/ai_assistant/i18n/pl.json +74 -1
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-loop-phase0.test.ts +439 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-loop-phase1.test.ts +243 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-loop-phase2.test.ts +388 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-loop-phase3.test.ts +359 -0
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime-phase4a.test.ts +2 -2
- package/src/modules/ai_assistant/lib/__tests__/agent-runtime.test.ts +2 -1
- package/src/modules/ai_assistant/lib/__tests__/max-steps-budget.integration.test.ts +12 -13
- package/src/modules/ai_assistant/lib/__tests__/model-factory.test.ts +77 -14
- package/src/modules/ai_assistant/lib/agent-policy.ts +9 -0
- package/src/modules/ai_assistant/lib/agent-runtime.ts +1148 -43
- package/src/modules/ai_assistant/lib/agent-tools.ts +5 -1
- package/src/modules/ai_assistant/lib/ai-agent-definition.ts +289 -2
- package/src/modules/ai_assistant/lib/model-factory.ts +128 -43
- package/src/modules/ai_assistant/lib/token-usage-recorder.ts +122 -0
- package/src/modules/ai_assistant/lib/usage-serialization.ts +29 -0
- package/src/modules/ai_assistant/migrations/.snapshot-open-mercato.json +791 -0
- package/src/modules/ai_assistant/migrations/Migration20260508160000_ai_agent_loop_overrides.ts +25 -0
- package/src/modules/ai_assistant/migrations/Migration20260508170000_ai_token_usage.ts +89 -0
- package/src/modules/ai_assistant/setup.ts +49 -0
- package/src/modules/ai_assistant/workers/__tests__/ai-token-usage-prune.test.ts +144 -0
- package/src/modules/ai_assistant/workers/ai-token-usage-prune.ts +188 -0
|
@@ -36,6 +36,13 @@ type Row = {
|
|
|
36
36
|
createdAt: Date
|
|
37
37
|
updatedAt: Date
|
|
38
38
|
deletedAt: Date | null
|
|
39
|
+
loopDisabled: boolean | null
|
|
40
|
+
loopMaxSteps: number | null
|
|
41
|
+
loopMaxToolCalls: number | null
|
|
42
|
+
loopMaxWallClockMs: number | null
|
|
43
|
+
loopMaxTokens: number | null
|
|
44
|
+
loopStopWhenJson: unknown | null
|
|
45
|
+
loopActiveToolsJson: unknown | null
|
|
39
46
|
}
|
|
40
47
|
|
|
41
48
|
let idCounter = 0
|
|
@@ -93,6 +100,13 @@ function mockEm() {
|
|
|
93
100
|
createdAt: new Date(),
|
|
94
101
|
updatedAt: new Date(),
|
|
95
102
|
deletedAt: data.deletedAt ?? null,
|
|
103
|
+
loopDisabled: data.loopDisabled ?? null,
|
|
104
|
+
loopMaxSteps: data.loopMaxSteps ?? null,
|
|
105
|
+
loopMaxToolCalls: data.loopMaxToolCalls ?? null,
|
|
106
|
+
loopMaxWallClockMs: data.loopMaxWallClockMs ?? null,
|
|
107
|
+
loopMaxTokens: data.loopMaxTokens ?? null,
|
|
108
|
+
loopStopWhenJson: data.loopStopWhenJson ?? null,
|
|
109
|
+
loopActiveToolsJson: data.loopActiveToolsJson ?? null,
|
|
96
110
|
}
|
|
97
111
|
store.push(row)
|
|
98
112
|
return row
|
|
@@ -335,3 +349,212 @@ describe('AiAgentRuntimeOverrideRepository', () => {
|
|
|
335
349
|
void AiAgentRuntimeOverride
|
|
336
350
|
})
|
|
337
351
|
})
|
|
352
|
+
|
|
353
|
+
describe('AiAgentRuntimeOverrideRepository — loop override validation (Phase 1782-3)', () => {
|
|
354
|
+
describe('loopStopWhenJson validation', () => {
|
|
355
|
+
it('accepts valid stepCount items', async () => {
|
|
356
|
+
const em = mockEm()
|
|
357
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
358
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
359
|
+
|
|
360
|
+
await expect(
|
|
361
|
+
repo.upsertDefault(
|
|
362
|
+
{
|
|
363
|
+
agentId: 'catalog.assistant',
|
|
364
|
+
loopStopWhenJson: [{ kind: 'stepCount', count: 5 }],
|
|
365
|
+
},
|
|
366
|
+
ctx,
|
|
367
|
+
),
|
|
368
|
+
).resolves.toBeDefined()
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
it('accepts valid hasToolCall items', async () => {
|
|
372
|
+
const em = mockEm()
|
|
373
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
374
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
375
|
+
|
|
376
|
+
await expect(
|
|
377
|
+
repo.upsertDefault(
|
|
378
|
+
{
|
|
379
|
+
agentId: 'catalog.assistant',
|
|
380
|
+
loopStopWhenJson: [{ kind: 'hasToolCall', toolName: 'catalog.update_product' }],
|
|
381
|
+
},
|
|
382
|
+
ctx,
|
|
383
|
+
),
|
|
384
|
+
).resolves.toBeDefined()
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
it('rejects kind "custom" with invalid_loop_override', async () => {
|
|
388
|
+
const em = mockEm()
|
|
389
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
390
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
391
|
+
|
|
392
|
+
await expect(
|
|
393
|
+
repo.upsertDefault(
|
|
394
|
+
{
|
|
395
|
+
agentId: 'catalog.assistant',
|
|
396
|
+
loopStopWhenJson: [{ kind: 'custom', stop: () => false } as any],
|
|
397
|
+
},
|
|
398
|
+
ctx,
|
|
399
|
+
),
|
|
400
|
+
).rejects.toMatchObject({ name: 'AiAgentRuntimeOverrideValidationError', code: 'invalid_loop_override' })
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
it('rejects unknown kind with invalid_loop_override', async () => {
|
|
404
|
+
const em = mockEm()
|
|
405
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
406
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
407
|
+
|
|
408
|
+
await expect(
|
|
409
|
+
repo.upsertDefault(
|
|
410
|
+
{
|
|
411
|
+
agentId: 'catalog.assistant',
|
|
412
|
+
loopStopWhenJson: [{ kind: 'unknownKind' } as any],
|
|
413
|
+
},
|
|
414
|
+
ctx,
|
|
415
|
+
),
|
|
416
|
+
).rejects.toMatchObject({ name: 'AiAgentRuntimeOverrideValidationError', code: 'invalid_loop_override' })
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
it('rejects stepCount without numeric count', async () => {
|
|
420
|
+
const em = mockEm()
|
|
421
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
422
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
423
|
+
|
|
424
|
+
await expect(
|
|
425
|
+
repo.upsertDefault(
|
|
426
|
+
{
|
|
427
|
+
agentId: 'catalog.assistant',
|
|
428
|
+
loopStopWhenJson: [{ kind: 'stepCount' } as any],
|
|
429
|
+
},
|
|
430
|
+
ctx,
|
|
431
|
+
),
|
|
432
|
+
).rejects.toMatchObject({ code: 'invalid_loop_override' })
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
it('rejects hasToolCall without string toolName', async () => {
|
|
436
|
+
const em = mockEm()
|
|
437
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
438
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
439
|
+
|
|
440
|
+
await expect(
|
|
441
|
+
repo.upsertDefault(
|
|
442
|
+
{
|
|
443
|
+
agentId: 'catalog.assistant',
|
|
444
|
+
loopStopWhenJson: [{ kind: 'hasToolCall' } as any],
|
|
445
|
+
},
|
|
446
|
+
ctx,
|
|
447
|
+
),
|
|
448
|
+
).rejects.toMatchObject({ code: 'invalid_loop_override' })
|
|
449
|
+
})
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
describe('loopActiveToolsJson validation', () => {
|
|
453
|
+
it('accepts valid tool names', async () => {
|
|
454
|
+
const em = mockEm()
|
|
455
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
456
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
457
|
+
|
|
458
|
+
await expect(
|
|
459
|
+
repo.upsertDefault(
|
|
460
|
+
{
|
|
461
|
+
agentId: 'catalog.assistant',
|
|
462
|
+
loopActiveToolsJson: ['catalog.list_products', 'search.hybrid_search'],
|
|
463
|
+
agentAllowedTools: ['catalog.list_products', 'search.hybrid_search', 'meta.describe_agent'],
|
|
464
|
+
},
|
|
465
|
+
ctx,
|
|
466
|
+
),
|
|
467
|
+
).resolves.toBeDefined()
|
|
468
|
+
})
|
|
469
|
+
|
|
470
|
+
it('rejects tools outside the agent allowlist when agentAllowedTools is provided', async () => {
|
|
471
|
+
const em = mockEm()
|
|
472
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
473
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
474
|
+
|
|
475
|
+
await expect(
|
|
476
|
+
repo.upsertDefault(
|
|
477
|
+
{
|
|
478
|
+
agentId: 'catalog.assistant',
|
|
479
|
+
loopActiveToolsJson: ['catalog.list_products', 'admin.delete_all'],
|
|
480
|
+
agentAllowedTools: ['catalog.list_products'],
|
|
481
|
+
},
|
|
482
|
+
ctx,
|
|
483
|
+
),
|
|
484
|
+
).rejects.toMatchObject({ code: 'invalid_loop_override' })
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
it('accepts without agentAllowedTools (allowlist validation skipped)', async () => {
|
|
488
|
+
const em = mockEm()
|
|
489
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
490
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
491
|
+
|
|
492
|
+
await expect(
|
|
493
|
+
repo.upsertDefault(
|
|
494
|
+
{
|
|
495
|
+
agentId: 'catalog.assistant',
|
|
496
|
+
loopActiveToolsJson: ['any.tool'],
|
|
497
|
+
},
|
|
498
|
+
ctx,
|
|
499
|
+
),
|
|
500
|
+
).resolves.toBeDefined()
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
it('rejects non-array values', async () => {
|
|
504
|
+
const em = mockEm()
|
|
505
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
506
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
507
|
+
|
|
508
|
+
await expect(
|
|
509
|
+
repo.upsertDefault(
|
|
510
|
+
{
|
|
511
|
+
agentId: 'catalog.assistant',
|
|
512
|
+
loopActiveToolsJson: 'not-an-array' as any,
|
|
513
|
+
},
|
|
514
|
+
ctx,
|
|
515
|
+
),
|
|
516
|
+
).rejects.toMatchObject({ code: 'invalid_loop_override' })
|
|
517
|
+
})
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
describe('loop columns persisted on upsert', () => {
|
|
521
|
+
it('stores all loop columns on insert', async () => {
|
|
522
|
+
const em = mockEm()
|
|
523
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
524
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
525
|
+
|
|
526
|
+
const row = await repo.upsertDefault(
|
|
527
|
+
{
|
|
528
|
+
agentId: 'catalog.assistant',
|
|
529
|
+
loopDisabled: true,
|
|
530
|
+
loopMaxSteps: 3,
|
|
531
|
+
loopMaxToolCalls: 10,
|
|
532
|
+
loopMaxWallClockMs: 30000,
|
|
533
|
+
loopMaxTokens: 50000,
|
|
534
|
+
loopStopWhenJson: [{ kind: 'stepCount', count: 3 }],
|
|
535
|
+
loopActiveToolsJson: ['catalog.list_products'],
|
|
536
|
+
agentAllowedTools: ['catalog.list_products'],
|
|
537
|
+
},
|
|
538
|
+
ctx,
|
|
539
|
+
)
|
|
540
|
+
|
|
541
|
+
expect(row.loopDisabled).toBe(true)
|
|
542
|
+
expect(row.loopMaxSteps).toBe(3)
|
|
543
|
+
expect(row.loopMaxToolCalls).toBe(10)
|
|
544
|
+
expect(row.loopMaxWallClockMs).toBe(30000)
|
|
545
|
+
expect(row.loopMaxTokens).toBe(50000)
|
|
546
|
+
expect(row.loopStopWhenJson).toEqual([{ kind: 'stepCount', count: 3 }])
|
|
547
|
+
expect(row.loopActiveToolsJson).toEqual(['catalog.list_products'])
|
|
548
|
+
})
|
|
549
|
+
|
|
550
|
+
it('updates existing loop columns on second upsert', async () => {
|
|
551
|
+
const em = mockEm()
|
|
552
|
+
const repo = new AiAgentRuntimeOverrideRepository(em)
|
|
553
|
+
const ctx = { tenantId: 't1', organizationId: null, userId: 'u1' }
|
|
554
|
+
|
|
555
|
+
await repo.upsertDefault({ agentId: 'catalog.assistant', loopDisabled: false }, ctx)
|
|
556
|
+
const updated = await repo.upsertDefault({ agentId: 'catalog.assistant', loopDisabled: true }, ctx)
|
|
557
|
+
expect(updated.loopDisabled).toBe(true)
|
|
558
|
+
})
|
|
559
|
+
})
|
|
560
|
+
})
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AiTokenUsageRepository } from '../AiTokenUsageRepository'
|
|
2
|
+
|
|
3
|
+
function makeRepository() {
|
|
4
|
+
const execute = jest.fn(async () => [{ already_seen: false }])
|
|
5
|
+
const em = {
|
|
6
|
+
getConnection: () => ({ execute }),
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
repo: new AiTokenUsageRepository(em as never),
|
|
11
|
+
execute,
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function baseInput(overrides: Record<string, unknown> = {}) {
|
|
16
|
+
return {
|
|
17
|
+
tenantId: '00000000-0000-0000-0000-000000000001',
|
|
18
|
+
organizationId: null,
|
|
19
|
+
day: '2026-05-13',
|
|
20
|
+
agentId: 'customers.account_assistant',
|
|
21
|
+
modelId: 'gpt-5-mini',
|
|
22
|
+
providerId: 'openai',
|
|
23
|
+
sessionId: '00000000-0000-0000-0000-000000000002',
|
|
24
|
+
inputTokens: 100,
|
|
25
|
+
outputTokens: 25,
|
|
26
|
+
cachedInputTokens: 0,
|
|
27
|
+
reasoningTokens: 0,
|
|
28
|
+
...overrides,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
describe('AiTokenUsageRepository', () => {
|
|
33
|
+
it('targets the tenant-wide partial unique index in daily rollup upserts', async () => {
|
|
34
|
+
const { repo, execute } = makeRepository()
|
|
35
|
+
|
|
36
|
+
await repo.upsertDaily(baseInput())
|
|
37
|
+
|
|
38
|
+
const upsertSql = String(execute.mock.calls[1]?.[0] ?? '')
|
|
39
|
+
expect(upsertSql).toContain('on conflict (tenant_id, day, agent_id, model_id)')
|
|
40
|
+
expect(upsertSql).toContain('where organization_id is null')
|
|
41
|
+
expect(upsertSql).not.toContain('on constraint')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('targets the organization-scoped partial unique index in daily rollup upserts', async () => {
|
|
45
|
+
const { repo, execute } = makeRepository()
|
|
46
|
+
|
|
47
|
+
await repo.upsertDaily(baseInput({
|
|
48
|
+
organizationId: '00000000-0000-0000-0000-000000000003',
|
|
49
|
+
}))
|
|
50
|
+
|
|
51
|
+
const upsertSql = String(execute.mock.calls[1]?.[0] ?? '')
|
|
52
|
+
expect(upsertSql).toContain(
|
|
53
|
+
'on conflict (tenant_id, day, agent_id, model_id, organization_id)',
|
|
54
|
+
)
|
|
55
|
+
expect(upsertSql).toContain('where organization_id is not null')
|
|
56
|
+
expect(upsertSql).not.toContain('on constraint')
|
|
57
|
+
})
|
|
58
|
+
})
|
|
@@ -39,6 +39,14 @@ const events = [
|
|
|
39
39
|
entity: 'ai_pending_action',
|
|
40
40
|
category: 'system' as const,
|
|
41
41
|
},
|
|
42
|
+
{
|
|
43
|
+
id: 'ai.token_usage.recorded',
|
|
44
|
+
label: 'AI Token Usage Recorded',
|
|
45
|
+
entity: 'token_usage',
|
|
46
|
+
category: 'system' as const,
|
|
47
|
+
clientBroadcast: false,
|
|
48
|
+
portalBroadcast: false,
|
|
49
|
+
},
|
|
42
50
|
] as const
|
|
43
51
|
|
|
44
52
|
export const eventsConfig = createModuleEvents({
|
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
"ai_assistant.agents.empty.title": "Für Ihre Rolle sind noch keine KI-Agenten registriert.",
|
|
9
9
|
"ai_assistant.agents.loadErrorTitle": "KI-Agenten konnten nicht geladen werden",
|
|
10
10
|
"ai_assistant.agents.loadingAgents": "KI-Agenten werden geladen...",
|
|
11
|
+
"ai_assistant.agents.loop_policy.clear": "Überschreibung löschen",
|
|
12
|
+
"ai_assistant.agents.loop_policy.clearedMessage": "Loop-Richtlinien-Überschreibung gelöscht; Agent verwendet seine deklarierten Standardwerte.",
|
|
13
|
+
"ai_assistant.agents.loop_policy.disabledBadge": "Loop deaktiviert",
|
|
14
|
+
"ai_assistant.agents.loop_policy.errorTitle": "Loop-Richtlinie konnte nicht aktualisiert werden",
|
|
15
|
+
"ai_assistant.agents.loop_policy.killSwitchDescription": "Wenn aktiviert, läuft der Agent als einzelner Modellaufruf ohne Toolschleife.",
|
|
16
|
+
"ai_assistant.agents.loop_policy.killSwitchLabel": "Kill-Schalter",
|
|
17
|
+
"ai_assistant.agents.loop_policy.loadErrorTitle": "Loop-Richtlinie konnte nicht geladen werden",
|
|
18
|
+
"ai_assistant.agents.loop_policy.loading": "Loop-Richtlinie wird geladen...",
|
|
19
|
+
"ai_assistant.agents.loop_policy.maxStepsLabel": "Max. Schritte",
|
|
20
|
+
"ai_assistant.agents.loop_policy.maxTokensLabel": "Max. Tokens",
|
|
21
|
+
"ai_assistant.agents.loop_policy.maxToolCallsLabel": "Max. Tool-Aufrufe",
|
|
22
|
+
"ai_assistant.agents.loop_policy.maxWallClockMsLabel": "Max. Echtzeit (ms)",
|
|
23
|
+
"ai_assistant.agents.loop_policy.noOverridePlaceholder": "Keine Überschreibung",
|
|
24
|
+
"ai_assistant.agents.loop_policy.save": "Überschreibung speichern",
|
|
25
|
+
"ai_assistant.agents.loop_policy.savedMessage": "Loop-Richtlinien-Überschreibung gespeichert.",
|
|
26
|
+
"ai_assistant.agents.loop_policy.savedTitle": "Loop-Richtlinie aktualisiert",
|
|
27
|
+
"ai_assistant.agents.loop_policy.subtitle": "Legen Sie mandantenweite Budget-Limits fest oder deaktivieren Sie den agentischen Loop für diesen Agenten.",
|
|
28
|
+
"ai_assistant.agents.loop_policy.title": "Loop-Richtlinie",
|
|
11
29
|
"ai_assistant.agents.meta.executionMode": "Ausführungsmodus",
|
|
12
30
|
"ai_assistant.agents.meta.id": "Agenten-ID",
|
|
13
31
|
"ai_assistant.agents.meta.maxSteps": "Max. Schritte",
|
|
@@ -17,6 +35,22 @@
|
|
|
17
35
|
"ai_assistant.agents.meta.readOnlyNo": "Nein",
|
|
18
36
|
"ai_assistant.agents.meta.readOnlyYes": "Ja",
|
|
19
37
|
"ai_assistant.agents.meta.unlimited": "Unbegrenzt",
|
|
38
|
+
"ai_assistant.agents.model_override.allowlistCustom": "benutzerdefiniert",
|
|
39
|
+
"ai_assistant.agents.model_override.allowlistInherited": "geerbt",
|
|
40
|
+
"ai_assistant.agents.model_override.allowlistReset": "Erben",
|
|
41
|
+
"ai_assistant.agents.model_override.allowlistSave": "Auswahl speichern",
|
|
42
|
+
"ai_assistant.agents.model_override.anyProvider": "erste konfigurierte",
|
|
43
|
+
"ai_assistant.agents.model_override.clear": "Überschreibung löschen",
|
|
44
|
+
"ai_assistant.agents.model_override.codeDefault": "Im Code deklarierter Standard",
|
|
45
|
+
"ai_assistant.agents.model_override.defaultBadge": "Standard",
|
|
46
|
+
"ai_assistant.agents.model_override.model": "Modell",
|
|
47
|
+
"ai_assistant.agents.model_override.noOverride": "Keine agentenspezifische Überschreibung",
|
|
48
|
+
"ai_assistant.agents.model_override.provider": "Anbieter",
|
|
49
|
+
"ai_assistant.agents.model_override.providerDefault": "Anbieter-Standard",
|
|
50
|
+
"ai_assistant.agents.model_override.save": "Überschreibung speichern",
|
|
51
|
+
"ai_assistant.agents.model_override.saved": "Modell-Überschreibung gespeichert.",
|
|
52
|
+
"ai_assistant.agents.model_override.tenantOverride": "Mandanten-Überschreibung",
|
|
53
|
+
"ai_assistant.agents.model_override.title": "Anbieter und Modell",
|
|
20
54
|
"ai_assistant.agents.mutation_policy.clear": "Überschreibung löschen",
|
|
21
55
|
"ai_assistant.agents.mutation_policy.clearedMessage": "Überschreibung der Mutationsrichtlinie gelöscht; Agent verwendet die im Code deklarierte Richtlinie.",
|
|
22
56
|
"ai_assistant.agents.mutation_policy.codeDeclared": "Im Code deklariert",
|
|
@@ -112,6 +146,7 @@
|
|
|
112
146
|
"ai_assistant.allowlist.save.success": "Liste gespeichert.",
|
|
113
147
|
"ai_assistant.allowlist.subtitle": "Schränke Anbieter und Modelle ein, die für diesen Mandanten verwendet werden dürfen. Die ENV-Liste ist die äußere Beschränkung — die Mandantenauswahl engt sie weiter ein.",
|
|
114
148
|
"ai_assistant.allowlist.title": "Anbieter- & Modell-Allowlist",
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Agent-Aufgaben",
|
|
115
150
|
"ai_assistant.chat.assistantRoleLabel": "Assistent",
|
|
116
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
117
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +292,8 @@
|
|
|
257
292
|
"ai_assistant.launcher.welcome.suggestion3": "Suggest things to try",
|
|
258
293
|
"ai_assistant.launcher.welcome.suggestion4": "How do I use this assistant?",
|
|
259
294
|
"ai_assistant.launcher.writesBadge": "Can write",
|
|
295
|
+
"ai_assistant.loop.disabledBanner.description": "Der agentische Loop wurde für diesen Agenten von einem Mandantenadministrator deaktiviert. Jeder Durchlauf wird als einzelner Modellaufruf ausgeführt. Um den Loop wieder zu aktivieren, aktualisieren Sie die Loop-Richtlinie in den KI-Assistenten-Einstellungen.",
|
|
296
|
+
"ai_assistant.loop.disabledBanner.title": "Agenten-Loop durch Mandantenrichtlinie deaktiviert",
|
|
260
297
|
"ai_assistant.mcp.apiKeyLabel": "API-Schlüssel:",
|
|
261
298
|
"ai_assistant.mcp.close": "Schließen",
|
|
262
299
|
"ai_assistant.mcp.copied": "Kopiert!",
|
|
@@ -272,9 +309,11 @@
|
|
|
272
309
|
"ai_assistant.modelPicker.activeBadge": "aktiv",
|
|
273
310
|
"ai_assistant.modelPicker.defaultBadge": "Standard",
|
|
274
311
|
"ai_assistant.modelPicker.defaultLabel": "Modell: Standard",
|
|
312
|
+
"ai_assistant.modelPicker.defaultWithModelLabel": "Standard: {{model}}",
|
|
275
313
|
"ai_assistant.modelPicker.listAriaLabel": "Verfügbare Modelle",
|
|
276
314
|
"ai_assistant.modelPicker.triggerAriaLabel": "KI-Modell auswählen",
|
|
277
315
|
"ai_assistant.modelPicker.useDefault": "Standard des Agenten verwenden",
|
|
316
|
+
"ai_assistant.modelPicker.useDefaultWithModel": "Standard des Agenten verwenden: {{model}}",
|
|
278
317
|
"ai_assistant.playground.agentPickerLabel": "Agent",
|
|
279
318
|
"ai_assistant.playground.chat.notSupportedBody": "Wählen Sie einen Agenten, dessen Ausführungsmodus \"chat\" ist, oder wechseln Sie zum Objekt-Modus-Tab.",
|
|
280
319
|
"ai_assistant.playground.chat.notSupportedTitle": "Chat-Modus ist für diesen Agenten nicht verfügbar.",
|
|
@@ -346,6 +385,7 @@
|
|
|
346
385
|
"ai_assistant.settings.envKeyMissing": "{{key}} nicht gesetzt",
|
|
347
386
|
"ai_assistant.settings.generateMcpConfig": "MCP-Konfiguration generieren",
|
|
348
387
|
"ai_assistant.settings.generateSessionKey": "Sitzungsschlüssel generieren",
|
|
388
|
+
"ai_assistant.settings.launchDescription": "Öffnen Sie den KI-Assistenten von dieser Seite.",
|
|
349
389
|
"ai_assistant.settings.llmProviderLabel": "LLM-Anbieter:",
|
|
350
390
|
"ai_assistant.settings.loading": "Einstellungen werden geladen...",
|
|
351
391
|
"ai_assistant.settings.mcpAuthLabel": "MCP-Authentifizierung:",
|
|
@@ -362,6 +402,7 @@
|
|
|
362
402
|
"ai_assistant.settings.notAvailable": "Nicht verfügbar",
|
|
363
403
|
"ai_assistant.settings.notConfigured": "Nicht konfiguriert",
|
|
364
404
|
"ai_assistant.settings.openButton": "KI-Assistent öffnen",
|
|
405
|
+
"ai_assistant.settings.openSelectorButton": "KI-Assistenten öffnen",
|
|
365
406
|
"ai_assistant.settings.pageDescription": "KI-Assistent konfigurieren und überwachen",
|
|
366
407
|
"ai_assistant.settings.pageTitle": "KI-Assistent-Einstellungen",
|
|
367
408
|
"ai_assistant.settings.providerColumn": "Anbieter",
|
|
@@ -382,5 +423,37 @@
|
|
|
382
423
|
"ai_assistant.status.executing": "Tools werden ausgeführt...",
|
|
383
424
|
"ai_assistant.status.responding": "Antwort wird erstellt...",
|
|
384
425
|
"ai_assistant.status.thinking": "Denkt nach...",
|
|
385
|
-
"ai_assistant.status.working": "Arbeitet..."
|
|
426
|
+
"ai_assistant.status.working": "Arbeitet...",
|
|
427
|
+
"ai_assistant.usage.apply": "Anwenden",
|
|
428
|
+
"ai_assistant.usage.col.agent": "Agent",
|
|
429
|
+
"ai_assistant.usage.col.day": "Tag",
|
|
430
|
+
"ai_assistant.usage.col.finishReason": "Abschluss",
|
|
431
|
+
"ai_assistant.usage.col.inputTokens": "Eingabe",
|
|
432
|
+
"ai_assistant.usage.col.model": "Modell",
|
|
433
|
+
"ai_assistant.usage.col.outputTokens": "Ausgabe",
|
|
434
|
+
"ai_assistant.usage.col.session": "Sitzung",
|
|
435
|
+
"ai_assistant.usage.col.sessions": "Sitzungen",
|
|
436
|
+
"ai_assistant.usage.col.startedAt": "Gestartet",
|
|
437
|
+
"ai_assistant.usage.col.step": "Schritt",
|
|
438
|
+
"ai_assistant.usage.col.steps": "Schritte",
|
|
439
|
+
"ai_assistant.usage.dailyBreakdown": "Tägliche Aufschlüsselung",
|
|
440
|
+
"ai_assistant.usage.error": "Nutzungsdaten konnten nicht geladen werden.",
|
|
441
|
+
"ai_assistant.usage.errorDetail": "Sitzungsereignisse konnten nicht geladen werden.",
|
|
442
|
+
"ai_assistant.usage.errorSessions": "Sitzungen konnten nicht geladen werden.",
|
|
443
|
+
"ai_assistant.usage.from": "Von",
|
|
444
|
+
"ai_assistant.usage.inputTokens": "Eingabe-Tokens",
|
|
445
|
+
"ai_assistant.usage.loading": "Nutzungsdaten werden geladen...",
|
|
446
|
+
"ai_assistant.usage.loadingDetail": "Sitzungsereignisse werden geladen...",
|
|
447
|
+
"ai_assistant.usage.loadingSessions": "Sitzungen werden geladen...",
|
|
448
|
+
"ai_assistant.usage.navTitle": "KI-Nutzung",
|
|
449
|
+
"ai_assistant.usage.next": "Weiter",
|
|
450
|
+
"ai_assistant.usage.noSessions": "Für den ausgewählten Zeitraum wurden keine Sitzungen gefunden.",
|
|
451
|
+
"ai_assistant.usage.outputTokens": "Ausgabe-Tokens",
|
|
452
|
+
"ai_assistant.usage.prev": "Zurück",
|
|
453
|
+
"ai_assistant.usage.sessionDetail": "Sitzungsdetails",
|
|
454
|
+
"ai_assistant.usage.sessions": "Sitzungen",
|
|
455
|
+
"ai_assistant.usage.sessionsList": "Sitzungen",
|
|
456
|
+
"ai_assistant.usage.steps": "Schritte",
|
|
457
|
+
"ai_assistant.usage.title": "Token-Nutzungsstatistik",
|
|
458
|
+
"ai_assistant.usage.to": "Bis"
|
|
386
459
|
}
|
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
"ai_assistant.agents.empty.title": "No AI agents are registered for your role yet.",
|
|
9
9
|
"ai_assistant.agents.loadErrorTitle": "Failed to load AI agents",
|
|
10
10
|
"ai_assistant.agents.loadingAgents": "Loading AI agents...",
|
|
11
|
+
"ai_assistant.agents.loop_policy.clear": "Clear override",
|
|
12
|
+
"ai_assistant.agents.loop_policy.clearedMessage": "Loop policy override cleared; agent is using its declared defaults.",
|
|
13
|
+
"ai_assistant.agents.loop_policy.disabledBadge": "Loop disabled",
|
|
14
|
+
"ai_assistant.agents.loop_policy.errorTitle": "Failed to update loop policy",
|
|
15
|
+
"ai_assistant.agents.loop_policy.killSwitchDescription": "When enabled, the agent runs as a single model call with no tool loop.",
|
|
16
|
+
"ai_assistant.agents.loop_policy.killSwitchLabel": "Kill switch",
|
|
17
|
+
"ai_assistant.agents.loop_policy.loadErrorTitle": "Failed to load loop policy",
|
|
18
|
+
"ai_assistant.agents.loop_policy.loading": "Loading loop policy...",
|
|
19
|
+
"ai_assistant.agents.loop_policy.maxStepsLabel": "Max steps",
|
|
20
|
+
"ai_assistant.agents.loop_policy.maxTokensLabel": "Max tokens",
|
|
21
|
+
"ai_assistant.agents.loop_policy.maxToolCallsLabel": "Max tool calls",
|
|
22
|
+
"ai_assistant.agents.loop_policy.maxWallClockMsLabel": "Max wall-clock (ms)",
|
|
23
|
+
"ai_assistant.agents.loop_policy.noOverridePlaceholder": "No override",
|
|
24
|
+
"ai_assistant.agents.loop_policy.save": "Save override",
|
|
25
|
+
"ai_assistant.agents.loop_policy.savedMessage": "Loop policy override saved.",
|
|
26
|
+
"ai_assistant.agents.loop_policy.savedTitle": "Loop policy updated",
|
|
27
|
+
"ai_assistant.agents.loop_policy.subtitle": "Set per-tenant budget limits or disable the agentic loop for this agent.",
|
|
28
|
+
"ai_assistant.agents.loop_policy.title": "Loop policy",
|
|
11
29
|
"ai_assistant.agents.meta.executionMode": "Execution mode",
|
|
12
30
|
"ai_assistant.agents.meta.id": "Agent id",
|
|
13
31
|
"ai_assistant.agents.meta.maxSteps": "Max steps",
|
|
@@ -17,6 +35,22 @@
|
|
|
17
35
|
"ai_assistant.agents.meta.readOnlyNo": "No",
|
|
18
36
|
"ai_assistant.agents.meta.readOnlyYes": "Yes",
|
|
19
37
|
"ai_assistant.agents.meta.unlimited": "Unlimited",
|
|
38
|
+
"ai_assistant.agents.model_override.allowlistCustom": "custom",
|
|
39
|
+
"ai_assistant.agents.model_override.allowlistInherited": "inherited",
|
|
40
|
+
"ai_assistant.agents.model_override.allowlistReset": "Inherit",
|
|
41
|
+
"ai_assistant.agents.model_override.allowlistSave": "Save choices",
|
|
42
|
+
"ai_assistant.agents.model_override.anyProvider": "first configured",
|
|
43
|
+
"ai_assistant.agents.model_override.clear": "Clear override",
|
|
44
|
+
"ai_assistant.agents.model_override.codeDefault": "Code-declared default",
|
|
45
|
+
"ai_assistant.agents.model_override.defaultBadge": "default",
|
|
46
|
+
"ai_assistant.agents.model_override.model": "Model",
|
|
47
|
+
"ai_assistant.agents.model_override.noOverride": "No per-agent override",
|
|
48
|
+
"ai_assistant.agents.model_override.provider": "Provider",
|
|
49
|
+
"ai_assistant.agents.model_override.providerDefault": "provider default",
|
|
50
|
+
"ai_assistant.agents.model_override.save": "Save override",
|
|
51
|
+
"ai_assistant.agents.model_override.saved": "Model override saved.",
|
|
52
|
+
"ai_assistant.agents.model_override.tenantOverride": "Tenant override",
|
|
53
|
+
"ai_assistant.agents.model_override.title": "Provider and model",
|
|
20
54
|
"ai_assistant.agents.mutation_policy.clear": "Clear override",
|
|
21
55
|
"ai_assistant.agents.mutation_policy.clearedMessage": "Mutation policy override cleared; agent is using its code-declared policy.",
|
|
22
56
|
"ai_assistant.agents.mutation_policy.codeDeclared": "Code-declared",
|
|
@@ -112,6 +146,7 @@
|
|
|
112
146
|
"ai_assistant.allowlist.save.success": "Allowlist saved.",
|
|
113
147
|
"ai_assistant.allowlist.subtitle": "Limit which providers and models the runtime, settings, and chat picker may use for this tenant. The env allowlist is the outer constraint — tenant picks narrow it further.",
|
|
114
148
|
"ai_assistant.allowlist.title": "AI provider & model allowlist",
|
|
149
|
+
"ai_assistant.chat.agentTasksTitle": "Agent tasks",
|
|
115
150
|
"ai_assistant.chat.assistantRoleLabel": "Assistant",
|
|
116
151
|
"ai_assistant.chat.attachFile": "Attach file",
|
|
117
152
|
"ai_assistant.chat.betaChip": "beta",
|
|
@@ -257,6 +292,8 @@
|
|
|
257
292
|
"ai_assistant.launcher.welcome.suggestion3": "Suggest things to try",
|
|
258
293
|
"ai_assistant.launcher.welcome.suggestion4": "How do I use this assistant?",
|
|
259
294
|
"ai_assistant.launcher.writesBadge": "Can write",
|
|
295
|
+
"ai_assistant.loop.disabledBanner.description": "The agentic loop has been disabled for this agent by a tenant administrator. Each turn runs as a single model call. To re-enable the loop, update the Loop policy in AI assistant settings.",
|
|
296
|
+
"ai_assistant.loop.disabledBanner.title": "Agent loop disabled by tenant policy",
|
|
260
297
|
"ai_assistant.mcp.apiKeyLabel": "API Key:",
|
|
261
298
|
"ai_assistant.mcp.close": "Close",
|
|
262
299
|
"ai_assistant.mcp.copied": "Copied!",
|
|
@@ -272,9 +309,11 @@
|
|
|
272
309
|
"ai_assistant.modelPicker.activeBadge": "active",
|
|
273
310
|
"ai_assistant.modelPicker.defaultBadge": "default",
|
|
274
311
|
"ai_assistant.modelPicker.defaultLabel": "Model: Default",
|
|
312
|
+
"ai_assistant.modelPicker.defaultWithModelLabel": "Default: {{model}}",
|
|
275
313
|
"ai_assistant.modelPicker.listAriaLabel": "Available models",
|
|
276
314
|
"ai_assistant.modelPicker.triggerAriaLabel": "Select AI model",
|
|
277
315
|
"ai_assistant.modelPicker.useDefault": "Use agent default",
|
|
316
|
+
"ai_assistant.modelPicker.useDefaultWithModel": "Use agent default: {{model}}",
|
|
278
317
|
"ai_assistant.playground.agentPickerLabel": "Agent",
|
|
279
318
|
"ai_assistant.playground.chat.notSupportedBody": "Pick an agent whose execution mode is \"chat\", or switch to the object-mode tab.",
|
|
280
319
|
"ai_assistant.playground.chat.notSupportedTitle": "Chat mode is not available for this agent.",
|
|
@@ -346,6 +385,7 @@
|
|
|
346
385
|
"ai_assistant.settings.envKeyMissing": "{{key}} not set",
|
|
347
386
|
"ai_assistant.settings.generateMcpConfig": "Generate MCP Config",
|
|
348
387
|
"ai_assistant.settings.generateSessionKey": "Generate Session Key",
|
|
388
|
+
"ai_assistant.settings.launchDescription": "Open the AI assistant from this page.",
|
|
349
389
|
"ai_assistant.settings.llmProviderLabel": "LLM Provider:",
|
|
350
390
|
"ai_assistant.settings.loading": "Loading settings...",
|
|
351
391
|
"ai_assistant.settings.mcpAuthLabel": "MCP Authentication:",
|
|
@@ -362,6 +402,7 @@
|
|
|
362
402
|
"ai_assistant.settings.notAvailable": "Not available",
|
|
363
403
|
"ai_assistant.settings.notConfigured": "Not configured",
|
|
364
404
|
"ai_assistant.settings.openButton": "Open AI Assistant",
|
|
405
|
+
"ai_assistant.settings.openSelectorButton": "Open AI assistants",
|
|
365
406
|
"ai_assistant.settings.pageDescription": "Configure and monitor the AI assistant",
|
|
366
407
|
"ai_assistant.settings.pageTitle": "AI Assistant Settings",
|
|
367
408
|
"ai_assistant.settings.providerColumn": "Provider",
|
|
@@ -382,5 +423,37 @@
|
|
|
382
423
|
"ai_assistant.status.executing": "Executing tools...",
|
|
383
424
|
"ai_assistant.status.responding": "Responding...",
|
|
384
425
|
"ai_assistant.status.thinking": "Thinking...",
|
|
385
|
-
"ai_assistant.status.working": "Working..."
|
|
426
|
+
"ai_assistant.status.working": "Working...",
|
|
427
|
+
"ai_assistant.usage.apply": "Apply",
|
|
428
|
+
"ai_assistant.usage.col.agent": "Agent",
|
|
429
|
+
"ai_assistant.usage.col.day": "Day",
|
|
430
|
+
"ai_assistant.usage.col.finishReason": "Finish",
|
|
431
|
+
"ai_assistant.usage.col.inputTokens": "Input",
|
|
432
|
+
"ai_assistant.usage.col.model": "Model",
|
|
433
|
+
"ai_assistant.usage.col.outputTokens": "Output",
|
|
434
|
+
"ai_assistant.usage.col.session": "Session",
|
|
435
|
+
"ai_assistant.usage.col.sessions": "Sessions",
|
|
436
|
+
"ai_assistant.usage.col.startedAt": "Started",
|
|
437
|
+
"ai_assistant.usage.col.step": "Step",
|
|
438
|
+
"ai_assistant.usage.col.steps": "Steps",
|
|
439
|
+
"ai_assistant.usage.dailyBreakdown": "Daily breakdown",
|
|
440
|
+
"ai_assistant.usage.error": "Failed to load usage data.",
|
|
441
|
+
"ai_assistant.usage.errorDetail": "Failed to load session events.",
|
|
442
|
+
"ai_assistant.usage.errorSessions": "Failed to load sessions.",
|
|
443
|
+
"ai_assistant.usage.from": "From",
|
|
444
|
+
"ai_assistant.usage.inputTokens": "Input tokens",
|
|
445
|
+
"ai_assistant.usage.loading": "Loading usage data...",
|
|
446
|
+
"ai_assistant.usage.loadingDetail": "Loading session events...",
|
|
447
|
+
"ai_assistant.usage.loadingSessions": "Loading sessions...",
|
|
448
|
+
"ai_assistant.usage.navTitle": "AI Usage",
|
|
449
|
+
"ai_assistant.usage.next": "Next",
|
|
450
|
+
"ai_assistant.usage.noSessions": "No sessions found for the selected period.",
|
|
451
|
+
"ai_assistant.usage.outputTokens": "Output tokens",
|
|
452
|
+
"ai_assistant.usage.prev": "Previous",
|
|
453
|
+
"ai_assistant.usage.sessionDetail": "Session detail",
|
|
454
|
+
"ai_assistant.usage.sessions": "Sessions",
|
|
455
|
+
"ai_assistant.usage.sessionsList": "Sessions",
|
|
456
|
+
"ai_assistant.usage.steps": "Steps",
|
|
457
|
+
"ai_assistant.usage.title": "Token Usage Statistics",
|
|
458
|
+
"ai_assistant.usage.to": "To"
|
|
386
459
|
}
|