@agent-plan/server 0.2.19-next.0 → 0.2.19-next.10
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/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +109 -27
- package/package.json +2 -2
- package/web-ui-dist/assets/index--nGmEtA7.js +216 -0
- package/web-ui-dist/assets/index-Bfahk4d3.css +1 -0
- package/web-ui-dist/index.html +2 -2
- package/web-ui-dist/assets/index-DmQC9Ttj.css +0 -1
- package/web-ui-dist/assets/index-O9MpLyc3.js +0 -211
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAiHpC,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;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAiHpC,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;AAqyBD,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,CAkFvE"}
|
package/dist/serve.js
CHANGED
|
@@ -344,6 +344,8 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
344
344
|
updatedAt: now,
|
|
345
345
|
handoff: "",
|
|
346
346
|
handoffUpdatedAt: "",
|
|
347
|
+
handoffReadAt: "",
|
|
348
|
+
handoffHistory: [],
|
|
347
349
|
};
|
|
348
350
|
await store.savePhase(phase);
|
|
349
351
|
// Link to feature if featureId provided
|
|
@@ -642,45 +644,120 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
642
644
|
});
|
|
643
645
|
// ── Reorder (priority) ───────────────────────────────────────────
|
|
644
646
|
app.post(route("/reorder"), async (c) => {
|
|
647
|
+
// Midpoint-insert reorder: only the moved item's priority changes (when
|
|
648
|
+
// the gap between its new neighbours allows it). When the gap is exhausted
|
|
649
|
+
// (≤1, e.g. all-zero defaults or tight spacing), the segment is reindexed
|
|
650
|
+
// with GAP. Keeps priority as int (no schema migration) and minimises the
|
|
651
|
+
// set of changed items per drag.
|
|
645
652
|
const body = await c.req.json();
|
|
646
|
-
const { kind,
|
|
647
|
-
if (!
|
|
648
|
-
return c.json({ error: "
|
|
649
|
-
const
|
|
653
|
+
const { kind, movedId, beforeId, afterId } = body;
|
|
654
|
+
if (!movedId)
|
|
655
|
+
return c.json({ error: "movedId required" }, 400);
|
|
656
|
+
const GAP = 10;
|
|
657
|
+
// Reindex a list in-place: reconstruct the desired order (moved removed +
|
|
658
|
+
// reinserted between beforeId and afterId) then assign (i+1)*GAP.
|
|
659
|
+
const reindexList = (all) => {
|
|
660
|
+
const sorted = [...all].sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
661
|
+
const moved = sorted.find((x) => x.id === movedId);
|
|
662
|
+
const withoutMoved = sorted.filter((x) => x.id !== movedId);
|
|
663
|
+
let insertIdx;
|
|
664
|
+
if (beforeId) {
|
|
665
|
+
const bi = withoutMoved.findIndex((x) => x.id === beforeId);
|
|
666
|
+
insertIdx = bi === -1 ? withoutMoved.length : bi + 1;
|
|
667
|
+
}
|
|
668
|
+
else {
|
|
669
|
+
insertIdx = 0;
|
|
670
|
+
}
|
|
671
|
+
if (moved)
|
|
672
|
+
withoutMoved.splice(insertIdx, 0, moved);
|
|
673
|
+
withoutMoved.forEach((item, i) => { item.priority = (i + 1) * GAP; });
|
|
674
|
+
};
|
|
650
675
|
if (kind === "feature") {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
676
|
+
// Priority-only: suspend status rollup so reordering never flips a
|
|
677
|
+
// partially-done feature to in-progress (priority ≠ status).
|
|
678
|
+
await store.runBatch(async () => {
|
|
679
|
+
await store.updateFeatures((doc) => {
|
|
680
|
+
const moved = doc.features.find((x) => x.id === movedId);
|
|
681
|
+
if (!moved)
|
|
682
|
+
return doc;
|
|
683
|
+
const before = beforeId ? doc.features.find((x) => x.id === beforeId) : null;
|
|
684
|
+
const after = afterId ? doc.features.find((x) => x.id === afterId) : null;
|
|
685
|
+
const beforeP = before ? before.priority : 0;
|
|
686
|
+
const maxP = doc.features.reduce((m, f) => Math.max(m, f.priority), 0);
|
|
687
|
+
const afterP = after ? after.priority : (maxP + GAP);
|
|
688
|
+
if (afterP - beforeP > 1) {
|
|
689
|
+
moved.priority = Math.floor((beforeP + afterP) / 2);
|
|
690
|
+
}
|
|
691
|
+
else {
|
|
692
|
+
reindexList(doc.features);
|
|
693
|
+
}
|
|
694
|
+
doc.features.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
695
|
+
return doc;
|
|
696
|
+
});
|
|
659
697
|
});
|
|
660
698
|
hub()?.broadcast({ type: "features-updated", data: { action: "reordered" } });
|
|
661
699
|
}
|
|
662
700
|
else if (kind === "phase") {
|
|
663
701
|
const phases = await store.loadAllPhases();
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
702
|
+
const moved = phases.find((p) => p.id === movedId);
|
|
703
|
+
if (!moved)
|
|
704
|
+
return c.json({ error: "moved phase not found" }, 404);
|
|
705
|
+
const siblings = phases.filter((p) => p.featureId === moved.featureId);
|
|
706
|
+
const before = beforeId ? siblings.find((p) => p.id === beforeId) : null;
|
|
707
|
+
const after = afterId ? siblings.find((p) => p.id === afterId) : null;
|
|
708
|
+
const beforeP = before ? before.priority : 0;
|
|
709
|
+
const maxP = siblings.reduce((m, p) => Math.max(m, p.priority), 0);
|
|
710
|
+
const afterP = after ? after.priority : (maxP + GAP);
|
|
711
|
+
await store.runBatch(async () => {
|
|
712
|
+
if (afterP - beforeP > 1) {
|
|
713
|
+
await store.updatePhase(movedId, (entry) => { entry.priority = Math.floor((beforeP + afterP) / 2); return entry; });
|
|
667
714
|
}
|
|
668
|
-
|
|
715
|
+
else {
|
|
716
|
+
// Reindex all siblings (each phase is a separate file)
|
|
717
|
+
const sorted = [...siblings].sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
718
|
+
const withoutMoved = sorted.filter((x) => x.id !== movedId);
|
|
719
|
+
let insertIdx;
|
|
720
|
+
if (beforeId) {
|
|
721
|
+
const bi = withoutMoved.findIndex((x) => x.id === beforeId);
|
|
722
|
+
insertIdx = bi === -1 ? withoutMoved.length : bi + 1;
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
insertIdx = 0;
|
|
726
|
+
}
|
|
727
|
+
const movedEntry = sorted.find((x) => x.id === movedId);
|
|
728
|
+
if (movedEntry)
|
|
729
|
+
withoutMoved.splice(insertIdx, 0, movedEntry);
|
|
730
|
+
for (const [i, p] of withoutMoved.entries()) {
|
|
731
|
+
await store.updatePhase(p.id, (entry) => { entry.priority = (i + 1) * GAP; return entry; });
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
});
|
|
669
735
|
hub()?.broadcast({ type: "phases-updated", data: { action: "reordered" } });
|
|
670
736
|
}
|
|
671
737
|
else if (kind === "task") {
|
|
672
738
|
const allPhases = await store.loadAllPhases();
|
|
673
|
-
const host = allPhases.find((p) => p.tasks.some((t) =>
|
|
739
|
+
const host = allPhases.find((p) => p.tasks.some((t) => t.id === movedId));
|
|
674
740
|
if (host) {
|
|
675
|
-
await store.
|
|
676
|
-
|
|
677
|
-
const
|
|
678
|
-
if (
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
741
|
+
await store.runBatch(async () => {
|
|
742
|
+
await store.updatePhase(host.id, (phase) => {
|
|
743
|
+
const moved = phase.tasks.find((x) => x.id === movedId);
|
|
744
|
+
if (!moved)
|
|
745
|
+
return phase;
|
|
746
|
+
const before = beforeId ? phase.tasks.find((x) => x.id === beforeId) : null;
|
|
747
|
+
const after = afterId ? phase.tasks.find((x) => x.id === afterId) : null;
|
|
748
|
+
const beforeP = before ? before.priority : 0;
|
|
749
|
+
const maxP = phase.tasks.reduce((m, t) => Math.max(m, t.priority), 0);
|
|
750
|
+
const afterP = after ? after.priority : (maxP + GAP);
|
|
751
|
+
if (afterP - beforeP > 1) {
|
|
752
|
+
moved.priority = Math.floor((beforeP + afterP) / 2);
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
reindexList(phase.tasks);
|
|
756
|
+
}
|
|
757
|
+
phase.tasks.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
758
|
+
phase.taskIds = phase.tasks.map((t) => t.id);
|
|
759
|
+
return phase;
|
|
760
|
+
});
|
|
684
761
|
});
|
|
685
762
|
hub()?.broadcast({ type: "phases-updated", data: { action: "reordered", phaseId: host.id, featureId: host.featureId } });
|
|
686
763
|
}
|
|
@@ -690,7 +767,7 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
690
767
|
}
|
|
691
768
|
await store.writeGenerated();
|
|
692
769
|
hub()?.broadcast({ type: "plan-rendered", data: {} });
|
|
693
|
-
return c.json({ ok: true, kind,
|
|
770
|
+
return c.json({ ok: true, kind, movedId });
|
|
694
771
|
});
|
|
695
772
|
// ── Render ───────────────────────────────────────────────────────
|
|
696
773
|
app.post(route("/render"), async (c) => {
|
|
@@ -814,6 +891,11 @@ export async function serve(options) {
|
|
|
814
891
|
}
|
|
815
892
|
// Self-heal stale/legacy persisted statuses before the UI reads them.
|
|
816
893
|
await store.syncStatuses();
|
|
894
|
+
// Backfill missing shortIds (globally-unique 5-char) + priorities so the
|
|
895
|
+
// Web UI always shows short IDs even before the adapter's first-turn init
|
|
896
|
+
// runs. Idempotent: only assigns MISSING shortIds/priorities, never
|
|
897
|
+
// overwrites existing ones.
|
|
898
|
+
await store.ensureShortIdsAndPriority().catch(() => null);
|
|
817
899
|
// Shared mutable reference — routes see the hub after it's created
|
|
818
900
|
const hubRef = { current: null };
|
|
819
901
|
// Default to the bundled web UI when the caller doesn't pass staticDir. Pass
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/server",
|
|
3
|
-
"version": "0.2.19-next.
|
|
3
|
+
"version": "0.2.19-next.10",
|
|
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.19-next.
|
|
44
|
+
"@agent-plan/core": "0.2.19-next.10"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/ws": "^8.18.0"
|