@grackle-ai/server 0.40.0 → 0.41.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/dist/db.d.ts.map +1 -1
- package/dist/db.js +10 -0
- package/dist/db.js.map +1 -1
- package/dist/event-bus.d.ts +37 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +65 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/event-processor.d.ts.map +1 -1
- package/dist/event-processor.js +14 -11
- package/dist/event-processor.js.map +1 -1
- package/dist/event-store.d.ts +9 -0
- package/dist/event-store.d.ts.map +1 -0
- package/dist/event-store.js +16 -0
- package/dist/event-store.js.map +1 -0
- package/dist/github-import.js +3 -5
- package/dist/github-import.js.map +1 -1
- package/dist/grpc-service.d.ts +6 -0
- package/dist/grpc-service.d.ts.map +1 -1
- package/dist/grpc-service.js +29 -85
- package/dist/grpc-service.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/reanimate-agent.d.ts +12 -0
- package/dist/reanimate-agent.d.ts.map +1 -0
- package/dist/reanimate-agent.js +78 -0
- package/dist/reanimate-agent.js.map +1 -0
- package/dist/schema.d.ts +85 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +7 -0
- package/dist/schema.js.map +1 -1
- package/dist/session-store.d.ts +6 -1
- package/dist/session-store.d.ts.map +1 -1
- package/dist/session-store.js +23 -5
- package/dist/session-store.js.map +1 -1
- package/dist/ws-bridge.d.ts.map +1 -1
- package/dist/ws-bridge.js +92 -123
- package/dist/ws-bridge.js.map +1 -1
- package/dist/ws-broadcast.d.ts +5 -0
- package/dist/ws-broadcast.d.ts.map +1 -1
- package/dist/ws-broadcast.js +24 -0
- package/dist/ws-broadcast.js.map +1 -1
- package/package.json +7 -6
package/dist/ws-bridge.js
CHANGED
|
@@ -14,7 +14,7 @@ import * as findingStore from "./finding-store.js";
|
|
|
14
14
|
import * as personaStore from "./persona-store.js";
|
|
15
15
|
import { v4 as uuid } from "uuid";
|
|
16
16
|
import { join } from "node:path";
|
|
17
|
-
import { LOGS_DIR, SESSION_STATUS, TASK_STATUS, eventTypeToString, } from "@grackle-ai/common";
|
|
17
|
+
import { LOGS_DIR, SESSION_STATUS, TASK_STATUS, DEFAULT_MCP_PORT, eventTypeToString, } from "@grackle-ai/common";
|
|
18
18
|
import { resolvePersona } from "./resolve-persona.js";
|
|
19
19
|
import * as settingsStore from "./settings-store.js";
|
|
20
20
|
import { isAllowedSettingKey } from "./settings-store.js";
|
|
@@ -26,8 +26,13 @@ import { buildTaskSystemContext } from "./utils/system-context.js";
|
|
|
26
26
|
import { slugify } from "./utils/slugify.js";
|
|
27
27
|
import { processEventStream } from "./event-processor.js";
|
|
28
28
|
import * as processorRegistry from "./processor-registry.js";
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
29
|
+
import { setWssInstance, envRowToWs } from "./ws-broadcast.js";
|
|
30
|
+
import { emit } from "./event-bus.js";
|
|
31
|
+
import { buildMcpServersJson, toDialableHost } from "./grpc-service.js";
|
|
32
|
+
import { createScopedToken } from "@grackle-ai/mcp";
|
|
33
|
+
import { loadOrCreateApiKey } from "./api-key.js";
|
|
34
|
+
import { reanimateAgent } from "./reanimate-agent.js";
|
|
35
|
+
import { ConnectError } from "@connectrpc/connect";
|
|
31
36
|
import { computeTaskStatus } from "./compute-task-status.js";
|
|
32
37
|
import { exec } from "./utils/exec.js";
|
|
33
38
|
import { formatGhError } from "./utils/format-gh-error.js";
|
|
@@ -111,20 +116,17 @@ async function autoProvisionEnvironment(ws, environmentId, env, logContext) {
|
|
|
111
116
|
}
|
|
112
117
|
logger.info({ environmentId, ...logContext }, "Auto-provisioning environment");
|
|
113
118
|
envRegistry.updateEnvironmentStatus(environmentId, "connecting");
|
|
114
|
-
|
|
119
|
+
emit("environment.changed", {});
|
|
115
120
|
try {
|
|
116
121
|
const config = safeParseAdapterConfig(env.adapterConfig, environmentId);
|
|
117
122
|
const powerlineToken = env.powerlineToken || "";
|
|
118
123
|
for await (const provEvent of reconnectOrProvision(environmentId, adapter, config, powerlineToken, !!env.bootstrapped)) {
|
|
119
124
|
logger.info({ environmentId, stage: provEvent.stage, ...logContext }, "Auto-provision progress");
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
message: provEvent.message,
|
|
126
|
-
progress: provEvent.progress,
|
|
127
|
-
},
|
|
125
|
+
emit("environment.provision_progress", {
|
|
126
|
+
environmentId,
|
|
127
|
+
stage: provEvent.stage,
|
|
128
|
+
message: provEvent.message,
|
|
129
|
+
progress: provEvent.progress,
|
|
128
130
|
});
|
|
129
131
|
}
|
|
130
132
|
conn = await adapter.connect(environmentId, config, powerlineToken);
|
|
@@ -133,32 +135,26 @@ async function autoProvisionEnvironment(ws, environmentId, env, logContext) {
|
|
|
133
135
|
await tokenBroker.pushToEnv(environmentId);
|
|
134
136
|
envRegistry.updateEnvironmentStatus(environmentId, "connected");
|
|
135
137
|
envRegistry.markBootstrapped(environmentId);
|
|
136
|
-
|
|
138
|
+
emit("environment.changed", {});
|
|
137
139
|
logger.info({ environmentId, ...logContext }, "Auto-provision complete");
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
message: "Environment connected",
|
|
144
|
-
progress: 1,
|
|
145
|
-
},
|
|
140
|
+
emit("environment.provision_progress", {
|
|
141
|
+
environmentId,
|
|
142
|
+
stage: "ready",
|
|
143
|
+
message: "Environment connected",
|
|
144
|
+
progress: 1,
|
|
146
145
|
});
|
|
147
146
|
return conn;
|
|
148
147
|
}
|
|
149
148
|
catch (err) {
|
|
150
149
|
logger.error({ environmentId, ...logContext, err }, "Auto-provision failed");
|
|
151
150
|
envRegistry.updateEnvironmentStatus(environmentId, "error");
|
|
152
|
-
|
|
151
|
+
emit("environment.changed", {});
|
|
153
152
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
message: `Auto-provision failed: ${errorMessage}`,
|
|
160
|
-
progress: 0,
|
|
161
|
-
},
|
|
153
|
+
emit("environment.provision_progress", {
|
|
154
|
+
environmentId,
|
|
155
|
+
stage: "error",
|
|
156
|
+
message: `Auto-provision failed: ${errorMessage}`,
|
|
157
|
+
progress: 0,
|
|
162
158
|
});
|
|
163
159
|
sendWs(ws, {
|
|
164
160
|
type: "error",
|
|
@@ -212,13 +208,10 @@ async function startTaskSession(ws, task, options) {
|
|
|
212
208
|
systemContext = systemPrompt + "\n\n" + systemContext;
|
|
213
209
|
}
|
|
214
210
|
sessionStore.createSession(sessionId, environmentId, runtime, freshTask.title, model, logPath, freshTask.id, resolved.personaId);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
sessionId,
|
|
220
|
-
projectId: freshTask.projectId,
|
|
221
|
-
},
|
|
211
|
+
emit("task.started", {
|
|
212
|
+
taskId: freshTask.id,
|
|
213
|
+
sessionId,
|
|
214
|
+
projectId: freshTask.projectId,
|
|
222
215
|
});
|
|
223
216
|
// Re-push stored tokens + provider credentials (scoped to runtime) so they're fresh for this session.
|
|
224
217
|
// For local envs, skip file tokens — the PowerLine is on the same machine.
|
|
@@ -236,6 +229,11 @@ async function startTaskSession(ws, task, options) {
|
|
|
236
229
|
catch {
|
|
237
230
|
logger.warn("Failed to parse persona.mcpServers JSON; ignoring");
|
|
238
231
|
}
|
|
232
|
+
// Build MCP broker URL + scoped token so runtimes can call the MCP server.
|
|
233
|
+
const mcpPort = parseInt(process.env.GRACKLE_MCP_PORT || String(DEFAULT_MCP_PORT), 10);
|
|
234
|
+
const mcpDialHost = toDialableHost(process.env.GRACKLE_HOST || "127.0.0.1");
|
|
235
|
+
const mcpUrl = `http://${mcpDialHost}:${mcpPort}/mcp`;
|
|
236
|
+
const mcpToken = createScopedToken({ sub: freshTask.id, pid: freshTask.projectId, per: resolved.personaId, sid: sessionId }, loadOrCreateApiKey());
|
|
239
237
|
const powerlineReq = create(powerline.SpawnRequestSchema, {
|
|
240
238
|
sessionId,
|
|
241
239
|
runtime,
|
|
@@ -250,6 +248,8 @@ async function startTaskSession(ws, task, options) {
|
|
|
250
248
|
projectId: freshTask.projectId,
|
|
251
249
|
taskId: freshTask.id,
|
|
252
250
|
mcpServersJson,
|
|
251
|
+
mcpUrl,
|
|
252
|
+
mcpToken,
|
|
253
253
|
});
|
|
254
254
|
processEventStream(conn.client.spawn(powerlineReq), {
|
|
255
255
|
sessionId,
|
|
@@ -529,11 +529,27 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
529
529
|
if (session.taskId) {
|
|
530
530
|
const task = taskStore.getTask(session.taskId);
|
|
531
531
|
if (task) {
|
|
532
|
-
|
|
532
|
+
emit("task.updated", { taskId: task.id, projectId: task.projectId });
|
|
533
533
|
}
|
|
534
534
|
}
|
|
535
535
|
break;
|
|
536
536
|
}
|
|
537
|
+
case "resume_agent": {
|
|
538
|
+
const resumeSessionId = msg.payload?.sessionId;
|
|
539
|
+
if (!resumeSessionId) {
|
|
540
|
+
sendWs(ws, { type: "error", payload: { message: "sessionId required" } });
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
try {
|
|
544
|
+
reanimateAgent(resumeSessionId);
|
|
545
|
+
sendWs(ws, { type: "agent_resumed", payload: { sessionId: resumeSessionId } });
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
const message = err instanceof ConnectError ? err.message : String(err);
|
|
549
|
+
sendWs(ws, { type: "error", payload: { message } });
|
|
550
|
+
}
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
537
553
|
// ─── Projects ──────────────────────────────────────────
|
|
538
554
|
case "list_projects": {
|
|
539
555
|
const rows = projectStore.listProjects();
|
|
@@ -574,15 +590,14 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
574
590
|
// useWorktrees defaults to true when not specified
|
|
575
591
|
const createUseWorktrees = msg.payload?.useWorktrees ?? true;
|
|
576
592
|
projectStore.createProject(id, name, msg.payload?.description || "", msg.payload?.repoUrl || "", msg.payload?.defaultEnvironmentId || "", createUseWorktrees, typeof msg.payload?.worktreeBasePath === "string" ? msg.payload.worktreeBasePath.trim() : "", msg.payload?.defaultPersonaId || "");
|
|
577
|
-
|
|
578
|
-
broadcast({ type: "project_created", payload: { project: row } });
|
|
593
|
+
emit("project.created", { projectId: id });
|
|
579
594
|
break;
|
|
580
595
|
}
|
|
581
596
|
case "archive_project": {
|
|
582
597
|
const projectId = msg.payload?.projectId;
|
|
583
598
|
if (projectId)
|
|
584
599
|
projectStore.archiveProject(projectId);
|
|
585
|
-
|
|
600
|
+
emit("project.archived", { projectId });
|
|
586
601
|
break;
|
|
587
602
|
}
|
|
588
603
|
case "update_project": {
|
|
@@ -620,7 +635,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
620
635
|
worktreeBasePath: worktreeBasePathVal,
|
|
621
636
|
defaultPersonaId: defaultPersonaIdVal,
|
|
622
637
|
});
|
|
623
|
-
|
|
638
|
+
emit("project.updated", { projectId });
|
|
624
639
|
break;
|
|
625
640
|
}
|
|
626
641
|
// ─── Personas ──────────────────────────────────────────
|
|
@@ -666,7 +681,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
666
681
|
personaId = `${slugify(personaName) || "persona"}-${uuid().slice(0, 4)}`;
|
|
667
682
|
}
|
|
668
683
|
personaStore.createPersona(personaId, personaName, msg.payload?.description || "", personaSystemPrompt, msg.payload?.toolConfig || "{}", msg.payload?.runtime || "", msg.payload?.model || "", msg.payload?.maxTurns || 0, msg.payload?.mcpServers || "[]");
|
|
669
|
-
|
|
684
|
+
emit("persona.created", { personaId });
|
|
670
685
|
break;
|
|
671
686
|
}
|
|
672
687
|
case "get_persona": {
|
|
@@ -702,10 +717,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
702
717
|
return;
|
|
703
718
|
}
|
|
704
719
|
personaStore.updatePersona(updatePersonaId, msg.payload?.name || existingPersona.name, msg.payload?.description || existingPersona.description, msg.payload?.systemPrompt || existingPersona.systemPrompt, msg.payload?.toolConfig || existingPersona.toolConfig, msg.payload?.runtime || existingPersona.runtime, msg.payload?.model || existingPersona.model, msg.payload?.maxTurns || existingPersona.maxTurns, msg.payload?.mcpServers || existingPersona.mcpServers);
|
|
705
|
-
|
|
706
|
-
type: "persona_updated",
|
|
707
|
-
payload: { personaId: updatePersonaId },
|
|
708
|
-
});
|
|
720
|
+
emit("persona.updated", { personaId: updatePersonaId });
|
|
709
721
|
break;
|
|
710
722
|
}
|
|
711
723
|
case "delete_persona": {
|
|
@@ -713,10 +725,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
713
725
|
if (!deletePersonaId)
|
|
714
726
|
return;
|
|
715
727
|
personaStore.deletePersona(deletePersonaId);
|
|
716
|
-
|
|
717
|
-
type: "persona_deleted",
|
|
718
|
-
payload: { personaId: deletePersonaId },
|
|
719
|
-
});
|
|
728
|
+
emit("persona.deleted", { personaId: deletePersonaId });
|
|
720
729
|
break;
|
|
721
730
|
}
|
|
722
731
|
// ─── Settings ────────────────────────────────────────────
|
|
@@ -754,7 +763,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
754
763
|
}
|
|
755
764
|
}
|
|
756
765
|
settingsStore.setSetting(key, value);
|
|
757
|
-
|
|
766
|
+
emit("setting.changed", { key, value });
|
|
758
767
|
break;
|
|
759
768
|
}
|
|
760
769
|
// ─── Tasks ─────────────────────────────────────────────
|
|
@@ -834,16 +843,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
834
843
|
try {
|
|
835
844
|
const id = uuid().slice(0, 8);
|
|
836
845
|
taskStore.createTask(id, projectId, title, msg.payload?.description || "", msg.payload?.dependsOn || [], slugify(project.name), parentTaskId, canDecompose, msg.payload?.defaultPersonaId || "");
|
|
837
|
-
|
|
838
|
-
broadcast({
|
|
839
|
-
type: "task_created",
|
|
840
|
-
payload: {
|
|
841
|
-
task: row
|
|
842
|
-
? { ...row, dependsOn: safeParseJsonArray(row.dependsOn) }
|
|
843
|
-
: null,
|
|
844
|
-
requestId,
|
|
845
|
-
},
|
|
846
|
-
});
|
|
846
|
+
emit("task.created", { taskId: id, projectId, requestId });
|
|
847
847
|
}
|
|
848
848
|
catch (error) {
|
|
849
849
|
const message = error instanceof Error ? error.message : "Failed to create task";
|
|
@@ -897,10 +897,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
897
897
|
sendWs(ws, { type: "error", payload: { message: String(err) } });
|
|
898
898
|
return;
|
|
899
899
|
}
|
|
900
|
-
|
|
901
|
-
type: "task_started",
|
|
902
|
-
payload: { taskId: updateTaskId, sessionId: lateBindSessionId, projectId: existingTask.projectId },
|
|
903
|
-
});
|
|
900
|
+
emit("task.started", { taskId: updateTaskId, sessionId: lateBindSessionId, projectId: existingTask.projectId });
|
|
904
901
|
break;
|
|
905
902
|
}
|
|
906
903
|
// Only allow editing not_started tasks (non-late-bind path)
|
|
@@ -929,17 +926,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
929
926
|
? msg.payload.defaultPersonaId
|
|
930
927
|
: undefined;
|
|
931
928
|
taskStore.updateTask(updateTaskId, updatedTitle, updatedDescription, existingTask.status, updatedDependsOn, updatedDefaultPersonaId);
|
|
932
|
-
|
|
933
|
-
broadcast({
|
|
934
|
-
type: "task_updated",
|
|
935
|
-
payload: {
|
|
936
|
-
taskId: updateTaskId,
|
|
937
|
-
projectId: existingTask.projectId,
|
|
938
|
-
task: updatedRow
|
|
939
|
-
? { ...updatedRow, dependsOn: safeParseJsonArray(updatedRow.dependsOn) }
|
|
940
|
-
: null,
|
|
941
|
-
},
|
|
942
|
-
});
|
|
929
|
+
emit("task.updated", { taskId: updateTaskId, projectId: existingTask.projectId });
|
|
943
930
|
break;
|
|
944
931
|
}
|
|
945
932
|
case "start_task": {
|
|
@@ -999,10 +986,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
999
986
|
},
|
|
1000
987
|
});
|
|
1001
988
|
if (task) {
|
|
1002
|
-
|
|
1003
|
-
type: "task_completed",
|
|
1004
|
-
payload: { taskId, projectId: task.projectId },
|
|
1005
|
-
});
|
|
989
|
+
emit("task.completed", { taskId, projectId: task.projectId });
|
|
1006
990
|
}
|
|
1007
991
|
break;
|
|
1008
992
|
}
|
|
@@ -1055,10 +1039,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1055
1039
|
projectId: task.projectId,
|
|
1056
1040
|
taskId: task.id,
|
|
1057
1041
|
});
|
|
1058
|
-
|
|
1059
|
-
type: "task_started",
|
|
1060
|
-
payload: { taskId: task.id, sessionId: latestSession.id, projectId: task.projectId },
|
|
1061
|
-
});
|
|
1042
|
+
emit("task.started", { taskId: task.id, sessionId: latestSession.id, projectId: task.projectId });
|
|
1062
1043
|
break;
|
|
1063
1044
|
}
|
|
1064
1045
|
case "delete_task": {
|
|
@@ -1107,7 +1088,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1107
1088
|
sendWs(ws, { type: "error", payload: { message: `Failed to delete task ${taskId}: no rows affected` } });
|
|
1108
1089
|
return;
|
|
1109
1090
|
}
|
|
1110
|
-
|
|
1091
|
+
emit("task.deleted", { taskId, projectId: deletedTask.projectId });
|
|
1111
1092
|
break;
|
|
1112
1093
|
}
|
|
1113
1094
|
// ─── Task Sessions ─────────────────────────────────────
|
|
@@ -1258,7 +1239,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1258
1239
|
}
|
|
1259
1240
|
logger.info({ environmentId, adapterType: env.adapterType }, "Provisioning environment");
|
|
1260
1241
|
envRegistry.updateEnvironmentStatus(environmentId, "connecting");
|
|
1261
|
-
|
|
1242
|
+
emit("environment.changed", {});
|
|
1262
1243
|
// Run provision in background, broadcasting progress to all connected clients
|
|
1263
1244
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
1264
1245
|
(async () => {
|
|
@@ -1267,14 +1248,11 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1267
1248
|
const powerlineToken = env.powerlineToken || "";
|
|
1268
1249
|
for await (const event of reconnectOrProvision(environmentId, adapter, config, powerlineToken, !!env.bootstrapped)) {
|
|
1269
1250
|
logger.info({ environmentId, stage: event.stage, message: event.message }, "Provision progress");
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
message: event.message,
|
|
1276
|
-
progress: event.progress,
|
|
1277
|
-
},
|
|
1251
|
+
emit("environment.provision_progress", {
|
|
1252
|
+
environmentId,
|
|
1253
|
+
stage: event.stage,
|
|
1254
|
+
message: event.message,
|
|
1255
|
+
progress: event.progress,
|
|
1278
1256
|
});
|
|
1279
1257
|
}
|
|
1280
1258
|
logger.info({ environmentId }, "Provision complete, calling adapter.connect");
|
|
@@ -1285,31 +1263,25 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1285
1263
|
envRegistry.updateEnvironmentStatus(environmentId, "connected");
|
|
1286
1264
|
envRegistry.markBootstrapped(environmentId);
|
|
1287
1265
|
logger.info({ environmentId }, "Environment connected");
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
message: "Environment connected",
|
|
1294
|
-
progress: 1,
|
|
1295
|
-
},
|
|
1266
|
+
emit("environment.provision_progress", {
|
|
1267
|
+
environmentId,
|
|
1268
|
+
stage: "ready",
|
|
1269
|
+
message: "Environment connected",
|
|
1270
|
+
progress: 1,
|
|
1296
1271
|
});
|
|
1297
1272
|
}
|
|
1298
1273
|
catch (err) {
|
|
1299
1274
|
logger.error({ environmentId, err }, "Provision failed");
|
|
1300
1275
|
envRegistry.updateEnvironmentStatus(environmentId, "error");
|
|
1301
1276
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
message: `Connection failed: ${errorMessage}`,
|
|
1308
|
-
progress: 0,
|
|
1309
|
-
},
|
|
1277
|
+
emit("environment.provision_progress", {
|
|
1278
|
+
environmentId,
|
|
1279
|
+
stage: "error",
|
|
1280
|
+
message: `Connection failed: ${errorMessage}`,
|
|
1281
|
+
progress: 0,
|
|
1310
1282
|
});
|
|
1311
1283
|
}
|
|
1312
|
-
|
|
1284
|
+
emit("environment.changed", {});
|
|
1313
1285
|
})();
|
|
1314
1286
|
break;
|
|
1315
1287
|
}
|
|
@@ -1338,7 +1310,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1338
1310
|
adapterManager.removeConnection(environmentId);
|
|
1339
1311
|
envRegistry.updateEnvironmentStatus(environmentId, "disconnected");
|
|
1340
1312
|
logger.info({ environmentId }, "Environment stopped");
|
|
1341
|
-
|
|
1313
|
+
emit("environment.changed", {});
|
|
1342
1314
|
break;
|
|
1343
1315
|
}
|
|
1344
1316
|
case "add_environment": {
|
|
@@ -1399,8 +1371,8 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1399
1371
|
}
|
|
1400
1372
|
envRegistry.addEnvironment(id, displayName, adapterType, adapterConfig);
|
|
1401
1373
|
logger.info({ id, displayName, adapterType }, "Environment added via WebSocket");
|
|
1402
|
-
|
|
1403
|
-
|
|
1374
|
+
emit("environment.added", { environmentId: id });
|
|
1375
|
+
emit("environment.changed", {});
|
|
1404
1376
|
break;
|
|
1405
1377
|
}
|
|
1406
1378
|
case "remove_environment": {
|
|
@@ -1435,8 +1407,8 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1435
1407
|
sessionStore.deleteByEnvironment(environmentId);
|
|
1436
1408
|
envRegistry.removeEnvironment(environmentId);
|
|
1437
1409
|
logger.info({ environmentId }, "Environment removed");
|
|
1438
|
-
|
|
1439
|
-
|
|
1410
|
+
emit("environment.removed", { environmentId });
|
|
1411
|
+
emit("environment.changed", {});
|
|
1440
1412
|
break;
|
|
1441
1413
|
}
|
|
1442
1414
|
// ─── Codespaces ─────────────────────────────────────
|
|
@@ -1536,7 +1508,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1536
1508
|
value,
|
|
1537
1509
|
expiresAt: msg.payload?.expiresAt || "",
|
|
1538
1510
|
});
|
|
1539
|
-
|
|
1511
|
+
emit("token.changed", {});
|
|
1540
1512
|
break;
|
|
1541
1513
|
}
|
|
1542
1514
|
case "delete_token": {
|
|
@@ -1546,7 +1518,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1546
1518
|
return;
|
|
1547
1519
|
}
|
|
1548
1520
|
await tokenBroker.deleteToken(tokenName);
|
|
1549
|
-
|
|
1521
|
+
emit("token.changed", {});
|
|
1550
1522
|
break;
|
|
1551
1523
|
}
|
|
1552
1524
|
case "get_credential_providers": {
|
|
@@ -1563,10 +1535,7 @@ async function handleMessage(ws, msg, subscriptions) {
|
|
|
1563
1535
|
return;
|
|
1564
1536
|
}
|
|
1565
1537
|
credentialProviders.setCredentialProviders(msg.payload);
|
|
1566
|
-
|
|
1567
|
-
type: "credential_providers",
|
|
1568
|
-
payload: credentialProviders.getCredentialProviders(),
|
|
1569
|
-
});
|
|
1538
|
+
emit("credential.providers_changed", credentialProviders.getCredentialProviders());
|
|
1570
1539
|
break;
|
|
1571
1540
|
}
|
|
1572
1541
|
}
|