@nxisai/agent-harness 0.6.0 → 0.7.0

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.
Files changed (46) hide show
  1. package/README.md +16 -3
  2. package/dist/handoff/tools.d.ts.map +1 -1
  3. package/dist/handoff/tools.js +11 -4
  4. package/dist/handoff/tools.js.map +1 -1
  5. package/dist/harness/harness.d.ts.map +1 -1
  6. package/dist/harness/harness.js +26 -8
  7. package/dist/harness/harness.js.map +1 -1
  8. package/dist/harness/renderer.d.ts +20 -0
  9. package/dist/harness/renderer.d.ts.map +1 -1
  10. package/dist/harness/tools/action-tools.d.ts +29 -0
  11. package/dist/harness/tools/action-tools.d.ts.map +1 -1
  12. package/dist/harness/tools/action-tools.js +64 -4
  13. package/dist/harness/tools/action-tools.js.map +1 -1
  14. package/dist/harness/tools/site-actions.d.ts +27 -0
  15. package/dist/harness/tools/site-actions.d.ts.map +1 -1
  16. package/dist/harness/tools/site-actions.js +47 -0
  17. package/dist/harness/tools/site-actions.js.map +1 -1
  18. package/dist/harness/tools/source.d.ts.map +1 -1
  19. package/dist/harness/tools/source.js +5 -2
  20. package/dist/harness/tools/source.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/ui/action-card.d.ts +141 -0
  26. package/dist/ui/action-card.d.ts.map +1 -0
  27. package/dist/ui/action-card.js +384 -0
  28. package/dist/ui/action-card.js.map +1 -0
  29. package/dist/ui/agent-fullscreen.d.ts.map +1 -1
  30. package/dist/ui/agent-fullscreen.js +531 -16
  31. package/dist/ui/agent-fullscreen.js.map +1 -1
  32. package/dist/ui/tailwind.generated.d.ts +1 -1
  33. package/dist/ui/tailwind.generated.d.ts.map +1 -1
  34. package/dist/ui/tailwind.generated.js +1 -1
  35. package/dist/ui/tailwind.generated.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/handoff/tools.ts +11 -7
  38. package/src/harness/harness.ts +31 -15
  39. package/src/harness/renderer.ts +22 -0
  40. package/src/harness/tools/action-tools.ts +74 -4
  41. package/src/harness/tools/site-actions.ts +58 -0
  42. package/src/harness/tools/source.ts +5 -2
  43. package/src/index.ts +1 -1
  44. package/src/ui/action-card.ts +496 -0
  45. package/src/ui/agent-fullscreen.ts +563 -15
  46. package/src/ui/tailwind.generated.ts +1 -1
@@ -1,2 +1,2 @@
1
- export declare const TAILWIND_CSS = "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:\"Inter\", system-ui, sans-serif;--font-mono:\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-2xl:1rem;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#fff;--color-surface:#f5f7fb;--color-border-hair:#e4e9f2;--color-ink:#0f172a;--color-ink-2:#475569;--color-ink-3:#8a97ac;--color-blue:#2563eb;--color-blue-strong:#1d4ed8;--color-blue-tint:#eef3ff;--color-green-strong:#16a34a;--color-red:#b91c1c;--font-display:\"Manrope\", system-ui, sans-serif;--radius-card:14px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-1{margin-top:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.w-full{width:100%}.max-w-\\[76\\%\\]{max-width:76%}.max-w-\\[420px\\]{max-width:420px}.flex-shrink{flex-shrink:1}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-card{border-radius:var(--radius-card)}.rounded-br-md{border-bottom-right-radius:var(--radius-md)}.rounded-bl-md{border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-border-hair{border-color:var(--color-border-hair)}.border-red{border-color:var(--color-red)}.border-red\\/25{border-color:#b91c1c40}@supports (color:color-mix(in lab, red, red)){.border-red\\/25{border-color:color-mix(in oklab, var(--color-red) 25%, transparent)}}.bg-blue{background-color:var(--color-blue)}.bg-surface{background-color:var(--color-surface)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\\[0\\.14em\\]{--tw-tracking:.14em;letter-spacing:.14em}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-green-strong{color:var(--color-green-strong)}.text-ink{color:var(--color-ink)}.text-ink-2{color:var(--color-ink-2)}.text-red{color:var(--color-red)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-resting{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0f172a0d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow\\/border{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.\\!ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)!important}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}}@property --tw-rotate-x{syntax:\"*\";inherits:false}@property --tw-rotate-y{syntax:\"*\";inherits:false}@property --tw-rotate-z{syntax:\"*\";inherits:false}@property --tw-skew-x{syntax:\"*\";inherits:false}@property --tw-skew-y{syntax:\"*\";inherits:false}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-tracking{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\"*\";inherits:false}@property --tw-brightness{syntax:\"*\";inherits:false}@property --tw-contrast{syntax:\"*\";inherits:false}@property --tw-grayscale{syntax:\"*\";inherits:false}@property --tw-hue-rotate{syntax:\"*\";inherits:false}@property --tw-invert{syntax:\"*\";inherits:false}@property --tw-opacity{syntax:\"*\";inherits:false}@property --tw-saturate{syntax:\"*\";inherits:false}@property --tw-sepia{syntax:\"*\";inherits:false}@property --tw-drop-shadow{syntax:\"*\";inherits:false}@property --tw-drop-shadow-color{syntax:\"*\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\"*\";inherits:false}@property --tw-ease{syntax:\"*\";inherits:false}";
1
+ export declare const TAILWIND_CSS = "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:\"Inter\", system-ui, sans-serif;--font-mono:\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-2xl:1rem;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#fff;--color-surface:#f5f7fb;--color-border-hair:#e4e9f2;--color-ink:#0f172a;--color-ink-2:#475569;--color-ink-3:#8a97ac;--color-blue:#2563eb;--color-blue-strong:#1d4ed8;--color-blue-tint:#eef3ff;--color-green-strong:#16a34a;--color-red:#b91c1c;--font-display:\"Manrope\", system-ui, sans-serif;--radius-card:14px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-1{margin-top:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.w-full{width:100%}.max-w-\\[76\\%\\]{max-width:76%}.max-w-\\[420px\\]{max-width:420px}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-card{border-radius:var(--radius-card)}.rounded-br-md{border-bottom-right-radius:var(--radius-md)}.rounded-bl-md{border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-border-hair{border-color:var(--color-border-hair)}.border-red{border-color:var(--color-red)}.border-red\\/25{border-color:#b91c1c40}@supports (color:color-mix(in lab, red, red)){.border-red\\/25{border-color:color-mix(in oklab, var(--color-red) 25%, transparent)}}.bg-blue{background-color:var(--color-blue)}.bg-surface{background-color:var(--color-surface)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\\[0\\.14em\\]{--tw-tracking:.14em;letter-spacing:.14em}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-green-strong{color:var(--color-green-strong)}.text-ink{color:var(--color-ink)}.text-ink-2{color:var(--color-ink-2)}.text-red{color:var(--color-red)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-resting{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0f172a0d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow\\/border{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.\\!ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)!important}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}}@property --tw-rotate-x{syntax:\"*\";inherits:false}@property --tw-rotate-y{syntax:\"*\";inherits:false}@property --tw-rotate-z{syntax:\"*\";inherits:false}@property --tw-skew-x{syntax:\"*\";inherits:false}@property --tw-skew-y{syntax:\"*\";inherits:false}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-tracking{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\"*\";inherits:false}@property --tw-brightness{syntax:\"*\";inherits:false}@property --tw-contrast{syntax:\"*\";inherits:false}@property --tw-grayscale{syntax:\"*\";inherits:false}@property --tw-hue-rotate{syntax:\"*\";inherits:false}@property --tw-invert{syntax:\"*\";inherits:false}@property --tw-opacity{syntax:\"*\";inherits:false}@property --tw-saturate{syntax:\"*\";inherits:false}@property --tw-sepia{syntax:\"*\";inherits:false}@property --tw-drop-shadow{syntax:\"*\";inherits:false}@property --tw-drop-shadow-color{syntax:\"*\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\"*\";inherits:false}@property --tw-ease{syntax:\"*\";inherits:false}";
2
2
  //# sourceMappingURL=tailwind.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tailwind.generated.d.ts","sourceRoot":"","sources":["../../src/ui/tailwind.generated.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,YAAY,u8ZAAu8Z,CAAC"}
1
+ {"version":3,"file":"tailwind.generated.d.ts","sourceRoot":"","sources":["../../src/ui/tailwind.generated.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,YAAY,89ZAA89Z,CAAC"}
@@ -1,3 +1,3 @@
1
1
  /* GENERATED by scripts/css-to-ts.mjs — do not edit. Source: src/ui/agent.tw.css */
2
- export const TAILWIND_CSS = "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:\"Inter\", system-ui, sans-serif;--font-mono:\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-2xl:1rem;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#fff;--color-surface:#f5f7fb;--color-border-hair:#e4e9f2;--color-ink:#0f172a;--color-ink-2:#475569;--color-ink-3:#8a97ac;--color-blue:#2563eb;--color-blue-strong:#1d4ed8;--color-blue-tint:#eef3ff;--color-green-strong:#16a34a;--color-red:#b91c1c;--font-display:\"Manrope\", system-ui, sans-serif;--radius-card:14px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-1{margin-top:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.w-full{width:100%}.max-w-\\[76\\%\\]{max-width:76%}.max-w-\\[420px\\]{max-width:420px}.flex-shrink{flex-shrink:1}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-card{border-radius:var(--radius-card)}.rounded-br-md{border-bottom-right-radius:var(--radius-md)}.rounded-bl-md{border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-border-hair{border-color:var(--color-border-hair)}.border-red{border-color:var(--color-red)}.border-red\\/25{border-color:#b91c1c40}@supports (color:color-mix(in lab, red, red)){.border-red\\/25{border-color:color-mix(in oklab, var(--color-red) 25%, transparent)}}.bg-blue{background-color:var(--color-blue)}.bg-surface{background-color:var(--color-surface)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\\[0\\.14em\\]{--tw-tracking:.14em;letter-spacing:.14em}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-green-strong{color:var(--color-green-strong)}.text-ink{color:var(--color-ink)}.text-ink-2{color:var(--color-ink-2)}.text-red{color:var(--color-red)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-resting{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0f172a0d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow\\/border{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.\\!ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)!important}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}}@property --tw-rotate-x{syntax:\"*\";inherits:false}@property --tw-rotate-y{syntax:\"*\";inherits:false}@property --tw-rotate-z{syntax:\"*\";inherits:false}@property --tw-skew-x{syntax:\"*\";inherits:false}@property --tw-skew-y{syntax:\"*\";inherits:false}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-tracking{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\"*\";inherits:false}@property --tw-brightness{syntax:\"*\";inherits:false}@property --tw-contrast{syntax:\"*\";inherits:false}@property --tw-grayscale{syntax:\"*\";inherits:false}@property --tw-hue-rotate{syntax:\"*\";inherits:false}@property --tw-invert{syntax:\"*\";inherits:false}@property --tw-opacity{syntax:\"*\";inherits:false}@property --tw-saturate{syntax:\"*\";inherits:false}@property --tw-sepia{syntax:\"*\";inherits:false}@property --tw-drop-shadow{syntax:\"*\";inherits:false}@property --tw-drop-shadow-color{syntax:\"*\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\"*\";inherits:false}@property --tw-ease{syntax:\"*\";inherits:false}";
2
+ export const TAILWIND_CSS = "/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:\"Inter\", system-ui, sans-serif;--font-mono:\"JetBrains Mono\", ui-monospace, SFMono-Regular, Menlo, monospace;--color-white:#fff;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--leading-normal:1.5;--leading-relaxed:1.625;--radius-sm:.25rem;--radius-md:.375rem;--radius-2xl:1rem;--shadow-sm:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#fff;--color-surface:#f5f7fb;--color-border-hair:#e4e9f2;--color-ink:#0f172a;--color-ink-2:#475569;--color-ink-3:#8a97ac;--color-blue:#2563eb;--color-blue-strong:#1d4ed8;--color-blue-tint:#eef3ff;--color-green-strong:#16a34a;--color-red:#b91c1c;--font-display:\"Manrope\", system-ui, sans-serif;--radius-card:14px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", \"Noto Sans\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-1{margin-top:var(--spacing)}.block{display:block}.contents{display:contents}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.w-full{width:100%}.max-w-\\[76\\%\\]{max-width:76%}.max-w-\\[420px\\]{max-width:420px}.flex-shrink{flex-shrink:1}.flex-grow{flex-grow:1}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.self-end{align-self:flex-end}.self-start{align-self:flex-start}.self-stretch{align-self:stretch}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-card{border-radius:var(--radius-card)}.rounded-br-md{border-bottom-right-radius:var(--radius-md)}.rounded-bl-md{border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-border-hair{border-color:var(--color-border-hair)}.border-red{border-color:var(--color-red)}.border-red\\/25{border-color:#b91c1c40}@supports (color:color-mix(in lab, red, red)){.border-red\\/25{border-color:color-mix(in oklab, var(--color-red) 25%, transparent)}}.bg-blue{background-color:var(--color-blue)}.bg-surface{background-color:var(--color-surface)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\\.5{padding-inline:calc(var(--spacing) * 3.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-normal{--tw-leading:var(--leading-normal);line-height:var(--leading-normal)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-\\[0\\.14em\\]{--tw-tracking:.14em;letter-spacing:.14em}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-green-strong{color:var(--color-green-strong)}.text-ink{color:var(--color-ink)}.text-ink-2{color:var(--color-ink-2)}.text-red{color:var(--color-red)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-resting{--tw-shadow:0 1px 2px var(--tw-shadow-color,#0f172a0d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow\\/border{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.\\!ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)!important}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}}@property --tw-rotate-x{syntax:\"*\";inherits:false}@property --tw-rotate-y{syntax:\"*\";inherits:false}@property --tw-rotate-z{syntax:\"*\";inherits:false}@property --tw-skew-x{syntax:\"*\";inherits:false}@property --tw-skew-y{syntax:\"*\";inherits:false}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-tracking{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\"*\";inherits:false}@property --tw-brightness{syntax:\"*\";inherits:false}@property --tw-contrast{syntax:\"*\";inherits:false}@property --tw-grayscale{syntax:\"*\";inherits:false}@property --tw-hue-rotate{syntax:\"*\";inherits:false}@property --tw-invert{syntax:\"*\";inherits:false}@property --tw-opacity{syntax:\"*\";inherits:false}@property --tw-saturate{syntax:\"*\";inherits:false}@property --tw-sepia{syntax:\"*\";inherits:false}@property --tw-drop-shadow{syntax:\"*\";inherits:false}@property --tw-drop-shadow-color{syntax:\"*\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\"*\";inherits:false}@property --tw-ease{syntax:\"*\";inherits:false}";
3
3
  //# sourceMappingURL=tailwind.generated.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tailwind.generated.js","sourceRoot":"","sources":["../../src/ui/tailwind.generated.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,CAAC,MAAM,YAAY,GAAG,o8ZAAo8Z,CAAC"}
1
+ {"version":3,"file":"tailwind.generated.js","sourceRoot":"","sources":["../../src/ui/tailwind.generated.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,MAAM,CAAC,MAAM,YAAY,GAAG,29ZAA29Z,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxisai/agent-harness",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "An on-device agent for the browser: a tool-calling harness over WebMCP and remote MCP, plus a drop-in chat UI. Decides whether to run a tool, ask for what's missing, or confirm before writing.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -77,7 +77,10 @@ function buildTool(
77
77
  const description =
78
78
  kind === 'agent'
79
79
  ? `Hand this conversation to another agent that can finish what you can't. Use only when the visitor needs something one of these handles: ${menu}. The visitor sees the summary and confirms before anything is sent.`
80
- : `Hand this conversation to a person on the site's team. Use when the visitor asks for a person, or when you can't help. Targets: ${menu}. The visitor sees the summary and confirms before anything is sent. When the team is away, ask for an email so they can reply.`;
80
+ : `Hand this conversation to a person on the site's team. Use when the visitor asks for a person, or when you can't help. Targets: ${menu}. The visitor sees the summary and confirms before anything is sent. When the team is away, include the visitor's email if they gave one; the page asks for it otherwise.`;
81
+ // Everyone away: a reply can only go to an email, so the email is required and the page asks for it
82
+ // in the same form as any other missing detail, before the visitor presses Send rather than after.
83
+ const away = kind === 'person' && targets.every((t) => !t.available);
81
84
 
82
85
  const properties: Record<string, JsonSchema> = {
83
86
  target: {
@@ -97,14 +100,16 @@ function buildTool(
97
100
  properties.email = {
98
101
  type: 'string',
99
102
  format: 'email',
100
- description: 'Only when the team is away: an email address the visitor gave for a reply.',
103
+ description: away
104
+ ? 'The team is away: the email address they should reply to.'
105
+ : 'Only when the team is away: an email address the visitor gave for a reply.',
101
106
  };
102
107
  }
103
108
 
104
109
  return {
105
110
  name,
106
111
  description,
107
- inputSchema: { type: 'object', properties, required: ['target', 'reason', 'summary'] },
112
+ inputSchema: { type: 'object', properties, required: ['target', 'reason', 'summary', ...(away ? ['email'] : [])] },
108
113
  // A write: what the visitor said leaves the site. The harness confirms before it runs.
109
114
  annotations: { readOnlyHint: false, consequentialHint: true },
110
115
  execute: async (input: Record<string, unknown>) => {
@@ -115,11 +120,10 @@ function buildTool(
115
120
  return text(`"${String(input?.target ?? '')}" is not someone this conversation can be handed to.`, true);
116
121
  }
117
122
  const email = typeof input.email === 'string' ? input.email.trim() : '';
123
+ // Went away since the tools were built, or one of several desks is away: said to the visitor,
124
+ // who reads a failed call's result, and read by the model on the next turn.
118
125
  if (!current.available && !email) {
119
- return text(
120
- `${current.label} is ${availability(current)}. Ask the visitor for an email address to reply to, then call ${name} again with it.`,
121
- true,
122
- );
126
+ return text(`${current.label} is ${availability(current)}. Leave an email address and they'll reply there.`, true);
123
127
  }
124
128
  const envelope = buildEnvelope({
125
129
  target: current.name,
@@ -766,12 +766,14 @@ export class AgentHarness {
766
766
  detail: resolution.missing.map((s) => humanize(s.name).toLowerCase()).join(', '),
767
767
  });
768
768
  const plan = buildPlan(resolution.missing, this.opts.groupRelated !== false);
769
- this.renderer.message(
770
- 'assistant',
771
- plan.stepped
772
- ? `I need ${plan.steps.length} more details for ${humanize(tool.name)}.`
773
- : `One more thing for ${humanize(tool.name)}.`,
774
- );
769
+ if (!this.renderer.inlinePrompts) {
770
+ this.renderer.message(
771
+ 'assistant',
772
+ plan.stepped
773
+ ? `I need ${plan.steps.length} more details for ${humanize(tool.name)}.`
774
+ : `One more thing for ${humanize(tool.name)}.`,
775
+ );
776
+ }
775
777
  this.renderer.ask({
776
778
  tool,
777
779
  plan,
@@ -874,17 +876,23 @@ export class AgentHarness {
874
876
  // courier persists the journey as it leaves, and this step has to be in
875
877
  // it or the page it lands on shows no reason for being there.
876
878
  const handing = isHandoffTool(tool.name);
877
- this.emitStep(
878
- handing
879
- ? { id: 'fill', label: 'Handing the conversation over', status: 'active' }
880
- : leaving
879
+ const inFlight: AgentStep = handing
880
+ ? { id: 'fill', label: 'Handing the conversation over', status: 'active' }
881
+ : leaving
881
882
  ? { id: 'navigate', label: `Opening ${leaving.label}`, status: 'active' }
882
883
  : {
883
884
  id: 'fill',
884
885
  label: readOnly ? 'Looking that up' : `Filling ${humanize(tool.name)}`,
885
886
  status: 'active',
886
- },
887
- );
887
+ };
888
+ this.emitStep(inFlight);
889
+ // A failure ends the step that was running, so the card never shows it still under way.
890
+ const failed = (detail: string) => {
891
+ this.emitStep({ ...inFlight, label: 'It did not go through', status: 'failed', detail });
892
+ // The model reads why on its next turn, and can act on it rather than repeat the call.
893
+ messages.push({ role: 'user', content: `[${tool.name} did not go through: ${detail.slice(0, 400)}]` });
894
+ this.opts.onMessages?.(messages);
895
+ };
888
896
  try {
889
897
  const res: ModelContextToolResponse = await this.toolSource.execTool(tool, tool.name, values);
890
898
  const text = extractResult(res);
@@ -900,7 +908,7 @@ export class AgentHarness {
900
908
  });
901
909
 
902
910
  if (res?.isError) {
903
- this.emitStep({ id: 'submit', label: 'It did not go through', status: 'failed', detail: text });
911
+ failed(text || 'Failed');
904
912
  this.renderer.toolError(tool, text || 'Failed');
905
913
  return;
906
914
  }
@@ -915,6 +923,11 @@ export class AgentHarness {
915
923
  // Said from what we know, not from what came back: a registry may
916
924
  // return the whole response object as JSON, and that is not a
917
925
  // sentence to put in front of anyone.
926
+ if (this.renderer.left) {
927
+ const carried = res?.structuredContent?.[HANDOFF_RESULT] as { label?: string } | undefined;
928
+ this.renderer.left(tool, (visiting ?? leaving)?.label ?? carried?.label ?? null);
929
+ return;
930
+ }
918
931
  this.renderer.message(
919
932
  'assistant',
920
933
  visiting
@@ -931,7 +944,10 @@ export class AgentHarness {
931
944
  const started = res?.structuredContent?.[HANDOFF_SESSION_RESULT] as { label?: string } | undefined;
932
945
  if (handing && started) {
933
946
  const who = started.label ?? 'another agent';
934
- this.emitStep({ id: 'fill', label: `Handed to ${who}`, status: 'done' });
947
+ // Handing over is where this journey ends; the conversation carries on outside it. Without a
948
+ // `submit` step the card would read as running for as long as the handoff lasts.
949
+ this.emitStep({ id: 'fill', label: 'Handed the conversation over', status: 'done' });
950
+ this.emitStep({ id: 'submit', label: `Handed to ${who}`, status: 'done' });
935
951
  messages.push({
936
952
  role: 'user',
937
953
  content: `[${tool.name}: the conversation was handed to ${who}. Their replies go to the visitor directly.]`,
@@ -970,7 +986,7 @@ export class AgentHarness {
970
986
  this.opts.onMessages?.(messages);
971
987
  } catch (err) {
972
988
  const message = String((err as Error)?.message || err);
973
- this.emitStep({ id: 'submit', label: 'It did not go through', status: 'failed', detail: message });
989
+ failed(message);
974
990
  working.finalize('');
975
991
  this.renderer.status('');
976
992
  // A call that threw is the main reason to open a trace.
@@ -195,6 +195,28 @@ export interface HarnessRenderer {
195
195
  /** Tear down any live ask or confirm UI. */
196
196
  dismissPrompt?(): void;
197
197
 
198
+ /**
199
+ * Whether this renderer's ask and confirm prompts say for themselves what
200
+ * they need and where they go.
201
+ *
202
+ * When true, the harness adds no "One more thing for …" line of its own
203
+ * before an ask: the prompt already reads as the assistant speaking.
204
+ */
205
+ inlinePrompts?: boolean;
206
+
207
+ /**
208
+ * A confirmed call is leaving for the page that can submit it.
209
+ *
210
+ * Called instead of the harness's own "Opening … to submit this…" message,
211
+ * for a renderer that shows the departure on the prompt the visitor just
212
+ * confirmed. The page it opens finishes the call.
213
+ *
214
+ * @param tool - The tool whose call is travelling.
215
+ * @param destination - The page it is going to, named for the visitor, or
216
+ * null when the harness cannot tell which.
217
+ */
218
+ left?(tool: ModelContextToolInfo, destination: string | null): void;
219
+
198
220
  /**
199
221
  * Report whether the turn can still be stopped.
200
222
  *
@@ -285,6 +285,11 @@ export interface BuildOptions {
285
285
  navigate?: (url: string) => void;
286
286
  /** The conversation a travelling call should report back to. */
287
287
  conversationId?: string;
288
+ /**
289
+ * Look up a form none of a tool's own actions matched: the site's index may
290
+ * hold it only inside the record it belongs to. See `findEmbeddedAction`.
291
+ */
292
+ findAction?: (query: { actionName: string; field: string; value: string }) => Promise<NxisAction | null>;
288
293
  }
289
294
 
290
295
  /**
@@ -356,6 +361,15 @@ export function isSiteTool(tool: ModelContextToolInfo): boolean {
356
361
  return coverageOf(tool) !== null;
357
362
  }
358
363
 
364
+ /**
365
+ * The field that says which of a site tool's forms a call means: `business`,
366
+ * or the added `target`. Null for a tool that covers one form, or is not a
367
+ * site tool.
368
+ */
369
+ export function chooserOf(tool: ModelContextToolInfo): string | null {
370
+ return coverageOf(tool)?.chooser || null;
371
+ }
372
+
359
373
  /** A tool's coverage, from what this page built or from what it carries. */
360
374
  function coverageOf(tool: ModelContextToolInfo): Coverage | null {
361
375
  const local = built.get(tool.name);
@@ -484,6 +498,31 @@ function pickAction(
484
498
  return loose >= 0 ? tool.actions[loose] : null;
485
499
  }
486
500
 
501
+ /**
502
+ * The options each field offers on the one form a call means.
503
+ *
504
+ * A site tool's schema accepts any option the same field offers on any of its
505
+ * pages, which for a per-business quote form is every service of every
506
+ * business. Once the call says which business, only that form's options mean
507
+ * anything, and a prompt should offer only those.
508
+ *
509
+ * @returns Option values by field name; empty when the tool is not a site
510
+ * tool built on this page, or the call does not yet say which form.
511
+ */
512
+ export function formOptions(tool: ModelContextToolInfo, values: Record<string, unknown>): Record<string, string[]> {
513
+ const local = built.get(tool.name);
514
+ const action = local ? pickAction(local, values ?? {}) : null;
515
+ const out: Record<string, string[]> = {};
516
+ for (const spec of action?.input ?? []) {
517
+ const options = (spec['nxis:valueOption'] ?? []).map((o) => o.value).filter((v) => !isPlaceholder(v));
518
+ if (options.length) out[spec.valueName] = options;
519
+ }
520
+ return out;
521
+ }
522
+
523
+ /** An option that only asks to choose: "Select…", "Choose a service…". */
524
+ export const isPlaceholder = (value: string): boolean => /^\s*(select|choose|pick)\b/i.test(value) || /…\s*$|\.\.\.\s*$/.test(value);
525
+
487
526
  /** Which page tool to look for: the action's id, and the name it would have. */
488
527
  export interface PageToolRef {
489
528
  /** The action's `@id`. */
@@ -622,10 +661,12 @@ async function runSiteAction(
622
661
  input: Record<string, unknown>,
623
662
  opts: BuildOptions,
624
663
  ): Promise<ModelContextToolResponse> {
625
- const action = pickAction(tool, input ?? {});
664
+ const wanted = tool.discriminator ? String(input?.[tool.discriminator] ?? '').trim() : '';
665
+ const action = pickAction(tool, input ?? {}) ?? (await lookUp(tool, wanted, opts));
626
666
  if (!action) {
627
- const choices = (tool.choices ?? []).join(', ');
628
- return text(`Say which one this is for. Choices: ${choices}.`, true);
667
+ // Said to the visitor as well as the model: the renderer shows a failed call's result.
668
+ if (!wanted) return text(`Say which one this is for: ${summarize(tool.choices ?? [])}.`, true);
669
+ return text(`I couldn't find a ${humanize(tool.actions[0].name)} for "${wanted}" on this site. It covers ${summarize(tool.choices ?? [])}.`, true);
629
670
  }
630
671
 
631
672
  const pageUrl = action.target['nxis:pageUrl'] ?? '';
@@ -633,7 +674,7 @@ async function runSiteAction(
633
674
  // Filling the form means being on its page, so the confirmed call travels:
634
675
  // held in this tab, submitted once the browser arrives.
635
676
  const index = tool.actions.indexOf(action);
636
- const label = tool.choices?.[index] || pageLabel(pageUrl);
677
+ const label = tool.choices?.[index] || wanted || pageLabel(pageUrl);
637
678
  const here = opts.href ?? (typeof location === 'undefined' ? '' : location.href);
638
679
  if (!sameOrigin(pageUrl, here)) {
639
680
  return text(`"${action.name}" belongs to another site, so I did not open it.`, true);
@@ -684,6 +725,35 @@ async function runSiteAction(
684
725
  return executeRegistered(mc, pageTool, pageTool.name, args);
685
726
  }
686
727
 
728
+ /**
729
+ * The action a call names that is not among the tool's own: found in the
730
+ * site's index, inside the record it belongs to. Null when there is nothing
731
+ * to look up, nobody to ask, or nothing found.
732
+ */
733
+ async function lookUp(
734
+ tool: Pick<SiteActionTool, 'actions' | 'discriminator'>,
735
+ wanted: string,
736
+ opts: BuildOptions,
737
+ ): Promise<NxisAction | null> {
738
+ if (!wanted || !tool.discriminator || !opts.findAction) return null;
739
+ try {
740
+ return await opts.findAction({ actionName: tool.actions[0].name, field: tool.discriminator, value: wanted });
741
+ } catch (err) {
742
+ console.warn(`[nxis-mcp] could not look up "${wanted}":`, err);
743
+ return null;
744
+ }
745
+ }
746
+
747
+ /** A list of choices short enough to read: the first few, and how many more. */
748
+ function summarize(choices: string[]): string {
749
+ if (!choices.length) return 'nothing yet';
750
+ const shown = choices.slice(0, 5).join(', ');
751
+ return choices.length > 5 ? `${shown}, and ${choices.length - 5} more` : shown;
752
+ }
753
+
754
+ /** `quote-form` → `quote form`. */
755
+ const humanize = (name: string): string => name.replace(/[-_]+/g, ' ').trim();
756
+
687
757
  /**
688
758
  * The arguments the form itself takes.
689
759
  *
@@ -256,6 +256,64 @@ export async function queryTypedRecords(client: Client, fragment: string): Promi
256
256
  return records;
257
257
  }
258
258
 
259
+ /** What a form tool is looking for when none of its own actions matched. */
260
+ export interface EmbeddedActionQuery {
261
+ /** The action's name, as the tool's group shares it: `quote-form`. */
262
+ actionName: string;
263
+ /** The field that chooses between the group's actions: `business`, or the added `target`. */
264
+ field: string;
265
+ /** The value the call gave it: `Hatzel & Sons Plumbing`. */
266
+ value: string;
267
+ /** The origin the action's page must be on. Defaults to the page's own. */
268
+ origin?: string;
269
+ }
270
+
271
+ /**
272
+ * Find a form the index holds only inside another record.
273
+ *
274
+ * The site's actions are fetched once, as standalone Action records. An index
275
+ * can lag behind its pages — a partial re-crawl leaves some forms only as the
276
+ * `potentialAction` of the business or page they belong to — and a call naming
277
+ * one of those would otherwise fail with "say which one". So a miss looks the
278
+ * value up by name, and takes an action embedded in what it finds when that
279
+ * action is the same form: the same name, on this origin, and meant for this
280
+ * value.
281
+ *
282
+ * @param client - A connected client for the site's MCP server.
283
+ * @param query - The form, the choosing field, and the value asked for.
284
+ * @returns The action, or null when nothing on the site matches.
285
+ */
286
+ export async function findEmbeddedAction(client: Client, query: EmbeddedActionQuery): Promise<NxisAction | null> {
287
+ const origin = query.origin ?? location.origin;
288
+ const wanted = query.value.trim().toLowerCase();
289
+ if (!wanted) return null;
290
+ const result = await withRetry(() =>
291
+ client.callTool({
292
+ name: 'nxis_query',
293
+ arguments: {
294
+ filter: { schema_type: '', field_filters: [{ path: 'name', operator: 'CONTAINS', value: query.value.trim() }] },
295
+ limit: 20,
296
+ },
297
+ }),
298
+ );
299
+ const matches: NxisAction[] = [];
300
+ for (const record of readResults(result).results) {
301
+ if (!isObj(record)) continue;
302
+ const owner = (str(schemaValue(record, 'name')) ?? '').trim().toLowerCase();
303
+ const embedded = schemaValue(record, 'potentialAction');
304
+ for (const raw of Array.isArray(embedded) ? embedded : [embedded]) {
305
+ const action = parseAction(raw);
306
+ if (!action || action.name !== query.actionName || !onOrigin(action, origin)) continue;
307
+ // Meant for this value: the form says so itself, or it belongs to the record the value names.
308
+ const own = action.input?.find((i) => i.valueName === query.field)?.defaultValue?.trim().toLowerCase();
309
+ if (own ? own === wanted : owner === wanted) matches.push(action);
310
+ }
311
+ }
312
+ // Two different forms answering to one name is a question for the visitor, not a guess.
313
+ const pages = new Set(matches.map((a) => a.target['nxis:pageUrl']));
314
+ return pages.size === 1 ? matches[0] : null;
315
+ }
316
+
259
317
  /** The tab's session storage, or null where it is unavailable or blocked. */
260
318
  function defaultStorage(): Storage | null {
261
319
  try {
@@ -17,7 +17,7 @@ import { registerRemoteTools, type BridgeOptions } from './bridge.js';
17
17
  import { ensureModelContext } from './local-context.js';
18
18
  import { connectMcp } from './client.js';
19
19
  import { discoverMcpServer } from './discovery.js';
20
- import { loadSiteActions, type SiteActionsOptions } from './site-actions.js';
20
+ import { findEmbeddedAction, loadSiteActions, type SiteActionsOptions } from './site-actions.js';
21
21
  import { registerSiteActionTools } from './action-tools.js';
22
22
  import { loadSitePages, mergePages, pagesFromActions, type SitePage } from './site-pages.js';
23
23
  import { registerOpenPageTool, OPEN_PAGE_TOOL, type OpenPageOptions } from './open-page.js';
@@ -218,7 +218,10 @@ async function connectRegistry(
218
218
  let warning: string | undefined;
219
219
  try {
220
220
  siteActions = await loadSiteActions(client, info, siteOpts);
221
- siteTools = await registerSiteActionTools(mc, siteActions);
221
+ siteTools = await registerSiteActionTools(mc, siteActions, {
222
+ // A form the index holds only inside its business or page, looked up when a call names it.
223
+ findAction: (query) => findEmbeddedAction(client, { ...query, origin: siteOpts.origin }),
224
+ });
222
225
  } catch (err) {
223
226
  warning = `site actions unavailable — this page's own actions still work: ${errorText(err)}`;
224
227
  console.warn(`[nxis-mcp] ${warning}`);
package/src/index.ts CHANGED
@@ -171,7 +171,7 @@ export {
171
171
  setConversationSource,
172
172
  } from './harness/tools/pending-action.js';
173
173
  export type { PendingAction, PendingVisit } from './harness/tools/pending-action.js';
174
- export { loadSiteActions, parseAction } from './harness/tools/site-actions.js';
174
+ export { findEmbeddedAction, loadSiteActions, parseAction, type EmbeddedActionQuery } from './harness/tools/site-actions.js';
175
175
  export type { ConnectResult, ConnectOptions, SiteActionsOptions } from './harness/tools/source.js';
176
176
  export type { BridgeOptions } from './harness/tools/bridge.js';
177
177