@axiom-lattice/gateway 4.6.1 → 4.8.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.
- package/dist/OrphanRecoveryRuntime-BEFILJMU.mjs +8 -0
- package/dist/RecoveryCallerDeps-6SJUYJ5S.mjs +8 -0
- package/dist/RecoveryCallerDeps-6SJUYJ5S.mjs.map +1 -0
- package/dist/{a2a-standard-PIOKEHPS.mjs → a2a-standard-PBYPNHOA.mjs} +59 -21
- package/dist/a2a-standard-PBYPNHOA.mjs.map +1 -0
- package/dist/{chunk-2POW27EI.mjs → chunk-7CG57LEF.mjs} +2 -2
- package/dist/{chunk-WKNZ7GBC.mjs → chunk-EXPERMZR.mjs} +1 -1
- package/dist/chunk-EXPERMZR.mjs.map +1 -0
- package/dist/{chunk-52SUWMOX.mjs → chunk-JUA3VJE7.mjs} +3 -2
- package/dist/chunk-JUA3VJE7.mjs.map +1 -0
- package/dist/chunk-NOXGKYUV.mjs +37 -0
- package/dist/chunk-NOXGKYUV.mjs.map +1 -0
- package/dist/{chunk-526UYVNQ.mjs → chunk-NPHK4SZ6.mjs} +4 -4
- package/dist/{chunk-TJAUXMYJ.mjs → chunk-URXZPI2F.mjs} +8 -1
- package/dist/chunk-URXZPI2F.mjs.map +1 -0
- package/dist/chunk-ZBTG3T7K.mjs +324 -0
- package/dist/chunk-ZBTG3T7K.mjs.map +1 -0
- package/dist/embed/{embed-page-AgentDetailSideApp-7NYLPLAX.js → embed-page-AgentDetailSideApp-NTLAFO5C.js} +1 -1
- package/dist/embed/{embed-page-AgentGovernanceWorkbench-LNGNSI7X.js → embed-page-AgentGovernanceWorkbench-QPVBOMLH.js} +1 -1
- package/dist/embed/{embed-page-MessageGraph-E6DZDT65.js → embed-page-MessageGraph-JAJGMYKH.js} +1 -1
- package/dist/embed/{embed-page-ReactChart-3VE7F5VJ.js → embed-page-ReactChart-WUG6TEAZ.js} +1 -1
- package/dist/embed/{embed-page-SkillFlow-XMMHEHQL.js → embed-page-SkillFlow-TSBZ4V2P.js} +1 -1
- package/dist/embed/{embed-page-TasksSideApp-QM5TZ7EG.js → embed-page-TasksSideApp-TJI22YGD.js} +1 -1
- package/dist/embed/{embed-page-TeamWorkspace-E7RFY3ZY.js → embed-page-TeamWorkspace-OJJLN5VI.js} +1 -1
- package/dist/embed/{embed-page-TopologyRuntimeView-DLPDUB7Z.js → embed-page-TopologyRuntimeView-ZFU4N6TV.js} +1 -1
- package/dist/embed/{embed-page-WorkflowAutomationView-FKSVOHHB.js → embed-page-WorkflowAutomationView-ALXV7VQQ.js} +1 -1
- package/dist/embed/{embed-page-chunk-I7PWCKAG.js → embed-page-chunk-DZQBVJ7Z.js} +1 -1
- package/dist/embed/{embed-page-chunk-WWTU55RX.js → embed-page-chunk-IPIJ2SG6.js} +1 -1
- package/dist/embed/{embed-page-chunk-KN7D66KL.js → embed-page-chunk-N22EGQAJ.js} +1 -1
- package/dist/embed/{embed-page-chunk-EXCJ42IB.js → embed-page-chunk-O72XBKQH.js} +2 -2
- package/dist/embed/{embed-page-chunk-U276WBDI.js → embed-page-chunk-QMVIL4BJ.js} +190 -185
- package/dist/embed/{embed-page-chunk-H6TK3FAR.js → embed-page-chunk-UT3WYBZH.js} +1 -1
- package/dist/embed/embed-page-chunk-YPNSOZYW.js +8 -0
- package/dist/embed/embed-page.js +1 -1
- package/dist/index.d.mts +362 -10
- package/dist/index.d.ts +362 -10
- package/dist/index.js +1693 -450
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +714 -154
- package/dist/index.mjs.map +1 -1
- package/dist/{open-AMEMJOFJ.mjs → open-UVKMONVE.mjs} +10 -9
- package/dist/open-UVKMONVE.mjs.map +1 -0
- package/dist/{open-exposure-I44Q4M3T.mjs → open-exposure-VU227IO3.mjs} +5 -5
- package/dist/{open-files-EJ6O2SGX.mjs → open-files-X3HXVEEM.mjs} +6 -6
- package/dist/{open-session-LBTCU3AE.mjs → open-session-2Y7XJJW2.mjs} +6 -6
- package/dist/{resources-DXPXAXEZ.mjs → resources-2L3KSUUU.mjs} +2 -2
- package/dist/sandboxOpenCredentialProvider-USIU7Z7H.mjs +275 -0
- package/dist/sandboxOpenCredentialProvider-USIU7Z7H.mjs.map +1 -0
- package/dist/{sandboxProvider-I3P66VXT.mjs → sandboxProvider-DUYWHYJN.mjs} +2 -2
- package/dist/sandboxProvider-DUYWHYJN.mjs.map +1 -0
- package/package.json +14 -8
- package/dist/a2a-standard-PIOKEHPS.mjs.map +0 -1
- package/dist/chunk-52SUWMOX.mjs.map +0 -1
- package/dist/chunk-TJAUXMYJ.mjs.map +0 -1
- package/dist/chunk-WKNZ7GBC.mjs.map +0 -1
- package/dist/embed/embed-page-chunk-HEMNMC4X.js +0 -7
- package/dist/open-AMEMJOFJ.mjs.map +0 -1
- /package/dist/{sandboxProvider-I3P66VXT.mjs.map → OrphanRecoveryRuntime-BEFILJMU.mjs.map} +0 -0
- /package/dist/{chunk-2POW27EI.mjs.map → chunk-7CG57LEF.mjs.map} +0 -0
- /package/dist/{chunk-526UYVNQ.mjs.map → chunk-NPHK4SZ6.mjs.map} +0 -0
- /package/dist/{open-exposure-I44Q4M3T.mjs.map → open-exposure-VU227IO3.mjs.map} +0 -0
- /package/dist/{open-files-EJ6O2SGX.mjs.map → open-files-X3HXVEEM.mjs.map} +0 -0
- /package/dist/{open-session-LBTCU3AE.mjs.map → open-session-2Y7XJJW2.mjs.map} +0 -0
- /package/dist/{resources-DXPXAXEZ.mjs.map → resources-2L3KSUUU.mjs.map} +0 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
// src/services/collaboration/OrphanRecoveryRuntime.ts
|
|
2
|
+
import {
|
|
3
|
+
createTaskLifecycleService,
|
|
4
|
+
reconcileAllTenantTaskRuns,
|
|
5
|
+
taskRunRegistry as taskRunRegistry2
|
|
6
|
+
} from "@axiom-lattice/core";
|
|
7
|
+
|
|
8
|
+
// src/services/collaboration/TopCallerRecovery.ts
|
|
9
|
+
import { ToolMessage } from "@langchain/core/messages";
|
|
10
|
+
import {
|
|
11
|
+
reconcileStaleTaskRuns,
|
|
12
|
+
taskRunRegistry
|
|
13
|
+
} from "@axiom-lattice/core";
|
|
14
|
+
function hasPendingInterrupts(state) {
|
|
15
|
+
return (state.tasks ?? []).some((t) => (t.interrupts?.length ?? 0) > 0);
|
|
16
|
+
}
|
|
17
|
+
function pendingTaskCalls(state) {
|
|
18
|
+
const messages = state.values?.messages ?? [];
|
|
19
|
+
const resolved = new Set(
|
|
20
|
+
messages.filter((m) => m.tool_call_id).map((m) => m.tool_call_id)
|
|
21
|
+
);
|
|
22
|
+
const calls = [];
|
|
23
|
+
for (const m of messages) {
|
|
24
|
+
const typed = m;
|
|
25
|
+
if (typeof typed.getType !== "function" || typed.getType() !== "ai") continue;
|
|
26
|
+
const toolCalls = m.tool_calls;
|
|
27
|
+
if (!Array.isArray(toolCalls)) continue;
|
|
28
|
+
for (const c of toolCalls) {
|
|
29
|
+
if (c.name !== "task" || !c.id || resolved.has(c.id)) continue;
|
|
30
|
+
const taskId = typeof c.args?.taskId === "string" ? c.args.taskId : void 0;
|
|
31
|
+
calls.push({ id: c.id, ...taskId ? { taskId } : {} });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return calls;
|
|
35
|
+
}
|
|
36
|
+
function outcome(task) {
|
|
37
|
+
if (task.status === "completed") {
|
|
38
|
+
return JSON.stringify({ success: true, taskId: task.id, result: task.result ?? "" });
|
|
39
|
+
}
|
|
40
|
+
if (task.status === "failed") {
|
|
41
|
+
return JSON.stringify({ success: false, code: "TASK_FAILED", retryable: false, taskId: task.id, error: task.failureReason ?? "" });
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify({
|
|
44
|
+
success: false,
|
|
45
|
+
code: "TASK_INTERRUPTED",
|
|
46
|
+
retryable: false,
|
|
47
|
+
taskId: task.id,
|
|
48
|
+
error: "Run ended before completion; the task is interrupted and awaiting a decision."
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function backfillTopCallerGroup(tasks, top, deps) {
|
|
52
|
+
const registry = deps.registry ?? taskRunRegistry;
|
|
53
|
+
const results = [];
|
|
54
|
+
const eligible = [];
|
|
55
|
+
for (const task of tasks) {
|
|
56
|
+
if (!task.context?.caller_thread_id) {
|
|
57
|
+
results.push({ id: task.id, reason: "skipped:no_caller_link" });
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (registry.isLive(task.id) || deps.isTaskLive && await deps.isTaskLive(task)) {
|
|
61
|
+
results.push({ id: task.id, reason: "skipped:live" });
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
eligible.push(task);
|
|
65
|
+
}
|
|
66
|
+
if (eligible.length === 0) return results;
|
|
67
|
+
const target = await deps.callerFor(top, eligible[0].tenantId);
|
|
68
|
+
if (!target) {
|
|
69
|
+
return [...results, ...eligible.map((task) => ({ id: task.id, reason: "skipped:no_caller_client" }))];
|
|
70
|
+
}
|
|
71
|
+
const state = await target.client.getState(target.config);
|
|
72
|
+
if (hasPendingInterrupts(state)) {
|
|
73
|
+
return [...results, ...eligible.map((task) => ({ id: task.id, reason: "skipped:hitl" }))];
|
|
74
|
+
}
|
|
75
|
+
const nodeName = (state.tasks ?? [])[0]?.name;
|
|
76
|
+
if (!nodeName) {
|
|
77
|
+
return [...results, ...eligible.map((task) => ({ id: task.id, reason: "skipped:no_pending_node" }))];
|
|
78
|
+
}
|
|
79
|
+
const calls = pendingTaskCalls(state);
|
|
80
|
+
const matched = [];
|
|
81
|
+
for (const task of eligible) {
|
|
82
|
+
const call = calls.find((candidate) => candidate.taskId === task.id);
|
|
83
|
+
if (!call) {
|
|
84
|
+
results.push({ id: task.id, reason: "skipped:no_pending_task_call" });
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
matched.push({ task, call });
|
|
88
|
+
}
|
|
89
|
+
if (matched.length === 0) return results;
|
|
90
|
+
await target.client.updateState(target.config, {
|
|
91
|
+
messages: matched.map(({ task, call }) => new ToolMessage({ content: outcome(task), tool_call_id: call.id, name: "task" }))
|
|
92
|
+
}, nodeName);
|
|
93
|
+
await deps.resume(target.client, target.config, target.agent);
|
|
94
|
+
return [...results, ...matched.map(({ task }) => ({ id: task.id, reason: "recovered" }))];
|
|
95
|
+
}
|
|
96
|
+
async function recoverTopCaller(task, top, deps) {
|
|
97
|
+
if (!task.context?.caller_thread_id) return "skipped:no_caller_link";
|
|
98
|
+
if (task.context.caller_thread_id !== top.threadId) return "skipped:middle";
|
|
99
|
+
const [first] = await backfillTopCallerGroup([task], top, deps);
|
|
100
|
+
return first?.reason ?? "skipped:no_pending_task_call";
|
|
101
|
+
}
|
|
102
|
+
async function recoverTask(task, deps) {
|
|
103
|
+
if (task.status !== "in_progress") {
|
|
104
|
+
return { kind: "skipped", reason: "not_in_progress" };
|
|
105
|
+
}
|
|
106
|
+
const registry = deps.registry ?? taskRunRegistry;
|
|
107
|
+
if (registry.isLive(task.id) || deps.isTaskLive && await deps.isTaskLive(task)) {
|
|
108
|
+
return { kind: "skipped", reason: "live" };
|
|
109
|
+
}
|
|
110
|
+
const { convergedTasks } = await reconcileStaleTaskRuns({
|
|
111
|
+
tasks: [task],
|
|
112
|
+
actor: "system:on-demand-recovery",
|
|
113
|
+
lifecycle: deps.lifecycle,
|
|
114
|
+
...deps.registry ? { registry: deps.registry } : {},
|
|
115
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
116
|
+
});
|
|
117
|
+
const converged = convergedTasks[0];
|
|
118
|
+
if (!converged) {
|
|
119
|
+
return { kind: "skipped", reason: "convergence_failed" };
|
|
120
|
+
}
|
|
121
|
+
const top = resolveTopCaller(converged, deps.orphans ?? [converged]);
|
|
122
|
+
if (!top) {
|
|
123
|
+
return { kind: "skipped", reason: "no_top_caller" };
|
|
124
|
+
}
|
|
125
|
+
if (converged.context?.caller_thread_id !== top.threadId) {
|
|
126
|
+
return { kind: "skipped", reason: "middle" };
|
|
127
|
+
}
|
|
128
|
+
const reason = await recoverTopCaller(converged, top, {
|
|
129
|
+
callerFor: deps.callerFor,
|
|
130
|
+
resume: deps.resume,
|
|
131
|
+
...deps.registry ? { registry: deps.registry } : {},
|
|
132
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
133
|
+
});
|
|
134
|
+
if (reason === "recovered") return { kind: "recovered" };
|
|
135
|
+
if (reason === "skipped:no_pending_task_call") return { kind: "converged_no_call" };
|
|
136
|
+
return { kind: "skipped", reason: reason.replace(/^skipped:/, "") };
|
|
137
|
+
}
|
|
138
|
+
function resolveTopCaller(task, orphans) {
|
|
139
|
+
const tenantId = task.tenantId;
|
|
140
|
+
const runThreadToTask = new Map(
|
|
141
|
+
orphans.map((orphan) => [`${orphan.tenantId}:${orphan.context?.thread_id}`, orphan])
|
|
142
|
+
);
|
|
143
|
+
let threadId = task.context?.caller_thread_id;
|
|
144
|
+
let assistantId = task.context?.caller_assistant_id;
|
|
145
|
+
const seen = /* @__PURE__ */ new Set();
|
|
146
|
+
while (threadId) {
|
|
147
|
+
const scopeKey = `${tenantId}:${threadId}`;
|
|
148
|
+
if (!runThreadToTask.has(scopeKey) || seen.has(scopeKey)) break;
|
|
149
|
+
seen.add(scopeKey);
|
|
150
|
+
const parent = runThreadToTask.get(scopeKey);
|
|
151
|
+
threadId = parent.context?.caller_thread_id;
|
|
152
|
+
assistantId = parent.context?.caller_assistant_id;
|
|
153
|
+
}
|
|
154
|
+
return threadId ? { threadId, ...assistantId ? { assistantId } : {} } : void 0;
|
|
155
|
+
}
|
|
156
|
+
async function runOrphanRecovery(deps) {
|
|
157
|
+
let convergedTasks;
|
|
158
|
+
try {
|
|
159
|
+
({ convergedTasks } = await deps.reconcile());
|
|
160
|
+
} catch (error) {
|
|
161
|
+
deps.log.warn("Task orphan recovery reconcile failed", {
|
|
162
|
+
error: error instanceof Error ? error.message : String(error)
|
|
163
|
+
});
|
|
164
|
+
return { recovered: [], skipped: ["reconcile:error"] };
|
|
165
|
+
}
|
|
166
|
+
const orphans = convergedTasks;
|
|
167
|
+
const recovered = [];
|
|
168
|
+
const skipped = [];
|
|
169
|
+
const groups = /* @__PURE__ */ new Map();
|
|
170
|
+
for (const task of orphans) {
|
|
171
|
+
const top = resolveTopCaller(task, orphans);
|
|
172
|
+
if (!top) {
|
|
173
|
+
skipped.push(`${task.id}:skipped:no_top_caller`);
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (task.context?.caller_thread_id !== top.threadId) {
|
|
177
|
+
skipped.push(`${task.id}:skipped:middle`);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
const key = `${task.tenantId}:${top.threadId}`;
|
|
181
|
+
const group = groups.get(key);
|
|
182
|
+
if (group) group.tasks.push(task);
|
|
183
|
+
else groups.set(key, { top, tasks: [task] });
|
|
184
|
+
}
|
|
185
|
+
for (const { top, tasks } of groups.values()) {
|
|
186
|
+
try {
|
|
187
|
+
const results = await backfillTopCallerGroup(tasks, top, {
|
|
188
|
+
callerFor: deps.callerFor,
|
|
189
|
+
resume: deps.resume,
|
|
190
|
+
...deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}
|
|
191
|
+
});
|
|
192
|
+
for (const { id, reason } of results) {
|
|
193
|
+
(reason === "recovered" ? recovered : skipped).push(`${id}:${reason}`);
|
|
194
|
+
}
|
|
195
|
+
} catch (error) {
|
|
196
|
+
for (const task of tasks) skipped.push(`${task.id}:error`);
|
|
197
|
+
deps.log.warn("Task orphan recovery group failed", {
|
|
198
|
+
threadId: top.threadId,
|
|
199
|
+
error: error instanceof Error ? error.message : String(error)
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
deps.log.info("Task orphan recovery complete", { recovered, skipped });
|
|
204
|
+
return { recovered, skipped };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/services/collaboration/projectTaskScope.ts
|
|
208
|
+
function isProjectLifecycleTask(task) {
|
|
209
|
+
const source = task.context?.source;
|
|
210
|
+
return typeof task.workspaceId === "string" && task.workspaceId.length > 0 && typeof task.projectId === "string" && task.projectId.length > 0 && (source === "project_room" || source === "project_task" || source === "user");
|
|
211
|
+
}
|
|
212
|
+
function isRosterExemptProject(project) {
|
|
213
|
+
return project?.kind === "public";
|
|
214
|
+
}
|
|
215
|
+
function resolveTaskOwnerMembership(task, project, room, membership) {
|
|
216
|
+
const active = membership && membership.status === "active" && membership.tenantId === task.tenantId && membership.workspaceId === task.workspaceId && membership.projectId === task.projectId && membership.assistantId === task.ownerId && membership.roomId === room.id;
|
|
217
|
+
if (active) return membership;
|
|
218
|
+
if (!isRosterExemptProject(project)) return void 0;
|
|
219
|
+
return syntheticPublicProjectOwnerMembership(task, room);
|
|
220
|
+
}
|
|
221
|
+
function syntheticPublicProjectOwnerMembership(task, room) {
|
|
222
|
+
const threadId = typeof task.context?.thread_id === "string" && task.context.thread_id.length > 0 ? task.context.thread_id : task.ownerId;
|
|
223
|
+
return {
|
|
224
|
+
id: `public-project-owner:${task.projectId}:${task.ownerId}`,
|
|
225
|
+
tenantId: task.tenantId,
|
|
226
|
+
workspaceId: task.workspaceId,
|
|
227
|
+
projectId: task.projectId,
|
|
228
|
+
roomId: room.id,
|
|
229
|
+
assistantId: task.ownerId,
|
|
230
|
+
role: "specialist",
|
|
231
|
+
title: task.ownerId,
|
|
232
|
+
mentionName: task.ownerId,
|
|
233
|
+
status: "active",
|
|
234
|
+
roomThreadId: threadId,
|
|
235
|
+
joinedAt: task.createdAt,
|
|
236
|
+
updatedAt: task.updatedAt
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/services/collaboration/taskRunLiveness.ts
|
|
241
|
+
import {
|
|
242
|
+
storeLatticeManager,
|
|
243
|
+
taskRunLeaseKey,
|
|
244
|
+
threadRunLeaseKey
|
|
245
|
+
} from "@axiom-lattice/core";
|
|
246
|
+
function createTaskRunLiveness() {
|
|
247
|
+
try {
|
|
248
|
+
storeLatticeManager.getStoreLattice("default", "lease");
|
|
249
|
+
} catch {
|
|
250
|
+
return void 0;
|
|
251
|
+
}
|
|
252
|
+
return async (task) => {
|
|
253
|
+
try {
|
|
254
|
+
const store = storeLatticeManager.getStoreLattice("default", "lease").store;
|
|
255
|
+
if (await store.get(taskRunLeaseKey(task.id))) return true;
|
|
256
|
+
const threadId = typeof task.context?.thread_id === "string" ? task.context.thread_id : void 0;
|
|
257
|
+
if (threadId && task.ownerId) {
|
|
258
|
+
if (await store.get(threadRunLeaseKey(task.tenantId, task.ownerId, threadId))) return true;
|
|
259
|
+
}
|
|
260
|
+
return false;
|
|
261
|
+
} catch {
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/services/collaboration/OrphanRecoveryRuntime.ts
|
|
268
|
+
function createOrphanRecoveryRuntime(deps) {
|
|
269
|
+
const lifecycle = deps.lifecycle ?? createTaskLifecycleService({
|
|
270
|
+
taskStore: deps.taskStore,
|
|
271
|
+
workItemStore: deps.workItemStore
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
async recoverAll() {
|
|
275
|
+
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
276
|
+
return runOrphanRecovery({
|
|
277
|
+
reconcile: () => reconcileAllTenantTaskRuns({
|
|
278
|
+
actor: "system:orphan-recovery",
|
|
279
|
+
tenantStore: {
|
|
280
|
+
listTenants: async () => (await deps.tenantStore.getAllTenants()).map((tenant) => ({ id: tenant.id }))
|
|
281
|
+
},
|
|
282
|
+
taskStore: deps.taskStore,
|
|
283
|
+
lifecycle,
|
|
284
|
+
include: (t) => !isProjectLifecycleTask(t),
|
|
285
|
+
...isTaskLive ? { isTaskLive } : {}
|
|
286
|
+
}),
|
|
287
|
+
callerFor: deps.callerFor,
|
|
288
|
+
resume: deps.resume,
|
|
289
|
+
...isTaskLive ? { isTaskLive } : {},
|
|
290
|
+
log: deps.log
|
|
291
|
+
});
|
|
292
|
+
},
|
|
293
|
+
async recoverTask(input) {
|
|
294
|
+
const task = await deps.taskStore.getById(input.tenantId, input.taskId);
|
|
295
|
+
if (!task) return { kind: "skipped", reason: "not_found" };
|
|
296
|
+
if (isProjectLifecycleTask(task)) {
|
|
297
|
+
return { kind: "skipped", reason: "project_task" };
|
|
298
|
+
}
|
|
299
|
+
const orphans = await deps.taskStore.list({ tenantId: input.tenantId, status: "in_progress" });
|
|
300
|
+
const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();
|
|
301
|
+
return recoverTask(task, {
|
|
302
|
+
lifecycle,
|
|
303
|
+
registry: taskRunRegistry2,
|
|
304
|
+
orphans,
|
|
305
|
+
callerFor: deps.callerFor,
|
|
306
|
+
resume: deps.resume,
|
|
307
|
+
...isTaskLive ? { isTaskLive } : {}
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export {
|
|
314
|
+
isProjectLifecycleTask,
|
|
315
|
+
isRosterExemptProject,
|
|
316
|
+
resolveTaskOwnerMembership,
|
|
317
|
+
recoverTopCaller,
|
|
318
|
+
recoverTask,
|
|
319
|
+
resolveTopCaller,
|
|
320
|
+
runOrphanRecovery,
|
|
321
|
+
createTaskRunLiveness,
|
|
322
|
+
createOrphanRecoveryRuntime
|
|
323
|
+
};
|
|
324
|
+
//# sourceMappingURL=chunk-ZBTG3T7K.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/services/collaboration/OrphanRecoveryRuntime.ts","../src/services/collaboration/TopCallerRecovery.ts","../src/services/collaboration/projectTaskScope.ts","../src/services/collaboration/taskRunLiveness.ts"],"sourcesContent":["/**\n * Shared orphan-recovery runtime: the startup sweep and the on-demand\n * single-task entry point share one dependency shape and one lifecycle.\n *\n * @remarks\n * `recoverAll()` is the behavior-preserving move of the gateway startup block\n * (reconcile every tenant's orphaned ordinary tasks, then backfill the\n * top-level caller). `recoverTask()` is the A-lite on-demand entry: no HTTP\n * route, just a programmatic call used by the `task:recover` CLI/script.\n */\nimport type { TaskStore, TaskWorkItemStore, TenantStore } from \"@axiom-lattice/protocols\";\nimport {\n createTaskLifecycleService,\n reconcileAllTenantTaskRuns,\n taskRunRegistry,\n type TaskLifecycleService,\n} from \"@axiom-lattice/core\";\nimport {\n recoverTask as recoverSingleTask,\n runOrphanRecovery,\n type RecoverTaskResult,\n type TopCallerRecoveryDeps,\n} from \"./TopCallerRecovery\";\nimport { isProjectLifecycleTask } from \"./projectTaskScope\";\nimport { createTaskRunLiveness, type TaskLivenessProbe } from \"./taskRunLiveness\";\n\n/** Dependencies shared by the startup sweep and the single-task entry. */\nexport interface OrphanRecoveryRuntimeDeps {\n /** Task store used to enumerate tenants' orphans and read one task by id. */\n taskStore: TaskStore;\n /** Work-item store used to build the lifecycle when `lifecycle` is omitted. */\n workItemStore: TaskWorkItemStore;\n /** Tenant store supplying `getAllTenants()` for the startup sweep. */\n tenantStore: Pick<TenantStore, \"getAllTenants\">;\n /** Lifecycle used to converge orphans (built from the stores when omitted). */\n lifecycle?: Pick<TaskLifecycleService, \"failTask\">;\n /** Resolve a caller's agent client + config from the resolved top caller. */\n callerFor: TopCallerRecoveryDeps[\"callerFor\"];\n /** Resume the continuation (tests can call client.invoke(null, config)). */\n resume: TopCallerRecoveryDeps[\"resume\"];\n /**\n * Cross-replica liveness probe; defaults to the shared cross-replica probe\n * ({@link createTaskRunLiveness()}); inherit it unless a test injects one.\n */\n isTaskLive?: TaskLivenessProbe;\n /** Structured logger. */\n log: { info(msg: string, ctx: Record<string, unknown>): void; warn(msg: string, ctx: Record<string, unknown>): void };\n}\n\n/** Entry points returned by {@link createOrphanRecoveryRuntime}. */\nexport interface OrphanRecoveryRuntime {\n /** Startup/interval sweep over every tenant's orphaned ordinary tasks. */\n recoverAll(): Promise<{ recovered: string[]; skipped: string[] }>;\n /**\n * On-demand recovery of exactly one task within one tenant.\n *\n * @remarks Offline/maintenance: run when the Gateway is stopped, or from the\n * Gateway process. The `live` guard reads the process-local task registry and,\n * when a lease store is registered, also consults the cross-replica liveness\n * probe so a run held by another process is not converged. Governed Project\n * tasks are refused (`skipped:project_task`) so this never bypasses their\n * managed runtime.\n */\n recoverTask(input: { tenantId: string; taskId: string }): Promise<RecoverTaskResult>;\n}\n\n/**\n * Builds the shared orphan-recovery runtime.\n *\n * @param deps Task/work-item/tenant stores, optional lifecycle, caller\n * resolver, resume hook, and logger.\n * @returns `recoverAll()` (startup sweep) and `recoverTask()` (on-demand).\n * @remarks\n * Governed Project tasks are excluded from `recoverAll()` (they have their own\n * observer-based reconciliation) and from `recoverTask()`\n * (`skipped:project_task`), so the on-demand entry can never bypass the managed\n * Project runtime. `recoverTask()` delegates to {@link recoverSingleTask} with\n * the shared lifecycle, the process-local live-run registry, and the\n * cross-replica liveness probe (built from the shared `\"lease\"` store unless\n * `isTaskLive` is supplied), so it does not converge a task a live run still\n * holds — in this process or a peer replica. The liveness probe is advisory: a\n * benign race exists between the probe read and `failTask` (no\n * fencing/heartbeat support yet).\n *\n * @example\n * ```ts\n * const runtime = createOrphanRecoveryRuntime({ taskStore, workItemStore, tenantStore, callerFor, resume, log });\n * await runtime.recoverAll();\n * const outcome = await runtime.recoverTask({ tenantId, taskId });\n * ```\n */\nexport function createOrphanRecoveryRuntime(\n deps: OrphanRecoveryRuntimeDeps,\n): OrphanRecoveryRuntime {\n const lifecycle = deps.lifecycle ?? createTaskLifecycleService({\n taskStore: deps.taskStore,\n workItemStore: deps.workItemStore,\n });\n\n return {\n async recoverAll() {\n const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();\n return runOrphanRecovery({\n reconcile: () => reconcileAllTenantTaskRuns({\n actor: \"system:orphan-recovery\",\n tenantStore: {\n listTenants: async () => (await deps.tenantStore.getAllTenants()).map((tenant) => ({ id: tenant.id })),\n },\n taskStore: deps.taskStore,\n lifecycle,\n include: (t) => !isProjectLifecycleTask(t),\n ...(isTaskLive ? { isTaskLive } : {}),\n }),\n callerFor: deps.callerFor,\n resume: deps.resume,\n ...(isTaskLive ? { isTaskLive } : {}),\n log: deps.log,\n });\n },\n\n async recoverTask(input) {\n const task = await deps.taskStore.getById(input.tenantId, input.taskId);\n if (!task) return { kind: \"skipped\", reason: \"not_found\" };\n if (isProjectLifecycleTask(task)) {\n return { kind: \"skipped\", reason: \"project_task\" };\n }\n const orphans = await deps.taskStore.list({ tenantId: input.tenantId, status: \"in_progress\" });\n const isTaskLive = deps.isTaskLive ?? createTaskRunLiveness();\n return recoverSingleTask(task, {\n lifecycle,\n registry: taskRunRegistry,\n orphans,\n callerFor: deps.callerFor,\n resume: deps.resume,\n ...(isTaskLive ? { isTaskLive } : {}),\n });\n },\n };\n}\n","/**\n * Collapse recovery: backfill the top-level caller of converged orphan tasks.\n *\n * @remarks Only direct children of the top-level caller are backfilled; middle\n * task runs are frozen by the collapse design. Four guards: A skip a caller\n * with a pending interrupt (HITL), B skip live tasks (process-local registry\n * OR the optional cross-replica liveness probe), C derive the tool node name\n * from state, D use the task's real terminal state.\n */\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { TaskItem } from \"@axiom-lattice/protocols\";\nimport {\n reconcileStaleTaskRuns,\n taskRunRegistry,\n type TaskLifecycleService,\n type TaskRunRegistry,\n} from \"@axiom-lattice/core\";\nimport { type TaskLivenessProbe } from \"./taskRunLiveness\";\n\n/** Minimal caller-graph client surface used by recovery. */\nexport interface RecoveryCallerClient {\n getState(config: unknown): Promise<unknown>;\n updateState(config: unknown, values: unknown, asNode?: string): Promise<unknown>;\n invoke(input: unknown, config: unknown): Promise<unknown>;\n}\n\nexport interface TopCallerRecoveryDeps {\n /**\n * Resolve a caller's agent client + config from the resolved top caller.\n *\n * @param top The resolved top-level caller thread + assistant.\n * @param tenantId The orphan task's tenant, used to scope the caller client.\n */\n callerFor(\n top: { threadId: string; assistantId?: string },\n tenantId: string,\n ): Promise<{ client: RecoveryCallerClient; config: unknown; agent?: unknown } | undefined>;\n /** Live-run registry (defaults to the shared Core singleton). */\n registry?: { isLive(taskId: string): boolean };\n /**\n * Optional cross-replica liveness probe consulted by Guard B, so a run held\n * by a peer replica is not converged/backfilled. Mutually additive with the\n * process-local `registry`.\n */\n isTaskLive?: TaskLivenessProbe;\n /** Resume the continuation (tests can call client.invoke(null, config)). */\n resume(client: RecoveryCallerClient, config: unknown, agent?: unknown): Promise<void>;\n}\n\n/** Dependencies for an on-demand single-task recovery ({@link recoverTask}). */\nexport interface RecoverTaskDeps {\n /** Lifecycle used to converge the orphan to `failed(no_executor)`. */\n lifecycle: Pick<TaskLifecycleService, \"failTask\">;\n /** Live-run registry (defaults to the shared Core singleton). */\n registry?: TaskRunRegistry;\n /**\n * The tenant's other orphan candidates (normally every `in_progress` task),\n * used to walk the caller chain up to the true top-level caller.\n *\n * @remarks\n * Without this set {@link resolveTopCaller} can only see the target itself,\n * so a nested middle run would be mistaken for a direct child of its\n * immediate (frozen) caller. Defaults to `[converged]` when omitted.\n */\n orphans?: TaskItem[];\n /**\n * Optional cross-replica liveness probe consulted by Guard B, so a run held\n * by a peer replica is not converged. Forwarded to\n * {@link reconcileStaleTaskRuns} and to {@link recoverTopCaller}.\n */\n isTaskLive?: TaskLivenessProbe;\n /** Resolve a caller's agent client + config from the resolved top caller. */\n callerFor: TopCallerRecoveryDeps[\"callerFor\"];\n /** Resume the continuation (tests can call client.invoke(null, config)). */\n resume: TopCallerRecoveryDeps[\"resume\"];\n}\n\n/**\n * Outcome of an on-demand single-task recovery attempt.\n *\n * @remarks\n * - `recovered`: the task was converged and its top-level caller was resumed.\n * - `skipped`: nothing was changed; `reason` names the guard (for example\n * `not_in_progress`, `live`, `middle`, `project_task`, `no_top_caller`,\n * `not_found`).\n * - `converged_no_call`: the task was converged to `failed`, but the caller had\n * no pending `task` call left to resolve, so no continuation was resumed.\n */\nexport type RecoverTaskResult =\n | { kind: \"recovered\" }\n | { kind: \"skipped\"; reason: string }\n | { kind: \"converged_no_call\" };\n\n/** A `task` tool call that still has no tool result. */\ninterface PendingTaskCall {\n id: string;\n taskId?: string;\n}\n\n/** Guard A: a caller waiting for a human is never touched. */\nfunction hasPendingInterrupts(state: Record<string, unknown>): boolean {\n return ((state.tasks as Array<{ interrupts?: unknown[] }> | undefined) ?? [])\n .some((t) => (t.interrupts?.length ?? 0) > 0);\n}\n\n/** Collects every pending `task` tool call, keyed by its `args.taskId` when present. */\nfunction pendingTaskCalls(state: Record<string, unknown>): PendingTaskCall[] {\n const messages = ((state.values as { messages?: Array<Record<string, unknown>> } | undefined)?.messages) ?? [];\n const resolved = new Set(\n messages\n .filter((m) => (m as { tool_call_id?: string }).tool_call_id)\n .map((m) => (m as { tool_call_id: string }).tool_call_id),\n );\n const calls: PendingTaskCall[] = [];\n for (const m of messages) {\n const typed = m as { getType?: () => string };\n if (typeof typed.getType !== \"function\" || typed.getType() !== \"ai\") continue;\n const toolCalls = (m as {\n tool_calls?: Array<{ id?: string; name?: string; args?: { taskId?: unknown } }>;\n }).tool_calls;\n if (!Array.isArray(toolCalls)) continue;\n for (const c of toolCalls) {\n if (c.name !== \"task\" || !c.id || resolved.has(c.id)) continue;\n const taskId = typeof c.args?.taskId === \"string\" ? c.args.taskId : undefined;\n calls.push({ id: c.id, ...(taskId ? { taskId } : {}) });\n }\n }\n return calls;\n}\n\n/** Guard D: the outcome follows the task's real terminal state. */\nfunction outcome(task: TaskItem): string {\n if (task.status === \"completed\") {\n return JSON.stringify({ success: true, taskId: task.id, result: task.result ?? \"\" });\n }\n if (task.status === \"failed\") {\n return JSON.stringify({ success: false, code: \"TASK_FAILED\", retryable: false, taskId: task.id, error: task.failureReason ?? \"\" });\n }\n return JSON.stringify({\n success: false,\n code: \"TASK_INTERRUPTED\",\n retryable: false,\n taskId: task.id,\n error: \"Run ended before completion; the task is interrupted and awaiting a decision.\",\n });\n}\n\n/** Per-task recovery outcome. */\ninterface RecoveryEntry {\n id: string;\n reason: string;\n}\n\n/**\n * Backfills a batch of converged direct-child tasks that share one top caller.\n *\n * @param tasks The direct-child orphans whose top caller is `top`.\n * @param top The resolved top-level caller.\n * @param deps Caller resolver, live-run registry, and resume hook.\n * @returns One `\"recovered\"` or `\"skipped:<reason>\"` entry per task.\n * @remarks\n * Reads the caller state once, matches each task to its pending `task` tool\n * call by `args.taskId`, injects every matched result in a single\n * `updateState`, then resumes once.\n */\nasync function backfillTopCallerGroup(\n tasks: TaskItem[],\n top: { threadId: string; assistantId?: string },\n deps: TopCallerRecoveryDeps,\n): Promise<RecoveryEntry[]> {\n const registry = deps.registry ?? taskRunRegistry;\n const results: RecoveryEntry[] = [];\n const eligible: TaskItem[] = [];\n for (const task of tasks) {\n if (!task.context?.caller_thread_id) {\n results.push({ id: task.id, reason: \"skipped:no_caller_link\" });\n continue;\n }\n if (registry.isLive(task.id) || (deps.isTaskLive && await deps.isTaskLive(task))) { // Guard B\n results.push({ id: task.id, reason: \"skipped:live\" });\n continue;\n }\n eligible.push(task);\n }\n if (eligible.length === 0) return results;\n\n const target = await deps.callerFor(top, eligible[0].tenantId);\n if (!target) {\n return [...results, ...eligible.map((task) => ({ id: task.id, reason: \"skipped:no_caller_client\" }))];\n }\n const state = (await target.client.getState(target.config)) as Record<string, unknown>;\n if (hasPendingInterrupts(state)) { // Guard A\n return [...results, ...eligible.map((task) => ({ id: task.id, reason: \"skipped:hitl\" }))];\n }\n const nodeName = ((state.tasks as Array<{ name?: string }> | undefined) ?? [])[0]?.name; // Guard C\n if (!nodeName) {\n return [...results, ...eligible.map((task) => ({ id: task.id, reason: \"skipped:no_pending_node\" }))];\n }\n\n const calls = pendingTaskCalls(state);\n const matched: Array<{ task: TaskItem; call: PendingTaskCall }> = [];\n for (const task of eligible) {\n const call = calls.find((candidate) => candidate.taskId === task.id);\n if (!call) {\n results.push({ id: task.id, reason: \"skipped:no_pending_task_call\" });\n continue;\n }\n matched.push({ task, call });\n }\n if (matched.length === 0) return results;\n\n await target.client.updateState(target.config, {\n messages: matched.map(({ task, call }) =>\n new ToolMessage({ content: outcome(task), tool_call_id: call.id, name: \"task\" })),\n }, nodeName); // Guard D via outcome()\n await deps.resume(target.client, target.config, target.agent);\n return [...results, ...matched.map(({ task }) => ({ id: task.id, reason: \"recovered\" }))];\n}\n\n/**\n * Backfills one converged direct-child task's top-level caller.\n *\n * @param task The converged orphan task (must carry `context.caller_thread_id`).\n * @param top The resolved top-level caller.\n * @param deps Caller resolver, live-run registry, and resume hook.\n * @returns `\"recovered\"` or a `\"skipped:<reason>\"` string.\n */\nexport async function recoverTopCaller(\n task: TaskItem,\n top: { threadId: string; assistantId?: string },\n deps: TopCallerRecoveryDeps,\n): Promise<string> {\n if (!task.context?.caller_thread_id) return \"skipped:no_caller_link\";\n // Only direct children may be backfilled; a middle run is frozen by design.\n if (task.context.caller_thread_id !== top.threadId) return \"skipped:middle\";\n const [first] = await backfillTopCallerGroup([task], top, deps);\n return first?.reason ?? \"skipped:no_pending_task_call\";\n}\n\n/**\n * Recovers a single orphan task on demand, reusing the collapse logic.\n *\n * @param task The candidate task (any status).\n * @param deps Lifecycle, live-run registry, orphan candidate set (for the\n * caller-chain walk), caller resolver, and resume hook.\n * @returns A discriminated outcome: `recovered`, `skipped:<reason>`, or\n * `converged_no_call` when the task was converged but the caller had no\n * pending `task` call to resolve.\n * @remarks\n * Mirrors {@link runOrphanRecovery} for exactly one task: anything not\n * `in_progress`, or still held by a live run, is skipped; the rest is converged\n * to `failed` (`no_executor`, ADR-143) and its **top-level** caller is\n * backfilled. `deps.orphans` must carry the tenant's other `in_progress`\n * candidates so a nested middle run is correctly skipped (`middle`) instead of\n * being mistaken for a direct child of its frozen immediate caller.\n *\n * This is an **offline/maintenance** entry point (the `task:recover` CLI): run\n * it when the Gateway is stopped, or from within the Gateway process. Guard B\n * reads the process-local {@link taskRunRegistry}; when the optional\n * `isTaskLive` cross-replica probe is supplied (the gateway's lease-backed\n * probe), it also detects a run held by a peer replica.\n *\n * The convergence actor is `system:on-demand-recovery` (distinct from the\n * startup sweep's `system:orphan-recovery`), so on-demand convergences are\n * auditable in the task work-item trail. No HTTP route is added and recovery\n * semantics are unchanged.\n */\nexport async function recoverTask(\n task: TaskItem,\n deps: RecoverTaskDeps,\n): Promise<RecoverTaskResult> {\n if (task.status !== \"in_progress\") {\n return { kind: \"skipped\", reason: \"not_in_progress\" };\n }\n const registry = deps.registry ?? taskRunRegistry;\n if (registry.isLive(task.id) || (deps.isTaskLive && await deps.isTaskLive(task))) { // Guard B\n return { kind: \"skipped\", reason: \"live\" };\n }\n\n const { convergedTasks } = await reconcileStaleTaskRuns({\n tasks: [task],\n actor: \"system:on-demand-recovery\",\n lifecycle: deps.lifecycle,\n ...(deps.registry ? { registry: deps.registry } : {}),\n ...(deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}),\n });\n const converged = convergedTasks[0];\n if (!converged) {\n return { kind: \"skipped\", reason: \"convergence_failed\" };\n }\n\n const top = resolveTopCaller(converged, deps.orphans ?? [converged]);\n if (!top) {\n return { kind: \"skipped\", reason: \"no_top_caller\" };\n }\n // Only direct children may be backfilled; a middle run is frozen by design.\n if (converged.context?.caller_thread_id !== top.threadId) {\n return { kind: \"skipped\", reason: \"middle\" };\n }\n\n const reason = await recoverTopCaller(converged, top, {\n callerFor: deps.callerFor,\n resume: deps.resume,\n ...(deps.registry ? { registry: deps.registry } : {}),\n ...(deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}),\n });\n if (reason === \"recovered\") return { kind: \"recovered\" };\n if (reason === \"skipped:no_pending_task_call\") return { kind: \"converged_no_call\" };\n return { kind: \"skipped\", reason: reason.replace(/^skipped:/, \"\") };\n}\n\n/** Walks caller links up to the thread that is not any orphan's run thread. */\nexport function resolveTopCaller(\n task: TaskItem,\n orphans: TaskItem[],\n): { threadId: string; assistantId?: string } | undefined {\n const tenantId = task.tenantId;\n const runThreadToTask = new Map(\n orphans.map((orphan) => [`${orphan.tenantId}:${orphan.context?.thread_id}`, orphan]),\n );\n let threadId = task.context?.caller_thread_id as string | undefined;\n let assistantId = task.context?.caller_assistant_id as string | undefined;\n const seen = new Set<string>();\n while (threadId) {\n const scopeKey = `${tenantId}:${threadId}`;\n if (!runThreadToTask.has(scopeKey) || seen.has(scopeKey)) break;\n seen.add(scopeKey);\n const parent = runThreadToTask.get(scopeKey)!;\n threadId = parent.context?.caller_thread_id as string | undefined;\n assistantId = parent.context?.caller_assistant_id as string | undefined;\n }\n return threadId ? { threadId, ...(assistantId ? { assistantId } : {}) } : undefined;\n}\n\n/**\n * Runs the whole collapse recovery once: reconcile orphan tasks, then backfill\n * the top-level caller of every direct-child orphan, grouped per top caller.\n * Best-effort; a failing group is contained and never aborts the others.\n *\n * @param deps Reconcile source, caller resolution, resume, and logger.\n * @returns The recovered and skipped `taskId:reason` entries.\n */\nexport async function runOrphanRecovery(deps: {\n reconcile: () => Promise<{ convergedTasks: TaskItem[] }>;\n callerFor: TopCallerRecoveryDeps[\"callerFor\"];\n resume: TopCallerRecoveryDeps[\"resume\"];\n isTaskLive?: TaskLivenessProbe;\n log: { info(msg: string, ctx: Record<string, unknown>): void; warn(msg: string, ctx: Record<string, unknown>): void };\n}): Promise<{ recovered: string[]; skipped: string[] }> {\n let convergedTasks: TaskItem[];\n try {\n ({ convergedTasks } = await deps.reconcile());\n } catch (error) {\n deps.log.warn(\"Task orphan recovery reconcile failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return { recovered: [], skipped: [\"reconcile:error\"] };\n }\n const orphans = convergedTasks;\n const recovered: string[] = [];\n const skipped: string[] = [];\n\n const groups = new Map<string, { top: { threadId: string; assistantId?: string }; tasks: TaskItem[] }>();\n for (const task of orphans) {\n const top = resolveTopCaller(task, orphans);\n if (!top) { skipped.push(`${task.id}:skipped:no_top_caller`); continue; }\n // Only direct children are backfilled; middle task runs are frozen by design.\n if (task.context?.caller_thread_id !== top.threadId) {\n skipped.push(`${task.id}:skipped:middle`);\n continue;\n }\n const key = `${task.tenantId}:${top.threadId}`;\n const group = groups.get(key);\n if (group) group.tasks.push(task);\n else groups.set(key, { top, tasks: [task] });\n }\n\n for (const { top, tasks } of groups.values()) {\n try {\n const results = await backfillTopCallerGroup(tasks, top, {\n callerFor: deps.callerFor,\n resume: deps.resume,\n ...(deps.isTaskLive ? { isTaskLive: deps.isTaskLive } : {}),\n });\n for (const { id, reason } of results) {\n (reason === \"recovered\" ? recovered : skipped).push(`${id}:${reason}`);\n }\n } catch (error) {\n for (const task of tasks) skipped.push(`${task.id}:error`);\n deps.log.warn(\"Task orphan recovery group failed\", {\n threadId: top.threadId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n deps.log.info(\"Task orphan recovery complete\", { recovered, skipped });\n return { recovered, skipped };\n}\n","import type {\n Project,\n ProjectBotMembership,\n ProjectRoom,\n TaskItem,\n} from \"@axiom-lattice/protocols\";\n\n/**\n * Whether a task belongs to the Project lifecycle scope enforced by this host.\n *\n * Host-owned business predicate (ADR-118): Core no longer interprets\n * `context.source`; the gateway decides which tasks its Project runtime owns.\n *\n * @param task Task snapshot whose durable scope and host-stamped origin are inspected.\n * @returns True for Project Room, Project Task, or human `user` origins with an explicit scope.\n *\n * @remarks ADR-118 §6: classification is **explicit scope presence + host-stamped\n * `context.source`** — there is no `\"default\"` sentinel. A source of\n * `project_room`/`project_task` is stamped only by the host's trusted run context,\n * which always carries a real workspace/project id. `user` marks UI/human-created\n * Project tasks, which share the same durable Project queue runtime.\n */\nexport function isProjectLifecycleTask(task: TaskItem): task is TaskItem & {\n workspaceId: string;\n projectId: string;\n} {\n const source = task.context?.source;\n return typeof task.workspaceId === \"string\" && task.workspaceId.length > 0\n && typeof task.projectId === \"string\" && task.projectId.length > 0\n && (source === \"project_room\" || source === \"project_task\" || source === \"user\");\n}\n\n/**\n * Whether a Project's public (general) kind is exempt from roster authority.\n *\n * @param project Project row being inspected, or `null`/`undefined` when absent.\n * @returns True only for `kind === \"public\"`.\n *\n * @remarks The public project kind is the workspace-wide general space: it has no\n * authored roster, so any available agent may own its tasks. Every other kind\n * (`business`, `training`, `personal`, legacy omitted) keeps strict roster\n * validation. The decision is a project property, not a task-source property.\n */\nexport function isRosterExemptProject(project: Pick<Project, \"kind\"> | null | undefined): boolean {\n return project?.kind === \"public\";\n}\n\n/**\n * Resolves the owner membership that authorizes a Project task's execution thread.\n *\n * @param task Exact Project task whose owner is being resolved.\n * @param project Exact Project row; `kind` decides roster exemption.\n * @param room Exact Project main room the owner executes in.\n * @param membership Roster lookup result for `task.ownerId`, if any.\n * @returns The active exact-scope roster membership, or a synthesized membership\n * for a public-project task whose owner is not an active roster bot, or\n * `undefined` when the owner is not an active roster bot and the project is not\n * public.\n *\n * @remarks Public-project tasks may use any available agent as owner, so the\n * Project runtime synthesizes a stable, task-scoped membership descriptor instead\n * of requiring a roster row. Roster authority is unchanged everywhere else.\n */\nexport function resolveTaskOwnerMembership(\n task: TaskItem,\n project: Pick<Project, \"kind\"> | null | undefined,\n room: ProjectRoom,\n membership: ProjectBotMembership | undefined,\n): ProjectBotMembership | undefined {\n const active = membership && membership.status === \"active\"\n && membership.tenantId === task.tenantId && membership.workspaceId === task.workspaceId\n && membership.projectId === task.projectId && membership.assistantId === task.ownerId\n && membership.roomId === room.id;\n if (active) return membership;\n if (!isRosterExemptProject(project)) return undefined;\n return syntheticPublicProjectOwnerMembership(task, room);\n}\n\n/**\n * Builds the stable, task-scoped owner membership used for a public-project task\n * whose owner agent has no active Project roster row.\n *\n * @param task Exact public-project task.\n * @param room Exact Project main room.\n * @returns A descriptor-safe `active` membership matching the task's exact scope\n * and owner, with a deterministic synthetic id so subsequent `ensure`/recovery\n * reads resolve the same canonical Task Thread metadata.\n */\nexport function syntheticPublicProjectOwnerMembership(task: TaskItem, room: ProjectRoom): ProjectBotMembership {\n const threadId = typeof task.context?.thread_id === \"string\" && task.context.thread_id.length > 0\n ? task.context.thread_id\n : task.ownerId;\n return {\n id: `public-project-owner:${task.projectId}:${task.ownerId}`,\n tenantId: task.tenantId,\n workspaceId: task.workspaceId!,\n projectId: task.projectId!,\n roomId: room.id,\n assistantId: task.ownerId,\n role: \"specialist\",\n title: task.ownerId,\n mentionName: task.ownerId,\n status: \"active\",\n roomThreadId: threadId,\n joinedAt: task.createdAt,\n updatedAt: task.updatedAt,\n };\n}\n","import type { LeaseStore, TaskItem } from \"@axiom-lattice/protocols\";\nimport {\n storeLatticeManager,\n taskRunLeaseKey,\n threadRunLeaseKey,\n} from \"@axiom-lattice/core\";\n\n/** Cross-replica liveness probe: resolves true when a peer still owns the task's run. */\nexport type TaskLivenessProbe = (task: TaskItem) => Promise<boolean>;\n\n/**\n * Builds a cross-replica task-liveness probe from the registered `\"lease\"` store.\n *\n * @returns A {@link TaskLivenessProbe}, or `undefined` only when no `lease`\n * store is registered (a test-only path); with the default in-memory lease\n * store a probe is always returned (single-process safe because the in-memory\n * store has no peer).\n * @remarks\n * A task is considered live when EITHER lease is currently held:\n * - `task-run:<taskId>` — the immediate executor's run-lifetime lease, or\n * - `thread-run:<tenantId>:<ownerId>:<thread_id>` — the queue processor\n * executing the task's run thread (dispatched workers run through this).\n *\n * Fail-safe: any lease-store error resolves `true`, so an unknown liveness\n * state never causes a live run to be converged as an orphan.\n *\n * The probe is advisory: there is a benign race between the probe read and\n * `failTask` (a run could acquire its lease in that window), and no\n * fencing/heartbeat-expiry detection is provided yet — consistent with the\n * framework's current no-lease posture.\n *\n * @example\n * ```ts\n * const probe = createTaskRunLiveness();\n * if (probe && await probe(task)) return; // a peer replica owns it\n * ```\n */\nexport function createTaskRunLiveness(): TaskLivenessProbe | undefined {\n try {\n storeLatticeManager.getStoreLattice(\"default\", \"lease\");\n } catch {\n return undefined;\n }\n return async (task: TaskItem): Promise<boolean> => {\n try {\n const store = storeLatticeManager.getStoreLattice(\"default\", \"lease\").store as LeaseStore;\n if (await store.get(taskRunLeaseKey(task.id))) return true;\n const threadId =\n typeof task.context?.thread_id === \"string\" ? task.context.thread_id : undefined;\n if (threadId && task.ownerId) {\n if (await store.get(threadRunLeaseKey(task.tenantId, task.ownerId, threadId))) return true;\n }\n return false;\n } catch {\n return true;\n }\n };\n}\n"],"mappings":"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","names":["taskRunRegistry","taskRunRegistry"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as C}from"./embed-page-chunk-
|
|
1
|
+
import{l as C}from"./embed-page-chunk-DZQBVJ7Z.js";import"./embed-page-chunk-UT3WYBZH.js";import"./embed-page-chunk-N22EGQAJ.js";import"./embed-page-chunk-IPIJ2SG6.js";import"./embed-page-chunk-KEL6XU6R.js";import"./embed-page-chunk-AC6X2XRH.js";import"./embed-page-chunk-S4XZPBRM.js";import"./embed-page-chunk-O72XBKQH.js";import{Ba as T,nb as B}from"./embed-page-chunk-QMVIL4BJ.js";import{y as P}from"./embed-page-chunk-YPNSOZYW.js";import{a as I}from"./embed-page-chunk-MB65DZAX.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-5JDQ456X.js";import"./embed-page-chunk-Z7USDLHI.js";import{U as c,W as p,oa as D,va as b,xa as l}from"./embed-page-chunk-O4QK5LWZ.js";import{a as U}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-IX4WLWCY.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as u}from"./embed-page-chunk-6Y3UYJ6Z.js";var e=u(U());var t=u(I()),G={component_key:"workspace_assistants",data:{},message:"Assistants"},N=r=>{let i=r;if(typeof r=="string")try{i=JSON.parse(r)}catch{return{}}return i!==null&&typeof i=="object"&&!Array.isArray(i)?i:{}},H=({data:r})=>{let{assistantId:i,initialTab:F}=r??{},{get:m,put:f,del:A}=P(),y=T(),[g,w]=(0,e.useState)(null),[R,h]=(0,e.useState)([]),[E,v]=(0,e.useState)(!1),[L,S]=(0,e.useState)(null),d=(0,e.useCallback)(()=>{y(G)},[y]),a=(0,e.useCallback)(async()=>{v(!0),S(null);try{let s=(await m("/api/assistants")).data?.records??[];h(s),w(s.find(o=>o.id===i)??null)}catch{S("Failed to load agent")}finally{v(!1)}},[m,i]);(0,e.useEffect)(()=>{i&&a()},[a,i]);let _=(0,e.useCallback)(async(n,s)=>{let o=N(n.graphDefinition),k;try{k=await f(`/api/assistants/${n.id}`,{name:s.name!==void 0?s.name:n.name,description:s.description!==void 0?s.description:n.description,graphDefinition:{...o,...s}})}catch(z){throw l.error("Failed to save agent"),z}if(!k.success)throw l.error("Failed to save agent"),new Error("Failed to save agent");l.success("Saved"),await a()},[f,a]),j=(0,e.useCallback)(n=>{w(s=>s&&s.id===n.id?n:s),h(s=>s.map(o=>o.id===n.id?n:o))},[]),x=(0,e.useCallback)(async n=>{if(!(await A(`/api/assistants/${n}`)).success)throw new Error("Failed to delete agent");l.success("Agent deleted"),d()},[A,d]);return i?g?(0,t.jsx)("div",{style:{height:"100%",overflow:"auto"},children:(0,t.jsx)(B,{children:(0,t.jsx)(C,{assistant:g,allAssistants:R,onBack:d,onDeleted:x,onSave:_,onAssistantUpdated:j,onAgentListInvalidated:()=>void a(),initialTab:F})},g.id)}):E?(0,t.jsx)("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",height:"100%"},children:(0,t.jsx)(b,{})}):L?(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(c,{type:"error",showIcon:!0,message:"Failed to load agent","data-testid":"detail-error",action:(0,t.jsxs)(D,{children:[(0,t.jsx)(p,{size:"small",onClick:()=>void a(),children:"Retry"}),(0,t.jsx)(p,{size:"small",type:"primary",onClick:d,children:"Back to list"})]})})}):(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(c,{type:"warning",showIcon:!0,message:"Agent not found","data-testid":"detail-not-found",action:(0,t.jsx)(p,{size:"small",type:"primary",onClick:d,children:"Back to list"})})}):(0,t.jsx)("div",{style:{padding:24},children:(0,t.jsx)(c,{type:"warning",showIcon:!0,message:"Missing agent id","data-testid":"detail-missing-id"})})};export{H as AgentDetailSideApp};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as Re,b as Ne,c as Dt,d as Rt,e as Pt,f as Ft,g as Mt,h as Et,i as Nt,j as Lt,k as Bt,l as Ot}from"./embed-page-chunk-
|
|
1
|
+
import{a as Re,b as Ne,c as Dt,d as Rt,e as Pt,f as Ft,g as Mt,h as Et,i as Nt,j as Lt,k as Bt,l as Ot}from"./embed-page-chunk-DZQBVJ7Z.js";import"./embed-page-chunk-UT3WYBZH.js";import{a as Ue}from"./embed-page-chunk-N22EGQAJ.js";import"./embed-page-chunk-IPIJ2SG6.js";import"./embed-page-chunk-KEL6XU6R.js";import{b as Ge,e as ze,f as xt,g as wt,h as vt,i as kt,l as St,m as It}from"./embed-page-chunk-AC6X2XRH.js";import{a as ft,b as yt,c as ht,d as bt,e as At}from"./embed-page-chunk-SV2BM3WO.js";import"./embed-page-chunk-S4XZPBRM.js";import"./embed-page-chunk-O72XBKQH.js";import{$ as ct,Aa as ut,Ba as Ct,C as st,F as it,L as lt,Ma as Ve,X as dt,g as De,ka as pt,nb as Tt,ra as mt,s as rt,sa as gt}from"./embed-page-chunk-QMVIL4BJ.js";import{t as et,y as ye}from"./embed-page-chunk-YPNSOZYW.js";import{a as M}from"./embed-page-chunk-MB65DZAX.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-5JDQ456X.js";import"./embed-page-chunk-Z7USDLHI.js";import{Db as nt,Fa as Qe,Ia as Te,Ja as Xe,La as X,Ua as tt,W as J,_ as Se,aa as Ie,ac as Ee,ea as Me,ka as Ke,la as Ze,ma as Je,mc as at,oa as Ye,ra as R,ta as V,wa as _e,xa as v,ya as fe,yc as ot}from"./embed-page-chunk-O4QK5LWZ.js";import{a as ue}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-IX4WLWCY.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as x}from"./embed-page-chunk-6Y3UYJ6Z.js";var u=x(ue());var te=x(ue());var Y=x(ue());var $t=x(ue());var ie=x(M()),Kt=60,_t=72,je=(0,$t.memo)(({data:n})=>{let r=Re(n.type),p=Math.min(12+Math.sqrt(n.subAgentCount)*10,48);return(0,ie.jsxs)("div",{style:{display:"flex",flexDirection:"column",alignItems:"center"},children:[(0,ie.jsx)(ze,{type:"target",position:Ge.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1}),(0,ie.jsx)("div",{title:n.label,style:{width:p,height:p,borderRadius:"50%",background:Ne(r.color),display:"flex",alignItems:"center",justifyContent:"center",color:"#fff",fontSize:Math.max(10,p*.4),fontWeight:600,cursor:"pointer",boxShadow:"0 2px 8px rgba(0,0,0,0.15)"},children:n.label.charAt(0).toUpperCase()}),(0,ie.jsx)("div",{style:{fontSize:11,maxWidth:120,textAlign:"center",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",marginTop:4},children:n.label}),(0,ie.jsx)(ze,{type:"source",position:Ge.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:0,height:0},isConnectable:!1})]})});je.displayName="AgentGraphNode";var ee=x(M()),sn=({assistants:n,onNodeClick:r})=>{let[p,l,g]=vt([]),[o,f,k]=kt([]),[d,S]=(0,Y.useState)(null),H=(0,Y.useMemo)(()=>({agent:je}),[]),m=(0,Y.useMemo)(()=>Pt(n),[n]);(0,Y.useEffect)(()=>{let w=m.nodes.map(i=>({id:i.id})),P=m.edges.map(i=>({source:i.source,target:i.target})),N=new Map(m.nodes.map(i=>[i.id,i])),z=bt(w).force("link",ht(P).id(i=>i.id).distance(80)).force("charge",At().strength(-220)).force("center",ft(0,0)).force("collide",yt(45)).stop();for(let i=0;i<300;i++)z.tick();let F=w.map(i=>({id:i.id,type:"agent",data:N.get(i.id),position:{x:i.x-Kt/2,y:i.y-_t/2}})),s=m.edges.map(i=>({id:`e${i.source}-${i.target}`,source:i.source,target:i.target,style:{stroke:"#1677ff",strokeWidth:2},type:"straight"}));l(F),f(s)},[m,l,f]);let T=(0,Y.useMemo)(()=>d===null?p:p.map(w=>{let P=w.id===d||o.some(N=>N.source===d&&N.target===w.id||N.target===d&&N.source===w.id);return{...w,style:{opacity:P?1:.2,transition:"opacity 0.2s ease"}}}),[p,o,d]),K=(0,Y.useMemo)(()=>d===null?o.map(w=>({...w,style:{stroke:"#1677ff",strokeWidth:1.5,opacity:.25,transition:"opacity 0.2s ease"}})):o.map(w=>{let P=w.source===d||w.target===d;return{...w,style:{stroke:"#1677ff",strokeWidth:P?2.5:1,opacity:P?1:.04,transition:"opacity 0.2s ease"}}}),[o,d]);return(0,ee.jsx)("div",{style:{width:"100%",height:"100%",background:"#fafafa",position:"relative"},children:(0,ee.jsxs)(wt,{nodes:T,edges:K,onNodesChange:g,onEdgesChange:k,onNodeMouseEnter:(w,P)=>S(P.id),onNodeMouseLeave:()=>S(null),onNodeClick:(w,P)=>r?.(String(P.id)),nodeTypes:H,fitView:!0,fitViewOptions:{padding:.25},children:[(0,ee.jsx)(St,{color:"#eee",gap:20}),(0,ee.jsx)(It,{})]})})},Vt=n=>(0,ee.jsx)(xt,{children:(0,ee.jsx)(sn,{...n})});var E=x(M()),ln=n=>{if(!n)return"\u2014";let r=Date.now()-new Date(n).getTime(),p=Math.floor(r/6e4);if(p<1)return"just now";if(p<60)return`${p}m ago`;let l=Math.floor(p/60);return l<24?`${l}h ago`:`${Math.floor(l/24)}d ago`},dn=n=>n===null?"#d9d9d9":n>=80?"#22c55e":n>=50?"#f59e0b":"#ef4444",cn=mt(({css:n})=>({row:n`
|
|
2
2
|
display: flex;
|
|
3
3
|
justify-content: space-between;
|
|
4
4
|
align-items: flex-end;
|
package/dist/embed/{embed-page-MessageGraph-E6DZDT65.js → embed-page-MessageGraph-JAJGMYKH.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as W,d as V}from"./embed-page-chunk-KEL6XU6R.js";import{b as N,d as U,e as k}from"./embed-page-chunk-AC6X2XRH.js";import"./embed-page-chunk-S4XZPBRM.js";import{
|
|
1
|
+
import{c as W,d as V}from"./embed-page-chunk-KEL6XU6R.js";import{b as N,d as U,e as k}from"./embed-page-chunk-AC6X2XRH.js";import"./embed-page-chunk-S4XZPBRM.js";import{Da as b,Fa as z,Ga as F,Ha as H,Ia as L,Sa as R,Ta as $,Ua as J}from"./embed-page-chunk-QMVIL4BJ.js";import"./embed-page-chunk-YPNSOZYW.js";import{a as g}from"./embed-page-chunk-MB65DZAX.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-5JDQ456X.js";import"./embed-page-chunk-Z7USDLHI.js";import{Dc as D,Ia as O,Rc as G,Sc as w,Vc as _,W as v,aa as M,gb as P,lb as B,nc as E}from"./embed-page-chunk-O4QK5LWZ.js";import{a as C}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-IX4WLWCY.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as p}from"./embed-page-chunk-6Y3UYJ6Z.js";var s=p(C());var S=p(C());var o=p(g());var se="tracePulse 1.4s ease-in-out infinite",ie={running:(0,o.jsx)(E,{style:{color:"#1890ff"}}),success:(0,o.jsx)(P,{style:{color:"#52c41a"}}),error:(0,o.jsx)(B,{style:{color:"#ff4d4f"}})};function ae({kind:e}){switch(e){case"human":return(0,o.jsx)(_,{});case"agent":return(0,o.jsx)(G,{});case"tool":return(0,o.jsx)(w,{});case"ai":return(0,o.jsx)(D,{});default:return(0,o.jsx)(w,{})}}var I=S.default.createContext({}),le=()=>S.default.useContext(I),de=({data:e,selected:i})=>{let{onJumpToMessage:a}=le(),t=e.isAnswer===!0,r=e.status==="running",d=(e.parallelCount??1)>1,m=!!(a&&e.messageId&&!e.messageId.startsWith("summary:")),f=e.toolCall?F(e.toolCall.name):e.label,y=()=>{if((e.kind==="tool"||e.kind==="agent")&&e.toolCall){let h=H(e.toolCall.response);return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(z,{data:{name:e.toolCall.name,parameters:e.toolCall.args,type:"tool_call"},component_key:`${e.toolCall.id}-params`,interactive:!1}),h&&(0,o.jsx)("div",{style:{marginTop:8},children:(0,o.jsx)(b,{content:h})}),(0,o.jsx)(L,{ui:e.toolCall.ui})]})}return e.content?(0,o.jsx)(b,{content:e.content}):(0,o.jsx)("span",{style:{color:"#8c8c8c"},children:e.label})};return(0,o.jsxs)("div",{"data-testid":"trace-card",style:{height:"100%",display:"flex",flexDirection:"column",border:`1px solid ${t||i?"#6366f1":r?"#91caff":"#e5e7eb"}`,borderRadius:12,background:t?"#eef2ff":"#fff",boxShadow:r?"0 0 0 2px rgba(24,144,255,0.18)":i?"0 0 0 2px rgba(99,102,241,0.2)":"none",animation:r?se:void 0,overflow:"hidden",fontSize:13},children:[(0,o.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,padding:"8px 12px",borderBottom:"1px solid #f0f0f0",background:"rgba(0,0,0,0.02)"},children:[(0,o.jsx)(ae,{kind:e.kind}),(0,o.jsx)("span",{style:{fontWeight:t?700:600,flex:1,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:f}),d&&(0,o.jsxs)(O,{color:"purple",style:{marginInlineEnd:0,fontSize:10},children:["\u5E76\u53D1 \xD7",e.parallelCount]}),ie[e.status],m&&(0,o.jsx)(v,{type:"text",size:"small",onClick:()=>a?.(e.messageId),children:"\u5BF9\u8BDD"})]}),(0,o.jsx)("div",{style:{flex:1,minHeight:0,overflow:"auto",padding:12},children:y()})]})},ce=({data:e,selected:i})=>(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(k,{type:"target",position:N.Top}),(0,o.jsx)(de,{data:e,selected:i}),(0,o.jsx)(k,{type:"source",position:N.Bottom})]}),K={trace:ce};var Y=p(C());var u=p(g()),pe={running:"#1890ff",success:"#52c41a",error:"#ff4d4f"},Z=({graph:e,activeNodeId:i,onSelectNode:a})=>{let t=Y.default.useMemo(()=>new Map(e.nodes.map(r=>[r.id,r])),[e.nodes]);return(0,u.jsx)("div",{"data-testid":"trace-overview-rail",style:{display:"flex",flexDirection:"column",gap:10,width:160,padding:8,overflowY:"auto",borderRight:"1px solid #f0f0f0"},children:e.phases.map(r=>(0,u.jsxs)("div",{"data-testid":"trace-rail-phase",children:[(0,u.jsx)("div",{style:{fontSize:12,color:"#8c8c8c",marginBottom:4},children:r.title}),(0,u.jsx)("div",{style:{display:"flex",flexWrap:"wrap",gap:4},children:r.nodeIds.map(d=>{let m=t.get(d);if(!m)return null;let f=d===i;return(0,u.jsx)(M,{title:m.data.label,children:(0,u.jsx)("button",{type:"button","data-testid":"trace-rail-tick",onClick:()=>a?.(d),style:{width:f?12:8,height:f?12:8,borderRadius:"50%",border:"none",padding:0,cursor:"pointer",background:pe[m.data.status],outline:f?"2px solid #6366f1":"none"}})},d)})})]},r.id))})};var l=p(g()),j=3,q=()=>{},fe=`
|
|
2
2
|
@keyframes tracePulse {
|
|
3
3
|
0%, 100% { box-shadow: 0 0 0 2px rgba(24,144,255,0.18); }
|
|
4
4
|
50% { box-shadow: 0 0 0 6px rgba(24,144,255,0.05); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{s as C}from"./embed-page-chunk-OOZDPBUK.js";import{
|
|
1
|
+
import{s as C}from"./embed-page-chunk-OOZDPBUK.js";import{Ca as v}from"./embed-page-chunk-QMVIL4BJ.js";import{h as w}from"./embed-page-chunk-YPNSOZYW.js";import{a as x}from"./embed-page-chunk-MB65DZAX.js";import"./embed-page-chunk-VW3NF5NT.js";import"./embed-page-chunk-5JDQ456X.js";import"./embed-page-chunk-Z7USDLHI.js";import{ga as b}from"./embed-page-chunk-O4QK5LWZ.js";import{a as D}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-IX4WLWCY.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as d}from"./embed-page-chunk-6Y3UYJ6Z.js";var c=d(D());var E=d(w());var f=d(x());function p(s){if(!s||s.length===0)return{title:{text:"Chart",left:"left"},tooltip:{trigger:"axis"},legend:{right:0,orient:"vertical"},xAxis:{type:"category",data:[]},yAxis:{type:"value"},series:[{type:"line",name:"Series 1",data:[]}],grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0}};let i=s[0],t=Object.keys(i);if(t.length===0)return p([]);let r=t.filter(e=>{let n=i[e];return typeof n=="number"||!isNaN(Number(n))});if(r.length>0){let e=r[0],n=t.find(a=>!r.includes(a))||t[0],o=s.map((a,l)=>a[n]!==void 0?String(a[n]):`Item ${l+1}`),u=s.map(a=>{let l=a[e];return typeof l=="number"?l:Number(l)||0});return{title:{text:"Chart",left:"left"},tooltip:{trigger:"axis"},legend:{right:0,orient:"vertical",data:[e]},xAxis:{type:"category",data:o},yAxis:{type:"value"},series:[{type:"line",name:e,data:u}],grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0}}}return{title:{text:"Chart",left:"left"},tooltip:{trigger:"axis"},legend:{right:0,orient:"vertical"},xAxis:{type:"category",data:s.map((e,n)=>`Item ${n+1}`)},yAxis:{type:"value"},series:[{type:"bar",name:"Count",data:s.map(()=>1)}],grid:{left:"3%",right:"4%",bottom:"3%",containLabel:!0}}}function S(s){if(!s||typeof s!="object"||!s.series||!Array.isArray(s.series)||s.series.length===0)return null;let i=s.series.map((e,n)=>{if(!e||typeof e!="object"||!e.type||!e.data||!Array.isArray(e.data)||e.data.length===0)return null;let o={...e,name:e.name||`Series ${n+1}`};if(e.type==="pie"){let u=e.data.map((a,l)=>typeof a=="object"&&a!==null&&"value"in a?{value:a.value,name:a.name||`Item ${l+1}`}:typeof a=="number"?{value:a,name:`Item ${l+1}`}:null).filter(a=>a!==null);return u.length===0?null:{...o,data:u}}return o}).filter(e=>e!==null);if(i.length===0)return null;let t={...s,series:i},r=i[0].type;if(r!=="pie"){if(!t.xAxis)t.xAxis={type:"category",data:[]};else if(typeof t.xAxis=="object"&&!Array.isArray(t.xAxis)){let e=t.xAxis;if(e.type||(e.type="category"),e.type==="category"&&!e.data){let n=i[0].data;Array.isArray(n)&&n.length>0?Array.isArray(n[0])?e.data=n.map(o=>o[0]):e.data=n.map((o,u)=>`Item ${u+1}`):e.data=[]}t.xAxis=e}t.yAxis?typeof t.yAxis=="object"&&!Array.isArray(t.yAxis)&&(t.yAxis.type||(t.yAxis.type="value")):t.yAxis={type:"value"}}if(!t.title)t.title={text:"Chart",left:"left"};else if(typeof t.title=="object"){let e=t.title;e.left||(e.left="left"),e.text||(e.text="Chart"),t.title=e}if(t.tooltip||(t.tooltip={trigger:r==="pie"?"item":"axis"}),!t.legend)i.length>1&&(t.legend={right:0,orient:"vertical"});else if(typeof t.legend=="object"){let e=t.legend;t.legend=e}return r!=="pie"&&!t.grid&&(t.grid={left:"3%",right:"4%",bottom:"3%",containLabel:!0}),t}function j(s){let i=null;try{let n=typeof s=="string"?s:s.join("");i=(0,E.parse)(n)}catch(n){return{data:null,error:`Failed to parse JSON: ${n instanceof Error?n.message:String(n)}`}}if(!i||typeof i!="object")return{data:null,error:"Parsed data is not an object"};let t=i.series&&Array.isArray(i.series)&&i.series.length>0,r={table:Array.isArray(i.table)?i.table:void 0},e=null;if(i.echarts?e=i.echarts:t&&(e=i),e){let n=S(e);if(n)r.echarts=n;else if(r.table&&r.table.length>0)r.echarts=p(r.table);else return{data:null,error:"ECharts configuration is invalid or incomplete. Required: series array with at least one series containing type and data."}}else r.table&&r.table.length>0?r.echarts=p(r.table):r.echarts=p([]);return{data:r,error:null}}var T=s=>{let{children:i}=s,t=(0,c.useRef)(null),r=(0,c.useRef)(null),e=(0,c.useRef)(null),[n,o]=(0,c.useState)(null);(0,c.useEffect)(()=>{if(!t.current)return;r.current||(r.current=C(t.current));let a=null;if((typeof i=="string"||Array.isArray(i))&&(a=i),!a){r.current&&r.current.clear(),o(null);return}let{data:l,error:g}=j(a);if(g||!l){console.warn("ReactChart failed to parse chart data:",g||"Unknown parse error"),r.current&&r.current.clear(),o(null);return}if(l.table&&Array.isArray(l.table)&&o(l.table),l.echarts)try{r.current.setOption(l.echarts,!0)}catch(h){let m=h instanceof Error?h.message:"Failed to render chart";console.error("Failed to set ECharts option:",h),r.current&&r.current.clear(),o(null)}let y=()=>{r.current&&r.current.resize()};return e.current&&(e.current.disconnect(),e.current=null),t.current&&typeof ResizeObserver<"u"&&(e.current=new ResizeObserver(h=>{requestAnimationFrame(()=>{y()})}),e.current.observe(t.current)),window.addEventListener("resize",y),()=>{e.current&&(e.current.disconnect(),e.current=null),window.removeEventListener("resize",y)}},[i]),(0,c.useEffect)(()=>()=>{e.current&&(e.current.disconnect(),e.current=null),r.current&&(r.current.dispose(),r.current=null)},[]);let u=a=>{if(!a||a.length===0)return[];if(Array.isArray(a[0])){let l=a[0];return a.slice(1).map((y,h)=>{let m={};return y.forEach((R,A)=>{m[l[A]||`col_${A}`]=R}),m})}return a};return(0,f.jsxs)(b,{children:[(0,f.jsx)("div",{ref:t,style:{width:"100%",height:"400px",minHeight:"300px"}}),n&&n.length>0&&(0,f.jsx)("div",{style:{marginTop:16},children:(0,f.jsx)(v,{component_key:"chart_table_data",data:{dataSource:u(n),message:"Data Details"},interactive:!0,default_open_in_side_app:!0})})]})};export{T as ReactChart};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as J,c as me,e as Q,f as Se,g as he,h as xe,i as ke,l as ve,m as be}from"./embed-page-chunk-AC6X2XRH.js";import{a as pe,b as ye,c as ge,d as fe,e as ue}from"./embed-page-chunk-SV2BM3WO.js";import"./embed-page-chunk-S4XZPBRM.js";import{m as le,q as ne,r as U,s as Te}from"./embed-page-chunk-HEMNMC4X.js";import{a as _}from"./embed-page-chunk-MB65DZAX.js";import{Ia as D,Ja as j,La as ie,Tb as de,W as k,ab as ae,fc as ce,ka as te,oa as I,qb as re,rb as se,ta as N,xa as T,ya as oe,yc as K}from"./embed-page-chunk-O4QK5LWZ.js";import{a as ee}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as B}from"./embed-page-chunk-6Y3UYJ6Z.js";var S=B(ee());var m=B(ee());var e=B(_()),{Text:d}=ie,{TextArea:Ce}=N,Me=({data:v})=>{let{token:o}=j.useToken(),{config:C}=ne(),{put:V}=U(),R=me(t=>t.transform[2])>.6,q=le("__GLOBAL__");if(!v)return null;let{skill:g,onClick:F,onDelete:h}=v;if(!g)return null;let[i,A]=(0,m.useState)(g),O=i.subSkills&&i.subSkills.length>0,f=i.subSkills?.length||0,E=(0,m.useMemo)(()=>Math.min(12+Math.sqrt(f)*10,48),[f]),Y=i.metadata&&i.metadata.category||"global",b=(0,m.useMemo)(()=>i.metadata?Object.entries(i.metadata).filter(([t,n])=>t&&n):[],[i.metadata]),L=t=>{if(!t)return"";let n=t instanceof Date?t:new Date(t);return Number.isNaN(n.getTime())?"":n.toLocaleString()},G=t=>{navigator.clipboard.writeText(t)},[z,x]=(0,m.useState)(!1),[c,a]=(0,m.useState)({...g,id:g.name}),[s,u]=(0,m.useState)(b.map(([t,n])=>({key:t,value:n}))),[W,M]=(0,m.useState)(!1),[X,P]=(0,m.useState)(!1);(0,m.useEffect)(()=>{x(!1),A(g),a({...g,id:g.name}),u(Object.entries(g.metadata||{}).map(([t,n])=>({key:t,value:n})))},[g]);let l=(t,n)=>{if(t==="name"){a(r=>({...r,name:n,id:n}));return}a(r=>({...r,[t]:n}))},$=async t=>{t?.stopPropagation(),t?.preventDefault();try{let n=i.id||i.name;if(!n){T.error("Skill ID is missing");return}await q.skills.delete(n),T.success("Skill deleted successfully"),M(!1),h&&await h()}catch(n){T.error(n?.message||"An error occurred while deleting the skill")}},H=t=>{u(t);let n=t.reduce((r,p)=>(p.key&&(r[p.key]=p.value),r),{});a(r=>({...r,metadata:n}))},Z=(t,n,r)=>{let p=[...s];p[t]={...p[t],[n]:r},H(p)},ze=()=>{H([...s,{key:"",value:""}])},Be=async()=>{try{P(!0);let t={"Content-Type":"application/json"};C.apiKey&&(t.Authorization=`Bearer ${C.apiKey}`);let n={name:c.name,description:c.description,license:c.license||void 0,compatibility:c.compatibility||void 0,metadata:c.metadata||void 0,content:c.content||void 0,subSkills:c.subSkills||void 0},r=await V(`/api/skills/${i.id}`,n);if(r.success){T.success("Skill updated successfully");let p=r.data||c;A(p),a({...p,id:p.name}),u(Object.entries(p.metadata||{}).map(([Re,Ee])=>({key:Re,value:Ee}))),x(!1),F?.(p)}else T.error(r.message||"Failed to update skill")}catch(t){T.error(t.message||"An error occurred while updating the skill")}finally{P(!1)}},Ie=(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"row",gap:24},children:[(0,e.jsxs)("div",{style:{flex:"0 0 320px",display:"flex",flexDirection:"column",gap:12},children:[(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Description"}),(0,e.jsx)(Ce,{value:c.description,onChange:t=>l("description",t.target.value),placeholder:"Description",rows:3})]}),(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"License"}),(0,e.jsx)(N,{value:c.license,onChange:t=>l("license",t.target.value),placeholder:"License"})]}),(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Compatibility"}),(0,e.jsx)(N,{value:c.compatibility,onChange:t=>l("compatibility",t.target.value),placeholder:"Compatibility"})]}),(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:"Metadata"}),(0,e.jsx)(k,{size:"small",icon:(0,e.jsx)(K,{}),onClick:ze,children:"Add"})]}),(0,e.jsxs)(I,{direction:"vertical",size:8,style:{width:"100%"},children:[s.length===0&&(0,e.jsx)(d,{style:{fontSize:11,color:o.colorTextTertiary},children:"No metadata yet. Use Add to create one."}),s.map((t,n)=>(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:4,width:"100%"},children:[(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextSecondary},children:["Meta ",n+1]}),(0,e.jsxs)(I,{style:{width:"100%"},size:8,wrap:!0,children:[(0,e.jsx)(N,{value:t.key,placeholder:"Key",style:{width:120},onChange:r=>Z(n,"key",r.target.value)}),(0,e.jsx)(N,{value:t.value,placeholder:"Value",style:{flex:1,minWidth:160},onChange:r=>Z(n,"value",r.target.value)})]})]},n))]})]}),(0,e.jsxs)("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:6,minWidth:400},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Content"}),(0,e.jsx)(Ce,{value:c.content,onChange:t=>l("content",t.target.value),placeholder:"Enter skill content here...",rows:30,style:{fontFamily:"monospace",fontSize:13,flex:1,minHeight:600}})]})]}),Ne=(0,e.jsxs)("div",{style:{width:z?960:720,maxHeight:"95vh",overflowY:"auto",padding:24},children:[(0,e.jsx)("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",marginBottom:16},children:(0,e.jsxs)("div",{style:{flex:1},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(d,{strong:!0,style:{fontSize:18,fontWeight:600,color:o.colorText},children:i.name}),(0,e.jsx)(D,{style:{margin:0,fontSize:10,padding:"2px 8px",fontWeight:600},color:"geekblue",children:Y.toUpperCase()})]}),(0,e.jsx)("div",{style:{display:"flex",alignItems:"center",gap:6},children:(0,e.jsx)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:`>_ ${i.id}`})})]})}),z?Ie:(0,e.jsxs)(e.Fragment,{children:[i.description&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorText,lineHeight:1.6,fontStyle:"italic"},children:['"',i.description,'"']})}),b.length>0&&(0,e.jsxs)("div",{style:{marginBottom:16},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(ce,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:["Metadata (",b.length,")"]})]}),(0,e.jsx)("div",{style:{border:`1px solid ${o.colorBorderSecondary}`,borderRadius:6,overflow:"hidden"},children:b.map(([t,n],r)=>(0,e.jsxs)("div",{style:{display:"flex",alignItems:"stretch",borderBottom:r===b.length-1?"none":`1px solid ${o.colorBorderSecondary}`},children:[(0,e.jsx)("div",{style:{width:140,padding:"8px 10px",background:o.colorFillTertiary,borderRight:`1px solid ${o.colorBorderSecondary}`,fontSize:11,color:o.colorTextSecondary,fontWeight:600,textTransform:"capitalize"},children:t}),(0,e.jsx)("div",{style:{flex:1,padding:"8px 10px",fontSize:11,color:o.colorText,wordBreak:"break-word"},children:n})]},t))})]}),O&&(0,e.jsxs)("div",{style:{marginBottom:16},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(ae,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:["Sub-Skills (",i.subSkills.length,")"]})]}),(0,e.jsx)(I,{size:[8,8],wrap:!0,children:i.subSkills.map((t,n)=>(0,e.jsx)(D,{style:{fontSize:11,padding:"4px 12px",backgroundColor:o.colorFillTertiary,color:o.colorText,border:`1px solid ${o.colorBorderSecondary}`},children:t},n))})]}),(i.license||i.compatibility)&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(I,{size:[8,8],wrap:!0,children:[i.license&&(0,e.jsx)(D,{icon:(0,e.jsx)(se,{}),style:{margin:0,fontSize:11,padding:"4px 12px",borderRadius:6,backgroundColor:o.colorInfoBg,color:o.colorInfo,border:`1px solid ${o.colorInfoBorder}`,fontWeight:500,lineHeight:"16px"},children:i.license}),i.compatibility&&(0,e.jsx)(D,{style:{margin:0,fontSize:11,padding:"4px 12px",borderRadius:6,backgroundColor:o.colorSuccessBg,color:o.colorSuccess,border:`1px solid ${o.colorSuccessBorder}`,fontWeight:500,lineHeight:"16px",display:"inline-flex",alignItems:"center",gap:4},children:i.compatibility})]})}),(i.createdAt||i.updatedAt)&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(I,{direction:"vertical",size:4,children:[i.createdAt&&(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:["Created: ",L(i.createdAt)]}),i.updatedAt&&(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:["Updated: ",L(i.updatedAt)]})]})}),i.content&&(0,e.jsxs)("div",{style:{marginBottom:0},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(de,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:600,letterSpacing:.5},children:"CONTENT"})]}),(0,e.jsx)("div",{style:{padding:16,background:o.colorFillTertiary,border:`1px solid ${o.colorBorderSecondary}`,borderRadius:6,maxHeight:400,overflowY:"auto"},children:(0,e.jsx)(d,{style:{fontSize:12,color:o.colorText,lineHeight:1.7,whiteSpace:"pre-wrap",fontFamily:"monospace"},children:i.content})})]})]}),(0,e.jsx)(te,{style:{margin:"16px 0"}}),(0,e.jsx)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:z?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(k,{block:!0,onClick:()=>{x(!1),a(g)},style:{flex:1},children:"Cancel"}),(0,e.jsx)(k,{type:"primary",block:!0,onClick:Be,loading:X,style:{flex:1},children:"Save"})]}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(k,{type:"primary",block:!0,onClick:()=>x(!0),style:{flex:1},children:"Edit Skill"}),(0,e.jsx)(k,{danger:!0,onClick:t=>{t.stopPropagation(),$(t)},children:"Delete"}),(0,e.jsx)(k,{icon:(0,e.jsx)(re,{}),onClick:()=>G(i.id),title:"Copy ID"})]})})]});return(0,e.jsxs)("div",{style:{position:"relative",padding:4,overflow:"visible"},children:[(0,e.jsx)(Q,{type:"source",position:J.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:1,height:1,borderRadius:"50%",pointerEvents:"none"},isConnectable:!1}),(0,e.jsx)(Q,{type:"target",position:J.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:1,height:1,borderRadius:"50%",pointerEvents:"none"},isConnectable:!1}),(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:6,cursor:"pointer",position:"relative"},onClick:()=>M(!0),children:[(0,e.jsx)("div",{style:{width:E,height:E,borderRadius:"50%",background:"#999",flexShrink:0,boxShadow:"0 1px 4px rgba(0,0,0,0.15)",transition:"transform 0.15s ease"},onMouseEnter:t=>{t.currentTarget.style.transform="scale(1.15)"},onMouseLeave:t=>{t.currentTarget.style.transform="scale(1)"}}),R&&(0,e.jsx)(d,{style:{position:"absolute",top:"100%",left:"50%",transform:"translateX(-50%)",marginTop:4,fontSize:10,color:o.colorTextSecondary,opacity:.45,whiteSpace:"nowrap",pointerEvents:"none",userSelect:"none"},children:i.name})]}),(0,e.jsx)(oe,{open:W,onCancel:()=>{M(!1),x(!1),a({...i,id:i.name})},footer:null,width:z?1e3:760,destroyOnClose:!0,title:null,styles:{body:{padding:0}},children:Ne})]})},we=Me;var y=B(_()),De=({onNodeClick:v})=>{let[o,C,V]=xe([]),[w,R,q]=ke([]),[g,F]=(0,S.useState)(!1),[h,i]=(0,S.useState)([]),[A,O]=(0,S.useState)(!1),[f,E]=(0,S.useState)(null),{token:Y}=j.useToken(),{get:b}=U(),L=(0,S.useMemo)(()=>({skill:we}),[]),G=(0,S.useMemo)(()=>f===null?o:o.map(a=>{let s=a.id===f||w.some(u=>u.source===f&&u.target===a.id||u.target===f&&u.source===a.id);return{...a,style:{opacity:s?1:.2,transition:"opacity 0.2s ease"}}}),[o,w,f]),z=(0,S.useMemo)(()=>f===null?w.map(a=>({...a,style:{stroke:"#1677ff",strokeWidth:1.5,opacity:.25,transition:"opacity 0.2s ease"}})):w.map(a=>{let s=a.source===f||a.target===f;return{...a,style:{stroke:"#1677ff",strokeWidth:s?2.5:1,opacity:s?1:.04,transition:"opacity 0.2s ease"}}}),[w,f]),x=async()=>{O(!0);try{let a=await b("/api/skills");a.success&&a.data&&Array.isArray(a.data.records)&&i(a.data.records)}catch(a){console.error("Failed to fetch skills:",a),i([])}finally{O(!1)}};(0,S.useEffect)(()=>{x()},[]),(0,S.useEffect)(()=>{if(!h||h.length===0){C([]),R([]);return}let a=[],s=new Map,u=[];h.forEach(l=>{s.set(l.name,l),l.subSkills&&l.subSkills.length>0&&l.subSkills.forEach($=>{h.find(H=>H.name===$)&&u.push({source:l.name,target:$})})});let W=h.map(l=>({id:l.name})),M=u.map(l=>({source:l.source,target:l.target})),X=fe(W).force("link",ge(M).id(l=>l.id).distance(80)).force("charge",ue().strength(-300)).force("center",pe(0,0)).force("collide",ye(30)).stop();for(let l=0;l<300;l++)X.tick();let P=W.map(l=>({id:l.id,type:"skill",data:{skill:s.get(l.id),onClick:()=>v?.(s.get(l.id)),onDelete:x},position:{x:l.x,y:l.y}}));u.forEach(l=>{s.has(l.source)&&s.has(l.target)&&a.push({id:`e${l.source}-${l.target}`,source:l.source,target:l.target,style:{stroke:"#1677ff",strokeWidth:2},type:"straight"})}),C(P),R(a)},[h,C,R,v]);let c=async()=>{await x()};return A?(0,y.jsx)("div",{style:{width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center",background:"#fafafa"},children:"Loading skills..."}):(0,y.jsxs)("div",{style:{width:"100%",height:"100%",background:"#fafafa",position:"relative"},children:[(0,y.jsxs)(he,{nodes:G,edges:z,onNodesChange:V,onEdgesChange:q,onNodeMouseEnter:(a,s)=>E(s.id),onNodeMouseLeave:()=>E(null),nodeTypes:L,fitView:!0,children:[(0,y.jsx)(ve,{color:"#eee",gap:20}),(0,y.jsx)(be,{})]}),(0,y.jsx)("div",{style:{position:"absolute",top:20,right:20,zIndex:10},children:(0,y.jsx)(k,{type:"primary",size:"large",icon:(0,y.jsx)(K,{}),onClick:()=>F(!0),style:{height:48,width:48,borderRadius:"50%",boxShadow:Y.boxShadowTertiary,display:"flex",alignItems:"center",justifyContent:"center",padding:0}})}),(0,y.jsx)(Te,{open:g,onCancel:()=>F(!1),onSuccess:c})]})},Fe=v=>(0,y.jsx)(Se,{children:(0,y.jsx)(De,{...v})}),it=Fe;export{it as default};
|
|
1
|
+
import{b as J,c as me,e as Q,f as Se,g as he,h as xe,i as ke,l as ve,m as be}from"./embed-page-chunk-AC6X2XRH.js";import{a as pe,b as ye,c as ge,d as fe,e as ue}from"./embed-page-chunk-SV2BM3WO.js";import"./embed-page-chunk-S4XZPBRM.js";import{t as le,x as ne,y as U,z as Te}from"./embed-page-chunk-YPNSOZYW.js";import{a as _}from"./embed-page-chunk-MB65DZAX.js";import{Ia as D,Ja as j,La as ie,Tb as de,W as k,ab as ae,fc as ce,ka as te,oa as I,qb as re,rb as se,ta as N,xa as T,ya as oe,yc as K}from"./embed-page-chunk-O4QK5LWZ.js";import{a as ee}from"./embed-page-chunk-4BKXE5ON.js";import"./embed-page-chunk-EUOOO2LS.js";import{e as B}from"./embed-page-chunk-6Y3UYJ6Z.js";var S=B(ee());var m=B(ee());var e=B(_()),{Text:d}=ie,{TextArea:Ce}=N,Me=({data:v})=>{let{token:o}=j.useToken(),{config:C}=ne(),{put:V}=U(),R=me(t=>t.transform[2])>.6,q=le("__GLOBAL__");if(!v)return null;let{skill:g,onClick:F,onDelete:h}=v;if(!g)return null;let[i,A]=(0,m.useState)(g),O=i.subSkills&&i.subSkills.length>0,f=i.subSkills?.length||0,E=(0,m.useMemo)(()=>Math.min(12+Math.sqrt(f)*10,48),[f]),Y=i.metadata&&i.metadata.category||"global",b=(0,m.useMemo)(()=>i.metadata?Object.entries(i.metadata).filter(([t,n])=>t&&n):[],[i.metadata]),L=t=>{if(!t)return"";let n=t instanceof Date?t:new Date(t);return Number.isNaN(n.getTime())?"":n.toLocaleString()},G=t=>{navigator.clipboard.writeText(t)},[z,x]=(0,m.useState)(!1),[c,a]=(0,m.useState)({...g,id:g.name}),[s,u]=(0,m.useState)(b.map(([t,n])=>({key:t,value:n}))),[W,M]=(0,m.useState)(!1),[X,P]=(0,m.useState)(!1);(0,m.useEffect)(()=>{x(!1),A(g),a({...g,id:g.name}),u(Object.entries(g.metadata||{}).map(([t,n])=>({key:t,value:n})))},[g]);let l=(t,n)=>{if(t==="name"){a(r=>({...r,name:n,id:n}));return}a(r=>({...r,[t]:n}))},$=async t=>{t?.stopPropagation(),t?.preventDefault();try{let n=i.id||i.name;if(!n){T.error("Skill ID is missing");return}await q.skills.delete(n),T.success("Skill deleted successfully"),M(!1),h&&await h()}catch(n){T.error(n?.message||"An error occurred while deleting the skill")}},H=t=>{u(t);let n=t.reduce((r,p)=>(p.key&&(r[p.key]=p.value),r),{});a(r=>({...r,metadata:n}))},Z=(t,n,r)=>{let p=[...s];p[t]={...p[t],[n]:r},H(p)},ze=()=>{H([...s,{key:"",value:""}])},Be=async()=>{try{P(!0);let t={"Content-Type":"application/json"};C.apiKey&&(t.Authorization=`Bearer ${C.apiKey}`);let n={name:c.name,description:c.description,license:c.license||void 0,compatibility:c.compatibility||void 0,metadata:c.metadata||void 0,content:c.content||void 0,subSkills:c.subSkills||void 0},r=await V(`/api/skills/${i.id}`,n);if(r.success){T.success("Skill updated successfully");let p=r.data||c;A(p),a({...p,id:p.name}),u(Object.entries(p.metadata||{}).map(([Re,Ee])=>({key:Re,value:Ee}))),x(!1),F?.(p)}else T.error(r.message||"Failed to update skill")}catch(t){T.error(t.message||"An error occurred while updating the skill")}finally{P(!1)}},Ie=(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"row",gap:24},children:[(0,e.jsxs)("div",{style:{flex:"0 0 320px",display:"flex",flexDirection:"column",gap:12},children:[(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Description"}),(0,e.jsx)(Ce,{value:c.description,onChange:t=>l("description",t.target.value),placeholder:"Description",rows:3})]}),(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"License"}),(0,e.jsx)(N,{value:c.license,onChange:t=>l("license",t.target.value),placeholder:"License"})]}),(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:6},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Compatibility"}),(0,e.jsx)(N,{value:c.compatibility,onChange:t=>l("compatibility",t.target.value),placeholder:"Compatibility"})]}),(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:"Metadata"}),(0,e.jsx)(k,{size:"small",icon:(0,e.jsx)(K,{}),onClick:ze,children:"Add"})]}),(0,e.jsxs)(I,{direction:"vertical",size:8,style:{width:"100%"},children:[s.length===0&&(0,e.jsx)(d,{style:{fontSize:11,color:o.colorTextTertiary},children:"No metadata yet. Use Add to create one."}),s.map((t,n)=>(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",gap:4,width:"100%"},children:[(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextSecondary},children:["Meta ",n+1]}),(0,e.jsxs)(I,{style:{width:"100%"},size:8,wrap:!0,children:[(0,e.jsx)(N,{value:t.key,placeholder:"Key",style:{width:120},onChange:r=>Z(n,"key",r.target.value)}),(0,e.jsx)(N,{value:t.value,placeholder:"Value",style:{flex:1,minWidth:160},onChange:r=>Z(n,"value",r.target.value)})]})]},n))]})]}),(0,e.jsxs)("div",{style:{flex:1,display:"flex",flexDirection:"column",gap:6,minWidth:400},children:[(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary},children:"Content"}),(0,e.jsx)(Ce,{value:c.content,onChange:t=>l("content",t.target.value),placeholder:"Enter skill content here...",rows:30,style:{fontFamily:"monospace",fontSize:13,flex:1,minHeight:600}})]})]}),Ne=(0,e.jsxs)("div",{style:{width:z?960:720,maxHeight:"95vh",overflowY:"auto",padding:24},children:[(0,e.jsx)("div",{style:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",marginBottom:16},children:(0,e.jsxs)("div",{style:{flex:1},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(d,{strong:!0,style:{fontSize:18,fontWeight:600,color:o.colorText},children:i.name}),(0,e.jsx)(D,{style:{margin:0,fontSize:10,padding:"2px 8px",fontWeight:600},color:"geekblue",children:Y.toUpperCase()})]}),(0,e.jsx)("div",{style:{display:"flex",alignItems:"center",gap:6},children:(0,e.jsx)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:`>_ ${i.id}`})})]})}),z?Ie:(0,e.jsxs)(e.Fragment,{children:[i.description&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorText,lineHeight:1.6,fontStyle:"italic"},children:['"',i.description,'"']})}),b.length>0&&(0,e.jsxs)("div",{style:{marginBottom:16},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(ce,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:["Metadata (",b.length,")"]})]}),(0,e.jsx)("div",{style:{border:`1px solid ${o.colorBorderSecondary}`,borderRadius:6,overflow:"hidden"},children:b.map(([t,n],r)=>(0,e.jsxs)("div",{style:{display:"flex",alignItems:"stretch",borderBottom:r===b.length-1?"none":`1px solid ${o.colorBorderSecondary}`},children:[(0,e.jsx)("div",{style:{width:140,padding:"8px 10px",background:o.colorFillTertiary,borderRight:`1px solid ${o.colorBorderSecondary}`,fontSize:11,color:o.colorTextSecondary,fontWeight:600,textTransform:"capitalize"},children:t}),(0,e.jsx)("div",{style:{flex:1,padding:"8px 10px",fontSize:11,color:o.colorText,wordBreak:"break-word"},children:n})]},t))})]}),O&&(0,e.jsxs)("div",{style:{marginBottom:16},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(ae,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsxs)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:500},children:["Sub-Skills (",i.subSkills.length,")"]})]}),(0,e.jsx)(I,{size:[8,8],wrap:!0,children:i.subSkills.map((t,n)=>(0,e.jsx)(D,{style:{fontSize:11,padding:"4px 12px",backgroundColor:o.colorFillTertiary,color:o.colorText,border:`1px solid ${o.colorBorderSecondary}`},children:t},n))})]}),(i.license||i.compatibility)&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(I,{size:[8,8],wrap:!0,children:[i.license&&(0,e.jsx)(D,{icon:(0,e.jsx)(se,{}),style:{margin:0,fontSize:11,padding:"4px 12px",borderRadius:6,backgroundColor:o.colorInfoBg,color:o.colorInfo,border:`1px solid ${o.colorInfoBorder}`,fontWeight:500,lineHeight:"16px"},children:i.license}),i.compatibility&&(0,e.jsx)(D,{style:{margin:0,fontSize:11,padding:"4px 12px",borderRadius:6,backgroundColor:o.colorSuccessBg,color:o.colorSuccess,border:`1px solid ${o.colorSuccessBorder}`,fontWeight:500,lineHeight:"16px",display:"inline-flex",alignItems:"center",gap:4},children:i.compatibility})]})}),(i.createdAt||i.updatedAt)&&(0,e.jsx)("div",{style:{marginBottom:16},children:(0,e.jsxs)(I,{direction:"vertical",size:4,children:[i.createdAt&&(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:["Created: ",L(i.createdAt)]}),i.updatedAt&&(0,e.jsxs)(d,{style:{fontSize:11,color:o.colorTextTertiary,fontFamily:"monospace"},children:["Updated: ",L(i.updatedAt)]})]})}),i.content&&(0,e.jsxs)("div",{style:{marginBottom:0},children:[(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:8,marginBottom:8},children:[(0,e.jsx)(de,{style:{fontSize:14,color:o.colorTextSecondary}}),(0,e.jsx)(d,{style:{fontSize:12,color:o.colorTextSecondary,fontWeight:600,letterSpacing:.5},children:"CONTENT"})]}),(0,e.jsx)("div",{style:{padding:16,background:o.colorFillTertiary,border:`1px solid ${o.colorBorderSecondary}`,borderRadius:6,maxHeight:400,overflowY:"auto"},children:(0,e.jsx)(d,{style:{fontSize:12,color:o.colorText,lineHeight:1.7,whiteSpace:"pre-wrap",fontFamily:"monospace"},children:i.content})})]})]}),(0,e.jsx)(te,{style:{margin:"16px 0"}}),(0,e.jsx)("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:z?(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(k,{block:!0,onClick:()=>{x(!1),a(g)},style:{flex:1},children:"Cancel"}),(0,e.jsx)(k,{type:"primary",block:!0,onClick:Be,loading:X,style:{flex:1},children:"Save"})]}):(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)(k,{type:"primary",block:!0,onClick:()=>x(!0),style:{flex:1},children:"Edit Skill"}),(0,e.jsx)(k,{danger:!0,onClick:t=>{t.stopPropagation(),$(t)},children:"Delete"}),(0,e.jsx)(k,{icon:(0,e.jsx)(re,{}),onClick:()=>G(i.id),title:"Copy ID"})]})})]});return(0,e.jsxs)("div",{style:{position:"relative",padding:4,overflow:"visible"},children:[(0,e.jsx)(Q,{type:"source",position:J.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:1,height:1,borderRadius:"50%",pointerEvents:"none"},isConnectable:!1}),(0,e.jsx)(Q,{type:"target",position:J.Top,style:{left:"50%",top:"50%",transform:"translate(-50%, -50%)",background:"transparent",border:"none",width:1,height:1,borderRadius:"50%",pointerEvents:"none"},isConnectable:!1}),(0,e.jsxs)("div",{style:{display:"flex",alignItems:"center",gap:6,cursor:"pointer",position:"relative"},onClick:()=>M(!0),children:[(0,e.jsx)("div",{style:{width:E,height:E,borderRadius:"50%",background:"#999",flexShrink:0,boxShadow:"0 1px 4px rgba(0,0,0,0.15)",transition:"transform 0.15s ease"},onMouseEnter:t=>{t.currentTarget.style.transform="scale(1.15)"},onMouseLeave:t=>{t.currentTarget.style.transform="scale(1)"}}),R&&(0,e.jsx)(d,{style:{position:"absolute",top:"100%",left:"50%",transform:"translateX(-50%)",marginTop:4,fontSize:10,color:o.colorTextSecondary,opacity:.45,whiteSpace:"nowrap",pointerEvents:"none",userSelect:"none"},children:i.name})]}),(0,e.jsx)(oe,{open:W,onCancel:()=>{M(!1),x(!1),a({...i,id:i.name})},footer:null,width:z?1e3:760,destroyOnClose:!0,title:null,styles:{body:{padding:0}},children:Ne})]})},we=Me;var y=B(_()),De=({onNodeClick:v})=>{let[o,C,V]=xe([]),[w,R,q]=ke([]),[g,F]=(0,S.useState)(!1),[h,i]=(0,S.useState)([]),[A,O]=(0,S.useState)(!1),[f,E]=(0,S.useState)(null),{token:Y}=j.useToken(),{get:b}=U(),L=(0,S.useMemo)(()=>({skill:we}),[]),G=(0,S.useMemo)(()=>f===null?o:o.map(a=>{let s=a.id===f||w.some(u=>u.source===f&&u.target===a.id||u.target===f&&u.source===a.id);return{...a,style:{opacity:s?1:.2,transition:"opacity 0.2s ease"}}}),[o,w,f]),z=(0,S.useMemo)(()=>f===null?w.map(a=>({...a,style:{stroke:"#1677ff",strokeWidth:1.5,opacity:.25,transition:"opacity 0.2s ease"}})):w.map(a=>{let s=a.source===f||a.target===f;return{...a,style:{stroke:"#1677ff",strokeWidth:s?2.5:1,opacity:s?1:.04,transition:"opacity 0.2s ease"}}}),[w,f]),x=async()=>{O(!0);try{let a=await b("/api/skills");a.success&&a.data&&Array.isArray(a.data.records)&&i(a.data.records)}catch(a){console.error("Failed to fetch skills:",a),i([])}finally{O(!1)}};(0,S.useEffect)(()=>{x()},[]),(0,S.useEffect)(()=>{if(!h||h.length===0){C([]),R([]);return}let a=[],s=new Map,u=[];h.forEach(l=>{s.set(l.name,l),l.subSkills&&l.subSkills.length>0&&l.subSkills.forEach($=>{h.find(H=>H.name===$)&&u.push({source:l.name,target:$})})});let W=h.map(l=>({id:l.name})),M=u.map(l=>({source:l.source,target:l.target})),X=fe(W).force("link",ge(M).id(l=>l.id).distance(80)).force("charge",ue().strength(-300)).force("center",pe(0,0)).force("collide",ye(30)).stop();for(let l=0;l<300;l++)X.tick();let P=W.map(l=>({id:l.id,type:"skill",data:{skill:s.get(l.id),onClick:()=>v?.(s.get(l.id)),onDelete:x},position:{x:l.x,y:l.y}}));u.forEach(l=>{s.has(l.source)&&s.has(l.target)&&a.push({id:`e${l.source}-${l.target}`,source:l.source,target:l.target,style:{stroke:"#1677ff",strokeWidth:2},type:"straight"})}),C(P),R(a)},[h,C,R,v]);let c=async()=>{await x()};return A?(0,y.jsx)("div",{style:{width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center",background:"#fafafa"},children:"Loading skills..."}):(0,y.jsxs)("div",{style:{width:"100%",height:"100%",background:"#fafafa",position:"relative"},children:[(0,y.jsxs)(he,{nodes:G,edges:z,onNodesChange:V,onEdgesChange:q,onNodeMouseEnter:(a,s)=>E(s.id),onNodeMouseLeave:()=>E(null),nodeTypes:L,fitView:!0,children:[(0,y.jsx)(ve,{color:"#eee",gap:20}),(0,y.jsx)(be,{})]}),(0,y.jsx)("div",{style:{position:"absolute",top:20,right:20,zIndex:10},children:(0,y.jsx)(k,{type:"primary",size:"large",icon:(0,y.jsx)(K,{}),onClick:()=>F(!0),style:{height:48,width:48,borderRadius:"50%",boxShadow:Y.boxShadowTertiary,display:"flex",alignItems:"center",justifyContent:"center",padding:0}})}),(0,y.jsx)(Te,{open:g,onCancel:()=>F(!1),onSuccess:c})]})},Fe=v=>(0,y.jsx)(Se,{children:(0,y.jsx)(De,{...v})}),it=Fe;export{it as default};
|