@agent-plan/server 0.2.20 → 0.2.21

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.
@@ -1 +1 @@
1
- {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAuIpC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,GAAG,KAAK,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACzF,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAu0BD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,GAAG,KAAK,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA6EvE"}
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAuIpC,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,GAAG,KAAK,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC;IACzF,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;CACrC;AAg4BD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,IAAI,EAAE,OAAO,GAAG,KAAK,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA6EvE"}
package/dist/serve.js CHANGED
@@ -473,6 +473,8 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
473
473
  const title = body.title?.trim();
474
474
  if (!title)
475
475
  return c.json({ error: "title required" }, 400);
476
+ if (body.status === "paused")
477
+ return c.json({ error: "A task cannot be created paused without an in-progress checkpoint. Create it planned, then use task_pause/task_switch." }, 400);
476
478
  const phase = await store.loadPhase(phaseId).catch(() => null);
477
479
  if (!phase)
478
480
  return c.json({ error: "phase not found" }, 404);
@@ -509,6 +511,8 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
509
511
  checklist: checklistItems,
510
512
  subtasks: [],
511
513
  dependsOn: [],
514
+ pauseSnapshot: null,
515
+ pauseHistory: [],
512
516
  startedAt: initialStatus === "in-progress" || initialStatus === "done" ? now : "",
513
517
  completedAt: initialStatus === "done" ? now : "",
514
518
  createdAt: now,
@@ -569,6 +573,56 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
569
573
  }
570
574
  return c.json(Array.from(activeTasksMap.values()));
571
575
  });
576
+ app.get(route("/tasks/focus"), async (c) => {
577
+ const [phases, featuresDoc, project] = await Promise.all([
578
+ store.loadAllPhases(), store.loadFeatures(), store.loadProject(),
579
+ ]);
580
+ const featureIdToNum = new Map(featuresDoc.features.map((feature) => [feature.id, feature.number]));
581
+ const openReturn = [...project.workDeviations]
582
+ .filter((deviation) => deviation.state === "resume-required" || deviation.state === "resolved")
583
+ .sort((left, right) => right.createdAt.localeCompare(left.createdAt));
584
+ const pendingByTask = new Map();
585
+ for (const deviation of openReturn) {
586
+ if (!pendingByTask.has(deviation.resumeTaskId))
587
+ pendingByTask.set(deviation.resumeTaskId, deviation);
588
+ }
589
+ const pendingOrder = new Map(openReturn.map((deviation, index) => [deviation.id, index]));
590
+ const active = [];
591
+ const paused = [];
592
+ const pendingResume = [];
593
+ for (const phase of phases) {
594
+ if (!phase.featureId)
595
+ continue;
596
+ for (const task of phase.tasks) {
597
+ const deviation = pendingByTask.get(task.id);
598
+ if (task.status !== "in-progress" && task.status !== "paused" && !deviation)
599
+ continue;
600
+ const summary = {
601
+ id: task.id,
602
+ number: task.number,
603
+ shortId: task.shortId,
604
+ title: task.title,
605
+ phaseId: phase.id,
606
+ phaseNumber: phase.number,
607
+ featureId: phase.featureId,
608
+ featureNumber: featureIdToNum.get(phase.featureId) ?? 0,
609
+ status: task.status,
610
+ pauseSnapshot: task.pauseSnapshot ?? deviation?.snapshot ?? null,
611
+ pendingResume: Boolean(deviation),
612
+ deviationId: deviation?.id ?? "",
613
+ };
614
+ if (deviation)
615
+ pendingResume.push(summary);
616
+ else if (task.status === "in-progress")
617
+ active.push(summary);
618
+ else if (task.status === "paused")
619
+ paused.push(summary);
620
+ }
621
+ }
622
+ pendingResume.sort((left, right) => (pendingOrder.get(left.deviationId) ?? Number.MAX_SAFE_INTEGER) - (pendingOrder.get(right.deviationId) ?? Number.MAX_SAFE_INTEGER));
623
+ paused.sort((left, right) => (right.pauseSnapshot?.pausedAt ?? "").localeCompare(left.pauseSnapshot?.pausedAt ?? ""));
624
+ return c.json({ active, paused, pendingResume });
625
+ });
572
626
  app.get(route("/tasks/:id"), async (c) => {
573
627
  const taskId = c.req.param("id");
574
628
  const phases = await store.loadAllPhases();
@@ -590,6 +644,9 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
590
644
  const existing = phase.tasks.find((t) => t.id === taskId);
591
645
  if (!existing)
592
646
  return c.json({ error: "task not found" }, 404);
647
+ if (body.status && body.status !== existing.status && (body.status === "paused" || existing.status === "paused")) {
648
+ return c.json({ error: "Paused lifecycle transitions require task_pause/task_switch/task_start so the resume checkpoint and return stack remain consistent." }, 400);
649
+ }
593
650
  // Validate motivation requirement for status transitions.
594
651
  if (body.status && body.status !== existing.status && needsMotivation(existing.status, body.status)) {
595
652
  if (!body.motivation || !body.motivation.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-plan/server",
3
- "version": "0.2.20",
3
+ "version": "0.2.21",
4
4
  "private": false,
5
5
  "description": "Local HTTP/WebSocket server for Agent Plan dashboards and planner APIs.",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "@hono/node-server": "^1.14.0",
42
42
  "hono": "^4.7.0",
43
43
  "ws": "^8.18.0",
44
- "@agent-plan/core": "0.2.20"
44
+ "@agent-plan/core": "0.2.21"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/ws": "^8.18.0"