@sleep2agi/commhub-server 0.8.2 → 0.8.3-preview.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.ts +20 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/commhub-server",
3
- "version": "0.8.2",
3
+ "version": "0.8.3-preview.0",
4
4
  "description": "CommHub Server — AI Agent communication hub with MCP protocol, multi-network isolation, user auth, and 17 MCP tools.",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/index.ts CHANGED
@@ -342,6 +342,7 @@ const TaskSchema = z.object({
342
342
  priority: z.enum(["high", "normal", "low"]).default("normal"),
343
343
  from: z.string().max(200).optional(),
344
344
  network_id: z.string().max(200).optional(),
345
+ parent_task_id: z.string().max(200).optional(),
345
346
  });
346
347
 
347
348
  const BroadcastSchema = z.object({
@@ -1177,9 +1178,9 @@ Bun.serve({
1177
1178
  [id, body.alias, body.priority, body.task, fromSession, taskNetId]
1178
1179
  );
1179
1180
  db.run(
1180
- `INSERT INTO tasks (task_id, from_name, to_name, priority, status, content, requires_response, created_at, delivered_at, expires_at, network_id)
1181
- VALUES (?1, ?2, ?3, ?4, 'delivered', ?5, 'reply', datetime('now'), datetime('now'), datetime('now', ?6), ?7)`,
1182
- [id, fromSession, body.alias, body.priority, body.task, `+${ttlSeconds} seconds`, taskNetId]
1181
+ `INSERT INTO tasks (task_id, from_name, to_name, priority, status, content, requires_response, created_at, delivered_at, expires_at, network_id, parent_task_id)
1182
+ VALUES (?1, ?2, ?3, ?4, 'delivered', ?5, 'reply', datetime('now'), datetime('now'), datetime('now', ?6), ?7, ?8)`,
1183
+ [id, fromSession, body.alias, body.priority, body.task, `+${ttlSeconds} seconds`, taskNetId, body.parent_task_id ?? null]
1183
1184
  );
1184
1185
  // Touch session row so the dashboard reflects "task in flight"
1185
1186
  // immediately, without waiting for the agent's report_status to
@@ -1200,7 +1201,7 @@ Bun.serve({
1200
1201
  if (taskNetId) { sessionSql += " AND network_id = ?2"; sessionParams.push(taskNetId); }
1201
1202
  const targetSession = db.get<any>(sessionSql, ...sessionParams);
1202
1203
  if (targetSession) pushEvent(body.alias, { type: "new_task", inbox_count: pending?.cnt ?? 1, priority: body.priority, from: fromSession }, taskNetId);
1203
- return withCors(req, Response.json({ ok: true, message_id: id }));
1204
+ return withCors(req, Response.json({ ok: true, task_id: id, message_id: id }));
1204
1205
  }
1205
1206
 
1206
1207
  // ── REST: broadcast ──
@@ -1460,6 +1461,21 @@ Bun.serve({
1460
1461
  return withCors(req, Response.json({ ok: true, nodes: rows, count: rows.length }));
1461
1462
  }
1462
1463
 
1464
+ // ── REST: single task lookup (V2) ──
1465
+ const taskPathMatch = url.pathname.match(/^\/api\/tasks?\/([^/]+)$/);
1466
+ if (taskPathMatch && req.method === "GET") {
1467
+ const taskId = decodeURIComponent(taskPathMatch[1] ?? "");
1468
+ const params: any[] = [taskId];
1469
+ let sql = "SELECT * FROM tasks WHERE task_id = ?1";
1470
+ sql = addNetworkScope(sql, params, restScope);
1471
+ sql += " LIMIT 1";
1472
+ const task = db.get(sql, ...params);
1473
+ if (!task) {
1474
+ return withCors(req, Response.json({ ok: false, error: "task_not_found", task_id: taskId }, { status: 404 }));
1475
+ }
1476
+ return withCors(req, Response.json({ ok: true, task }));
1477
+ }
1478
+
1463
1479
  // ── REST: tasks table (V2) ──
1464
1480
  if (url.pathname === "/api/tasks") {
1465
1481
  const taskId = url.searchParams.get("task_id");