ideaco 1.1.5
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/.dockerignore +33 -0
- package/.nvmrc +1 -0
- package/ARCHITECTURE.md +394 -0
- package/Dockerfile +50 -0
- package/LICENSE +29 -0
- package/README.md +206 -0
- package/bin/i18n.js +46 -0
- package/bin/ideaco.js +494 -0
- package/deploy.sh +15 -0
- package/docker-compose.yml +30 -0
- package/electron/main.cjs +986 -0
- package/electron/preload.cjs +14 -0
- package/electron/web-backends.cjs +854 -0
- package/jsconfig.json +8 -0
- package/next.config.mjs +34 -0
- package/package.json +134 -0
- package/postcss.config.mjs +6 -0
- package/public/demo/dashboard.png +0 -0
- package/public/demo/employee.png +0 -0
- package/public/demo/messages.png +0 -0
- package/public/demo/office.png +0 -0
- package/public/demo/requirement.png +0 -0
- package/public/logo.jpeg +0 -0
- package/public/logo.png +0 -0
- package/scripts/prepare-electron.js +67 -0
- package/scripts/release.js +76 -0
- package/src/app/api/agents/[agentId]/chat/route.js +70 -0
- package/src/app/api/agents/[agentId]/conversations/route.js +35 -0
- package/src/app/api/agents/[agentId]/route.js +106 -0
- package/src/app/api/avatar/route.js +104 -0
- package/src/app/api/browse-dir/route.js +44 -0
- package/src/app/api/chat/route.js +265 -0
- package/src/app/api/company/factory-reset/route.js +43 -0
- package/src/app/api/company/route.js +82 -0
- package/src/app/api/departments/[deptId]/agents/[agentId]/dismiss/route.js +19 -0
- package/src/app/api/departments/route.js +92 -0
- package/src/app/api/group-chat-loop/events/route.js +70 -0
- package/src/app/api/group-chat-loop/route.js +94 -0
- package/src/app/api/mailbox/route.js +100 -0
- package/src/app/api/messages/route.js +14 -0
- package/src/app/api/providers/[id]/configure/route.js +21 -0
- package/src/app/api/providers/[id]/refresh-cookie/route.js +38 -0
- package/src/app/api/providers/[id]/test-cookie/route.js +28 -0
- package/src/app/api/providers/route.js +11 -0
- package/src/app/api/requirements/route.js +242 -0
- package/src/app/api/secretary/route.js +65 -0
- package/src/app/api/system/cli-backends/route.js +91 -0
- package/src/app/api/system/cron/route.js +110 -0
- package/src/app/api/system/knowledge/route.js +104 -0
- package/src/app/api/system/plugins/route.js +40 -0
- package/src/app/api/system/skills/route.js +46 -0
- package/src/app/api/system/status/route.js +46 -0
- package/src/app/api/talent-market/[profileId]/recall/route.js +22 -0
- package/src/app/api/talent-market/[profileId]/route.js +17 -0
- package/src/app/api/talent-market/route.js +26 -0
- package/src/app/api/teams/route.js +773 -0
- package/src/app/api/ws-files/[departmentId]/file/route.js +27 -0
- package/src/app/api/ws-files/[departmentId]/files/route.js +22 -0
- package/src/app/globals.css +130 -0
- package/src/app/layout.jsx +40 -0
- package/src/app/page.jsx +97 -0
- package/src/components/AgentChatModal.jsx +164 -0
- package/src/components/AgentDetailModal.jsx +425 -0
- package/src/components/AgentSpyModal.jsx +481 -0
- package/src/components/AvatarGrid.jsx +29 -0
- package/src/components/BossProfileModal.jsx +162 -0
- package/src/components/CachedAvatar.jsx +77 -0
- package/src/components/ChatPanel.jsx +219 -0
- package/src/components/ChatShared.jsx +255 -0
- package/src/components/DepartmentDetail.jsx +842 -0
- package/src/components/DepartmentView.jsx +367 -0
- package/src/components/FileReference.jsx +260 -0
- package/src/components/FilesView.jsx +465 -0
- package/src/components/GroupChatView.jsx +799 -0
- package/src/components/Mailbox.jsx +926 -0
- package/src/components/MessagesView.jsx +112 -0
- package/src/components/OnboardingGuide.jsx +209 -0
- package/src/components/OrgTree.jsx +151 -0
- package/src/components/Overview.jsx +391 -0
- package/src/components/PixelOffice.jsx +2281 -0
- package/src/components/ProviderGrid.jsx +551 -0
- package/src/components/ProvidersBoard.jsx +16 -0
- package/src/components/RequirementDetail.jsx +1279 -0
- package/src/components/RequirementsBoard.jsx +187 -0
- package/src/components/SecretarySettings.jsx +295 -0
- package/src/components/SetupWizard.jsx +388 -0
- package/src/components/Sidebar.jsx +169 -0
- package/src/components/SystemMonitor.jsx +808 -0
- package/src/components/TalentMarket.jsx +183 -0
- package/src/components/TeamDetail.jsx +697 -0
- package/src/core/agent/base-agent.js +104 -0
- package/src/core/agent/chat-store.js +602 -0
- package/src/core/agent/cli-agent/backends/claude-code/README.md +52 -0
- package/src/core/agent/cli-agent/backends/claude-code/config.js +27 -0
- package/src/core/agent/cli-agent/backends/codebuddy/README.md +236 -0
- package/src/core/agent/cli-agent/backends/codebuddy/config.js +27 -0
- package/src/core/agent/cli-agent/backends/codex/README.md +51 -0
- package/src/core/agent/cli-agent/backends/codex/config.js +27 -0
- package/src/core/agent/cli-agent/backends/index.js +27 -0
- package/src/core/agent/cli-agent/backends/registry.js +580 -0
- package/src/core/agent/cli-agent/index.js +154 -0
- package/src/core/agent/index.js +60 -0
- package/src/core/agent/llm-agent/client.js +320 -0
- package/src/core/agent/llm-agent/index.js +97 -0
- package/src/core/agent/message-bus.js +211 -0
- package/src/core/agent/session.js +608 -0
- package/src/core/agent/tools.js +596 -0
- package/src/core/agent/web-agent/backends/base-backend.js +180 -0
- package/src/core/agent/web-agent/backends/chatgpt/client.js +146 -0
- package/src/core/agent/web-agent/backends/chatgpt/config.js +148 -0
- package/src/core/agent/web-agent/backends/chatgpt/dom-scripts.js +303 -0
- package/src/core/agent/web-agent/backends/index.js +91 -0
- package/src/core/agent/web-agent/index.js +278 -0
- package/src/core/agent/web-agent/web-client.js +407 -0
- package/src/core/employee/base-employee.js +1088 -0
- package/src/core/employee/index.js +35 -0
- package/src/core/employee/knowledge.js +327 -0
- package/src/core/employee/lifecycle.js +990 -0
- package/src/core/employee/memory/index.js +642 -0
- package/src/core/employee/memory/store.js +143 -0
- package/src/core/employee/performance.js +224 -0
- package/src/core/employee/secretary.js +625 -0
- package/src/core/employee/skills.js +398 -0
- package/src/core/index.js +38 -0
- package/src/core/organization/company.js +2600 -0
- package/src/core/organization/department.js +737 -0
- package/src/core/organization/group-chat-loop.js +264 -0
- package/src/core/organization/index.js +8 -0
- package/src/core/organization/persistence.js +111 -0
- package/src/core/organization/team.js +267 -0
- package/src/core/organization/workforce/hr.js +377 -0
- package/src/core/organization/workforce/providers.js +468 -0
- package/src/core/organization/workforce/role-archetypes.js +805 -0
- package/src/core/organization/workforce/talent-market.js +205 -0
- package/src/core/prompts.js +532 -0
- package/src/core/requirement.js +1789 -0
- package/src/core/system/audit.js +483 -0
- package/src/core/system/cron.js +449 -0
- package/src/core/system/index.js +7 -0
- package/src/core/system/plugin.js +2183 -0
- package/src/core/utils/json-parse.js +188 -0
- package/src/core/workspace.js +239 -0
- package/src/lib/api-i18n.js +211 -0
- package/src/lib/avatar.js +268 -0
- package/src/lib/client-store.js +1025 -0
- package/src/lib/config-validator.js +483 -0
- package/src/lib/format-time.js +22 -0
- package/src/lib/hooks.js +414 -0
- package/src/lib/i18n.js +134 -0
- package/src/lib/paths.js +23 -0
- package/src/lib/store.js +72 -0
- package/src/locales/de.js +393 -0
- package/src/locales/en.js +1054 -0
- package/src/locales/es.js +393 -0
- package/src/locales/fr.js +393 -0
- package/src/locales/ja.js +501 -0
- package/src/locales/ko.js +513 -0
- package/src/locales/zh.js +828 -0
- package/tailwind.config.mjs +11 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Backends API - Manage CLI backends (detect, register, configure)
|
|
3
|
+
*/
|
|
4
|
+
import { NextResponse } from 'next/server';
|
|
5
|
+
import { cliBackendRegistry } from '@/core/agent/cli-agent/backends/index.js';
|
|
6
|
+
import { getCompany } from '@/lib/store';
|
|
7
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GET /api/system/cli-backends
|
|
11
|
+
* Get all CLI backend statuses
|
|
12
|
+
*/
|
|
13
|
+
export async function GET() {
|
|
14
|
+
try {
|
|
15
|
+
const backends = cliBackendRegistry.listAll();
|
|
16
|
+
return NextResponse.json({ data: backends });
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* POST /api/system/cli-backends
|
|
24
|
+
* CLI backend management operations
|
|
25
|
+
*
|
|
26
|
+
* Actions:
|
|
27
|
+
* - detect: detect all CLIs
|
|
28
|
+
* - detectOne: detect a single CLI
|
|
29
|
+
* - register: register a custom CLI
|
|
30
|
+
* - unregister: remove a custom CLI
|
|
31
|
+
*/
|
|
32
|
+
export async function POST(request) {
|
|
33
|
+
const t = getApiT(request);
|
|
34
|
+
try {
|
|
35
|
+
const body = await request.json();
|
|
36
|
+
const { action } = body;
|
|
37
|
+
|
|
38
|
+
switch (action) {
|
|
39
|
+
case 'detect': {
|
|
40
|
+
const results = await cliBackendRegistry.detectAll();
|
|
41
|
+
// Sync detected CLI backends into provider registry
|
|
42
|
+
const company = getCompany();
|
|
43
|
+
if (company) {
|
|
44
|
+
company.providerRegistry.syncCLIBackends(cliBackendRegistry);
|
|
45
|
+
}
|
|
46
|
+
return NextResponse.json({ data: results });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
case 'detectOne': {
|
|
50
|
+
const { backendId } = body;
|
|
51
|
+
if (!backendId) {
|
|
52
|
+
return NextResponse.json({ error: t('api.missingBackendId') }, { status: 400 });
|
|
53
|
+
}
|
|
54
|
+
const result = await cliBackendRegistry.detect(backendId);
|
|
55
|
+
return NextResponse.json({ data: { id: backendId, ...result } });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case 'register': {
|
|
59
|
+
const { config } = body;
|
|
60
|
+
if (!config || !config.id || !config.execCommand) {
|
|
61
|
+
return NextResponse.json({ error: t('api.cliConfigRequired') }, { status: 400 });
|
|
62
|
+
}
|
|
63
|
+
const registered = cliBackendRegistry.register(config);
|
|
64
|
+
// Detect immediately after registration
|
|
65
|
+
await cliBackendRegistry.detect(registered.id);
|
|
66
|
+
// Sync to provider registry
|
|
67
|
+
const company2 = getCompany();
|
|
68
|
+
if (company2) {
|
|
69
|
+
company2.providerRegistry.syncCLIBackends(cliBackendRegistry);
|
|
70
|
+
}
|
|
71
|
+
const backends = cliBackendRegistry.listAll();
|
|
72
|
+
return NextResponse.json({ data: backends });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
case 'unregister': {
|
|
76
|
+
const { backendId } = body;
|
|
77
|
+
if (!backendId) {
|
|
78
|
+
return NextResponse.json({ error: t('api.missingBackendId') }, { status: 400 });
|
|
79
|
+
}
|
|
80
|
+
cliBackendRegistry.unregister(backendId);
|
|
81
|
+
const backends = cliBackendRegistry.listAll();
|
|
82
|
+
return NextResponse.json({ data: backends });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
default:
|
|
86
|
+
return NextResponse.json({ error: t('api.pluginUnknownAction', { action }) }, { status: 400 });
|
|
87
|
+
}
|
|
88
|
+
} catch (error) {
|
|
89
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getCompany } from '@/lib/store';
|
|
3
|
+
import { cronScheduler } from '@/core/system/cron.js';
|
|
4
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* GET /api/system/cron - List all cron jobs
|
|
8
|
+
*/
|
|
9
|
+
export async function GET() {
|
|
10
|
+
try {
|
|
11
|
+
return NextResponse.json({
|
|
12
|
+
data: {
|
|
13
|
+
summary: cronScheduler.getSummary(),
|
|
14
|
+
jobs: cronScheduler.listJobs(),
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
} catch (error) {
|
|
18
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* POST /api/system/cron - Manage cron jobs
|
|
24
|
+
*
|
|
25
|
+
* Actions:
|
|
26
|
+
* - create: { name, cronExpression, agentId, taskPrompt, description? }
|
|
27
|
+
* - pause: { jobId }
|
|
28
|
+
* - resume: { jobId }
|
|
29
|
+
* - trigger: { jobId }
|
|
30
|
+
* - delete: { jobId }
|
|
31
|
+
*/
|
|
32
|
+
export async function POST(request) {
|
|
33
|
+
const t = getApiT(request);
|
|
34
|
+
const company = getCompany();
|
|
35
|
+
if (!company) {
|
|
36
|
+
return NextResponse.json({ error: t('api.noCompany') }, { status: 400 });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const body = await request.json();
|
|
41
|
+
const { action = 'create' } = body;
|
|
42
|
+
|
|
43
|
+
switch (action) {
|
|
44
|
+
case 'create': {
|
|
45
|
+
const { name, cronExpression, agentId, taskPrompt, description } = body;
|
|
46
|
+
if (!name || !cronExpression || !agentId || !taskPrompt) {
|
|
47
|
+
return NextResponse.json(
|
|
48
|
+
{ error: t('api.cronMissingFields') },
|
|
49
|
+
{ status: 400 }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Verify agent exists
|
|
54
|
+
let agentFound = false;
|
|
55
|
+
for (const dept of company.departments.values()) {
|
|
56
|
+
if (dept.agents.has(agentId)) {
|
|
57
|
+
agentFound = true;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (!agentFound) {
|
|
62
|
+
return NextResponse.json({ error: t('api.agentNotFoundId', { id: agentId }) }, { status: 404 });
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const job = cronScheduler.addJob({
|
|
66
|
+
name,
|
|
67
|
+
cronExpression,
|
|
68
|
+
agentId,
|
|
69
|
+
taskPrompt,
|
|
70
|
+
description: description || '',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return NextResponse.json({
|
|
74
|
+
data: {
|
|
75
|
+
id: job.id,
|
|
76
|
+
name: job.name,
|
|
77
|
+
cronExpression: job.cronExpression,
|
|
78
|
+
nextRun: job.nextRun?.toISOString(),
|
|
79
|
+
status: job.status,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
case 'pause': {
|
|
85
|
+
cronScheduler.pauseJob(body.jobId);
|
|
86
|
+
return NextResponse.json({ data: { success: true } });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
case 'resume': {
|
|
90
|
+
cronScheduler.resumeJob(body.jobId);
|
|
91
|
+
return NextResponse.json({ data: { success: true } });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
case 'trigger': {
|
|
95
|
+
await cronScheduler.triggerJob(body.jobId);
|
|
96
|
+
return NextResponse.json({ data: { success: true } });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
case 'delete': {
|
|
100
|
+
cronScheduler.removeJob(body.jobId);
|
|
101
|
+
return NextResponse.json({ data: { success: true } });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
default:
|
|
105
|
+
return NextResponse.json({ error: t('api.pluginUnknownAction', { action }) }, { status: 400 });
|
|
106
|
+
}
|
|
107
|
+
} catch (error) {
|
|
108
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { knowledgeManager, KnowledgeType, EntryType } from '@/core/employee/knowledge.js';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GET /api/system/knowledge - Get knowledge base list or search
|
|
7
|
+
*/
|
|
8
|
+
export async function GET(request) {
|
|
9
|
+
const t = getApiT(request);
|
|
10
|
+
try {
|
|
11
|
+
const { searchParams } = new URL(request.url);
|
|
12
|
+
const query = searchParams.get('query');
|
|
13
|
+
const kbId = searchParams.get('kbId');
|
|
14
|
+
|
|
15
|
+
// Search
|
|
16
|
+
if (query) {
|
|
17
|
+
const results = knowledgeManager.search(query, { limit: 20 });
|
|
18
|
+
return NextResponse.json({ data: results });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Get entries for a specific knowledge base
|
|
22
|
+
if (kbId) {
|
|
23
|
+
const kb = knowledgeManager.get(kbId);
|
|
24
|
+
if (!kb) return NextResponse.json({ error: t('api.kbNotFound') }, { status: 404 });
|
|
25
|
+
return NextResponse.json({
|
|
26
|
+
data: {
|
|
27
|
+
id: kb.id,
|
|
28
|
+
name: kb.name,
|
|
29
|
+
description: kb.description,
|
|
30
|
+
type: kb.type,
|
|
31
|
+
enabled: kb.enabled,
|
|
32
|
+
entries: kb.listEntries(),
|
|
33
|
+
stats: kb.getStats(),
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// List all knowledge bases
|
|
39
|
+
return NextResponse.json({
|
|
40
|
+
data: {
|
|
41
|
+
bases: knowledgeManager.list(),
|
|
42
|
+
stats: knowledgeManager.getOverallStats(),
|
|
43
|
+
types: KnowledgeType,
|
|
44
|
+
entryTypes: EntryType,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* POST /api/system/knowledge - Knowledge base management operations
|
|
54
|
+
* Actions: create, addEntry, removeEntry, delete, toggle
|
|
55
|
+
*/
|
|
56
|
+
export async function POST(request) {
|
|
57
|
+
const t = getApiT(request);
|
|
58
|
+
try {
|
|
59
|
+
const body = await request.json();
|
|
60
|
+
const { action } = body;
|
|
61
|
+
|
|
62
|
+
switch (action) {
|
|
63
|
+
case 'create': {
|
|
64
|
+
const kb = knowledgeManager.create({
|
|
65
|
+
name: body.name,
|
|
66
|
+
description: body.description,
|
|
67
|
+
type: body.type || KnowledgeType.GLOBAL,
|
|
68
|
+
ownerId: body.ownerId || null,
|
|
69
|
+
});
|
|
70
|
+
return NextResponse.json({ data: { id: kb.id, success: true } });
|
|
71
|
+
}
|
|
72
|
+
case 'addEntry': {
|
|
73
|
+
const entry = knowledgeManager.addEntry(body.kbId, {
|
|
74
|
+
title: body.title,
|
|
75
|
+
content: body.content,
|
|
76
|
+
type: body.entryType || EntryType.NOTE,
|
|
77
|
+
tags: body.tags || [],
|
|
78
|
+
importance: body.importance || 0.5,
|
|
79
|
+
source: body.source || null,
|
|
80
|
+
createdBy: body.createdBy || null,
|
|
81
|
+
});
|
|
82
|
+
return NextResponse.json({ data: { id: entry.id, success: true } });
|
|
83
|
+
}
|
|
84
|
+
case 'removeEntry': {
|
|
85
|
+
const result = knowledgeManager.removeEntry(body.kbId, body.entryId);
|
|
86
|
+
return NextResponse.json({ data: { success: result } });
|
|
87
|
+
}
|
|
88
|
+
case 'delete': {
|
|
89
|
+
const result = knowledgeManager.delete(body.kbId);
|
|
90
|
+
return NextResponse.json({ data: { success: result } });
|
|
91
|
+
}
|
|
92
|
+
case 'toggle': {
|
|
93
|
+
const kb = knowledgeManager.get(body.kbId);
|
|
94
|
+
if (!kb) return NextResponse.json({ error: t('api.kbNotFound') }, { status: 404 });
|
|
95
|
+
kb.enabled = !kb.enabled;
|
|
96
|
+
return NextResponse.json({ data: { success: true, enabled: kb.enabled } });
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
return NextResponse.json({ error: t('api.kbUnknownAction', { action }) }, { status: 400 });
|
|
100
|
+
}
|
|
101
|
+
} catch (error) {
|
|
102
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { pluginRegistry } from '@/core/system/plugin.js';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GET /api/system/plugins - List all plugins
|
|
7
|
+
*/
|
|
8
|
+
export async function GET() {
|
|
9
|
+
try {
|
|
10
|
+
return NextResponse.json({ data: pluginRegistry.list() });
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* POST /api/system/plugins - Manage plugins
|
|
18
|
+
* Actions: enable, disable
|
|
19
|
+
*/
|
|
20
|
+
export async function POST(request) {
|
|
21
|
+
const t = getApiT(request);
|
|
22
|
+
try {
|
|
23
|
+
const { action, pluginId } = await request.json();
|
|
24
|
+
if (!pluginId) {
|
|
25
|
+
return NextResponse.json({ error: t('api.missingPluginId') }, { status: 400 });
|
|
26
|
+
}
|
|
27
|
+
switch (action) {
|
|
28
|
+
case 'enable':
|
|
29
|
+
pluginRegistry.enable(pluginId);
|
|
30
|
+
return NextResponse.json({ data: { success: true } });
|
|
31
|
+
case 'disable':
|
|
32
|
+
pluginRegistry.disable(pluginId);
|
|
33
|
+
return NextResponse.json({ data: { success: true } });
|
|
34
|
+
default:
|
|
35
|
+
return NextResponse.json({ error: t('api.pluginUnknownAction', { action }) }, { status: 400 });
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { skillRegistry } from '@/core/employee/skills.js';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* GET /api/system/skills - Get all skills
|
|
7
|
+
*/
|
|
8
|
+
export async function GET() {
|
|
9
|
+
try {
|
|
10
|
+
return NextResponse.json({ data: skillRegistry.list() });
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* POST /api/system/skills - Manage skills
|
|
18
|
+
* Actions: enable, disable, configure
|
|
19
|
+
*/
|
|
20
|
+
export async function POST(request) {
|
|
21
|
+
const t = getApiT(request);
|
|
22
|
+
try {
|
|
23
|
+
const { action, skillId, config } = await request.json();
|
|
24
|
+
if (!skillId) {
|
|
25
|
+
return NextResponse.json({ error: t('api.missingSkillId') }, { status: 400 });
|
|
26
|
+
}
|
|
27
|
+
switch (action) {
|
|
28
|
+
case 'enable':
|
|
29
|
+
skillRegistry.enable(skillId);
|
|
30
|
+
return NextResponse.json({ data: { success: true } });
|
|
31
|
+
case 'disable':
|
|
32
|
+
skillRegistry.disable(skillId);
|
|
33
|
+
return NextResponse.json({ data: { success: true } });
|
|
34
|
+
case 'install':
|
|
35
|
+
skillRegistry.install(skillId, config || {});
|
|
36
|
+
return NextResponse.json({ data: { success: true } });
|
|
37
|
+
case 'configure':
|
|
38
|
+
skillRegistry.configure(skillId, config || {});
|
|
39
|
+
return NextResponse.json({ data: { success: true } });
|
|
40
|
+
default:
|
|
41
|
+
return NextResponse.json({ error: t('api.pluginUnknownAction', { action }) }, { status: 400 });
|
|
42
|
+
}
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { auditLogger, securityGuard } from '@/core/system/audit.js';
|
|
3
|
+
import { pluginRegistry } from '@/core/system/plugin.js';
|
|
4
|
+
import { cronScheduler } from '@/core/system/cron.js';
|
|
5
|
+
import { hookRegistry } from '@/lib/hooks.js';
|
|
6
|
+
import { sessionManager } from '@/core/agent/session.js';
|
|
7
|
+
import { configValidator } from '@/lib/config-validator.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* GET /api/system/status - System status dashboard
|
|
11
|
+
* Returns health of all distilled systems: audit, routing, plugins, cron, hooks, sessions, config
|
|
12
|
+
*/
|
|
13
|
+
export async function GET() {
|
|
14
|
+
try {
|
|
15
|
+
const status = {
|
|
16
|
+
// Audit system summary
|
|
17
|
+
audit: auditLogger.getSummary(),
|
|
18
|
+
|
|
19
|
+
// Plugin system status
|
|
20
|
+
plugins: pluginRegistry.list(),
|
|
21
|
+
|
|
22
|
+
// Cron scheduler status
|
|
23
|
+
cron: cronScheduler.getSummary(),
|
|
24
|
+
cronJobs: cronScheduler.listJobs(),
|
|
25
|
+
|
|
26
|
+
// Hook system status
|
|
27
|
+
hooks: hookRegistry.getSummary(),
|
|
28
|
+
|
|
29
|
+
// Session manager status
|
|
30
|
+
sessions: sessionManager.getSummary(),
|
|
31
|
+
|
|
32
|
+
// Config validator (validate current empty config as health check)
|
|
33
|
+
configHealth: {
|
|
34
|
+
schemaFields: Object.keys(configValidator.schema.properties || {}),
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// Recent security events
|
|
38
|
+
recentAuditEvents: auditLogger.query({ limit: 20 }),
|
|
39
|
+
blockedActions: auditLogger.query({ blocked: true, limit: 10 }),
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return NextResponse.json({ data: status });
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return NextResponse.json({ error: error.message }, { status: 500 });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getCompany } from '@/lib/store';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
export async function POST(request, { params }) {
|
|
6
|
+
const t = getApiT(request);
|
|
7
|
+
const company = getCompany();
|
|
8
|
+
if (!company) return NextResponse.json({ error: t('api.noCompany') }, { status: 400 });
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const { profileId } = await params;
|
|
12
|
+
const { departmentId, newSkills } = await request.json();
|
|
13
|
+
if (!departmentId) {
|
|
14
|
+
return NextResponse.json({ error: t('api.targetDeptRequired') }, { status: 400 });
|
|
15
|
+
}
|
|
16
|
+
company.recallAgent(departmentId, profileId, newSkills || []);
|
|
17
|
+
company._log('Recall talent', `Recalled employee from talent market`);
|
|
18
|
+
return NextResponse.json({ success: true, data: company.getFullState() });
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return NextResponse.json({ error: e.message }, { status: 400 });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getCompany } from '@/lib/store';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
export async function DELETE(request, { params }) {
|
|
6
|
+
const t = getApiT(request);
|
|
7
|
+
const company = getCompany();
|
|
8
|
+
if (!company) return NextResponse.json({ error: t('api.noCompany') }, { status: 400 });
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
const { profileId } = await params;
|
|
12
|
+
company.deleteTalent(profileId);
|
|
13
|
+
return NextResponse.json({ success: true, data: company.getFullState() });
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return NextResponse.json({ error: e.message }, { status: 400 });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { NextResponse } from 'next/server';
|
|
2
|
+
import { getCompany } from '@/lib/store';
|
|
3
|
+
import { getApiT } from '@/lib/api-i18n';
|
|
4
|
+
|
|
5
|
+
export async function GET(request) {
|
|
6
|
+
const t = getApiT(request);
|
|
7
|
+
const company = getCompany();
|
|
8
|
+
if (!company) return NextResponse.json({ error: t('api.noCompany') }, { status: 400 });
|
|
9
|
+
|
|
10
|
+
const market = company.talentMarket.listAvailable().map(p => ({
|
|
11
|
+
id: p.id,
|
|
12
|
+
name: p.name,
|
|
13
|
+
role: p.role,
|
|
14
|
+
skills: [...p.skills, ...p.acquiredSkills],
|
|
15
|
+
acquiredSkills: p.acquiredSkills,
|
|
16
|
+
dismissalReason: p.dismissalReason,
|
|
17
|
+
performanceScore: p.performanceData?.averageScore,
|
|
18
|
+
registeredAt: p.registeredAt,
|
|
19
|
+
workHistory: p.workHistory,
|
|
20
|
+
memoryCount: p.memorySnapshot
|
|
21
|
+
? (p.memorySnapshot.shortTerm?.length || 0) + (p.memorySnapshot.longTerm?.length || 0)
|
|
22
|
+
: 0,
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
return NextResponse.json({ data: market });
|
|
26
|
+
}
|