@arcgis/ai-orchestrator 5.1.0-next.73 → 5.1.0-next.74
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/index.js +479 -442
- package/dist/utils/invokeAgent.d.ts +21 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -1,66 +1,67 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { Annotation as b, StateGraph as
|
|
4
|
-
import { HumanMessage as W, AIMessage as
|
|
5
|
-
import { dispatchCustomEvent as
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import H from "@arcgis/core/
|
|
11
|
-
import
|
|
12
|
-
|
|
1
|
+
import R from "@arcgis/core/identity/IdentityManager.js";
|
|
2
|
+
import I from "@arcgis/core/portal/Portal.js";
|
|
3
|
+
import { Annotation as b, isGraphInterrupt as ne, StateGraph as re, START as se, END as ie, MemorySaver as ae } from "@langchain/langgraph/web";
|
|
4
|
+
import { HumanMessage as W, AIMessage as P, isAIMessage as oe, isToolMessage as ce } from "@langchain/core/messages";
|
|
5
|
+
import { dispatchCustomEvent as q } from "@langchain/core/callbacks/dispatch/web";
|
|
6
|
+
import p, { z as l } from "zod";
|
|
7
|
+
import { ChatPromptTemplate as N, SystemMessagePromptTemplate as de } from "@langchain/core/prompts";
|
|
8
|
+
import { createAgent as le, summarizationMiddleware as me, modelCallLimitMiddleware as ge } from "langchain";
|
|
9
|
+
import { OpenAIEmbeddings as ue, ChatOpenAI as pe } from "@langchain/openai";
|
|
10
|
+
import * as H from "@arcgis/core/core/reactiveUtils.js";
|
|
11
|
+
import O from "@arcgis/core/layers/FeatureLayer.js";
|
|
12
|
+
import he from "@arcgis/core/request.js";
|
|
13
|
+
const V = {
|
|
13
14
|
advanced: "gpt-5.2",
|
|
14
15
|
default: "gpt-5-mini",
|
|
15
16
|
fast: "gpt-5.4-nano"
|
|
16
|
-
},
|
|
17
|
+
}, k = {
|
|
17
18
|
default: "text-embedding-ada-002"
|
|
18
|
-
},
|
|
19
|
-
let
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
if (!
|
|
19
|
+
}, M = /* @__PURE__ */ new Map();
|
|
20
|
+
let E = null;
|
|
21
|
+
const fe = () => {
|
|
22
|
+
const e = I.getDefault().helperServices;
|
|
23
|
+
if (!e?.aiModels?.url)
|
|
23
24
|
throw new Error("AI Models Service URL is not defined in the portal's helper services.");
|
|
24
|
-
return
|
|
25
|
-
},
|
|
26
|
-
const
|
|
27
|
-
|
|
25
|
+
return e.aiModels.url;
|
|
26
|
+
}, z = async (t) => {
|
|
27
|
+
const e = fe();
|
|
28
|
+
M.size === 0 && (E || (E = (async () => {
|
|
28
29
|
try {
|
|
29
|
-
const n = await fetch(`${
|
|
30
|
+
const n = await fetch(`${e}/models`);
|
|
30
31
|
if (!n.ok)
|
|
31
32
|
throw new Error("Failed to fetch AI service discovery data.");
|
|
32
|
-
(await n.json()).models.forEach((
|
|
33
|
+
(await n.json()).models.forEach((a) => M.set(a.name, a));
|
|
33
34
|
} catch (n) {
|
|
34
|
-
throw
|
|
35
|
+
throw E = null, n;
|
|
35
36
|
}
|
|
36
|
-
})()), await
|
|
37
|
-
const r =
|
|
37
|
+
})()), await E);
|
|
38
|
+
const r = M.get(t);
|
|
38
39
|
if (!r)
|
|
39
|
-
throw new Error(`Model '${
|
|
40
|
+
throw new Error(`Model '${t}' is not available in the discovery service.`);
|
|
40
41
|
return r.endpoint;
|
|
41
|
-
},
|
|
42
|
-
const
|
|
42
|
+
}, ye = async (t = "default") => await z(V[t]), G = async (t = "default") => await z(k[t]), we = async (t) => {
|
|
43
|
+
const e = await ve(), r = await G("default"), n = I.getDefault(), a = (await R.getCredential(`${n.url}/sharing`)).token, i = {
|
|
43
44
|
type: "generateEmbeddings",
|
|
44
|
-
webmapEmbeddings:
|
|
45
|
-
auth: { apiUrl: r, token:
|
|
45
|
+
webmapEmbeddings: t,
|
|
46
|
+
auth: { apiUrl: r, token: a }
|
|
46
47
|
};
|
|
47
|
-
return
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
}, m = (
|
|
51
|
-
|
|
48
|
+
return e.postMessage(i), await new Promise((c, o) => {
|
|
49
|
+
const d = (g) => {
|
|
50
|
+
g.data === "completed" && (e.removeEventListener("message", d), c());
|
|
51
|
+
}, m = (g) => {
|
|
52
|
+
e.removeEventListener("message", d), o(g instanceof Error ? g : new Error("Embeddings worker error"));
|
|
52
53
|
};
|
|
53
|
-
|
|
54
|
-
}),
|
|
55
|
-
},
|
|
54
|
+
e.addEventListener("message", d), e.addEventListener("error", m, { once: !0 });
|
|
55
|
+
}), e;
|
|
56
|
+
}, ve = async () => {
|
|
56
57
|
{
|
|
57
|
-
const
|
|
58
|
-
return new
|
|
58
|
+
const t = (await import("./embeddings.worker-GH7zdYqF.js")).default;
|
|
59
|
+
return new t();
|
|
59
60
|
}
|
|
60
|
-
},
|
|
61
|
-
...
|
|
62
|
-
...
|
|
63
|
-
}),
|
|
61
|
+
}, F = (t, e) => e, be = (t, e) => ({
|
|
62
|
+
...t,
|
|
63
|
+
...e
|
|
64
|
+
}), xe = b.Root({
|
|
64
65
|
agentExecutionContext: b({
|
|
65
66
|
default: () => ({
|
|
66
67
|
userRequest: "",
|
|
@@ -68,277 +69,265 @@ const pe = () => {
|
|
|
68
69
|
priorSteps: [],
|
|
69
70
|
messages: []
|
|
70
71
|
}),
|
|
71
|
-
reducer:
|
|
72
|
+
reducer: be
|
|
72
73
|
}),
|
|
73
74
|
currentIntent: b({
|
|
74
75
|
default: () => "none",
|
|
75
|
-
reducer:
|
|
76
|
+
reducer: F
|
|
76
77
|
}),
|
|
77
78
|
requiresFollowUp: b({
|
|
78
79
|
default: () => !0,
|
|
79
|
-
reducer:
|
|
80
|
+
reducer: F
|
|
80
81
|
}),
|
|
81
82
|
stepCount: b({
|
|
82
83
|
default: () => 0,
|
|
83
|
-
reducer: (
|
|
84
|
+
reducer: (t, e) => e ?? t + 1
|
|
84
85
|
})
|
|
85
|
-
}), h = async (
|
|
86
|
-
await
|
|
87
|
-
},
|
|
88
|
-
await
|
|
89
|
-
},
|
|
90
|
-
|
|
91
|
-
},
|
|
92
|
-
if (
|
|
93
|
-
const n = new W(
|
|
94
|
-
|
|
86
|
+
}), h = async (t, e) => {
|
|
87
|
+
await q("trace_message", t, e);
|
|
88
|
+
}, ut = async (t, e) => {
|
|
89
|
+
await q("graph_ux_suggestion", t, e);
|
|
90
|
+
}, Ee = (t) => {
|
|
91
|
+
t.currentIntent = "none";
|
|
92
|
+
}, Ie = async (t, e) => {
|
|
93
|
+
if (t.agentExecutionContext.userRequest) {
|
|
94
|
+
const n = new W(t.agentExecutionContext.userRequest.trim());
|
|
95
|
+
t.agentExecutionContext.messages = [...t.agentExecutionContext.messages, n], Ee(t);
|
|
95
96
|
}
|
|
96
|
-
const r =
|
|
97
|
-
return await h({ text: `Available agents: ${[...r].join(", ")}` },
|
|
98
|
-
},
|
|
99
|
-
if (typeof
|
|
97
|
+
const r = e?.configurable?.services.agentRegistry.list().map((n) => n.agent.id) ?? [];
|
|
98
|
+
return await h({ text: `Available agents: ${[...r].join(", ")}` }, e), await h({ text: "Analyzing user input" }, e), t;
|
|
99
|
+
}, Se = async (t, e) => (await h({ text: "Exiting..." }, e), t), L = 4e3, $ = (t) => {
|
|
100
|
+
if (typeof t != "string")
|
|
100
101
|
return;
|
|
101
|
-
const
|
|
102
|
-
return
|
|
103
|
-
},
|
|
104
|
-
const r =
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
const e = t.trim();
|
|
103
|
+
return e || void 0;
|
|
104
|
+
}, Me = (t) => t === "failed" || t === "partial" || t === "success", Re = (t) => t === "failed" ? "Agent failed without a summary." : t === "partial" ? "Agent partially completed without a summary." : "Agent completed without a summary.", ke = (t, e) => {
|
|
105
|
+
const r = $(e?.outputMessage), n = $(e?.summary), s = e?.status;
|
|
106
|
+
if (!Me(s))
|
|
107
|
+
throw new Error(`Registered agent "${t}" returned an invalid or missing status.`);
|
|
107
108
|
return {
|
|
108
109
|
outputMessage: r,
|
|
109
|
-
summary: n ?? r ??
|
|
110
|
-
status:
|
|
110
|
+
summary: n ?? r ?? Re(s),
|
|
111
|
+
status: s
|
|
111
112
|
};
|
|
112
|
-
},
|
|
113
|
-
const r =
|
|
113
|
+
}, Te = async (t, e) => {
|
|
114
|
+
const r = e?.configurable, { agentRegistry: n } = r.services, s = n?.get(t.currentIntent);
|
|
114
115
|
if (!s)
|
|
115
|
-
return console.warn(`No agent found for intent: ${
|
|
116
|
-
await h({ text: `Executing registered agent: ${s.agent.name}` },
|
|
117
|
-
const
|
|
118
|
-
...
|
|
116
|
+
return console.warn(`No agent found for intent: ${t.currentIntent}`), t;
|
|
117
|
+
await h({ text: `Executing registered agent: ${s.agent.name}` }, e);
|
|
118
|
+
const a = {
|
|
119
|
+
...e ?? {},
|
|
119
120
|
configurable: {
|
|
120
121
|
...r ?? {},
|
|
121
122
|
agentId: s.agent.id,
|
|
122
123
|
context: s.getContext ? await s.getContext() : void 0
|
|
123
124
|
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
125
|
+
};
|
|
126
|
+
let i;
|
|
127
|
+
try {
|
|
128
|
+
const d = await s.agent.createGraph().compile().invoke(
|
|
129
|
+
{
|
|
130
|
+
agentExecutionContext: {
|
|
131
|
+
...t.agentExecutionContext,
|
|
132
|
+
messages: [...t.agentExecutionContext.messages],
|
|
133
|
+
priorSteps: [...t.agentExecutionContext.priorSteps ?? []]
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
a
|
|
137
|
+
);
|
|
138
|
+
i = ke(s.agent.name, d), await h({ text: `Finished executing registered agent: ${s.agent.name}` }, e);
|
|
139
|
+
} catch (d) {
|
|
140
|
+
if (ne(d))
|
|
141
|
+
throw d;
|
|
142
|
+
const m = d instanceof Error ? d.message : String(d);
|
|
143
|
+
console.error(`Agent "${s.agent.name}" failed:`, d), await h({ text: `Registered agent failed: ${s.agent.name}. ${m}` }, e), i = {
|
|
144
|
+
status: "failed",
|
|
145
|
+
outputMessage: `Agent execution failed: ${m}`,
|
|
146
|
+
summary: `Agent execution failed: ${m}`
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const c = i.outputMessage, o = [...t.agentExecutionContext.messages];
|
|
150
|
+
if (c) {
|
|
151
|
+
const d = c.length > L ? `${c.slice(0, L - 14)}
|
|
152
|
+
[truncated]` : c;
|
|
153
|
+
o.push(new P(d));
|
|
140
154
|
}
|
|
141
155
|
return {
|
|
142
|
-
...
|
|
143
|
-
stepCount:
|
|
156
|
+
...t,
|
|
157
|
+
stepCount: t.stepCount + 1,
|
|
144
158
|
agentExecutionContext: {
|
|
145
|
-
...
|
|
146
|
-
messages:
|
|
159
|
+
...t.agentExecutionContext,
|
|
160
|
+
messages: o,
|
|
147
161
|
priorSteps: [
|
|
148
|
-
...
|
|
162
|
+
...t.agentExecutionContext.priorSteps ?? [],
|
|
149
163
|
{
|
|
150
164
|
agentId: s.agent.id,
|
|
151
|
-
assignedTask:
|
|
152
|
-
summary:
|
|
153
|
-
status:
|
|
165
|
+
assignedTask: t.agentExecutionContext.assignedTask,
|
|
166
|
+
summary: i.summary,
|
|
167
|
+
status: i.status
|
|
154
168
|
}
|
|
155
169
|
]
|
|
156
170
|
}
|
|
157
171
|
};
|
|
158
|
-
},
|
|
159
|
-
const n = e
|
|
160
|
-
return n ? typeof n == "function" ? n() : Promise.resolve(n) : new Promise((s,
|
|
161
|
-
(typeof queueMicrotask == "function" ? queueMicrotask : setTimeout)(
|
|
172
|
+
}, Ae = (t, e, r) => {
|
|
173
|
+
const n = t[e];
|
|
174
|
+
return n ? typeof n == "function" ? n() : Promise.resolve(n) : new Promise((s, a) => {
|
|
175
|
+
(typeof queueMicrotask == "function" ? queueMicrotask : setTimeout)(a.bind(null, /* @__PURE__ */ new Error("Unknown variable dynamic import: " + e + (e.split("/").length !== r ? ". Note that variables only represent file names one level deep." : ""))));
|
|
162
176
|
});
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}, G = (e) => async (t, r) => {
|
|
177
|
+
}, T = async (t) => (await Ae(/* @__PURE__ */ Object.assign({ "./field_descriptions_prompt.md": () => import("./field_descriptions_prompt-haMV_aoG.js"), "./intent_prompt.md": () => import("./intent_prompt-DULnCkLt.js"), "./layer_descriptions_prompt.md": () => import("./layer_descriptions_prompt-NAaKWdJi.js") }), `./${t}.md`, 2)).default, Ce = async (t) => {
|
|
178
|
+
const { agent: e, messages: r, config: n } = t;
|
|
179
|
+
return { structuredResponse: (await e.invoke(
|
|
180
|
+
{
|
|
181
|
+
messages: r
|
|
182
|
+
},
|
|
183
|
+
n
|
|
184
|
+
)).structuredResponse };
|
|
185
|
+
}, K = (t) => async (e, r) => {
|
|
173
186
|
const n = new Headers(r?.headers);
|
|
174
|
-
return n.delete("Authorization"), n.delete("api-key"),
|
|
187
|
+
return n.delete("Authorization"), n.delete("api-key"), t && t.length > 0 && (n.set("X-Esri-Authorization", `Bearer ${t}`), n.set("X-Esri-Request-Source", "MapsSDK")), await fetch(e, {
|
|
175
188
|
...r,
|
|
176
189
|
headers: n
|
|
177
190
|
});
|
|
178
|
-
},
|
|
179
|
-
const r =
|
|
180
|
-
return new
|
|
191
|
+
}, x = async (t = "default", e = 0) => {
|
|
192
|
+
const r = I.getDefault(), n = await R.getCredential(`${r.url}/sharing`), s = V[t], a = await ye(t);
|
|
193
|
+
return new pe({
|
|
181
194
|
modelName: s,
|
|
182
195
|
apiKey: "dummy-key",
|
|
183
196
|
// 5-mini does not support temperature parameter
|
|
184
|
-
...
|
|
197
|
+
...t !== "default" && { temperature: e },
|
|
185
198
|
configuration: {
|
|
186
|
-
baseURL:
|
|
187
|
-
fetch:
|
|
199
|
+
baseURL: a,
|
|
200
|
+
fetch: K(n.token)
|
|
188
201
|
}
|
|
189
202
|
});
|
|
190
|
-
},
|
|
191
|
-
const
|
|
192
|
-
return new
|
|
203
|
+
}, De = async (t = "default") => {
|
|
204
|
+
const e = I.getDefault(), r = await R.getCredential(`${e.url}/sharing`), n = k[t], s = await G(t);
|
|
205
|
+
return new ue({
|
|
193
206
|
modelName: n,
|
|
194
207
|
apiKey: "dummy-key",
|
|
195
208
|
configuration: {
|
|
196
209
|
baseURL: s,
|
|
197
|
-
fetch:
|
|
210
|
+
fetch: K(r.token)
|
|
198
211
|
},
|
|
199
212
|
batchSize: 2048,
|
|
200
213
|
maxConcurrency: 10
|
|
201
214
|
});
|
|
202
|
-
},
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const s = n;
|
|
207
|
-
s.tool_calls && s.tool_calls.length > 0 && s.tool_calls.forEach((i) => {
|
|
208
|
-
i.id && t.add(i.id);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
return e.filter((n) => {
|
|
212
|
-
if (ae(n)) {
|
|
213
|
-
const s = n;
|
|
214
|
-
return t.has(s.tool_call_id);
|
|
215
|
-
}
|
|
216
|
-
return !0;
|
|
217
|
-
});
|
|
218
|
-
}, k = (e, t) => {
|
|
219
|
-
const r = oe.fromTemplate(e);
|
|
220
|
-
return ce.fromMessages([r, ...t]);
|
|
221
|
-
}, Ce = async (e) => {
|
|
222
|
-
const { promptText: t, modelTier: r, temperature: n, messages: s } = e, i = k(t, s ?? []), a = await R(r, n);
|
|
223
|
-
return i.pipe(a);
|
|
224
|
-
}, ct = async (e) => {
|
|
225
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: i } = e, c = await (await Ce({
|
|
226
|
-
promptText: t,
|
|
227
|
-
modelTier: r,
|
|
228
|
-
temperature: n,
|
|
229
|
-
messages: s
|
|
230
|
-
})).invoke(i ?? {});
|
|
231
|
-
if (typeof c == "string")
|
|
232
|
-
return c;
|
|
233
|
-
const o = c.content;
|
|
234
|
-
return typeof o == "string" ? o : JSON.stringify(o);
|
|
235
|
-
}, T = async (e) => {
|
|
236
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: i, schema: a } = e, c = k(t, s ?? []), l = (await R(r, n)).withStructuredOutput(a);
|
|
237
|
-
return await c.pipe(l).invoke(i ?? {});
|
|
238
|
-
}, dt = async (e) => {
|
|
239
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: i, tools: a } = e, c = a.length > 0 ? Te(s ?? []) : s ?? [], o = k(t, c), l = await R(r, n);
|
|
240
|
-
return await o.pipe(l.bindTools(a)).invoke(i ?? {});
|
|
241
|
-
}, Ae = d.object({
|
|
242
|
-
id: d.string().min(1),
|
|
243
|
-
name: d.string().min(1),
|
|
244
|
-
description: d.string().min(1)
|
|
215
|
+
}, Fe = l.object({
|
|
216
|
+
id: l.string().min(1),
|
|
217
|
+
name: l.string().min(1),
|
|
218
|
+
description: l.string().min(1)
|
|
245
219
|
});
|
|
246
|
-
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
return
|
|
220
|
+
l.array(Fe);
|
|
221
|
+
const Le = (t) => {
|
|
222
|
+
const e = t.map((n) => n.id), r = l.enum(e);
|
|
223
|
+
return l.object({
|
|
250
224
|
intent: r.nullable(),
|
|
251
|
-
assignedTask:
|
|
252
|
-
requiresFollowUp:
|
|
225
|
+
assignedTask: l.string().nullable(),
|
|
226
|
+
requiresFollowUp: l.boolean()
|
|
253
227
|
});
|
|
254
|
-
},
|
|
228
|
+
}, $e = async (t, e) => {
|
|
255
229
|
try {
|
|
256
|
-
await h({ text: "Asking LLM to
|
|
257
|
-
const
|
|
258
|
-
id:
|
|
259
|
-
name:
|
|
260
|
-
description:
|
|
230
|
+
await h({ text: "Asking LLM to route to an agent" }, e);
|
|
231
|
+
const s = (e?.configurable?.services.agentRegistry?.list() ?? []).map(({ agent: v }) => ({
|
|
232
|
+
id: v.id,
|
|
233
|
+
name: v.name,
|
|
234
|
+
description: v.description
|
|
261
235
|
}));
|
|
262
|
-
if (!
|
|
263
|
-
return await h({ text: "No agents registered; skipping intent detection" },
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
236
|
+
if (!s.length)
|
|
237
|
+
return await h({ text: "No agents registered; skipping intent detection" }, e), { ...t, currentIntent: "none" };
|
|
238
|
+
const a = await T("intent_prompt"), i = s.map((v) => JSON.stringify(v)).join(`
|
|
239
|
+
`), c = Le(s), o = {
|
|
240
|
+
registeredAgents: i,
|
|
241
|
+
priorSteps: t.agentExecutionContext.priorSteps,
|
|
242
|
+
userRequest: t.agentExecutionContext.userRequest
|
|
243
|
+
}, m = await N.fromTemplate(a).format(o), g = le({
|
|
244
|
+
model: await x("default"),
|
|
245
|
+
tools: [],
|
|
246
|
+
systemPrompt: m,
|
|
247
|
+
checkpointer: !0,
|
|
248
|
+
responseFormat: c,
|
|
249
|
+
middleware: [
|
|
250
|
+
// Preserve recent conversation context while summarizing older messages
|
|
251
|
+
// to control token usage without losing important intent signals.
|
|
252
|
+
// The trigger and keep parameters can be tuned based on token limits and behavior.
|
|
253
|
+
me({
|
|
254
|
+
model: await x("fast"),
|
|
255
|
+
trigger: { tokens: 4e3 },
|
|
256
|
+
keep: { messages: 6 }
|
|
257
|
+
}),
|
|
258
|
+
// Enforce no loop/retry.
|
|
259
|
+
// 1 usual LLM call and 1 optional summarization call.
|
|
260
|
+
ge({ runLimit: 2 })
|
|
261
|
+
]
|
|
262
|
+
}), { structuredResponse: y } = await Ce({
|
|
263
|
+
agent: g,
|
|
264
|
+
messages: t.agentExecutionContext.messages,
|
|
265
|
+
config: e
|
|
266
|
+
}), f = c.parse(
|
|
267
|
+
y ?? { intent: null, assignedTask: null, requiresFollowUp: !1 }
|
|
268
|
+
), u = f.intent ?? "none", S = {
|
|
269
|
+
...t,
|
|
270
|
+
currentIntent: u,
|
|
271
|
+
requiresFollowUp: f.requiresFollowUp,
|
|
283
272
|
agentExecutionContext: {
|
|
284
|
-
...
|
|
285
|
-
assignedTask:
|
|
273
|
+
...t.agentExecutionContext,
|
|
274
|
+
assignedTask: f.assignedTask ?? ""
|
|
286
275
|
}
|
|
287
276
|
};
|
|
288
|
-
return await h({ text: `Intent came back as: ${
|
|
289
|
-
{ text: `Agent picked: ${
|
|
290
|
-
Task Assigned: ${
|
|
291
|
-
|
|
292
|
-
),
|
|
277
|
+
return await h({ text: `Intent came back as: ${u}` }, e), await h(
|
|
278
|
+
{ text: `Agent picked: ${u}
|
|
279
|
+
Task Assigned: ${f.assignedTask ?? ""}` },
|
|
280
|
+
e
|
|
281
|
+
), S;
|
|
293
282
|
} catch (r) {
|
|
294
|
-
throw await h({ text: "Error during intent detection" },
|
|
283
|
+
throw await h({ text: "Error during intent detection" }, e), new Error(`Error during intent detection: ${r instanceof Error ? r.message : String(r)}`);
|
|
295
284
|
}
|
|
296
|
-
}, _ = 3,
|
|
297
|
-
intent:
|
|
298
|
-
followUp:
|
|
299
|
-
step:
|
|
285
|
+
}, _ = 3, _e = () => new re(xe).addNode("ingestInput", Ie).addNode("intentLLM", $e).addNode("executeRegisteredAgent", Te).addNode("exit", Se).addEdge(se, "ingestInput").addEdge("ingestInput", "intentLLM").addConditionalEdges("intentLLM", (e) => e.currentIntent === "none" ? "exit" : "executeRegisteredAgent").addConditionalEdges("executeRegisteredAgent", (e) => (console.log("[Dispatcher][executeRegisteredAgent]", {
|
|
286
|
+
intent: e.currentIntent,
|
|
287
|
+
followUp: e.requiresFollowUp,
|
|
288
|
+
step: e.stepCount,
|
|
300
289
|
maxSteps: _
|
|
301
|
-
}), !
|
|
302
|
-
class
|
|
290
|
+
}), !e.requiresFollowUp || e.stepCount >= _ ? "exit" : "intentLLM")).addEdge("exit", ie);
|
|
291
|
+
class je {
|
|
303
292
|
constructor() {
|
|
304
293
|
this.agentRegistry = /* @__PURE__ */ new Map();
|
|
305
294
|
}
|
|
306
|
-
register(
|
|
307
|
-
const { agent: r } =
|
|
295
|
+
register(e) {
|
|
296
|
+
const { agent: r } = e;
|
|
308
297
|
if (this.agentRegistry.has(r.id))
|
|
309
298
|
throw new Error(`Duplicate agent id: ${r.id}`);
|
|
310
|
-
this.agentRegistry.set(r.id,
|
|
299
|
+
this.agentRegistry.set(r.id, e);
|
|
311
300
|
}
|
|
312
|
-
get(
|
|
313
|
-
return this.agentRegistry.get(
|
|
301
|
+
get(e) {
|
|
302
|
+
return this.agentRegistry.get(e);
|
|
314
303
|
}
|
|
315
304
|
list() {
|
|
316
305
|
return [...this.agentRegistry.values()];
|
|
317
306
|
}
|
|
318
307
|
}
|
|
319
|
-
class
|
|
308
|
+
class Ue {
|
|
320
309
|
/**
|
|
321
310
|
* Create a new InterruptHandler tied to a specific compiled graph and config.
|
|
322
311
|
*/
|
|
323
|
-
constructor(
|
|
324
|
-
this.graph =
|
|
312
|
+
constructor(e, r) {
|
|
313
|
+
this.graph = e, this.config = { ...r };
|
|
325
314
|
}
|
|
326
315
|
/**
|
|
327
316
|
* Returns a promise that resolves when the user provides a HITL response.
|
|
328
317
|
*/
|
|
329
318
|
async waitForUser() {
|
|
330
|
-
return await new Promise((
|
|
331
|
-
this.resolveWait =
|
|
319
|
+
return await new Promise((e, r) => {
|
|
320
|
+
this.resolveWait = e, this.rejectWait = r;
|
|
332
321
|
});
|
|
333
322
|
}
|
|
334
323
|
/**
|
|
335
324
|
* Resume graph execution after the UI responds to an interrupt.
|
|
336
325
|
*/
|
|
337
|
-
handle(
|
|
326
|
+
handle(e, r) {
|
|
338
327
|
try {
|
|
339
328
|
const n = {
|
|
340
|
-
agentId:
|
|
341
|
-
id:
|
|
329
|
+
agentId: e.agentId,
|
|
330
|
+
id: e.id,
|
|
342
331
|
payload: r
|
|
343
332
|
}, s = this.graph.streamEvents(null, {
|
|
344
333
|
...this.config,
|
|
@@ -363,155 +352,164 @@ class _e {
|
|
|
363
352
|
this.rejectWait && (this.rejectWait(new Error("Request cancelled by user.")), this.resolveWait = void 0, this.rejectWait = void 0);
|
|
364
353
|
}
|
|
365
354
|
}
|
|
366
|
-
const
|
|
355
|
+
const We = (t) => {
|
|
356
|
+
let e = -1;
|
|
357
|
+
for (let r = t.length - 1; r >= 0; r--)
|
|
358
|
+
if (t[r] instanceof W) {
|
|
359
|
+
e = r;
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
return e === -1 ? "" : t.slice(e + 1).filter((r) => r instanceof P).map((r) => r.content).join(`
|
|
363
|
+
`);
|
|
364
|
+
}, B = async (t) => {
|
|
367
365
|
try {
|
|
368
|
-
return await (await
|
|
369
|
-
} catch (
|
|
370
|
-
throw console.error("Failed to generate embeddings:",
|
|
366
|
+
return await (await De()).embedDocuments(t);
|
|
367
|
+
} catch (e) {
|
|
368
|
+
throw console.error("Failed to generate embeddings:", e), e;
|
|
371
369
|
}
|
|
372
|
-
},
|
|
373
|
-
const r =
|
|
370
|
+
}, J = async (t, e) => {
|
|
371
|
+
const r = e.get(t);
|
|
374
372
|
if (r)
|
|
375
373
|
return r;
|
|
376
|
-
const n = await
|
|
377
|
-
return
|
|
374
|
+
const n = await B([t]);
|
|
375
|
+
return e.set(t, n[0]), n[0];
|
|
378
376
|
};
|
|
379
|
-
async function
|
|
380
|
-
const s = `req-${Date.now()}`,
|
|
377
|
+
async function Pe(t, e, r, n) {
|
|
378
|
+
const s = `req-${Date.now()}`, i = {
|
|
381
379
|
type: "layerSearch",
|
|
382
|
-
precomputedEmbedding: n ? await
|
|
380
|
+
precomputedEmbedding: n ? await J(t, n) : void 0,
|
|
383
381
|
requestId: s,
|
|
384
382
|
minScore: r
|
|
385
383
|
};
|
|
386
384
|
return await new Promise((c) => {
|
|
387
|
-
const o = (
|
|
388
|
-
|
|
385
|
+
const o = (d) => {
|
|
386
|
+
d.data.requestId === s && c(d.data.results);
|
|
389
387
|
};
|
|
390
|
-
|
|
388
|
+
e.addEventListener("message", o, { once: !0 }), e.postMessage(i);
|
|
391
389
|
});
|
|
392
390
|
}
|
|
393
|
-
function
|
|
394
|
-
const { worker:
|
|
391
|
+
function qe(t) {
|
|
392
|
+
const { worker: e } = t;
|
|
395
393
|
return {
|
|
396
394
|
async searchLayers({
|
|
397
395
|
text: r,
|
|
398
396
|
minScore: n,
|
|
399
397
|
embeddingCache: s
|
|
400
398
|
}) {
|
|
401
|
-
return await
|
|
399
|
+
return await Pe(r, e, n, s);
|
|
402
400
|
}
|
|
403
401
|
};
|
|
404
402
|
}
|
|
405
|
-
const
|
|
406
|
-
combinedQuery:
|
|
407
|
-
layerIds:
|
|
403
|
+
const Ne = async ({
|
|
404
|
+
combinedQuery: t,
|
|
405
|
+
layerIds: e,
|
|
408
406
|
embeddingsWorker: r,
|
|
409
407
|
minScore: n,
|
|
410
408
|
topResults: s,
|
|
411
|
-
embeddingCache:
|
|
409
|
+
embeddingCache: a
|
|
412
410
|
}) => {
|
|
413
|
-
const
|
|
411
|
+
const i = `req-${Date.now()}`, c = a ? await J(t, a) : void 0, o = {
|
|
414
412
|
type: "fieldSearch",
|
|
415
|
-
layerIdForFieldsSearch:
|
|
413
|
+
layerIdForFieldsSearch: e,
|
|
416
414
|
precomputedEmbedding: c,
|
|
417
|
-
requestId:
|
|
415
|
+
requestId: i,
|
|
418
416
|
minScore: n,
|
|
419
417
|
topResults: s
|
|
420
418
|
};
|
|
421
|
-
return await new Promise((
|
|
422
|
-
const m = (
|
|
423
|
-
if (
|
|
419
|
+
return await new Promise((d) => {
|
|
420
|
+
const m = (g) => {
|
|
421
|
+
if (g.data.requestId !== i)
|
|
424
422
|
return;
|
|
425
|
-
const y =
|
|
426
|
-
layerId:
|
|
427
|
-
results:
|
|
423
|
+
const y = g.data.results.map(({ layerId: f, results: u }) => ({
|
|
424
|
+
layerId: f,
|
|
425
|
+
results: u
|
|
428
426
|
}));
|
|
429
|
-
|
|
427
|
+
d(y);
|
|
430
428
|
};
|
|
431
429
|
r.addEventListener("message", m, { once: !0 }), r.postMessage(o);
|
|
432
430
|
});
|
|
433
431
|
};
|
|
434
|
-
function
|
|
435
|
-
const { worker:
|
|
432
|
+
function He(t) {
|
|
433
|
+
const { worker: e } = t;
|
|
436
434
|
return {
|
|
437
|
-
async searchFields({ text: r, layerIds: n, minScore: s, topResults:
|
|
438
|
-
return await
|
|
435
|
+
async searchFields({ text: r, layerIds: n, minScore: s, topResults: a, embeddingCache: i }) {
|
|
436
|
+
return await Ne({
|
|
439
437
|
combinedQuery: r,
|
|
440
438
|
layerIds: n,
|
|
441
|
-
embeddingsWorker:
|
|
439
|
+
embeddingsWorker: e,
|
|
442
440
|
minScore: s,
|
|
443
|
-
topResults:
|
|
444
|
-
embeddingCache:
|
|
441
|
+
topResults: a,
|
|
442
|
+
embeddingCache: i
|
|
445
443
|
});
|
|
446
444
|
}
|
|
447
445
|
};
|
|
448
446
|
}
|
|
449
|
-
const
|
|
447
|
+
const X = "0.1", w = 1536, Q = "openai", Y = k.default, A = `Name: {name}
|
|
450
448
|
Title: {title}
|
|
451
|
-
Description: {description}`,
|
|
449
|
+
Description: {description}`, C = `Name: {name}
|
|
452
450
|
Alias: {alias}
|
|
453
|
-
Description: {description}`,
|
|
454
|
-
schemaVersion:
|
|
455
|
-
modified:
|
|
456
|
-
embeddings:
|
|
457
|
-
modelProvider:
|
|
458
|
-
model:
|
|
459
|
-
dimensions:
|
|
460
|
-
templates:
|
|
461
|
-
layer:
|
|
462
|
-
field:
|
|
451
|
+
Description: {description}`, Z = l.object({
|
|
452
|
+
schemaVersion: l.literal(X),
|
|
453
|
+
modified: l.number().int().nonnegative(),
|
|
454
|
+
embeddings: l.object({
|
|
455
|
+
modelProvider: l.literal(Q),
|
|
456
|
+
model: l.literal(Y),
|
|
457
|
+
dimensions: l.literal(w),
|
|
458
|
+
templates: l.object({
|
|
459
|
+
layer: l.string().default(A),
|
|
460
|
+
field: l.string().default(C)
|
|
463
461
|
})
|
|
464
462
|
}),
|
|
465
|
-
layers:
|
|
466
|
-
|
|
467
|
-
id:
|
|
468
|
-
name:
|
|
469
|
-
title:
|
|
470
|
-
description:
|
|
471
|
-
vector:
|
|
463
|
+
layers: l.array(
|
|
464
|
+
l.object({
|
|
465
|
+
id: l.string().min(1),
|
|
466
|
+
name: l.string().min(1),
|
|
467
|
+
title: l.string().catch(""),
|
|
468
|
+
description: l.string().catch(""),
|
|
469
|
+
vector: l.array(l.number()).length(w, {
|
|
472
470
|
message: `Layer vector must be exactly ${w} dimensions`
|
|
473
471
|
}),
|
|
474
|
-
fields:
|
|
475
|
-
|
|
476
|
-
name:
|
|
477
|
-
alias:
|
|
478
|
-
description:
|
|
479
|
-
vector:
|
|
472
|
+
fields: l.array(
|
|
473
|
+
l.object({
|
|
474
|
+
name: l.string().min(1),
|
|
475
|
+
alias: l.string().catch(""),
|
|
476
|
+
description: l.string().catch(""),
|
|
477
|
+
vector: l.array(l.number()).length(w, {
|
|
480
478
|
message: `Field vector must be exactly ${w} dimensions`
|
|
481
479
|
})
|
|
482
480
|
})
|
|
483
481
|
)
|
|
484
482
|
})
|
|
485
483
|
).default([])
|
|
486
|
-
}),
|
|
487
|
-
const
|
|
488
|
-
if (!
|
|
484
|
+
}), Oe = (t) => {
|
|
485
|
+
const e = Z.safeParse(t);
|
|
486
|
+
if (!e.success)
|
|
489
487
|
throw new Error("Embeddings response validation failed. Regenerate embeddings.");
|
|
490
|
-
return
|
|
491
|
-
},
|
|
488
|
+
return e.data;
|
|
489
|
+
}, Ve = (t, e) => {
|
|
492
490
|
const r = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
493
|
-
if (
|
|
494
|
-
s instanceof
|
|
495
|
-
}),
|
|
491
|
+
if (e.allLayers.forEach((s) => {
|
|
492
|
+
s instanceof O && n.set(s.id, s);
|
|
493
|
+
}), t.length !== n.size)
|
|
496
494
|
throw new Error("Layer count mismatch during registry restoration. Regenerate embeddings.");
|
|
497
|
-
for (const s of
|
|
498
|
-
const
|
|
499
|
-
if (!
|
|
495
|
+
for (const s of t) {
|
|
496
|
+
const a = n.get(s.id);
|
|
497
|
+
if (!a)
|
|
500
498
|
throw new Error(
|
|
501
499
|
`Layer with ID ${s.id} not found in the original map during registry restoration. Regenerate embeddings.`
|
|
502
500
|
);
|
|
503
|
-
if (s.fields.length !==
|
|
501
|
+
if (s.fields.length !== a.fields.length)
|
|
504
502
|
throw new Error(
|
|
505
503
|
`Field count mismatch for layer ID ${s.id} during registry restoration. Regenerate embeddings.`
|
|
506
504
|
);
|
|
507
|
-
const
|
|
505
|
+
const i = {
|
|
508
506
|
name: s.name,
|
|
509
507
|
title: s.title,
|
|
510
508
|
description: s.description
|
|
511
509
|
}, c = /* @__PURE__ */ new Map();
|
|
512
510
|
for (const o of s.fields) {
|
|
513
|
-
const
|
|
514
|
-
if (!
|
|
511
|
+
const d = a.fieldsIndex.get(o.name);
|
|
512
|
+
if (!d)
|
|
515
513
|
throw new Error(
|
|
516
514
|
`Field with name ${o.name} not found in the original layer ${s.id} during registry restoration. Regenerate embeddings.`
|
|
517
515
|
);
|
|
@@ -519,56 +517,56 @@ Description: {description}`, Y = d.object({
|
|
|
519
517
|
name: o.name,
|
|
520
518
|
alias: o.alias,
|
|
521
519
|
description: o.description,
|
|
522
|
-
type:
|
|
523
|
-
valueType:
|
|
524
|
-
domain:
|
|
520
|
+
type: d.type || "unknown",
|
|
521
|
+
valueType: d.valueType || "unknown",
|
|
522
|
+
domain: a.getFieldDomain(o.name) ?? void 0
|
|
525
523
|
});
|
|
526
524
|
}
|
|
527
525
|
r.set(s.id, {
|
|
528
|
-
layerItem:
|
|
526
|
+
layerItem: i,
|
|
529
527
|
fieldRegistry: c
|
|
530
528
|
});
|
|
531
529
|
}
|
|
532
530
|
return r;
|
|
533
|
-
},
|
|
531
|
+
}, ze = async (t) => {
|
|
534
532
|
try {
|
|
535
|
-
return (await
|
|
533
|
+
return (await he(t, {
|
|
536
534
|
responseType: "json"
|
|
537
535
|
})).data;
|
|
538
|
-
} catch (
|
|
539
|
-
throw new Error(`Failed to fetch data from ${
|
|
536
|
+
} catch (e) {
|
|
537
|
+
throw new Error(`Failed to fetch data from ${t}: ${String(e)}`);
|
|
540
538
|
}
|
|
541
|
-
},
|
|
542
|
-
const
|
|
543
|
-
if (!
|
|
539
|
+
}, Ge = async (t) => {
|
|
540
|
+
const e = t.map;
|
|
541
|
+
if (!e?.portalItem)
|
|
544
542
|
throw new Error("WebMap portal item is missing.");
|
|
545
|
-
const { resources: r } = await
|
|
543
|
+
const { resources: r } = await e.portalItem.fetchResources(), n = r.find((i) => i.resource.path === "embeddings-v01.json");
|
|
546
544
|
if (!n?.resource.url)
|
|
547
545
|
throw new Error("Embeddings resource 'embeddings-v01.json' not found in the webmap portal item.");
|
|
548
|
-
const s = await
|
|
549
|
-
return
|
|
546
|
+
const s = await ze(n.resource.url);
|
|
547
|
+
return Oe(s);
|
|
550
548
|
};
|
|
551
|
-
class
|
|
549
|
+
class ee {
|
|
552
550
|
constructor() {
|
|
553
|
-
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.threadId = "", this.agentRegistry = new
|
|
551
|
+
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.threadId = "", this.agentRegistry = new je(), this.streamEpoch = 0;
|
|
554
552
|
}
|
|
555
553
|
/**
|
|
556
554
|
* Creates and returns an AI-ready Orchestrator instance.
|
|
557
555
|
* @param deps Core dependencies (layer/field registry plus optional map views).
|
|
558
556
|
* @returns Ready Orchestrator.
|
|
559
557
|
*/
|
|
560
|
-
static async init(
|
|
561
|
-
const r = new
|
|
558
|
+
static async init(e) {
|
|
559
|
+
const r = new ee();
|
|
562
560
|
try {
|
|
563
|
-
if (
|
|
564
|
-
await
|
|
565
|
-
const n = await
|
|
561
|
+
if (e.view?.map) {
|
|
562
|
+
await H.whenOnce(() => e.view.ready);
|
|
563
|
+
const n = await Ge(e.view), s = Ve(
|
|
566
564
|
n.layers,
|
|
567
|
-
|
|
565
|
+
e.view.map
|
|
568
566
|
);
|
|
569
|
-
r.layersAndFieldsRegistry = s, r.embeddingsWorker = await
|
|
567
|
+
r.layersAndFieldsRegistry = s, r.embeddingsWorker = await we(n);
|
|
570
568
|
}
|
|
571
|
-
return
|
|
569
|
+
return e.agents?.forEach((n) => {
|
|
572
570
|
r.agentRegistry.register(n);
|
|
573
571
|
}), r.orchestratorReady = !0, r;
|
|
574
572
|
} catch (n) {
|
|
@@ -583,15 +581,15 @@ class Z {
|
|
|
583
581
|
* - `completed`: final result with chat history + layer styling
|
|
584
582
|
* - `cancelled`: user aborted the run
|
|
585
583
|
*/
|
|
586
|
-
async *ask(
|
|
584
|
+
async *ask(e) {
|
|
587
585
|
if (!this.orchestratorReady)
|
|
588
586
|
throw new Error("Orchestrator is not ready yet.");
|
|
589
587
|
if (!this.agentRegistry.list().length)
|
|
590
588
|
throw new Error("Orchestrator has no registered agents.");
|
|
591
|
-
if (++this.streamEpoch, !
|
|
589
|
+
if (++this.streamEpoch, !e.trim())
|
|
592
590
|
return;
|
|
593
|
-
this.threadId = String(Date.now()), this.graph || (this.graph =
|
|
594
|
-
const r = this.embeddingsWorker ?
|
|
591
|
+
this.threadId = String(Date.now()), this.graph || (this.graph = _e().compile({ checkpointer: new ae() }));
|
|
592
|
+
const r = this.embeddingsWorker ? qe({ worker: this.embeddingsWorker }) : void 0, n = this.embeddingsWorker ? He({ worker: this.embeddingsWorker }) : void 0, s = /* @__PURE__ */ new Map(), i = {
|
|
595
593
|
version: "v2",
|
|
596
594
|
streamMode: "custom",
|
|
597
595
|
configurable: {
|
|
@@ -608,24 +606,24 @@ class Z {
|
|
|
608
606
|
},
|
|
609
607
|
subgraphs: !0
|
|
610
608
|
}, c = this.graph?.streamEvents(
|
|
611
|
-
{ agentExecutionContext: { userRequest:
|
|
612
|
-
|
|
609
|
+
{ agentExecutionContext: { userRequest: e, messages: this.chatHistory, priorSteps: this.priorSteps } },
|
|
610
|
+
i
|
|
613
611
|
), o = ++this.streamEpoch;
|
|
614
612
|
for (yield* this.pipeStream(c, o); ; ) {
|
|
615
|
-
const
|
|
616
|
-
if (!
|
|
613
|
+
const f = (await this.graph.getState(i, { subgraphs: !0 })).tasks.find((u) => u.interrupts.length > 0)?.interrupts[0]?.value;
|
|
614
|
+
if (!f)
|
|
617
615
|
break;
|
|
618
|
-
this.currentInterrupt =
|
|
616
|
+
this.currentInterrupt = f, this.interruptHandler = new Ue(this.graph, i), yield { runId: this.threadId, timestamp: Date.now(), type: "interrupt", interrupt: f };
|
|
619
617
|
try {
|
|
620
|
-
const
|
|
621
|
-
yield* this.pipeStream(
|
|
622
|
-
} catch (
|
|
623
|
-
if (
|
|
618
|
+
const u = await this.interruptHandler.waitForUser(), S = ++this.streamEpoch;
|
|
619
|
+
yield* this.pipeStream(u, S);
|
|
620
|
+
} catch (u) {
|
|
621
|
+
if (u) {
|
|
624
622
|
yield {
|
|
625
623
|
runId: this.threadId,
|
|
626
624
|
timestamp: Date.now(),
|
|
627
625
|
type: "error",
|
|
628
|
-
error: { message:
|
|
626
|
+
error: { message: u?.message }
|
|
629
627
|
};
|
|
630
628
|
return;
|
|
631
629
|
}
|
|
@@ -633,12 +631,12 @@ class Z {
|
|
|
633
631
|
return;
|
|
634
632
|
}
|
|
635
633
|
}
|
|
636
|
-
const m = (await this.graph.getState(
|
|
634
|
+
const m = (await this.graph.getState(i, { subgraphs: !0 })).values;
|
|
637
635
|
this.chatHistory = m.agentExecutionContext.messages.length ? m.agentExecutionContext.messages : this.chatHistory, this.priorSteps = m.agentExecutionContext.priorSteps?.slice(-5) ?? [], yield {
|
|
638
636
|
runId: this.threadId,
|
|
639
637
|
timestamp: Date.now(),
|
|
640
638
|
type: "completed",
|
|
641
|
-
result: { content:
|
|
639
|
+
result: { content: We(m.agentExecutionContext.messages) }
|
|
642
640
|
};
|
|
643
641
|
}
|
|
644
642
|
/**
|
|
@@ -651,10 +649,10 @@ class Z {
|
|
|
651
649
|
* Generic resume for any HITL interrupt.
|
|
652
650
|
* The payload is whatever the UI collected (e.g. "yes", "no", layerId, etc).
|
|
653
651
|
*/
|
|
654
|
-
resumeInterrupt(
|
|
652
|
+
resumeInterrupt(e) {
|
|
655
653
|
if (!this.currentInterrupt || !this.interruptHandler)
|
|
656
654
|
throw new Error("No pending interrupt to resume.");
|
|
657
|
-
this.interruptHandler.handle(this.currentInterrupt,
|
|
655
|
+
this.interruptHandler.handle(this.currentInterrupt, e);
|
|
658
656
|
}
|
|
659
657
|
/**
|
|
660
658
|
* Optional: allow UI to cancel the current HITL.
|
|
@@ -662,8 +660,8 @@ class Z {
|
|
|
662
660
|
cancelInterrupt() {
|
|
663
661
|
this.interruptHandler && this.interruptHandler.cancel();
|
|
664
662
|
}
|
|
665
|
-
async *pipeStream(
|
|
666
|
-
for await (const n of
|
|
663
|
+
async *pipeStream(e, r) {
|
|
664
|
+
for await (const n of e) {
|
|
667
665
|
if (r !== this.streamEpoch) {
|
|
668
666
|
console.log("Stale stream detected, aborting.");
|
|
669
667
|
break;
|
|
@@ -684,155 +682,194 @@ class Z {
|
|
|
684
682
|
this.embeddingsWorker && (this.embeddingsWorker.terminate(), this.embeddingsWorker = void 0), this.orchestratorReady = !1;
|
|
685
683
|
}
|
|
686
684
|
}
|
|
687
|
-
const
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
685
|
+
const Ke = (t) => {
|
|
686
|
+
const e = /* @__PURE__ */ new Set();
|
|
687
|
+
for (const n of t)
|
|
688
|
+
if (oe(n)) {
|
|
689
|
+
const s = n;
|
|
690
|
+
s.tool_calls && s.tool_calls.length > 0 && s.tool_calls.forEach((a) => {
|
|
691
|
+
a.id && e.add(a.id);
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
return t.filter((n) => {
|
|
695
|
+
if (ce(n)) {
|
|
696
|
+
const s = n;
|
|
697
|
+
return e.has(s.tool_call_id);
|
|
698
|
+
}
|
|
699
|
+
return !0;
|
|
700
|
+
});
|
|
701
|
+
}, D = (t, e) => {
|
|
702
|
+
const r = de.fromTemplate(t);
|
|
703
|
+
return N.fromMessages([r, ...e]);
|
|
704
|
+
}, Be = async (t) => {
|
|
705
|
+
const { promptText: e, modelTier: r, temperature: n, messages: s } = t, a = D(e, s ?? []), i = await x(r, n);
|
|
706
|
+
return a.pipe(i);
|
|
707
|
+
}, pt = async (t) => {
|
|
708
|
+
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a } = t, c = await (await Be({
|
|
709
|
+
promptText: e,
|
|
710
|
+
modelTier: r,
|
|
711
|
+
temperature: n,
|
|
712
|
+
messages: s
|
|
713
|
+
})).invoke(a ?? {});
|
|
714
|
+
if (typeof c == "string")
|
|
715
|
+
return c;
|
|
716
|
+
const o = c.content;
|
|
717
|
+
return typeof o == "string" ? o : JSON.stringify(o);
|
|
718
|
+
}, te = async (t) => {
|
|
719
|
+
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, schema: i } = t, c = D(e, s ?? []), d = (await x(r, n)).withStructuredOutput(i);
|
|
720
|
+
return await c.pipe(d).invoke(a ?? {});
|
|
721
|
+
}, ht = async (t) => {
|
|
722
|
+
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, tools: i } = t, c = i.length > 0 ? Ke(s ?? []) : s ?? [], o = D(e, c), d = await x(r, n);
|
|
723
|
+
return await o.pipe(d.bindTools(i)).invoke(a ?? {});
|
|
724
|
+
}, Je = p.object({
|
|
725
|
+
name: p.string(),
|
|
726
|
+
description: p.string(),
|
|
727
|
+
valueType: p.string(),
|
|
728
|
+
alias: p.string()
|
|
729
|
+
}), Xe = p.object({
|
|
730
|
+
fields: p.array(Je)
|
|
694
731
|
});
|
|
695
|
-
function j(
|
|
732
|
+
function j(t, e) {
|
|
696
733
|
const r = /* @__PURE__ */ new Map();
|
|
697
|
-
for (const n of
|
|
698
|
-
const s =
|
|
734
|
+
for (const n of t.fields) {
|
|
735
|
+
const s = e.fields.find((i) => i.name === n.name), a = {
|
|
699
736
|
name: n.name,
|
|
700
737
|
type: n.type,
|
|
701
738
|
alias: s?.alias ?? n.alias ?? "",
|
|
702
739
|
description: s?.description ?? n.description ?? "",
|
|
703
740
|
valueType: s?.valueType ?? n.valueType ?? "",
|
|
704
|
-
domain:
|
|
741
|
+
domain: t.getFieldDomain(n.name) ?? void 0
|
|
705
742
|
};
|
|
706
|
-
r.set(n.name,
|
|
743
|
+
r.set(n.name, a);
|
|
707
744
|
}
|
|
708
745
|
return r;
|
|
709
746
|
}
|
|
710
|
-
const
|
|
711
|
-
const r = await
|
|
712
|
-
const { name: c, type: o, alias:
|
|
713
|
-
return [`Name: ${c}`, `Type: ${o}`, `Alias: ${
|
|
747
|
+
const Qe = async (t) => {
|
|
748
|
+
const r = await T("field_descriptions_prompt"), n = t.fields.filter((i) => !(i.alias && i.description)).map((i) => {
|
|
749
|
+
const { name: c, type: o, alias: d, description: m } = i;
|
|
750
|
+
return [`Name: ${c}`, `Type: ${o}`, `Alias: ${d}`, `Description: ${m ?? "N/A"}`].join(", ");
|
|
714
751
|
}).join(`
|
|
715
752
|
`);
|
|
716
753
|
if (n.length === 0)
|
|
717
|
-
return j(
|
|
754
|
+
return j(t, { fields: [] });
|
|
718
755
|
const s = {
|
|
719
|
-
existingItemTitle:
|
|
720
|
-
existingItemDescription:
|
|
721
|
-
existingLayerTitle:
|
|
722
|
-
existingLayerDescription:
|
|
756
|
+
existingItemTitle: t.portalItem?.title,
|
|
757
|
+
existingItemDescription: t.portalItem?.description,
|
|
758
|
+
existingLayerTitle: t.title,
|
|
759
|
+
existingLayerDescription: t.portalItem?.description,
|
|
723
760
|
fieldInformation: n
|
|
724
|
-
},
|
|
761
|
+
}, a = await te({
|
|
725
762
|
promptText: r,
|
|
726
|
-
schema:
|
|
763
|
+
schema: Xe,
|
|
727
764
|
inputVariables: s
|
|
728
765
|
});
|
|
729
|
-
return j(
|
|
730
|
-
},
|
|
731
|
-
title:
|
|
732
|
-
description:
|
|
733
|
-
name:
|
|
734
|
-
}),
|
|
735
|
-
const n = await
|
|
766
|
+
return j(t, a);
|
|
767
|
+
}, Ye = p.object({
|
|
768
|
+
title: p.string(),
|
|
769
|
+
description: p.string(),
|
|
770
|
+
name: p.string().nullable()
|
|
771
|
+
}), Ze = async (t, e) => {
|
|
772
|
+
const n = await T("layer_descriptions_prompt"), s = Array.from(e.values()), a = {
|
|
736
773
|
fieldInformation: JSON.stringify(s, null, 2),
|
|
737
|
-
existingLayerTitle:
|
|
738
|
-
existingLayerDescription:
|
|
739
|
-
existingLayerSnippet:
|
|
740
|
-
layerGeometryType:
|
|
774
|
+
existingLayerTitle: t.title,
|
|
775
|
+
existingLayerDescription: t.portalItem?.description,
|
|
776
|
+
existingLayerSnippet: t.portalItem?.snippet,
|
|
777
|
+
layerGeometryType: t.geometryType
|
|
741
778
|
};
|
|
742
|
-
return { ...await
|
|
779
|
+
return { ...await te({
|
|
743
780
|
promptText: n,
|
|
744
|
-
schema:
|
|
745
|
-
inputVariables:
|
|
746
|
-
}), name:
|
|
747
|
-
},
|
|
748
|
-
const
|
|
749
|
-
for (const s of
|
|
750
|
-
if (s instanceof
|
|
751
|
-
const
|
|
752
|
-
const
|
|
753
|
-
n.set(s.id, { layerItem: c, fieldRegistry:
|
|
781
|
+
schema: Ye,
|
|
782
|
+
inputVariables: a
|
|
783
|
+
}), name: t.title ?? null };
|
|
784
|
+
}, et = async (t) => {
|
|
785
|
+
const e = t.allLayers.toArray(), r = [], n = /* @__PURE__ */ new Map();
|
|
786
|
+
for (const s of e)
|
|
787
|
+
if (s instanceof O) {
|
|
788
|
+
const a = (async () => {
|
|
789
|
+
const i = await Qe(s), c = await Ze(s, i);
|
|
790
|
+
n.set(s.id, { layerItem: c, fieldRegistry: i });
|
|
754
791
|
})();
|
|
755
|
-
r.push(
|
|
792
|
+
r.push(a);
|
|
756
793
|
}
|
|
757
794
|
return await Promise.all(r), n;
|
|
758
|
-
},
|
|
759
|
-
await
|
|
760
|
-
const
|
|
761
|
-
schemaVersion:
|
|
795
|
+
}, ft = async (t) => {
|
|
796
|
+
await H.whenOnce(() => t.ready);
|
|
797
|
+
const e = await et(t.map), { layers: r } = await tt(e), n = {
|
|
798
|
+
schemaVersion: X,
|
|
762
799
|
modified: Date.now(),
|
|
763
800
|
embeddings: {
|
|
764
|
-
modelProvider:
|
|
765
|
-
model:
|
|
801
|
+
modelProvider: Q,
|
|
802
|
+
model: Y,
|
|
766
803
|
dimensions: w,
|
|
767
804
|
templates: {
|
|
768
|
-
layer:
|
|
769
|
-
field:
|
|
805
|
+
layer: A,
|
|
806
|
+
field: C
|
|
770
807
|
}
|
|
771
808
|
},
|
|
772
809
|
layers: r
|
|
773
|
-
}, s =
|
|
810
|
+
}, s = Z.safeParse(n);
|
|
774
811
|
if (!s.success)
|
|
775
812
|
throw console.error("Schema Mismatch:", s.error.format()), new Error("Webmap embedding generation failed validation.");
|
|
776
813
|
return s.data;
|
|
777
|
-
},
|
|
778
|
-
const
|
|
779
|
-
for (const [
|
|
780
|
-
const
|
|
814
|
+
}, tt = async (t) => {
|
|
815
|
+
const e = [], r = [];
|
|
816
|
+
for (const [i, { fieldRegistry: c, layerItem: o }] of t.entries()) {
|
|
817
|
+
const d = U(A, {
|
|
781
818
|
name: o.name,
|
|
782
819
|
title: o.title,
|
|
783
820
|
description: o.description
|
|
784
821
|
});
|
|
785
|
-
|
|
822
|
+
e.push(d);
|
|
786
823
|
const m = {
|
|
787
|
-
id:
|
|
824
|
+
id: i,
|
|
788
825
|
name: o.name ?? "",
|
|
789
826
|
title: o.title,
|
|
790
827
|
description: o.description,
|
|
791
828
|
vector: [],
|
|
792
829
|
fields: []
|
|
793
830
|
};
|
|
794
|
-
for (const [,
|
|
795
|
-
const y = U(
|
|
796
|
-
name:
|
|
797
|
-
alias:
|
|
798
|
-
description:
|
|
831
|
+
for (const [, g] of c.entries()) {
|
|
832
|
+
const y = U(C, {
|
|
833
|
+
name: g.name,
|
|
834
|
+
alias: g.alias,
|
|
835
|
+
description: g.description
|
|
799
836
|
});
|
|
800
|
-
|
|
801
|
-
name:
|
|
802
|
-
alias:
|
|
803
|
-
description:
|
|
837
|
+
e.push(y), m.fields.push({
|
|
838
|
+
name: g.name,
|
|
839
|
+
alias: g.alias,
|
|
840
|
+
description: g.description,
|
|
804
841
|
vector: []
|
|
805
842
|
});
|
|
806
843
|
}
|
|
807
844
|
r.push(m);
|
|
808
845
|
}
|
|
809
|
-
const n = await
|
|
846
|
+
const n = await B(e);
|
|
810
847
|
let s = 0;
|
|
811
|
-
return { layers: r.map((
|
|
848
|
+
return { layers: r.map((i) => (i.vector = n[s++], i.fields.forEach((c) => {
|
|
812
849
|
c.vector = n[s++];
|
|
813
|
-
}),
|
|
814
|
-
}, U = (
|
|
815
|
-
if (
|
|
850
|
+
}), i)) };
|
|
851
|
+
}, U = (t, e) => t.replace(/\{(\w+)\}/gu, (r, n) => e[n] ?? ""), yt = (t, e) => {
|
|
852
|
+
if (t.length !== e.length)
|
|
816
853
|
throw new Error("Vectors must be the same length");
|
|
817
854
|
let r = 0, n = 0, s = 0;
|
|
818
|
-
for (let c = 0; c <
|
|
819
|
-
const o =
|
|
820
|
-
r += o *
|
|
855
|
+
for (let c = 0; c < t.length; ++c) {
|
|
856
|
+
const o = t[c], d = e[c];
|
|
857
|
+
r += o * d, n += o * o, s += d * d;
|
|
821
858
|
}
|
|
822
|
-
const
|
|
823
|
-
if (
|
|
859
|
+
const a = Math.sqrt(n * s);
|
|
860
|
+
if (a === 0)
|
|
824
861
|
return 0;
|
|
825
|
-
const
|
|
826
|
-
return Math.max(-1, Math.min(1,
|
|
862
|
+
const i = r / a;
|
|
863
|
+
return Math.max(-1, Math.min(1, i));
|
|
827
864
|
};
|
|
828
865
|
export {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
866
|
+
ee as Orchestrator,
|
|
867
|
+
yt as cosineSimilarity,
|
|
868
|
+
ft as createWebmapEmbeddings,
|
|
869
|
+
B as getEmbeddings,
|
|
870
|
+
te as invokeStructuredPrompt,
|
|
871
|
+
pt as invokeTextPrompt,
|
|
872
|
+
ht as invokeToolPrompt,
|
|
836
873
|
h as sendTraceMessage,
|
|
837
|
-
|
|
874
|
+
ut as sendUXSuggestion
|
|
838
875
|
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseMessage } from '@langchain/core/messages';
|
|
2
|
+
import { RunnableConfig } from '@langchain/core/runnables';
|
|
3
|
+
type AgentInvoker = {
|
|
4
|
+
invoke: (input: {
|
|
5
|
+
messages: BaseMessage[];
|
|
6
|
+
}, config?: RunnableConfig) => Promise<Record<string, unknown> | {
|
|
7
|
+
messages: BaseMessage[];
|
|
8
|
+
}>;
|
|
9
|
+
};
|
|
10
|
+
type InvokeAgentOptions = {
|
|
11
|
+
agent: AgentInvoker;
|
|
12
|
+
messages: BaseMessage[];
|
|
13
|
+
config?: RunnableConfig;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Invokes an agent with a runnable config and returns the latest AI text response.
|
|
17
|
+
*/
|
|
18
|
+
export declare const invokeAgent: (options: InvokeAgentOptions) => Promise<{
|
|
19
|
+
structuredResponse?: unknown;
|
|
20
|
+
}>;
|
|
21
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcgis/ai-orchestrator",
|
|
3
|
-
"version": "5.1.0-next.
|
|
3
|
+
"version": "5.1.0-next.74",
|
|
4
4
|
"description": "ArcGIS AI Orchestrator Package",
|
|
5
5
|
"homepage": "https://developers.arcgis.com/javascript/latest/",
|
|
6
6
|
"type": "module",
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
],
|
|
17
17
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@langchain/core": "^1.1.
|
|
20
|
-
"@langchain/langgraph": "^1.2.
|
|
21
|
-
"@langchain/openai": "^1.3
|
|
19
|
+
"@langchain/core": "^1.1.39",
|
|
20
|
+
"@langchain/langgraph": "^1.2.6",
|
|
21
|
+
"@langchain/openai": "^1.4.3",
|
|
22
|
+
"langchain": "^1.3.1",
|
|
22
23
|
"tslib": "^2.8.1",
|
|
23
24
|
"zod": "^4.3.6"
|
|
24
25
|
},
|