@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 CHANGED
@@ -1,8 +1,8 @@
1
- import R from "@arcgis/core/identity/IdentityManager.js";
2
- import I from "@arcgis/core/portal/Portal.js";
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 W, AIMessage as k, isAIMessage as oe, isToolMessage as ce } from "@langchain/core/messages";
5
- import { dispatchCustomEvent as j } from "@langchain/core/callbacks/dispatch/web";
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
- }, T = {
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 = I.getDefault().helperServices;
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(T[e]), we = async (e) => {
43
- const t = await ve(), r = await G("default"), n = I.getDefault(), a = (await R.getCredential(`${n.url}/sharing`)).token, i = {
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((c, o) => {
48
+ return t.postMessage(i), await new Promise((o, c) => {
49
49
  const d = (m) => {
50
- m.data === "completed" && (t.removeEventListener("message", d), c());
50
+ m.data === "completed" && (t.removeEventListener("message", d), o());
51
51
  }, u = (m) => {
52
- t.removeEventListener("message", d), o(m instanceof Error ? m : new Error("Embeddings worker error"));
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 j("trace_message", e, t);
88
- }, gt = async (e, t) => {
89
- await j("graph_ux_suggestion", e, t);
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
- }, Ie = async (e, t) => {
93
+ }, Se = async (e, t) => {
93
94
  if (e.agentExecutionContext.userRequest) {
94
- const n = new W(e.agentExecutionContext.userRequest.trim());
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
- }, Se = async (e, t) => (await f({ text: "Exiting..." }, t), e), $ = 4e3, q = (e) => {
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 = q(t?.outputMessage), n = q(t?.summary), s = t?.status ?? "unknown";
117
- return s === "unknown" && console.warn(`Registered agent "${e}" returned an invalid or missing status.`), {
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(s),
120
- status: s
122
+ summary: n ?? r ?? Me(a),
123
+ status: a,
124
+ sharedStatePatch: o
121
125
  };
122
- }, ke = async (e, t) => {
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
- priorSteps: [...e.agentExecutionContext.priorSteps ?? []]
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 c = i.outputMessage, o = [...e.agentExecutionContext.messages];
159
- if (c) {
160
- const d = c.length > $ ? `${c.slice(0, $ - 14)}
161
- [truncated]` : c;
162
- o.push(new k(d));
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: o,
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.status
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
- }, C = async (e) => (await Te(/* @__PURE__ */ Object.assign({ "./field_descriptions_prompt.md": () => import("./field_descriptions_prompt-haMV_aoG.js"), "./intent_prompt.md": () => import("./intent_prompt-BSRo2YLj.js"), "./layer_descriptions_prompt.md": () => import("./layer_descriptions_prompt-NAaKWdJi.js") }), `./${e}.md`, 2)).default, Ce = async (e) => {
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 = I.getDefault(), n = await R.getCredential(`${r.url}/sharing`), s = V[e], a = await ye(e);
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
- }, Ae = async (e = "default") => {
214
- const t = I.getDefault(), r = await R.getCredential(`${t.url}/sharing`), n = T[e], s = await G(e);
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
- }, Fe = l.object({
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(Fe);
231
- const U = (e) => JSON.stringify(e, null, 2), De = (e) => {
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
- }, Le = async (e, t) => {
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 C("intent_prompt"), i = U(s), c = De(s), o = {
259
+ const a = await T("intent_prompt"), i = q(s), o = Le(s), c = {
249
260
  registeredAgents: i,
250
- priorSteps: U(e.agentExecutionContext.priorSteps),
261
+ priorSteps: q(e.agentExecutionContext.priorSteps),
251
262
  userRequest: e.agentExecutionContext.userRequest
252
- }, u = await N.fromTemplate(a).format(o), m = le({
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: c,
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 Ce({
282
+ }), { structuredResponse: y } = await Ae({
272
283
  agent: m,
273
284
  messages: e.agentExecutionContext.messages,
274
285
  config: t
275
- }), p = c.parse(
286
+ }), p = o.parse(
276
287
  y ?? { intent: null, assignedTask: null, requiresFollowUp: !1 }
277
- ), g = p.intent ?? "none", S = {
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 k(v)],
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: "success"
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
- ), S;
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
- }, $e = 3, qe = () => new re(be).addNode("ingestInput", Ie).addNode("intentLLM", Le).addNode("executeRegisteredAgent", ke).addNode("exit", Se).addEdge(se, "ingestInput").addEdge("ingestInput", "intentLLM").addConditionalEdges("intentLLM", (t) => t.currentIntent === "none" ? "exit" : "executeRegisteredAgent").addConditionalEdges(
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 >= $e || !t.requiresFollowUp ? "exit" : "intentLLM"
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 Pe = (e) => {
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 W) {
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 k).map((r) => r.content).join(`
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 Ae()).embedDocuments(e);
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((c) => {
417
- const o = (d) => {
418
- d.data.requestId === s && c(d.data.results);
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", o, { once: !0 }), t.postMessage(i);
431
+ t.addEventListener("message", c, { once: !0 }), t.postMessage(i);
421
432
  });
422
433
  }
423
- function je(e) {
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 Ne = async ({
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()}`, c = a ? await J(e, a) : void 0, o = {
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: c,
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(o);
472
+ r.addEventListener("message", u, { once: !0 }), r.postMessage(c);
462
473
  });
463
474
  };
464
- function He(e) {
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 Ne({
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 = T.default, A = `Name: {name}
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
- }), Oe = (e) => {
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
- }, Ve = (e, t) => {
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
- }, c = /* @__PURE__ */ new Map();
542
- for (const o of s.fields) {
543
- const d = a.fieldsIndex.get(o.name);
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 ${o.name} not found in the original layer ${s.id} during registry restoration. Regenerate embeddings.`
557
+ `Field with name ${c.name} not found in the original layer ${s.id} during registry restoration. Regenerate embeddings.`
547
558
  );
548
- c.set(o.name, {
549
- name: o.name,
550
- alias: o.alias,
551
- description: o.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(o.name) ?? void 0
565
+ domain: a.getFieldDomain(c.name) ?? void 0
555
566
  });
556
567
  }
557
568
  r.set(s.id, {
558
569
  layerItem: i,
559
- fieldRegistry: c
570
+ fieldRegistry: o
560
571
  });
561
572
  }
562
573
  return r;
563
- }, ze = async (e) => {
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
- }, Ge = async (e) => {
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 ze(n.resource.url);
579
- return Oe(s);
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 Ge(t.view), s = Ve(
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 ? je({ worker: this.embeddingsWorker }) : void 0, n = this.embeddingsWorker ? He({ worker: this.embeddingsWorker }) : void 0, s = /* @__PURE__ */ new Map(), i = {
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
- }, c = this.graph?.streamEvents(
641
- { agentExecutionContext: { userRequest: t, messages: this.chatHistory, priorSteps: this.priorSteps } },
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
- ), o = ++this.streamEpoch;
644
- for (yield* this.pipeStream(c, o); ; ) {
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(), S = ++this.streamEpoch;
651
- yield* this.pipeStream(g, S);
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: Pe(u.agentExecutionContext.messages) }
689
+ result: { content: je(u.agentExecutionContext.messages) }
672
690
  };
673
691
  }
674
692
  /**
675
- * Start a new conversation by clearing chat history and prior steps.
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 Ke = (e) => {
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
- }, Be = async (e) => {
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
- }, pt = async (e) => {
740
- const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a } = e, c = await (await Be({
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 c == "string")
747
- return c;
748
- const o = c.content;
749
- return typeof o == "string" ? o : JSON.stringify(o);
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, c = D(t, s ?? []), d = (await b(r, n)).withStructuredOutput(i);
752
- return await c.pipe(d).invoke(a ?? {});
753
- }, ht = async (e) => {
754
- const { promptText: t, modelTier: r = "default", temperature: n = 0, messages: s, inputVariables: a, tools: i } = e, c = i.length > 0 ? Ke(s ?? []) : s ?? [], o = D(t, c), d = await b(r, n);
755
- return await o.pipe(d.bindTools(i)).invoke(a ?? {});
756
- }, Je = h.object({
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
- }), Xe = h.object({
762
- fields: h.array(Je)
779
+ }), Qe = h.object({
780
+ fields: h.array(Xe)
763
781
  });
764
- function _(e, t) {
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 Qe = async (e) => {
780
- const r = await C("field_descriptions_prompt"), n = e.fields.filter((i) => !(i.alias && i.description)).map((i) => {
781
- const { name: c, type: o, alias: d, description: u } = i;
782
- return [`Name: ${c}`, `Type: ${o}`, `Alias: ${d}`, `Description: ${u ?? "N/A"}`].join(", ");
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 _(e, { fields: [] });
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: Xe,
813
+ schema: Qe,
796
814
  inputVariables: s
797
815
  });
798
- return _(e, a);
799
- }, Ye = h.object({
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
- }), Ze = async (e, t) => {
804
- const n = await C("layer_descriptions_prompt"), s = Array.from(t.values()), a = {
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: Ye,
831
+ schema: Ze,
814
832
  inputVariables: a
815
833
  }), name: e.title ?? null };
816
- }, et = async (e) => {
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 Qe(s), c = await Ze(s, i);
822
- n.set(s.id, { layerItem: c, fieldRegistry: i });
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
- }, ft = async (e) => {
845
+ }, yt = async (e) => {
828
846
  await H.whenOnce(() => e.ready);
829
- const t = await et(e.map), { layers: r } = await tt(t), n = {
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
- }, tt = async (e) => {
864
+ }, nt = async (e) => {
847
865
  const t = [], r = [];
848
- for (const [i, { fieldRegistry: c, layerItem: o }] of e.entries()) {
849
- const d = P(A, {
850
- name: o.name,
851
- title: o.title,
852
- description: o.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: o.name ?? "",
858
- title: o.title,
859
- description: o.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 c.entries()) {
864
- const y = P(F, {
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((c) => {
881
- c.vector = n[s++];
898
+ return { layers: r.map((i) => (i.vector = n[s++], i.fields.forEach((o) => {
899
+ o.vector = n[s++];
882
900
  }), i)) };
883
- }, P = (e, t) => e.replace(/\{(\w+)\}/gu, (r, n) => t[n] ?? ""), yt = (e, t) => {
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 c = 0; c < e.length; ++c) {
888
- const o = e[c], d = t[c];
889
- r += o * d, n += o * o, s += d * d;
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
- yt as cosineSimilarity,
917
+ wt as cosineSimilarity,
900
918
  b as createChatModel,
901
- ft as createWebmapEmbeddings,
919
+ yt as createWebmapEmbeddings,
902
920
  B as getEmbeddings,
903
921
  te as invokeStructuredPrompt,
904
- pt as invokeTextPrompt,
905
- ht as invokeToolPrompt,
922
+ ht as invokeTextPrompt,
923
+ ft as invokeToolPrompt,
906
924
  f as sendTraceMessage,
907
- gt as sendUXSuggestion
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 prior steps.
51
+ * Start a new conversation by clearing chat history, prior steps, and shared state.
51
52
  */
52
53
  newConversation(): void;
53
54
  /**
@@ -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: AgentStatus;
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcgis/ai-orchestrator",
3
- "version": "5.1.0-next.87",
3
+ "version": "5.1.0-next.89",
4
4
  "description": "ArcGIS AI Orchestrator Package",
5
5
  "homepage": "https://developers.arcgis.com/javascript/latest/",
6
6
  "type": "module",
@@ -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
- };