@tangle-network/agent-app 0.43.13 → 0.43.14

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.
@@ -1,12 +1,12 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import { ToolDetailRenderers, ChatUiMessage } from '../web-react/index.js';
4
+ import '@tangle-network/agent-interface';
4
5
  import '../agent-activity-C8ZG0F0M.js';
5
6
  import '../flow-types-Cb_AblZs.js';
6
7
  import '../sandbox-terminal-BIIC__CP.js';
7
8
  import '../model-catalog-BEAEVDaa.js';
8
9
  import '../harness/index.js';
9
- import '@tangle-network/agent-interface';
10
10
 
11
11
  /**
12
12
  * Wire + UI types for the in-app assistant panel. The wire shapes mirror the
@@ -3,7 +3,7 @@ import {
3
3
  ChatMessages,
4
4
  ModelPicker,
5
5
  ProviderLogo
6
- } from "../chunk-4X7OOVII.js";
6
+ } from "../chunk-VMY4TKMN.js";
7
7
  import "../chunk-65P3HJY3.js";
8
8
  import "../chunk-2QI7XV2T.js";
9
9
  import "../chunk-E7QYOOON.js";
@@ -364,6 +364,145 @@ function BrandMark({ size = 24, className }) {
364
364
  return /* @__PURE__ */ jsx3(Suspense, { fallback: /* @__PURE__ */ jsx3(MarkSpacer, { size, className }), children: /* @__PURE__ */ jsx3(LazyKnot, { size, className }) });
365
365
  }
366
366
 
367
+ // src/web-react/chat-interactions.ts
368
+ import {
369
+ InteractionRequestSchema
370
+ } from "@tangle-network/agent-interface";
371
+ var INTERACTION_EVENT = "interaction";
372
+ var INTERACTION_CANCEL_EVENT = "interaction.cancel";
373
+ var INTERACTION_RESOLVED_EVENT = "interaction.resolved";
374
+ var RENDERABLE_INTERACTION_KINDS = /* @__PURE__ */ new Set(["question", "plan"]);
375
+ function isRenderableInteractionKind(kind) {
376
+ return RENDERABLE_INTERACTION_KINDS.has(kind);
377
+ }
378
+ function isSafeInteractionFieldKey(key) {
379
+ return /^[A-Za-z0-9_-]+$/.test(key) && key !== "__proto__" && key !== "constructor" && key !== "prototype";
380
+ }
381
+ function isTerminalInteractionStatus(status) {
382
+ return status !== "pending";
383
+ }
384
+ function canTransitionInteractionStatus(from, to) {
385
+ return from === "pending" && to !== from;
386
+ }
387
+ function cancelStatusFor(reason) {
388
+ return reason === "timeout" ? "expired" : "cancelled";
389
+ }
390
+ function stableValue(value) {
391
+ if (Array.isArray(value)) return value.map(stableValue);
392
+ if (!value || typeof value !== "object") return value;
393
+ return Object.fromEntries(
394
+ Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, nested]) => [key, stableValue(nested)])
395
+ );
396
+ }
397
+ function normalizedInteractionText(value) {
398
+ return (value ?? "").replace(/\s+/g, " ").trim();
399
+ }
400
+ function questionInteractionContentSignature(interaction) {
401
+ if (interaction.kind !== "question") return null;
402
+ return JSON.stringify(stableValue({
403
+ kind: interaction.kind,
404
+ title: normalizedInteractionText(interaction.title),
405
+ body: normalizedInteractionText(interaction.body),
406
+ fields: interaction.fields
407
+ }));
408
+ }
409
+ function dedupeQuestionInteractionsByContent(interactions) {
410
+ const seen = /* @__PURE__ */ new Set();
411
+ return interactions.filter((interaction) => {
412
+ const signature = questionInteractionContentSignature(interaction);
413
+ if (!signature) return true;
414
+ if (seen.has(signature)) return false;
415
+ seen.add(signature);
416
+ return true;
417
+ });
418
+ }
419
+ function parseInteractionRequest(data) {
420
+ const request = data?.request;
421
+ if (!request || typeof request !== "object") {
422
+ return { succeeded: false, error: "interaction event carried no request object" };
423
+ }
424
+ const validation = InteractionRequestSchema.safeParse(request);
425
+ if (!validation.success) {
426
+ return { succeeded: false, error: `malformed interaction request: ${validation.error.message}` };
427
+ }
428
+ return { succeeded: true, value: request };
429
+ }
430
+ function parseInteractionCancel(data) {
431
+ const id = typeof data?.id === "string" && data.id ? data.id : null;
432
+ if (!id) return { succeeded: false, error: "interaction.cancel event carried no id" };
433
+ const reason = typeof data?.reason === "string" && data.reason ? data.reason : void 0;
434
+ return { succeeded: true, value: { id, ...reason ? { reason } : {} } };
435
+ }
436
+ function fieldAcceptsFreeText(field) {
437
+ if (field.type === "text") return true;
438
+ if (field.type === "select") return field.allowCustom === true;
439
+ return false;
440
+ }
441
+ function composerAnswerDeliveries(pending) {
442
+ const deliveries = [];
443
+ for (const interaction of pending) {
444
+ if (interaction.kind !== "question") continue;
445
+ const field = interaction.fields.find(fieldAcceptsFreeText) ?? interaction.fields[0];
446
+ if (!field) continue;
447
+ deliveries.push({ interactionId: interaction.id, field });
448
+ }
449
+ return deliveries;
450
+ }
451
+ function composerAnswerData(field, text) {
452
+ return { [field.name]: field.type === "select" ? [text] : text };
453
+ }
454
+ function interactionPartKey(id) {
455
+ return `interaction:${id}`;
456
+ }
457
+ function noticePartKey(id) {
458
+ return `notice:${id}`;
459
+ }
460
+ function noticePart(noticeKind, id, text) {
461
+ return { type: "notice", id, noticeKind, text };
462
+ }
463
+ function interactionFromWireRequest(request) {
464
+ return {
465
+ id: request.id,
466
+ kind: request.kind,
467
+ title: request.title,
468
+ ...request.body ? { body: request.body } : {},
469
+ fields: request.answerSpec.fields,
470
+ status: "pending"
471
+ };
472
+ }
473
+ function interactionToPersistedPart(request, status, cancelReason) {
474
+ return {
475
+ type: "interaction",
476
+ id: request.id,
477
+ kind: request.kind,
478
+ title: request.title,
479
+ ...request.body ? { body: request.body } : {},
480
+ answerSpec: { fields: request.answerSpec.fields },
481
+ status,
482
+ ...cancelReason ? { cancelReason } : {}
483
+ };
484
+ }
485
+ function persistedPartToInteraction(part) {
486
+ if (String(part.type ?? "") !== "interaction") return null;
487
+ const id = typeof part.id === "string" && part.id ? part.id : null;
488
+ const kind = typeof part.kind === "string" && part.kind ? part.kind : null;
489
+ const title = typeof part.title === "string" ? part.title : "";
490
+ const answerSpec = part.answerSpec;
491
+ const fields = Array.isArray(answerSpec?.fields) ? answerSpec.fields : null;
492
+ const status = part.status;
493
+ const validStatus = status && ["pending", "answered", "declined", "cancelled", "expired"].includes(status);
494
+ if (!id || !kind || !fields || !validStatus) return null;
495
+ return {
496
+ id,
497
+ kind,
498
+ title,
499
+ ...typeof part.body === "string" && part.body ? { body: part.body } : {},
500
+ fields,
501
+ status,
502
+ ...typeof part.cancelReason === "string" && part.cancelReason ? { cancelReason: part.cancelReason } : {}
503
+ };
504
+ }
505
+
367
506
  // src/web-react/chat-stream.ts
368
507
  function dispatchChatStreamLine(line, cb) {
369
508
  let receivedContent = false;
@@ -429,6 +568,16 @@ function dispatchChatStreamLine(line, cb) {
429
568
  case "metadata":
430
569
  cb.onMetadata?.(evt.data ?? {});
431
570
  break;
571
+ case "interaction": {
572
+ const parsed2 = parseInteractionRequest(evt.data);
573
+ if (parsed2.succeeded) {
574
+ cb.onInteraction?.(interactionFromWireRequest(parsed2.value));
575
+ receivedContent = true;
576
+ } else {
577
+ console.error("[chat-stream] dropping malformed interaction line:", parsed2.error);
578
+ }
579
+ break;
580
+ }
432
581
  case "error":
433
582
  cb.onErrorEvent?.(String(evt.details ?? evt.error ?? "Unknown stream error"));
434
583
  break;
@@ -1914,6 +2063,27 @@ export {
1914
2063
  ModelPicker,
1915
2064
  DEFAULT_EFFORT_LEVELS,
1916
2065
  EffortPicker,
2066
+ INTERACTION_EVENT,
2067
+ INTERACTION_CANCEL_EVENT,
2068
+ INTERACTION_RESOLVED_EVENT,
2069
+ isRenderableInteractionKind,
2070
+ isSafeInteractionFieldKey,
2071
+ isTerminalInteractionStatus,
2072
+ canTransitionInteractionStatus,
2073
+ cancelStatusFor,
2074
+ questionInteractionContentSignature,
2075
+ dedupeQuestionInteractionsByContent,
2076
+ parseInteractionRequest,
2077
+ parseInteractionCancel,
2078
+ fieldAcceptsFreeText,
2079
+ composerAnswerDeliveries,
2080
+ composerAnswerData,
2081
+ interactionPartKey,
2082
+ noticePartKey,
2083
+ noticePart,
2084
+ interactionFromWireRequest,
2085
+ interactionToPersistedPart,
2086
+ persistedPartToInteraction,
1917
2087
  dispatchChatStreamLine,
1918
2088
  consumeChatStream,
1919
2089
  streamChatTurn,
@@ -1936,4 +2106,4 @@ export {
1936
2106
  useThinkingSeconds,
1937
2107
  ChatMessages
1938
2108
  };
1939
- //# sourceMappingURL=chunk-4X7OOVII.js.map
2109
+ //# sourceMappingURL=chunk-VMY4TKMN.js.map