@pixelbyte-software/pixcode 1.51.1 → 1.51.3
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/CODE_OF_CONDUCT.md +41 -41
- package/CONTRIBUTING.md +155 -155
- package/LICENSE +718 -718
- package/README.de.md +169 -169
- package/README.ja.md +167 -167
- package/README.ko.md +167 -167
- package/README.md +419 -419
- package/README.ru.md +169 -169
- package/README.tr.md +298 -298
- package/README.zh-CN.md +167 -167
- package/SECURITY.md +46 -46
- package/dist/api-automation.html +110 -110
- package/dist/api-docs.html +548 -548
- package/dist/assets/{index-DARIZgoD.js → index-17CwxHSZ.js} +185 -185
- package/dist/assets/index-B9N-gfOQ.css +32 -0
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/docs.html +308 -308
- package/dist/favicon.svg +8 -8
- package/dist/features.html +133 -133
- package/dist/generate-icons.js +48 -48
- package/dist/humans.txt +15 -15
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +9 -9
- package/dist/icons/icon-144x144.svg +9 -9
- package/dist/icons/icon-152x152.svg +9 -9
- package/dist/icons/icon-192x192.svg +9 -9
- package/dist/icons/icon-384x384.svg +9 -9
- package/dist/icons/icon-512x512.svg +9 -9
- package/dist/icons/icon-72x72.svg +9 -9
- package/dist/icons/icon-96x96.svg +9 -9
- package/dist/icons/icon-template.svg +9 -9
- package/dist/icons/qwen-logo.svg +14 -14
- package/dist/index.html +59 -59
- package/dist/landing.html +268 -268
- package/dist/llms-full.txt +119 -119
- package/dist/llms.txt +53 -53
- package/dist/logo.svg +12 -12
- package/dist/manifest.json +60 -60
- package/dist/openapi.yaml +1696 -1696
- package/dist/orchestration.html +125 -125
- package/dist/robots.txt +4 -4
- package/dist/site.css +692 -692
- package/dist/sitemap.xml +51 -51
- package/dist/sw.js +132 -132
- package/dist-server/server/cli.js +96 -96
- package/dist-server/server/daemon/manager.js +33 -33
- package/dist-server/server/daemon-manager.js +64 -64
- package/dist-server/server/index.js +125 -4
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js +84 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.js.map +1 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js +43 -0
- package/dist-server/server/modules/orchestration/a2a/adapters/json-event.adapter.test.js.map +1 -0
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js +55 -1
- package/dist-server/server/modules/orchestration/hermes/hermes.routes.js.map +1 -1
- package/dist-server/server/modules/orchestration/index.js +1 -0
- package/dist-server/server/modules/orchestration/index.js.map +1 -1
- package/dist-server/server/routes/commands.js +25 -25
- package/dist-server/server/routes/git.js +17 -17
- package/dist-server/server/routes/live-view.js +46 -46
- package/dist-server/server/services/hermes-gateway.js +310 -0
- package/dist-server/server/services/hermes-gateway.js.map +1 -1
- package/dist-server/server/services/public-api-manifest.js +59 -51
- package/dist-server/server/services/public-api-manifest.js.map +1 -1
- package/package.json +222 -222
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/github/create-v1.38-issues.mjs +351 -351
- package/scripts/github/create-vscode-workbench-issues.mjs +121 -121
- package/scripts/hermes/configure-pixcode-mcp.mjs +165 -163
- package/scripts/hermes/pixcode-mcp-server.mjs +1009 -958
- package/scripts/smoke/changes-panel-layout.mjs +48 -48
- package/scripts/smoke/chat-composer-fixed-layout.mjs +55 -55
- package/scripts/smoke/chat-message-timeline-order.mjs +41 -41
- package/scripts/smoke/chat-realtime-hydration.mjs +44 -44
- package/scripts/smoke/chat-session-provider-pools.mjs +35 -35
- package/scripts/smoke/chat-session-state.mjs +19 -19
- package/scripts/smoke/code-editor-theme.mjs +55 -55
- package/scripts/smoke/code-editor-vscode-engine.mjs +91 -91
- package/scripts/smoke/command-center-agent-writes.mjs +79 -79
- package/scripts/smoke/command-center-non-git.mjs +46 -46
- package/scripts/smoke/context-packet.mjs +43 -43
- package/scripts/smoke/control-room-ux-redesign.mjs +91 -91
- package/scripts/smoke/daemon-entrypoint.mjs +20 -20
- package/scripts/smoke/default-landing-routing.mjs +33 -33
- package/scripts/smoke/desktop-native-notifications.mjs +30 -30
- package/scripts/smoke/desktop-tray-icon.mjs +33 -33
- package/scripts/smoke/discord-release-workflow.mjs +24 -24
- package/scripts/smoke/git-install-update.mjs +255 -255
- package/scripts/smoke/handoff-artifact-protocol.mjs +50 -50
- package/scripts/smoke/hermes-api-install.mjs +56 -56
- package/scripts/smoke/hermes-gateway-persistence.mjs +104 -104
- package/scripts/smoke/hermes-mcp-pixcode-roundtrip.mjs +426 -367
- package/scripts/smoke/hermes-rest-chat-api.mjs +162 -162
- package/scripts/smoke/hermes-rest-chat-live.mjs +45 -45
- package/scripts/smoke/hermes-rest-codex-launch.mjs +209 -209
- package/scripts/smoke/hermes-rest-gateway.mjs +79 -70
- package/scripts/smoke/hermes-rest-live.mjs +42 -42
- package/scripts/smoke/hermes-roundtrip.mjs +167 -167
- package/scripts/smoke/hermes-settings-commands.mjs +349 -346
- package/scripts/smoke/hermes-smoke-launcher-guard.mjs +34 -34
- package/scripts/smoke/live-view-diagnostics.mjs +53 -53
- package/scripts/smoke/live-view-environment.mjs +92 -92
- package/scripts/smoke/live-view-integration.mjs +450 -450
- package/scripts/smoke/mac-desktop-runtime.mjs +37 -37
- package/scripts/smoke/mobile-tunnel-guidance.mjs +29 -29
- package/scripts/smoke/model-registry.mjs +36 -36
- package/scripts/smoke/multi-project-ui.mjs +45 -45
- package/scripts/smoke/multi-worker-slots.mjs +42 -42
- package/scripts/smoke/notification-center.mjs +87 -87
- package/scripts/smoke/notification-inapp-preference.mjs +23 -23
- package/scripts/smoke/notification-taxonomy.mjs +58 -58
- package/scripts/smoke/orchestration-api.mjs +172 -172
- package/scripts/smoke/orchestration-execution-dashboard.mjs +33 -33
- package/scripts/smoke/orchestration-live-run.mjs +176 -176
- package/scripts/smoke/orchestration-mobile-scroll.mjs +29 -29
- package/scripts/smoke/orchestration-model-sync.mjs +30 -30
- package/scripts/smoke/orchestration-permission-fallback.mjs +34 -34
- package/scripts/smoke/orchestration-runtime-guards.mjs +48 -48
- package/scripts/smoke/orchestration-user-facing-output.mjs +25 -25
- package/scripts/smoke/permission-policy.mjs +50 -50
- package/scripts/smoke/pixcode-workbench-1-48.mjs +167 -164
- package/scripts/smoke/provider-models-opencode-live.mjs +66 -66
- package/scripts/smoke/provider-rest-api.mjs +124 -124
- package/scripts/smoke/provider-selection-status.mjs +52 -52
- package/scripts/smoke/run-state-refresh.mjs +52 -52
- package/scripts/smoke/runtime-manager.mjs +99 -99
- package/scripts/smoke/shell-manual-disconnect.mjs +30 -30
- package/scripts/smoke/side-panel-editor-layout.mjs +34 -34
- package/scripts/smoke/static-root-routing.mjs +21 -21
- package/scripts/smoke/strict-handoff-compact.mjs +60 -60
- package/scripts/smoke/taskmaster-config.mjs +24 -24
- package/scripts/smoke/taskmaster-execution-telegram.mjs +3 -3
- package/scripts/smoke/taskmaster-onboarding.mjs +3 -3
- package/scripts/smoke/taskmaster-run-graph.mjs +3 -3
- package/scripts/smoke/telegram-control.mjs +242 -242
- package/scripts/smoke/tunnel-persistence.mjs +56 -56
- package/scripts/smoke/update-issue-progress.mjs +69 -69
- package/scripts/smoke/update-ux.mjs +55 -55
- package/scripts/smoke/v138-completion.mjs +132 -132
- package/scripts/smoke/v138-desktop-release-hardening.mjs +69 -69
- package/scripts/smoke/v138-diagnostics.mjs +63 -63
- package/scripts/smoke/v138-issue-planner.mjs +33 -33
- package/scripts/smoke/v143-remote-control.mjs +76 -76
- package/scripts/smoke/v144-production-loop.mjs +47 -47
- package/scripts/smoke/v145-platformization.mjs +46 -46
- package/scripts/smoke/v146-control-room-ui.mjs +150 -150
- package/scripts/smoke/version-modal-autoshow.mjs +29 -29
- package/scripts/smoke/vscode-workbench-layout.mjs +63 -63
- package/scripts/smoke/vscode-workbench-polish.mjs +461 -436
- package/scripts/smoke/workflow-fallback-replay.mjs +56 -56
- package/scripts/smoke/workflow-templates.mjs +43 -43
- package/scripts/smoke/workflow-trace-timeline.mjs +46 -46
- package/scripts/update-git-install.mjs +293 -293
- package/server/claude-sdk.js +920 -920
- package/server/cli.js +1039 -1039
- package/server/constants/config.js +4 -4
- package/server/cursor-cli.js +344 -344
- package/server/daemon/manager.js +563 -563
- package/server/daemon-manager.js +964 -964
- package/server/database/db.js +921 -921
- package/server/database/json-store.js +197 -197
- package/server/gemini-cli.js +550 -550
- package/server/gemini-response-handler.js +79 -79
- package/server/index.js +131 -3
- package/server/load-env.js +35 -35
- package/server/middleware/auth.js +175 -175
- package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
- package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +63 -63
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +286 -286
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.test.ts +60 -0
- package/server/modules/orchestration/a2a/adapters/json-event.adapter.ts +101 -0
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/agent-card.ts +55 -55
- package/server/modules/orchestration/a2a/routes.ts +590 -590
- package/server/modules/orchestration/a2a/task-store.ts +178 -178
- package/server/modules/orchestration/a2a/types.ts +126 -126
- package/server/modules/orchestration/a2a/validator.ts +113 -113
- package/server/modules/orchestration/hermes/hermes.routes.ts +642 -583
- package/server/modules/orchestration/index.ts +101 -100
- package/server/modules/orchestration/preview/port-watcher.ts +112 -112
- package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
- package/server/modules/orchestration/preview/types.ts +19 -19
- package/server/modules/orchestration/security/permission-policy.ts +401 -401
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +41 -41
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +64 -64
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +209 -209
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +40 -40
- package/server/modules/orchestration/tasks/task-run-graph.ts +155 -155
- package/server/modules/orchestration/workflows/approval-queue.ts +106 -106
- package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
- package/server/modules/orchestration/workflows/context-packet.ts +186 -186
- package/server/modules/orchestration/workflows/handoff-artifact.ts +175 -175
- package/server/modules/orchestration/workflows/workflow-fallback-policy.ts +161 -161
- package/server/modules/orchestration/workflows/workflow-replay.ts +254 -254
- package/server/modules/orchestration/workflows/workflow-runner.ts +2070 -2070
- package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
- package/server/modules/orchestration/workflows/workflow-templates.ts +272 -272
- package/server/modules/orchestration/workflows/workflow-trace.ts +424 -424
- package/server/modules/orchestration/workflows/workflow.routes.ts +586 -586
- package/server/modules/orchestration/workflows/workflow.types.ts +111 -111
- package/server/modules/orchestration/workflows/workspace-target.ts +122 -122
- package/server/modules/orchestration/workspace/docker-workspace.ts +136 -136
- package/server/modules/orchestration/workspace/path-safety.ts +55 -55
- package/server/modules/orchestration/workspace/types.ts +52 -52
- package/server/modules/orchestration/workspace/workspace-manager.ts +102 -102
- package/server/modules/orchestration/workspace/worktree-workspace.ts +126 -126
- package/server/modules/providers/index.ts +2 -2
- package/server/modules/providers/list/claude/claude-auth.provider.ts +146 -146
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
- package/server/modules/providers/list/claude/claude.provider.ts +15 -15
- package/server/modules/providers/list/codex/codex-auth.provider.ts +117 -117
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
- package/server/modules/providers/list/codex/codex.provider.ts +15 -15
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +147 -147
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
- package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +173 -173
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
- package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +131 -131
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +286 -286
- package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +146 -146
- package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
- package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
- package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
- package/server/modules/providers/provider.registry.ts +40 -40
- package/server/modules/providers/provider.routes.ts +944 -944
- package/server/modules/providers/services/mcp.service.ts +86 -86
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/sessions.service.ts +45 -45
- package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/provider-configs.ts +142 -142
- package/server/modules/providers/tests/mcp.test.ts +293 -293
- package/server/openai-codex.js +462 -462
- package/server/opencode-cli.js +491 -491
- package/server/opencode-response-handler.js +111 -111
- package/server/projects.js +3008 -3008
- package/server/qwen-code-cli.js +410 -410
- package/server/qwen-response-handler.js +73 -73
- package/server/routes/agent.js +1435 -1435
- package/server/routes/auth.js +159 -159
- package/server/routes/codex.js +20 -20
- package/server/routes/commands.js +570 -570
- package/server/routes/cursor.js +61 -61
- package/server/routes/diagnostics.js +41 -41
- package/server/routes/gemini.js +25 -25
- package/server/routes/git.js +1650 -1650
- package/server/routes/live-view.js +411 -411
- package/server/routes/mcp-utils.js +13 -13
- package/server/routes/messages.js +62 -62
- package/server/routes/network.js +125 -125
- package/server/routes/platformization.js +212 -212
- package/server/routes/plugins.js +320 -320
- package/server/routes/production-agent-loop.js +90 -90
- package/server/routes/projects.js +917 -917
- package/server/routes/public-api.js +34 -34
- package/server/routes/qwen.js +27 -27
- package/server/routes/remote.js +55 -55
- package/server/routes/settings.js +321 -321
- package/server/routes/telegram.js +140 -140
- package/server/routes/user.js +125 -125
- package/server/routes/webhooks.js +63 -63
- package/server/services/control-room.js +102 -102
- package/server/services/diagnostics.js +165 -165
- package/server/services/external-access.js +375 -375
- package/server/services/hermes-gateway.js +1562 -1247
- package/server/services/hermes-install-jobs.js +729 -729
- package/server/services/install-jobs.js +715 -715
- package/server/services/live-view.js +956 -956
- package/server/services/managed-runtimes.js +493 -493
- package/server/services/model-registry.js +144 -144
- package/server/services/notification-orchestrator.js +365 -365
- package/server/services/notification-taxonomy.js +204 -204
- package/server/services/platformization.js +815 -815
- package/server/services/production-agent-loop.js +248 -248
- package/server/services/provider-cli-versions.js +149 -149
- package/server/services/provider-credentials.js +189 -189
- package/server/services/provider-models.js +396 -396
- package/server/services/public-api-manifest.js +190 -182
- package/server/services/remote-connection.js +127 -127
- package/server/services/runtime-manager.js +323 -323
- package/server/services/startup-update.js +234 -234
- package/server/services/telegram/bot.js +331 -331
- package/server/services/telegram/control-center.js +979 -979
- package/server/services/telegram/telegram-http-client.js +151 -151
- package/server/services/telegram/translations.js +340 -340
- package/server/services/vapid-keys.js +36 -36
- package/server/services/webhooks.js +216 -216
- package/server/sessionManager.js +225 -225
- package/server/shared/interfaces.ts +54 -54
- package/server/shared/types.ts +172 -172
- package/server/shared/utils.ts +193 -193
- package/server/tsconfig.json +36 -36
- package/server/utils/colors.js +21 -21
- package/server/utils/commandParser.js +305 -305
- package/server/utils/frontmatter.js +18 -18
- package/server/utils/gitConfig.js +34 -34
- package/server/utils/plugin-loader.js +457 -457
- package/server/utils/plugin-process-manager.js +185 -185
- package/server/utils/port-access.js +209 -209
- package/server/utils/runtime-paths.js +37 -37
- package/server/utils/url-detection.js +71 -71
- package/server/vite-daemon.js +79 -79
- package/shared/modelConstants.js +161 -161
- package/shared/networkHosts.js +22 -22
- package/dist/assets/index-DMz0zv6T.css +0 -32
package/server/sessionManager.js
CHANGED
|
@@ -1,226 +1,226 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import os from 'os';
|
|
4
|
-
|
|
5
|
-
class SessionManager {
|
|
6
|
-
constructor() {
|
|
7
|
-
// Store sessions in memory with conversation history
|
|
8
|
-
this.sessions = new Map();
|
|
9
|
-
this.maxSessions = 100;
|
|
10
|
-
this.sessionsDir = path.join(os.homedir(), '.gemini', 'sessions');
|
|
11
|
-
this.ready = this.init();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async init() {
|
|
15
|
-
await this.initSessionsDir();
|
|
16
|
-
await this.loadSessions();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async initSessionsDir() {
|
|
20
|
-
try {
|
|
21
|
-
await fs.mkdir(this.sessionsDir, { recursive: true });
|
|
22
|
-
} catch (error) {
|
|
23
|
-
// console.error('Error creating sessions directory:', error);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Create a new session
|
|
28
|
-
createSession(sessionId, projectPath) {
|
|
29
|
-
const session = {
|
|
30
|
-
id: sessionId,
|
|
31
|
-
projectPath: projectPath,
|
|
32
|
-
messages: [],
|
|
33
|
-
createdAt: new Date(),
|
|
34
|
-
lastActivity: new Date()
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Evict oldest session from memory if we exceed limit
|
|
38
|
-
if (this.sessions.size >= this.maxSessions) {
|
|
39
|
-
const oldestKey = this.sessions.keys().next().value;
|
|
40
|
-
if (oldestKey) this.sessions.delete(oldestKey);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
this.sessions.set(sessionId, session);
|
|
44
|
-
this.saveSession(sessionId);
|
|
45
|
-
|
|
46
|
-
return session;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Add a message to session
|
|
50
|
-
addMessage(sessionId, role, content) {
|
|
51
|
-
let session = this.sessions.get(sessionId);
|
|
52
|
-
|
|
53
|
-
if (!session) {
|
|
54
|
-
// Create session if it doesn't exist
|
|
55
|
-
session = this.createSession(sessionId, '');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const message = {
|
|
59
|
-
role: role, // 'user' or 'assistant'
|
|
60
|
-
content: content,
|
|
61
|
-
timestamp: new Date()
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
session.messages.push(message);
|
|
65
|
-
session.lastActivity = new Date();
|
|
66
|
-
|
|
67
|
-
this.saveSession(sessionId);
|
|
68
|
-
|
|
69
|
-
return session;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Get session by ID
|
|
73
|
-
getSession(sessionId) {
|
|
74
|
-
return this.sessions.get(sessionId);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Get all sessions for a project
|
|
78
|
-
getProjectSessions(projectPath) {
|
|
79
|
-
const sessions = [];
|
|
80
|
-
|
|
81
|
-
for (const [id, session] of this.sessions) {
|
|
82
|
-
if (session.projectPath === projectPath) {
|
|
83
|
-
sessions.push({
|
|
84
|
-
id: session.id,
|
|
85
|
-
summary: this.getSessionSummary(session),
|
|
86
|
-
messageCount: session.messages.length,
|
|
87
|
-
lastActivity: session.lastActivity
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
return sessions.sort((a, b) =>
|
|
93
|
-
new Date(b.lastActivity) - new Date(a.lastActivity)
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Get session summary
|
|
98
|
-
getSessionSummary(session) {
|
|
99
|
-
if (session.messages.length === 0) {
|
|
100
|
-
return 'New Session';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Find first user message
|
|
104
|
-
const firstUserMessage = session.messages.find(m => m.role === 'user');
|
|
105
|
-
if (firstUserMessage) {
|
|
106
|
-
const content = firstUserMessage.content;
|
|
107
|
-
return content.length > 50 ? content.substring(0, 50) + '...' : content;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return 'New Session';
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Build conversation context for Gemini
|
|
114
|
-
buildConversationContext(sessionId, maxMessages = 10) {
|
|
115
|
-
const session = this.sessions.get(sessionId);
|
|
116
|
-
|
|
117
|
-
if (!session || session.messages.length === 0) {
|
|
118
|
-
return '';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Get last N messages for context
|
|
122
|
-
const recentMessages = session.messages.slice(-maxMessages);
|
|
123
|
-
|
|
124
|
-
let context = 'Here is the conversation history:\n\n';
|
|
125
|
-
|
|
126
|
-
for (const msg of recentMessages) {
|
|
127
|
-
if (msg.role === 'user') {
|
|
128
|
-
context += `User: ${msg.content}\n`;
|
|
129
|
-
} else {
|
|
130
|
-
context += `Assistant: ${msg.content}\n`;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
context += '\nBased on the conversation history above, please answer the following:\n';
|
|
135
|
-
|
|
136
|
-
return context;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Prevent path traversal
|
|
140
|
-
_safeFilePath(sessionId) {
|
|
141
|
-
const safeId = String(sessionId).replace(/[/\\]|\.\./g, '');
|
|
142
|
-
return path.join(this.sessionsDir, `${safeId}.json`);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Save session to disk
|
|
146
|
-
async saveSession(sessionId) {
|
|
147
|
-
const session = this.sessions.get(sessionId);
|
|
148
|
-
if (!session) return;
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
const filePath = this._safeFilePath(sessionId);
|
|
152
|
-
await fs.writeFile(filePath, JSON.stringify(session, null, 2));
|
|
153
|
-
} catch (error) {
|
|
154
|
-
// console.error('Error saving session:', error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// Load sessions from disk
|
|
159
|
-
async loadSessions() {
|
|
160
|
-
try {
|
|
161
|
-
const files = await fs.readdir(this.sessionsDir);
|
|
162
|
-
|
|
163
|
-
for (const file of files) {
|
|
164
|
-
if (file.endsWith('.json')) {
|
|
165
|
-
try {
|
|
166
|
-
const filePath = path.join(this.sessionsDir, file);
|
|
167
|
-
const data = await fs.readFile(filePath, 'utf8');
|
|
168
|
-
const session = JSON.parse(data);
|
|
169
|
-
|
|
170
|
-
// Convert dates
|
|
171
|
-
session.createdAt = new Date(session.createdAt);
|
|
172
|
-
session.lastActivity = new Date(session.lastActivity);
|
|
173
|
-
session.messages.forEach(msg => {
|
|
174
|
-
msg.timestamp = new Date(msg.timestamp);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
this.sessions.set(session.id, session);
|
|
178
|
-
} catch (error) {
|
|
179
|
-
// console.error(`Error loading session ${file}:`, error);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Enforce eviction after loading to prevent massive memory usage
|
|
185
|
-
while (this.sessions.size > this.maxSessions) {
|
|
186
|
-
const oldestKey = this.sessions.keys().next().value;
|
|
187
|
-
if (oldestKey) this.sessions.delete(oldestKey);
|
|
188
|
-
}
|
|
189
|
-
} catch (error) {
|
|
190
|
-
// console.error('Error loading sessions:', error);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Delete a session
|
|
195
|
-
async deleteSession(sessionId) {
|
|
196
|
-
this.sessions.delete(sessionId);
|
|
197
|
-
|
|
198
|
-
try {
|
|
199
|
-
const filePath = this._safeFilePath(sessionId);
|
|
200
|
-
await fs.unlink(filePath);
|
|
201
|
-
} catch (error) {
|
|
202
|
-
// console.error('Error deleting session file:', error);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// Get session messages for display
|
|
207
|
-
getSessionMessages(sessionId) {
|
|
208
|
-
const session = this.sessions.get(sessionId);
|
|
209
|
-
if (!session) return [];
|
|
210
|
-
|
|
211
|
-
return session.messages.map(msg => ({
|
|
212
|
-
type: 'message',
|
|
213
|
-
message: {
|
|
214
|
-
role: msg.role,
|
|
215
|
-
content: msg.content
|
|
216
|
-
},
|
|
217
|
-
timestamp: msg.timestamp.toISOString()
|
|
218
|
-
}));
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Singleton instance
|
|
223
|
-
const sessionManager = new SessionManager();
|
|
224
|
-
|
|
225
|
-
export const ready = sessionManager.ready;
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
|
|
5
|
+
class SessionManager {
|
|
6
|
+
constructor() {
|
|
7
|
+
// Store sessions in memory with conversation history
|
|
8
|
+
this.sessions = new Map();
|
|
9
|
+
this.maxSessions = 100;
|
|
10
|
+
this.sessionsDir = path.join(os.homedir(), '.gemini', 'sessions');
|
|
11
|
+
this.ready = this.init();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async init() {
|
|
15
|
+
await this.initSessionsDir();
|
|
16
|
+
await this.loadSessions();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async initSessionsDir() {
|
|
20
|
+
try {
|
|
21
|
+
await fs.mkdir(this.sessionsDir, { recursive: true });
|
|
22
|
+
} catch (error) {
|
|
23
|
+
// console.error('Error creating sessions directory:', error);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Create a new session
|
|
28
|
+
createSession(sessionId, projectPath) {
|
|
29
|
+
const session = {
|
|
30
|
+
id: sessionId,
|
|
31
|
+
projectPath: projectPath,
|
|
32
|
+
messages: [],
|
|
33
|
+
createdAt: new Date(),
|
|
34
|
+
lastActivity: new Date()
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Evict oldest session from memory if we exceed limit
|
|
38
|
+
if (this.sessions.size >= this.maxSessions) {
|
|
39
|
+
const oldestKey = this.sessions.keys().next().value;
|
|
40
|
+
if (oldestKey) this.sessions.delete(oldestKey);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
this.sessions.set(sessionId, session);
|
|
44
|
+
this.saveSession(sessionId);
|
|
45
|
+
|
|
46
|
+
return session;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Add a message to session
|
|
50
|
+
addMessage(sessionId, role, content) {
|
|
51
|
+
let session = this.sessions.get(sessionId);
|
|
52
|
+
|
|
53
|
+
if (!session) {
|
|
54
|
+
// Create session if it doesn't exist
|
|
55
|
+
session = this.createSession(sessionId, '');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const message = {
|
|
59
|
+
role: role, // 'user' or 'assistant'
|
|
60
|
+
content: content,
|
|
61
|
+
timestamp: new Date()
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
session.messages.push(message);
|
|
65
|
+
session.lastActivity = new Date();
|
|
66
|
+
|
|
67
|
+
this.saveSession(sessionId);
|
|
68
|
+
|
|
69
|
+
return session;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Get session by ID
|
|
73
|
+
getSession(sessionId) {
|
|
74
|
+
return this.sessions.get(sessionId);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Get all sessions for a project
|
|
78
|
+
getProjectSessions(projectPath) {
|
|
79
|
+
const sessions = [];
|
|
80
|
+
|
|
81
|
+
for (const [id, session] of this.sessions) {
|
|
82
|
+
if (session.projectPath === projectPath) {
|
|
83
|
+
sessions.push({
|
|
84
|
+
id: session.id,
|
|
85
|
+
summary: this.getSessionSummary(session),
|
|
86
|
+
messageCount: session.messages.length,
|
|
87
|
+
lastActivity: session.lastActivity
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return sessions.sort((a, b) =>
|
|
93
|
+
new Date(b.lastActivity) - new Date(a.lastActivity)
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Get session summary
|
|
98
|
+
getSessionSummary(session) {
|
|
99
|
+
if (session.messages.length === 0) {
|
|
100
|
+
return 'New Session';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Find first user message
|
|
104
|
+
const firstUserMessage = session.messages.find(m => m.role === 'user');
|
|
105
|
+
if (firstUserMessage) {
|
|
106
|
+
const content = firstUserMessage.content;
|
|
107
|
+
return content.length > 50 ? content.substring(0, 50) + '...' : content;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return 'New Session';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Build conversation context for Gemini
|
|
114
|
+
buildConversationContext(sessionId, maxMessages = 10) {
|
|
115
|
+
const session = this.sessions.get(sessionId);
|
|
116
|
+
|
|
117
|
+
if (!session || session.messages.length === 0) {
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Get last N messages for context
|
|
122
|
+
const recentMessages = session.messages.slice(-maxMessages);
|
|
123
|
+
|
|
124
|
+
let context = 'Here is the conversation history:\n\n';
|
|
125
|
+
|
|
126
|
+
for (const msg of recentMessages) {
|
|
127
|
+
if (msg.role === 'user') {
|
|
128
|
+
context += `User: ${msg.content}\n`;
|
|
129
|
+
} else {
|
|
130
|
+
context += `Assistant: ${msg.content}\n`;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
context += '\nBased on the conversation history above, please answer the following:\n';
|
|
135
|
+
|
|
136
|
+
return context;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Prevent path traversal
|
|
140
|
+
_safeFilePath(sessionId) {
|
|
141
|
+
const safeId = String(sessionId).replace(/[/\\]|\.\./g, '');
|
|
142
|
+
return path.join(this.sessionsDir, `${safeId}.json`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Save session to disk
|
|
146
|
+
async saveSession(sessionId) {
|
|
147
|
+
const session = this.sessions.get(sessionId);
|
|
148
|
+
if (!session) return;
|
|
149
|
+
|
|
150
|
+
try {
|
|
151
|
+
const filePath = this._safeFilePath(sessionId);
|
|
152
|
+
await fs.writeFile(filePath, JSON.stringify(session, null, 2));
|
|
153
|
+
} catch (error) {
|
|
154
|
+
// console.error('Error saving session:', error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Load sessions from disk
|
|
159
|
+
async loadSessions() {
|
|
160
|
+
try {
|
|
161
|
+
const files = await fs.readdir(this.sessionsDir);
|
|
162
|
+
|
|
163
|
+
for (const file of files) {
|
|
164
|
+
if (file.endsWith('.json')) {
|
|
165
|
+
try {
|
|
166
|
+
const filePath = path.join(this.sessionsDir, file);
|
|
167
|
+
const data = await fs.readFile(filePath, 'utf8');
|
|
168
|
+
const session = JSON.parse(data);
|
|
169
|
+
|
|
170
|
+
// Convert dates
|
|
171
|
+
session.createdAt = new Date(session.createdAt);
|
|
172
|
+
session.lastActivity = new Date(session.lastActivity);
|
|
173
|
+
session.messages.forEach(msg => {
|
|
174
|
+
msg.timestamp = new Date(msg.timestamp);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
this.sessions.set(session.id, session);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
// console.error(`Error loading session ${file}:`, error);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Enforce eviction after loading to prevent massive memory usage
|
|
185
|
+
while (this.sessions.size > this.maxSessions) {
|
|
186
|
+
const oldestKey = this.sessions.keys().next().value;
|
|
187
|
+
if (oldestKey) this.sessions.delete(oldestKey);
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
// console.error('Error loading sessions:', error);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Delete a session
|
|
195
|
+
async deleteSession(sessionId) {
|
|
196
|
+
this.sessions.delete(sessionId);
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
const filePath = this._safeFilePath(sessionId);
|
|
200
|
+
await fs.unlink(filePath);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
// console.error('Error deleting session file:', error);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Get session messages for display
|
|
207
|
+
getSessionMessages(sessionId) {
|
|
208
|
+
const session = this.sessions.get(sessionId);
|
|
209
|
+
if (!session) return [];
|
|
210
|
+
|
|
211
|
+
return session.messages.map(msg => ({
|
|
212
|
+
type: 'message',
|
|
213
|
+
message: {
|
|
214
|
+
role: msg.role,
|
|
215
|
+
content: msg.content
|
|
216
|
+
},
|
|
217
|
+
timestamp: msg.timestamp.toISOString()
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Singleton instance
|
|
223
|
+
const sessionManager = new SessionManager();
|
|
224
|
+
|
|
225
|
+
export const ready = sessionManager.ready;
|
|
226
226
|
export default sessionManager;
|
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FetchHistoryOptions,
|
|
3
|
-
FetchHistoryResult,
|
|
4
|
-
LLMProvider,
|
|
5
|
-
McpScope,
|
|
6
|
-
NormalizedMessage,
|
|
7
|
-
ProviderAuthStatus,
|
|
8
|
-
ProviderMcpServer,
|
|
9
|
-
UpsertProviderMcpServerInput,
|
|
10
|
-
} from '@/shared/types.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Main provider contract for CLI and SDK integrations.
|
|
14
|
-
*
|
|
15
|
-
* Each concrete provider owns its MCP/auth handlers plus the provider-specific
|
|
16
|
-
* logic for converting native events/history into the app's normalized shape.
|
|
17
|
-
*/
|
|
18
|
-
export interface IProvider {
|
|
19
|
-
readonly id: LLMProvider;
|
|
20
|
-
readonly mcp: IProviderMcp;
|
|
21
|
-
readonly auth: IProviderAuth;
|
|
22
|
-
readonly sessions: IProviderSessions;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Auth contract for one provider.
|
|
28
|
-
*/
|
|
29
|
-
export interface IProviderAuth {
|
|
30
|
-
/**
|
|
31
|
-
* Checks whether the provider is installed and has usable credentials.
|
|
32
|
-
*/
|
|
33
|
-
getStatus(): Promise<ProviderAuthStatus>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* MCP contract for one provider.
|
|
38
|
-
*/
|
|
39
|
-
export interface IProviderMcp {
|
|
40
|
-
listServers(options?: { workspacePath?: string }): Promise<Record<McpScope, ProviderMcpServer[]>>;
|
|
41
|
-
listServersForScope(scope: McpScope, options?: { workspacePath?: string }): Promise<ProviderMcpServer[]>;
|
|
42
|
-
upsertServer(input: UpsertProviderMcpServerInput): Promise<ProviderMcpServer>;
|
|
43
|
-
removeServer(
|
|
44
|
-
input: { name: string; scope?: McpScope; workspacePath?: string },
|
|
45
|
-
): Promise<{ removed: boolean; provider: LLMProvider; name: string; scope: McpScope }>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Session/history contract for one provider.
|
|
50
|
-
*/
|
|
51
|
-
export interface IProviderSessions {
|
|
52
|
-
normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
|
|
53
|
-
fetchHistory(sessionId: string, options?: FetchHistoryOptions): Promise<FetchHistoryResult>;
|
|
54
|
-
}
|
|
1
|
+
import type {
|
|
2
|
+
FetchHistoryOptions,
|
|
3
|
+
FetchHistoryResult,
|
|
4
|
+
LLMProvider,
|
|
5
|
+
McpScope,
|
|
6
|
+
NormalizedMessage,
|
|
7
|
+
ProviderAuthStatus,
|
|
8
|
+
ProviderMcpServer,
|
|
9
|
+
UpsertProviderMcpServerInput,
|
|
10
|
+
} from '@/shared/types.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Main provider contract for CLI and SDK integrations.
|
|
14
|
+
*
|
|
15
|
+
* Each concrete provider owns its MCP/auth handlers plus the provider-specific
|
|
16
|
+
* logic for converting native events/history into the app's normalized shape.
|
|
17
|
+
*/
|
|
18
|
+
export interface IProvider {
|
|
19
|
+
readonly id: LLMProvider;
|
|
20
|
+
readonly mcp: IProviderMcp;
|
|
21
|
+
readonly auth: IProviderAuth;
|
|
22
|
+
readonly sessions: IProviderSessions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Auth contract for one provider.
|
|
28
|
+
*/
|
|
29
|
+
export interface IProviderAuth {
|
|
30
|
+
/**
|
|
31
|
+
* Checks whether the provider is installed and has usable credentials.
|
|
32
|
+
*/
|
|
33
|
+
getStatus(): Promise<ProviderAuthStatus>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* MCP contract for one provider.
|
|
38
|
+
*/
|
|
39
|
+
export interface IProviderMcp {
|
|
40
|
+
listServers(options?: { workspacePath?: string }): Promise<Record<McpScope, ProviderMcpServer[]>>;
|
|
41
|
+
listServersForScope(scope: McpScope, options?: { workspacePath?: string }): Promise<ProviderMcpServer[]>;
|
|
42
|
+
upsertServer(input: UpsertProviderMcpServerInput): Promise<ProviderMcpServer>;
|
|
43
|
+
removeServer(
|
|
44
|
+
input: { name: string; scope?: McpScope; workspacePath?: string },
|
|
45
|
+
): Promise<{ removed: boolean; provider: LLMProvider; name: string; scope: McpScope }>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Session/history contract for one provider.
|
|
50
|
+
*/
|
|
51
|
+
export interface IProviderSessions {
|
|
52
|
+
normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
|
|
53
|
+
fetchHistory(sessionId: string, options?: FetchHistoryOptions): Promise<FetchHistoryResult>;
|
|
54
|
+
}
|