@backlogmd/serve 0.2.1 → 0.3.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 (118) hide show
  1. package/app/dist/index.html +40 -20
  2. package/dist/assignmentQueue.d.ts +22 -0
  3. package/dist/assignmentQueue.d.ts.map +1 -0
  4. package/dist/assignmentQueue.js +27 -0
  5. package/dist/assignmentQueue.js.map +1 -0
  6. package/dist/chatAgent.d.ts +2 -0
  7. package/dist/chatAgent.d.ts.map +1 -0
  8. package/dist/chatAgent.js +89 -0
  9. package/dist/chatAgent.js.map +1 -0
  10. package/dist/cli.d.ts +4 -2
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +53 -18
  13. package/dist/cli.js.map +1 -1
  14. package/dist/context.d.ts +45 -0
  15. package/dist/context.d.ts.map +1 -0
  16. package/dist/context.js +2 -0
  17. package/dist/context.js.map +1 -0
  18. package/dist/html.d.ts +2 -2
  19. package/dist/html.d.ts.map +1 -1
  20. package/dist/html.js +20 -5
  21. package/dist/html.js.map +1 -1
  22. package/dist/index.d.ts +5 -1
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +11 -5
  25. package/dist/index.js.map +1 -1
  26. package/dist/lib/errorOutput.d.ts +7 -0
  27. package/dist/lib/errorOutput.d.ts.map +1 -0
  28. package/dist/lib/errorOutput.js +23 -0
  29. package/dist/lib/errorOutput.js.map +1 -0
  30. package/dist/lib/validStatuses.d.ts +2 -0
  31. package/dist/lib/validStatuses.d.ts.map +1 -0
  32. package/dist/lib/validStatuses.js +7 -0
  33. package/dist/lib/validStatuses.js.map +1 -0
  34. package/dist/routes.d.ts +4 -0
  35. package/dist/routes.d.ts.map +1 -0
  36. package/dist/routes.js +36 -0
  37. package/dist/routes.js.map +1 -0
  38. package/dist/server.d.ts +11 -2
  39. package/dist/server.d.ts.map +1 -1
  40. package/dist/server.js +123 -156
  41. package/dist/server.js.map +1 -1
  42. package/dist/shared/os.d.ts +2 -0
  43. package/dist/shared/os.d.ts.map +1 -0
  44. package/dist/shared/os.js +23 -0
  45. package/dist/shared/os.js.map +1 -0
  46. package/dist/useCases/deleteItem.d.ts +14 -0
  47. package/dist/useCases/deleteItem.d.ts.map +1 -0
  48. package/dist/useCases/deleteItem.js +27 -0
  49. package/dist/useCases/deleteItem.js.map +1 -0
  50. package/dist/useCases/deleteTask.d.ts +14 -0
  51. package/dist/useCases/deleteTask.d.ts.map +1 -0
  52. package/dist/useCases/deleteTask.js +28 -0
  53. package/dist/useCases/deleteTask.js.map +1 -0
  54. package/dist/useCases/getBacklog.d.ts +4 -0
  55. package/dist/useCases/getBacklog.d.ts.map +1 -0
  56. package/dist/useCases/getBacklog.js +19 -0
  57. package/dist/useCases/getBacklog.js.map +1 -0
  58. package/dist/useCases/getEvents.d.ts +4 -0
  59. package/dist/useCases/getEvents.d.ts.map +1 -0
  60. package/dist/useCases/getEvents.js +17 -0
  61. package/dist/useCases/getEvents.js.map +1 -0
  62. package/dist/useCases/getIndexPage.d.ts +4 -0
  63. package/dist/useCases/getIndexPage.d.ts.map +1 -0
  64. package/dist/useCases/getIndexPage.js +20 -0
  65. package/dist/useCases/getIndexPage.js.map +1 -0
  66. package/dist/useCases/getItemContent.d.ts +14 -0
  67. package/dist/useCases/getItemContent.d.ts.map +1 -0
  68. package/dist/useCases/getItemContent.js +26 -0
  69. package/dist/useCases/getItemContent.js.map +1 -0
  70. package/dist/useCases/getTaskContent.d.ts +13 -0
  71. package/dist/useCases/getTaskContent.d.ts.map +1 -0
  72. package/dist/useCases/getTaskContent.js +28 -0
  73. package/dist/useCases/getTaskContent.js.map +1 -0
  74. package/dist/useCases/getWork.d.ts +10 -0
  75. package/dist/useCases/getWork.d.ts.map +1 -0
  76. package/dist/useCases/getWork.js +6 -0
  77. package/dist/useCases/getWork.js.map +1 -0
  78. package/dist/useCases/getWorkerAssignments.d.ts +17 -0
  79. package/dist/useCases/getWorkerAssignments.d.ts.map +1 -0
  80. package/dist/useCases/getWorkerAssignments.js +92 -0
  81. package/dist/useCases/getWorkerAssignments.js.map +1 -0
  82. package/dist/useCases/getWorkers.d.ts +4 -0
  83. package/dist/useCases/getWorkers.d.ts.map +1 -0
  84. package/dist/useCases/getWorkers.js +5 -0
  85. package/dist/useCases/getWorkers.js.map +1 -0
  86. package/dist/useCases/patchTaskStatus.d.ts +14 -0
  87. package/dist/useCases/patchTaskStatus.d.ts.map +1 -0
  88. package/dist/useCases/patchTaskStatus.js +34 -0
  89. package/dist/useCases/patchTaskStatus.js.map +1 -0
  90. package/dist/useCases/postAssignWork.d.ts +11 -0
  91. package/dist/useCases/postAssignWork.d.ts.map +1 -0
  92. package/dist/useCases/postAssignWork.js +48 -0
  93. package/dist/useCases/postAssignWork.js.map +1 -0
  94. package/dist/useCases/postChat.d.ts +13 -0
  95. package/dist/useCases/postChat.d.ts.map +1 -0
  96. package/dist/useCases/postChat.js +44 -0
  97. package/dist/useCases/postChat.js.map +1 -0
  98. package/dist/useCases/postWorkerReport.d.ts +6 -0
  99. package/dist/useCases/postWorkerReport.d.ts.map +1 -0
  100. package/dist/useCases/postWorkerReport.js +71 -0
  101. package/dist/useCases/postWorkerReport.js.map +1 -0
  102. package/dist/useCases/putItemContent.d.ts +18 -0
  103. package/dist/useCases/putItemContent.d.ts.map +1 -0
  104. package/dist/useCases/putItemContent.js +30 -0
  105. package/dist/useCases/putItemContent.js.map +1 -0
  106. package/dist/useCases/putTaskContent.d.ts +17 -0
  107. package/dist/useCases/putTaskContent.d.ts.map +1 -0
  108. package/dist/useCases/putTaskContent.js +31 -0
  109. package/dist/useCases/putTaskContent.js.map +1 -0
  110. package/dist/watcher.d.ts +1 -1
  111. package/dist/watcher.d.ts.map +1 -1
  112. package/dist/watcher.js +1 -1
  113. package/dist/watcher.js.map +1 -1
  114. package/dist/workerRegistry.d.ts +35 -0
  115. package/dist/workerRegistry.d.ts.map +1 -0
  116. package/dist/workerRegistry.js +53 -0
  117. package/dist/workerRegistry.js.map +1 -0
  118. package/package.json +25 -14
@@ -0,0 +1,14 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ interface Params {
4
+ encodedSlug?: string;
5
+ }
6
+ /**
7
+ * GET /api/items/:encodedSlug/content
8
+ * Returns the plain-text body of the work item index (DESCRIPTION, CONTEXT, etc.).
9
+ */
10
+ export declare function getItemContent(ctx: AppContext, request: FastifyRequest<{
11
+ Params: Params;
12
+ }>, reply: FastifyReply): Promise<void>;
13
+ export {};
14
+ //# sourceMappingURL=getItemContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getItemContent.d.ts","sourceRoot":"","sources":["../../src/useCases/getItemContent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,MAAM;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAC3C,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAoBf"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * GET /api/items/:encodedSlug/content
3
+ * Returns the plain-text body of the work item index (DESCRIPTION, CONTEXT, etc.).
4
+ */
5
+ export async function getItemContent(ctx, request, reply) {
6
+ const slug = request.params.encodedSlug ? decodeURIComponent(request.params.encodedSlug) : "";
7
+ if (!slug) {
8
+ await reply.code(400).type("application/json").send({ error: "Missing item slug" });
9
+ return;
10
+ }
11
+ try {
12
+ const { content } = await ctx.backlogmd.getItemContent(slug);
13
+ await reply.type("application/json").send({ content });
14
+ }
15
+ catch (err) {
16
+ const message = err.message;
17
+ if (message.includes("not found")) {
18
+ await reply.code(404).type("application/json").send({ error: message });
19
+ }
20
+ else {
21
+ console.error("[backlogmd-serve] getItemContent error:", message);
22
+ await reply.code(500).type("application/json").send({ error: message });
23
+ }
24
+ }
25
+ }
26
+ //# sourceMappingURL=getItemContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getItemContent.js","sourceRoot":"","sources":["../../src/useCases/getItemContent.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,OAA2C,EAC3C,KAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAE9F,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACpF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ /**
4
+ * GET /api/tasks/:taskId/content
5
+ * taskId is URL-encoded so path stays one segment (e.g. work%2F002-item%2F001-task.md).
6
+ * Returns the full file content of the task (METADATA + DESCRIPTION + ACCEPTANCE CRITERIA).
7
+ */
8
+ export declare function getTaskContent(ctx: AppContext, request: FastifyRequest<{
9
+ Params: {
10
+ taskId: string;
11
+ };
12
+ }>, reply: FastifyReply): Promise<void>;
13
+ //# sourceMappingURL=getTaskContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTaskContent.d.ts","sourceRoot":"","sources":["../../src/useCases/getTaskContent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,EACvD,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * GET /api/tasks/:taskId/content
3
+ * taskId is URL-encoded so path stays one segment (e.g. work%2F002-item%2F001-task.md).
4
+ * Returns the full file content of the task (METADATA + DESCRIPTION + ACCEPTANCE CRITERIA).
5
+ */
6
+ export async function getTaskContent(ctx, request, reply) {
7
+ const raw = request.params.taskId ?? "";
8
+ const taskId = raw ? decodeURIComponent(raw) : "";
9
+ if (!taskId) {
10
+ await reply.code(400).type("application/json").send({ error: "Missing task id" });
11
+ return;
12
+ }
13
+ try {
14
+ const { content } = await ctx.backlogmd.getTaskFileContent(taskId);
15
+ await reply.type("application/json").send({ content });
16
+ }
17
+ catch (err) {
18
+ const message = err.message;
19
+ if (message.includes("not found")) {
20
+ await reply.code(404).type("application/json").send({ error: message });
21
+ }
22
+ else {
23
+ console.error("[backlogmd-serve] getTaskContent error:", message);
24
+ await reply.code(500).type("application/json").send({ error: message });
25
+ }
26
+ }
27
+ }
28
+ //# sourceMappingURL=getTaskContent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getTaskContent.js","sourceRoot":"","sources":["../../src/useCases/getTaskContent.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,OAAuD,EACvD,KAAmB;IAEnB,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;IACxC,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAElD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACnE,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ /** Delegates to getWorkerAssignments (same API). */
4
+ export declare function getWork(ctx: AppContext, request: FastifyRequest<{
5
+ Querystring: {
6
+ name?: string;
7
+ role?: string;
8
+ };
9
+ }>, reply: FastifyReply): Promise<void>;
10
+ //# sourceMappingURL=getWork.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWork.d.ts","sourceRoot":"","sources":["../../src/useCases/getWork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,oDAAoD;AACpD,wBAAsB,OAAO,CACzB,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,WAAW,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,EAC1E,KAAK,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAEf"}
@@ -0,0 +1,6 @@
1
+ import { getWorkerAssignments } from "./getWorkerAssignments.js";
2
+ /** Delegates to getWorkerAssignments (same API). */
3
+ export async function getWork(ctx, request, reply) {
4
+ return getWorkerAssignments(ctx, request, reply);
5
+ }
6
+ //# sourceMappingURL=getWork.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWork.js","sourceRoot":"","sources":["../../src/useCases/getWork.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,OAAO,CACzB,GAAe,EACf,OAA0E,EAC1E,KAAmB;IAEnB,OAAO,oBAAoB,CAAC,GAAG,EAAE,OAAgB,EAAE,KAAK,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ /**
4
+ * Returns the list of available work (assignments) for the requesting worker
5
+ * by reading the backlog. Assignee is stored in the backlog document, so
6
+ * after a server reload the list is still correct.
7
+ * Query: name (optional). If omitted, returns all assignments with assignee set (for debug).
8
+ * Match when name given: assignee === name or assignee starts with "name:".
9
+ * Response: 200 with { assignments: { taskId?: string; itemId?: string; assignee?: string }[] }.
10
+ */
11
+ export declare function getWorkerAssignments(ctx: AppContext, request: FastifyRequest<{
12
+ Querystring: {
13
+ name?: string;
14
+ role?: string;
15
+ };
16
+ }>, reply: FastifyReply): Promise<void>;
17
+ //# sourceMappingURL=getWorkerAssignments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWorkerAssignments.d.ts","sourceRoot":"","sources":["../../src/useCases/getWorkerAssignments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C,CAAC,EACF,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CA4Ff"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Returns the list of available work (assignments) for the requesting worker
3
+ * by reading the backlog. Assignee is stored in the backlog document, so
4
+ * after a server reload the list is still correct.
5
+ * Query: name (optional). If omitted, returns all assignments with assignee set (for debug).
6
+ * Match when name given: assignee === name or assignee starts with "name:".
7
+ * Response: 200 with { assignments: { taskId?: string; itemId?: string; assignee?: string }[] }.
8
+ */
9
+ export async function getWorkerAssignments(ctx, request, reply) {
10
+ const name = typeof request.query?.name === "string" ? request.query.name.trim() : "";
11
+ const allWorkers = !name;
12
+ function assigneeMatches(assignee) {
13
+ if (!assignee)
14
+ return false;
15
+ if (allWorkers)
16
+ return true;
17
+ return assignee === name || assignee.startsWith(name + ":");
18
+ }
19
+ let doc;
20
+ try {
21
+ doc = ctx.backlogmd.getDocument();
22
+ }
23
+ catch (err) {
24
+ console.error("[backlogmd-serve] Assignments parse error:", err.message);
25
+ await reply.code(500).type("application/json").send({
26
+ error: err.message,
27
+ });
28
+ return;
29
+ }
30
+ const assignments = [];
31
+ const debug = process.env.BACKLOGMD_DEBUG_ASSIGNMENTS === "1";
32
+ if (debug) {
33
+ const totalTasks = doc.work.reduce((n, w) => n + w.tasks.length, 0);
34
+ console.log(`[assignments] name=${name || "(all)"} backlogDir=${ctx.backlogDir} work=${doc.work.length} tasks=${totalTasks}`);
35
+ for (const w of doc.work) {
36
+ const taskAssignees = w.tasks.map((t) => t.assignee).filter(Boolean);
37
+ const match = taskAssignees.some((a) => assigneeMatches(a));
38
+ if (match || taskAssignees.length) {
39
+ console.log(`[assignments] item ${w.slug} status=${w.status} match=${match}`);
40
+ }
41
+ }
42
+ }
43
+ for (const item of doc.work) {
44
+ for (const task of item.tasks) {
45
+ if (assigneeMatches(task.assignee) &&
46
+ task.status !== "done" &&
47
+ task.status !== "in-progress") {
48
+ const taskId = `${task.itemSlug}/${task.priority}`;
49
+ assignments.push(allWorkers && task.assignee
50
+ ? { taskId, itemId: task.itemSlug, assignee: task.assignee }
51
+ : { taskId, itemId: task.itemSlug });
52
+ }
53
+ }
54
+ }
55
+ for (const item of doc.work) {
56
+ const itemAssignedToWorker = assigneeMatches(item.assignee) || item.tasks.some((t) => assigneeMatches(t.assignee));
57
+ if (!itemAssignedToWorker || item.status === "done")
58
+ continue;
59
+ if (!allWorkers && ctx.isItemClaimed(item.slug)) {
60
+ if (debug)
61
+ console.log(`[assignments] skip ${item.slug}: claimed`);
62
+ continue;
63
+ }
64
+ const allTasksDone = item.tasks.length > 0 && item.tasks.every((t) => t.status === "done");
65
+ if (allTasksDone) {
66
+ if (debug)
67
+ console.log(`[assignments] skip ${item.slug}: allTasksDone`);
68
+ continue;
69
+ }
70
+ const anyInProgress = item.tasks.some((t) => t.status === "in-progress");
71
+ if (anyInProgress) {
72
+ if (debug)
73
+ console.log(`[assignments] skip ${item.slug}: anyInProgress`);
74
+ continue;
75
+ }
76
+ const alreadyHasTaskForItem = assignments.some((a) => a.itemId === item.slug && a.taskId != null);
77
+ if (!alreadyHasTaskForItem) {
78
+ const assignee = allWorkers
79
+ ? (item.assignee || item.tasks.find((t) => t.assignee)?.assignee || undefined)
80
+ : undefined;
81
+ assignments.push(assignee != null ? { itemId: item.slug, assignee } : { itemId: item.slug });
82
+ if (debug)
83
+ console.log(`[assignments] add itemId=${item.slug}`);
84
+ }
85
+ }
86
+ if (debug)
87
+ console.log(`[assignments] returning ${assignments.length} assignment(s)`);
88
+ await reply.code(200).type("application/json").send({
89
+ assignments,
90
+ });
91
+ }
92
+ //# sourceMappingURL=getWorkerAssignments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWorkerAssignments.js","sourceRoot":"","sources":["../../src/useCases/getWorkerAssignments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ export declare function getWorkers(ctx: AppContext, _request: FastifyRequest, reply: FastifyReply): Promise<void>;
4
+ //# sourceMappingURL=getWorkers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWorkers.d.ts","sourceRoot":"","sources":["../../src/useCases/getWorkers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,wBAAsB,UAAU,CAC9B,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAGf"}
@@ -0,0 +1,5 @@
1
+ export async function getWorkers(ctx, _request, reply) {
2
+ const workers = ctx.getWorkerStates();
3
+ reply.code(200).send({ workers });
4
+ }
5
+ //# sourceMappingURL=getWorkers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getWorkers.js","sourceRoot":"","sources":["../../src/useCases/getWorkers.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAe,EACf,QAAwB,EACxB,KAAmB;IAEnB,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;IACtC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ interface Params {
4
+ taskId?: string;
5
+ }
6
+ interface Body {
7
+ status?: string;
8
+ }
9
+ export declare function patchTaskStatus(ctx: AppContext, request: FastifyRequest<{
10
+ Params: Params;
11
+ Body: Body;
12
+ }>, reply: FastifyReply): Promise<void>;
13
+ export {};
14
+ //# sourceMappingURL=patchTaskStatus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patchTaskStatus.d.ts","sourceRoot":"","sources":["../../src/useCases/patchTaskStatus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,MAAM;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,UAAU,IAAI;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,EACvD,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAgCf"}
@@ -0,0 +1,34 @@
1
+ import { VALID_STATUSES } from "../lib/validStatuses.js";
2
+ export async function patchTaskStatus(ctx, request, reply) {
3
+ const taskId = request.params.taskId
4
+ ? decodeURIComponent(request.params.taskId)
5
+ : "";
6
+ if (!taskId) {
7
+ await reply.code(400).type("application/json").send({ error: "Missing task id" });
8
+ return;
9
+ }
10
+ const body = request.body;
11
+ const newStatus = body?.status;
12
+ if (!newStatus || !VALID_STATUSES.has(newStatus)) {
13
+ await reply.code(400).type("application/json").send({
14
+ error: `Invalid status "${newStatus}". Must be one of: ${[...VALID_STATUSES].join(", ")}`,
15
+ });
16
+ return;
17
+ }
18
+ try {
19
+ await ctx.backlogmd.updateTaskStatus(taskId, newStatus);
20
+ ctx.notifyClients();
21
+ await reply.type("application/json").send({ ok: true });
22
+ }
23
+ catch (err) {
24
+ const message = err.message;
25
+ if (message.includes("not found")) {
26
+ await reply.code(404).type("application/json").send({ error: message });
27
+ }
28
+ else {
29
+ console.error("[backlogmd-serve] PATCH error:", message);
30
+ await reply.code(500).type("application/json").send({ error: message });
31
+ }
32
+ }
33
+ }
34
+ //# sourceMappingURL=patchTaskStatus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patchTaskStatus.js","sourceRoot":"","sources":["../../src/useCases/patchTaskStatus.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAWzD,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAe,EACf,OAAuD,EACvD,KAAmB;IAEnB,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM;QAClC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QAC3C,CAAC,CAAC,EAAE,CAAC;IAEP,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QAClF,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAwB,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,EAAE,MAAM,CAAC;IAC/B,IAAI,CAAC,SAAS,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACjD,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YAClD,KAAK,EAAE,mBAAmB,SAAS,sBAAsB,CAAC,GAAG,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC1F,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,SAAkD,CAAC,CAAC;QACjG,GAAG,CAAC,aAAa,EAAE,CAAC;QACpB,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ export interface AssignWorkBody {
4
+ workerId?: string;
5
+ taskId?: string;
6
+ itemId?: string;
7
+ }
8
+ export declare function postAssignWork(ctx: AppContext, request: FastifyRequest<{
9
+ Body: AssignWorkBody;
10
+ }>, reply: FastifyReply): Promise<void>;
11
+ //# sourceMappingURL=postAssignWork.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postAssignWork.d.ts","sourceRoot":"","sources":["../../src/useCases/postAssignWork.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,CAAC,EACjD,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -0,0 +1,48 @@
1
+ export async function postAssignWork(ctx, request, reply) {
2
+ const body = request.body ?? {};
3
+ const workerId = typeof body.workerId === "string" ? body.workerId.trim() : "";
4
+ const taskId = typeof body.taskId === "string" ? body.taskId.trim() : undefined;
5
+ const itemId = typeof body.itemId === "string" ? body.itemId.trim() : undefined;
6
+ if (!workerId) {
7
+ await reply.code(400).type("application/json").send({
8
+ error: "Missing workerId",
9
+ });
10
+ return;
11
+ }
12
+ if (!taskId && !itemId) {
13
+ await reply.code(400).type("application/json").send({
14
+ error: "Provide at least one of taskId or itemId",
15
+ });
16
+ return;
17
+ }
18
+ try {
19
+ if (taskId) {
20
+ await ctx.backlogmd.assignAgent(taskId, workerId);
21
+ if (process.env.BACKLOGMD_DEBUG_ASSIGNMENTS === "1") {
22
+ console.log(`[assign] task assignee written workerId=${workerId} taskId=${taskId} backlogDir=${ctx.backlogDir}`);
23
+ }
24
+ }
25
+ if (itemId) {
26
+ await ctx.backlogmd.assignItem(itemId, workerId);
27
+ if (process.env.BACKLOGMD_DEBUG_ASSIGNMENTS === "1") {
28
+ console.log(`[assign] item assignee written workerId=${workerId} itemId=${itemId} backlogDir=${ctx.backlogDir}`);
29
+ }
30
+ }
31
+ }
32
+ catch (err) {
33
+ const message = err.message;
34
+ await reply.code(404).type("application/json").send({
35
+ error: message,
36
+ });
37
+ return;
38
+ }
39
+ ctx.enqueueAssignment({
40
+ workerId,
41
+ taskId,
42
+ itemId,
43
+ });
44
+ ctx.notifyClients();
45
+ ctx.triggerWorkAvailable();
46
+ await reply.code(200).type("application/json").send({ ok: true });
47
+ }
48
+ //# sourceMappingURL=postAssignWork.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postAssignWork.js","sourceRoot":"","sources":["../../src/useCases/postAssignWork.ts"],"names":[],"mappings":"AASA,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,GAAe,EACf,OAAiD,EACjD,KAAmB;IAEnB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAChF,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YAClD,KAAK,EAAE,kBAAkB;SAC1B,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YAClD,KAAK,EAAE,0CAA0C;SAClD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,GAAG,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClD,IAAI,OAAO,CAAC,GAAG,CAAC,2BAA2B,KAAK,GAAG,EAAE,CAAC;gBACpD,OAAO,CAAC,GAAG,CAAC,2CAA2C,QAAQ,WAAW,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACnH,CAAC;QACH,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACjD,IAAI,OAAO,CAAC,GAAG,CAAC,2BAA2B,KAAK,GAAG,EAAE,CAAC;gBACpD,OAAO,CAAC,GAAG,CAAC,2CAA2C,QAAQ,WAAW,MAAM,eAAe,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;YACnH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAI,GAAa,CAAC,OAAO,CAAC;QACvC,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YAClD,KAAK,EAAE,OAAO;SACf,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,GAAG,CAAC,iBAAiB,CAAC;QACpB,QAAQ;QACR,MAAM;QACN,MAAM;KACP,CAAC,CAAC;IACH,GAAG,CAAC,aAAa,EAAE,CAAC;IACpB,GAAG,CAAC,oBAAoB,EAAE,CAAC;IAE3B,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;AACpE,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ interface Body {
4
+ messages?: Array<{
5
+ role?: string;
6
+ content?: string;
7
+ }>;
8
+ }
9
+ export declare function postChat(ctx: AppContext, request: FastifyRequest<{
10
+ Body: Body;
11
+ }>, reply: FastifyReply): Promise<void>;
12
+ export {};
13
+ //# sourceMappingURL=postChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postChat.d.ts","sourceRoot":"","sources":["../../src/useCases/postChat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,IAAI;IACZ,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,EACvC,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CA6Cf"}
@@ -0,0 +1,44 @@
1
+ export async function postChat(ctx, request, reply) {
2
+ const parsed = request.body;
3
+ const messages = parsed?.messages;
4
+ if (!Array.isArray(messages) || messages.length === 0) {
5
+ await reply.code(400).type("application/json").send({
6
+ error: "Request body must include a non-empty messages array",
7
+ });
8
+ return;
9
+ }
10
+ const lastUser = [...messages].reverse().find((m) => m.role === "user");
11
+ const userInput = typeof lastUser?.content === "string"
12
+ ? lastUser.content
13
+ : "Send a message with role 'user' and content to get a reply.";
14
+ const agent = await ctx.getChatAgent();
15
+ if (agent) {
16
+ try {
17
+ const result = await agent.invoke({ input: userInput });
18
+ const content = typeof result?.output === "string" ? result.output : String(result?.output ?? "");
19
+ ctx.notifyClients();
20
+ await reply.type("application/json").send({
21
+ message: { role: "assistant", content },
22
+ });
23
+ }
24
+ catch (err) {
25
+ const e = err;
26
+ console.error("[backlogmd-serve] Chat agent error:", e.message, e.stack ?? "");
27
+ await reply.code(500).type("application/json").send({
28
+ error: "Chat failed",
29
+ message: e.message,
30
+ });
31
+ }
32
+ }
33
+ else {
34
+ await reply.type("application/json").send({
35
+ message: {
36
+ role: "assistant",
37
+ content: process.env.OPENAI_API_KEY
38
+ ? "Agent is starting up; try again in a moment."
39
+ : `Echo (stub): ${userInput}. Set OPENAI_API_KEY to enable the live agent.`,
40
+ },
41
+ });
42
+ }
43
+ }
44
+ //# sourceMappingURL=postChat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postChat.js","sourceRoot":"","sources":["../../src/useCases/postChat.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,GAAe,EACf,OAAuC,EACvC,KAAmB;IAEnB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAwB,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,CAAC;IAElC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YAClD,KAAK,EAAE,sDAAsD;SAC9D,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IACxE,MAAM,SAAS,GACb,OAAO,QAAQ,EAAE,OAAO,KAAK,QAAQ;QACnC,CAAC,CAAC,QAAQ,CAAC,OAAO;QAClB,CAAC,CAAC,6DAA6D,CAAC;IAEpE,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;IACvC,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACxD,MAAM,OAAO,GACX,OAAO,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;YACpF,GAAG,CAAC,aAAa,EAAE,CAAC;YACpB,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;gBACxC,OAAO,EAAE,EAAE,IAAI,EAAE,WAAoB,EAAE,OAAO,EAAE;aACjD,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,GAAY,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YAC/E,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;gBAClD,KAAK,EAAE,aAAa;gBACpB,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC;YACxC,OAAO,EAAE;gBACP,IAAI,EAAE,WAAoB;gBAC1B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;oBACjC,CAAC,CAAC,8CAA8C;oBAChD,CAAC,CAAC,gBAAgB,SAAS,gDAAgD;aAC9E;SACF,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext, WorkerReportBody } from "../context.js";
3
+ export declare function postWorkerReport(ctx: AppContext, request: FastifyRequest<{
4
+ Body: WorkerReportBody;
5
+ }>, reply: FastifyReply): Promise<void>;
6
+ //# sourceMappingURL=postWorkerReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postWorkerReport.d.ts","sourceRoot":"","sources":["../../src/useCases/postWorkerReport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAqDlE,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,CAAC,EACnD,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * When a worker reports "in-progress", update the backlog so the task/item
3
+ * is marked in-progress and removed from the assignments list.
4
+ * @returns true if a task was updated (item has tasks); false if item has no tasks (caller should claim item).
5
+ */
6
+ async function updateBacklogInProgress(ctx, body) {
7
+ if (body.status !== "in-progress")
8
+ return false;
9
+ const taskId = typeof body.taskId === "string" ? body.taskId.trim() : undefined;
10
+ const itemId = typeof body.itemId === "string" ? body.itemId.trim() : undefined;
11
+ if (!taskId && !itemId)
12
+ return false;
13
+ try {
14
+ const doc = ctx.backlogmd.getDocument();
15
+ let resolvedTaskId;
16
+ if (taskId) {
17
+ for (const item of doc.work) {
18
+ const task = item.tasks.find((t) => `${t.itemSlug}/${t.priority}` === taskId || t.slug === taskId);
19
+ if (task) {
20
+ resolvedTaskId = `${task.itemSlug}/${task.priority}`;
21
+ break;
22
+ }
23
+ }
24
+ }
25
+ else if (itemId) {
26
+ for (const item of doc.work) {
27
+ if (item.slug !== itemId && !item.slug.startsWith(itemId + "-"))
28
+ continue;
29
+ const task = item.tasks.find((t) => t.status !== "done");
30
+ if (task) {
31
+ resolvedTaskId = `${task.itemSlug}/${task.priority}`;
32
+ break;
33
+ }
34
+ }
35
+ }
36
+ if (resolvedTaskId) {
37
+ await ctx.backlogmd.updateTaskStatus(resolvedTaskId, "in-progress");
38
+ ctx.notifyClients();
39
+ return true;
40
+ }
41
+ }
42
+ catch (err) {
43
+ console.error("[backlogmd-serve] Report in-progress backlog update:", err.message);
44
+ }
45
+ return false;
46
+ }
47
+ function workerKey(body) {
48
+ const name = (body.name ?? "worker").trim() || "worker";
49
+ const role = (body.role ?? "").trim() || "worker";
50
+ return `${name}:${role}`;
51
+ }
52
+ export async function postWorkerReport(ctx, request, reply) {
53
+ const body = request.body ?? {};
54
+ const key = workerKey(body);
55
+ if (body.status === "in-progress") {
56
+ const updated = await updateBacklogInProgress(ctx, body);
57
+ const itemId = typeof body.itemId === "string" ? body.itemId.trim() : undefined;
58
+ if (itemId && !updated) {
59
+ ctx.setClaimedItem(key, itemId);
60
+ }
61
+ }
62
+ else if (body.status === "idle") {
63
+ ctx.setClaimedItem(key, null);
64
+ // Worker finished (or went idle); backlog may have task status updates (done). Notify clients so dashboard refetches.
65
+ ctx.notifyClients();
66
+ }
67
+ const state = ctx.reportWorker(body);
68
+ ctx.broadcastStatus();
69
+ reply.code(200).send(state);
70
+ }
71
+ //# sourceMappingURL=postWorkerReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postWorkerReport.js","sourceRoot":"","sources":["../../src/useCases/postWorkerReport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { FastifyRequest, FastifyReply } from "fastify";
2
+ import type { AppContext } from "../context.js";
3
+ interface Params {
4
+ encodedSlug?: string;
5
+ }
6
+ interface Body {
7
+ content?: string;
8
+ }
9
+ /**
10
+ * PUT /api/items/:encodedSlug/content
11
+ * Overwrites the work item index body (preserves METADATA). Reloads tree and notifies clients.
12
+ */
13
+ export declare function putItemContent(ctx: AppContext, request: FastifyRequest<{
14
+ Params: Params;
15
+ Body: Body;
16
+ }>, reply: FastifyReply): Promise<void>;
17
+ export {};
18
+ //# sourceMappingURL=putItemContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"putItemContent.d.ts","sourceRoot":"","sources":["../../src/useCases/putItemContent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,UAAU,MAAM;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,IAAI;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,cAAc,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,EACvD,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,IAAI,CAAC,CAyBf"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * PUT /api/items/:encodedSlug/content
3
+ * Overwrites the work item index body (preserves METADATA). Reloads tree and notifies clients.
4
+ */
5
+ export async function putItemContent(ctx, request, reply) {
6
+ const slug = request.params.encodedSlug ? decodeURIComponent(request.params.encodedSlug) : "";
7
+ if (!slug) {
8
+ await reply.code(400).type("application/json").send({ error: "Missing item slug" });
9
+ return;
10
+ }
11
+ const body = request.body;
12
+ const content = typeof body?.content === "string" ? body.content : "";
13
+ try {
14
+ await ctx.backlogmd.updateItemContent(slug, content);
15
+ ctx.notifyClients();
16
+ ctx.triggerWorkAvailable();
17
+ await reply.type("application/json").send({ ok: true });
18
+ }
19
+ catch (err) {
20
+ const message = err.message;
21
+ if (message.includes("not found")) {
22
+ await reply.code(404).type("application/json").send({ error: message });
23
+ }
24
+ else {
25
+ console.error("[backlogmd-serve] putItemContent error:", message);
26
+ await reply.code(500).type("application/json").send({ error: message });
27
+ }
28
+ }
29
+ }
30
+ //# sourceMappingURL=putItemContent.js.map