@ai-matrx/chat 0.5.18 → 0.6.1

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 (99) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/agents/components/identity-refs/AiIdentityRef.d.ts +33 -0
  3. package/dist/agents/components/identity-refs/AiIdentityRef.js +138 -0
  4. package/dist/agents/components/inputs/resources/RenderedArtifactChip.d.ts +8 -0
  5. package/dist/agents/components/inputs/resources/RenderedArtifactChip.js +109 -0
  6. package/dist/agents/components/inputs/resources/SmartAgentResourceChips.js +20 -0
  7. package/dist/agents/components/inputs/resources/useAttachRenderedArtifact.js +31 -6
  8. package/dist/agents/components/inputs/smart-input/QuicksetPanel.js +5 -9
  9. package/dist/agents/components/inputs/smart-input/RunSkillPicker.js +1 -1
  10. package/dist/agents/components/inputs/smart-input/RunToolPicker.js +6 -11
  11. package/dist/agents/components/inputs/smart-input/ShapeChipsRow.js +1 -1
  12. package/dist/agents/components/inputs/smart-input/composer/ComposerEffortPill.js +1 -1
  13. package/dist/agents/components/inputs/smart-input/composer/ComposerOutput.js +1 -1
  14. package/dist/agents/components/inputs/smart-input/composer/ComposerPlusMenu.js +1 -1
  15. package/dist/agents/components/inputs/smart-input/composer/useComposerAgent.js +1 -1
  16. package/dist/agents/components/inputs/smart-input/composer/useRunControlCounts.d.ts +3 -0
  17. package/dist/agents/components/inputs/smart-input/composer/useRunControlCounts.js +54 -0
  18. package/dist/agents/components/model-tiers/ModelTierIdentityList.js +1 -1
  19. package/dist/agents/components/run-controls/RunConfigOverrides.js +1 -1
  20. package/dist/agents/components/run-controls/RunInputCapabilities.js +1 -1
  21. package/dist/agents/components/run-controls/panels/shared.d.ts +0 -2
  22. package/dist/agents/hooks/useDiffEnrichment.js +3 -6
  23. package/dist/agents/identity/agent-catalog-lists.js +2 -1
  24. package/dist/agents/identity/agent-identity.js +2 -1
  25. package/dist/agents/identity/model-catalog.d.ts +9 -0
  26. package/dist/agents/identity/model-catalog.js +25 -0
  27. package/dist/agents/identity/preferred-chat-model.d.ts +9 -0
  28. package/dist/agents/identity/preferred-chat-model.js +33 -0
  29. package/dist/agents/identity/settings-store.d.ts +10 -0
  30. package/dist/agents/identity/settings-store.js +49 -0
  31. package/dist/agents/identity/skill-catalog.d.ts +27 -0
  32. package/dist/agents/identity/skill-catalog.js +100 -0
  33. package/dist/agents/identity/tool-catalog.d.ts +15 -0
  34. package/dist/agents/identity/tool-catalog.js +67 -0
  35. package/dist/agents/redux/agent-definition/cache-bust-middleware.d.ts +0 -1
  36. package/dist/agents/redux/agent-definition/cache-bust-middleware.js +1 -13
  37. package/dist/agents/redux/agent-definition/selectors.d.ts +12 -546
  38. package/dist/agents/redux/agent-settings/internal-utils.d.ts +2 -123
  39. package/dist/agents/redux/agent-settings/internal-utils.js +1 -315
  40. package/dist/agents/redux/agent-settings/settings-catalogue.d.ts +2 -78
  41. package/dist/agents/redux/agent-settings/settings-catalogue.js +1 -176
  42. package/dist/agents/redux/agent-settings/types.d.ts +2 -148
  43. package/dist/agents/redux/agent-settings/types.js +1 -0
  44. package/dist/agents/redux/agent-settings/ui-gates.d.ts +2 -54
  45. package/dist/agents/redux/agent-settings/ui-gates.js +1 -38
  46. package/dist/agents/redux/agent-shortcut-categories/selectors.d.ts +0 -100
  47. package/dist/agents/redux/agent-shortcuts/selectors.d.ts +0 -294
  48. package/dist/agents/redux/conversation-history/selectors.d.ts +0 -32
  49. package/dist/agents/redux/conversation-list/conversation-list.selectors.d.ts +0 -4
  50. package/dist/agents/redux/execution-system/active-requests/active-requests.selectors.d.ts +0 -108
  51. package/dist/agents/redux/execution-system/context-state/context-state.selectors.d.ts +0 -28
  52. package/dist/agents/redux/execution-system/conversations/conversations.selectors.d.ts +0 -10
  53. package/dist/agents/redux/execution-system/instance-context/instance-context.selectors.d.ts +0 -6
  54. package/dist/agents/redux/execution-system/instance-model-overrides/launch-model-overrides.js +1 -1
  55. package/dist/agents/redux/execution-system/instance-resources/instance-resources.selectors.d.ts +0 -16
  56. package/dist/agents/redux/execution-system/instance-ui-state/instance-ui-state.selectors.d.ts +0 -10
  57. package/dist/agents/redux/execution-system/instance-variable-values/instance-variable-values.selectors.d.ts +0 -14
  58. package/dist/agents/redux/execution-system/messages/messages.selectors.d.ts +0 -2
  59. package/dist/agents/redux/execution-system/observability/observability.selectors.d.ts +0 -14
  60. package/dist/agents/redux/execution-system/observational-memory/observational-memory.selectors.d.ts +0 -2
  61. package/dist/agents/redux/execution-system/selectors/aggregate.selectors.d.ts +0 -28
  62. package/dist/agents/redux/execution-system/thunks/process-stream.js +2 -5
  63. package/dist/agents/redux/execution-system/utils/loaded-skill-sources.d.ts +1 -1
  64. package/dist/agents/redux/execution-system/utils/loaded-skill-sources.js +3 -3
  65. package/dist/agents/redux/proposed-directives/proposedDirectivesSlice.d.ts +0 -2
  66. package/dist/agents/ui-first-tools/redux/agent-lists.selectors.d.ts +0 -4
  67. package/dist/agents/utils/renderedArtifactContext.d.ts +55 -17
  68. package/dist/agents/utils/renderedArtifactContext.js +83 -2
  69. package/dist/conversation/utils/frame-print.d.ts +10 -5
  70. package/dist/conversation/utils/frame-print.js +65 -27
  71. package/dist/host/frame-print.d.ts +10 -0
  72. package/dist/host/frame-print.js +9 -0
  73. package/dist/host/ui-slots.d.ts +0 -46
  74. package/dist/host/ui-slots.js +0 -33
  75. package/dist/store/create-chat-store.d.ts +0 -4
  76. package/dist/store/middlewares.d.ts +0 -10
  77. package/dist/store/slices.d.ts +0 -2
  78. package/dist/store/slices.js +0 -4
  79. package/dist/surfaces/redux/selectors.d.ts +0 -4
  80. package/dist/tool-call-visualization/redux/selectors.d.ts +0 -2
  81. package/dist/ui/chat-default-model-knob.d.ts +1 -1
  82. package/dist/ui/chat-default-model-knob.js +1 -1
  83. package/package.json +5 -5
  84. package/dist/agents/components/model/AgentModelPanel.d.ts +0 -4
  85. package/dist/agents/components/model/AgentModelPanel.js +0 -9
  86. package/dist/agents/redux/agent-settings/agentSettingsSlice.d.ts +0 -1015
  87. package/dist/agents/redux/agent-settings/agentSettingsSlice.js +0 -659
  88. package/dist/agents/redux/agent-settings/selectors.d.ts +0 -10057
  89. package/dist/agents/redux/agent-settings/selectors.js +0 -234
  90. package/dist/agents/redux/agent-settings/useNormalizedControls.d.ts +0 -8
  91. package/dist/agents/redux/agent-settings/useNormalizedControls.js +0 -24
  92. package/dist/agents/redux/tools/tools.selectors.d.ts +0 -529
  93. package/dist/agents/redux/tools/tools.selectors.js +0 -24
  94. package/dist/agents/redux/tools/tools.slice.d.ts +0 -12
  95. package/dist/agents/redux/tools/tools.slice.js +0 -37
  96. package/dist/agents/redux/tools/tools.thunks.d.ts +0 -125
  97. package/dist/agents/redux/tools/tools.thunks.js +0 -45
  98. package/dist/host/defaults/setting-control-input.d.ts +0 -11
  99. package/dist/host/defaults/setting-control-input.js +0 -91
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @ai-matrx/chat
2
2
 
3
+ ## 0.6.1
4
+ ### rendered-output P2 WP4: every artifact type attaches
5
+
6
+ - `RenderedArtifactSource` carries `artifact_type`, the type's own `options` (first = default,
7
+ per-type labels: "Code", "Source", "Data", …; `unavailable` names why one is not offered yet)
8
+ and, for an UNSAVED block, `record_type: "inline"` + `body: { code, text }` — its content/text
9
+ ride `request.context` as a named entry (never `user_input`). Saved items keep the
10
+ `canvas_item` / `html_page` resource reference.
11
+ - `readableText(value)` — the readable text form of structured data (server twin
12
+ `canvas_sources.readable_text`).
13
+ - Composer: a `rendered_artifact` chip is `RenderedArtifactChip` — a representation part
14
+ switches content ↔ text, or captures a Screenshot now through the capture kept from attach time.
15
+ - `attachRenderedArtifact` uploads a local (`kind: "file"`) capture through the file funnel when
16
+ no React upload hook is passed (canvas menus, message block actions).
17
+
18
+ Consumer action: optional — pass `artifact_type` + `options` (and `body` for unsaved blocks).
19
+
20
+ ### rendered-output P2 WP3: Full Print draws canvases and marked surfaces
21
+
22
+ - Full Print's pre-pass (`conversation/utils/frame-print`) now also swaps every `<canvas>` for the
23
+ picture it holds (an honest stand-in when another origin drew into it) and every
24
+ `[data-matrx-print-picture]` element for the host's picture of it — new port
25
+ `setElementPrintCapture` in `@ai-matrx/chat/host/frame-print` (a Leaflet map's tiles).
26
+
27
+ Consumer action: optional — plug `setElementPrintCapture` to draw marked surfaces.
28
+
29
+ ## 0.6.0
30
+
31
+ Automatic changed-only republish (docs/metadata drift since the last tag — see
32
+ `git diff npm/chat/v0.5.18..npm/chat/v0.6.0 -- apps/shared/chat`).
33
+ No source changes intended and no consumer action required.
34
+
3
35
  ## 0.5.18
4
36
 
5
37
  Automatic changed-only republish (docs/metadata drift since the last tag — see
@@ -0,0 +1,33 @@
1
+ /** The admin model console deep link. */
2
+ export declare function aiModelHref(modelId: string): string;
3
+ /** The admin tool console deep link. */
4
+ export declare function toolHref(toolId: string): string;
5
+ interface AiIdentityRefCommonProps {
6
+ /** Explicit joined label wins and avoids even a cached lookup. */
7
+ name?: string | null;
8
+ /** Audit/history mode: render the complete raw FK directly below the name. */
9
+ showId?: boolean;
10
+ showIcon?: boolean;
11
+ alwaysShowActions?: boolean;
12
+ openInNewTab?: boolean;
13
+ /** For identity text nested inside another interactive control. */
14
+ disableNavigation?: boolean;
15
+ className?: string;
16
+ labelClassName?: string;
17
+ }
18
+ export interface AiModelRefProps extends AiIdentityRefCommonProps {
19
+ modelId: string;
20
+ /**
21
+ * Naming the model an agent or run USES: a model with several classes is
22
+ * shown with its class ("Qwen3.8 27B · Matrx Lightning"). `offeringId` is the
23
+ * pin; none = the preferred class the server runs.
24
+ */
25
+ showClass?: boolean;
26
+ offeringId?: string | null;
27
+ }
28
+ export declare function AiModelRef({ modelId, showClass, offeringId, name, showId, showIcon, alwaysShowActions, openInNewTab, disableNavigation, className, labelClassName, }: AiModelRefProps): import("react").JSX.Element;
29
+ export interface AiToolRefProps extends AiIdentityRefCommonProps {
30
+ toolId: string;
31
+ }
32
+ export declare function AiToolRef({ toolId, name, showId, showIcon, alwaysShowActions, openInNewTab, disableNavigation, className, labelClassName, }: AiToolRefProps): import("react").JSX.Element;
33
+ export {};
@@ -0,0 +1,138 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect } from "react";
4
+ import { withModelClass, selectModelById, selectModelClassName, selectModelIdentityById, selectModelIdentityLookupStatus } from "@ai-matrx/agents/models";
5
+ import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
6
+ import { getModelRecords, useModelRecords } from "../../identity/model-catalog.js";
7
+ import { loadToolById, selectToolById, selectToolLookupStatus, useToolCatalog } from "../../identity/tool-catalog.js";
8
+ import { EntityRef } from "../../../host/ui-slots.js";
9
+ import { selectIsSuperAdmin } from "../../../host/identity.js";
10
+ import { useAppSelector } from "../../../store/hooks.js";
11
+ const cn = (...parts) => parts.filter(Boolean).join(" ");
12
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
13
+ const isUuidValue = (value) => typeof value === "string" && UUID.test(value.trim());
14
+ function aiModelHref(modelId) {
15
+ return `/administration/ai/ai-models?model=${encodeURIComponent(modelId)}`;
16
+ }
17
+ function toolHref(toolId) {
18
+ return `/administration/agents/mcp-tools/${encodeURIComponent(toolId)}`;
19
+ }
20
+ function IdentityLabel({ id, name, showId }) {
21
+ return /* @__PURE__ */ jsxs(
22
+ "span",
23
+ {
24
+ className: cn(
25
+ "inline-flex min-w-0",
26
+ showId ? "flex-col" : "items-baseline gap-1"
27
+ ),
28
+ children: [
29
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate font-medium", children: name }),
30
+ showId ? /* @__PURE__ */ jsx("span", { className: "select-all break-all font-mono type-meta font-normal text-muted-foreground", children: id }) : null
31
+ ]
32
+ }
33
+ );
34
+ }
35
+ function fallbackName(kind, id) {
36
+ return isUuidValue(id) ? `Unknown ${kind}` : humanizeIdentifier(id);
37
+ }
38
+ function AiModelRef({
39
+ modelId,
40
+ showClass = false,
41
+ offeringId,
42
+ name,
43
+ showId = false,
44
+ showIcon = true,
45
+ alwaysShowActions,
46
+ openInNewTab = true,
47
+ disableNavigation = false,
48
+ className,
49
+ labelClassName
50
+ }) {
51
+ const model = useModelRecords((state) => selectModelById(state, modelId));
52
+ const historicalIdentity = useModelRecords(
53
+ (state) => selectModelIdentityById(state, modelId)
54
+ );
55
+ const lookupStatus = useModelRecords(
56
+ (state) => selectModelIdentityLookupStatus(state, modelId)
57
+ );
58
+ const isSuperAdmin = useAppSelector(selectIsSuperAdmin);
59
+ const classStatus = useModelRecords((s) => s.modelClassStatus);
60
+ const modelClass = useModelRecords(
61
+ (s) => showClass ? selectModelClassName(s, modelId, offeringId) : void 0
62
+ );
63
+ useEffect(() => {
64
+ if (showClass && !classStatus) getModelRecords().loadClasses();
65
+ }, [showClass, classStatus]);
66
+ useEffect(() => {
67
+ if (!name && !model && !historicalIdentity && isUuidValue(modelId) && lookupStatus === "idle") {
68
+ getModelRecords().loadIdentity(modelId);
69
+ }
70
+ }, [historicalIdentity, lookupStatus, model, modelId, name]);
71
+ const baseName = name?.trim() || model?.common_name || model?.name || historicalIdentity?.common_name || historicalIdentity?.name || fallbackName("AI model", modelId);
72
+ const resolvedName = withModelClass(baseName, modelClass);
73
+ const mustShowId = showId || !name && !model && !historicalIdentity && isUuidValue(modelId);
74
+ return /* @__PURE__ */ jsx(
75
+ EntityRef,
76
+ {
77
+ token: "ai_model",
78
+ id: modelId,
79
+ name: resolvedName,
80
+ href: isSuperAdmin && !disableNavigation ? aiModelHref(modelId) : void 0,
81
+ showIcon,
82
+ disablePeek: disableNavigation,
83
+ disableNewTab: disableNavigation,
84
+ openInNewTab,
85
+ alwaysShowActions,
86
+ wrap: mustShowId,
87
+ className,
88
+ labelClassName,
89
+ children: /* @__PURE__ */ jsx(IdentityLabel, { id: modelId, name: resolvedName, showId: mustShowId })
90
+ }
91
+ );
92
+ }
93
+ function AiToolRef({
94
+ toolId,
95
+ name,
96
+ showId = false,
97
+ showIcon = true,
98
+ alwaysShowActions,
99
+ openInNewTab = true,
100
+ disableNavigation = false,
101
+ className,
102
+ labelClassName
103
+ }) {
104
+ const tool = useToolCatalog((state) => selectToolById(state, toolId));
105
+ const lookupStatus = useToolCatalog((state) => selectToolLookupStatus(state, toolId));
106
+ const isSuperAdmin = useAppSelector(selectIsSuperAdmin);
107
+ useEffect(() => {
108
+ if (!name && !tool && isUuidValue(toolId) && lookupStatus === "idle") {
109
+ void loadToolById(toolId);
110
+ }
111
+ }, [lookupStatus, name, tool, toolId]);
112
+ const resolvedName = name?.trim() || tool?.name || fallbackName("tool", toolId);
113
+ const mustShowId = showId || !name && !tool && isUuidValue(toolId);
114
+ return /* @__PURE__ */ jsx(
115
+ EntityRef,
116
+ {
117
+ token: "tool",
118
+ id: toolId,
119
+ name: resolvedName,
120
+ href: isSuperAdmin && !disableNavigation ? toolHref(toolId) : void 0,
121
+ showIcon,
122
+ disablePeek: disableNavigation,
123
+ disableNewTab: disableNavigation,
124
+ openInNewTab,
125
+ alwaysShowActions,
126
+ wrap: mustShowId,
127
+ className,
128
+ labelClassName,
129
+ children: /* @__PURE__ */ jsx(IdentityLabel, { id: toolId, name: resolvedName, showId: mustShowId })
130
+ }
131
+ );
132
+ }
133
+ export {
134
+ AiModelRef,
135
+ AiToolRef,
136
+ aiModelHref,
137
+ toolHref
138
+ };
@@ -0,0 +1,8 @@
1
+ import type { ManagedResource } from "../../../types/instance.types.js";
2
+ export declare function RenderedArtifactChip({ conversationId, resource, onRemove, onOpen, pressed, }: {
3
+ conversationId: string;
4
+ resource: ManagedResource;
5
+ onRemove: () => void;
6
+ onOpen: () => void;
7
+ pressed: boolean;
8
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,109 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { createElement, useState } from "react";
4
+ import { Check, ChevronDown, Shapes } from "lucide-react";
5
+ import { Popover, PopoverContent, PopoverTrigger } from "@ai-matrx/design-system";
6
+ import { Tile } from "@ai-matrx/design-system/controls";
7
+ import { useAppStore } from "../../../../store/hooks.js";
8
+ import {
9
+ isRenderedArtifactRepresentation,
10
+ isRenderedArtifactSource,
11
+ renderedArtifactCaptureFor,
12
+ renderedArtifactOptionsOf,
13
+ renderedArtifactRepresentationLabel
14
+ } from "../../../utils/renderedArtifactContext.js";
15
+ import { ComposerChip, ComposerChipPart } from "../smart-input/ComposerChip.js";
16
+ import { compactChipLabel } from "../../messages-display/user/compact-chip-label.js";
17
+ import { attachRenderedArtifact } from "./useAttachRenderedArtifact.js";
18
+ import {
19
+ removeResource,
20
+ setResourcePreview,
21
+ updateResourceOptions
22
+ } from "../../../redux/execution-system/instance-resources/instance-resources.slice.js";
23
+ function RenderedArtifactChip({
24
+ conversationId,
25
+ resource,
26
+ onRemove,
27
+ onOpen,
28
+ pressed
29
+ }) {
30
+ const store = useAppStore();
31
+ const [open, setOpen] = useState(false);
32
+ const source = isRenderedArtifactSource(resource.source) ? resource.source : null;
33
+ if (!source) return null;
34
+ const current = isRenderedArtifactRepresentation(
35
+ resource.options.representation
36
+ ) ? resource.options.representation : "code";
37
+ const title = source.title || "Artifact";
38
+ const capture = renderedArtifactCaptureFor(source);
39
+ const choose = async (value) => {
40
+ setOpen(false);
41
+ if (value === current) return;
42
+ const { resourceId } = resource;
43
+ if (value !== "screenshot") {
44
+ store.dispatch(updateResourceOptions({ conversationId, resourceId, options: { representation: value } }));
45
+ store.dispatch(
46
+ setResourcePreview({
47
+ conversationId,
48
+ resourceId,
49
+ preview: `${title} \xB7 ${renderedArtifactRepresentationLabel(source, value)}`
50
+ })
51
+ );
52
+ return;
53
+ }
54
+ if (!capture) return;
55
+ const ok = await attachRenderedArtifact(
56
+ { dispatch: store.dispatch, getState: store.getState },
57
+ conversationId,
58
+ { source, representation: "screenshot", capture }
59
+ );
60
+ if (ok) store.dispatch(removeResource({ conversationId, resourceId }));
61
+ };
62
+ const stop = (event) => event.stopPropagation();
63
+ return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
64
+ /* @__PURE__ */ jsx(
65
+ ComposerChip,
66
+ {
67
+ tone: "quiet",
68
+ onClick: onOpen,
69
+ "aria-label": `Attached ${source.artifact_type ?? "artifact"}: ${title}`,
70
+ pressed,
71
+ icon: createElement(Shapes),
72
+ label: compactChipLabel(title),
73
+ remove: { label: `Remove ${title}`, onRemove },
74
+ parts: /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
75
+ ComposerChipPart,
76
+ {
77
+ tone: "quiet",
78
+ onClick: stop,
79
+ onPointerDown: stop,
80
+ "aria-label": `What the AI receives from ${title}: ${renderedArtifactRepresentationLabel(source, current)}`,
81
+ children: [
82
+ /* @__PURE__ */ jsx("span", { children: renderedArtifactRepresentationLabel(source, current) }),
83
+ /* @__PURE__ */ jsx(ChevronDown, { className: "!size-3" })
84
+ ]
85
+ }
86
+ ) })
87
+ }
88
+ ),
89
+ /* @__PURE__ */ jsx(PopoverContent, { sizing: "content", side: "top", align: "start", sideOffset: 6, className: "p-1", onClick: stop, children: renderedArtifactOptionsOf(source).map((option) => {
90
+ const blocked = option.unavailable ?? (option.value === "screenshot" && !capture ? "Attach again to capture" : void 0);
91
+ return /* @__PURE__ */ jsx(
92
+ Tile,
93
+ {
94
+ variant: "quiet",
95
+ icon: option.value === current ? /* @__PURE__ */ jsx(Check, {}) : /* @__PURE__ */ jsx("span", {}),
96
+ title: option.label,
97
+ selected: option.value === current,
98
+ line: blocked ?? option.hint,
99
+ disabled: Boolean(blocked),
100
+ onClick: () => void choose(option.value)
101
+ },
102
+ option.value
103
+ );
104
+ }) })
105
+ ] });
106
+ }
107
+ export {
108
+ RenderedArtifactChip
109
+ };
@@ -22,6 +22,7 @@ import { revokeTrackedObjectUrl } from "@ai-matrx/media/files";
22
22
  import { resolveContextItemDef } from "../../context-items/registry.js";
23
23
  import { remarkKindDisplay } from "../../context-items/remark-display.js";
24
24
  import { dismissRemarkChip, remarkSourceOf } from "../../../redux/execution-system/instance-resources/remarks.js";
25
+ import { RenderedArtifactChip } from "./RenderedArtifactChip.js";
25
26
  import {
26
27
  AttachedDocumentChip
27
28
  } from "./AttachedDocumentChip.js";
@@ -293,6 +294,25 @@ function SmartAgentResourceChips({
293
294
  onSettingsChange: (settings) => handleDocumentSettings(resource.resourceId, settings)
294
295
  },
295
296
  resource.resourceId
297
+ ) : resource.blockType === "rendered_artifact" && resource.status === "ready" ? /* @__PURE__ */ jsx(
298
+ motion.div,
299
+ {
300
+ initial: { opacity: 0, scale: 0.85 },
301
+ animate: { opacity: 1, scale: 1 },
302
+ exit: { opacity: 0, scale: 0.85 },
303
+ className: "inline-flex shrink-0",
304
+ children: /* @__PURE__ */ jsx(
305
+ RenderedArtifactChip,
306
+ {
307
+ conversationId,
308
+ resource,
309
+ onRemove: () => handleRemove(resource.resourceId),
310
+ onOpen: () => openDrawerForResource(resource.resourceId),
311
+ pressed: isShowingResource(resource.resourceId)
312
+ }
313
+ )
314
+ },
315
+ resource.resourceId
296
316
  ) : /* @__PURE__ */ jsx(
297
317
  ResourceChip,
298
318
  {
@@ -9,10 +9,34 @@ import {
9
9
  } from "../../../redux/execution-system/instance-resources/instance-resources.slice.js";
10
10
  import { generateResourceId } from "../../../redux/execution-system/utils/ids.js";
11
11
  import {
12
- RENDERED_ARTIFACT_BLOCK_TYPE
12
+ RENDERED_ARTIFACT_BLOCK_TYPE,
13
+ registerRenderedArtifactCapture,
14
+ renderedArtifactRepresentationLabel
13
15
  } from "../../../utils/renderedArtifactContext.js";
16
+ import { fileHandler } from "@ai-matrx/media/files/engine/handler/handler";
17
+ import { composeUploadFolderPath } from "@ai-matrx/media/files";
18
+ import {
19
+ ensureExecutionOrganization,
20
+ requireExecutionOrganizationId
21
+ } from "../../../redux/execution-system/utils/required-organization.js";
14
22
  import { attachResourceToConversation } from "./attach-resource.js";
15
23
  import { useUploadAgentResources } from "./usePasteImageResource.js";
24
+ async function uploadCapturedImage(store, conversationId, file) {
25
+ const state = store.getState();
26
+ const organizationId = await ensureExecutionOrganization(state, conversationId) ?? requireExecutionOrganizationId(state, conversationId);
27
+ const uploaded = await fileHandler.upload(
28
+ { kind: "file", file },
29
+ {
30
+ folderPath: composeUploadFolderPath("attachments", "screenshots"),
31
+ visibility: "personal",
32
+ metadata: { scope: { organization_id: organizationId } },
33
+ createShareLink: true,
34
+ shareLinkPermissionLevel: "viewer"
35
+ }
36
+ );
37
+ if (!uploaded.fileId) throw new Error("The screenshot upload returned no file id");
38
+ return { fileId: uploaded.fileId, url: uploaded.url ?? null };
39
+ }
16
40
  function screenshotName(title) {
17
41
  const base = title.trim().replace(/[^\w\s.-]+/g, "").trim().slice(0, 60) || "page";
18
42
  return `${base} screenshot.png`;
@@ -37,6 +61,7 @@ async function attachRenderedArtifact(store, conversationId, { source, represent
37
61
  toast.error("Open a chat to attach this to.");
38
62
  return false;
39
63
  }
64
+ if (capture) registerRenderedArtifactCapture(source, capture);
40
65
  if (representation !== "screenshot") {
41
66
  const resourceId = generateResourceId();
42
67
  dispatch(
@@ -52,7 +77,7 @@ async function attachRenderedArtifact(store, conversationId, { source, represent
52
77
  setResourcePreview({
53
78
  conversationId,
54
79
  resourceId,
55
- preview: `${source.title || "Page"} \xB7 ${representation === "code" ? "Code" : "Text"}`
80
+ preview: `${source.title || "Artifact"} \xB7 ${renderedArtifactRepresentationLabel(source, representation)}`
56
81
  })
57
82
  );
58
83
  return true;
@@ -77,18 +102,18 @@ async function attachRenderedArtifact(store, conversationId, { source, represent
77
102
  if (state.instanceResources.byConversationId[conversationId]?.[placeholderId] === void 0) {
78
103
  return false;
79
104
  }
80
- if (result.kind === "file") {
81
- if (!uploadFiles) throw new Error("This capture needs an upload, which is not available here");
105
+ if (result.kind === "file" && uploadFiles) {
82
106
  dispatch(removeResource({ conversationId, resourceId: placeholderId }));
83
107
  await uploadFiles([result.file]);
84
108
  return true;
85
109
  }
110
+ const stored = result.kind === "file" ? await uploadCapturedImage(store, conversationId, result.file) : result;
86
111
  const attached = await attachResourceToConversation(store, conversationId, {
87
112
  type: "file",
88
113
  data: {
89
- id: result.fileId,
114
+ id: stored.fileId,
90
115
  filename: name,
91
- url: result.url ?? void 0,
116
+ url: stored.url ?? void 0,
92
117
  type: "image/png",
93
118
  mime_type: "image/png",
94
119
  details: { filename: name }
@@ -42,15 +42,11 @@ import {
42
42
  selectAgentTools,
43
43
  selectAgentRunControlsReady
44
44
  } from "../../../redux/agent-definition/selectors.js";
45
- import {
46
- selectAllTools,
47
- selectToolsStatus
48
- } from "../../../redux/tools/tools.selectors.js";
49
- import { fetchAvailableTools } from "../../../redux/tools/tools.thunks.js";
50
45
  import { fetchAgentRunControls } from "../../../redux/agent-definition/thunks.js";
51
- import { AiToolRef } from "../../../../host/ui-slots.js";
46
+ import { AiToolRef } from "../../identity-refs/AiIdentityRef.js";
52
47
  import { useTouchOnlyDevice } from "../../../../ui/composer/useTouchOnlyDevice.js";
53
48
  import { selectSandboxBySurface } from "../../../../host/prefs.js";
49
+ import { loadAvailableTools, selectAllTools, selectToolsStatus, useToolCatalog } from "../../../identity/tool-catalog.js";
54
50
  const EMPTY_LIST = [];
55
51
  function Row({ label, children }) {
56
52
  return /* @__PURE__ */ jsxs("div", { className: "grid min-h-8 grid-cols-[9rem_minmax(0,1fr)] items-center gap-2", children: [
@@ -140,8 +136,8 @@ function QuicksetPanel({
140
136
  const mcpServers = useAppSelector(
141
137
  (state) => agentId ? selectAgentMcpServers(state, agentId) : EMPTY_LIST
142
138
  );
143
- const toolCatalog = useAppSelector(selectAllTools);
144
- const toolsStatus = useAppSelector(selectToolsStatus);
139
+ const toolCatalog = useToolCatalog(selectAllTools);
140
+ const toolsStatus = useToolCatalog(selectToolsStatus);
145
141
  const agentReady = useAppSelector(
146
142
  (state) => agentId ? selectAgentRunControlsReady(state, agentId) : true
147
143
  );
@@ -156,7 +152,7 @@ function QuicksetPanel({
156
152
  });
157
153
  useEffect(() => {
158
154
  if (toolsStatus !== "succeeded" && toolsStatus !== "loading") {
159
- void dispatch(fetchAvailableTools());
155
+ void loadAvailableTools();
160
156
  }
161
157
  }, [dispatch, toolsStatus]);
162
158
  useEffect(() => {
@@ -17,7 +17,7 @@ import { fetchAgentRunControls } from "../../../redux/agent-definition/thunks.js
17
17
  import { selectBuilderAdvancedSettings } from "../../../redux/execution-system/instance-ui-state/instance-ui-state.selectors.js";
18
18
  import { setBuilderAdvancedSettings } from "../../../redux/execution-system/instance-ui-state/instance-ui-state.slice.js";
19
19
  import { DEFAULT_BUILDER_ADVANCED_SETTINGS } from "../../../types/instance.types.js";
20
- import { useSkills } from "../../../../host/ui-slots.js";
20
+ import { useSkills } from "../../../identity/skill-catalog.js";
21
21
  import { ReadFailure } from "../../../../host/ui-slots.js";
22
22
  import { filterAndSortBySearch } from "@ai-matrx/kit/search-scoring";
23
23
  import {
@@ -14,13 +14,7 @@ import {
14
14
  PicksSkeletons,
15
15
  PicksSwitchRow
16
16
  } from "./RunPicksSurface.js";
17
- import {
18
- selectAllTools,
19
- selectToolsStatus,
20
- selectToolsError
21
- } from "../../../redux/tools/tools.selectors.js";
22
17
  import { ReadFailure } from "../../../../host/ui-slots.js";
23
- import { fetchAvailableTools } from "../../../redux/tools/tools.thunks.js";
24
18
  import {
25
19
  selectAgentError,
26
20
  selectAgentTools,
@@ -44,11 +38,12 @@ import { DEFAULT_BUILDER_ADVANCED_SETTINGS } from "../../../types/instance.types
44
38
  import { filterAndSortBySearch } from "@ai-matrx/kit/search-scoring";
45
39
  import { getToolDisplayName } from "../../../../tool-call-visualization/registry/registry.js";
46
40
  import { groupToolCatalog, toolCategoryLabel } from "./run-tool-catalog.js";
41
+ import { loadAvailableTools, selectAllTools, selectToolsError, selectToolsStatus, useToolCatalog } from "../../../identity/tool-catalog.js";
47
42
  function RunToolPicker({ conversationId }) {
48
43
  const dispatch = useAppDispatch();
49
- const tools = useAppSelector(selectAllTools);
50
- const status = useAppSelector(selectToolsStatus);
51
- const toolsError = useAppSelector(selectToolsError);
44
+ const tools = useToolCatalog(selectAllTools);
45
+ const status = useToolCatalog(selectToolsStatus);
46
+ const toolsError = useToolCatalog(selectToolsError);
52
47
  const agentId = useAppSelector(selectAgentIdFromInstance(conversationId));
53
48
  const agentToolIds = useAppSelector(
54
49
  (s) => agentId ? selectAgentTools(s, agentId) : void 0
@@ -92,7 +87,7 @@ function RunToolPicker({ conversationId }) {
92
87
  const added = new Set(addedList);
93
88
  useEffect(() => {
94
89
  if (status === "idle") {
95
- void dispatch(fetchAvailableTools());
90
+ void loadAvailableTools();
96
91
  }
97
92
  }, [status, dispatch]);
98
93
  useEffect(() => {
@@ -249,7 +244,7 @@ function RunToolPicker({ conversationId }) {
249
244
  error: toolsError ?? true,
250
245
  what: "the tool catalog",
251
246
  className: "m-2",
252
- onRetry: () => void dispatch(fetchAvailableTools())
247
+ onRetry: () => void loadAvailableTools()
253
248
  }
254
249
  ) : void 0,
255
250
  addDisabledReason: modelSupportsTools ? void 0 : "Pick a model that supports tools to add any."
@@ -12,7 +12,7 @@ import { useAppDispatch, useAppSelector } from "../../../../store/hooks.js";
12
12
  import { selectBuilderAdvancedSettings } from "../../../redux/execution-system/instance-ui-state/instance-ui-state.selectors.js";
13
13
  import { setBuilderAdvancedSettings } from "../../../redux/execution-system/instance-ui-state/instance-ui-state.slice.js";
14
14
  import { DEFAULT_BUILDER_ADVANCED_SETTINGS } from "../../../types/instance.types.js";
15
- import { useSkills } from "../../../../host/ui-slots.js";
15
+ import { useSkills } from "../../../identity/skill-catalog.js";
16
16
  import { SHAPE_CHIP_DEFS } from "./shape-chips.js";
17
17
  import { selectedOutputKinds, toggleOutputKind } from "./composer/output-selection.js";
18
18
  const CHIP_ICONS = {
@@ -12,7 +12,7 @@ import {
12
12
  resetOverride,
13
13
  setOverrides
14
14
  } from "../../../../redux/execution-system/instance-model-overrides/instance-model-overrides.slice.js";
15
- import { useModelFull } from "../../../../../host/ui-slots.js";
15
+ import { useModelFull } from "../../../../identity/model-catalog.js";
16
16
  import { resolveModelControls } from "../../../../hooks/useModelControls.js";
17
17
  import {
18
18
  ComposerMenuDivider,
@@ -31,7 +31,7 @@ import { useAppDispatch, useAppSelector } from "../../../../../store/hooks.js";
31
31
  import { selectBuilderAdvancedSettings } from "../../../../redux/execution-system/instance-ui-state/instance-ui-state.selectors.js";
32
32
  import { setBuilderAdvancedSettings } from "../../../../redux/execution-system/instance-ui-state/instance-ui-state.slice.js";
33
33
  import { DEFAULT_BUILDER_ADVANCED_SETTINGS } from "../../../../types/instance.types.js";
34
- import { useSkills } from "../../../../../host/ui-slots.js";
34
+ import { useSkills } from "../../../../identity/skill-catalog.js";
35
35
  import { useClippedContentGuard } from "../../../../../host/ui-slots.js";
36
36
  import { ComposerMenuDivider, ComposerMenuHelp, ComposerMenuLabel, ComposerMenuRow } from "./ComposerMenu.js";
37
37
  import {
@@ -33,7 +33,7 @@ import { useAppDispatch, useAppSelector } from "../../../../../store/hooks.js";
33
33
  import { ResourcePickerMenu } from "../../../../../host/ui-slots.js";
34
34
  import { flattenResourcePickerItems } from "../../../../../host/ui-slots.js";
35
35
  import { useKnowledgeAttachSearch } from "../../../../../host/ui-slots.js";
36
- import { useRunControlCounts } from "../../../../../host/ui-slots.js";
36
+ import { useRunControlCounts } from "./useRunControlCounts.js";
37
37
  import {
38
38
  useAttachResource,
39
39
  useDetachResource
@@ -13,7 +13,7 @@ import {
13
13
  selectModelLabelById,
14
14
  selectModelLabelWithClass
15
15
  } from "@ai-matrx/agents/models";
16
- import { useModelOptions } from "../../../../../host/ui-slots.js";
16
+ import { useModelOptions } from "../../../../identity/model-catalog.js";
17
17
  import { useModelClassLabels, useModelRecords } from "../../../../identity/model-catalog.js";
18
18
  import { useEffectiveClassPin } from "../../../../redux/execution-system/instance-model-overrides/useEffectiveClassPin.js";
19
19
  import { ensureAgentCatalog, useAgentName } from "../../../../identity/agent-identity.js";
@@ -0,0 +1,3 @@
1
+ import { type RunControlCounts } from "@ai-matrx/agents/runtime";
2
+ export type { RunControlCounts };
3
+ export declare function useRunControlCounts(conversationId?: string): RunControlCounts;
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { computeRunControlCounts } from "@ai-matrx/agents/runtime";
4
+ import { hasField } from "@ai-matrx/agents/field-flags";
5
+ import { useAppDispatch, useAppSelector } from "../../../../../store/hooks.js";
6
+ import { selectAgentIdFromInstance } from "../../../../redux/execution-system/conversations/conversations.selectors.js";
7
+ import {
8
+ selectAgentById,
9
+ selectAgentCustomTools,
10
+ selectAgentRunTier,
11
+ selectAgentSkillConfig,
12
+ selectAgentTools
13
+ } from "../../../../redux/agent-definition/selectors.js";
14
+ import { fetchAgentRunTier } from "../../../../redux/agent-definition/thunks.js";
15
+ import { selectBuilderAdvancedSettings } from "../../../../redux/execution-system/instance-ui-state/instance-ui-state.selectors.js";
16
+ import { DEFAULT_BUILDER_ADVANCED_SETTINGS } from "../../../../types/instance.types.js";
17
+ function useRunControlCounts(conversationId) {
18
+ const dispatch = useAppDispatch();
19
+ const agentId = useAppSelector((s) => conversationId ? selectAgentIdFromInstance(conversationId)(s) : void 0);
20
+ const runTierReady = useAppSelector((s) => agentId ? selectAgentRunTier(s, agentId).isReady : false);
21
+ const customToolsKnown = useAppSelector((s) => {
22
+ const record = agentId ? selectAgentById(s, agentId) : void 0;
23
+ return !!record && hasField(record._loadedFields, "customTools");
24
+ });
25
+ const skillConfigKnown = useAppSelector((s) => {
26
+ const record = agentId ? selectAgentById(s, agentId) : void 0;
27
+ return !!record && hasField(record._loadedFields, "skillConfig");
28
+ });
29
+ const runCounts = useAppSelector((s) => agentId ? selectAgentRunTier(s, agentId).counts : null);
30
+ const builtInToolIds = useAppSelector((s) => agentId ? selectAgentTools(s, agentId) : void 0);
31
+ const customTools = useAppSelector((s) => agentId ? selectAgentCustomTools(s, agentId) : void 0);
32
+ const skillConfig = useAppSelector((s) => agentId ? selectAgentSkillConfig(s, agentId) : void 0);
33
+ const settings = useAppSelector((s) => conversationId ? selectBuilderAdvancedSettings(conversationId)(s) : void 0);
34
+ useEffect(() => {
35
+ if (agentId && !runTierReady) void dispatch(fetchAgentRunTier(agentId));
36
+ }, [agentId, runTierReady, dispatch]);
37
+ if (!conversationId) return {};
38
+ const advanced = settings ?? DEFAULT_BUILDER_ADVANCED_SETTINGS;
39
+ return computeRunControlCounts({
40
+ hasAgent: Boolean(agentId),
41
+ runTierReady,
42
+ runCounts,
43
+ builtInToolIds: Array.isArray(builtInToolIds) ? builtInToolIds : [],
44
+ customTools: Array.isArray(customTools) ? customTools : [],
45
+ customToolsKnown,
46
+ skillConfig: skillConfig ?? null,
47
+ skillConfigKnown,
48
+ addedTools: advanced.addedTools ?? [],
49
+ addedSkills: advanced.addedSkills ?? []
50
+ });
51
+ }
52
+ export {
53
+ useRunControlCounts
54
+ };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { AiModelRef } from "../../../host/ui-slots.js";
3
+ import { AiModelRef } from "../identity-refs/AiIdentityRef.js";
4
4
  import { cn } from "@ai-matrx/design-system";
5
5
  function isRecord(value) {
6
6
  return typeof value === "object" && value !== null && !Array.isArray(value);