@axhub/genie 0.2.7 → 0.2.9
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/LICENSE +21 -675
- package/dist/api-docs.html +2 -2
- package/dist/assets/App-GBcTeeUS.js +460 -0
- package/dist/assets/App-qxJ8_QYu.css +32 -0
- package/dist/assets/ReviewApp-C9K--AQE.js +1 -0
- package/dist/assets/{_basePickBy-C19AekOu.js → _basePickBy-DR_8uFCo.js} +1 -1
- package/dist/assets/{_baseUniq-JsnevLw_.js → _baseUniq-D0njlQ_7.js} +1 -1
- package/dist/assets/{arc-BLpcuBlf.js → arc-CKlr_Rec.js} +1 -1
- package/dist/assets/architectureDiagram-2XIMDMQ5-BmO_uLUH.js +36 -0
- package/dist/assets/{blockDiagram-WCTKOSBZ-DQBLwsUS.js → blockDiagram-WCTKOSBZ-DhAeO-56.js} +3 -3
- package/dist/assets/c4Diagram-IC4MRINW-C67kFoXx.js +10 -0
- package/dist/assets/channel-V3MBjKys.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-De63kbgc.js → chunk-4BX2VUAB-mLLagvJi.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-DtTDDdM9.js → chunk-55IACEB6-Lx-hOjlM.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-DHuwd8tw.js → chunk-FMBD7UC4-Bt-XmVUV.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-BgytFtmO.js → chunk-JSJVCQXG-Cya6gaDV.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-nZdp86aN.js → chunk-KX2RTZJC-Bd7Ig6tF.js} +1 -1
- package/dist/assets/chunk-NQ4KR5QH-5UAE0Vg-.js +220 -0
- package/dist/assets/{chunk-QZHKN3VN-DvUQ3mnO.js → chunk-QZHKN3VN-BAxZ8m7w.js} +1 -1
- package/dist/assets/chunk-WL4C6EOR-DjDPvUUP.js +189 -0
- package/dist/assets/classDiagram-VBA2DB6C-C790yYiY.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-C790yYiY.js +1 -0
- package/dist/assets/clone-BbMGfZwt.js +1 -0
- package/dist/assets/cose-bilkent-S5V4N54A-D-60XrkJ.js +1 -0
- package/dist/assets/cytoscape.esm-2ZfV8NB5.js +331 -0
- package/dist/assets/{dagre-KLK3FWXG-CHYIvW47.js → dagre-KLK3FWXG-bqu3ZS4K.js} +1 -1
- package/dist/assets/diagram-E7M64L7V-BueeqoYm.js +24 -0
- package/dist/assets/{diagram-IFDJBPK2-Dzsiln_C.js → diagram-IFDJBPK2-D4fDv2E7.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-DKnGbUpE.js → diagram-P4PSJMXO-WqipY3fN.js} +1 -1
- package/dist/assets/erDiagram-INFDFZHY-D0oVnO-x.js +70 -0
- package/dist/assets/{flowDiagram-PKNHOUZH-BAZ2-jKp.js → flowDiagram-PKNHOUZH-DzbGyxrr.js} +4 -4
- package/dist/assets/ganttDiagram-A5KZAMGK-BwhbbgCP.js +292 -0
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-BflpyjGy.js → gitGraphDiagram-K3NZZRJ6-DZgAh_KM.js} +1 -1
- package/dist/assets/{graph-suelaXFh.js → graph-DzKos-N0.js} +1 -1
- package/dist/assets/highlighted-body-TPN3WLV5-CKDMgz3X.js +1 -0
- package/dist/assets/index-DiQlHzGj.js +2 -0
- package/dist/assets/index-Drat2nB9.css +1 -0
- package/dist/assets/{infoDiagram-LFFYTUFH-pfD1FA3p.js → infoDiagram-LFFYTUFH-BFicZbTf.js} +1 -1
- package/dist/assets/ishikawaDiagram-PHBUUO56-CtihxDxl.js +70 -0
- package/dist/assets/journeyDiagram-4ABVD52K-Du00J8_d.js +139 -0
- package/dist/assets/{kanban-definition-K7BYSVSG-FWinmur1.js → kanban-definition-K7BYSVSG-BJi9S0iQ.js} +5 -5
- package/dist/assets/{layout-vcz43XvZ.js → layout-B80Sityu.js} +1 -1
- package/dist/assets/{linear-le4gc0vx.js → linear-sRQLOf5H.js} +1 -1
- package/dist/assets/mermaid-O7DHMXV3-CBuVs4eJ.js +1038 -0
- package/dist/assets/mindmap-definition-YRQLILUH-C5IL_xi-.js +68 -0
- package/dist/assets/{pieDiagram-SKSYHLDU-C7PKDh3b.js → pieDiagram-SKSYHLDU-CeTwlJ8z.js} +2 -2
- package/dist/assets/quadrantDiagram-337W2JSQ-COfUcLWt.js +7 -0
- package/dist/assets/requirementDiagram-Z7DCOOCP-DSb-CJ5B.js +73 -0
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-4gulcOP4.js → sankeyDiagram-WA2Y5GQK-8jtuVb45.js} +3 -3
- package/dist/assets/sequenceDiagram-2WXFIKYE-C2VpkMwA.js +145 -0
- package/dist/assets/{stateDiagram-RAJIS63D-CB4Vl7qM.js → stateDiagram-RAJIS63D-fmwMqxxc.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-9GGXVWrR.js +1 -0
- package/dist/assets/timeline-definition-YZTLITO2-Dx1hP5lg.js +61 -0
- package/dist/assets/{treemap-KZPCXAKY-DZSEE6Hz.js → treemap-KZPCXAKY-CkLOdYCZ.js} +58 -58
- package/dist/assets/vendor-codemirror-BxPY6emf.js +39 -0
- package/dist/assets/vendor-react-xmA_f8ig.js +59 -0
- package/dist/assets/vendor-xterm-DfaPXD3y.js +66 -0
- package/dist/assets/{vennDiagram-LZ73GAT5-8E_G06fI.js → vennDiagram-LZ73GAT5-D6KWcnln.js} +4 -4
- package/dist/assets/xychartDiagram-JWTSCODW-6fh6qmzN.js +7 -0
- package/dist/index.html +5 -5
- package/package.json +36 -35
- package/server/acp-runtime/client.js +91 -17
- package/server/acp-runtime/index.js +5 -16
- package/server/acp-runtime/session-store.js +4 -4
- package/server/channels/runtime/AgentRuntimeAdapter.js +1 -10
- package/server/claude-sdk.js +1 -3
- package/server/cli.js +159 -2
- package/server/external-agent/service.js +24 -6
- package/server/external-agent/ws.js +63 -3
- package/server/gemini-cli.js +1 -3
- package/server/index.js +120 -19
- package/server/openai-codex.js +1 -3
- package/server/opencode-cli.js +1 -3
- package/server/projects.js +654 -236
- package/server/routes/cc-connect.js +1131 -0
- package/server/routes/cli-auth.js +1 -73
- package/server/routes/commands.js +4 -9
- package/server/routes/projects.js +45 -24
- package/server/routes/session-core.js +149 -86
- package/server/session-core/eventStore.js +45 -18
- package/server/session-core/providerAdapters.js +50 -13
- package/server/session-core/providerDiscovery.js +8 -3
- package/server/session-core/runtimeState.js +8 -0
- package/server/utils/ccConnectManager.js +390 -0
- package/server/utils/ccConnectState.js +575 -0
- package/server/utils/resolveCommandPath.js +71 -0
- package/server/utils/workspaceRoots.js +154 -0
- package/shared/conversationEvents.js +78 -14
- package/dist/assets/App-BWSqiXAT.js +0 -220
- package/dist/assets/App-DrlLKa8f.css +0 -1
- package/dist/assets/ReviewApp-nz3mbArg.js +0 -1
- package/dist/assets/architectureDiagram-2XIMDMQ5-CarjBOOv.js +0 -36
- package/dist/assets/c4Diagram-IC4MRINW-CGobwBIj.js +0 -10
- package/dist/assets/channel-DkFNxV_H.js +0 -1
- package/dist/assets/chunk-NQ4KR5QH-CMH6EDP2.js +0 -220
- package/dist/assets/chunk-WL4C6EOR-Dn7db_6t.js +0 -189
- package/dist/assets/classDiagram-VBA2DB6C-DtwCEe8S.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-DtwCEe8S.js +0 -1
- package/dist/assets/clone-C0lCEIEO.js +0 -1
- package/dist/assets/cose-bilkent-S5V4N54A-DD_nzqsz.js +0 -1
- package/dist/assets/cytoscape.esm-5J0xJHOV.js +0 -321
- package/dist/assets/diagram-E7M64L7V-TVdvHtGc.js +0 -24
- package/dist/assets/erDiagram-INFDFZHY-5Kw0bByo.js +0 -70
- package/dist/assets/ganttDiagram-A5KZAMGK-CsADFkcq.js +0 -292
- package/dist/assets/highlighted-body-OFNGDK62-CZrBMazC.js +0 -1
- package/dist/assets/index-B01NxbUv.css +0 -1
- package/dist/assets/index-DW5pGgQ_.js +0 -2
- package/dist/assets/ishikawaDiagram-PHBUUO56-ndm9snwO.js +0 -70
- package/dist/assets/journeyDiagram-4ABVD52K-HgF2t7z5.js +0 -139
- package/dist/assets/mermaid-GHXKKRXX-CK8m3lad.js +0 -870
- package/dist/assets/mindmap-definition-YRQLILUH-CNq9SKj4.js +0 -68
- package/dist/assets/quadrantDiagram-337W2JSQ-B7FnztNO.js +0 -7
- package/dist/assets/requirementDiagram-Z7DCOOCP-Bl_BM2Th.js +0 -73
- package/dist/assets/sequenceDiagram-2WXFIKYE-VEuJDwyJ.js +0 -145
- package/dist/assets/stateDiagram-v2-FVOUBMTO-C85ucl39.js +0 -1
- package/dist/assets/timeline-definition-YZTLITO2-BPGKhi7f.js +0 -61
- package/dist/assets/vendor-codemirror-CyOKkaQZ.js +0 -31
- package/dist/assets/vendor-react-CP4yFTs7.js +0 -8
- package/dist/assets/vendor-xterm-DfcmCpbH.js +0 -66
- package/dist/assets/xychartDiagram-JWTSCODW-CbBk50-O.js +0 -7
- package/server/_legacy-providers/README.md +0 -30
- package/server/_legacy-providers/claude-sdk.js +0 -956
- package/server/_legacy-providers/gemini-cli.js +0 -368
- package/server/_legacy-providers/openai-codex.js +0 -705
- package/server/_legacy-providers/opencode-cli.js +0 -674
- package/server/acp-runtime/client.test.js +0 -688
- package/server/acp-runtime/session-store.test.js +0 -89
- package/server/cli.test.js +0 -76
- package/server/external-agent/service.test.js +0 -53
- package/server/external-agent/ws.test.js +0 -289
- package/shared/conversationEvents.test.js +0 -403
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
buildSessionRuntimeSnapshot,
|
|
14
14
|
createSessionRuntimeSubscriptionKey,
|
|
15
|
+
seedSessionRuntimeSubscriptionSnapshot,
|
|
15
16
|
subscribeToSessionRuntimeStateChanges
|
|
16
17
|
} from '../session-core/runtimeState.js';
|
|
17
18
|
import { SUPPORTED_PROVIDERS } from '../../shared/conversationEvents.js';
|
|
@@ -24,6 +25,7 @@ const INTEGRATION_PING_TIMEOUT_MS = 1500;
|
|
|
24
25
|
const INTEGRATION_EDITOR_REQUEST_TIMEOUT_MS = 15000;
|
|
25
26
|
const INTEGRATION_EDITOR_TYPE_PREFIX = 'integration.editor.';
|
|
26
27
|
const INTEGRATION_EDITOR_RESULT_SUFFIX = '.result';
|
|
28
|
+
const VALID_EDITING_STATES = Object.freeze(['editing', 'idle', 'completed', 'error']);
|
|
27
29
|
const INTEGRATION_EDITOR_CAPABILITIES = Object.freeze({
|
|
28
30
|
'integration.editor.snapshot.get': 'editor.snapshot',
|
|
29
31
|
'integration.editor.nodes.list': 'editor.nodes.list',
|
|
@@ -38,6 +40,35 @@ const pendingIntegrationPings = new Map();
|
|
|
38
40
|
const sessionStateSubscriptionsByWs = new Map();
|
|
39
41
|
const sessionStateSubscribersByKey = new Map();
|
|
40
42
|
|
|
43
|
+
// Editing state cache for resilience across connection drops
|
|
44
|
+
const recentEditingStates = new Map();
|
|
45
|
+
const EDITING_STATE_TTL_MS = 30 * 60 * 1000;
|
|
46
|
+
const EDITING_STATE_CLEANUP_INTERVAL_MS = 5 * 60 * 1000;
|
|
47
|
+
|
|
48
|
+
function cacheEditingState(channel, targetClientId, elementKey, state, taskRef) {
|
|
49
|
+
const key = `${channel}::${targetClientId}::${elementKey}`;
|
|
50
|
+
recentEditingStates.set(key, {
|
|
51
|
+
channel,
|
|
52
|
+
targetClientId,
|
|
53
|
+
elementKey,
|
|
54
|
+
state,
|
|
55
|
+
taskRef: taskRef || null,
|
|
56
|
+
updatedAt: Date.now(),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function cleanupExpiredEditingStates() {
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
for (const [key, entry] of recentEditingStates.entries()) {
|
|
63
|
+
if (now - entry.updatedAt > EDITING_STATE_TTL_MS) {
|
|
64
|
+
recentEditingStates.delete(key);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const editingStateCleanupTimer = setInterval(cleanupExpiredEditingStates, EDITING_STATE_CLEANUP_INTERVAL_MS);
|
|
70
|
+
editingStateCleanupTimer.unref?.();
|
|
71
|
+
|
|
41
72
|
function sendJson(ws, payload) {
|
|
42
73
|
if (ws.readyState === WebSocket.OPEN) {
|
|
43
74
|
ws.send(JSON.stringify(payload));
|
|
@@ -258,6 +289,7 @@ async function handleAgentStateSubscribe(ws, data) {
|
|
|
258
289
|
}
|
|
259
290
|
|
|
260
291
|
const subscriptionKey = createSessionRuntimeSubscriptionKey(normalized.provider, normalized.sessionId);
|
|
292
|
+
seedSessionRuntimeSubscriptionSnapshot(subscriptionKey, snapshot);
|
|
261
293
|
addSessionStateSubscription(ws, subscriptionKey);
|
|
262
294
|
|
|
263
295
|
sendJson(ws, {
|
|
@@ -369,6 +401,7 @@ function buildEditorClientSummary(meta) {
|
|
|
369
401
|
return {
|
|
370
402
|
channel: meta.channel,
|
|
371
403
|
clientId: meta.clientId,
|
|
404
|
+
source: meta.source || null,
|
|
372
405
|
sessionId: meta.sessionId || null,
|
|
373
406
|
pageUrl: meta.pageUrl || null,
|
|
374
407
|
lastSeenAt: meta.lastSeenAt || null,
|
|
@@ -565,6 +598,7 @@ function validateIntegrationConnectPayload(payload) {
|
|
|
565
598
|
role,
|
|
566
599
|
channel,
|
|
567
600
|
clientId,
|
|
601
|
+
source: normalizeNonEmptyString(payload.source) || null,
|
|
568
602
|
pageUrl: normalizeNonEmptyString(payload.pageUrl) || null,
|
|
569
603
|
sessionId: normalizeNonEmptyString(payload.sessionId) || null,
|
|
570
604
|
capabilities: Array.isArray(payload.capabilities)
|
|
@@ -948,8 +982,12 @@ function validateEditorEditingSetPayload(payload) {
|
|
|
948
982
|
}
|
|
949
983
|
|
|
950
984
|
const state = normalizeNonEmptyString(payload.state);
|
|
951
|
-
if (state
|
|
952
|
-
return {
|
|
985
|
+
if (!VALID_EDITING_STATES.includes(state)) {
|
|
986
|
+
return {
|
|
987
|
+
ok: false,
|
|
988
|
+
code: 'INVALID_PAYLOAD',
|
|
989
|
+
message: `state must be one of: ${VALID_EDITING_STATES.join(', ')}`
|
|
990
|
+
};
|
|
953
991
|
}
|
|
954
992
|
|
|
955
993
|
return validateEditorTargetPayload(payload, {
|
|
@@ -1137,6 +1175,24 @@ async function forwardIntegrationResponseToOrigin(data) {
|
|
|
1137
1175
|
outgoingData?.type === 'integration.error'
|
|
1138
1176
|
|| isEditorResultMessageType(outgoingData?.type)
|
|
1139
1177
|
|| (outgoingData?.type === 'integration.ack' && pendingRequest.awaitResult !== true);
|
|
1178
|
+
|
|
1179
|
+
// Cache successful editing state changes for resilience
|
|
1180
|
+
if (
|
|
1181
|
+
outgoingData?.type === 'integration.editor.editing.result'
|
|
1182
|
+
&& isPlainObject(outgoingData?.payload)
|
|
1183
|
+
&& outgoingData.payload.applied === true
|
|
1184
|
+
&& pendingRequest.requestPayload
|
|
1185
|
+
) {
|
|
1186
|
+
const rp = pendingRequest.requestPayload;
|
|
1187
|
+
cacheEditingState(
|
|
1188
|
+
rp.channel,
|
|
1189
|
+
rp.targetClientId,
|
|
1190
|
+
outgoingData.payload.elementKey || rp.elementKey,
|
|
1191
|
+
outgoingData.payload.state,
|
|
1192
|
+
outgoingData.payload.taskRef || rp.taskRef,
|
|
1193
|
+
);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1140
1196
|
if (isTerminal) {
|
|
1141
1197
|
clearPendingIntegrationRequest(requestId);
|
|
1142
1198
|
}
|
|
@@ -1173,7 +1229,11 @@ class ExternalAgentWebSocketWriter {
|
|
|
1173
1229
|
requestId: this.requestId,
|
|
1174
1230
|
provider: payload.provider || this.provider,
|
|
1175
1231
|
sessionId,
|
|
1176
|
-
...buildSessionNavigation(
|
|
1232
|
+
...buildSessionNavigation({
|
|
1233
|
+
provider: payload.provider || this.provider,
|
|
1234
|
+
sessionId,
|
|
1235
|
+
projectPath: payload.projectPath || null
|
|
1236
|
+
})
|
|
1177
1237
|
});
|
|
1178
1238
|
return;
|
|
1179
1239
|
}
|
package/server/gemini-cli.js
CHANGED
|
@@ -4,15 +4,13 @@ import {
|
|
|
4
4
|
getActiveAgentSessions,
|
|
5
5
|
isAgentSessionActive
|
|
6
6
|
} from './acp-runtime/index.js';
|
|
7
|
-
import { GEMINI_MODELS } from '../shared/modelConstants.js';
|
|
8
7
|
|
|
9
8
|
export async function queryGemini(command, options = {}, writer) {
|
|
10
9
|
return executeAgentPrompt({
|
|
11
10
|
agentKey: 'gemini',
|
|
12
11
|
command,
|
|
13
12
|
options: {
|
|
14
|
-
...options
|
|
15
|
-
model: options.model || GEMINI_MODELS.DEFAULT
|
|
13
|
+
...options
|
|
16
14
|
},
|
|
17
15
|
writer
|
|
18
16
|
});
|
package/server/index.js
CHANGED
|
@@ -96,7 +96,7 @@ async function getPty() {
|
|
|
96
96
|
import fetch from 'node-fetch';
|
|
97
97
|
import mime from 'mime-types';
|
|
98
98
|
|
|
99
|
-
import { getProjects, getSessions, getSessionMessages, renameProject, deleteSession, deleteProject, addProjectManually, extractProjectDirectory, clearProjectDirectoryCache, clearProviderSessionLookupCaches, getGeminiSessionMessages } from './projects.js';
|
|
99
|
+
import { getProjects, getProjectsList, getProjectDetails, getSessions, getSessionMessages, renameProject, deleteSession, deleteProject, addProjectManually, extractProjectDirectory, clearProjectDirectoryCache, clearProviderSessionLookupCaches, getGeminiSessionMessages } from './projects.js';
|
|
100
100
|
import {
|
|
101
101
|
executeAgentPrompt,
|
|
102
102
|
getActiveAgentSessions,
|
|
@@ -113,8 +113,20 @@ import commandsRoutes from './routes/commands.js';
|
|
|
113
113
|
import settingsRoutes from './routes/settings.js';
|
|
114
114
|
import channelsRoutes from './routes/channels.js';
|
|
115
115
|
import agentRoutes from './routes/agent.js';
|
|
116
|
-
import projectsRoutes, {
|
|
116
|
+
import projectsRoutes, {
|
|
117
|
+
DEFAULT_WORKSPACES_ROOT,
|
|
118
|
+
HAS_WORKSPACES_ROOT_RESTRICTION,
|
|
119
|
+
WORKSPACES_ROOTS,
|
|
120
|
+
validateWorkspacePath
|
|
121
|
+
} from './routes/projects.js';
|
|
122
|
+
import {
|
|
123
|
+
UNIX_WORKSPACE_ROOTS,
|
|
124
|
+
buildWorkspaceRootSuggestions,
|
|
125
|
+
expandWorkspacePath,
|
|
126
|
+
shouldUseVirtualWorkspaceRoots
|
|
127
|
+
} from './utils/workspaceRoots.js';
|
|
117
128
|
import cliAuthRoutes, { detectProviderInstallationStatus } from './routes/cli-auth.js';
|
|
129
|
+
import ccConnectRoutes from './routes/cc-connect.js';
|
|
118
130
|
import userRoutes from './routes/user.js';
|
|
119
131
|
import codexRoutes from './routes/codex.js';
|
|
120
132
|
import opencodeRoutes from './routes/opencode.js';
|
|
@@ -138,6 +150,7 @@ const UPDATE_PACKAGE_NAME = process.env.UPDATE_PACKAGE_NAME || packageInfo.id ||
|
|
|
138
150
|
const VERSION_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
|
|
139
151
|
let cachedSystemVersion = null;
|
|
140
152
|
let cachedSystemVersionExpiresAt = 0;
|
|
153
|
+
const WINDOWS_DRIVES_ROOT = '__windows_drives__';
|
|
141
154
|
const RUNTIME_STATUS_PATH = (() => {
|
|
142
155
|
if (process.env.AXHUB_GENIE_STATUS_PATH) {
|
|
143
156
|
return process.env.AXHUB_GENIE_STATUS_PATH;
|
|
@@ -320,8 +333,8 @@ async function setupProjectsWatcher() {
|
|
|
320
333
|
clearProjectDirectoryCache();
|
|
321
334
|
clearProviderSessionLookupCaches();
|
|
322
335
|
|
|
323
|
-
// Get updated projects list
|
|
324
|
-
const updatedProjects = await
|
|
336
|
+
// Get updated lightweight projects list
|
|
337
|
+
const updatedProjects = await getProjectsList(broadcastProgress);
|
|
325
338
|
|
|
326
339
|
// Notify all connected clients about the project changes
|
|
327
340
|
const changedProvider = filePath.startsWith(codexSessionsPath)
|
|
@@ -330,14 +343,21 @@ async function setupProjectsWatcher() {
|
|
|
330
343
|
const changedFileRoot = changedProvider === 'codex'
|
|
331
344
|
? codexSessionsPath
|
|
332
345
|
: claudeProjectsPath;
|
|
346
|
+
const normalizedRelativePath = path.relative(changedFileRoot, filePath);
|
|
347
|
+
const changedPathSegments = normalizedRelativePath.split(path.sep).filter(Boolean);
|
|
348
|
+
const affectedProjectName = changedProvider === 'claude'
|
|
349
|
+
? (changedPathSegments[0] || null)
|
|
350
|
+
: null;
|
|
333
351
|
const updateMessage = JSON.stringify({
|
|
334
352
|
type: 'projects_updated',
|
|
335
353
|
projects: updatedProjects,
|
|
336
354
|
timestamp: new Date().toISOString(),
|
|
337
355
|
changeType: eventType,
|
|
338
|
-
changedFile:
|
|
356
|
+
changedFile: normalizedRelativePath,
|
|
339
357
|
changedProvider,
|
|
340
|
-
changedSessionId: extractSessionIdFromChangedFile(filePath)
|
|
358
|
+
changedSessionId: extractSessionIdFromChangedFile(filePath),
|
|
359
|
+
affectedProjectName,
|
|
360
|
+
requiresDetailsRefresh: Boolean(affectedProjectName)
|
|
341
361
|
});
|
|
342
362
|
|
|
343
363
|
connectedClients.forEach(client => {
|
|
@@ -504,6 +524,7 @@ app.use('/api/channels', authenticateToken, channelsRoutes);
|
|
|
504
524
|
|
|
505
525
|
// CLI Authentication API Routes (protected)
|
|
506
526
|
app.use('/api/cli', authenticateToken, cliAuthRoutes);
|
|
527
|
+
app.use('/api/cc-connect', authenticateToken, ccConnectRoutes);
|
|
507
528
|
|
|
508
529
|
// User API Routes (protected)
|
|
509
530
|
app.use('/api/user', authenticateToken, userRoutes);
|
|
@@ -633,6 +654,7 @@ app.post('/api/system/update', authenticateToken, async (req, res) => {
|
|
|
633
654
|
|
|
634
655
|
app.get('/api/projects', authenticateToken, async (req, res) => {
|
|
635
656
|
try {
|
|
657
|
+
res.setHeader('Deprecation', 'true');
|
|
636
658
|
const projects = await getProjects(broadcastProgress);
|
|
637
659
|
res.json(projects);
|
|
638
660
|
} catch (error) {
|
|
@@ -640,6 +662,27 @@ app.get('/api/projects', authenticateToken, async (req, res) => {
|
|
|
640
662
|
}
|
|
641
663
|
});
|
|
642
664
|
|
|
665
|
+
app.get('/api/projects/list', authenticateToken, async (req, res) => {
|
|
666
|
+
try {
|
|
667
|
+
const projects = await getProjectsList(broadcastProgress);
|
|
668
|
+
res.json(projects);
|
|
669
|
+
} catch (error) {
|
|
670
|
+
res.status(500).json({ error: error.message });
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
|
|
674
|
+
app.get('/api/projects/:projectName/details', authenticateToken, async (req, res) => {
|
|
675
|
+
try {
|
|
676
|
+
const project = await getProjectDetails(req.params.projectName);
|
|
677
|
+
res.json(project);
|
|
678
|
+
} catch (error) {
|
|
679
|
+
if (/Project not found/i.test(error.message)) {
|
|
680
|
+
return res.status(404).json({ error: error.message });
|
|
681
|
+
}
|
|
682
|
+
res.status(500).json({ error: error.message });
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
|
|
643
686
|
app.get('/api/projects/:projectName/sessions', authenticateToken, async (req, res) => {
|
|
644
687
|
try {
|
|
645
688
|
const { limit = 5, offset = 0 } = req.query;
|
|
@@ -743,16 +786,31 @@ app.post('/api/projects/create', authenticateToken, async (req, res) => {
|
|
|
743
786
|
}
|
|
744
787
|
});
|
|
745
788
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
}
|
|
789
|
+
async function listWindowsDrives() {
|
|
790
|
+
const checks = await Promise.all(
|
|
791
|
+
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('').map(async (letter) => {
|
|
792
|
+
const drivePath = `${letter}:\\`;
|
|
793
|
+
try {
|
|
794
|
+
await fsPromises.access(drivePath, fs.constants.R_OK);
|
|
795
|
+
const stats = await fsPromises.stat(drivePath);
|
|
796
|
+
if (!stats.isDirectory()) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
return {
|
|
801
|
+
path: drivePath,
|
|
802
|
+
name: drivePath,
|
|
803
|
+
type: 'directory',
|
|
804
|
+
isDrive: true
|
|
805
|
+
};
|
|
806
|
+
} catch (error) {
|
|
807
|
+
return null;
|
|
808
|
+
}
|
|
809
|
+
})
|
|
810
|
+
);
|
|
811
|
+
|
|
812
|
+
return checks.filter(Boolean);
|
|
813
|
+
}
|
|
756
814
|
|
|
757
815
|
// Browse filesystem endpoint for project suggestions - uses existing getFileTree
|
|
758
816
|
app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
|
|
@@ -760,9 +818,47 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
|
|
|
760
818
|
const { path: dirPath } = req.query;
|
|
761
819
|
|
|
762
820
|
console.log('[API] Browse filesystem request for path:', dirPath);
|
|
763
|
-
console.log('[API]
|
|
821
|
+
console.log('[API] WORKSPACES_ROOTS are:', WORKSPACES_ROOTS.length > 0 ? WORKSPACES_ROOTS : '(unrestricted)');
|
|
822
|
+
|
|
823
|
+
if (process.platform === 'win32' && dirPath === WINDOWS_DRIVES_ROOT) {
|
|
824
|
+
const suggestions = await listWindowsDrives();
|
|
825
|
+
return res.json({
|
|
826
|
+
path: WINDOWS_DRIVES_ROOT,
|
|
827
|
+
displayPath: 'This PC',
|
|
828
|
+
suggestions,
|
|
829
|
+
platform: process.platform,
|
|
830
|
+
virtualRoot: 'windows-drives',
|
|
831
|
+
hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
|
|
832
|
+
allowedRoots: WORKSPACES_ROOTS
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
if (shouldUseVirtualWorkspaceRoots({ dirPath })) {
|
|
837
|
+
const suggestions = buildWorkspaceRootSuggestions({
|
|
838
|
+
allowedWorkspaceRoots: WORKSPACES_ROOTS,
|
|
839
|
+
homeDir: DEFAULT_WORKSPACES_ROOT,
|
|
840
|
+
platform: process.platform
|
|
841
|
+
}).filter((entry) => {
|
|
842
|
+
try {
|
|
843
|
+
return fs.existsSync(entry.path);
|
|
844
|
+
} catch (error) {
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
});
|
|
848
|
+
|
|
849
|
+
return res.json({
|
|
850
|
+
path: UNIX_WORKSPACE_ROOTS,
|
|
851
|
+
displayPath: 'Allowed workspace roots',
|
|
852
|
+
suggestions,
|
|
853
|
+
platform: process.platform,
|
|
854
|
+
virtualRoot: 'workspace-roots',
|
|
855
|
+
hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
|
|
856
|
+
allowedRoots: WORKSPACES_ROOTS
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
|
|
764
860
|
// Default to home directory if no path provided
|
|
765
|
-
const defaultRoot =
|
|
861
|
+
const defaultRoot = DEFAULT_WORKSPACES_ROOT;
|
|
766
862
|
let targetPath = dirPath ? expandWorkspacePath(dirPath) : defaultRoot;
|
|
767
863
|
|
|
768
864
|
// Resolve and normalize the path
|
|
@@ -826,7 +922,12 @@ app.get('/api/browse-filesystem', authenticateToken, async (req, res) => {
|
|
|
826
922
|
|
|
827
923
|
res.json({
|
|
828
924
|
path: resolvedPath,
|
|
829
|
-
|
|
925
|
+
displayPath: resolvedPath,
|
|
926
|
+
suggestions: suggestions,
|
|
927
|
+
platform: process.platform,
|
|
928
|
+
virtualRoot: null,
|
|
929
|
+
hasWorkspaceRootRestriction: HAS_WORKSPACES_ROOT_RESTRICTION,
|
|
930
|
+
allowedRoots: WORKSPACES_ROOTS
|
|
830
931
|
});
|
|
831
932
|
|
|
832
933
|
} catch (error) {
|
package/server/openai-codex.js
CHANGED
|
@@ -4,15 +4,13 @@ import {
|
|
|
4
4
|
getActiveAgentSessions,
|
|
5
5
|
isAgentSessionActive
|
|
6
6
|
} from './acp-runtime/index.js';
|
|
7
|
-
import { CODEX_MODELS } from '../shared/modelConstants.js';
|
|
8
7
|
|
|
9
8
|
export async function queryCodex(command, options = {}, writer) {
|
|
10
9
|
return executeAgentPrompt({
|
|
11
10
|
agentKey: 'codex',
|
|
12
11
|
command,
|
|
13
12
|
options: {
|
|
14
|
-
...options
|
|
15
|
-
model: options.model || CODEX_MODELS.DEFAULT
|
|
13
|
+
...options
|
|
16
14
|
},
|
|
17
15
|
writer
|
|
18
16
|
});
|
package/server/opencode-cli.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
getActiveAgentSessions,
|
|
5
5
|
isAgentSessionActive
|
|
6
6
|
} from './acp-runtime/index.js';
|
|
7
|
-
import { OPENCODE_MODELS } from '../shared/modelConstants.js';
|
|
8
7
|
import { spawnCommand } from './utils/spawnCommand.js';
|
|
9
8
|
import { resolveWorkingDirectory } from './utils/defaultWorkingDirectory.js';
|
|
10
9
|
|
|
@@ -84,8 +83,7 @@ export async function queryOpencode(command, options = {}, writer) {
|
|
|
84
83
|
agentKey: 'opencode',
|
|
85
84
|
command,
|
|
86
85
|
options: {
|
|
87
|
-
...options
|
|
88
|
-
model: options.model || OPENCODE_MODELS.DEFAULT
|
|
86
|
+
...options
|
|
89
87
|
},
|
|
90
88
|
writer
|
|
91
89
|
});
|