@cadraos/sdk 0.3.9 → 0.3.11
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/chat/index.cjs +0 -4
- package/dist/chat/index.cjs.map +1 -1
- package/dist/chat/index.js +0 -4
- package/dist/chat/index.js.map +1 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/kanban/engine/index.cjs +0 -6
- package/dist/kanban/engine/index.cjs.map +1 -1
- package/dist/kanban/engine/index.js +0 -6
- package/dist/kanban/engine/index.js.map +1 -1
- package/dist/kanban/index.cjs +277 -41
- package/dist/kanban/index.cjs.map +1 -1
- package/dist/kanban/index.d.cts +110 -5
- package/dist/kanban/index.d.ts +110 -5
- package/dist/kanban/index.js +277 -41
- package/dist/kanban/index.js.map +1 -1
- package/dist/teams/index.cjs +0 -4
- package/dist/teams/index.cjs.map +1 -1
- package/dist/teams/index.js +0 -4
- package/dist/teams/index.js.map +1 -1
- package/package.json +1 -1
package/dist/kanban/index.js
CHANGED
|
@@ -258,9 +258,12 @@ function useKanbanBoard(options) {
|
|
|
258
258
|
]);
|
|
259
259
|
setBoard(nextBoard);
|
|
260
260
|
setCards(cardList.cards);
|
|
261
|
-
setSelectedCard(
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
setSelectedCard((prev) => {
|
|
262
|
+
if (!prev) return prev;
|
|
263
|
+
const next = cardList.cards.find((c) => c.id === prev.id);
|
|
264
|
+
if (!next) return prev;
|
|
265
|
+
return next.run ? next : { ...next, run: prev.run };
|
|
266
|
+
});
|
|
264
267
|
} catch (err) {
|
|
265
268
|
fail(err, "Failed to load board");
|
|
266
269
|
} finally {
|
|
@@ -275,9 +278,12 @@ function useKanbanBoard(options) {
|
|
|
275
278
|
]);
|
|
276
279
|
setBoard(nextBoard);
|
|
277
280
|
setCards(cardList.cards);
|
|
278
|
-
setSelectedCard(
|
|
279
|
-
|
|
280
|
-
|
|
281
|
+
setSelectedCard((prev) => {
|
|
282
|
+
if (!prev) return prev;
|
|
283
|
+
const next = cardList.cards.find((c) => c.id === prev.id);
|
|
284
|
+
if (!next) return prev;
|
|
285
|
+
return next.run ? next : { ...next, run: prev.run };
|
|
286
|
+
});
|
|
281
287
|
} catch {
|
|
282
288
|
}
|
|
283
289
|
}, [adapter]);
|
|
@@ -298,7 +304,7 @@ function useKanbanBoard(options) {
|
|
|
298
304
|
try {
|
|
299
305
|
const full = await adapter.getCard(cardId);
|
|
300
306
|
setSelectedCard(
|
|
301
|
-
(prev) => prev
|
|
307
|
+
(prev) => prev == null || prev.id === cardId ? full : prev
|
|
302
308
|
);
|
|
303
309
|
} catch (err) {
|
|
304
310
|
if (!known) fail(err, "Failed to open card");
|
|
@@ -407,6 +413,27 @@ function useKanbanBoard(options) {
|
|
|
407
413
|
},
|
|
408
414
|
[refresh]
|
|
409
415
|
);
|
|
416
|
+
const deleteCard = useCallback(
|
|
417
|
+
async (cardId) => {
|
|
418
|
+
if (!adapter.deleteCard) return false;
|
|
419
|
+
setError(null);
|
|
420
|
+
const prevCards = cards;
|
|
421
|
+
const prevSelected = selectedCard;
|
|
422
|
+
setCards((prev) => prev.filter((c) => c.id !== cardId));
|
|
423
|
+
setSelectedCard((prev) => prev && prev.id === cardId ? null : prev);
|
|
424
|
+
try {
|
|
425
|
+
await adapter.deleteCard(cardId);
|
|
426
|
+
void silentRefresh();
|
|
427
|
+
return true;
|
|
428
|
+
} catch (err) {
|
|
429
|
+
setCards(prevCards);
|
|
430
|
+
setSelectedCard(prevSelected);
|
|
431
|
+
fail(err, "Failed to delete card");
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
[adapter, cards, selectedCard, silentRefresh, fail]
|
|
436
|
+
);
|
|
410
437
|
return {
|
|
411
438
|
board,
|
|
412
439
|
lanes: board?.lanes ?? [],
|
|
@@ -422,6 +449,7 @@ function useKanbanBoard(options) {
|
|
|
422
449
|
createCard,
|
|
423
450
|
updateCard,
|
|
424
451
|
transitionCard,
|
|
452
|
+
deleteCard,
|
|
425
453
|
handleRunTerminal
|
|
426
454
|
};
|
|
427
455
|
}
|
|
@@ -2715,6 +2743,9 @@ function KanbanCard({
|
|
|
2715
2743
|
onClick,
|
|
2716
2744
|
selected,
|
|
2717
2745
|
dueState,
|
|
2746
|
+
draggable,
|
|
2747
|
+
onDragStart,
|
|
2748
|
+
onDragEnd,
|
|
2718
2749
|
className
|
|
2719
2750
|
}) {
|
|
2720
2751
|
const runStatus = card.run?.status;
|
|
@@ -2743,10 +2774,20 @@ function KanbanCard({
|
|
|
2743
2774
|
onClick: () => onClick?.(card),
|
|
2744
2775
|
"aria-pressed": selected,
|
|
2745
2776
|
"aria-busy": isWorking,
|
|
2777
|
+
draggable,
|
|
2778
|
+
onDragStart: draggable ? (e) => {
|
|
2779
|
+
e.dataTransfer.effectAllowed = "move";
|
|
2780
|
+
e.dataTransfer.setData("text/plain", card.id);
|
|
2781
|
+
onDragStart?.(card);
|
|
2782
|
+
} : void 0,
|
|
2783
|
+
onDragEnd: draggable ? () => onDragEnd?.() : void 0,
|
|
2746
2784
|
className: cn9(
|
|
2747
|
-
|
|
2785
|
+
// Solid card: fill + border + a faint token top-sheen (adapts to theme),
|
|
2786
|
+
// matching the host's cockpit cards (work-shell v2 visual pass).
|
|
2787
|
+
"relative w-full text-left rounded-xl border bg-card bg-gradient-to-b from-foreground/[0.03] to-transparent p-3 shadow-sm motion-safe:transition-shadow",
|
|
2748
2788
|
"hover:shadow-md hover:border-primary/40",
|
|
2749
2789
|
"focus:outline-none focus:ring-2 focus:ring-ring/50",
|
|
2790
|
+
draggable && "cursor-grab active:cursor-grabbing",
|
|
2750
2791
|
// The working card carries the SINGLE focal motion on the board (F11).
|
|
2751
2792
|
isWorking ? "border-info/60 ring-2 ring-info/40 animate-pulse" : selected ? "border-primary/60 ring-2 ring-primary/30" : "border-border",
|
|
2752
2793
|
className
|
|
@@ -2823,6 +2864,11 @@ function CapMeter({ count, cap, className }) {
|
|
|
2823
2864
|
}
|
|
2824
2865
|
);
|
|
2825
2866
|
}
|
|
2867
|
+
var AGENT_GROUPS = [
|
|
2868
|
+
{ kind: "cadra", label: "Cadra agents" },
|
|
2869
|
+
{ kind: "remote", label: "Your own agents" },
|
|
2870
|
+
{ kind: "human", label: "Teammates" }
|
|
2871
|
+
];
|
|
2826
2872
|
function AgentKindIcon({ kind }) {
|
|
2827
2873
|
const common = {
|
|
2828
2874
|
viewBox: "0 0 24 24",
|
|
@@ -2865,17 +2911,55 @@ function OnlineDot({ online }) {
|
|
|
2865
2911
|
}
|
|
2866
2912
|
);
|
|
2867
2913
|
}
|
|
2914
|
+
function RemoteBadge() {
|
|
2915
|
+
return /* @__PURE__ */ jsx("span", { className: "shrink-0 rounded-full border border-accent/40 bg-accent/15 px-1.5 py-px text-[10px] font-semibold leading-4 text-accent", children: "Remote" });
|
|
2916
|
+
}
|
|
2868
2917
|
function LaneAgentPicker({
|
|
2869
2918
|
selected,
|
|
2870
2919
|
options,
|
|
2871
2920
|
onSelect,
|
|
2872
2921
|
canEdit = true,
|
|
2873
2922
|
lockedReason,
|
|
2923
|
+
onEditAgent,
|
|
2874
2924
|
className
|
|
2875
2925
|
}) {
|
|
2876
2926
|
const [open, setOpen] = useState(false);
|
|
2927
|
+
const [placement, setPlacement] = useState(null);
|
|
2877
2928
|
const rootRef = useRef(null);
|
|
2929
|
+
const triggerRef = useRef(null);
|
|
2878
2930
|
const editable = canEdit && !!onSelect && (options?.length ?? 0) > 0;
|
|
2931
|
+
const openMenu = () => {
|
|
2932
|
+
const el = triggerRef.current;
|
|
2933
|
+
if (el && typeof window !== "undefined") {
|
|
2934
|
+
const rect = el.getBoundingClientRect();
|
|
2935
|
+
const vw = window.innerWidth || 0;
|
|
2936
|
+
const vh = window.innerHeight || 0;
|
|
2937
|
+
const margin = 8;
|
|
2938
|
+
const gap = 4;
|
|
2939
|
+
const desired = 288;
|
|
2940
|
+
const width = Math.max(
|
|
2941
|
+
Math.min(rect.width || 224, Math.max(vw - margin * 2, 160)),
|
|
2942
|
+
160
|
|
2943
|
+
);
|
|
2944
|
+
const left = Math.min(
|
|
2945
|
+
Math.max(rect.left, margin),
|
|
2946
|
+
Math.max(vw - width - margin, margin)
|
|
2947
|
+
);
|
|
2948
|
+
const spaceBelow = vh - rect.bottom - gap - margin;
|
|
2949
|
+
const spaceAbove = rect.top - gap - margin;
|
|
2950
|
+
const flipUp = spaceBelow < desired && spaceAbove > spaceBelow;
|
|
2951
|
+
const maxHeight = Math.max(
|
|
2952
|
+
Math.min(desired, flipUp ? spaceAbove : spaceBelow),
|
|
2953
|
+
120
|
|
2954
|
+
);
|
|
2955
|
+
setPlacement(
|
|
2956
|
+
flipUp ? { bottom: Math.max(vh - rect.top + gap, margin), left, width, maxHeight } : { top: rect.bottom + gap, left, width, maxHeight }
|
|
2957
|
+
);
|
|
2958
|
+
} else {
|
|
2959
|
+
setPlacement(null);
|
|
2960
|
+
}
|
|
2961
|
+
setOpen(true);
|
|
2962
|
+
};
|
|
2879
2963
|
useEffect(() => {
|
|
2880
2964
|
if (!open) return;
|
|
2881
2965
|
const onDocDown = (e) => {
|
|
@@ -2909,14 +2993,28 @@ function LaneAgentPicker({
|
|
|
2909
2993
|
}
|
|
2910
2994
|
),
|
|
2911
2995
|
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: displayLabel }),
|
|
2996
|
+
kind === "remote" && /* @__PURE__ */ jsx(RemoteBadge, {}),
|
|
2912
2997
|
/* @__PURE__ */ jsx(OnlineDot, { online: selected?.online })
|
|
2913
2998
|
] });
|
|
2999
|
+
const grouped = AGENT_GROUPS.map((group) => ({
|
|
3000
|
+
...group,
|
|
3001
|
+
items: (options ?? []).filter((opt) => (opt.kind ?? "cadra") === group.kind)
|
|
3002
|
+
})).filter((group) => group.items.length > 0);
|
|
3003
|
+
const menuStyle = placement ? {
|
|
3004
|
+
position: "fixed",
|
|
3005
|
+
top: placement.top,
|
|
3006
|
+
bottom: placement.bottom,
|
|
3007
|
+
left: placement.left,
|
|
3008
|
+
width: placement.width,
|
|
3009
|
+
maxHeight: placement.maxHeight
|
|
3010
|
+
} : void 0;
|
|
2914
3011
|
return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn9("relative mt-2 w-full", className), children: [
|
|
2915
3012
|
editable ? /* @__PURE__ */ jsxs(
|
|
2916
3013
|
"button",
|
|
2917
3014
|
{
|
|
3015
|
+
ref: triggerRef,
|
|
2918
3016
|
type: "button",
|
|
2919
|
-
onClick: () => setOpen(
|
|
3017
|
+
onClick: () => open ? setOpen(false) : openMenu(),
|
|
2920
3018
|
"aria-haspopup": "listbox",
|
|
2921
3019
|
"aria-expanded": open,
|
|
2922
3020
|
"aria-label": `Assigned agent: ${displayLabel}. Change`,
|
|
@@ -2994,47 +3092,106 @@ function LaneAgentPicker({
|
|
|
2994
3092
|
),
|
|
2995
3093
|
/* @__PURE__ */ jsx("span", { children: lockedReason })
|
|
2996
3094
|
] }),
|
|
2997
|
-
editable && open && /* @__PURE__ */
|
|
2998
|
-
"
|
|
3095
|
+
editable && open && /* @__PURE__ */ jsxs(
|
|
3096
|
+
"div",
|
|
2999
3097
|
{
|
|
3000
|
-
|
|
3001
|
-
"aria-label": "Assign an agent",
|
|
3098
|
+
style: menuStyle,
|
|
3002
3099
|
className: cn9(
|
|
3003
|
-
"
|
|
3004
|
-
"
|
|
3100
|
+
"flex flex-col overflow-hidden rounded-lg border border-border bg-popover shadow-lg",
|
|
3101
|
+
menuStyle ? "z-50" : "absolute z-20 mt-1 max-h-64 w-full"
|
|
3005
3102
|
),
|
|
3006
|
-
children:
|
|
3007
|
-
|
|
3008
|
-
|
|
3103
|
+
children: [
|
|
3104
|
+
/* @__PURE__ */ jsx(
|
|
3105
|
+
"ul",
|
|
3106
|
+
{
|
|
3107
|
+
role: "listbox",
|
|
3108
|
+
"aria-label": "Assign an agent",
|
|
3109
|
+
className: "min-h-0 flex-1 overflow-y-auto p-1",
|
|
3110
|
+
children: grouped.map((group) => /* @__PURE__ */ jsxs("li", { role: "presentation", children: [
|
|
3111
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 pb-1 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground", children: group.label }),
|
|
3112
|
+
/* @__PURE__ */ jsx("ul", { role: "group", "aria-label": group.label, children: group.items.map((opt) => {
|
|
3113
|
+
const isSelected = opt.id === selected?.id;
|
|
3114
|
+
const optKind = opt.kind ?? "cadra";
|
|
3115
|
+
return /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": isSelected, children: /* @__PURE__ */ jsxs(
|
|
3116
|
+
"button",
|
|
3117
|
+
{
|
|
3118
|
+
type: "button",
|
|
3119
|
+
onClick: () => {
|
|
3120
|
+
onSelect(opt.id);
|
|
3121
|
+
setOpen(false);
|
|
3122
|
+
},
|
|
3123
|
+
className: cn9(
|
|
3124
|
+
"flex min-h-11 w-full items-center gap-1.5 rounded-md px-2 text-left text-xs font-medium",
|
|
3125
|
+
"hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring/50",
|
|
3126
|
+
isSelected ? "text-primary" : "text-foreground"
|
|
3127
|
+
),
|
|
3128
|
+
children: [
|
|
3129
|
+
/* @__PURE__ */ jsx(
|
|
3130
|
+
"span",
|
|
3131
|
+
{
|
|
3132
|
+
className: cn9(
|
|
3133
|
+
"grid h-5 w-5 shrink-0 place-items-center rounded-full",
|
|
3134
|
+
optKind === "cadra" ? "bg-primary/15 text-primary" : "bg-secondary text-foreground"
|
|
3135
|
+
),
|
|
3136
|
+
children: /* @__PURE__ */ jsx(AgentKindIcon, { kind: optKind })
|
|
3137
|
+
}
|
|
3138
|
+
),
|
|
3139
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: opt.label }),
|
|
3140
|
+
optKind === "remote" && /* @__PURE__ */ jsx(RemoteBadge, {}),
|
|
3141
|
+
/* @__PURE__ */ jsx(OnlineDot, { online: opt.online }),
|
|
3142
|
+
isSelected && /* @__PURE__ */ jsx(
|
|
3143
|
+
"svg",
|
|
3144
|
+
{
|
|
3145
|
+
viewBox: "0 0 24 24",
|
|
3146
|
+
fill: "none",
|
|
3147
|
+
stroke: "currentColor",
|
|
3148
|
+
strokeWidth: 2,
|
|
3149
|
+
strokeLinecap: "round",
|
|
3150
|
+
strokeLinejoin: "round",
|
|
3151
|
+
"aria-hidden": true,
|
|
3152
|
+
className: "h-3.5 w-3.5 shrink-0",
|
|
3153
|
+
children: /* @__PURE__ */ jsx("path", { d: "M20 6L9 17l-5-5" })
|
|
3154
|
+
}
|
|
3155
|
+
)
|
|
3156
|
+
]
|
|
3157
|
+
}
|
|
3158
|
+
) }, opt.id);
|
|
3159
|
+
}) })
|
|
3160
|
+
] }, group.kind))
|
|
3161
|
+
}
|
|
3162
|
+
),
|
|
3163
|
+
onEditAgent && selected && /* @__PURE__ */ jsx("div", { className: "border-t border-border p-1", children: /* @__PURE__ */ jsxs(
|
|
3009
3164
|
"button",
|
|
3010
3165
|
{
|
|
3011
3166
|
type: "button",
|
|
3012
3167
|
onClick: () => {
|
|
3013
|
-
|
|
3168
|
+
onEditAgent(selected.id);
|
|
3014
3169
|
setOpen(false);
|
|
3015
3170
|
},
|
|
3016
3171
|
className: cn9(
|
|
3017
|
-
"flex min-h-11 w-full items-center gap-1.5 rounded-md px-2 text-left text-xs font-medium",
|
|
3018
|
-
"hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring/50"
|
|
3019
|
-
isSelected ? "text-primary" : "text-foreground"
|
|
3172
|
+
"flex min-h-11 w-full items-center gap-1.5 rounded-md px-2 text-left text-xs font-medium text-foreground",
|
|
3173
|
+
"hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring/50"
|
|
3020
3174
|
),
|
|
3021
3175
|
children: [
|
|
3022
3176
|
/* @__PURE__ */ jsx(
|
|
3023
|
-
"
|
|
3177
|
+
"svg",
|
|
3024
3178
|
{
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3179
|
+
viewBox: "0 0 24 24",
|
|
3180
|
+
fill: "none",
|
|
3181
|
+
stroke: "currentColor",
|
|
3182
|
+
strokeWidth: 2,
|
|
3183
|
+
strokeLinecap: "round",
|
|
3184
|
+
strokeLinejoin: "round",
|
|
3185
|
+
"aria-hidden": true,
|
|
3186
|
+
className: "h-3.5 w-3.5 shrink-0 text-muted-foreground",
|
|
3187
|
+
children: /* @__PURE__ */ jsx("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" })
|
|
3030
3188
|
}
|
|
3031
3189
|
),
|
|
3032
|
-
|
|
3033
|
-
/* @__PURE__ */ jsx(OnlineDot, { online: opt.online })
|
|
3190
|
+
"Edit this agent"
|
|
3034
3191
|
]
|
|
3035
3192
|
}
|
|
3036
|
-
) }
|
|
3037
|
-
|
|
3193
|
+
) })
|
|
3194
|
+
]
|
|
3038
3195
|
}
|
|
3039
3196
|
)
|
|
3040
3197
|
] });
|
|
@@ -3059,6 +3216,12 @@ function KanbanColumn({
|
|
|
3059
3216
|
count,
|
|
3060
3217
|
agentPicker,
|
|
3061
3218
|
canEditHandlers,
|
|
3219
|
+
draggableCards,
|
|
3220
|
+
dragActive,
|
|
3221
|
+
dropAllowed,
|
|
3222
|
+
onCardDragStart,
|
|
3223
|
+
onCardDragEnd,
|
|
3224
|
+
onLaneDrop,
|
|
3062
3225
|
className
|
|
3063
3226
|
}) {
|
|
3064
3227
|
const headerCount = count ?? cards.length;
|
|
@@ -3069,9 +3232,21 @@ function KanbanColumn({
|
|
|
3069
3232
|
return /* @__PURE__ */ jsxs(
|
|
3070
3233
|
"div",
|
|
3071
3234
|
{
|
|
3235
|
+
onDragOver: dropAllowed ? (e) => {
|
|
3236
|
+
e.preventDefault();
|
|
3237
|
+
e.dataTransfer.dropEffect = "move";
|
|
3238
|
+
} : void 0,
|
|
3239
|
+
onDrop: dropAllowed && onLaneDrop ? (e) => {
|
|
3240
|
+
e.preventDefault();
|
|
3241
|
+
onLaneDrop(lane);
|
|
3242
|
+
} : void 0,
|
|
3072
3243
|
className: cn9(
|
|
3073
|
-
"flex w-[85vw] max-w-sm snap-start shrink-0 flex-col rounded-xl bg-muted/40 border border-border sm:w-72 sm:max-w-none",
|
|
3244
|
+
"flex w-[85vw] max-w-sm snap-start shrink-0 flex-col rounded-xl bg-muted/40 border border-border transition sm:w-72 sm:max-w-none",
|
|
3074
3245
|
isScheduled && "border-border",
|
|
3246
|
+
// MV4 drag affordance: allowed targets glow; other lanes dim so the
|
|
3247
|
+
// valid drop zones read at a glance.
|
|
3248
|
+
dragActive && dropAllowed && "border-primary/60 ring-2 ring-primary/40 bg-primary/5",
|
|
3249
|
+
dragActive && !dropAllowed && "opacity-55",
|
|
3075
3250
|
className
|
|
3076
3251
|
),
|
|
3077
3252
|
children: [
|
|
@@ -3140,7 +3315,10 @@ function KanbanColumn({
|
|
|
3140
3315
|
card,
|
|
3141
3316
|
onClick: onCardClick,
|
|
3142
3317
|
selected: card.id === selectedCardId,
|
|
3143
|
-
dueState: dueStateFor(card, lane, now)
|
|
3318
|
+
dueState: dueStateFor(card, lane, now),
|
|
3319
|
+
draggable: draggableCards,
|
|
3320
|
+
onDragStart: onCardDragStart,
|
|
3321
|
+
onDragEnd: onCardDragEnd
|
|
3144
3322
|
},
|
|
3145
3323
|
card.id
|
|
3146
3324
|
)),
|
|
@@ -3300,6 +3478,8 @@ function KanbanBoard({
|
|
|
3300
3478
|
laneAgentPicker,
|
|
3301
3479
|
scheduleStatus,
|
|
3302
3480
|
focusCardId,
|
|
3481
|
+
renderCardDrawer,
|
|
3482
|
+
enableDrag,
|
|
3303
3483
|
className
|
|
3304
3484
|
}) {
|
|
3305
3485
|
const {
|
|
@@ -3314,6 +3494,7 @@ function KanbanBoard({
|
|
|
3314
3494
|
createCard,
|
|
3315
3495
|
updateCard,
|
|
3316
3496
|
transitionCard,
|
|
3497
|
+
deleteCard,
|
|
3317
3498
|
handleRunTerminal
|
|
3318
3499
|
} = useKanbanBoard({ adapter, onError, onCardCreated, pollIntervalMs });
|
|
3319
3500
|
const lastFocusedRef = useRef(void 0);
|
|
@@ -3358,6 +3539,44 @@ function KanbanBoard({
|
|
|
3358
3539
|
(cardId, toLane) => transitionCard({ cardId, targetLane: toLane }),
|
|
3359
3540
|
[transitionCard]
|
|
3360
3541
|
);
|
|
3542
|
+
const [dragging, setDragging] = useState(null);
|
|
3543
|
+
const draggingRef = useRef(null);
|
|
3544
|
+
const dropInFlightRef = useRef(null);
|
|
3545
|
+
const allowedDropLanes = useMemo(() => {
|
|
3546
|
+
if (!dragging || !board?.transitions) return /* @__PURE__ */ new Set();
|
|
3547
|
+
return new Set(
|
|
3548
|
+
board.transitions.filter((t) => t.fromLane === dragging.lane && t.manualAllowed).map((t) => t.toLane)
|
|
3549
|
+
);
|
|
3550
|
+
}, [dragging, board?.transitions]);
|
|
3551
|
+
const handleCardDragStart = useCallback((card) => {
|
|
3552
|
+
const d = { id: card.id, lane: card.lane };
|
|
3553
|
+
draggingRef.current = d;
|
|
3554
|
+
setDragging(d);
|
|
3555
|
+
}, []);
|
|
3556
|
+
const handleCardDragEnd = useCallback(() => {
|
|
3557
|
+
draggingRef.current = null;
|
|
3558
|
+
setDragging(null);
|
|
3559
|
+
}, []);
|
|
3560
|
+
const handleLaneDrop = useCallback(
|
|
3561
|
+
(lane) => {
|
|
3562
|
+
const cur = draggingRef.current;
|
|
3563
|
+
draggingRef.current = null;
|
|
3564
|
+
setDragging(null);
|
|
3565
|
+
if (!cur || lane.key === cur.lane) return;
|
|
3566
|
+
if (dropInFlightRef.current === cur.id) return;
|
|
3567
|
+
const allowed = (board?.transitions ?? []).some(
|
|
3568
|
+
(t) => t.fromLane === cur.lane && t.toLane === lane.key && t.manualAllowed
|
|
3569
|
+
);
|
|
3570
|
+
if (!allowed) return;
|
|
3571
|
+
dropInFlightRef.current = cur.id;
|
|
3572
|
+
void Promise.resolve(transitionCard({ cardId: cur.id, targetLane: lane.key })).finally(
|
|
3573
|
+
() => {
|
|
3574
|
+
if (dropInFlightRef.current === cur.id) dropInFlightRef.current = null;
|
|
3575
|
+
}
|
|
3576
|
+
);
|
|
3577
|
+
},
|
|
3578
|
+
[board?.transitions, transitionCard]
|
|
3579
|
+
);
|
|
3361
3580
|
const initialLaneKey = lanes.find((l) => !l.terminal)?.key ?? lanes[0]?.key;
|
|
3362
3581
|
const selectedLane = selectedCard ? lanes.find((l) => l.key === selectedCard.lane) : void 0;
|
|
3363
3582
|
const canAdvanceSelected = !!selectedLane && !selectedLane.terminal;
|
|
@@ -3378,12 +3597,32 @@ function KanbanBoard({
|
|
|
3378
3597
|
showCreate: enableCreate && lane.key === initialLaneKey,
|
|
3379
3598
|
count: laneCounts?.[lane.key],
|
|
3380
3599
|
agentPicker: laneAgentPicker?.(lane),
|
|
3381
|
-
canEditHandlers
|
|
3600
|
+
canEditHandlers,
|
|
3601
|
+
draggableCards: enableDrag && enableAdvance,
|
|
3602
|
+
dragActive: !!dragging,
|
|
3603
|
+
dropAllowed: !!dragging && dragging.lane !== lane.key && allowedDropLanes.has(lane.key),
|
|
3604
|
+
onCardDragStart: handleCardDragStart,
|
|
3605
|
+
onCardDragEnd: handleCardDragEnd,
|
|
3606
|
+
onLaneDrop: handleLaneDrop
|
|
3382
3607
|
},
|
|
3383
3608
|
lane.id ?? lane.key
|
|
3384
3609
|
))
|
|
3385
3610
|
] }),
|
|
3386
|
-
selectedCard &&
|
|
3611
|
+
selectedCard && (renderCardDrawer ? renderCardDrawer({
|
|
3612
|
+
card: selectedCard,
|
|
3613
|
+
adapter,
|
|
3614
|
+
lanes,
|
|
3615
|
+
transitions: enableAdvance ? board?.transitions : void 0,
|
|
3616
|
+
canAdvance: canAdvanceSelected,
|
|
3617
|
+
onClose: closeCard,
|
|
3618
|
+
onRetry: onRetryCard ? handleRetry : void 0,
|
|
3619
|
+
onUpdate: enableEdit ? handleUpdate : void 0,
|
|
3620
|
+
onAdvance: enableAdvance ? handleAdvance : void 0,
|
|
3621
|
+
onTransition: enableAdvance ? handleTransition : void 0,
|
|
3622
|
+
onDelete: adapter.deleteCard ? deleteCard : void 0,
|
|
3623
|
+
onRunTerminal: handleRunTerminal,
|
|
3624
|
+
onError
|
|
3625
|
+
}) : /* @__PURE__ */ jsx(
|
|
3387
3626
|
CardDrawer,
|
|
3388
3627
|
{
|
|
3389
3628
|
card: selectedCard,
|
|
@@ -3399,7 +3638,7 @@ function KanbanBoard({
|
|
|
3399
3638
|
onRunTerminal: handleRunTerminal,
|
|
3400
3639
|
onError
|
|
3401
3640
|
}
|
|
3402
|
-
)
|
|
3641
|
+
))
|
|
3403
3642
|
] })
|
|
3404
3643
|
] });
|
|
3405
3644
|
}
|
|
@@ -3424,6 +3663,7 @@ function composeAdapter(source, boardConfigUuid, version, cardSource) {
|
|
|
3424
3663
|
transitionCard(input) {
|
|
3425
3664
|
return cardSource.transitionCard(input);
|
|
3426
3665
|
},
|
|
3666
|
+
...cardSource.deleteCard ? { deleteCard: (id) => cardSource.deleteCard(id) } : {},
|
|
3427
3667
|
...cardSource.createRunStream ? { createRunStream: (id) => cardSource.createRunStream(id) } : {}
|
|
3428
3668
|
};
|
|
3429
3669
|
}
|
|
@@ -4797,7 +5037,6 @@ var AgentsAPI = class extends BaseResourceAPI {
|
|
|
4797
5037
|
super(http, "/api/v1/agents");
|
|
4798
5038
|
this.getStreamConfig = getStreamConfig;
|
|
4799
5039
|
}
|
|
4800
|
-
getStreamConfig;
|
|
4801
5040
|
// ===== LIST Operations =====
|
|
4802
5041
|
/**
|
|
4803
5042
|
* List all agents in the organization
|
|
@@ -5703,7 +5942,6 @@ var SessionsAPI = class extends BaseResourceAPI {
|
|
|
5703
5942
|
super(http, "/api/v1/sessions");
|
|
5704
5943
|
this.getStreamConfig = getStreamConfig;
|
|
5705
5944
|
}
|
|
5706
|
-
getStreamConfig;
|
|
5707
5945
|
// ===== LIST Operations =====
|
|
5708
5946
|
/**
|
|
5709
5947
|
* List all sessions in the organization
|
|
@@ -6023,7 +6261,6 @@ var KanbanAPI = class extends BaseResourceAPI {
|
|
|
6023
6261
|
super(http, "/api/v1/kanban");
|
|
6024
6262
|
this.getStreamConfig = getStreamConfig;
|
|
6025
6263
|
}
|
|
6026
|
-
getStreamConfig;
|
|
6027
6264
|
// ===== BOARD =====
|
|
6028
6265
|
/**
|
|
6029
6266
|
* Get the current org's board (lanes in declared order). Auto-provisions
|
|
@@ -6225,7 +6462,6 @@ var RemoteAgentsAPI = class extends BaseResourceAPI {
|
|
|
6225
6462
|
super(http, "/api/v1/remote-agents");
|
|
6226
6463
|
this.getStreamConfig = getStreamConfig;
|
|
6227
6464
|
}
|
|
6228
|
-
getStreamConfig;
|
|
6229
6465
|
/**
|
|
6230
6466
|
* List all remote agents in the organization
|
|
6231
6467
|
*
|