@progmruansilva/omp-web 1.202608.0
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 -0
- package/README.md +181 -0
- package/dist/cli.js +1015 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/assets/CodeViewer-Da66baHj.js +4 -0
- package/dist/client/assets/TerminalPanel-Bj9an79F.js +126 -0
- package/dist/client/assets/UnifiedDiffViewer-eK_kynTO.js +34 -0
- package/dist/client/assets/index-DytaeWNd.js +3070 -0
- package/dist/client/assets/vendor-editor-core-CL2gOCIg.js +12 -0
- package/dist/client/assets/vendor-editor-languages-zOM9I4iZ.js +26 -0
- package/dist/client/assets/vendor-editor-legacy-B4QLsWF8.js +1 -0
- package/dist/client/assets/vendor-terminal-DDGTF8rc.css +1 -0
- package/dist/client/assets/vendor-terminal-DjQ08hXu.js +16 -0
- package/dist/client/favicon-16x16.png +0 -0
- package/dist/client/favicon-180x180.png +0 -0
- package/dist/client/favicon-192x192.png +0 -0
- package/dist/client/favicon-32x32.png +0 -0
- package/dist/client/favicon-512x512.png +0 -0
- package/dist/client/favicon.ico +0 -0
- package/dist/client/favicon.png +0 -0
- package/dist/client/favicon.svg +11 -0
- package/dist/client/index.html +67 -0
- package/dist/client/manifest.webmanifest +36 -0
- package/dist/config.js +272 -0
- package/dist/config.js.map +1 -0
- package/dist/docker/ompWebDockerCommandPlan.js +211 -0
- package/dist/docker/ompWebDockerCommandPlan.js.map +1 -0
- package/dist/omp-web-plugins/info/omp-web-plugin.js +51 -0
- package/dist/omp-web-plugins/info/package.json +9 -0
- package/dist/omp-web-plugins/schedule-prompts/omp-web-plugin.js +43 -0
- package/dist/omp-web-plugins/schedule-prompts/package.json +9 -0
- package/dist/omp-web-plugins/schedule-prompts/schedulePromptsPanelElement.js +242 -0
- package/dist/omp-web-plugins/schedule-prompts/types.js +2 -0
- package/dist/omp-web-plugins/updates/omp-web-plugin.js +173 -0
- package/dist/omp-web-plugins/updates/package.json +9 -0
- package/dist/omp-web-plugins/updates/updatesLogic.js +97 -0
- package/dist/ompWebVersionReport.js +217 -0
- package/dist/ompWebVersionReport.js.map +1 -0
- package/dist/plugin-api/unstable.d.ts +22 -0
- package/dist/plugin-api.d.ts +197 -0
- package/dist/server/activity/workspaceActivityRoutes.js +4 -0
- package/dist/server/activity/workspaceActivityRoutes.js.map +1 -0
- package/dist/server/activity/workspaceActivityService.js +98 -0
- package/dist/server/activity/workspaceActivityService.js.map +1 -0
- package/dist/server/app.js +162 -0
- package/dist/server/app.js.map +1 -0
- package/dist/server/configRoutes.js +270 -0
- package/dist/server/configRoutes.js.map +1 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js +130 -0
- package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -0
- package/dist/server/git/gitEnv.js +15 -0
- package/dist/server/git/gitEnv.js.map +1 -0
- package/dist/server/git/gitService.js +119 -0
- package/dist/server/git/gitService.js.map +1 -0
- package/dist/server/gitRoutes.js +23 -0
- package/dist/server/gitRoutes.js.map +1 -0
- package/dist/server/index.js +7 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/machines/machineClient.js +162 -0
- package/dist/server/machines/machineClient.js.map +1 -0
- package/dist/server/machines/machinePluginProxyRoutes.js +157 -0
- package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineProxyRoutes.js +127 -0
- package/dist/server/machines/machineProxyRoutes.js.map +1 -0
- package/dist/server/machines/machineRoutes.js +54 -0
- package/dist/server/machines/machineRoutes.js.map +1 -0
- package/dist/server/machines/machineService.js +230 -0
- package/dist/server/machines/machineService.js.map +1 -0
- package/dist/server/machines/machineStore.js +123 -0
- package/dist/server/machines/machineStore.js.map +1 -0
- package/dist/server/machines/proxyUtils.js +30 -0
- package/dist/server/machines/proxyUtils.js.map +1 -0
- package/dist/server/ompWebPluginService.js +279 -0
- package/dist/server/ompWebPluginService.js.map +1 -0
- package/dist/server/ompWebStatus.js +601 -0
- package/dist/server/ompWebStatus.js.map +1 -0
- package/dist/server/ompWebStatusCache.js +31 -0
- package/dist/server/ompWebStatusCache.js.map +1 -0
- package/dist/server/piPackageRoutes.js +82 -0
- package/dist/server/piPackageRoutes.js.map +1 -0
- package/dist/server/piPackageService.js +65 -0
- package/dist/server/piPackageService.js.map +1 -0
- package/dist/server/projects/directorySuggestions.js +37 -0
- package/dist/server/projects/directorySuggestions.js.map +1 -0
- package/dist/server/projects/projectService.js +31 -0
- package/dist/server/projects/projectService.js.map +1 -0
- package/dist/server/push/PushNotificationService.js +137 -0
- package/dist/server/push/PushNotificationService.js.map +1 -0
- package/dist/server/push/pushRoutes.js +55 -0
- package/dist/server/push/pushRoutes.js.map +1 -0
- package/dist/server/realtime/sessionEventHub.js +39 -0
- package/dist/server/realtime/sessionEventHub.js.map +1 -0
- package/dist/server/sessiond/sessionProxyRoutes.js +61 -0
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -0
- package/dist/server/sessiond.js +92 -0
- package/dist/server/sessiond.js.map +1 -0
- package/dist/server/sessions/attachmentService.js +112 -0
- package/dist/server/sessions/attachmentService.js.map +1 -0
- package/dist/server/sessions/authProviderOptions.js +52 -0
- package/dist/server/sessions/authProviderOptions.js.map +1 -0
- package/dist/server/sessions/authRoutes.js +59 -0
- package/dist/server/sessions/authRoutes.js.map +1 -0
- package/dist/server/sessions/authService.js +105 -0
- package/dist/server/sessions/authService.js.map +1 -0
- package/dist/server/sessions/builtinCommands.js +29 -0
- package/dist/server/sessions/builtinCommands.js.map +1 -0
- package/dist/server/sessions/editPreview.js +196 -0
- package/dist/server/sessions/editPreview.js.map +1 -0
- package/dist/server/sessions/messagePaging.js +41 -0
- package/dist/server/sessions/messagePaging.js.map +1 -0
- package/dist/server/sessions/oauthLoginFlowService.js +136 -0
- package/dist/server/sessions/oauthLoginFlowService.js.map +1 -0
- package/dist/server/sessions/piSessionManagerGateway.js +97 -0
- package/dist/server/sessions/piSessionManagerGateway.js.map +1 -0
- package/dist/server/sessions/piSessionService.js +2401 -0
- package/dist/server/sessions/piSessionService.js.map +1 -0
- package/dist/server/sessions/schedulePrompt/schedulePromptService.js +46 -0
- package/dist/server/sessions/schedulePrompt/schedulePromptService.js.map +1 -0
- package/dist/server/sessions/schedulePrompt/scheduler.js +315 -0
- package/dist/server/sessions/schedulePrompt/scheduler.js.map +1 -0
- package/dist/server/sessions/schedulePrompt/storage.js +118 -0
- package/dist/server/sessions/schedulePrompt/storage.js.map +1 -0
- package/dist/server/sessions/schedulePrompt/tool.js +252 -0
- package/dist/server/sessions/schedulePrompt/tool.js.map +1 -0
- package/dist/server/sessions/schedulePrompt/types.js +2 -0
- package/dist/server/sessions/schedulePrompt/types.js.map +1 -0
- package/dist/server/sessions/sessionArchiveStore.js +254 -0
- package/dist/server/sessions/sessionArchiveStore.js.map +1 -0
- package/dist/server/sessions/sessionArchiveTree.js +35 -0
- package/dist/server/sessions/sessionArchiveTree.js.map +1 -0
- package/dist/server/sessions/sessionCleanup.js +157 -0
- package/dist/server/sessions/sessionCleanup.js.map +1 -0
- package/dist/server/sessions/sessionCommandService.js +260 -0
- package/dist/server/sessions/sessionCommandService.js.map +1 -0
- package/dist/server/sessions/sessionNameGenerator.js +61 -0
- package/dist/server/sessions/sessionNameGenerator.js.map +1 -0
- package/dist/server/sessions/sessionRoutes.js +344 -0
- package/dist/server/sessions/sessionRoutes.js.map +1 -0
- package/dist/server/sessions/sessionRuntimeStore.js +2 -0
- package/dist/server/sessions/sessionRuntimeStore.js.map +1 -0
- package/dist/server/sessions/spawnSessionTool.js +41 -0
- package/dist/server/sessions/spawnSessionTool.js.map +1 -0
- package/dist/server/sessions/spawnSubsessionTool.js +203 -0
- package/dist/server/sessions/spawnSubsessionTool.js.map +1 -0
- package/dist/server/sessions/spawnTargetResolver.js +36 -0
- package/dist/server/sessions/spawnTargetResolver.js.map +1 -0
- package/dist/server/sessions/subsessionTranscript.js +233 -0
- package/dist/server/sessions/subsessionTranscript.js.map +1 -0
- package/dist/server/storage/projectStore.js +83 -0
- package/dist/server/storage/projectStore.js.map +1 -0
- package/dist/server/terminalProxyRoutes.js +140 -0
- package/dist/server/terminalProxyRoutes.js.map +1 -0
- package/dist/server/terminals/terminalRoutes.js +153 -0
- package/dist/server/terminals/terminalRoutes.js.map +1 -0
- package/dist/server/terminals/terminalService.js +320 -0
- package/dist/server/terminals/terminalService.js.map +1 -0
- package/dist/server/terminals/terminalSize.js +17 -0
- package/dist/server/terminals/terminalSize.js.map +1 -0
- package/dist/server/types.js +2 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/utils.js +8 -0
- package/dist/server/utils.js.map +1 -0
- package/dist/server/webSocketBridge.js +32 -0
- package/dist/server/webSocketBridge.js.map +1 -0
- package/dist/server/workingDirectory.js +44 -0
- package/dist/server/workingDirectory.js.map +1 -0
- package/dist/server/workspaceExplorerRoutes.js +109 -0
- package/dist/server/workspaceExplorerRoutes.js.map +1 -0
- package/dist/server/workspaces/effectivePathAccess.js +27 -0
- package/dist/server/workspaces/effectivePathAccess.js.map +1 -0
- package/dist/server/workspaces/fileContentService.js +181 -0
- package/dist/server/workspaces/fileContentService.js.map +1 -0
- package/dist/server/workspaces/fileSuggestions.js +512 -0
- package/dist/server/workspaces/fileSuggestions.js.map +1 -0
- package/dist/server/workspaces/fileTreeService.js +27 -0
- package/dist/server/workspaces/fileTreeService.js.map +1 -0
- package/dist/server/workspaces/gitWorktreeDiscovery.js +34 -0
- package/dist/server/workspaces/gitWorktreeDiscovery.js.map +1 -0
- package/dist/server/workspaces/imagePreviewService.js +40 -0
- package/dist/server/workspaces/imagePreviewService.js.map +1 -0
- package/dist/server/workspaces/pathAccessPolicy.js +87 -0
- package/dist/server/workspaces/pathAccessPolicy.js.map +1 -0
- package/dist/server/workspaces/pathSafety.js +54 -0
- package/dist/server/workspaces/pathSafety.js.map +1 -0
- package/dist/server/workspaces/projectOmpWebConfig.js +56 -0
- package/dist/server/workspaces/projectOmpWebConfig.js.map +1 -0
- package/dist/server/workspaces/workspaceContext.js +8 -0
- package/dist/server/workspaces/workspaceContext.js.map +1 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js +111 -0
- package/dist/server/workspaces/workspaceDeletionRoutes.js.map +1 -0
- package/dist/server/workspaces/workspaceService.js +39 -0
- package/dist/server/workspaces/workspaceService.js.map +1 -0
- package/dist/sessiond/config.js +9 -0
- package/dist/sessiond/config.js.map +1 -0
- package/dist/sessiond/sessionDaemonClient.js +65 -0
- package/dist/sessiond/sessionDaemonClient.js.map +1 -0
- package/dist/shared/activity.js +26 -0
- package/dist/shared/activity.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +688 -0
- package/dist/shared/apiTypes.js +11 -0
- package/dist/shared/apiTypes.js.map +1 -0
- package/dist/shared/capabilities.js +52 -0
- package/dist/shared/capabilities.js.map +1 -0
- package/dist/shared/federatedRoutes.js +79 -0
- package/dist/shared/federatedRoutes.js.map +1 -0
- package/dist/shared/machinePluginIds.js +41 -0
- package/dist/shared/machinePluginIds.js.map +1 -0
- package/dist/shared/ompWebStatusParsing.js +100 -0
- package/dist/shared/ompWebStatusParsing.js.map +1 -0
- package/dist/shared/pluginIds.js +5 -0
- package/dist/shared/pluginIds.js.map +1 -0
- package/dist/shared/promptAttachments.js +90 -0
- package/dist/shared/promptAttachments.js.map +1 -0
- package/dist/shared/thinkingLevels.d.ts +19 -0
- package/dist/shared/thinkingLevels.js +24 -0
- package/dist/shared/thinkingLevels.js.map +1 -0
- package/dist/shared/utils.js +4 -0
- package/dist/shared/utils.js.map +1 -0
- package/dist/shared/workspaceDeletion.js +12 -0
- package/dist/shared/workspaceDeletion.js.map +1 -0
- package/dist/shared/workspaceFiles.js +3 -0
- package/dist/shared/workspaceFiles.js.map +1 -0
- package/docs/assets/favicon.svg +11 -0
- package/docs/assets/omp-web-banner.png +0 -0
- package/docs/assets/omp-web-desktop.png +0 -0
- package/docs/assets/omp-web-mobile.png +0 -0
- package/docs/assets/omp-web-tablet.png +0 -0
- package/docs/config.md +208 -0
- package/docs/plugins.md +916 -0
- package/extensions/omp-web.ts +133 -0
- package/install.sh +5 -0
- package/package.json +141 -0
- package/plugin-api/unstable.d.ts +1 -0
- package/plugin-api.d.ts +1 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { normalizeRequestCwd } from "../workingDirectory.js";
|
|
2
|
+
import { normalizeSessionCleanupRequest } from "./sessionCleanup.js";
|
|
3
|
+
import { errorMessage, isRecord } from "../utils.js";
|
|
4
|
+
export function registerSessionRoutes(app, sessions, eventHub, prefix = "") {
|
|
5
|
+
app.get(`${prefix}/sessions`, async (request, reply) => {
|
|
6
|
+
if (request.query.cwd === undefined || request.query.cwd === "")
|
|
7
|
+
return reply.code(400).send({ error: "cwd query parameter is required" });
|
|
8
|
+
try {
|
|
9
|
+
return await sessions.list(normalizeRequestCwd(request.query.cwd));
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
app.post(`${prefix}/sessions`, async (request, reply) => {
|
|
16
|
+
try {
|
|
17
|
+
const body = requireRecord(request.body);
|
|
18
|
+
return await sessions.start(normalizeRequestCwd(requireString(body, "cwd")));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
app.post(`${prefix}/sessions/cleanup/preview`, async (request, reply) => {
|
|
25
|
+
try {
|
|
26
|
+
return await sessions.cleanupPreview(normalizeSessionCleanupRequest(optionalRecord(request.body)));
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
app.post(`${prefix}/sessions/cleanup`, async (request, reply) => {
|
|
33
|
+
try {
|
|
34
|
+
return await sessions.cleanup(normalizeSessionCleanupRequest(optionalRecord(request.body)));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return reply.code(400).send({ error: errorMessage(error) });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
app.post(`${prefix}/sessions/bulk/archive`, async (request, reply) => {
|
|
41
|
+
try {
|
|
42
|
+
return await sessions.archiveMany(bulkMutationRefsFromBody(request.body));
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
app.post(`${prefix}/sessions/bulk/delete-archived`, async (request, reply) => {
|
|
49
|
+
try {
|
|
50
|
+
return await sessions.deleteArchivedMany(bulkMutationRefsFromBody(request.body));
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
app.get(`${prefix}/sessions/:sessionId/messages`, async (request, reply) => {
|
|
57
|
+
try {
|
|
58
|
+
const page = { ...optionalField("before", optionalNumber(request.query.before)), ...optionalField("limit", optionalNumber(request.query.limit)) };
|
|
59
|
+
return await sessions.messages(sessionLookupFromQuery(request.params.sessionId, request.query), page);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return reply.code(404).send({ error: errorMessage(error) });
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
app.get(`${prefix}/sessions/:sessionId/status`, async (request, reply) => {
|
|
66
|
+
try {
|
|
67
|
+
return await sessions.status(sessionLookupFromQuery(request.params.sessionId, request.query));
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return reply.code(404).send({ error: errorMessage(error) });
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
app.get(`${prefix}/sessions/:sessionId/models`, async (request, reply) => {
|
|
74
|
+
try {
|
|
75
|
+
return { models: await sessions.availableModels(sessionLookupFromQuery(request.params.sessionId, request.query)) };
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return reply.code(404).send({ error: errorMessage(error) });
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
app.post(`${prefix}/sessions/:sessionId/model`, async (request, reply) => {
|
|
82
|
+
try {
|
|
83
|
+
const body = optionalRecord(request.body);
|
|
84
|
+
return await sessions.setModel(sessionLookupFromBody(request.params.sessionId, body), requireString(body, "provider"), requireString(body, "modelId"));
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
app.post(`${prefix}/sessions/:sessionId/model/cycle`, async (request, reply) => {
|
|
91
|
+
try {
|
|
92
|
+
const body = optionalRecord(request.body);
|
|
93
|
+
const direction = body["direction"];
|
|
94
|
+
if (direction !== undefined && direction !== "forward" && direction !== "backward")
|
|
95
|
+
throw new Error("direction must be forward or backward");
|
|
96
|
+
return await sessions.cycleModel(sessionLookupFromBody(request.params.sessionId, body), direction ?? "forward");
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
app.get(`${prefix}/sessions/:sessionId/thinking-levels`, async (request, reply) => {
|
|
103
|
+
try {
|
|
104
|
+
return { levels: await sessions.availableThinkingLevels(sessionLookupFromQuery(request.params.sessionId, request.query)) };
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return reply.code(404).send({ error: errorMessage(error) });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
app.post(`${prefix}/sessions/:sessionId/thinking-level`, async (request, reply) => {
|
|
111
|
+
try {
|
|
112
|
+
const body = optionalRecord(request.body);
|
|
113
|
+
// The level string is validated against the session's live available levels
|
|
114
|
+
// in the service, so it stays correct if pi changes the set.
|
|
115
|
+
return await sessions.setThinkingLevel(sessionLookupFromBody(request.params.sessionId, body), requireThinkingLevel(body["level"]));
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
app.post(`${prefix}/sessions/:sessionId/thinking-level/cycle`, async (request, reply) => {
|
|
122
|
+
try {
|
|
123
|
+
const body = optionalRecord(request.body);
|
|
124
|
+
return await sessions.cycleThinkingLevel(sessionLookupFromBody(request.params.sessionId, body));
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
app.get(`${prefix}/sessions/:sessionId/commands`, async (request, reply) => {
|
|
131
|
+
try {
|
|
132
|
+
return await sessions.commands(sessionLookupFromQuery(request.params.sessionId, request.query));
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return reply.code(404).send({ error: errorMessage(error) });
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
app.post(`${prefix}/sessions/:sessionId/prompt`, async (request, reply) => {
|
|
139
|
+
try {
|
|
140
|
+
const body = optionalRecord(request.body);
|
|
141
|
+
await sessions.prompt(sessionLookupFromBody(request.params.sessionId, body), body["text"], body["streamingBehavior"], body["attachments"]);
|
|
142
|
+
return { accepted: true };
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
app.post(`${prefix}/sessions/:sessionId/attachments`, async (request, reply) => {
|
|
149
|
+
try {
|
|
150
|
+
const body = optionalRecord(request.body);
|
|
151
|
+
const folder = body["folder"];
|
|
152
|
+
if (folder !== undefined && typeof folder !== "string")
|
|
153
|
+
throw new Error("folder field must be a string");
|
|
154
|
+
const attachments = await sessions.saveAttachments(sessionLookupFromBody(request.params.sessionId, body), body["attachments"], folder);
|
|
155
|
+
return { attachments };
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
app.post(`${prefix}/sessions/:sessionId/shell`, async (request, reply) => {
|
|
162
|
+
try {
|
|
163
|
+
const body = optionalRecord(request.body);
|
|
164
|
+
await sessions.shell(sessionLookupFromBody(request.params.sessionId, body), requireString(body, "text"));
|
|
165
|
+
return { accepted: true };
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
app.post(`${prefix}/sessions/:sessionId/commands/run`, async (request, reply) => {
|
|
172
|
+
try {
|
|
173
|
+
const body = optionalRecord(request.body);
|
|
174
|
+
return await sessions.runCommand(sessionLookupFromBody(request.params.sessionId, body), requireString(body, "text"));
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
app.post(`${prefix}/sessions/:sessionId/commands/respond`, async (request, reply) => {
|
|
181
|
+
try {
|
|
182
|
+
const body = optionalRecord(request.body);
|
|
183
|
+
return await sessions.respondToCommand(sessionLookupFromBody(request.params.sessionId, body), requireString(body, "requestId"), requireString(body, "value"));
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
app.post(`${prefix}/sessions/:sessionId/abort`, async (request, reply) => {
|
|
190
|
+
try {
|
|
191
|
+
await sessions.abort(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
192
|
+
return { aborted: true };
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
app.post(`${prefix}/sessions/:sessionId/stop`, (request, reply) => {
|
|
199
|
+
try {
|
|
200
|
+
sessions.stop(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
201
|
+
return { stopped: true };
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
app.post(`${prefix}/sessions/:sessionId/archive`, async (request, reply) => {
|
|
208
|
+
try {
|
|
209
|
+
await sessions.archive(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
210
|
+
return { archived: true };
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
app.post(`${prefix}/sessions/:sessionId/archive-tree`, async (request, reply) => {
|
|
217
|
+
try {
|
|
218
|
+
return await sessions.archiveTree(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
app.post(`${prefix}/sessions/:sessionId/restore`, async (request, reply) => {
|
|
225
|
+
try {
|
|
226
|
+
await sessions.restore(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
227
|
+
return { restored: true };
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
app.delete(`${prefix}/sessions/:sessionId`, async (request, reply) => {
|
|
234
|
+
try {
|
|
235
|
+
await sessions.deleteArchived(sessionLookupFromQuery(request.params.sessionId, request.query));
|
|
236
|
+
return { deleted: true };
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
app.post(`${prefix}/sessions/:sessionId/reload`, async (request, reply) => {
|
|
243
|
+
try {
|
|
244
|
+
await sessions.reload(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
245
|
+
return { reloaded: true };
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
app.post(`${prefix}/sessions/:sessionId/detach-parent`, async (request, reply) => {
|
|
252
|
+
try {
|
|
253
|
+
await sessions.detachParent(sessionLookupFromBody(request.params.sessionId, optionalRecord(request.body)));
|
|
254
|
+
return { detached: true };
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
return reply.code(mutationErrorStatus(error)).send({ error: errorMessage(error) });
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
app.get(`${prefix}/sessions/:sessionId/events`, { websocket: true }, (socket, request) => {
|
|
261
|
+
// Only the id matters for event subscription; cwd is intentionally ignored
|
|
262
|
+
// so a malformed value cannot throw inside the websocket handler.
|
|
263
|
+
eventHub.add(request.params.sessionId, socket);
|
|
264
|
+
});
|
|
265
|
+
app.get(`${prefix}/sessions/events`, { websocket: true }, (socket) => {
|
|
266
|
+
eventHub.addGlobal(socket);
|
|
267
|
+
});
|
|
268
|
+
app.get(`${prefix}/events`, { websocket: true }, (socket) => {
|
|
269
|
+
eventHub.addGlobal(socket);
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
function bulkMutationRefsFromBody(body) {
|
|
273
|
+
const record = requireRecord(body);
|
|
274
|
+
const sessions = record["sessions"];
|
|
275
|
+
if (!Array.isArray(sessions))
|
|
276
|
+
throw new Error("sessions field must be an array");
|
|
277
|
+
return sessions.map(parseBulkMutationRef);
|
|
278
|
+
}
|
|
279
|
+
function parseBulkMutationRef(value) {
|
|
280
|
+
const record = requireRecord(value);
|
|
281
|
+
const id = requireString(record, "id").trim();
|
|
282
|
+
if (id === "")
|
|
283
|
+
throw new Error("id field must not be empty");
|
|
284
|
+
const cwd = record["cwd"];
|
|
285
|
+
if (cwd === undefined || cwd === "")
|
|
286
|
+
return { id };
|
|
287
|
+
if (typeof cwd !== "string")
|
|
288
|
+
throw new Error("cwd field must be a string");
|
|
289
|
+
return { id, cwd: normalizeRequestCwd(cwd) };
|
|
290
|
+
}
|
|
291
|
+
function sessionLookupFromQuery(id, query) {
|
|
292
|
+
return sessionLookupFromCwd(id, query.cwd);
|
|
293
|
+
}
|
|
294
|
+
function sessionLookupFromBody(id, body) {
|
|
295
|
+
const cwd = body["cwd"];
|
|
296
|
+
if (cwd === undefined || cwd === "")
|
|
297
|
+
return id;
|
|
298
|
+
if (typeof cwd !== "string")
|
|
299
|
+
throw new Error("cwd field must be a string");
|
|
300
|
+
return { id, cwd: normalizeRequestCwd(cwd) };
|
|
301
|
+
}
|
|
302
|
+
function sessionLookupFromCwd(id, cwd) {
|
|
303
|
+
// Legacy id-only lookups (no cwd) remain supported; a supplied cwd is
|
|
304
|
+
// normalized here so everything past the route layer sees canonical paths.
|
|
305
|
+
return cwd === undefined || cwd === "" ? id : { id, cwd: normalizeRequestCwd(cwd) };
|
|
306
|
+
}
|
|
307
|
+
function optionalRecord(value) {
|
|
308
|
+
if (value === undefined || value === null)
|
|
309
|
+
return {};
|
|
310
|
+
return requireRecord(value);
|
|
311
|
+
}
|
|
312
|
+
function requireRecord(value) {
|
|
313
|
+
if (!isRecord(value))
|
|
314
|
+
throw new Error("request body must be an object");
|
|
315
|
+
return value;
|
|
316
|
+
}
|
|
317
|
+
function requireString(record, field) {
|
|
318
|
+
const value = record[field];
|
|
319
|
+
if (typeof value !== "string")
|
|
320
|
+
throw new Error(`${field} field must be a string`);
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
function requireThinkingLevel(value) {
|
|
324
|
+
if (typeof value !== "string" || value === "")
|
|
325
|
+
throw new Error("level field is invalid");
|
|
326
|
+
return value;
|
|
327
|
+
}
|
|
328
|
+
function optionalField(key, value) {
|
|
329
|
+
return value === undefined ? {} : { [key]: value };
|
|
330
|
+
}
|
|
331
|
+
function optionalNumber(value) {
|
|
332
|
+
if (value === undefined || value === "")
|
|
333
|
+
return undefined;
|
|
334
|
+
const parsed = Number(value);
|
|
335
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
336
|
+
}
|
|
337
|
+
function mutationErrorStatus(error) {
|
|
338
|
+
return isSessionNotFoundError(error) ? 404 : 400;
|
|
339
|
+
}
|
|
340
|
+
function isSessionNotFoundError(error) {
|
|
341
|
+
const message = errorMessage(error);
|
|
342
|
+
return message === "Session not found" || message === "Archived session not found";
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=sessionRoutes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRoutes.js","sourceRoot":"","sources":["../../../src/server/sessions/sessionRoutes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA0BrD,MAAM,UAAU,qBAAqB,CAAC,GAAoB,EAAE,QAA0B,EAAE,QAAyB,EAAE,MAAM,GAAG,EAAE;IAC5H,GAAG,CAAC,GAAG,CAAgC,GAAG,MAAM,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACpF,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE;YAAE,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iCAAiC,EAAE,CAAC,CAAC;QAC3I,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA0C,GAAG,MAAM,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/F,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzC,OAAO,MAAM,QAAQ,CAAC,KAAK,CAAC,mBAAmB,CAAC,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC/E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA8C,GAAG,MAAM,2BAA2B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACnH,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,cAAc,CAAC,8BAA8B,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA8C,GAAG,MAAM,mBAAmB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC3G,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,OAAO,CAAC,8BAA8B,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9F,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAmD,GAAG,MAAM,wBAAwB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACrH,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,WAAW,CAAC,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC5E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAmD,GAAG,MAAM,gCAAgC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC7H,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,kBAAkB,CAAC,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QACnF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,+BAA+B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvI,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,GAAG,aAAa,CAAC,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,aAAa,CAAC,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAClJ,OAAO,MAAM,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;QACxG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACrI,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAChG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACrI,IAAI,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC,eAAe,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACrH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAgH,GAAG,MAAM,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtL,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,MAAM,QAAQ,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;QACzJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA6G,GAAG,MAAM,kCAAkC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACzL,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;YACpC,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,UAAU;gBAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC7I,OAAO,MAAM,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,SAAS,IAAI,SAAS,CAAC,CAAC;QAClH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,sCAAsC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9I,IAAI,CAAC;YACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC7H,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA0F,GAAG,MAAM,qCAAqC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACzK,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,4EAA4E;YAC5E,6DAA6D;YAC7D,OAAO,MAAM,QAAQ,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACrI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,2CAA2C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC9J,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,MAAM,QAAQ,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAClG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,+BAA+B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvI,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QAClG,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChJ,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;YAC3I,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA8E,GAAG,MAAM,kCAAkC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1J,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACzG,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,CAAC;YACvI,OAAO,EAAE,WAAW,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyF,GAAG,MAAM,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/J,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,MAAM,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YACzG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyF,GAAG,MAAM,mCAAmC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtK,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,MAAM,QAAQ,CAAC,UAAU,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;QACvH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAA+G,GAAG,MAAM,uCAAuC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChM,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC1C,OAAO,MAAM,QAAQ,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAChK,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/I,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,2BAA2B,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACxI,IAAI,CAAC;YACH,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,8BAA8B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjJ,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,mCAAmC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACtJ,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,WAAW,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,8BAA8B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjJ,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,OAAO,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACtG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,MAAM,CAA+D,GAAG,MAAM,sBAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACjI,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YAC/F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAChJ,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACrG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,IAAI,CAAyE,GAAG,MAAM,oCAAoC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvJ,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,YAAY,CAAC,qBAAqB,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC3G,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAA+D,GAAG,MAAM,6BAA6B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QACrJ,2EAA2E;QAC3E,kEAAkE;QAClE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;QACnE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;QAC1D,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,wBAAwB,CAAC,IAA4C;IAC5E,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACjF,OAAO,QAAQ,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IAC9C,IAAI,EAAE,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC7D,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IACnD,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC3E,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,sBAAsB,CAAC,EAAU,EAAE,KAAmB;IAC7D,OAAO,oBAAoB,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,qBAAqB,CAAC,EAAU,EAAE,IAA6B;IACtE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC/C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC3E,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,SAAS,oBAAoB,CAAC,EAAU,EAAE,GAAuB;IAC/D,sEAAsE;IACtE,2EAA2E;IAC3E,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IACrD,OAAO,aAAa,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,aAAa,CAAC,KAAc;IACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACxE,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,MAA+B,EAAE,KAAa;IACnE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,yBAAyB,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,oBAAoB,CAAC,KAAc;IAC1C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IACzF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAI,GAAW,EAAE,KAAoB;IACzD,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACtD,CAAC;AAGD,SAAS,mBAAmB,CAAC,KAAc;IACzC,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AACnD,CAAC;AAED,SAAS,sBAAsB,CAAC,KAAc;IAC5C,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,OAAO,KAAK,mBAAmB,IAAI,OAAO,KAAK,4BAA4B,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionRuntimeStore.js","sourceRoot":"","sources":["../../../src/server/sessions/sessionRuntimeStore.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { isRecord } from "../utils.js";
|
|
2
|
+
import { Type } from "@oh-my-pi/pi-coding-agent/extensibility/typebox";
|
|
3
|
+
const SpawnSessionParams = Type.Object({
|
|
4
|
+
prompt: Type.String({
|
|
5
|
+
description: "The first instruction to send to the newly created session. The new session runs independently; you do not receive its output.",
|
|
6
|
+
}),
|
|
7
|
+
cwd: Type.Optional(Type.String({
|
|
8
|
+
description: "Working directory for the new session. Must be a workspace (worktree, or root) of the same project as this session. Defaults to this session's working directory.",
|
|
9
|
+
})),
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Custom tool that lets the LLM start a new, independent omp-web session and
|
|
13
|
+
* deliver an initial prompt to it. The spawned session is a normal omp-web session
|
|
14
|
+
* a human can open and interact with. The tool is constructed per-session, so it
|
|
15
|
+
* carries the spawning session's cwd for project-scope validation.
|
|
16
|
+
*/
|
|
17
|
+
export function createSpawnSessionToolDefinition(spawningCwd, deps) {
|
|
18
|
+
const def = {
|
|
19
|
+
name: "spawn_session",
|
|
20
|
+
label: "Spawn session",
|
|
21
|
+
description: "Start a new, independent omp-web session and send it an initial prompt. Use this to dispatch a fresh agent to continue work or follow a plan. The new session runs on its own and a human can interact with it; you do not receive its output.",
|
|
22
|
+
parameters: SpawnSessionParams,
|
|
23
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
24
|
+
const p = isRecord(params) ? params : {};
|
|
25
|
+
const prompt = typeof p["prompt"] === "string" ? p["prompt"] : "";
|
|
26
|
+
const cwd = typeof p["cwd"] === "string" ? p["cwd"] : undefined;
|
|
27
|
+
const result = await deps.spawn({
|
|
28
|
+
spawningCwd,
|
|
29
|
+
prompt,
|
|
30
|
+
cwd,
|
|
31
|
+
...(ctx.model === undefined ? {} : { model: ctx.model }),
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: `Started session ${result.sessionId} in ${result.cwd}.` }],
|
|
35
|
+
details: result,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
return def;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=spawnSessionTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawnSessionTool.js","sourceRoot":"","sources":["../../../src/server/sessions/spawnSessionTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,iDAAiD,CAAC;AAyBvE,MAAM,kBAAkB,GAAG,IAAI,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,gIAAgI;KAC7I,CAAC;IACF,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC;QAC9B,WAAW,EAAE,mKAAmK;KAChL,CAAC,CAAC;CACH,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC,CAAC,WAAmB,EAAE,IAA0B;IAC/F,MAAM,GAAG,GAAmB;QAC3B,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,eAAe;QACtB,WAAW,EAAE,gPAAgP;QAC7P,UAAU,EAAE,kBAAkB;QAC9B,KAAK,CAAC,OAAO,CAAC,WAAmB,EAAE,MAAe,EAAE,OAAgC,EAAE,SAAuE,EAAE,GAAqB;YACnL,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClE,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;gBAC/B,WAAW;gBACX,MAAM;gBACN,GAAG;gBACH,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;aACxD,CAAC,CAAC;YACH,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,MAAM,CAAC,SAAS,OAAO,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC;gBAC1F,OAAO,EAAE,MAAM;aACf,CAAC;QACH,CAAC;KACD,CAAC;IACF,OAAO,GAAG,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { isRecord } from "../utils.js";
|
|
2
|
+
import { Type } from "@oh-my-pi/pi-coding-agent/extensibility/typebox";
|
|
3
|
+
const SpawnSubsessionParams = Type.Object({
|
|
4
|
+
prompt: Type.String({
|
|
5
|
+
description: "The first instruction to send to the new tracked subsession.",
|
|
6
|
+
}),
|
|
7
|
+
cwd: Type.Optional(Type.String({
|
|
8
|
+
description: "Working directory for the subsession. Must be a workspace (worktree, or root) of the same project as this session. Defaults to this session's working directory.",
|
|
9
|
+
})),
|
|
10
|
+
});
|
|
11
|
+
const ListSubsessionsParams = Type.Object({});
|
|
12
|
+
const CheckSubsessionParams = Type.Object({
|
|
13
|
+
sessionId: Type.String({
|
|
14
|
+
description: "Id of a subsession you spawned (as returned by spawn_subsession or list_subsessions).",
|
|
15
|
+
}),
|
|
16
|
+
});
|
|
17
|
+
const ReadSubsessionParams = Type.Object({
|
|
18
|
+
sessionId: Type.String({
|
|
19
|
+
description: "Id of a subsession you spawned (as returned by spawn_subsession or list_subsessions).",
|
|
20
|
+
}),
|
|
21
|
+
roles: Type.Optional(Type.Array(Type.Union([Type.Literal("assistant"), Type.Literal("user"), Type.Literal("tool"), Type.Literal("system"), Type.Literal("custom")]), { description: "Message roles to include. Omit for all roles." })),
|
|
22
|
+
include: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("thinking"), Type.Literal("tool_call"), Type.Literal("tool_result"), Type.Literal("image")]), { description: "Content kinds to keep within messages. Omit for all kinds." })),
|
|
23
|
+
search: Type.Optional(Type.String({
|
|
24
|
+
description: "Case-insensitive substring; keep only messages whose text or tool name matches. Always searches full message content, even when maxChars is set.",
|
|
25
|
+
})),
|
|
26
|
+
maxChars: Type.Optional(Type.Integer({
|
|
27
|
+
minimum: 0,
|
|
28
|
+
description: "Truncate each text/thinking/tool-result value to this many characters; clipped parts are marked '[+N chars truncated]'. Omit for full, untruncated text (there is no default, so truncation only happens when you ask for it).",
|
|
29
|
+
})),
|
|
30
|
+
includeToolArgs: Type.Optional(Type.Boolean({
|
|
31
|
+
description: "Include raw tool-call arguments (can be large). A compact one-line summary of each call is always shown regardless.",
|
|
32
|
+
})),
|
|
33
|
+
before: Type.Optional(Type.Integer({
|
|
34
|
+
minimum: 0,
|
|
35
|
+
description: "Return only messages before this transcript index; page backward by passing the previous response's 'start'.",
|
|
36
|
+
})),
|
|
37
|
+
limit: Type.Optional(Type.Integer({
|
|
38
|
+
minimum: 1,
|
|
39
|
+
description: "Maximum number of most-recent matching messages to return within the window (returned in chronological order). Defaults to 50.",
|
|
40
|
+
})),
|
|
41
|
+
});
|
|
42
|
+
function statusLine(summary) {
|
|
43
|
+
return `- ${summary.sessionId} [${summary.status}] in ${summary.cwd}`;
|
|
44
|
+
}
|
|
45
|
+
function renderEntry(entry) {
|
|
46
|
+
const header = `#${String(entry.index)} ${entry.role}`;
|
|
47
|
+
const body = entry.parts.map(renderPart).filter((line) => line !== "").join("\n");
|
|
48
|
+
return body === "" ? header : `${header}\n${body}`;
|
|
49
|
+
}
|
|
50
|
+
function clipNotice(part) {
|
|
51
|
+
if ((part.kind === "text" || part.kind === "thinking" || part.kind === "tool_result") && part.truncated !== undefined) {
|
|
52
|
+
return ` [+${String(part.truncated.full - part.truncated.shown)} chars truncated; re-read with a larger maxChars]`;
|
|
53
|
+
}
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
function renderPart(part) {
|
|
57
|
+
if (part.kind === "text")
|
|
58
|
+
return `${part.text}${clipNotice(part)}`;
|
|
59
|
+
if (part.kind === "thinking")
|
|
60
|
+
return `[thinking] ${part.text}${clipNotice(part)}`;
|
|
61
|
+
if (part.kind === "tool_call") {
|
|
62
|
+
// Raw args are only present when the caller asked (includeToolArgs); when
|
|
63
|
+
// present, surface them in the model-facing text, not just `details`.
|
|
64
|
+
const args = "args" in part && part.args !== undefined ? `\n args: ${JSON.stringify(part.args)}` : "";
|
|
65
|
+
return `[tool ${part.toolName}] ${part.summary}${args}`;
|
|
66
|
+
}
|
|
67
|
+
if (part.kind === "tool_result")
|
|
68
|
+
return `[result${part.isError ? " error" : ""}${part.toolName === undefined ? "" : ` ${part.toolName}`}] ${part.text}${clipNotice(part)}`;
|
|
69
|
+
return "[image]";
|
|
70
|
+
}
|
|
71
|
+
function renderTranscript(result) {
|
|
72
|
+
const last = result.entries[result.entries.length - 1];
|
|
73
|
+
// Distinguish "nothing matched at all" (widen filters) from "matches exist but
|
|
74
|
+
// this page/window is empty" (page differently) so the agent isn't misled.
|
|
75
|
+
const range = last === undefined
|
|
76
|
+
? (result.matched === 0
|
|
77
|
+
? "no messages matched your filters"
|
|
78
|
+
: `no messages in this window (${String(result.matched)} matched outside it)`)
|
|
79
|
+
: `messages ${String(result.start)}–${String(last.index)} of ${String(result.total)} (${String(result.matched)} matched)`;
|
|
80
|
+
const more = result.hasMore ? `\n\nMore matching messages exist earlier; page back with before: ${String(result.start)}.` : "";
|
|
81
|
+
// Empty entries with matches means the `before` cursor excluded every match
|
|
82
|
+
// (they all sit at index >= before): the agent paged too far back and should
|
|
83
|
+
// raise `before` or omit it, not page back further.
|
|
84
|
+
const body = result.entries.length > 0
|
|
85
|
+
? result.entries.map(renderEntry).join("\n\n")
|
|
86
|
+
: (result.matched === 0
|
|
87
|
+
? "(nothing matched; try widening roles/include, dropping search, or raising limit)"
|
|
88
|
+
: `(no messages before index ${String(result.start)}; all ${String(result.matched)} matches are later — raise 'before' or omit it)`);
|
|
89
|
+
return `Subsession ${result.sessionId} [${result.status}] — ${range}:\n\n${body}${more}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Tools that let an agent spawn *tracked* child sessions and inspect them.
|
|
93
|
+
*
|
|
94
|
+
* Unlike `spawn_session` (fire-and-forget peers), a subsession records its
|
|
95
|
+
* parent in its session header, the parent is notified when it stops working,
|
|
96
|
+
* and the parent may read its transcript/result. The tools are constructed
|
|
97
|
+
* per-session, carrying the spawning cwd for project-scope validation; the
|
|
98
|
+
* parent's identity is taken from the live extension context at call time.
|
|
99
|
+
*/
|
|
100
|
+
export function createSubsessionToolDefinitions(spawningCwd, deps) {
|
|
101
|
+
const spawnTool = {
|
|
102
|
+
name: "spawn_subsession",
|
|
103
|
+
label: "Spawn subsession",
|
|
104
|
+
description: "Start a tracked child session and send it an initial prompt. The subsession runs independently and a human can interact with it, but unlike spawn_session it is linked to you: you are notified when it stops working (finished, idle, or errored), and you can inspect it with list_subsessions, check_subsession (a quick glance at its latest output), and read_subsession (read through its transcript). Use this to delegate work you intend to follow up on.",
|
|
105
|
+
parameters: SpawnSubsessionParams,
|
|
106
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
107
|
+
const p = isRecord(params) ? params : {};
|
|
108
|
+
const prompt = typeof p["prompt"] === "string" ? p["prompt"] : "";
|
|
109
|
+
const cwd = typeof p["cwd"] === "string" ? p["cwd"] : undefined;
|
|
110
|
+
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
111
|
+
const parentSessionFile = ctx.sessionManager.getSessionFile() ?? undefined;
|
|
112
|
+
const result = await deps.spawn({
|
|
113
|
+
spawningCwd,
|
|
114
|
+
parentSessionId,
|
|
115
|
+
parentSessionFile,
|
|
116
|
+
prompt,
|
|
117
|
+
cwd,
|
|
118
|
+
...(ctx.model === undefined ? {} : { model: ctx.model }),
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
content: [{ type: "text", text: `Started subsession ${result.sessionId} in ${result.cwd}. You will be notified when it stops working.` }],
|
|
122
|
+
details: result,
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
const listTool = {
|
|
127
|
+
name: "list_subsessions",
|
|
128
|
+
label: "List subsessions",
|
|
129
|
+
description: "List the tracked subsessions you spawned, with their current status (working, idle, error, or unknown).",
|
|
130
|
+
parameters: ListSubsessionsParams,
|
|
131
|
+
async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
|
|
132
|
+
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
133
|
+
const parentSessionFile = ctx.sessionManager.getSessionFile() ?? undefined;
|
|
134
|
+
const subsessions = await deps.list(parentSessionId, parentSessionFile);
|
|
135
|
+
const text = subsessions.length === 0
|
|
136
|
+
? "You have not spawned any subsessions."
|
|
137
|
+
: `Your subsessions:\n${subsessions.map(statusLine).join("\n")}`;
|
|
138
|
+
return { content: [{ type: "text", text }], details: { subsessions } };
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
const checkTool = {
|
|
142
|
+
name: "check_subsession",
|
|
143
|
+
label: "Check subsession",
|
|
144
|
+
description: "Quick glance at a subsession you spawned: its current status and most recent assistant output. Use this to react to what a subsession produced. When the summary is not enough, use read_subsession to look through its full transcript.",
|
|
145
|
+
parameters: CheckSubsessionParams,
|
|
146
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
147
|
+
const p = isRecord(params) ? params : {};
|
|
148
|
+
const sessionId = typeof p["sessionId"] === "string" ? p["sessionId"] : "";
|
|
149
|
+
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
150
|
+
const parentSessionFile = ctx.sessionManager.getSessionFile() ?? undefined;
|
|
151
|
+
const result = await deps.check(parentSessionId, sessionId, parentSessionFile);
|
|
152
|
+
const body = result.finalText === "" ? "(no output yet)" : result.finalText;
|
|
153
|
+
return {
|
|
154
|
+
content: [{ type: "text", text: `Subsession ${result.sessionId} [${result.status}]:\n\n${body}` }],
|
|
155
|
+
details: result,
|
|
156
|
+
};
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const readTool = {
|
|
160
|
+
name: "read_subsession",
|
|
161
|
+
label: "Read subsession",
|
|
162
|
+
description: "Read through the transcript of a subsession you spawned.",
|
|
163
|
+
parameters: ReadSubsessionParams,
|
|
164
|
+
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
165
|
+
const p = isRecord(params) ? params : {};
|
|
166
|
+
const sessionId = typeof p["sessionId"] === "string" ? p["sessionId"] : "";
|
|
167
|
+
const query = parseReadQuery(p);
|
|
168
|
+
const parentSessionId = ctx.sessionManager.getSessionId();
|
|
169
|
+
const parentSessionFile = ctx.sessionManager.getSessionFile() ?? undefined;
|
|
170
|
+
const result = await deps.read(parentSessionId, sessionId, query, parentSessionFile);
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: "text", text: renderTranscript(result) }],
|
|
173
|
+
details: result,
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
return [spawnTool, listTool, checkTool, readTool];
|
|
178
|
+
}
|
|
179
|
+
function parseReadQuery(p) {
|
|
180
|
+
const query = {};
|
|
181
|
+
if (Array.isArray(p["roles"]))
|
|
182
|
+
query.roles = p["roles"].filter(isRole);
|
|
183
|
+
if (Array.isArray(p["include"]))
|
|
184
|
+
query.include = p["include"].filter(isContentKind);
|
|
185
|
+
if (typeof p["search"] === "string")
|
|
186
|
+
query.search = p["search"];
|
|
187
|
+
if (typeof p["maxChars"] === "number")
|
|
188
|
+
query.maxChars = p["maxChars"];
|
|
189
|
+
if (typeof p["includeToolArgs"] === "boolean")
|
|
190
|
+
query.includeToolArgs = p["includeToolArgs"];
|
|
191
|
+
if (typeof p["before"] === "number")
|
|
192
|
+
query.before = p["before"];
|
|
193
|
+
if (typeof p["limit"] === "number")
|
|
194
|
+
query.limit = p["limit"];
|
|
195
|
+
return query;
|
|
196
|
+
}
|
|
197
|
+
function isRole(value) {
|
|
198
|
+
return typeof value === "string" && (value === "assistant" || value === "user" || value === "tool" || value === "system" || value === "custom");
|
|
199
|
+
}
|
|
200
|
+
function isContentKind(value) {
|
|
201
|
+
return typeof value === "string" && (value === "text" || value === "thinking" || value === "tool_call" || value === "tool_result" || value === "image");
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=spawnSubsessionTool.js.map
|