@agent-plan/server 0.2.18 → 0.2.19-next.1
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 +129 -13
- package/dist/ws-hub.d.ts +10 -0
- package/dist/ws-hub.d.ts.map +1 -1
- package/package.json +2 -2
- package/web-ui-dist/assets/index-CZ27vQH6.js +211 -0
- package/web-ui-dist/assets/index-Jy8Yy6I4.css +1 -0
- package/web-ui-dist/index.html +2 -2
- package/web-ui-dist/assets/index-Tma57h5W.js +0 -191
- package/web-ui-dist/assets/index-U-dx9Eua.css +0 -1
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;AAsuBD,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
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
import { createAdaptorServer } from "@hono/node-server";
|
|
7
7
|
import { Hono } from "hono";
|
|
8
8
|
import { cors } from "hono/cors";
|
|
9
|
-
import { ExportService, PlanStore, PlanStoreError, createFeatureId, createPhaseId, createTaskId, normalizeSlug, withFeatureLock, needsMotivation } from "@agent-plan/core";
|
|
9
|
+
import { ExportService, PlanStore, PlanStoreError, createFeatureId, createPhaseId, createShortId, createTaskId, normalizeSlug, withFeatureLock, needsMotivation } from "@agent-plan/core";
|
|
10
10
|
import { WsHub } from "./ws-hub.js";
|
|
11
11
|
// ─── Watcher ────────────────────────────────────────────────────────────
|
|
12
12
|
let watcherAbort = null;
|
|
@@ -202,10 +202,14 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
202
202
|
return c.json({ error: "name required" }, 400);
|
|
203
203
|
const features = await store.loadFeatures();
|
|
204
204
|
const number = features.features.length + 1;
|
|
205
|
+
const shortId = createShortId(await store.assignedShortIds());
|
|
206
|
+
const priority = await store.nextPriority("feature");
|
|
205
207
|
const now = nowISO();
|
|
206
208
|
const feature = {
|
|
207
209
|
id: createFeatureId(),
|
|
208
210
|
number,
|
|
211
|
+
shortId,
|
|
212
|
+
priority,
|
|
209
213
|
name,
|
|
210
214
|
description: body.description ?? "",
|
|
211
215
|
status: "planned",
|
|
@@ -307,11 +311,15 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
307
311
|
const allPhases = await store.loadAllPhases();
|
|
308
312
|
const number = allPhases.filter((p) => p.featureId === featureId).length + 1;
|
|
309
313
|
const slug = normalizeSlug(title);
|
|
314
|
+
const shortId = createShortId(await store.assignedShortIds());
|
|
315
|
+
const priority = await store.nextPriority("phase", featureId);
|
|
310
316
|
const now = nowISO();
|
|
311
317
|
phase = {
|
|
312
318
|
id: createPhaseId(),
|
|
313
319
|
featureId,
|
|
314
320
|
number,
|
|
321
|
+
shortId,
|
|
322
|
+
priority,
|
|
315
323
|
slug,
|
|
316
324
|
title,
|
|
317
325
|
status: "draft",
|
|
@@ -334,6 +342,8 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
334
342
|
dependsOn: [],
|
|
335
343
|
createdAt: now,
|
|
336
344
|
updatedAt: now,
|
|
345
|
+
handoff: "",
|
|
346
|
+
handoffUpdatedAt: "",
|
|
337
347
|
};
|
|
338
348
|
await store.savePhase(phase);
|
|
339
349
|
// Link to feature if featureId provided
|
|
@@ -432,10 +442,14 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
432
442
|
const taskNumber = nextTaskNumber(phase);
|
|
433
443
|
const shortName = normalizeSlug(title).trim() || `task-${Date.now().toString(36)}`;
|
|
434
444
|
const initialStatus = body.status ?? "planned";
|
|
445
|
+
const shortId = createShortId(await store.assignedShortIds());
|
|
446
|
+
const priority = await store.nextPriority("task", phase.id);
|
|
435
447
|
const task = {
|
|
436
448
|
id: createTaskId(),
|
|
437
449
|
phaseId: phase.id,
|
|
438
450
|
number: taskNumber,
|
|
451
|
+
shortId,
|
|
452
|
+
priority,
|
|
439
453
|
shortName,
|
|
440
454
|
title,
|
|
441
455
|
status: initialStatus,
|
|
@@ -626,25 +640,122 @@ function createApiApp(store, hubRef, apiPrefix = "", uiConfig, isBusy) {
|
|
|
626
640
|
hub()?.broadcast({ type: "phases-updated", data: { action: "repaired" } });
|
|
627
641
|
return c.json(report);
|
|
628
642
|
});
|
|
643
|
+
// ── Reorder (priority) ───────────────────────────────────────────
|
|
644
|
+
app.post(route("/reorder"), async (c) => {
|
|
645
|
+
const body = await c.req.json();
|
|
646
|
+
const { kind, ids } = body;
|
|
647
|
+
if (!Array.isArray(ids) || ids.length === 0)
|
|
648
|
+
return c.json({ error: "ids required" }, 400);
|
|
649
|
+
const gap = 10;
|
|
650
|
+
if (kind === "feature") {
|
|
651
|
+
// Priority-only: suspend status rollup so reordering never flips a
|
|
652
|
+
// partially-done feature to in-progress (priority ≠ status).
|
|
653
|
+
await store.runBatch(async () => {
|
|
654
|
+
await store.updateFeatures((doc) => {
|
|
655
|
+
for (const [i, id] of ids.entries()) {
|
|
656
|
+
const f = doc.features.find((x) => x.id === id);
|
|
657
|
+
if (f)
|
|
658
|
+
f.priority = (i + 1) * gap;
|
|
659
|
+
}
|
|
660
|
+
doc.features.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
661
|
+
return doc;
|
|
662
|
+
});
|
|
663
|
+
});
|
|
664
|
+
hub()?.broadcast({ type: "features-updated", data: { action: "reordered" } });
|
|
665
|
+
}
|
|
666
|
+
else if (kind === "phase") {
|
|
667
|
+
const phases = await store.loadAllPhases();
|
|
668
|
+
await store.runBatch(async () => {
|
|
669
|
+
for (const [i, id] of ids.entries()) {
|
|
670
|
+
if (phases.some((x) => x.id === id)) {
|
|
671
|
+
await store.updatePhase(id, (entry) => { entry.priority = (i + 1) * gap; return entry; });
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
});
|
|
675
|
+
hub()?.broadcast({ type: "phases-updated", data: { action: "reordered" } });
|
|
676
|
+
}
|
|
677
|
+
else if (kind === "task") {
|
|
678
|
+
const allPhases = await store.loadAllPhases();
|
|
679
|
+
const host = allPhases.find((p) => p.tasks.some((t) => ids.includes(t.id)));
|
|
680
|
+
if (host) {
|
|
681
|
+
await store.runBatch(async () => {
|
|
682
|
+
await store.updatePhase(host.id, (phase) => {
|
|
683
|
+
for (const [i, id] of ids.entries()) {
|
|
684
|
+
const t = phase.tasks.find((x) => x.id === id);
|
|
685
|
+
if (t)
|
|
686
|
+
t.priority = (i + 1) * gap;
|
|
687
|
+
}
|
|
688
|
+
phase.tasks.sort((a, b) => a.priority - b.priority || a.number - b.number);
|
|
689
|
+
phase.taskIds = phase.tasks.map((t) => t.id);
|
|
690
|
+
return phase;
|
|
691
|
+
});
|
|
692
|
+
});
|
|
693
|
+
hub()?.broadcast({ type: "phases-updated", data: { action: "reordered", phaseId: host.id, featureId: host.featureId } });
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
return c.json({ error: "invalid kind" }, 400);
|
|
698
|
+
}
|
|
699
|
+
await store.writeGenerated();
|
|
700
|
+
hub()?.broadcast({ type: "plan-rendered", data: {} });
|
|
701
|
+
return c.json({ ok: true, kind, count: ids.length });
|
|
702
|
+
});
|
|
629
703
|
// ── Render ───────────────────────────────────────────────────────
|
|
630
704
|
app.post(route("/render"), async (c) => {
|
|
631
705
|
const files = await store.writeGenerated();
|
|
632
706
|
hub()?.broadcast({ type: "plan-rendered", data: { files } });
|
|
633
707
|
return c.json({ files });
|
|
634
708
|
});
|
|
635
|
-
// ── Handoff
|
|
636
|
-
app.get(route("/
|
|
637
|
-
const
|
|
638
|
-
return c.json({
|
|
639
|
-
exists: Boolean(handoff),
|
|
640
|
-
content: handoff?.content ?? "",
|
|
641
|
-
createdAt: handoff?.createdAt ?? "",
|
|
642
|
-
updatedAt: handoff?.updatedAt ?? "",
|
|
643
|
-
});
|
|
709
|
+
// ── Handoff (entity-scoped, phase.handoff) ────────────────────
|
|
710
|
+
app.get(route("/handoffs"), async (c) => {
|
|
711
|
+
const list = await store.listHandoffs();
|
|
712
|
+
return c.json({ handoffs: list });
|
|
644
713
|
});
|
|
645
|
-
app.
|
|
646
|
-
|
|
647
|
-
|
|
714
|
+
app.get(route("/phases/:id/handoff"), async (c) => {
|
|
715
|
+
const id = c.req.param("id");
|
|
716
|
+
if (!id)
|
|
717
|
+
return c.json({ error: "id required" }, 400);
|
|
718
|
+
const phase = await store.loadPhase(id).catch(() => null);
|
|
719
|
+
if (!phase)
|
|
720
|
+
return c.json({ error: "phase not found" }, 404);
|
|
721
|
+
const content = await store.getPhaseHandoff(id);
|
|
722
|
+
return c.json({ content, updatedAt: phase.handoffUpdatedAt ?? "" });
|
|
723
|
+
});
|
|
724
|
+
app.put(route("/phases/:id/handoff"), async (c) => {
|
|
725
|
+
const id = c.req.param("id");
|
|
726
|
+
if (!id)
|
|
727
|
+
return c.json({ error: "id required" }, 400);
|
|
728
|
+
const phase = await store.loadPhase(id).catch(() => null);
|
|
729
|
+
if (!phase)
|
|
730
|
+
return c.json({ error: "phase not found" }, 404);
|
|
731
|
+
const body = await c.req.json().catch(() => ({ content: "" }));
|
|
732
|
+
const content = (body?.content ?? "").trim();
|
|
733
|
+
if (!content) {
|
|
734
|
+
// empty PUT = clear equivalent
|
|
735
|
+
await store.clearPhaseHandoff(id);
|
|
736
|
+
hub()?.broadcast({ type: "handoffCleared", data: { phaseId: id } });
|
|
737
|
+
hub()?.broadcast({ type: "phases-updated", data: { action: "updated", id, phaseId: id, featureId: phase.featureId ?? "" } });
|
|
738
|
+
hub()?.broadcast({ type: "plan-rendered", data: {} });
|
|
739
|
+
return c.json({ cleared: true });
|
|
740
|
+
}
|
|
741
|
+
await store.setPhaseHandoff(id, content);
|
|
742
|
+
hub()?.broadcast({ type: "handoffUpdated", data: { phaseId: id } });
|
|
743
|
+
hub()?.broadcast({ type: "phases-updated", data: { action: "updated", id, phaseId: id, featureId: phase.featureId ?? "" } });
|
|
744
|
+
hub()?.broadcast({ type: "plan-rendered", data: {} });
|
|
745
|
+
return c.json({ content, updatedAt: (await store.loadPhase(id)).handoffUpdatedAt ?? "" });
|
|
746
|
+
});
|
|
747
|
+
app.delete(route("/phases/:id/handoff"), async (c) => {
|
|
748
|
+
const id = c.req.param("id");
|
|
749
|
+
if (!id)
|
|
750
|
+
return c.json({ error: "id required" }, 400);
|
|
751
|
+
const phase = await store.loadPhase(id).catch(() => null);
|
|
752
|
+
if (!phase)
|
|
753
|
+
return c.json({ error: "phase not found" }, 404);
|
|
754
|
+
await store.clearPhaseHandoff(id);
|
|
755
|
+
hub()?.broadcast({ type: "handoffCleared", data: { phaseId: id } });
|
|
756
|
+
hub()?.broadcast({ type: "phases-updated", data: { action: "updated", id, phaseId: id, featureId: phase.featureId ?? "" } });
|
|
757
|
+
hub()?.broadcast({ type: "plan-rendered", data: {} });
|
|
758
|
+
return c.json({ cleared: true });
|
|
648
759
|
});
|
|
649
760
|
// ── Health ───────────────────────────────────────────────────────
|
|
650
761
|
app.get(route("/health"), (c) => c.json({ status: "ok", root: store.root }));
|
|
@@ -711,6 +822,11 @@ export async function serve(options) {
|
|
|
711
822
|
}
|
|
712
823
|
// Self-heal stale/legacy persisted statuses before the UI reads them.
|
|
713
824
|
await store.syncStatuses();
|
|
825
|
+
// Backfill missing shortIds (globally-unique 5-char) + priorities so the
|
|
826
|
+
// Web UI always shows short IDs even before the adapter's first-turn init
|
|
827
|
+
// runs. Idempotent: only assigns MISSING shortIds/priorities, never
|
|
828
|
+
// overwrites existing ones.
|
|
829
|
+
await store.ensureShortIdsAndPriority().catch(() => null);
|
|
714
830
|
// Shared mutable reference — routes see the hub after it's created
|
|
715
831
|
const hubRef = { current: null };
|
|
716
832
|
// Default to the bundled web UI when the caller doesn't pass staticDir. Pass
|
package/dist/ws-hub.d.ts
CHANGED
|
@@ -25,6 +25,16 @@ export type WsEvent = {
|
|
|
25
25
|
} | {
|
|
26
26
|
type: "plan-rendered";
|
|
27
27
|
data: unknown;
|
|
28
|
+
} | {
|
|
29
|
+
type: "handoffUpdated";
|
|
30
|
+
data: {
|
|
31
|
+
phaseId: string;
|
|
32
|
+
};
|
|
33
|
+
} | {
|
|
34
|
+
type: "handoffCleared";
|
|
35
|
+
data: {
|
|
36
|
+
phaseId: string;
|
|
37
|
+
};
|
|
28
38
|
};
|
|
29
39
|
export declare class WsHub {
|
|
30
40
|
private wss;
|
package/dist/ws-hub.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws-hub.d.ts","sourceRoot":"","sources":["../src/ws-hub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"ws-hub.d.ts","sourceRoot":"","sources":["../src/ws-hub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3C;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAE1D,qBAAa,KAAK;IAChB,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,KAAK,CAAU;gBAEX,MAAM,EAAE,MAAM,EAAE,KAAK,UAAQ,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI;IA0CzE,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAa/B,KAAK,IAAI,IAAI;CASd"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-plan/server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.19-next.1",
|
|
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.
|
|
44
|
+
"@agent-plan/core": "0.2.19-next.1"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@types/ws": "^8.18.0"
|