@arcgis/ai-orchestrator 5.1.0-next.84 → 5.1.0-next.85
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
CHANGED
|
@@ -1,111 +1,122 @@
|
|
|
1
1
|
import R from "@arcgis/core/identity/IdentityManager.js";
|
|
2
|
-
import
|
|
3
|
-
import { Annotation as
|
|
4
|
-
import { HumanMessage as
|
|
5
|
-
import { dispatchCustomEvent as
|
|
2
|
+
import E from "@arcgis/core/portal/Portal.js";
|
|
3
|
+
import { Annotation as v, isGraphInterrupt as re, StateGraph as se, START as ie, END as ae, MemorySaver as oe } from "@langchain/langgraph/web";
|
|
4
|
+
import { HumanMessage as P, AIMessage as q, isAIMessage as ce, isToolMessage as de } from "@langchain/core/messages";
|
|
5
|
+
import { dispatchCustomEvent as N } from "@langchain/core/callbacks/dispatch/web";
|
|
6
6
|
import p, { z as l } from "zod";
|
|
7
|
-
import { ChatPromptTemplate as
|
|
8
|
-
import { createAgent as
|
|
9
|
-
import { ChatOpenAI as
|
|
10
|
-
import * as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
const
|
|
7
|
+
import { ChatPromptTemplate as H, SystemMessagePromptTemplate as le } from "@langchain/core/prompts";
|
|
8
|
+
import { createAgent as me, summarizationMiddleware as ue, modelCallLimitMiddleware as ge } from "langchain";
|
|
9
|
+
import { ChatOpenAI as pe, OpenAIEmbeddings as he } from "@langchain/openai";
|
|
10
|
+
import * as O from "@arcgis/core/core/reactiveUtils.js";
|
|
11
|
+
import V from "@arcgis/core/layers/FeatureLayer.js";
|
|
12
|
+
import fe from "@arcgis/core/request.js";
|
|
13
|
+
const z = {
|
|
14
14
|
advanced: "gpt-5.2",
|
|
15
15
|
default: "gpt-5-mini",
|
|
16
16
|
fast: "gpt-5.4-nano"
|
|
17
17
|
}, k = {
|
|
18
18
|
default: "text-embedding-ada-002"
|
|
19
19
|
}, M = /* @__PURE__ */ new Map();
|
|
20
|
-
let
|
|
21
|
-
const
|
|
22
|
-
const e =
|
|
20
|
+
let x = null;
|
|
21
|
+
const ye = () => {
|
|
22
|
+
const e = E.getDefault().helperServices;
|
|
23
23
|
if (!e?.aiModels?.url)
|
|
24
24
|
throw new Error("AI Models Service URL is not defined in the portal's helper services.");
|
|
25
25
|
return e.aiModels.url;
|
|
26
|
-
},
|
|
27
|
-
const e =
|
|
28
|
-
M.size === 0 && (
|
|
26
|
+
}, G = async (t) => {
|
|
27
|
+
const e = ye();
|
|
28
|
+
M.size === 0 && (x || (x = (async () => {
|
|
29
29
|
try {
|
|
30
30
|
const n = await fetch(`${e}/models`);
|
|
31
31
|
if (!n.ok)
|
|
32
32
|
throw new Error("Failed to fetch AI service discovery data.");
|
|
33
33
|
(await n.json()).models.forEach((a) => M.set(a.name, a));
|
|
34
34
|
} catch (n) {
|
|
35
|
-
throw
|
|
35
|
+
throw x = null, n;
|
|
36
36
|
}
|
|
37
|
-
})()), await
|
|
37
|
+
})()), await x);
|
|
38
38
|
const r = M.get(t);
|
|
39
39
|
if (!r)
|
|
40
40
|
throw new Error(`Model '${t}' is not available in the discovery service.`);
|
|
41
41
|
return r.endpoint;
|
|
42
|
-
},
|
|
43
|
-
const e = await
|
|
42
|
+
}, we = async (t = "default") => await G(z[t]), K = async (t = "default") => await G(k[t]), ve = async (t) => {
|
|
43
|
+
const e = await be(), r = await K("default"), n = E.getDefault(), a = (await R.getCredential(`${n.url}/sharing`)).token, i = {
|
|
44
44
|
type: "generateEmbeddings",
|
|
45
45
|
webmapEmbeddings: t,
|
|
46
46
|
auth: { apiUrl: r, token: a }
|
|
47
47
|
};
|
|
48
48
|
return e.postMessage(i), await new Promise((c, o) => {
|
|
49
|
-
const d = (
|
|
50
|
-
|
|
51
|
-
}, m = (
|
|
52
|
-
e.removeEventListener("message", d), o(
|
|
49
|
+
const d = (u) => {
|
|
50
|
+
u.data === "completed" && (e.removeEventListener("message", d), c());
|
|
51
|
+
}, m = (u) => {
|
|
52
|
+
e.removeEventListener("message", d), o(u instanceof Error ? u : new Error("Embeddings worker error"));
|
|
53
53
|
};
|
|
54
54
|
e.addEventListener("message", d), e.addEventListener("error", m, { once: !0 });
|
|
55
55
|
}), e;
|
|
56
|
-
},
|
|
56
|
+
}, be = async () => {
|
|
57
57
|
{
|
|
58
58
|
const t = (await import("./embeddings.worker-GH7zdYqF.js")).default;
|
|
59
59
|
return new t();
|
|
60
60
|
}
|
|
61
|
-
}, F = (t, e) => e,
|
|
61
|
+
}, F = (t, e) => e, xe = (t, e) => ({
|
|
62
62
|
...t,
|
|
63
63
|
...e
|
|
64
|
-
}),
|
|
65
|
-
agentExecutionContext:
|
|
64
|
+
}), Ee = v.Root({
|
|
65
|
+
agentExecutionContext: v({
|
|
66
66
|
default: () => ({
|
|
67
67
|
userRequest: "",
|
|
68
68
|
assignedTask: "",
|
|
69
69
|
priorSteps: [],
|
|
70
70
|
messages: []
|
|
71
71
|
}),
|
|
72
|
-
reducer:
|
|
72
|
+
reducer: xe
|
|
73
73
|
}),
|
|
74
|
-
currentIntent:
|
|
74
|
+
currentIntent: v({
|
|
75
75
|
default: () => "none",
|
|
76
76
|
reducer: F
|
|
77
77
|
}),
|
|
78
|
-
requiresFollowUp:
|
|
78
|
+
requiresFollowUp: v({
|
|
79
79
|
default: () => !0,
|
|
80
80
|
reducer: F
|
|
81
81
|
}),
|
|
82
|
-
stepCount:
|
|
82
|
+
stepCount: v({
|
|
83
83
|
default: () => 0,
|
|
84
84
|
reducer: (t, e) => e ?? t + 1
|
|
85
85
|
})
|
|
86
86
|
}), h = async (t, e) => {
|
|
87
|
-
await
|
|
88
|
-
},
|
|
89
|
-
await
|
|
90
|
-
},
|
|
87
|
+
await N("trace_message", t, e);
|
|
88
|
+
}, gt = async (t, e) => {
|
|
89
|
+
await N("graph_ux_suggestion", t, e);
|
|
90
|
+
}, Ie = (t) => {
|
|
91
91
|
t.currentIntent = "none";
|
|
92
|
-
},
|
|
92
|
+
}, Se = async (t, e) => {
|
|
93
93
|
if (t.agentExecutionContext.userRequest) {
|
|
94
|
-
const n = new
|
|
95
|
-
t.agentExecutionContext.messages = [...t.agentExecutionContext.messages, n],
|
|
94
|
+
const n = new P(t.agentExecutionContext.userRequest.trim());
|
|
95
|
+
t.agentExecutionContext.messages = [...t.agentExecutionContext.messages, n], Ie(t);
|
|
96
96
|
}
|
|
97
97
|
const r = e?.configurable?.services.agentRegistry.list().map((n) => n.agent.id) ?? [];
|
|
98
98
|
return await h({ text: `Available agents: ${[...r].join(", ")}` }, e), await h({ text: "Analyzing user input" }, e), t;
|
|
99
|
-
},
|
|
99
|
+
}, Me = async (t, e) => (await h({ text: "Exiting..." }, e), t), L = 4e3, $ = (t) => {
|
|
100
100
|
if (typeof t != "string")
|
|
101
101
|
return;
|
|
102
102
|
const e = t.trim();
|
|
103
103
|
return e || void 0;
|
|
104
|
-
},
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
104
|
+
}, Re = (t) => {
|
|
105
|
+
switch (t) {
|
|
106
|
+
case "failed":
|
|
107
|
+
return "Agent failed without a summary.";
|
|
108
|
+
case "partial":
|
|
109
|
+
return "Agent partially completed without a summary.";
|
|
110
|
+
case "unknown":
|
|
111
|
+
return "Agent returned with unknown status.";
|
|
112
|
+
case "success":
|
|
113
|
+
return "Agent completed without a summary.";
|
|
114
|
+
default:
|
|
115
|
+
return "Agent completed without a summary.";
|
|
116
|
+
}
|
|
117
|
+
}, ke = (t, e) => {
|
|
118
|
+
const r = $(e?.outputMessage), n = $(e?.summary), s = e?.status ?? "unknown";
|
|
119
|
+
return s === "unknown" && console.warn(`Registered agent "${t}" returned an invalid or missing status.`), {
|
|
109
120
|
outputMessage: r,
|
|
110
121
|
summary: n ?? r ?? Re(s),
|
|
111
122
|
status: s
|
|
@@ -137,7 +148,7 @@ const fe = () => {
|
|
|
137
148
|
);
|
|
138
149
|
i = ke(s.agent.name, d), await h({ text: `Finished executing registered agent: ${s.agent.name}` }, e);
|
|
139
150
|
} catch (d) {
|
|
140
|
-
if (
|
|
151
|
+
if (re(d))
|
|
141
152
|
throw d;
|
|
142
153
|
const m = d instanceof Error ? d.message : String(d);
|
|
143
154
|
console.error(`Agent "${s.agent.name}" failed:`, d), await h({ text: `Registered agent failed: ${s.agent.name}. ${m}` }, e), i = {
|
|
@@ -150,7 +161,7 @@ const fe = () => {
|
|
|
150
161
|
if (c) {
|
|
151
162
|
const d = c.length > L ? `${c.slice(0, L - 14)}
|
|
152
163
|
[truncated]` : c;
|
|
153
|
-
o.push(new
|
|
164
|
+
o.push(new q(d));
|
|
154
165
|
}
|
|
155
166
|
return {
|
|
156
167
|
...t,
|
|
@@ -174,7 +185,7 @@ const fe = () => {
|
|
|
174
185
|
return n ? typeof n == "function" ? n() : Promise.resolve(n) : new Promise((s, a) => {
|
|
175
186
|
(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." : ""))));
|
|
176
187
|
});
|
|
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-
|
|
188
|
+
}, 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-DpOkH79K.js"), "./layer_descriptions_prompt.md": () => import("./layer_descriptions_prompt-NAaKWdJi.js") }), `./${t}.md`, 2)).default, Ce = async (t) => {
|
|
178
189
|
const { agent: e, messages: r, config: n } = t;
|
|
179
190
|
return { structuredResponse: (await e.invoke(
|
|
180
191
|
{
|
|
@@ -182,32 +193,32 @@ const fe = () => {
|
|
|
182
193
|
},
|
|
183
194
|
n
|
|
184
195
|
)).structuredResponse };
|
|
185
|
-
},
|
|
196
|
+
}, B = (t) => async (e, r) => {
|
|
186
197
|
const n = new Headers(r?.headers);
|
|
187
198
|
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, {
|
|
188
199
|
...r,
|
|
189
200
|
headers: n
|
|
190
201
|
});
|
|
191
|
-
},
|
|
192
|
-
const r =
|
|
193
|
-
return new
|
|
202
|
+
}, b = async (t = "default", e = 0) => {
|
|
203
|
+
const r = E.getDefault(), n = await R.getCredential(`${r.url}/sharing`), s = z[t], a = await we(t);
|
|
204
|
+
return new pe({
|
|
194
205
|
modelName: s,
|
|
195
206
|
apiKey: "dummy-key",
|
|
196
207
|
// 5-mini does not support temperature parameter
|
|
197
208
|
...t !== "default" && { temperature: e },
|
|
198
209
|
configuration: {
|
|
199
210
|
baseURL: a,
|
|
200
|
-
fetch:
|
|
211
|
+
fetch: B(n.token)
|
|
201
212
|
}
|
|
202
213
|
});
|
|
203
214
|
}, De = async (t = "default") => {
|
|
204
|
-
const e =
|
|
205
|
-
return new
|
|
215
|
+
const e = E.getDefault(), r = await R.getCredential(`${e.url}/sharing`), n = k[t], s = await K(t);
|
|
216
|
+
return new he({
|
|
206
217
|
modelName: n,
|
|
207
218
|
apiKey: "dummy-key",
|
|
208
219
|
configuration: {
|
|
209
220
|
baseURL: s,
|
|
210
|
-
fetch:
|
|
221
|
+
fetch: B(r.token)
|
|
211
222
|
},
|
|
212
223
|
batchSize: 2048,
|
|
213
224
|
maxConcurrency: 10
|
|
@@ -218,7 +229,7 @@ const fe = () => {
|
|
|
218
229
|
description: l.string().min(1)
|
|
219
230
|
});
|
|
220
231
|
l.array(Fe);
|
|
221
|
-
const Le = (t) => {
|
|
232
|
+
const _ = (t) => JSON.stringify(t, null, 2), Le = (t) => {
|
|
222
233
|
const e = t.map((n) => n.id), r = l.enum(e);
|
|
223
234
|
return l.object({
|
|
224
235
|
intent: r.nullable(),
|
|
@@ -228,20 +239,19 @@ const Le = (t) => {
|
|
|
228
239
|
}, $e = async (t, e) => {
|
|
229
240
|
try {
|
|
230
241
|
await h({ text: "Asking LLM to route to an agent" }, e);
|
|
231
|
-
const s = (e?.configurable?.services.agentRegistry?.list() ?? []).map(({ agent:
|
|
232
|
-
id:
|
|
233
|
-
name:
|
|
234
|
-
description:
|
|
242
|
+
const s = (e?.configurable?.services.agentRegistry?.list() ?? []).map(({ agent: S }) => ({
|
|
243
|
+
id: S.id,
|
|
244
|
+
name: S.name,
|
|
245
|
+
description: S.description
|
|
235
246
|
}));
|
|
236
247
|
if (!s.length)
|
|
237
248
|
return await h({ text: "No agents registered; skipping intent detection" }, e), { ...t, currentIntent: "none" };
|
|
238
|
-
const a = await T("intent_prompt"), i = s
|
|
239
|
-
`), c = Le(s), o = {
|
|
249
|
+
const a = await T("intent_prompt"), i = _(s), c = Le(s), o = {
|
|
240
250
|
registeredAgents: i,
|
|
241
|
-
priorSteps: t.agentExecutionContext.priorSteps,
|
|
251
|
+
priorSteps: _(t.agentExecutionContext.priorSteps),
|
|
242
252
|
userRequest: t.agentExecutionContext.userRequest
|
|
243
|
-
}, m = await
|
|
244
|
-
model: await
|
|
253
|
+
}, m = await H.fromTemplate(a).format(o), u = me({
|
|
254
|
+
model: await b("default"),
|
|
245
255
|
tools: [],
|
|
246
256
|
systemPrompt: m,
|
|
247
257
|
checkpointer: !0,
|
|
@@ -250,8 +260,8 @@ const Le = (t) => {
|
|
|
250
260
|
// Preserve recent conversation context while summarizing older messages
|
|
251
261
|
// to control token usage without losing important intent signals.
|
|
252
262
|
// The trigger and keep parameters can be tuned based on token limits and behavior.
|
|
253
|
-
|
|
254
|
-
model: await
|
|
263
|
+
ue({
|
|
264
|
+
model: await b("fast"),
|
|
255
265
|
trigger: { tokens: 4e3 },
|
|
256
266
|
keep: { messages: 6 }
|
|
257
267
|
}),
|
|
@@ -260,35 +270,35 @@ const Le = (t) => {
|
|
|
260
270
|
ge({ runLimit: 2 })
|
|
261
271
|
]
|
|
262
272
|
}), { structuredResponse: y } = await Ce({
|
|
263
|
-
agent:
|
|
273
|
+
agent: u,
|
|
264
274
|
messages: t.agentExecutionContext.messages,
|
|
265
275
|
config: e
|
|
266
276
|
}), f = c.parse(
|
|
267
277
|
y ?? { intent: null, assignedTask: null, requiresFollowUp: !1 }
|
|
268
|
-
),
|
|
278
|
+
), g = f.intent ?? "none", I = {
|
|
269
279
|
...t,
|
|
270
|
-
currentIntent:
|
|
280
|
+
currentIntent: g,
|
|
271
281
|
requiresFollowUp: f.requiresFollowUp,
|
|
272
282
|
agentExecutionContext: {
|
|
273
283
|
...t.agentExecutionContext,
|
|
274
284
|
assignedTask: f.assignedTask ?? ""
|
|
275
285
|
}
|
|
276
286
|
};
|
|
277
|
-
return await h({ text: `Intent came back as: ${
|
|
278
|
-
{ text: `Agent picked: ${
|
|
287
|
+
return await h({ text: `Intent came back as: ${g}` }, e), await h(
|
|
288
|
+
{ text: `Agent picked: ${g}
|
|
279
289
|
Task Assigned: ${f.assignedTask ?? ""}` },
|
|
280
290
|
e
|
|
281
|
-
),
|
|
291
|
+
), I;
|
|
282
292
|
} catch (r) {
|
|
283
293
|
throw await h({ text: "Error during intent detection" }, e), new Error(`Error during intent detection: ${r instanceof Error ? r.message : String(r)}`);
|
|
284
294
|
}
|
|
285
|
-
},
|
|
295
|
+
}, U = 3, _e = () => new se(Ee).addNode("ingestInput", Se).addNode("intentLLM", $e).addNode("executeRegisteredAgent", Te).addNode("exit", Me).addEdge(ie, "ingestInput").addEdge("ingestInput", "intentLLM").addConditionalEdges("intentLLM", (e) => e.currentIntent === "none" ? "exit" : "executeRegisteredAgent").addConditionalEdges("executeRegisteredAgent", (e) => (console.log("[Dispatcher][executeRegisteredAgent]", {
|
|
286
296
|
intent: e.currentIntent,
|
|
287
297
|
followUp: e.requiresFollowUp,
|
|
288
298
|
step: e.stepCount,
|
|
289
|
-
maxSteps:
|
|
290
|
-
}), !e.requiresFollowUp || e.stepCount >=
|
|
291
|
-
class
|
|
299
|
+
maxSteps: U
|
|
300
|
+
}), !e.requiresFollowUp || e.stepCount >= U ? "exit" : "intentLLM")).addEdge("exit", ae);
|
|
301
|
+
class Ue {
|
|
292
302
|
constructor() {
|
|
293
303
|
this.agentRegistry = /* @__PURE__ */ new Map();
|
|
294
304
|
}
|
|
@@ -305,7 +315,7 @@ class je {
|
|
|
305
315
|
return [...this.agentRegistry.values()];
|
|
306
316
|
}
|
|
307
317
|
}
|
|
308
|
-
class
|
|
318
|
+
class We {
|
|
309
319
|
/**
|
|
310
320
|
* Create a new InterruptHandler tied to a specific compiled graph and config.
|
|
311
321
|
*/
|
|
@@ -352,32 +362,32 @@ class Ue {
|
|
|
352
362
|
this.rejectWait && (this.rejectWait(new Error("Request cancelled by user.")), this.resolveWait = void 0, this.rejectWait = void 0);
|
|
353
363
|
}
|
|
354
364
|
}
|
|
355
|
-
const
|
|
365
|
+
const je = (t) => {
|
|
356
366
|
let e = -1;
|
|
357
367
|
for (let r = t.length - 1; r >= 0; r--)
|
|
358
|
-
if (t[r] instanceof
|
|
368
|
+
if (t[r] instanceof P) {
|
|
359
369
|
e = r;
|
|
360
370
|
break;
|
|
361
371
|
}
|
|
362
|
-
return e === -1 ? "" : t.slice(e + 1).filter((r) => r instanceof
|
|
372
|
+
return e === -1 ? "" : t.slice(e + 1).filter((r) => r instanceof q).map((r) => r.content).join(`
|
|
363
373
|
`);
|
|
364
|
-
},
|
|
374
|
+
}, J = async (t) => {
|
|
365
375
|
try {
|
|
366
376
|
return await (await De()).embedDocuments(t);
|
|
367
377
|
} catch (e) {
|
|
368
378
|
throw console.error("Failed to generate embeddings:", e), e;
|
|
369
379
|
}
|
|
370
|
-
},
|
|
380
|
+
}, X = async (t, e) => {
|
|
371
381
|
const r = e.get(t);
|
|
372
382
|
if (r)
|
|
373
383
|
return r;
|
|
374
|
-
const n = await
|
|
384
|
+
const n = await J([t]);
|
|
375
385
|
return e.set(t, n[0]), n[0];
|
|
376
386
|
};
|
|
377
387
|
async function Pe(t, e, r, n) {
|
|
378
388
|
const s = `req-${Date.now()}`, i = {
|
|
379
389
|
type: "layerSearch",
|
|
380
|
-
precomputedEmbedding: n ? await
|
|
390
|
+
precomputedEmbedding: n ? await X(t, n) : void 0,
|
|
381
391
|
requestId: s,
|
|
382
392
|
minScore: r
|
|
383
393
|
};
|
|
@@ -408,7 +418,7 @@ const Ne = async ({
|
|
|
408
418
|
topResults: s,
|
|
409
419
|
embeddingCache: a
|
|
410
420
|
}) => {
|
|
411
|
-
const i = `req-${Date.now()}`, c = a ? await
|
|
421
|
+
const i = `req-${Date.now()}`, c = a ? await X(t, a) : void 0, o = {
|
|
412
422
|
type: "fieldSearch",
|
|
413
423
|
layerIdForFieldsSearch: e,
|
|
414
424
|
precomputedEmbedding: c,
|
|
@@ -417,12 +427,12 @@ const Ne = async ({
|
|
|
417
427
|
topResults: s
|
|
418
428
|
};
|
|
419
429
|
return await new Promise((d) => {
|
|
420
|
-
const m = (
|
|
421
|
-
if (
|
|
430
|
+
const m = (u) => {
|
|
431
|
+
if (u.data.requestId !== i)
|
|
422
432
|
return;
|
|
423
|
-
const y =
|
|
433
|
+
const y = u.data.results.map(({ layerId: f, results: g }) => ({
|
|
424
434
|
layerId: f,
|
|
425
|
-
results:
|
|
435
|
+
results: g
|
|
426
436
|
}));
|
|
427
437
|
d(y);
|
|
428
438
|
};
|
|
@@ -444,16 +454,16 @@ function He(t) {
|
|
|
444
454
|
}
|
|
445
455
|
};
|
|
446
456
|
}
|
|
447
|
-
const
|
|
457
|
+
const Q = "0.1", w = 1536, Y = "openai", Z = k.default, A = `Name: {name}
|
|
448
458
|
Title: {title}
|
|
449
459
|
Description: {description}`, C = `Name: {name}
|
|
450
460
|
Alias: {alias}
|
|
451
|
-
Description: {description}`,
|
|
452
|
-
schemaVersion: l.literal(
|
|
461
|
+
Description: {description}`, ee = l.object({
|
|
462
|
+
schemaVersion: l.literal(Q),
|
|
453
463
|
modified: l.number().int().nonnegative(),
|
|
454
464
|
embeddings: l.object({
|
|
455
|
-
modelProvider: l.literal(
|
|
456
|
-
model: l.literal(
|
|
465
|
+
modelProvider: l.literal(Y),
|
|
466
|
+
model: l.literal(Z),
|
|
457
467
|
dimensions: l.literal(w),
|
|
458
468
|
templates: l.object({
|
|
459
469
|
layer: l.string().default(A),
|
|
@@ -482,14 +492,14 @@ Description: {description}`, Z = l.object({
|
|
|
482
492
|
})
|
|
483
493
|
).default([])
|
|
484
494
|
}), Oe = (t) => {
|
|
485
|
-
const e =
|
|
495
|
+
const e = ee.safeParse(t);
|
|
486
496
|
if (!e.success)
|
|
487
497
|
throw new Error("Embeddings response validation failed. Regenerate embeddings.");
|
|
488
498
|
return e.data;
|
|
489
499
|
}, Ve = (t, e) => {
|
|
490
500
|
const r = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
491
501
|
if (e.allLayers.forEach((s) => {
|
|
492
|
-
s instanceof
|
|
502
|
+
s instanceof V && n.set(s.id, s);
|
|
493
503
|
}), t.length !== n.size)
|
|
494
504
|
throw new Error("Layer count mismatch during registry restoration. Regenerate embeddings.");
|
|
495
505
|
for (const s of t) {
|
|
@@ -530,7 +540,7 @@ Description: {description}`, Z = l.object({
|
|
|
530
540
|
return r;
|
|
531
541
|
}, ze = async (t) => {
|
|
532
542
|
try {
|
|
533
|
-
return (await
|
|
543
|
+
return (await fe(t, {
|
|
534
544
|
responseType: "json"
|
|
535
545
|
})).data;
|
|
536
546
|
} catch (e) {
|
|
@@ -546,9 +556,9 @@ Description: {description}`, Z = l.object({
|
|
|
546
556
|
const s = await ze(n.resource.url);
|
|
547
557
|
return Oe(s);
|
|
548
558
|
};
|
|
549
|
-
class
|
|
559
|
+
class te {
|
|
550
560
|
constructor() {
|
|
551
|
-
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.threadId = "", this.agentRegistry = new
|
|
561
|
+
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.threadId = "", this.agentRegistry = new Ue(), this.streamEpoch = 0;
|
|
552
562
|
}
|
|
553
563
|
/**
|
|
554
564
|
* Creates and returns an AI-ready Orchestrator instance.
|
|
@@ -556,15 +566,15 @@ class ee {
|
|
|
556
566
|
* @returns Ready Orchestrator.
|
|
557
567
|
*/
|
|
558
568
|
static async init(e) {
|
|
559
|
-
const r = new
|
|
569
|
+
const r = new te();
|
|
560
570
|
try {
|
|
561
571
|
if (e.view?.map) {
|
|
562
|
-
await
|
|
572
|
+
await O.whenOnce(() => e.view.ready);
|
|
563
573
|
const n = await Ge(e.view), s = Ve(
|
|
564
574
|
n.layers,
|
|
565
575
|
e.view.map
|
|
566
576
|
);
|
|
567
|
-
r.layersAndFieldsRegistry = s, r.embeddingsWorker = await
|
|
577
|
+
r.layersAndFieldsRegistry = s, r.embeddingsWorker = await ve(n);
|
|
568
578
|
}
|
|
569
579
|
return e.agents?.forEach((n) => {
|
|
570
580
|
r.agentRegistry.register(n);
|
|
@@ -588,7 +598,7 @@ class ee {
|
|
|
588
598
|
throw new Error("Orchestrator has no registered agents.");
|
|
589
599
|
if (++this.streamEpoch, !e.trim())
|
|
590
600
|
return;
|
|
591
|
-
this.threadId = String(Date.now()), this.graph || (this.graph = _e().compile({ checkpointer: new
|
|
601
|
+
this.threadId = String(Date.now()), this.graph || (this.graph = _e().compile({ checkpointer: new oe() }));
|
|
592
602
|
const r = this.embeddingsWorker ? qe({ worker: this.embeddingsWorker }) : void 0, n = this.embeddingsWorker ? He({ worker: this.embeddingsWorker }) : void 0, s = /* @__PURE__ */ new Map(), i = {
|
|
593
603
|
version: "v2",
|
|
594
604
|
streamMode: "custom",
|
|
@@ -610,20 +620,20 @@ class ee {
|
|
|
610
620
|
i
|
|
611
621
|
), o = ++this.streamEpoch;
|
|
612
622
|
for (yield* this.pipeStream(c, o); ; ) {
|
|
613
|
-
const f = (await this.graph.getState(i, { subgraphs: !0 })).tasks.find((
|
|
623
|
+
const f = (await this.graph.getState(i, { subgraphs: !0 })).tasks.find((g) => g.interrupts.length > 0)?.interrupts[0]?.value;
|
|
614
624
|
if (!f)
|
|
615
625
|
break;
|
|
616
|
-
this.currentInterrupt = f, this.interruptHandler = new
|
|
626
|
+
this.currentInterrupt = f, this.interruptHandler = new We(this.graph, i), yield { runId: this.threadId, timestamp: Date.now(), type: "interrupt", interrupt: f };
|
|
617
627
|
try {
|
|
618
|
-
const
|
|
619
|
-
yield* this.pipeStream(
|
|
620
|
-
} catch (
|
|
621
|
-
if (
|
|
628
|
+
const g = await this.interruptHandler.waitForUser(), I = ++this.streamEpoch;
|
|
629
|
+
yield* this.pipeStream(g, I);
|
|
630
|
+
} catch (g) {
|
|
631
|
+
if (g) {
|
|
622
632
|
yield {
|
|
623
633
|
runId: this.threadId,
|
|
624
634
|
timestamp: Date.now(),
|
|
625
635
|
type: "error",
|
|
626
|
-
error: { message:
|
|
636
|
+
error: { message: g?.message }
|
|
627
637
|
};
|
|
628
638
|
return;
|
|
629
639
|
}
|
|
@@ -636,7 +646,7 @@ class ee {
|
|
|
636
646
|
runId: this.threadId,
|
|
637
647
|
timestamp: Date.now(),
|
|
638
648
|
type: "completed",
|
|
639
|
-
result: { content:
|
|
649
|
+
result: { content: je(m.agentExecutionContext.messages) }
|
|
640
650
|
};
|
|
641
651
|
}
|
|
642
652
|
/**
|
|
@@ -685,24 +695,24 @@ class ee {
|
|
|
685
695
|
const Ke = (t) => {
|
|
686
696
|
const e = /* @__PURE__ */ new Set();
|
|
687
697
|
for (const n of t)
|
|
688
|
-
if (
|
|
698
|
+
if (ce(n)) {
|
|
689
699
|
const s = n;
|
|
690
700
|
s.tool_calls && s.tool_calls.length > 0 && s.tool_calls.forEach((a) => {
|
|
691
701
|
a.id && e.add(a.id);
|
|
692
702
|
});
|
|
693
703
|
}
|
|
694
704
|
return t.filter((n) => {
|
|
695
|
-
if (
|
|
705
|
+
if (de(n)) {
|
|
696
706
|
const s = n;
|
|
697
707
|
return e.has(s.tool_call_id);
|
|
698
708
|
}
|
|
699
709
|
return !0;
|
|
700
710
|
});
|
|
701
711
|
}, D = (t, e) => {
|
|
702
|
-
const r =
|
|
703
|
-
return
|
|
712
|
+
const r = le.fromTemplate(t);
|
|
713
|
+
return H.fromMessages([r, ...e]);
|
|
704
714
|
}, Be = async (t) => {
|
|
705
|
-
const { promptText: e, modelTier: r, temperature: n, messages: s } = t, a = D(e, s ?? []), i = await
|
|
715
|
+
const { promptText: e, modelTier: r, temperature: n, messages: s } = t, a = D(e, s ?? []), i = await b(r, n);
|
|
706
716
|
return a.pipe(i);
|
|
707
717
|
}, pt = async (t) => {
|
|
708
718
|
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a } = t, c = await (await Be({
|
|
@@ -715,11 +725,11 @@ const Ke = (t) => {
|
|
|
715
725
|
return c;
|
|
716
726
|
const o = c.content;
|
|
717
727
|
return typeof o == "string" ? o : JSON.stringify(o);
|
|
718
|
-
},
|
|
719
|
-
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, schema: i } = t, c = D(e, s ?? []), d = (await
|
|
728
|
+
}, ne = async (t) => {
|
|
729
|
+
const { promptText: e, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, schema: i } = t, c = D(e, s ?? []), d = (await b(r, n)).withStructuredOutput(i);
|
|
720
730
|
return await c.pipe(d).invoke(a ?? {});
|
|
721
731
|
}, 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
|
|
732
|
+
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 b(r, n);
|
|
723
733
|
return await o.pipe(d.bindTools(i)).invoke(a ?? {});
|
|
724
734
|
}, Je = p.object({
|
|
725
735
|
name: p.string(),
|
|
@@ -729,7 +739,7 @@ const Ke = (t) => {
|
|
|
729
739
|
}), Xe = p.object({
|
|
730
740
|
fields: p.array(Je)
|
|
731
741
|
});
|
|
732
|
-
function
|
|
742
|
+
function W(t, e) {
|
|
733
743
|
const r = /* @__PURE__ */ new Map();
|
|
734
744
|
for (const n of t.fields) {
|
|
735
745
|
const s = e.fields.find((i) => i.name === n.name), a = {
|
|
@@ -751,19 +761,19 @@ const Qe = async (t) => {
|
|
|
751
761
|
}).join(`
|
|
752
762
|
`);
|
|
753
763
|
if (n.length === 0)
|
|
754
|
-
return
|
|
764
|
+
return W(t, { fields: [] });
|
|
755
765
|
const s = {
|
|
756
766
|
existingItemTitle: t.portalItem?.title,
|
|
757
767
|
existingItemDescription: t.portalItem?.description,
|
|
758
768
|
existingLayerTitle: t.title,
|
|
759
769
|
existingLayerDescription: t.portalItem?.description,
|
|
760
770
|
fieldInformation: n
|
|
761
|
-
}, a = await
|
|
771
|
+
}, a = await ne({
|
|
762
772
|
promptText: r,
|
|
763
773
|
schema: Xe,
|
|
764
774
|
inputVariables: s
|
|
765
775
|
});
|
|
766
|
-
return
|
|
776
|
+
return W(t, a);
|
|
767
777
|
}, Ye = p.object({
|
|
768
778
|
title: p.string(),
|
|
769
779
|
description: p.string(),
|
|
@@ -776,7 +786,7 @@ const Qe = async (t) => {
|
|
|
776
786
|
existingLayerSnippet: t.portalItem?.snippet,
|
|
777
787
|
layerGeometryType: t.geometryType
|
|
778
788
|
};
|
|
779
|
-
return { ...await
|
|
789
|
+
return { ...await ne({
|
|
780
790
|
promptText: n,
|
|
781
791
|
schema: Ye,
|
|
782
792
|
inputVariables: a
|
|
@@ -784,7 +794,7 @@ const Qe = async (t) => {
|
|
|
784
794
|
}, et = async (t) => {
|
|
785
795
|
const e = t.allLayers.toArray(), r = [], n = /* @__PURE__ */ new Map();
|
|
786
796
|
for (const s of e)
|
|
787
|
-
if (s instanceof
|
|
797
|
+
if (s instanceof V) {
|
|
788
798
|
const a = (async () => {
|
|
789
799
|
const i = await Qe(s), c = await Ze(s, i);
|
|
790
800
|
n.set(s.id, { layerItem: c, fieldRegistry: i });
|
|
@@ -793,13 +803,13 @@ const Qe = async (t) => {
|
|
|
793
803
|
}
|
|
794
804
|
return await Promise.all(r), n;
|
|
795
805
|
}, ft = async (t) => {
|
|
796
|
-
await
|
|
806
|
+
await O.whenOnce(() => t.ready);
|
|
797
807
|
const e = await et(t.map), { layers: r } = await tt(e), n = {
|
|
798
|
-
schemaVersion:
|
|
808
|
+
schemaVersion: Q,
|
|
799
809
|
modified: Date.now(),
|
|
800
810
|
embeddings: {
|
|
801
|
-
modelProvider:
|
|
802
|
-
model:
|
|
811
|
+
modelProvider: Y,
|
|
812
|
+
model: Z,
|
|
803
813
|
dimensions: w,
|
|
804
814
|
templates: {
|
|
805
815
|
layer: A,
|
|
@@ -807,14 +817,14 @@ const Qe = async (t) => {
|
|
|
807
817
|
}
|
|
808
818
|
},
|
|
809
819
|
layers: r
|
|
810
|
-
}, s =
|
|
820
|
+
}, s = ee.safeParse(n);
|
|
811
821
|
if (!s.success)
|
|
812
822
|
throw console.error("Schema Mismatch:", s.error.format()), new Error("Webmap embedding generation failed validation.");
|
|
813
823
|
return s.data;
|
|
814
824
|
}, tt = async (t) => {
|
|
815
825
|
const e = [], r = [];
|
|
816
826
|
for (const [i, { fieldRegistry: c, layerItem: o }] of t.entries()) {
|
|
817
|
-
const d =
|
|
827
|
+
const d = j(A, {
|
|
818
828
|
name: o.name,
|
|
819
829
|
title: o.title,
|
|
820
830
|
description: o.description
|
|
@@ -828,27 +838,27 @@ const Qe = async (t) => {
|
|
|
828
838
|
vector: [],
|
|
829
839
|
fields: []
|
|
830
840
|
};
|
|
831
|
-
for (const [,
|
|
832
|
-
const y =
|
|
833
|
-
name:
|
|
834
|
-
alias:
|
|
835
|
-
description:
|
|
841
|
+
for (const [, u] of c.entries()) {
|
|
842
|
+
const y = j(C, {
|
|
843
|
+
name: u.name,
|
|
844
|
+
alias: u.alias,
|
|
845
|
+
description: u.description
|
|
836
846
|
});
|
|
837
847
|
e.push(y), m.fields.push({
|
|
838
|
-
name:
|
|
839
|
-
alias:
|
|
840
|
-
description:
|
|
848
|
+
name: u.name,
|
|
849
|
+
alias: u.alias,
|
|
850
|
+
description: u.description,
|
|
841
851
|
vector: []
|
|
842
852
|
});
|
|
843
853
|
}
|
|
844
854
|
r.push(m);
|
|
845
855
|
}
|
|
846
|
-
const n = await
|
|
856
|
+
const n = await J(e);
|
|
847
857
|
let s = 0;
|
|
848
858
|
return { layers: r.map((i) => (i.vector = n[s++], i.fields.forEach((c) => {
|
|
849
859
|
c.vector = n[s++];
|
|
850
860
|
}), i)) };
|
|
851
|
-
},
|
|
861
|
+
}, j = (t, e) => t.replace(/\{(\w+)\}/gu, (r, n) => e[n] ?? ""), yt = (t, e) => {
|
|
852
862
|
if (t.length !== e.length)
|
|
853
863
|
throw new Error("Vectors must be the same length");
|
|
854
864
|
let r = 0, n = 0, s = 0;
|
|
@@ -863,14 +873,14 @@ const Qe = async (t) => {
|
|
|
863
873
|
return Math.max(-1, Math.min(1, i));
|
|
864
874
|
};
|
|
865
875
|
export {
|
|
866
|
-
|
|
876
|
+
te as Orchestrator,
|
|
867
877
|
yt as cosineSimilarity,
|
|
868
|
-
|
|
878
|
+
b as createChatModel,
|
|
869
879
|
ft as createWebmapEmbeddings,
|
|
870
|
-
|
|
871
|
-
|
|
880
|
+
J as getEmbeddings,
|
|
881
|
+
ne as invokeStructuredPrompt,
|
|
872
882
|
pt as invokeTextPrompt,
|
|
873
883
|
ht as invokeToolPrompt,
|
|
874
884
|
h as sendTraceMessage,
|
|
875
|
-
|
|
885
|
+
gt as sendUXSuggestion
|
|
876
886
|
};
|
|
@@ -19,6 +19,11 @@ Return either:
|
|
|
19
19
|
3. \`requiresFollowUp\` — whether another orchestration step will likely be needed after this agent succeeds
|
|
20
20
|
- or \`null\` if no registered agent applies
|
|
21
21
|
|
|
22
|
+
Important
|
|
23
|
+
|
|
24
|
+
- Return null only when the request is clearly outside the scope of all registered agents.
|
|
25
|
+
- If any agent can take the next useful step, select the best one instead of returning null.
|
|
26
|
+
|
|
22
27
|
Latest user request:
|
|
23
28
|
{userRequest}
|
|
24
29
|
|
|
@@ -52,6 +57,9 @@ Rules:
|
|
|
52
57
|
- Do not plan the full workflow up front. Only decide the next best step.
|
|
53
58
|
- Prefer an agent that can directly complete the user’s request.
|
|
54
59
|
- Only break the request into multiple steps when necessary.
|
|
60
|
+
- When multiple agents could help, choose the best fit instead of returning \`null\`.
|
|
61
|
+
- Base the choice on the registered agent descriptions, not on whether the user used exact matching keywords.
|
|
62
|
+
- If no agent can fully complete the request, but one agent can take the next useful step, choose that agent and set requiresFollowUp to true.
|
|
55
63
|
|
|
56
64
|
Assigned Task Guidelines (IMPORTANT):
|
|
57
65
|
|
package/dist/types/types.d.ts
CHANGED