@burdenoff/vibe-agent 2.1.0 → 2.2.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.
Files changed (54) hide show
  1. package/dist/app-6mmbmske.js +1166 -0
  2. package/dist/app-6mmbmske.js.map +19 -0
  3. package/dist/cli.js +152 -2036
  4. package/dist/cli.js.map +6 -28
  5. package/dist/index-05qfwz8r.js +122 -0
  6. package/dist/index-05qfwz8r.js.map +10 -0
  7. package/dist/index-30p492yv.js +294 -0
  8. package/dist/index-30p492yv.js.map +13 -0
  9. package/dist/index-3v78e2cn.js +373 -0
  10. package/dist/index-3v78e2cn.js.map +11 -0
  11. package/dist/index-41m1exz7.js +269 -0
  12. package/dist/index-41m1exz7.js.map +13 -0
  13. package/dist/index-88ym10cs.js +194 -0
  14. package/dist/index-88ym10cs.js.map +10 -0
  15. package/dist/index-9tgyd3ep.js +513 -0
  16. package/dist/index-9tgyd3ep.js.map +19 -0
  17. package/dist/index-a9g7hbj9.js +229 -0
  18. package/dist/index-a9g7hbj9.js.map +13 -0
  19. package/dist/index-atjhkm74.js +149 -0
  20. package/dist/index-atjhkm74.js.map +10 -0
  21. package/dist/index-c7zy3n33.js +167 -0
  22. package/dist/index-c7zy3n33.js.map +13 -0
  23. package/dist/index-gmz54dkc.js +2 -201
  24. package/dist/index-hefqxwht.js +270 -0
  25. package/dist/index-hefqxwht.js.map +13 -0
  26. package/dist/index-k9hb0b93.js +280 -0
  27. package/dist/index-k9hb0b93.js.map +13 -0
  28. package/dist/index-npmvh1x9.js +385 -0
  29. package/dist/index-npmvh1x9.js.map +13 -0
  30. package/dist/index-q4ytrfx7.js +286 -0
  31. package/dist/index-q4ytrfx7.js.map +13 -0
  32. package/dist/index-qthbtg9n.js +302 -0
  33. package/dist/index-qthbtg9n.js.map +13 -0
  34. package/dist/index-rdm6e3rr.js +587 -0
  35. package/dist/index-rdm6e3rr.js.map +13 -0
  36. package/dist/index-wdtxbebz.js +339 -0
  37. package/dist/index-wdtxbebz.js.map +13 -0
  38. package/dist/{app-31chs2a1.js → index-wr0mkm57.js} +8 -3204
  39. package/dist/{app-31chs2a1.js.map → index-wr0mkm57.js.map} +4 -25
  40. package/dist/index-xmeskdnb.js +292 -0
  41. package/dist/index-xmeskdnb.js.map +11 -0
  42. package/dist/index-xn4tarcd.js +287 -0
  43. package/dist/index-xn4tarcd.js.map +13 -0
  44. package/dist/index.js +9 -6
  45. package/dist/index.js.map +2 -2
  46. package/dist/{package-0158fp3w.js → package-ywexp6sg.js} +4 -4
  47. package/dist/{package-0158fp3w.js.map → package-ywexp6sg.js.map} +1 -1
  48. package/dist/plugin-system-v7a7xnhk.js +475 -0
  49. package/dist/plugin-system-v7a7xnhk.js.map +10 -0
  50. package/package.json +2 -2
  51. package/dist/index-t06ktmx9.js +0 -216
  52. package/dist/index-t06ktmx9.js.map +0 -11
  53. package/dist/plugin-system-bg1pzjj9.js +0 -453
  54. package/dist/plugin-system-bg1pzjj9.js.map +0 -11
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/plugins/notification/routes.ts", "../src/cli/commands/notify.cmd.ts", "../src/plugins/notification/commands.ts", "../src/plugins/notification/index.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Notification Plugin — Routes\n *\n * Notification management — CRUD, read/unread status, webhook endpoint.\n *\n * Endpoints (mounted by plugin system at /api/notifications):\n * GET / — List notifications (with filters)\n * GET /unread — Get unread notifications\n * GET /global — Get global notifications\n * GET /project/:projectId — Get notifications by project\n * PUT /read-all — Mark all as read\n * DELETE /clear/old — Clear old notifications\n * GET /:id — Get notification by ID\n * POST / — Create notification\n * PUT /:id/read — Mark as read\n * PUT /:id/unread — Mark as unread\n * DELETE /:id — Delete notification\n * POST /webhook/:sessionId — Webhook for external notifications\n */\n\nimport { Elysia, t } from \"elysia\";\nimport crypto from \"node:crypto\";\n\nimport type { AgentDatabase } from \"../../db/database.js\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\n\n// ── Routes ──────────────────────────────────────────────────────────────\n\nexport function createRoutes(deps: PluginRouteDeps) {\n const { db } = deps;\n\n return (\n new Elysia()\n // List notifications (with optional filters)\n .get(\"/\", ({ query }) => {\n const q = query as Record<string, string>;\n\n if (q.status === \"unread\") {\n return { notifications: db.getUnreadNotifications() };\n }\n if (q.projectId !== undefined) {\n return { notifications: db.getNotificationsByProject(q.projectId) };\n }\n return { notifications: db.getAllNotifications() };\n })\n\n // Get unread notifications\n .get(\"/unread\", () => {\n const notifications = db.getUnreadNotifications();\n return { notifications, count: notifications.length };\n })\n\n // Get global notifications (not tied to a project)\n .get(\"/global\", () => {\n const notifications = db.getGlobalNotifications();\n return { notifications, count: notifications.length };\n })\n\n // Get notifications by project\n .get(\"/project/:projectId\", ({ params }) => {\n const notifications = db.getNotificationsByProject(params.projectId);\n return { notifications };\n })\n\n // Mark all as read — defined before /:id to avoid route conflict\n .put(\"/read-all\", ({ set }) => {\n try {\n const count = db.markAllNotificationsRead();\n return { success: true, markedCount: count };\n } catch (err) {\n set.status = 500;\n return {\n error: \"Failed to mark all notifications as read\",\n details: String(err),\n };\n }\n })\n\n // Clear old notifications — defined before /:id to avoid route conflict\n .delete(\"/clear/old\", ({ query }) => {\n const q = query as Record<string, string>;\n const days = q.days ? parseInt(q.days, 10) : 30;\n const count = db.clearOldNotifications(days);\n return { success: true, deletedCount: count };\n })\n\n // Get notification by ID\n .get(\"/:id\", ({ params, set }) => {\n const notification = db.getNotification(params.id);\n if (!notification) {\n set.status = 404;\n return { error: \"Notification not found\" };\n }\n return { notification };\n })\n\n // Create notification\n .post(\n \"/\",\n ({ body, set }) => {\n try {\n const notification = db.createNotification({\n id: crypto.randomUUID(),\n sessionName: body.sessionName,\n projectId: body.projectId,\n type: body.type || \"info\",\n title: body.title,\n message: body.message,\n status: \"unread\",\n });\n return { notification };\n } catch (err) {\n set.status = 500;\n return {\n error: \"Failed to create notification\",\n details: String(err),\n };\n }\n },\n {\n body: t.Object({\n sessionName: t.Optional(t.String()),\n projectId: t.Optional(t.String()),\n type: t.Optional(\n t.Union([\n t.Literal(\"info\"),\n t.Literal(\"success\"),\n t.Literal(\"warning\"),\n t.Literal(\"error\"),\n ]),\n ),\n title: t.String(),\n message: t.String(),\n }),\n },\n )\n\n // Mark as read\n .put(\"/:id/read\", ({ params, set }) => {\n const notification = db.getNotification(params.id);\n if (!notification) {\n set.status = 404;\n return { error: \"Notification not found\" };\n }\n db.updateNotificationStatus(params.id, \"read\");\n return { success: true };\n })\n\n // Mark as unread\n .put(\"/:id/unread\", ({ params, set }) => {\n const notification = db.getNotification(params.id);\n if (!notification) {\n set.status = 404;\n return { error: \"Notification not found\" };\n }\n db.updateNotificationStatus(params.id, \"unread\");\n return { success: true };\n })\n\n // Delete notification\n .delete(\"/:id\", ({ params, set }) => {\n const notification = db.getNotification(params.id);\n if (!notification) {\n set.status = 404;\n return { error: \"Notification not found\" };\n }\n\n try {\n db.deleteNotification(params.id);\n return { success: true };\n } catch (err) {\n set.status = 500;\n return {\n error: \"Failed to delete notification\",\n details: String(err),\n };\n }\n })\n\n // Webhook endpoint for external notifications\n .post(\n \"/webhook/:sessionId\",\n ({ params, body, set }) => {\n try {\n // Map type variants to valid DB types\n const typeMap: Record<\n string,\n \"info\" | \"success\" | \"warning\" | \"error\"\n > = {\n task_completed: \"success\",\n info: \"info\",\n success: \"success\",\n warning: \"warning\",\n error: \"error\",\n };\n const mappedType = typeMap[body.type || \"info\"] || \"info\";\n\n const message = body.metadata\n ? `${body.message}\\n\\nMetadata: ${JSON.stringify(body.metadata, null, 2)}`\n : body.message;\n\n const notification = db.createNotification({\n id: crypto.randomUUID(),\n sessionName: body.projectName,\n projectId: params.sessionId,\n type: mappedType,\n title: body.title,\n message,\n status: \"unread\",\n });\n\n return {\n notification,\n webhook: true,\n originalType: body.type || \"info\",\n mappedType,\n };\n } catch (err) {\n set.status = 500;\n return {\n error: \"Failed to create webhook notification\",\n details: String(err),\n };\n }\n },\n {\n body: t.Object({\n type: t.Optional(t.String()),\n title: t.String(),\n message: t.String(),\n metadata: t.Optional(t.Record(t.String(), t.Unknown())),\n projectName: t.Optional(t.String()),\n }),\n },\n )\n );\n}\n",
6
+ "import { Command } from \"commander\";\nimport {\n getAgentUrl,\n apiGet,\n apiPost,\n apiPut,\n apiDelete,\n fail,\n success,\n info,\n header,\n kv,\n blank,\n formatNotificationType,\n timeAgo,\n shortId,\n colors,\n} from \"../utils/index.js\";\n\nconst DEFAULT_AGENT_URL = \"http://localhost:3005\";\n\nexport function register(program: Command): void {\n const cmd = program.command(\"notify\").description(\"Manage notifications\");\n\n // notify list\n cmd\n .command(\"list\")\n .description(\"List notifications\")\n .option(\"--unread\", \"Show only unread notifications\")\n .option(\"--project <id>\", \"Filter by project ID\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const params = new URLSearchParams();\n if (options.unread) params.set(\"unread\", \"true\");\n if (options.project) params.set(\"project\", options.project);\n const query = params.toString();\n const endpoint = query\n ? `/api/notifications?${query}`\n : \"/api/notifications\";\n const data = await apiGet<{ notifications: any[] }>(url, endpoint);\n const notifications = data.notifications || [];\n if (!notifications || notifications.length === 0) {\n info(\"No notifications found.\");\n return;\n }\n header(\"Notifications\");\n blank();\n for (const n of notifications) {\n const icon = formatNotificationType(n.type);\n const time = n.createdAt ? colors.dim(timeAgo(n.createdAt)) : \"\";\n const title = colors.bold(n.title || \"Untitled\");\n const id = colors.dim(`[${shortId(n.id)}]`);\n console.log(` ${icon} ${title} ${id} ${time}`);\n if (n.message) {\n console.log(` ${n.message}`);\n }\n blank();\n }\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // notify create\n cmd\n .command(\"create\")\n .description(\"Create a notification\")\n .requiredOption(\"--title <title>\", \"Notification title\")\n .requiredOption(\"--message <msg>\", \"Notification message\")\n .option(\"--type <type>\", \"Notification type\", \"info\")\n .option(\"--project <id>\", \"Project ID\")\n .option(\"--session <name>\", \"Session name\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const body: Record<string, any> = {\n title: options.title,\n message: options.message,\n type: options.type,\n };\n if (options.project) body.project = options.project;\n if (options.session) body.session = options.session;\n const result = await apiPost<any>(url, \"/api/notifications\", body);\n success(`Notification created: ${shortId(result?.id)}`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // notify delete\n cmd\n .command(\"delete\")\n .description(\"Delete a notification\")\n .requiredOption(\"-i, --id <id>\", \"Notification ID\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiDelete<any>(url, `/api/notifications/${options.id}`);\n success(`Notification ${shortId(options.id)} deleted.`);\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // notify read-all\n cmd\n .command(\"read-all\")\n .description(\"Mark all notifications as read\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiPut<any>(url, \"/api/notifications/read-all\", {});\n success(\"All notifications marked as read.\");\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // notify clear-old\n cmd\n .command(\"clear-old\")\n .description(\"Clear old notifications\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n await apiDelete<any>(url, \"/api/notifications/clear/old\");\n success(\"Old notifications cleared.\");\n } catch (err: any) {\n fail(err.message);\n }\n });\n\n // notify webhook\n cmd\n .command(\"webhook\")\n .description(\"Send a webhook notification to a session\")\n .requiredOption(\"--session <sessionId>\", \"Target session ID\")\n .option(\"--title <title>\", \"Notification title\")\n .option(\"--message <msg>\", \"Notification message\")\n .option(\"--type <type>\", \"Notification type\", \"info\")\n .option(\"--agent-url <url>\", \"Agent URL\", DEFAULT_AGENT_URL)\n .action(async (options) => {\n try {\n const url = getAgentUrl(options);\n const body: Record<string, any> = {};\n if (options.title) body.title = options.title;\n if (options.message) body.message = options.message;\n if (options.type) body.type = options.type;\n await apiPost<any>(\n url,\n `/api/notifications/webhook/${options.session}`,\n body,\n );\n success(\n `Webhook notification sent to session ${shortId(options.session)}.`,\n );\n } catch (err: any) {\n fail(err.message);\n }\n });\n}\n",
7
+ "import type { Command } from \"commander\";\nimport type { HostServices } from \"../../core/plugin-system.js\";\nimport { register as registerNotify } from \"../../cli/commands/notify.cmd.js\";\n\nexport function registerCommands(\n program: Command,\n _hostServices: HostServices,\n): void {\n registerNotify(program);\n}\n",
8
+ "import type { VibePlugin } from \"../../core/plugin-system.js\";\nimport type { PluginRouteDeps } from \"../../core/types.js\";\nimport { createRoutes } from \"./routes.js\";\nimport { registerCommands } from \"./commands.js\";\n\nexport const vibePlugin: VibePlugin = {\n name: \"notification\",\n version: \"2.2.0\",\n description: \"Notification management — CRUD, read/unread status, webhooks\",\n tags: [\"backend\", \"cli\"],\n cliCommand: \"notify\",\n apiPrefix: \"/api/notifications\",\n createRoutes: (deps: PluginRouteDeps) => createRoutes(deps),\n onCliSetup: async (program, hostServices) => {\n registerCommands(program, hostServices);\n },\n};\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "933C583CBD4F9A8B64756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,587 @@
1
+ // @bun
2
+ import {
3
+ Elysia,
4
+ t
5
+ } from "./index-wr0mkm57.js";
6
+ import {
7
+ apiDelete,
8
+ apiGet,
9
+ apiPost,
10
+ apiPut,
11
+ blank,
12
+ fail,
13
+ formatStatus,
14
+ formatTable,
15
+ getAgentUrl,
16
+ header,
17
+ info,
18
+ kv,
19
+ shortId,
20
+ success
21
+ } from "./index-xmeskdnb.js";
22
+ import"./index-g8dczzvv.js";
23
+
24
+ // src/plugins/session/routes.ts
25
+ function getSessionProvider(registry) {
26
+ const provider = registry.getProvider("session");
27
+ if (!provider) {
28
+ throw new Error("No session provider registered");
29
+ }
30
+ return provider;
31
+ }
32
+ function createRoutes(deps) {
33
+ const { serviceRegistry } = deps;
34
+ return new Elysia().get("/", async ({ set }) => {
35
+ try {
36
+ const provider = getSessionProvider(serviceRegistry);
37
+ const sessions = await provider.list();
38
+ return { sessions };
39
+ } catch (err) {
40
+ set.status = 500;
41
+ return { error: "Failed to list sessions", details: String(err) };
42
+ }
43
+ }).get("/system", async ({ set }) => {
44
+ try {
45
+ const provider = getSessionProvider(serviceRegistry);
46
+ const sessions = await provider.listSystem();
47
+ return { sessions };
48
+ } catch (err) {
49
+ set.status = 500;
50
+ return {
51
+ error: "Failed to get system sessions",
52
+ details: String(err)
53
+ };
54
+ }
55
+ }).get("/system/terminals", async ({ set }) => {
56
+ try {
57
+ const provider = getSessionProvider(serviceRegistry);
58
+ const processes = await provider.listSystemTerminals();
59
+ return { processes };
60
+ } catch (err) {
61
+ set.status = 500;
62
+ return {
63
+ error: "Failed to get system terminal processes",
64
+ details: String(err)
65
+ };
66
+ }
67
+ }).post("/system/kill", async ({ body, set }) => {
68
+ try {
69
+ const provider = getSessionProvider(serviceRegistry);
70
+ const results = [];
71
+ for (const sessionId of body.sessionIds) {
72
+ try {
73
+ await provider.killSystem(sessionId);
74
+ results.push({ target: sessionId, success: true });
75
+ } catch (err) {
76
+ results.push({
77
+ target: sessionId,
78
+ success: false,
79
+ error: String(err)
80
+ });
81
+ }
82
+ }
83
+ return { results };
84
+ } catch (err) {
85
+ set.status = 500;
86
+ return {
87
+ error: "Failed to kill system sessions",
88
+ details: String(err)
89
+ };
90
+ }
91
+ }, {
92
+ body: t.Object({
93
+ sessionIds: t.Array(t.String()),
94
+ force: t.Optional(t.Boolean())
95
+ })
96
+ }).post("/system/terminals/kill", async ({ body, set }) => {
97
+ try {
98
+ const provider = getSessionProvider(serviceRegistry);
99
+ const results = [];
100
+ for (const pid of body.pids) {
101
+ try {
102
+ await provider.killSystemTerminal(pid);
103
+ results.push({ target: String(pid), success: true });
104
+ } catch (err) {
105
+ results.push({
106
+ target: String(pid),
107
+ success: false,
108
+ error: String(err)
109
+ });
110
+ }
111
+ }
112
+ return { results };
113
+ } catch (err) {
114
+ set.status = 500;
115
+ return {
116
+ error: "Failed to kill system terminal processes",
117
+ details: String(err)
118
+ };
119
+ }
120
+ }, {
121
+ body: t.Object({
122
+ pids: t.Array(t.Number()),
123
+ force: t.Optional(t.Boolean())
124
+ })
125
+ }).post("/health-check", async ({ body, set }) => {
126
+ try {
127
+ const provider = getSessionProvider(serviceRegistry);
128
+ const results = [];
129
+ for (const sessionId of body.sessionIds) {
130
+ try {
131
+ const session = await provider.get(sessionId);
132
+ if (!session) {
133
+ results.push({ sessionId, status: "unknown" });
134
+ } else {
135
+ results.push({
136
+ sessionId,
137
+ status: session.status === "active" ? "running" : "dead"
138
+ });
139
+ }
140
+ } catch {
141
+ results.push({ sessionId, status: "unknown" });
142
+ }
143
+ }
144
+ return { results };
145
+ } catch (err) {
146
+ set.status = 500;
147
+ return {
148
+ error: "Failed to health check sessions",
149
+ details: String(err)
150
+ };
151
+ }
152
+ }, {
153
+ body: t.Object({
154
+ sessionIds: t.Array(t.String())
155
+ })
156
+ }).post("/create", async ({ body, set }) => {
157
+ try {
158
+ const provider = getSessionProvider(serviceRegistry);
159
+ if (body.sessionId) {
160
+ const existing = await provider.get(body.sessionId);
161
+ if (existing && existing.status === "active") {
162
+ return { session: existing, reused: true };
163
+ }
164
+ }
165
+ const session = await provider.create({
166
+ name: body.sessionName || `vibecontrols-${Date.now()}`,
167
+ command: body.command,
168
+ workingDirectory: body.startDirectory,
169
+ projectId: body.projectId
170
+ });
171
+ return { session, reused: false };
172
+ } catch (err) {
173
+ set.status = 500;
174
+ return { error: "Failed to create session", details: String(err) };
175
+ }
176
+ }, {
177
+ body: t.Object({
178
+ sessionId: t.Optional(t.String()),
179
+ projectId: t.Optional(t.String()),
180
+ sessionName: t.Optional(t.String()),
181
+ windowName: t.Optional(t.String()),
182
+ command: t.Optional(t.String()),
183
+ startDirectory: t.Optional(t.String())
184
+ })
185
+ }).get("/:id", async ({ params, set }) => {
186
+ try {
187
+ const provider = getSessionProvider(serviceRegistry);
188
+ const session = await provider.get(params.id);
189
+ if (!session) {
190
+ set.status = 404;
191
+ return { error: "Session not found" };
192
+ }
193
+ return { session };
194
+ } catch (err) {
195
+ set.status = 500;
196
+ return { error: "Failed to get session", details: String(err) };
197
+ }
198
+ }).delete("/:id", async ({ params, set }) => {
199
+ try {
200
+ const provider = getSessionProvider(serviceRegistry);
201
+ const session = await provider.get(params.id);
202
+ if (!session) {
203
+ set.status = 404;
204
+ return { error: "Session not found" };
205
+ }
206
+ await provider.kill(params.id);
207
+ return { success: true, sessionName: session.name };
208
+ } catch (err) {
209
+ set.status = 500;
210
+ return { error: "Failed to kill session", details: String(err) };
211
+ }
212
+ }).post("/:id/command", async ({ params, body, set }) => {
213
+ try {
214
+ const provider = getSessionProvider(serviceRegistry);
215
+ const session = await provider.get(params.id);
216
+ if (!session) {
217
+ set.status = 404;
218
+ return { error: "Session not found" };
219
+ }
220
+ await provider.sendCommand(params.id, body.command);
221
+ return { success: true };
222
+ } catch (err) {
223
+ set.status = 500;
224
+ return { error: "Failed to execute command", details: String(err) };
225
+ }
226
+ }, {
227
+ body: t.Object({
228
+ command: t.String()
229
+ })
230
+ }).post("/:id/keys", async ({ params, body, set }) => {
231
+ try {
232
+ const provider = getSessionProvider(serviceRegistry);
233
+ const session = await provider.get(params.id);
234
+ if (!session) {
235
+ set.status = 404;
236
+ return { error: "Session not found" };
237
+ }
238
+ await provider.sendKeys(params.id, body.keys);
239
+ return { success: true };
240
+ } catch (err) {
241
+ set.status = 500;
242
+ return { error: "Failed to send keys", details: String(err) };
243
+ }
244
+ }, {
245
+ body: t.Object({
246
+ keys: t.String()
247
+ })
248
+ }).post("/:id/interrupt", async ({ params, set }) => {
249
+ try {
250
+ const provider = getSessionProvider(serviceRegistry);
251
+ const session = await provider.get(params.id);
252
+ if (!session) {
253
+ set.status = 404;
254
+ return { error: "Session not found" };
255
+ }
256
+ await provider.interrupt(params.id);
257
+ return { success: true };
258
+ } catch (err) {
259
+ set.status = 500;
260
+ return { error: "Failed to send interrupt", details: String(err) };
261
+ }
262
+ }).get("/:id/capture", async ({ params, set }) => {
263
+ try {
264
+ const provider = getSessionProvider(serviceRegistry);
265
+ const session = await provider.get(params.id);
266
+ if (!session) {
267
+ set.status = 404;
268
+ return { error: "Session not found" };
269
+ }
270
+ const output = await provider.capture(params.id);
271
+ return { output };
272
+ } catch (err) {
273
+ set.status = 500;
274
+ return { error: "Failed to capture output", details: String(err) };
275
+ }
276
+ }).put("/:id/rename", async ({ params, body, set }) => {
277
+ try {
278
+ const provider = getSessionProvider(serviceRegistry);
279
+ const session = await provider.get(params.id);
280
+ if (!session) {
281
+ set.status = 404;
282
+ return { error: "Session not found" };
283
+ }
284
+ await provider.rename(params.id, body.newName);
285
+ return { success: true };
286
+ } catch (err) {
287
+ set.status = 500;
288
+ return { error: "Failed to rename session", details: String(err) };
289
+ }
290
+ }, {
291
+ body: t.Object({
292
+ newName: t.String()
293
+ })
294
+ }).post("/:id/toggle-mouse", async ({ params, set }) => {
295
+ try {
296
+ const provider = getSessionProvider(serviceRegistry);
297
+ const session = await provider.get(params.id);
298
+ if (!session) {
299
+ set.status = 404;
300
+ return { error: "Session not found" };
301
+ }
302
+ await provider.toggleMouse(params.id);
303
+ return { success: true };
304
+ } catch (err) {
305
+ set.status = 500;
306
+ return { error: "Failed to toggle mouse mode", details: String(err) };
307
+ }
308
+ }).get("/:id/termination-status", async ({ params, set }) => {
309
+ try {
310
+ const provider = getSessionProvider(serviceRegistry);
311
+ const session = await provider.get(params.id);
312
+ if (!session) {
313
+ set.status = 404;
314
+ return { error: "Session not found" };
315
+ }
316
+ const termStatus = await provider.getTerminationStatus(params.id);
317
+ return {
318
+ sessionId: params.id,
319
+ sessionName: session.name,
320
+ databaseStatus: session.status,
321
+ ...termStatus,
322
+ isFullyTerminated: termStatus.exited && session.status === "terminated"
323
+ };
324
+ } catch (err) {
325
+ set.status = 500;
326
+ return {
327
+ error: "Failed to verify termination",
328
+ details: String(err)
329
+ };
330
+ }
331
+ }).get("/:id/terminal", async ({ params, set }) => {
332
+ try {
333
+ const provider = getSessionProvider(serviceRegistry);
334
+ const session = await provider.get(params.id);
335
+ if (!session) {
336
+ set.status = 404;
337
+ return { error: "Session not found" };
338
+ }
339
+ const terminal = await provider.getTerminalInfo(params.id);
340
+ if (!terminal) {
341
+ set.status = 404;
342
+ return { error: "Terminal not running for this session" };
343
+ }
344
+ const tunnelProvider = serviceRegistry.getProvider("tunnel");
345
+ const tunnelUrl = tunnelProvider ? await tunnelProvider.getActiveTunnelUrl() : null;
346
+ const terminalProxyUrl = tunnelUrl ? `${tunnelUrl}/terminal/${params.id}/` : null;
347
+ return {
348
+ port: terminal.port,
349
+ url: `http://localhost:${terminal.port}`,
350
+ pid: terminal.pid,
351
+ terminalUrl: terminalProxyUrl
352
+ };
353
+ } catch (err) {
354
+ set.status = 500;
355
+ return { error: "Failed to get terminal info", details: String(err) };
356
+ }
357
+ }).post("/:id/terminal", async ({ params, set }) => {
358
+ try {
359
+ const provider = getSessionProvider(serviceRegistry);
360
+ const session = await provider.get(params.id);
361
+ if (!session) {
362
+ set.status = 404;
363
+ return { error: "Session not found" };
364
+ }
365
+ const existingTerminal = await provider.getTerminalInfo(params.id);
366
+ if (existingTerminal) {
367
+ const tunnelProvider2 = serviceRegistry.getProvider("tunnel");
368
+ const tunnelUrl2 = tunnelProvider2 ? await tunnelProvider2.getActiveTunnelUrl() : null;
369
+ const terminalProxyUrl2 = tunnelUrl2 ? `${tunnelUrl2}/terminal/${params.id}/` : null;
370
+ return {
371
+ port: existingTerminal.port,
372
+ pid: existingTerminal.pid,
373
+ url: `http://localhost:${existingTerminal.port}`,
374
+ terminalUrl: terminalProxyUrl2
375
+ };
376
+ }
377
+ const terminal = await provider.startTerminal(params.id);
378
+ const tunnelProvider = serviceRegistry.getProvider("tunnel");
379
+ const tunnelUrl = tunnelProvider ? await tunnelProvider.getActiveTunnelUrl() : null;
380
+ const terminalProxyUrl = tunnelUrl ? `${tunnelUrl}/terminal/${params.id}/` : null;
381
+ return {
382
+ port: terminal.port,
383
+ pid: terminal.pid,
384
+ url: `http://localhost:${terminal.port}`,
385
+ terminalUrl: terminalProxyUrl
386
+ };
387
+ } catch (err) {
388
+ set.status = 500;
389
+ return { error: "Failed to start terminal", details: String(err) };
390
+ }
391
+ }).post("/:id/terminal/stop", async ({ params, set }) => {
392
+ try {
393
+ const provider = getSessionProvider(serviceRegistry);
394
+ const session = await provider.get(params.id);
395
+ if (!session) {
396
+ set.status = 404;
397
+ return { error: "Session not found" };
398
+ }
399
+ await provider.stopTerminal(params.id);
400
+ return { success: true };
401
+ } catch (err) {
402
+ set.status = 500;
403
+ return { error: "Failed to stop terminal", details: String(err) };
404
+ }
405
+ });
406
+ }
407
+
408
+ // src/cli/commands/session.cmd.ts
409
+ var DEFAULT_AGENT_URL = "http://localhost:3005";
410
+ function register(program) {
411
+ const cmd = program.command("session").description("Manage terminal sessions");
412
+ cmd.command("list").description("List all sessions").option("--system", "Show system sessions instead of user sessions").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
413
+ try {
414
+ const url = getAgentUrl(options);
415
+ const endpoint = options.system ? "/api/sessions?system=true" : "/api/sessions";
416
+ const sessions = await apiGet(url, endpoint);
417
+ if (!sessions || sessions.length === 0) {
418
+ info("No sessions found.");
419
+ return;
420
+ }
421
+ header("Sessions");
422
+ formatTable(sessions.map((s) => ({
423
+ ID: shortId(s.id),
424
+ Name: s.name || "-",
425
+ Status: formatStatus(s.status),
426
+ Port: s.port ?? "-",
427
+ Project: s.project || s.projectId || "-"
428
+ })));
429
+ } catch (err) {
430
+ fail(err.message);
431
+ }
432
+ });
433
+ cmd.command("create").description("Create a new session").requiredOption("--name <name>", "Session name").option("--project <id>", "Project ID", "default").option("--command <cmd>", "Initial command to run").option("--cwd <dir>", "Working directory").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
434
+ try {
435
+ const url = getAgentUrl(options);
436
+ const body = {
437
+ name: options.name,
438
+ project: options.project
439
+ };
440
+ if (options.command)
441
+ body.command = options.command;
442
+ if (options.cwd)
443
+ body.cwd = options.cwd;
444
+ const result = await apiPost(url, "/api/sessions/create", body);
445
+ success(`Session created: ${shortId(result.id || result.sessionId)}`);
446
+ kv("Name", options.name);
447
+ kv("Project", options.project);
448
+ } catch (err) {
449
+ fail(err.message);
450
+ }
451
+ });
452
+ cmd.command("kill").description("Kill a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
453
+ try {
454
+ const url = getAgentUrl(options);
455
+ await apiDelete(url, `/api/sessions/${options.id}`);
456
+ success(`Session ${shortId(options.id)} killed.`);
457
+ } catch (err) {
458
+ fail(err.message);
459
+ }
460
+ });
461
+ cmd.command("exec").description("Execute a command in a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("-c, --command <cmd>", "Command to execute").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
462
+ try {
463
+ const url = getAgentUrl(options);
464
+ const result = await apiPost(url, `/api/sessions/${options.id}/command`, { command: options.command });
465
+ success("Command executed.");
466
+ if (result?.output) {
467
+ blank();
468
+ console.log(result.output);
469
+ }
470
+ } catch (err) {
471
+ fail(err.message);
472
+ }
473
+ });
474
+ cmd.command("capture").description("Capture session terminal output").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
475
+ try {
476
+ const url = getAgentUrl(options);
477
+ const result = await apiGet(url, `/api/sessions/${options.id}/capture`);
478
+ if (result?.content || result?.output) {
479
+ console.log(result.content || result.output);
480
+ } else {
481
+ info("No capture data available.");
482
+ }
483
+ } catch (err) {
484
+ fail(err.message);
485
+ }
486
+ });
487
+ cmd.command("keys").description("Send keys to a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("-k, --keys <keys>", "Keys to send").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
488
+ try {
489
+ const url = getAgentUrl(options);
490
+ await apiPost(url, `/api/sessions/${options.id}/keys`, {
491
+ keys: options.keys
492
+ });
493
+ success("Keys sent.");
494
+ } catch (err) {
495
+ fail(err.message);
496
+ }
497
+ });
498
+ cmd.command("interrupt").description("Send interrupt signal to a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
499
+ try {
500
+ const url = getAgentUrl(options);
501
+ await apiPost(url, `/api/sessions/${options.id}/interrupt`, {});
502
+ success(`Session ${shortId(options.id)} interrupted.`);
503
+ } catch (err) {
504
+ fail(err.message);
505
+ }
506
+ });
507
+ cmd.command("rename").description("Rename a session").requiredOption("-i, --id <id>", "Session ID").requiredOption("--name <name>", "New session name").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
508
+ try {
509
+ const url = getAgentUrl(options);
510
+ await apiPut(url, `/api/sessions/${options.id}/rename`, {
511
+ name: options.name
512
+ });
513
+ success(`Session ${shortId(options.id)} renamed to "${options.name}".`);
514
+ } catch (err) {
515
+ fail(err.message);
516
+ }
517
+ });
518
+ cmd.command("toggle-mouse").description("Toggle mouse support in a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
519
+ try {
520
+ const url = getAgentUrl(options);
521
+ const result = await apiPost(url, `/api/sessions/${options.id}/toggle-mouse`, {});
522
+ success(`Mouse support ${result?.mouseEnabled ? "enabled" : "toggled"} for session ${shortId(options.id)}.`);
523
+ } catch (err) {
524
+ fail(err.message);
525
+ }
526
+ });
527
+ cmd.command("terminal-start").description("Start terminal for a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
528
+ try {
529
+ const url = getAgentUrl(options);
530
+ const result = await apiPost(url, `/api/sessions/${options.id}/terminal`, {});
531
+ success(`Terminal started for session ${shortId(options.id)}.`);
532
+ if (result?.port)
533
+ kv("Port", result.port);
534
+ } catch (err) {
535
+ fail(err.message);
536
+ }
537
+ });
538
+ cmd.command("terminal-stop").description("Stop terminal for a session").requiredOption("-i, --id <id>", "Session ID").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
539
+ try {
540
+ const url = getAgentUrl(options);
541
+ await apiPost(url, `/api/sessions/${options.id}/terminal/stop`, {});
542
+ success(`Terminal stopped for session ${shortId(options.id)}.`);
543
+ } catch (err) {
544
+ fail(err.message);
545
+ }
546
+ });
547
+ cmd.command("health-check").description("Run health check on all sessions").option("--agent-url <url>", "Agent URL", DEFAULT_AGENT_URL).action(async (options) => {
548
+ try {
549
+ const url = getAgentUrl(options);
550
+ const result = await apiPost(url, "/api/sessions/health-check", {});
551
+ success("Health check completed.");
552
+ if (result?.healthy !== undefined)
553
+ kv("Healthy", result.healthy);
554
+ if (result?.checked !== undefined)
555
+ kv("Checked", result.checked);
556
+ if (result?.fixed !== undefined)
557
+ kv("Fixed", result.fixed);
558
+ } catch (err) {
559
+ fail(err.message);
560
+ }
561
+ });
562
+ }
563
+
564
+ // src/plugins/session/commands.ts
565
+ function registerCommands(program, _hostServices) {
566
+ register(program);
567
+ }
568
+
569
+ // src/plugins/session/index.ts
570
+ var vibePlugin = {
571
+ name: "session",
572
+ version: "2.2.0",
573
+ description: "Terminal session management via registered session provider",
574
+ tags: ["backend", "cli", "provider"],
575
+ cliCommand: "session",
576
+ apiPrefix: "/api/sessions",
577
+ createRoutes: (deps) => createRoutes(deps),
578
+ onCliSetup: async (program, hostServices) => {
579
+ registerCommands(program, hostServices);
580
+ }
581
+ };
582
+ export {
583
+ vibePlugin
584
+ };
585
+
586
+ //# debugId=D18B9D8D444814B064756E2164756E21
587
+ //# sourceMappingURL=index-rdm6e3rr.js.map