@lumea-labs/orchestrator 0.1.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 (46) hide show
  1. package/README.md +21 -0
  2. package/dist/index.d.ts +21 -0
  3. package/dist/index.js +93 -0
  4. package/dist/lib/format.d.ts +3 -0
  5. package/dist/lib/format.js +9 -0
  6. package/dist/orchestrator-document.d.ts +37 -0
  7. package/dist/orchestrator-document.js +122 -0
  8. package/dist/plan-detail.d.ts +102 -0
  9. package/dist/plan-detail.js +385 -0
  10. package/dist/plan-graph.d.ts +39 -0
  11. package/dist/plan-graph.js +597 -0
  12. package/dist/plan-node-detail.d.ts +29 -0
  13. package/dist/plan-node-detail.js +346 -0
  14. package/dist/plan-task-detail.d.ts +76 -0
  15. package/dist/plan-task-detail.js +450 -0
  16. package/dist/plan-types.d.ts +85 -0
  17. package/dist/plan-types.js +51 -0
  18. package/dist/run-kanban-filter-menu.d.ts +24 -0
  19. package/dist/run-kanban-filter-menu.js +152 -0
  20. package/dist/run-kanban.d.ts +61 -0
  21. package/dist/run-kanban.js +234 -0
  22. package/dist/swarm-agent-badge.d.ts +15 -0
  23. package/dist/swarm-agent-badge.js +39 -0
  24. package/dist/swarm-run-activity.d.ts +39 -0
  25. package/dist/swarm-run-activity.js +289 -0
  26. package/dist/swarm-run-card.d.ts +22 -0
  27. package/dist/swarm-run-card.js +91 -0
  28. package/dist/swarm-run-detail.d.ts +45 -0
  29. package/dist/swarm-run-detail.js +559 -0
  30. package/dist/swarm-run-list.d.ts +22 -0
  31. package/dist/swarm-run-list.js +75 -0
  32. package/dist/swarm-run-row.d.ts +22 -0
  33. package/dist/swarm-run-row.js +125 -0
  34. package/dist/swarm-skeletons.d.ts +28 -0
  35. package/dist/swarm-skeletons.js +78 -0
  36. package/dist/swarm-status-bar.d.ts +15 -0
  37. package/dist/swarm-status-bar.js +79 -0
  38. package/dist/swarm-status-pill.d.ts +12 -0
  39. package/dist/swarm-status-pill.js +86 -0
  40. package/dist/swarm-timeline.d.ts +21 -0
  41. package/dist/swarm-timeline.js +414 -0
  42. package/dist/task-workspace-sidebar.d.ts +71 -0
  43. package/dist/task-workspace-sidebar.js +352 -0
  44. package/dist/types.d.ts +285 -0
  45. package/dist/types.js +44 -0
  46. package/package.json +41 -0
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @lumea-labs/orchestrator
2
+
3
+ Swarm + workflow primitives — SwarmProvider, RunCard / RunRow / RunDetail / RunKanban, PlanGraph (React Flow), PlanDetail.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @lumea-labs/orchestrator
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```tsx
14
+ import { /* … */ } from "@lumea-labs/orchestrator";
15
+ ```
16
+
17
+ See the [Lumea Agents repo](https://github.com/Lumea-Technologies/lumea-agents/tree/main/packages/orchestrator) for the full source and a playground example.
18
+
19
+ ## License
20
+
21
+ Apache-2.0
@@ -0,0 +1,21 @@
1
+ export { SwarmAdapter, SwarmAgentRef, SwarmArtifact, SwarmArtifactKind, SwarmCapabilities, SwarmCounts, SwarmEvaluation, SwarmLabels, SwarmRun, SwarmRunActivity, SwarmRunEvent, SwarmRunEventKind, SwarmRunStatus, SwarmStartInput, SwarmToolCall, WorkspaceMission, WorkspaceTask, WorkspaceTaskStatus, defaultSwarmLabels, deriveSwarmCapabilities } from './types.js';
2
+ export { SwarmContextValue, SwarmProvider, SwarmProviderProps, useSwarm } from './orchestrator-document.js';
3
+ export { Plan, PlanCheckpoint, PlanDelay, PlanDetailLabels, PlanGraphLabels, PlanQualityGate, PlanTask, PlanTaskRuntime, PlanTaskStatus, RunKanbanLabels, defaultPlanDetailLabels, defaultPlanGraphLabels, defaultRunKanbanLabels } from './plan-types.js';
4
+ export { PlanGraph, PlanGraphProps, PlanGraphTaskRef } from './plan-graph.js';
5
+ export { PlanDetail, PlanDetailBreakdown, PlanDetailBreakdownProps, PlanDetailGraph, PlanDetailGraphProps, PlanDetailHeader, PlanDetailHeaderProps, PlanDetailMasthead, PlanDetailMastheadProps, PlanDetailProps } from './plan-detail.js';
6
+ export { PlanTaskActionConfig, PlanTaskActions, PlanTaskConfirmFn, PlanTaskDetail, PlanTaskDetailProps, PlanTaskDetailVariant } from './plan-task-detail.js';
7
+ export { PlanCheckpointDetail, PlanCheckpointDetailProps, PlanDelayDetail, PlanDelayDetailProps, PlanQualityGateDetail, PlanQualityGateDetailProps } from './plan-node-detail.js';
8
+ export { RunKanban, RunKanbanFilters, RunKanbanFiltersProps, RunKanbanGroupBy, RunKanbanLaneSummary, RunKanbanProps, summariseRunKanbanLanes } from './run-kanban.js';
9
+ export { RunKanbanFilterMenu, RunKanbanFilterMenuProps } from './run-kanban-filter-menu.js';
10
+ export { SwarmStatusPill, SwarmStatusPillProps } from './swarm-status-pill.js';
11
+ export { SwarmAgentBadge, SwarmAgentBadgeProps } from './swarm-agent-badge.js';
12
+ export { SwarmRunCard, SwarmRunCardProps } from './swarm-run-card.js';
13
+ export { SwarmRunRow, SwarmRunRowProps } from './swarm-run-row.js';
14
+ export { SwarmRunList, SwarmRunListProps } from './swarm-run-list.js';
15
+ export { SwarmStatusBar, SwarmStatusBarProps } from './swarm-status-bar.js';
16
+ export { SwarmRunDetail, SwarmRunDetailProps, SwarmRunDetailVariant } from './swarm-run-detail.js';
17
+ export { BuildSwarmRunActivityOptions, SwarmRunActivityStream, SwarmRunActivityStreamProps, buildSwarmRunActivity } from './swarm-run-activity.js';
18
+ export { SwarmRunActivityStreamSkeleton, SwarmRunActivityStreamSkeletonProps, SwarmRunDetailSkeleton, SwarmRunDetailSkeletonProps } from './swarm-skeletons.js';
19
+ export { SwarmTimeline, SwarmTimelineProps } from './swarm-timeline.js';
20
+ export { PlanOnlyTaskShape, RenderLinkArgs, RenderLinkFn, TaskWorkspaceSidebar, TaskWorkspaceSidebarLabels, TaskWorkspaceSidebarProps, defaultTaskWorkspaceSidebarLabels } from './task-workspace-sidebar.js';
21
+ import 'react';
package/dist/index.js ADDED
@@ -0,0 +1,93 @@
1
+ import { defaultSwarmLabels, deriveSwarmCapabilities } from "./types";
2
+ import {
3
+ SwarmProvider,
4
+ useSwarm
5
+ } from "./orchestrator-document";
6
+ import {
7
+ defaultPlanGraphLabels,
8
+ defaultPlanDetailLabels,
9
+ defaultRunKanbanLabels
10
+ } from "./plan-types";
11
+ import { PlanGraph } from "./plan-graph";
12
+ import {
13
+ PlanDetail,
14
+ PlanDetailHeader,
15
+ PlanDetailMasthead,
16
+ PlanDetailGraph,
17
+ PlanDetailBreakdown
18
+ } from "./plan-detail";
19
+ import {
20
+ PlanTaskDetail
21
+ } from "./plan-task-detail";
22
+ import {
23
+ PlanCheckpointDetail,
24
+ PlanQualityGateDetail,
25
+ PlanDelayDetail
26
+ } from "./plan-node-detail";
27
+ import {
28
+ RunKanban,
29
+ RunKanbanFilters,
30
+ summariseRunKanbanLanes
31
+ } from "./run-kanban";
32
+ import {
33
+ RunKanbanFilterMenu
34
+ } from "./run-kanban-filter-menu";
35
+ import { SwarmStatusPill } from "./swarm-status-pill";
36
+ import { SwarmAgentBadge } from "./swarm-agent-badge";
37
+ import { SwarmRunCard } from "./swarm-run-card";
38
+ import { SwarmRunRow } from "./swarm-run-row";
39
+ import { SwarmRunList } from "./swarm-run-list";
40
+ import { SwarmStatusBar } from "./swarm-status-bar";
41
+ import {
42
+ SwarmRunDetail
43
+ } from "./swarm-run-detail";
44
+ import {
45
+ SwarmRunActivityStream,
46
+ buildSwarmRunActivity
47
+ } from "./swarm-run-activity";
48
+ import {
49
+ SwarmRunDetailSkeleton,
50
+ SwarmRunActivityStreamSkeleton
51
+ } from "./swarm-skeletons";
52
+ import { SwarmTimeline } from "./swarm-timeline";
53
+ import {
54
+ TaskWorkspaceSidebar,
55
+ defaultTaskWorkspaceSidebarLabels
56
+ } from "./task-workspace-sidebar";
57
+ export {
58
+ PlanCheckpointDetail,
59
+ PlanDelayDetail,
60
+ PlanDetail,
61
+ PlanDetailBreakdown,
62
+ PlanDetailGraph,
63
+ PlanDetailHeader,
64
+ PlanDetailMasthead,
65
+ PlanGraph,
66
+ PlanQualityGateDetail,
67
+ PlanTaskDetail,
68
+ RunKanban,
69
+ RunKanbanFilterMenu,
70
+ RunKanbanFilters,
71
+ SwarmAgentBadge,
72
+ SwarmProvider,
73
+ SwarmRunActivityStream,
74
+ SwarmRunActivityStreamSkeleton,
75
+ SwarmRunCard,
76
+ SwarmRunDetail,
77
+ SwarmRunDetailSkeleton,
78
+ SwarmRunList,
79
+ SwarmRunRow,
80
+ SwarmStatusBar,
81
+ SwarmStatusPill,
82
+ SwarmTimeline,
83
+ TaskWorkspaceSidebar,
84
+ buildSwarmRunActivity,
85
+ defaultPlanDetailLabels,
86
+ defaultPlanGraphLabels,
87
+ defaultRunKanbanLabels,
88
+ defaultSwarmLabels,
89
+ defaultTaskWorkspaceSidebarLabels,
90
+ deriveSwarmCapabilities,
91
+ summariseRunKanbanLanes,
92
+ useSwarm
93
+ };
@@ -0,0 +1,3 @@
1
+ declare function elapsedSeconds(startedAt: string | undefined, finishedAt: string | undefined, now: number): number;
2
+
3
+ export { elapsedSeconds };
@@ -0,0 +1,9 @@
1
+ function elapsedSeconds(startedAt, finishedAt, now) {
2
+ if (!startedAt) return 0;
3
+ const start = new Date(startedAt).getTime();
4
+ const end = finishedAt ? new Date(finishedAt).getTime() : now;
5
+ return Math.max(0, (end - start) / 1e3);
6
+ }
7
+ export {
8
+ elapsedSeconds
9
+ };
@@ -0,0 +1,37 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { SwarmRun, SwarmCounts, SwarmStartInput, SwarmCapabilities, SwarmLabels, SwarmAdapter } from './types.js';
4
+
5
+ interface SwarmContextValue {
6
+ state: {
7
+ runs: SwarmRun[];
8
+ counts: SwarmCounts;
9
+ isLoading: boolean;
10
+ /** Monotonic clock tick — bumped every second so child components
11
+ * can recompute live elapsed durations without owning a timer. */
12
+ now: number;
13
+ };
14
+ actions: {
15
+ refresh: () => Promise<void>;
16
+ start: (input: SwarmStartInput) => Promise<SwarmRun | null>;
17
+ cancel: (id: string) => Promise<void>;
18
+ retry: (id: string) => Promise<SwarmRun | null>;
19
+ cancelAll: () => Promise<void>;
20
+ retryFailed: () => Promise<void>;
21
+ };
22
+ capabilities: SwarmCapabilities;
23
+ meta: {
24
+ labels: SwarmLabels;
25
+ };
26
+ }
27
+ declare function useSwarm(): SwarmContextValue;
28
+ interface SwarmProviderProps {
29
+ adapter: SwarmAdapter;
30
+ labels?: Partial<SwarmLabels>;
31
+ /** Auto-fetch via `adapter.list()` on mount. Default `true`. */
32
+ autoLoad?: boolean;
33
+ children: ReactNode;
34
+ }
35
+ declare function SwarmProvider({ adapter, labels, autoLoad, children, }: SwarmProviderProps): react.JSX.Element;
36
+
37
+ export { type SwarmContextValue, SwarmProvider, type SwarmProviderProps, useSwarm };
@@ -0,0 +1,122 @@
1
+ "use client";
2
+ import {
3
+ createContext,
4
+ use,
5
+ useCallback,
6
+ useEffect,
7
+ useMemo,
8
+ useRef,
9
+ useState
10
+ } from "react";
11
+ import {
12
+ defaultSwarmLabels,
13
+ deriveSwarmCapabilities
14
+ } from "./types";
15
+ const Ctx = createContext(null);
16
+ function useSwarm() {
17
+ const ctx = use(Ctx);
18
+ if (!ctx) throw new Error("useSwarm must be used inside <SwarmProvider>");
19
+ return ctx;
20
+ }
21
+ function SwarmProvider({
22
+ adapter,
23
+ labels,
24
+ autoLoad = true,
25
+ children
26
+ }) {
27
+ const merged = useMemo(
28
+ () => ({ ...defaultSwarmLabels, ...labels }),
29
+ [labels]
30
+ );
31
+ const capabilities = useMemo(() => deriveSwarmCapabilities(adapter), [adapter]);
32
+ const adapterRef = useRef(adapter);
33
+ useEffect(() => {
34
+ adapterRef.current = adapter;
35
+ });
36
+ const [runs, setRuns] = useState([]);
37
+ const [isLoading, setIsLoading] = useState(false);
38
+ const [now, setNow] = useState(() => Date.now());
39
+ useEffect(() => {
40
+ const id = window.setInterval(() => setNow(Date.now()), 1e3);
41
+ return () => window.clearInterval(id);
42
+ }, []);
43
+ const refresh = useCallback(async () => {
44
+ if (!adapterRef.current.list) return;
45
+ setIsLoading(true);
46
+ try {
47
+ const next = await adapterRef.current.list();
48
+ setRuns(next);
49
+ } finally {
50
+ setIsLoading(false);
51
+ }
52
+ }, []);
53
+ useEffect(() => {
54
+ if (!adapterRef.current.subscribe) {
55
+ if (autoLoad) void refresh();
56
+ return;
57
+ }
58
+ const off = adapterRef.current.subscribe((next) => setRuns(next));
59
+ if (autoLoad) void refresh();
60
+ return off;
61
+ }, [autoLoad, refresh]);
62
+ const start = useCallback(
63
+ async (input) => {
64
+ if (!adapterRef.current.start) return null;
65
+ const run = await adapterRef.current.start(input);
66
+ setRuns((prev) => [run, ...prev.filter((r) => r.id !== run.id)]);
67
+ return run;
68
+ },
69
+ []
70
+ );
71
+ const cancel = useCallback(async (id) => {
72
+ if (!adapterRef.current.cancel) return;
73
+ await adapterRef.current.cancel(id);
74
+ }, []);
75
+ const retry = useCallback(
76
+ async (id) => {
77
+ if (!adapterRef.current.retry) return null;
78
+ const run = await adapterRef.current.retry(id);
79
+ setRuns((prev) => [run, ...prev.filter((r) => r.id !== run.id)]);
80
+ return run;
81
+ },
82
+ []
83
+ );
84
+ const cancelAll = useCallback(async () => {
85
+ if (!adapterRef.current.cancel) return;
86
+ const targets = runs.filter((r) => r.status === "running" || r.status === "pending");
87
+ await Promise.allSettled(targets.map((r) => adapterRef.current.cancel(r.id)));
88
+ }, [runs]);
89
+ const retryFailed = useCallback(async () => {
90
+ if (!adapterRef.current.retry) return;
91
+ const targets = runs.filter((r) => r.status === "failed");
92
+ await Promise.allSettled(targets.map((r) => adapterRef.current.retry(r.id)));
93
+ }, [runs]);
94
+ const counts = useMemo(() => {
95
+ const c = {
96
+ scheduled: 0,
97
+ pending: 0,
98
+ running: 0,
99
+ review: 0,
100
+ done: 0,
101
+ failed: 0,
102
+ cancelled: 0,
103
+ total: runs.length
104
+ };
105
+ for (const r of runs) c[r.status] += 1;
106
+ return c;
107
+ }, [runs]);
108
+ const value = useMemo(
109
+ () => ({
110
+ state: { runs, counts, isLoading, now },
111
+ actions: { refresh, start, cancel, retry, cancelAll, retryFailed },
112
+ capabilities,
113
+ meta: { labels: merged }
114
+ }),
115
+ [runs, counts, isLoading, now, refresh, start, cancel, retry, cancelAll, retryFailed, capabilities, merged]
116
+ );
117
+ return /* @__PURE__ */ React.createElement(Ctx, { value }, children);
118
+ }
119
+ export {
120
+ SwarmProvider,
121
+ useSwarm
122
+ };
@@ -0,0 +1,102 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { PlanGraphTaskRef } from './plan-graph.js';
4
+ import { Plan, PlanTaskRuntime, PlanDetailLabels, PlanGraphLabels } from './plan-types.js';
5
+ import { SwarmAgentRef } from './types.js';
6
+
7
+ interface PlanDetailHeaderProps {
8
+ plan: Plan;
9
+ runtimeByTitle?: Map<string, PlanTaskRuntime>;
10
+ /** Free-form brief / description band. */
11
+ briefSlot?: ReactNode;
12
+ /** Action dock — execute / abort / retry. */
13
+ actionsSlot?: ReactNode;
14
+ /** Leading slot in the header row — sits BEFORE the kicker. Use for
15
+ * back / re-open buttons that should mirror a sidebar toggle. */
16
+ headerLeading?: ReactNode;
17
+ /** Trailing slot in the header row (e.g. id pill). */
18
+ headerTrailing?: ReactNode;
19
+ labels?: Partial<PlanDetailLabels>;
20
+ className?: string;
21
+ }
22
+ declare function PlanDetailHeader({ plan, runtimeByTitle, briefSlot, actionsSlot, headerLeading, headerTrailing, labels, className, }: PlanDetailHeaderProps): react.JSX.Element;
23
+ interface PlanDetailMastheadProps {
24
+ plan: Plan;
25
+ runtimeByTitle?: Map<string, PlanTaskRuntime>;
26
+ briefSlot?: ReactNode;
27
+ actionsSlot?: ReactNode;
28
+ /** Leading slot — rendered before the kicker / title block. Use
29
+ * for back / re-open buttons that mirror a sidebar toggle. */
30
+ headerLeading?: ReactNode;
31
+ headerTrailing?: ReactNode;
32
+ labels?: Partial<PlanDetailLabels>;
33
+ className?: string;
34
+ }
35
+ declare function PlanDetailMasthead({ plan, runtimeByTitle, briefSlot, actionsSlot, headerLeading, headerTrailing, labels, className, }: PlanDetailMastheadProps): react.JSX.Element;
36
+ interface PlanDetailGraphProps {
37
+ plan: Plan;
38
+ runtimeByTitle?: Map<string, PlanTaskRuntime>;
39
+ agents?: SwarmAgentRef[];
40
+ /** Pixel height of the graph container. Default `720`. Ignored when
41
+ * `fillHeight` is `true`. */
42
+ graphHeight?: number;
43
+ /** When `true`, the graph stretches to fill the available vertical
44
+ * space inside a flex container — `flex-1 min-h-0` instead of a
45
+ * fixed height. Use this when the parent is a `flex flex-col` and
46
+ * you want the graph to grow as siblings collapse (e.g. the
47
+ * breakdown section toggling closed). */
48
+ fillHeight?: boolean;
49
+ onOpenTask?: (ref: PlanGraphTaskRef) => void;
50
+ /** Forwarded to `<PlanGraph/>` — the canonical id of the currently
51
+ * selected node (`task:<title>` | `cp:<name>` | `qg:<name>` |
52
+ * `dl:<name>`). When set, the matching node renders in the strong
53
+ * selected state. */
54
+ selectedNodeId?: string | null;
55
+ /** Forwarded to `<PlanGraph/>` — when true, the viewport animates
56
+ * to centre + zoom on the selected node. */
57
+ zoomToSelected?: boolean;
58
+ /** Open callback for non-task nodes — same shape on both sides. */
59
+ onOpenCheckpoint?: (name: string) => void;
60
+ onOpenGate?: (name: string) => void;
61
+ onOpenDelay?: (name: string) => void;
62
+ graphLabels?: Partial<PlanGraphLabels>;
63
+ className?: string;
64
+ }
65
+ declare function PlanDetailGraph({ plan, runtimeByTitle, agents, graphHeight, fillHeight, onOpenTask, onOpenCheckpoint, onOpenGate, onOpenDelay, selectedNodeId, zoomToSelected, graphLabels, className, }: PlanDetailGraphProps): react.JSX.Element;
66
+ interface PlanDetailBreakdownProps {
67
+ plan: Plan;
68
+ runtimeByTitle?: Map<string, PlanTaskRuntime>;
69
+ agents?: SwarmAgentRef[];
70
+ defaultOpen?: boolean;
71
+ /** Drop the chevron toggle and render the list always-open. */
72
+ alwaysOpen?: boolean;
73
+ onOpenTask?: (ref: PlanGraphTaskRef) => void;
74
+ labels?: Partial<PlanDetailLabels>;
75
+ className?: string;
76
+ }
77
+ declare function PlanDetailBreakdown({ plan, runtimeByTitle, agents, defaultOpen, alwaysOpen, onOpenTask, labels, className, }: PlanDetailBreakdownProps): react.JSX.Element;
78
+ interface PlanDetailProps {
79
+ plan: Plan;
80
+ /** Runtime status overlay, keyed by task title. */
81
+ runtimeByTitle?: Map<string, PlanTaskRuntime>;
82
+ agents?: SwarmAgentRef[];
83
+ /** Brief / description block above the graph. */
84
+ briefSlot?: ReactNode;
85
+ /** Action dock — execute / abort / retry. */
86
+ actionsSlot?: ReactNode;
87
+ /** Trailing slot in the header (e.g. status pill, mono id). */
88
+ headerTrailing?: ReactNode;
89
+ /** Hide the per-task breakdown panel below the graph. */
90
+ hideBreakdown?: boolean;
91
+ /** Whether the breakdown starts open. Default true. */
92
+ defaultBreakdownOpen?: boolean;
93
+ /** Pixel height for the graph area. Default 720. */
94
+ graphHeight?: number;
95
+ onOpenTask?: (ref: PlanGraphTaskRef) => void;
96
+ labels?: Partial<PlanDetailLabels>;
97
+ graphLabels?: Partial<PlanGraphLabels>;
98
+ className?: string;
99
+ }
100
+ declare function PlanDetail({ plan, runtimeByTitle, agents, briefSlot, actionsSlot, headerTrailing, hideBreakdown, defaultBreakdownOpen, graphHeight, onOpenTask, labels, graphLabels, className, }: PlanDetailProps): react.JSX.Element;
101
+
102
+ export { PlanDetail, PlanDetailBreakdown, type PlanDetailBreakdownProps, PlanDetailGraph, type PlanDetailGraphProps, PlanDetailHeader, type PlanDetailHeaderProps, PlanDetailMasthead, type PlanDetailMastheadProps, type PlanDetailProps };