@arcgis/ai-orchestrator 5.1.0-next.87 → 5.1.0-next.89
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 +170 -152
- package/dist/intent_prompt-D6yvMy34.js +122 -0
- package/dist/orchestrator/orchestrator.d.ts +2 -1
- package/dist/types/types.d.ts +3 -1
- package/package.json +1 -1
- package/dist/intent_prompt-BSRo2YLj.js +0 -84
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import k from "@arcgis/core/identity/IdentityManager.js";
|
|
2
|
+
import S from "@arcgis/core/portal/Portal.js";
|
|
3
3
|
import { Annotation as x, isGraphInterrupt as ne, StateGraph as re, START as se, END as ie, MemorySaver as ae } from "@langchain/langgraph/web";
|
|
4
|
-
import { HumanMessage as
|
|
5
|
-
import { dispatchCustomEvent as
|
|
4
|
+
import { HumanMessage as j, AIMessage as R, isAIMessage as oe, isToolMessage as ce } from "@langchain/core/messages";
|
|
5
|
+
import { dispatchCustomEvent as W } from "@langchain/core/callbacks/dispatch/web";
|
|
6
6
|
import h, { z as l } from "zod";
|
|
7
7
|
import { ChatPromptTemplate as N, SystemMessagePromptTemplate as de } from "@langchain/core/prompts";
|
|
8
8
|
import { createAgent as le, summarizationMiddleware as ue, modelCallLimitMiddleware as me } from "langchain";
|
|
@@ -14,12 +14,12 @@ const V = {
|
|
|
14
14
|
advanced: "gpt-5.2",
|
|
15
15
|
default: "gpt-5-mini",
|
|
16
16
|
fast: "gpt-5.4-nano"
|
|
17
|
-
},
|
|
17
|
+
}, C = {
|
|
18
18
|
default: "text-embedding-ada-002"
|
|
19
19
|
}, M = /* @__PURE__ */ new Map();
|
|
20
20
|
let E = null;
|
|
21
21
|
const fe = () => {
|
|
22
|
-
const t =
|
|
22
|
+
const t = S.getDefault().helperServices;
|
|
23
23
|
if (!t?.aiModels?.url)
|
|
24
24
|
throw new Error("AI Models Service URL is not defined in the portal's helper services.");
|
|
25
25
|
return t.aiModels.url;
|
|
@@ -39,17 +39,17 @@ const fe = () => {
|
|
|
39
39
|
if (!r)
|
|
40
40
|
throw new Error(`Model '${e}' is not available in the discovery service.`);
|
|
41
41
|
return r.endpoint;
|
|
42
|
-
}, ye = async (e = "default") => await z(V[e]), G = async (e = "default") => await z(
|
|
43
|
-
const t = await ve(), r = await G("default"), n =
|
|
42
|
+
}, ye = async (e = "default") => await z(V[e]), G = async (e = "default") => await z(C[e]), we = async (e) => {
|
|
43
|
+
const t = await ve(), r = await G("default"), n = S.getDefault(), a = (await k.getCredential(`${n.url}/sharing`)).token, i = {
|
|
44
44
|
type: "generateEmbeddings",
|
|
45
45
|
webmapEmbeddings: e,
|
|
46
46
|
auth: { apiUrl: r, token: a }
|
|
47
47
|
};
|
|
48
|
-
return t.postMessage(i), await new Promise((
|
|
48
|
+
return t.postMessage(i), await new Promise((o, c) => {
|
|
49
49
|
const d = (m) => {
|
|
50
|
-
m.data === "completed" && (t.removeEventListener("message", d),
|
|
50
|
+
m.data === "completed" && (t.removeEventListener("message", d), o());
|
|
51
51
|
}, u = (m) => {
|
|
52
|
-
t.removeEventListener("message", d),
|
|
52
|
+
t.removeEventListener("message", d), c(m instanceof Error ? m : new Error("Embeddings worker error"));
|
|
53
53
|
};
|
|
54
54
|
t.addEventListener("message", d), t.addEventListener("error", u, { once: !0 });
|
|
55
55
|
}), t;
|
|
@@ -67,7 +67,8 @@ const fe = () => {
|
|
|
67
67
|
userRequest: "",
|
|
68
68
|
assignedTask: "",
|
|
69
69
|
priorSteps: [],
|
|
70
|
-
messages: []
|
|
70
|
+
messages: [],
|
|
71
|
+
sharedState: {}
|
|
71
72
|
}),
|
|
72
73
|
reducer: xe
|
|
73
74
|
}),
|
|
@@ -84,19 +85,19 @@ const fe = () => {
|
|
|
84
85
|
reducer: (e, t) => t ?? e + 1
|
|
85
86
|
})
|
|
86
87
|
}), f = async (e, t) => {
|
|
87
|
-
await
|
|
88
|
-
},
|
|
89
|
-
await
|
|
88
|
+
await W("trace_message", e, t);
|
|
89
|
+
}, pt = async (e, t) => {
|
|
90
|
+
await W("graph_ux_suggestion", e, t);
|
|
90
91
|
}, Ee = (e) => {
|
|
91
92
|
e.currentIntent = "none";
|
|
92
|
-
},
|
|
93
|
+
}, Se = async (e, t) => {
|
|
93
94
|
if (e.agentExecutionContext.userRequest) {
|
|
94
|
-
const n = new
|
|
95
|
+
const n = new j(e.agentExecutionContext.userRequest.trim());
|
|
95
96
|
e.agentExecutionContext.messages = [...e.agentExecutionContext.messages, n], Ee(e);
|
|
96
97
|
}
|
|
97
98
|
const r = t?.configurable?.services.agentRegistry.list().map((n) => n.agent.id) ?? [];
|
|
98
99
|
return await f({ text: `Available agents: ${[...r].join(", ")}` }, t), await f({ text: "Analyzing user input" }, t), e;
|
|
99
|
-
},
|
|
100
|
+
}, Ie = async (e, t) => (await f({ text: "Exiting..." }, t), e), $ = 4e3, P = (e) => {
|
|
100
101
|
if (typeof e != "string")
|
|
101
102
|
return;
|
|
102
103
|
const t = e.trim();
|
|
@@ -112,14 +113,17 @@ const fe = () => {
|
|
|
112
113
|
default:
|
|
113
114
|
return "Agent completed without a summary.";
|
|
114
115
|
}
|
|
115
|
-
}, Re = (e, t) => {
|
|
116
|
-
const r =
|
|
117
|
-
|
|
116
|
+
}, ke = (e) => typeof e == "object" && e !== null && !Array.isArray(e), Re = (e, t) => {
|
|
117
|
+
const r = P(t?.outputMessage), n = P(t?.summary), s = t?.status, a = s === "success" || s === "failed" ? s : "unknown";
|
|
118
|
+
a === "unknown" && console.warn(`Agent "${e}" returned missing/invalid status. Defaulting to "unknown".`);
|
|
119
|
+
const i = t?.sharedStatePatch, o = ke(i) ? i : void 0;
|
|
120
|
+
return i !== void 0 && o === void 0 && console.warn(`Agent "${e}" returned invalid sharedStatePatch. Ignoring it.`), {
|
|
118
121
|
outputMessage: r,
|
|
119
|
-
summary: n ?? r ?? Me(
|
|
120
|
-
status:
|
|
122
|
+
summary: n ?? r ?? Me(a),
|
|
123
|
+
status: a,
|
|
124
|
+
sharedStatePatch: o
|
|
121
125
|
};
|
|
122
|
-
},
|
|
126
|
+
}, Ce = async (e, t) => {
|
|
123
127
|
const r = t?.configurable, { agentRegistry: n } = r.services, s = n?.get(e.currentIntent);
|
|
124
128
|
if (!s)
|
|
125
129
|
return console.warn(`No agent found for intent: ${e.currentIntent}`), e;
|
|
@@ -138,8 +142,11 @@ const fe = () => {
|
|
|
138
142
|
{
|
|
139
143
|
agentExecutionContext: {
|
|
140
144
|
...e.agentExecutionContext,
|
|
145
|
+
// deep clone on messages did not work in agents, so its a shallow clone here.
|
|
141
146
|
messages: [...e.agentExecutionContext.messages],
|
|
142
|
-
|
|
147
|
+
// deep clone to prevent accidental mutations by agents
|
|
148
|
+
priorSteps: structuredClone(e.agentExecutionContext.priorSteps ?? []),
|
|
149
|
+
sharedState: structuredClone(e.agentExecutionContext.sharedState ?? {})
|
|
143
150
|
}
|
|
144
151
|
},
|
|
145
152
|
a
|
|
@@ -155,11 +162,11 @@ const fe = () => {
|
|
|
155
162
|
summary: `Agent execution failed: ${u}`
|
|
156
163
|
};
|
|
157
164
|
}
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
160
|
-
const d =
|
|
161
|
-
[truncated]` :
|
|
162
|
-
|
|
165
|
+
const o = i.outputMessage, c = [...e.agentExecutionContext.messages];
|
|
166
|
+
if (o) {
|
|
167
|
+
const d = o.length > $ ? `${o.slice(0, $ - 14)}
|
|
168
|
+
[truncated]` : o;
|
|
169
|
+
c.push(new R(d));
|
|
163
170
|
}
|
|
164
171
|
return {
|
|
165
172
|
...e,
|
|
@@ -167,16 +174,20 @@ const fe = () => {
|
|
|
167
174
|
requiresFollowUp: i.status === "failed" ? !0 : e.requiresFollowUp,
|
|
168
175
|
agentExecutionContext: {
|
|
169
176
|
...e.agentExecutionContext,
|
|
170
|
-
messages:
|
|
177
|
+
messages: c,
|
|
171
178
|
priorSteps: [
|
|
172
179
|
...e.agentExecutionContext.priorSteps ?? [],
|
|
173
180
|
{
|
|
174
181
|
agentId: s.agent.id,
|
|
175
182
|
assignedTask: e.agentExecutionContext.assignedTask,
|
|
176
183
|
summary: i?.summary || "No summary provided.",
|
|
177
|
-
status: i
|
|
184
|
+
status: i?.status || "unknown"
|
|
178
185
|
}
|
|
179
|
-
]
|
|
186
|
+
],
|
|
187
|
+
sharedState: {
|
|
188
|
+
...e.agentExecutionContext.sharedState,
|
|
189
|
+
...i.sharedStatePatch ?? {}
|
|
190
|
+
}
|
|
180
191
|
}
|
|
181
192
|
};
|
|
182
193
|
}, Te = (e, t, r) => {
|
|
@@ -184,7 +195,7 @@ const fe = () => {
|
|
|
184
195
|
return n ? typeof n == "function" ? n() : Promise.resolve(n) : new Promise((s, a) => {
|
|
185
196
|
(typeof queueMicrotask == "function" ? queueMicrotask : setTimeout)(a.bind(null, /* @__PURE__ */ new Error("Unknown variable dynamic import: " + t + (t.split("/").length !== r ? ". Note that variables only represent file names one level deep." : ""))));
|
|
186
197
|
});
|
|
187
|
-
},
|
|
198
|
+
}, T = async (e) => (await Te(/* @__PURE__ */ Object.assign({ "./field_descriptions_prompt.md": () => import("./field_descriptions_prompt-haMV_aoG.js"), "./intent_prompt.md": () => import("./intent_prompt-D6yvMy34.js"), "./layer_descriptions_prompt.md": () => import("./layer_descriptions_prompt-NAaKWdJi.js") }), `./${e}.md`, 2)).default, Ae = async (e) => {
|
|
188
199
|
const { agent: t, messages: r, config: n } = e;
|
|
189
200
|
return { structuredResponse: (await t.invoke(
|
|
190
201
|
{
|
|
@@ -199,7 +210,7 @@ const fe = () => {
|
|
|
199
210
|
headers: n
|
|
200
211
|
});
|
|
201
212
|
}, b = async (e = "default", t = 0) => {
|
|
202
|
-
const r =
|
|
213
|
+
const r = S.getDefault(), n = await k.getCredential(`${r.url}/sharing`), s = V[e], a = await ye(e);
|
|
203
214
|
return new ge({
|
|
204
215
|
modelName: s,
|
|
205
216
|
apiKey: "dummy-key",
|
|
@@ -210,8 +221,8 @@ const fe = () => {
|
|
|
210
221
|
fetch: K(n.token)
|
|
211
222
|
}
|
|
212
223
|
});
|
|
213
|
-
},
|
|
214
|
-
const t =
|
|
224
|
+
}, Fe = async (e = "default") => {
|
|
225
|
+
const t = S.getDefault(), r = await k.getCredential(`${t.url}/sharing`), n = C[e], s = await G(e);
|
|
215
226
|
return new pe({
|
|
216
227
|
modelName: n,
|
|
217
228
|
apiKey: "dummy-key",
|
|
@@ -222,20 +233,20 @@ const fe = () => {
|
|
|
222
233
|
batchSize: 2048,
|
|
223
234
|
maxConcurrency: 10
|
|
224
235
|
});
|
|
225
|
-
},
|
|
236
|
+
}, De = l.object({
|
|
226
237
|
id: l.string().min(1),
|
|
227
238
|
name: l.string().min(1),
|
|
228
239
|
description: l.string().min(1)
|
|
229
240
|
});
|
|
230
|
-
l.array(
|
|
231
|
-
const
|
|
241
|
+
l.array(De);
|
|
242
|
+
const q = (e) => JSON.stringify(e, null, 2), Le = (e) => {
|
|
232
243
|
const t = e.map((n) => n.id), r = l.enum(t);
|
|
233
244
|
return l.object({
|
|
234
245
|
intent: r.nullable(),
|
|
235
246
|
assignedTask: l.string().nullable(),
|
|
236
247
|
requiresFollowUp: l.boolean()
|
|
237
248
|
});
|
|
238
|
-
},
|
|
249
|
+
}, $e = async (e, t) => {
|
|
239
250
|
try {
|
|
240
251
|
await f({ text: "Asking LLM to route to an agent" }, t);
|
|
241
252
|
const s = (t?.configurable?.services.agentRegistry?.list() ?? []).map(({ agent: v }) => ({
|
|
@@ -245,16 +256,16 @@ const U = (e) => JSON.stringify(e, null, 2), De = (e) => {
|
|
|
245
256
|
}));
|
|
246
257
|
if (!s.length)
|
|
247
258
|
return await f({ text: "No agents registered; skipping intent detection" }, t), { ...e, currentIntent: "none" };
|
|
248
|
-
const a = await
|
|
259
|
+
const a = await T("intent_prompt"), i = q(s), o = Le(s), c = {
|
|
249
260
|
registeredAgents: i,
|
|
250
|
-
priorSteps:
|
|
261
|
+
priorSteps: q(e.agentExecutionContext.priorSteps),
|
|
251
262
|
userRequest: e.agentExecutionContext.userRequest
|
|
252
|
-
}, u = await N.fromTemplate(a).format(
|
|
263
|
+
}, u = await N.fromTemplate(a).format(c), m = le({
|
|
253
264
|
model: await b("fast"),
|
|
254
265
|
tools: [],
|
|
255
266
|
systemPrompt: u,
|
|
256
267
|
checkpointer: !0,
|
|
257
|
-
responseFormat:
|
|
268
|
+
responseFormat: o,
|
|
258
269
|
middleware: [
|
|
259
270
|
// Preserve recent conversation context while summarizing older messages
|
|
260
271
|
// to control token usage without losing important intent signals.
|
|
@@ -268,13 +279,13 @@ const U = (e) => JSON.stringify(e, null, 2), De = (e) => {
|
|
|
268
279
|
// 1 usual LLM call and 1 optional summarization call.
|
|
269
280
|
me({ runLimit: 2 })
|
|
270
281
|
]
|
|
271
|
-
}), { structuredResponse: y } = await
|
|
282
|
+
}), { structuredResponse: y } = await Ae({
|
|
272
283
|
agent: m,
|
|
273
284
|
messages: e.agentExecutionContext.messages,
|
|
274
285
|
config: t
|
|
275
|
-
}), p =
|
|
286
|
+
}), p = o.parse(
|
|
276
287
|
y ?? { intent: null, assignedTask: null, requiresFollowUp: !1 }
|
|
277
|
-
), g = p.intent ?? "none",
|
|
288
|
+
), g = p.intent ?? "none", I = {
|
|
278
289
|
...e,
|
|
279
290
|
currentIntent: g,
|
|
280
291
|
requiresFollowUp: p.requiresFollowUp,
|
|
@@ -292,14 +303,14 @@ const U = (e) => JSON.stringify(e, null, 2), De = (e) => {
|
|
|
292
303
|
agentExecutionContext: {
|
|
293
304
|
...e.agentExecutionContext,
|
|
294
305
|
assignedTask: "",
|
|
295
|
-
messages: [...e.agentExecutionContext.messages, new
|
|
306
|
+
messages: [...e.agentExecutionContext.messages, new R(v)],
|
|
296
307
|
priorSteps: [
|
|
297
308
|
...e.agentExecutionContext.priorSteps ?? [],
|
|
298
309
|
{
|
|
299
310
|
agentId: "no-intent-router",
|
|
300
311
|
assignedTask: e.agentExecutionContext.userRequest,
|
|
301
312
|
summary: "No matching agent found; asked user to rephrase.",
|
|
302
|
-
status: "
|
|
313
|
+
status: "failed"
|
|
303
314
|
}
|
|
304
315
|
]
|
|
305
316
|
}
|
|
@@ -312,13 +323,13 @@ Task Assigned: ${p.assignedTask ?? ""}
|
|
|
312
323
|
Requires Follow-Up: ${p.requiresFollowUp}`
|
|
313
324
|
},
|
|
314
325
|
t
|
|
315
|
-
),
|
|
326
|
+
), I;
|
|
316
327
|
} catch (r) {
|
|
317
328
|
throw await f({ text: "Error during intent detection" }, t), new Error(`Error during intent detection: ${r instanceof Error ? r.message : String(r)}`);
|
|
318
329
|
}
|
|
319
|
-
},
|
|
330
|
+
}, Pe = 3, qe = () => new re(be).addNode("ingestInput", Se).addNode("intentLLM", $e).addNode("executeRegisteredAgent", Ce).addNode("exit", Ie).addEdge(se, "ingestInput").addEdge("ingestInput", "intentLLM").addConditionalEdges("intentLLM", (t) => t.currentIntent === "none" ? "exit" : "executeRegisteredAgent").addConditionalEdges(
|
|
320
331
|
"executeRegisteredAgent",
|
|
321
|
-
(t) => t.stepCount >=
|
|
332
|
+
(t) => t.stepCount >= Pe || !t.requiresFollowUp ? "exit" : "intentLLM"
|
|
322
333
|
).addEdge("exit", ie);
|
|
323
334
|
class Ue {
|
|
324
335
|
constructor() {
|
|
@@ -384,18 +395,18 @@ class _e {
|
|
|
384
395
|
this.rejectWait && (this.rejectWait(new Error("Request cancelled by user.")), this.resolveWait = void 0, this.rejectWait = void 0);
|
|
385
396
|
}
|
|
386
397
|
}
|
|
387
|
-
const
|
|
398
|
+
const je = (e) => {
|
|
388
399
|
let t = -1;
|
|
389
400
|
for (let r = e.length - 1; r >= 0; r--)
|
|
390
|
-
if (e[r] instanceof
|
|
401
|
+
if (e[r] instanceof j) {
|
|
391
402
|
t = r;
|
|
392
403
|
break;
|
|
393
404
|
}
|
|
394
|
-
return t === -1 ? "" : e.slice(t + 1).filter((r) => r instanceof
|
|
405
|
+
return t === -1 ? "" : e.slice(t + 1).filter((r) => r instanceof R).map((r) => r.content).join(`
|
|
395
406
|
`);
|
|
396
407
|
}, B = async (e) => {
|
|
397
408
|
try {
|
|
398
|
-
return await (await
|
|
409
|
+
return await (await Fe()).embedDocuments(e);
|
|
399
410
|
} catch (t) {
|
|
400
411
|
throw console.error("Failed to generate embeddings:", t), t;
|
|
401
412
|
}
|
|
@@ -413,14 +424,14 @@ async function We(e, t, r, n) {
|
|
|
413
424
|
requestId: s,
|
|
414
425
|
minScore: r
|
|
415
426
|
};
|
|
416
|
-
return await new Promise((
|
|
417
|
-
const
|
|
418
|
-
d.data.requestId === s &&
|
|
427
|
+
return await new Promise((o) => {
|
|
428
|
+
const c = (d) => {
|
|
429
|
+
d.data.requestId === s && o(d.data.results);
|
|
419
430
|
};
|
|
420
|
-
t.addEventListener("message",
|
|
431
|
+
t.addEventListener("message", c, { once: !0 }), t.postMessage(i);
|
|
421
432
|
});
|
|
422
433
|
}
|
|
423
|
-
function
|
|
434
|
+
function Ne(e) {
|
|
424
435
|
const { worker: t } = e;
|
|
425
436
|
return {
|
|
426
437
|
async searchLayers({
|
|
@@ -432,7 +443,7 @@ function je(e) {
|
|
|
432
443
|
}
|
|
433
444
|
};
|
|
434
445
|
}
|
|
435
|
-
const
|
|
446
|
+
const He = async ({
|
|
436
447
|
combinedQuery: e,
|
|
437
448
|
layerIds: t,
|
|
438
449
|
embeddingsWorker: r,
|
|
@@ -440,10 +451,10 @@ const Ne = async ({
|
|
|
440
451
|
topResults: s,
|
|
441
452
|
embeddingCache: a
|
|
442
453
|
}) => {
|
|
443
|
-
const i = `req-${Date.now()}`,
|
|
454
|
+
const i = `req-${Date.now()}`, o = a ? await J(e, a) : void 0, c = {
|
|
444
455
|
type: "fieldSearch",
|
|
445
456
|
layerIdForFieldsSearch: t,
|
|
446
|
-
precomputedEmbedding:
|
|
457
|
+
precomputedEmbedding: o,
|
|
447
458
|
requestId: i,
|
|
448
459
|
minScore: n,
|
|
449
460
|
topResults: s
|
|
@@ -458,14 +469,14 @@ const Ne = async ({
|
|
|
458
469
|
}));
|
|
459
470
|
d(y);
|
|
460
471
|
};
|
|
461
|
-
r.addEventListener("message", u, { once: !0 }), r.postMessage(
|
|
472
|
+
r.addEventListener("message", u, { once: !0 }), r.postMessage(c);
|
|
462
473
|
});
|
|
463
474
|
};
|
|
464
|
-
function
|
|
475
|
+
function Oe(e) {
|
|
465
476
|
const { worker: t } = e;
|
|
466
477
|
return {
|
|
467
478
|
async searchFields({ text: r, layerIds: n, minScore: s, topResults: a, embeddingCache: i }) {
|
|
468
|
-
return await
|
|
479
|
+
return await He({
|
|
469
480
|
combinedQuery: r,
|
|
470
481
|
layerIds: n,
|
|
471
482
|
embeddingsWorker: t,
|
|
@@ -476,7 +487,7 @@ function He(e) {
|
|
|
476
487
|
}
|
|
477
488
|
};
|
|
478
489
|
}
|
|
479
|
-
const X = "0.1", w = 1536, Q = "openai", Y =
|
|
490
|
+
const X = "0.1", w = 1536, Q = "openai", Y = C.default, A = `Name: {name}
|
|
480
491
|
Title: {title}
|
|
481
492
|
Description: {description}`, F = `Name: {name}
|
|
482
493
|
Alias: {alias}
|
|
@@ -513,12 +524,12 @@ Description: {description}`, Z = l.object({
|
|
|
513
524
|
)
|
|
514
525
|
})
|
|
515
526
|
).default([])
|
|
516
|
-
}),
|
|
527
|
+
}), Ve = (e) => {
|
|
517
528
|
const t = Z.safeParse(e);
|
|
518
529
|
if (!t.success)
|
|
519
530
|
throw new Error("Embeddings response validation failed. Regenerate embeddings.");
|
|
520
531
|
return t.data;
|
|
521
|
-
},
|
|
532
|
+
}, ze = (e, t) => {
|
|
522
533
|
const r = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
|
|
523
534
|
if (t.allLayers.forEach((s) => {
|
|
524
535
|
s instanceof O && n.set(s.id, s);
|
|
@@ -538,29 +549,29 @@ Description: {description}`, Z = l.object({
|
|
|
538
549
|
name: s.name,
|
|
539
550
|
title: s.title,
|
|
540
551
|
description: s.description
|
|
541
|
-
},
|
|
542
|
-
for (const
|
|
543
|
-
const d = a.fieldsIndex.get(
|
|
552
|
+
}, o = /* @__PURE__ */ new Map();
|
|
553
|
+
for (const c of s.fields) {
|
|
554
|
+
const d = a.fieldsIndex.get(c.name);
|
|
544
555
|
if (!d)
|
|
545
556
|
throw new Error(
|
|
546
|
-
`Field with name ${
|
|
557
|
+
`Field with name ${c.name} not found in the original layer ${s.id} during registry restoration. Regenerate embeddings.`
|
|
547
558
|
);
|
|
548
|
-
|
|
549
|
-
name:
|
|
550
|
-
alias:
|
|
551
|
-
description:
|
|
559
|
+
o.set(c.name, {
|
|
560
|
+
name: c.name,
|
|
561
|
+
alias: c.alias,
|
|
562
|
+
description: c.description,
|
|
552
563
|
type: d.type || "unknown",
|
|
553
564
|
valueType: d.valueType || "unknown",
|
|
554
|
-
domain: a.getFieldDomain(
|
|
565
|
+
domain: a.getFieldDomain(c.name) ?? void 0
|
|
555
566
|
});
|
|
556
567
|
}
|
|
557
568
|
r.set(s.id, {
|
|
558
569
|
layerItem: i,
|
|
559
|
-
fieldRegistry:
|
|
570
|
+
fieldRegistry: o
|
|
560
571
|
});
|
|
561
572
|
}
|
|
562
573
|
return r;
|
|
563
|
-
},
|
|
574
|
+
}, Ge = async (e) => {
|
|
564
575
|
try {
|
|
565
576
|
return (await he(e, {
|
|
566
577
|
responseType: "json"
|
|
@@ -568,19 +579,19 @@ Description: {description}`, Z = l.object({
|
|
|
568
579
|
} catch (t) {
|
|
569
580
|
throw new Error(`Failed to fetch data from ${e}: ${String(t)}`);
|
|
570
581
|
}
|
|
571
|
-
},
|
|
582
|
+
}, Ke = async (e) => {
|
|
572
583
|
const t = e.map;
|
|
573
584
|
if (!t?.portalItem)
|
|
574
585
|
throw new Error("WebMap portal item is missing.");
|
|
575
586
|
const { resources: r } = await t.portalItem.fetchResources(), n = r.find((i) => i.resource.path === "embeddings-v01.json");
|
|
576
587
|
if (!n?.resource.url)
|
|
577
588
|
throw new Error("Embeddings resource 'embeddings-v01.json' not found in the webmap portal item.");
|
|
578
|
-
const s = await
|
|
579
|
-
return
|
|
589
|
+
const s = await Ge(n.resource.url);
|
|
590
|
+
return Ve(s);
|
|
580
591
|
};
|
|
581
592
|
class ee {
|
|
582
593
|
constructor() {
|
|
583
|
-
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.threadId = "", this.agentRegistry = new Ue(), this.streamEpoch = 0;
|
|
594
|
+
this.orchestratorReady = !1, this.chatHistory = [], this.priorSteps = [], this.sharedState = {}, this.threadId = "", this.agentRegistry = new Ue(), this.streamEpoch = 0;
|
|
584
595
|
}
|
|
585
596
|
/**
|
|
586
597
|
* Creates and returns an AI-ready Orchestrator instance.
|
|
@@ -592,7 +603,7 @@ class ee {
|
|
|
592
603
|
try {
|
|
593
604
|
if (t.view?.map) {
|
|
594
605
|
await H.whenOnce(() => t.view.ready);
|
|
595
|
-
const n = await
|
|
606
|
+
const n = await Ke(t.view), s = ze(
|
|
596
607
|
n.layers,
|
|
597
608
|
t.view.map
|
|
598
609
|
);
|
|
@@ -621,7 +632,7 @@ class ee {
|
|
|
621
632
|
if (++this.streamEpoch, !t.trim())
|
|
622
633
|
return;
|
|
623
634
|
this.threadId = String(Date.now()), this.graph || (this.graph = qe().compile({ checkpointer: new ae() }));
|
|
624
|
-
const r = this.embeddingsWorker ?
|
|
635
|
+
const r = this.embeddingsWorker ? Ne({ worker: this.embeddingsWorker }) : void 0, n = this.embeddingsWorker ? Oe({ worker: this.embeddingsWorker }) : void 0, s = /* @__PURE__ */ new Map(), i = {
|
|
625
636
|
version: "v2",
|
|
626
637
|
streamMode: "custom",
|
|
627
638
|
configurable: {
|
|
@@ -637,18 +648,25 @@ class ee {
|
|
|
637
648
|
}
|
|
638
649
|
},
|
|
639
650
|
subgraphs: !0
|
|
640
|
-
},
|
|
641
|
-
{
|
|
651
|
+
}, o = this.graph?.streamEvents(
|
|
652
|
+
{
|
|
653
|
+
agentExecutionContext: {
|
|
654
|
+
userRequest: t,
|
|
655
|
+
messages: this.chatHistory,
|
|
656
|
+
priorSteps: this.priorSteps,
|
|
657
|
+
sharedState: this.sharedState
|
|
658
|
+
}
|
|
659
|
+
},
|
|
642
660
|
i
|
|
643
|
-
),
|
|
644
|
-
for (yield* this.pipeStream(
|
|
661
|
+
), c = ++this.streamEpoch;
|
|
662
|
+
for (yield* this.pipeStream(o, c); ; ) {
|
|
645
663
|
const p = (await this.graph.getState(i, { subgraphs: !0 })).tasks.find((g) => g.interrupts.length > 0)?.interrupts[0]?.value;
|
|
646
664
|
if (!p)
|
|
647
665
|
break;
|
|
648
666
|
this.currentInterrupt = p, this.interruptHandler = new _e(this.graph, i), yield { runId: this.threadId, timestamp: Date.now(), type: "interrupt", interrupt: p };
|
|
649
667
|
try {
|
|
650
|
-
const g = await this.interruptHandler.waitForUser(),
|
|
651
|
-
yield* this.pipeStream(g,
|
|
668
|
+
const g = await this.interruptHandler.waitForUser(), I = ++this.streamEpoch;
|
|
669
|
+
yield* this.pipeStream(g, I);
|
|
652
670
|
} catch (g) {
|
|
653
671
|
if (g) {
|
|
654
672
|
yield {
|
|
@@ -668,14 +686,14 @@ class ee {
|
|
|
668
686
|
runId: this.threadId,
|
|
669
687
|
timestamp: Date.now(),
|
|
670
688
|
type: "completed",
|
|
671
|
-
result: { content:
|
|
689
|
+
result: { content: je(u.agentExecutionContext.messages) }
|
|
672
690
|
};
|
|
673
691
|
}
|
|
674
692
|
/**
|
|
675
|
-
* Start a new conversation by clearing chat history and
|
|
693
|
+
* Start a new conversation by clearing chat history, prior steps, and shared state.
|
|
676
694
|
*/
|
|
677
695
|
newConversation() {
|
|
678
|
-
this.chatHistory = [], this.priorSteps = [];
|
|
696
|
+
this.chatHistory = [], this.priorSteps = [], this.sharedState = {};
|
|
679
697
|
}
|
|
680
698
|
/**
|
|
681
699
|
* Generic resume for any HITL interrupt.
|
|
@@ -714,7 +732,7 @@ class ee {
|
|
|
714
732
|
this.embeddingsWorker && (this.embeddingsWorker.terminate(), this.embeddingsWorker = void 0), this.orchestratorReady = !1;
|
|
715
733
|
}
|
|
716
734
|
}
|
|
717
|
-
const
|
|
735
|
+
const Be = (e) => {
|
|
718
736
|
const t = /* @__PURE__ */ new Set();
|
|
719
737
|
for (const n of e)
|
|
720
738
|
if (oe(n)) {
|
|
@@ -733,35 +751,35 @@ const Ke = (e) => {
|
|
|
733
751
|
}, D = (e, t) => {
|
|
734
752
|
const r = de.fromTemplate(e);
|
|
735
753
|
return N.fromMessages([r, ...t]);
|
|
736
|
-
},
|
|
754
|
+
}, Je = async (e) => {
|
|
737
755
|
const { promptText: t, modelTier: r, temperature: n, messages: s } = e, a = D(t, s ?? []), i = await b(r, n);
|
|
738
756
|
return a.pipe(i);
|
|
739
|
-
},
|
|
740
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a } = e,
|
|
757
|
+
}, ht = async (e) => {
|
|
758
|
+
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a } = e, o = await (await Je({
|
|
741
759
|
promptText: t,
|
|
742
760
|
modelTier: r,
|
|
743
761
|
temperature: n,
|
|
744
762
|
messages: s
|
|
745
763
|
})).invoke(a ?? {});
|
|
746
|
-
if (typeof
|
|
747
|
-
return
|
|
748
|
-
const
|
|
749
|
-
return typeof
|
|
764
|
+
if (typeof o == "string")
|
|
765
|
+
return o;
|
|
766
|
+
const c = o.content;
|
|
767
|
+
return typeof c == "string" ? c : JSON.stringify(c);
|
|
750
768
|
}, te = async (e) => {
|
|
751
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, schema: i } = e,
|
|
752
|
-
return await
|
|
753
|
-
},
|
|
754
|
-
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, tools: i } = e,
|
|
755
|
-
return await
|
|
756
|
-
},
|
|
769
|
+
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, schema: i } = e, o = D(t, s ?? []), d = (await b(r, n)).withStructuredOutput(i);
|
|
770
|
+
return await o.pipe(d).invoke(a ?? {});
|
|
771
|
+
}, ft = async (e) => {
|
|
772
|
+
const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, tools: i } = e, o = i.length > 0 ? Be(s ?? []) : s ?? [], c = D(t, o), d = await b(r, n);
|
|
773
|
+
return await c.pipe(d.bindTools(i)).invoke(a ?? {});
|
|
774
|
+
}, Xe = h.object({
|
|
757
775
|
name: h.string(),
|
|
758
776
|
description: h.string(),
|
|
759
777
|
valueType: h.string(),
|
|
760
778
|
alias: h.string()
|
|
761
|
-
}),
|
|
762
|
-
fields: h.array(
|
|
779
|
+
}), Qe = h.object({
|
|
780
|
+
fields: h.array(Xe)
|
|
763
781
|
});
|
|
764
|
-
function
|
|
782
|
+
function U(e, t) {
|
|
765
783
|
const r = /* @__PURE__ */ new Map();
|
|
766
784
|
for (const n of e.fields) {
|
|
767
785
|
const s = t.fields.find((i) => i.name === n.name), a = {
|
|
@@ -776,14 +794,14 @@ function _(e, t) {
|
|
|
776
794
|
}
|
|
777
795
|
return r;
|
|
778
796
|
}
|
|
779
|
-
const
|
|
780
|
-
const r = await
|
|
781
|
-
const { name:
|
|
782
|
-
return [`Name: ${
|
|
797
|
+
const Ye = async (e) => {
|
|
798
|
+
const r = await T("field_descriptions_prompt"), n = e.fields.filter((i) => !(i.alias && i.description)).map((i) => {
|
|
799
|
+
const { name: o, type: c, alias: d, description: u } = i;
|
|
800
|
+
return [`Name: ${o}`, `Type: ${c}`, `Alias: ${d}`, `Description: ${u ?? "N/A"}`].join(", ");
|
|
783
801
|
}).join(`
|
|
784
802
|
`);
|
|
785
803
|
if (n.length === 0)
|
|
786
|
-
return
|
|
804
|
+
return U(e, { fields: [] });
|
|
787
805
|
const s = {
|
|
788
806
|
existingItemTitle: e.portalItem?.title,
|
|
789
807
|
existingItemDescription: e.portalItem?.description,
|
|
@@ -792,16 +810,16 @@ const Qe = async (e) => {
|
|
|
792
810
|
fieldInformation: n
|
|
793
811
|
}, a = await te({
|
|
794
812
|
promptText: r,
|
|
795
|
-
schema:
|
|
813
|
+
schema: Qe,
|
|
796
814
|
inputVariables: s
|
|
797
815
|
});
|
|
798
|
-
return
|
|
799
|
-
},
|
|
816
|
+
return U(e, a);
|
|
817
|
+
}, Ze = h.object({
|
|
800
818
|
title: h.string(),
|
|
801
819
|
description: h.string(),
|
|
802
820
|
name: h.string().nullable()
|
|
803
|
-
}),
|
|
804
|
-
const n = await
|
|
821
|
+
}), et = async (e, t) => {
|
|
822
|
+
const n = await T("layer_descriptions_prompt"), s = Array.from(t.values()), a = {
|
|
805
823
|
fieldInformation: JSON.stringify(s, null, 2),
|
|
806
824
|
existingLayerTitle: e.title,
|
|
807
825
|
existingLayerDescription: e.portalItem?.description,
|
|
@@ -810,23 +828,23 @@ const Qe = async (e) => {
|
|
|
810
828
|
};
|
|
811
829
|
return { ...await te({
|
|
812
830
|
promptText: n,
|
|
813
|
-
schema:
|
|
831
|
+
schema: Ze,
|
|
814
832
|
inputVariables: a
|
|
815
833
|
}), name: e.title ?? null };
|
|
816
|
-
},
|
|
834
|
+
}, tt = async (e) => {
|
|
817
835
|
const t = e.allLayers.toArray(), r = [], n = /* @__PURE__ */ new Map();
|
|
818
836
|
for (const s of t)
|
|
819
837
|
if (s instanceof O) {
|
|
820
838
|
const a = (async () => {
|
|
821
|
-
const i = await
|
|
822
|
-
n.set(s.id, { layerItem:
|
|
839
|
+
const i = await Ye(s), o = await et(s, i);
|
|
840
|
+
n.set(s.id, { layerItem: o, fieldRegistry: i });
|
|
823
841
|
})();
|
|
824
842
|
r.push(a);
|
|
825
843
|
}
|
|
826
844
|
return await Promise.all(r), n;
|
|
827
|
-
},
|
|
845
|
+
}, yt = async (e) => {
|
|
828
846
|
await H.whenOnce(() => e.ready);
|
|
829
|
-
const t = await
|
|
847
|
+
const t = await tt(e.map), { layers: r } = await nt(t), n = {
|
|
830
848
|
schemaVersion: X,
|
|
831
849
|
modified: Date.now(),
|
|
832
850
|
embeddings: {
|
|
@@ -843,25 +861,25 @@ const Qe = async (e) => {
|
|
|
843
861
|
if (!s.success)
|
|
844
862
|
throw console.error("Schema Mismatch:", s.error.format()), new Error("Webmap embedding generation failed validation.");
|
|
845
863
|
return s.data;
|
|
846
|
-
},
|
|
864
|
+
}, nt = async (e) => {
|
|
847
865
|
const t = [], r = [];
|
|
848
|
-
for (const [i, { fieldRegistry:
|
|
849
|
-
const d =
|
|
850
|
-
name:
|
|
851
|
-
title:
|
|
852
|
-
description:
|
|
866
|
+
for (const [i, { fieldRegistry: o, layerItem: c }] of e.entries()) {
|
|
867
|
+
const d = _(A, {
|
|
868
|
+
name: c.name,
|
|
869
|
+
title: c.title,
|
|
870
|
+
description: c.description
|
|
853
871
|
});
|
|
854
872
|
t.push(d);
|
|
855
873
|
const u = {
|
|
856
874
|
id: i,
|
|
857
|
-
name:
|
|
858
|
-
title:
|
|
859
|
-
description:
|
|
875
|
+
name: c.name ?? "",
|
|
876
|
+
title: c.title,
|
|
877
|
+
description: c.description,
|
|
860
878
|
vector: [],
|
|
861
879
|
fields: []
|
|
862
880
|
};
|
|
863
|
-
for (const [, m] of
|
|
864
|
-
const y =
|
|
881
|
+
for (const [, m] of o.entries()) {
|
|
882
|
+
const y = _(F, {
|
|
865
883
|
name: m.name,
|
|
866
884
|
alias: m.alias,
|
|
867
885
|
description: m.description
|
|
@@ -877,16 +895,16 @@ const Qe = async (e) => {
|
|
|
877
895
|
}
|
|
878
896
|
const n = await B(t);
|
|
879
897
|
let s = 0;
|
|
880
|
-
return { layers: r.map((i) => (i.vector = n[s++], i.fields.forEach((
|
|
881
|
-
|
|
898
|
+
return { layers: r.map((i) => (i.vector = n[s++], i.fields.forEach((o) => {
|
|
899
|
+
o.vector = n[s++];
|
|
882
900
|
}), i)) };
|
|
883
|
-
},
|
|
901
|
+
}, _ = (e, t) => e.replace(/\{(\w+)\}/gu, (r, n) => t[n] ?? ""), wt = (e, t) => {
|
|
884
902
|
if (e.length !== t.length)
|
|
885
903
|
throw new Error("Vectors must be the same length");
|
|
886
904
|
let r = 0, n = 0, s = 0;
|
|
887
|
-
for (let
|
|
888
|
-
const
|
|
889
|
-
r +=
|
|
905
|
+
for (let o = 0; o < e.length; ++o) {
|
|
906
|
+
const c = e[o], d = t[o];
|
|
907
|
+
r += c * d, n += c * c, s += d * d;
|
|
890
908
|
}
|
|
891
909
|
const a = Math.sqrt(n * s);
|
|
892
910
|
if (a === 0)
|
|
@@ -896,13 +914,13 @@ const Qe = async (e) => {
|
|
|
896
914
|
};
|
|
897
915
|
export {
|
|
898
916
|
ee as Orchestrator,
|
|
899
|
-
|
|
917
|
+
wt as cosineSimilarity,
|
|
900
918
|
b as createChatModel,
|
|
901
|
-
|
|
919
|
+
yt as createWebmapEmbeddings,
|
|
902
920
|
B as getEmbeddings,
|
|
903
921
|
te as invokeStructuredPrompt,
|
|
904
|
-
|
|
905
|
-
|
|
922
|
+
ht as invokeTextPrompt,
|
|
923
|
+
ft as invokeToolPrompt,
|
|
906
924
|
f as sendTraceMessage,
|
|
907
|
-
|
|
925
|
+
pt as sendUXSuggestion
|
|
908
926
|
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const e = `## GIS Agent Orchestrator
|
|
2
|
+
|
|
3
|
+
You are an orchestrator for an ArcGIS Maps SDK for JavaScript system.
|
|
4
|
+
|
|
5
|
+
Your job is to decide the single best next agent to execute for the current step.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
|
|
11
|
+
You are given:
|
|
12
|
+
|
|
13
|
+
- the latest user request
|
|
14
|
+
- relevant chat history
|
|
15
|
+
- the list of registered agents
|
|
16
|
+
- optional prior steps from earlier agent executions
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Output
|
|
21
|
+
|
|
22
|
+
Return either:
|
|
23
|
+
|
|
24
|
+
- one decision with:
|
|
25
|
+
1. \`agentId\` — the next agent to execute
|
|
26
|
+
2. \`assignedTask\` — a clear, actionable task for that agent
|
|
27
|
+
3. \`requiresFollowUp\` — whether another orchestration step will likely be needed after this agent succeeds
|
|
28
|
+
|
|
29
|
+
- or \`null\` if no registered agent applies
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Important
|
|
34
|
+
|
|
35
|
+
- Return \`null\` only when the request is clearly outside the scope of all registered agents.
|
|
36
|
+
- If any agent can take the next useful step, select the best one instead of returning \`null\`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Context
|
|
41
|
+
|
|
42
|
+
### Latest user request
|
|
43
|
+
|
|
44
|
+
{userRequest}
|
|
45
|
+
|
|
46
|
+
### Registered agents
|
|
47
|
+
|
|
48
|
+
Format:
|
|
49
|
+
{{id: string, name: string, description: string}}[]
|
|
50
|
+
|
|
51
|
+
{registeredAgents}
|
|
52
|
+
|
|
53
|
+
### Prior steps
|
|
54
|
+
|
|
55
|
+
Each step has:
|
|
56
|
+
|
|
57
|
+
- \`agentId: string\`
|
|
58
|
+
- \`assignedTask: string\`
|
|
59
|
+
- \`summary: string\`
|
|
60
|
+
- \`status: "success" | "failed" | "unknown"\`
|
|
61
|
+
|
|
62
|
+
Use prior steps to:
|
|
63
|
+
|
|
64
|
+
- Avoid repeating work that has already succeeded
|
|
65
|
+
- Retry or adjust steps that failed when appropriate
|
|
66
|
+
|
|
67
|
+
{priorSteps}
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Rules
|
|
72
|
+
|
|
73
|
+
- Focus primarily on the latest user request.
|
|
74
|
+
- Use relevant chat history only when the latest request clearly depends on earlier context; otherwise ignore it.
|
|
75
|
+
- Use prior steps to determine what has already been attempted or completed.
|
|
76
|
+
- Do not plan the full workflow up front. Only decide the next best step.
|
|
77
|
+
- Prefer an agent that can directly complete the user’s request.
|
|
78
|
+
- Only break the request into multiple steps when necessary.
|
|
79
|
+
- When multiple agents could help, choose the best fit instead of returning \`null\`.
|
|
80
|
+
- Base the choice on the registered agent descriptions, not on whether the user used exact matching keywords.
|
|
81
|
+
- 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\`.
|
|
82
|
+
- Do NOT reuse constraints from prior steps unless the current user request explicitly requires them.
|
|
83
|
+
- Each step must reflect the current user request exactly.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Constraint Interpretation
|
|
88
|
+
|
|
89
|
+
Interpret the user’s wording precisely:
|
|
90
|
+
|
|
91
|
+
- Do not substitute one type of constraint for another (e.g., distance vs containment, range vs exact match, etc.)
|
|
92
|
+
- If the user specifies a constraint, use it exactly
|
|
93
|
+
- If the user does not specify a constraint, do not assume or infer one
|
|
94
|
+
|
|
95
|
+
Do not reinterpret the request into a different form.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Assigned Task Guidelines (IMPORTANT)
|
|
100
|
+
|
|
101
|
+
- The \`assignedTask\` must match the user’s request exactly in meaning
|
|
102
|
+
- Do not add, remove, or transform constraints
|
|
103
|
+
- Do not substitute one type of constraint for another
|
|
104
|
+
- If a constraint is not explicitly stated, do not assume one
|
|
105
|
+
|
|
106
|
+
- Keep the task short, specific, and directly executable
|
|
107
|
+
- Keep wording close to the user’s request with minimal transformation
|
|
108
|
+
- Use only information explicitly present in the user request or provided context
|
|
109
|
+
|
|
110
|
+
- The \`assignedTask\` may represent only part of the user’s request when multiple steps are necessary
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## requiresFollowUp Guidelines
|
|
115
|
+
|
|
116
|
+
- \`requiresFollowUp\` should indicate a likely next agent step, not uncertainty about the current request
|
|
117
|
+
- Set \`requiresFollowUp\` to \`true\` only when another orchestration step will likely be needed after this agent succeeds
|
|
118
|
+
- Set \`requiresFollowUp\` to \`false\` when a successful result from this agent would likely complete the user-visible task
|
|
119
|
+
`;
|
|
120
|
+
export {
|
|
121
|
+
e as default
|
|
122
|
+
};
|
|
@@ -24,6 +24,7 @@ export declare class Orchestrator {
|
|
|
24
24
|
private graph?;
|
|
25
25
|
private chatHistory;
|
|
26
26
|
private priorSteps;
|
|
27
|
+
private sharedState;
|
|
27
28
|
private threadId;
|
|
28
29
|
private agentRegistry;
|
|
29
30
|
private layersAndFieldsRegistry?;
|
|
@@ -47,7 +48,7 @@ export declare class Orchestrator {
|
|
|
47
48
|
*/
|
|
48
49
|
ask(userInput: string): AsyncGenerator<OrchestratorEvent>;
|
|
49
50
|
/**
|
|
50
|
-
* Start a new conversation by clearing chat history and
|
|
51
|
+
* Start a new conversation by clearing chat history, prior steps, and shared state.
|
|
51
52
|
*/
|
|
52
53
|
newConversation(): void;
|
|
53
54
|
/**
|
package/dist/types/types.d.ts
CHANGED
|
@@ -63,6 +63,7 @@ export interface AgentExecutionContext {
|
|
|
63
63
|
assignedTask: string;
|
|
64
64
|
messages: ChatHistory;
|
|
65
65
|
priorSteps: PriorStep[];
|
|
66
|
+
sharedState: Record<string, unknown>;
|
|
66
67
|
}
|
|
67
68
|
export interface PriorStep {
|
|
68
69
|
agentId: string;
|
|
@@ -71,8 +72,9 @@ export interface PriorStep {
|
|
|
71
72
|
status: AgentStatus;
|
|
72
73
|
}
|
|
73
74
|
export interface AgentResult {
|
|
74
|
-
status
|
|
75
|
+
status?: AgentStatus;
|
|
75
76
|
outputMessage?: string;
|
|
76
77
|
summary?: string;
|
|
78
|
+
sharedStatePatch?: Record<string, unknown>;
|
|
77
79
|
}
|
|
78
80
|
export type AgentStatus = "failed" | "success" | "unknown";
|
package/package.json
CHANGED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
const e = `## GIS Agent Orchestrator
|
|
2
|
-
|
|
3
|
-
You are an orchestrator for an ArcGIS Maps SDK for JavaScript system.
|
|
4
|
-
|
|
5
|
-
Your job is to decide the single best next agent to execute for the current step.
|
|
6
|
-
|
|
7
|
-
You are given:
|
|
8
|
-
|
|
9
|
-
- the latest user request
|
|
10
|
-
- relevant chat history
|
|
11
|
-
- the list of registered agents
|
|
12
|
-
- optional prior steps from earlier agent executions
|
|
13
|
-
|
|
14
|
-
Return either:
|
|
15
|
-
|
|
16
|
-
- one decision with:
|
|
17
|
-
1. \`agentId\` — the next agent to execute
|
|
18
|
-
2. \`assignedTask\` — a clear, actionable task for that agent
|
|
19
|
-
3. \`requiresFollowUp\` — whether another orchestration step will likely be needed after this agent succeeds
|
|
20
|
-
- or \`null\` if no registered agent applies
|
|
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
|
-
|
|
27
|
-
Latest user request:
|
|
28
|
-
{userRequest}
|
|
29
|
-
|
|
30
|
-
Registered agents are provided in this format:
|
|
31
|
-
{{id: string, name: string, description: string}}[]
|
|
32
|
-
|
|
33
|
-
{registeredAgents}
|
|
34
|
-
|
|
35
|
-
Prior steps performed by agents are provided:
|
|
36
|
-
|
|
37
|
-
Each step has:
|
|
38
|
-
|
|
39
|
-
- agentId: string
|
|
40
|
-
- assignedTask: string
|
|
41
|
-
- summary: string
|
|
42
|
-
- status: "success" | "failed" | "unknown"
|
|
43
|
-
|
|
44
|
-
Use prior steps to:
|
|
45
|
-
|
|
46
|
-
- Avoid repeating work that has already succeeded
|
|
47
|
-
- Retry or adjust steps that failed when appropriate
|
|
48
|
-
|
|
49
|
-
{priorSteps}
|
|
50
|
-
|
|
51
|
-
Rules:
|
|
52
|
-
|
|
53
|
-
- Focus primarily on the latest user request.
|
|
54
|
-
- Use relevant chat history only when the latest request clearly depends on earlier context; otherwise ignore it.
|
|
55
|
-
- Use prior steps to determine what has already been attempted or completed.
|
|
56
|
-
- Do not plan the full workflow up front. Only decide the next best step.
|
|
57
|
-
- Prefer an agent that can directly complete the user’s request.
|
|
58
|
-
- Only break the request into multiple steps when necessary.
|
|
59
|
-
- When multiple agents could help, choose the best fit instead of returning \`null\`.
|
|
60
|
-
- Base the choice on the registered agent descriptions, not on whether the user used exact matching keywords.
|
|
61
|
-
- 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.
|
|
62
|
-
|
|
63
|
-
Assigned Task Guidelines (IMPORTANT):
|
|
64
|
-
|
|
65
|
-
- The assignedTask should be specific, short, and directly executable by the selected agent.
|
|
66
|
-
- Keep it as close as possible to the user’s request.
|
|
67
|
-
- Prefer minimal transformation of the user’s wording.
|
|
68
|
-
- It should be a concise restatement, not a rewritten or expanded version.
|
|
69
|
-
- Do not rephrase into more detailed or formal language than the user’s request.
|
|
70
|
-
- Use only information explicitly present in the user request or provided context.
|
|
71
|
-
- Do not enrich, elaborate, or add unstated details.
|
|
72
|
-
- Do not clarify or expand the request beyond what the user explicitly stated.
|
|
73
|
-
- Do not add implementation details, UI behavior, or inferred steps.
|
|
74
|
-
- The assignedTask may represent only part of the user’s full request when multiple steps are necessary.
|
|
75
|
-
|
|
76
|
-
requiresFollowUp Guidelines:
|
|
77
|
-
|
|
78
|
-
- requiresFollowUp should indicate a likely next agent step, not uncertainty about the current request.
|
|
79
|
-
- Set requiresFollowUp to true only when another orchestration step will likely be needed after this agent succeeds.
|
|
80
|
-
- Set requiresFollowUp to false when a successful result from this agent would likely complete the user-visible task.
|
|
81
|
-
`;
|
|
82
|
-
export {
|
|
83
|
-
e as default
|
|
84
|
-
};
|