@agent-native/core 0.118.1 → 0.119.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.
- package/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +19 -0
- package/corpus/core/docs/content/a2a-protocol.mdx +15 -0
- package/corpus/core/docs/content/template-chat.mdx +1 -1
- package/corpus/core/docs/content/template-plan.mdx +3 -3
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/activity.ts +371 -0
- package/corpus/core/src/a2a/client.ts +3 -1
- package/corpus/core/src/a2a/index.ts +21 -0
- package/corpus/core/src/a2a/types.ts +8 -0
- package/corpus/core/src/agent/model-config.ts +19 -23
- package/corpus/core/src/agent/production-agent.ts +167 -100
- package/corpus/core/src/agent/types.ts +16 -1
- package/corpus/core/src/client/chat/tool-call-display.tsx +190 -35
- package/corpus/core/src/client/chat-model-groups.ts +67 -27
- package/corpus/core/src/client/sharing/ShareButton.tsx +1 -27
- package/corpus/core/src/client/sharing/ShareDialog.tsx +0 -16
- package/corpus/core/src/client/sharing/useShareButtonController.ts +0 -7
- package/corpus/core/src/client/sharing/useShareDialogController.ts +0 -2
- package/corpus/core/src/client/sse-event-processor.ts +85 -1
- package/corpus/core/src/ingestion/figma-node-to-html.ts +20 -99
- package/corpus/core/src/ingestion/figma-paint-math.ts +371 -0
- package/corpus/core/src/ingestion/index.ts +20 -0
- package/corpus/core/src/localization/default-messages.ts +6 -0
- package/corpus/core/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/corpus/core/src/scripts/call-agent.ts +49 -6
- package/corpus/core/src/server/agent-chat-plugin.ts +50 -10
- package/corpus/core/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/corpus/templates/assets/app/routes/library.tsx +17 -9
- package/corpus/templates/clips/changelog/2026-07-23-fixed-recordings-failing-to-save-with-a-cancelled-or-cleanup.md +6 -0
- package/corpus/templates/clips/server/plugins/db.ts +9 -1
- package/corpus/templates/design/AGENTS.md +18 -5
- package/corpus/templates/design/FIGMA_INTEROPERABILITY.md +25 -12
- package/corpus/templates/design/actions/hydrate-figma-paste-images.ts +115 -0
- package/corpus/templates/design/actions/import-figma-clipboard.ts +83 -18
- package/corpus/templates/design/actions/import-figma-frame.ts +34 -21
- package/corpus/templates/design/app/components/design/DesignCanvas.tsx +28 -1
- package/corpus/templates/design/app/components/design/DesignImportPanel.tsx +106 -11
- package/corpus/templates/design/app/components/design/FigmaHydrationDialog.tsx +273 -0
- package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +7 -7
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +57 -9
- package/corpus/templates/design/app/components/design/design-canvas/iframe-events.ts +10 -0
- package/corpus/templates/design/app/components/design/multi-screen/board-surface-html.ts +8 -1
- package/corpus/templates/design/app/components/design/multi-screen/types.ts +3 -0
- package/corpus/templates/design/app/i18n-data.ts +150 -2
- package/corpus/templates/design/app/lib/design-file-upload.ts +85 -0
- package/corpus/templates/design/app/lib/design-import.ts +19 -1
- package/corpus/templates/design/app/lib/figma-clipboard.ts +110 -10
- package/corpus/templates/design/changelog/2026-07-20-paste-figma-frames-directly-onto-the-canvas-no-token-needed.md +6 -0
- package/corpus/templates/design/changelog/2026-07-21-fig-upload-frame-url-and-rate-limit-errors.md +5 -0
- package/corpus/templates/design/changelog/2026-07-22-connecting-a-figma-token-now-actually-fills-in-a-pasted-desi.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-figma-line-arrow-vectors-and-stroked-icons-now-render-instea.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-fill-a-no-token-figma-paste-s-images-by-dropping-the-origina.md +6 -0
- package/corpus/templates/design/changelog/2026-07-22-imported-and-pasted-figma-frames-now-render-faithfully-fixed.md +6 -0
- package/corpus/templates/design/server/handlers/import-design-file.ts +50 -0
- package/corpus/templates/design/server/lib/fig-file-decoder.ts +90 -49
- package/corpus/templates/design/server/lib/fig-file-import.ts +19 -5
- package/corpus/templates/design/server/lib/fig-file-to-html.ts +583 -78
- package/corpus/templates/design/server/lib/figma-clipboard-local-decode.ts +238 -0
- package/corpus/templates/design/server/lib/figma-image-hydration.ts +389 -0
- package/corpus/templates/design/server/lib/figma-node-import.ts +136 -36
- package/corpus/templates/design/server/register-secrets.ts +14 -2
- package/dist/a2a/activity.d.ts +50 -0
- package/dist/a2a/activity.d.ts.map +1 -0
- package/dist/a2a/activity.js +236 -0
- package/dist/a2a/activity.js.map +1 -0
- package/dist/a2a/client.d.ts +2 -0
- package/dist/a2a/client.d.ts.map +1 -1
- package/dist/a2a/client.js +1 -1
- package/dist/a2a/client.js.map +1 -1
- package/dist/a2a/index.d.ts +2 -1
- package/dist/a2a/index.d.ts.map +1 -1
- package/dist/a2a/index.js +1 -0
- package/dist/a2a/index.js.map +1 -1
- package/dist/a2a/types.d.ts +1 -0
- package/dist/a2a/types.d.ts.map +1 -1
- package/dist/a2a/types.js.map +1 -1
- package/dist/agent/engine/anthropic-engine.d.ts +1 -1
- package/dist/agent/engine/builder-engine.d.ts +2 -2
- package/dist/agent/engine/builder-engine.d.ts.map +1 -1
- package/dist/agent/model-config.d.ts +16 -16
- package/dist/agent/model-config.d.ts.map +1 -1
- package/dist/agent/model-config.js +19 -23
- package/dist/agent/model-config.js.map +1 -1
- package/dist/agent/production-agent.d.ts +26 -0
- package/dist/agent/production-agent.d.ts.map +1 -1
- package/dist/agent/production-agent.js +137 -80
- package/dist/agent/production-agent.js.map +1 -1
- package/dist/agent/types.d.ts +10 -0
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/client/chat/tool-call-display.d.ts.map +1 -1
- package/dist/client/chat/tool-call-display.js +63 -14
- package/dist/client/chat/tool-call-display.js.map +1 -1
- package/dist/client/chat-model-groups.d.ts.map +1 -1
- package/dist/client/chat-model-groups.js +44 -21
- package/dist/client/chat-model-groups.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +1 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +3 -4
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +1 -2
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/client/sharing/useShareButtonController.d.ts +0 -1
- package/dist/client/sharing/useShareButtonController.d.ts.map +1 -1
- package/dist/client/sharing/useShareButtonController.js +0 -6
- package/dist/client/sharing/useShareButtonController.js.map +1 -1
- package/dist/client/sharing/useShareDialogController.d.ts +0 -1
- package/dist/client/sharing/useShareDialogController.d.ts.map +1 -1
- package/dist/client/sharing/useShareDialogController.js +0 -1
- package/dist/client/sharing/useShareDialogController.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts +12 -0
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +63 -1
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/ingestion/figma-node-to-html.d.ts.map +1 -1
- package/dist/ingestion/figma-node-to-html.js +14 -88
- package/dist/ingestion/figma-node-to-html.js.map +1 -1
- package/dist/ingestion/figma-paint-math.d.ts +157 -0
- package/dist/ingestion/figma-paint-math.d.ts.map +1 -0
- package/dist/ingestion/figma-paint-math.js +274 -0
- package/dist/ingestion/figma-paint-math.js.map +1 -0
- package/dist/ingestion/index.d.ts +1 -0
- package/dist/ingestion/index.d.ts.map +1 -1
- package/dist/ingestion/index.js +1 -0
- package/dist/ingestion/index.js.map +1 -1
- package/dist/localization/default-messages.d.ts +6 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +6 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +5 -5
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +12 -12
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.d.ts.map +1 -1
- package/dist/scripts/agent-engines/list-agent-engines.js +1 -18
- package/dist/scripts/agent-engines/list-agent-engines.js.map +1 -1
- package/dist/scripts/call-agent.d.ts.map +1 -1
- package/dist/scripts/call-agent.js +49 -6
- package/dist/scripts/call-agent.js.map +1 -1
- package/dist/secrets/routes.d.ts +3 -3
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +38 -10
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/docs/content/a2a-protocol.mdx +15 -0
- package/docs/content/template-chat.mdx +1 -1
- package/docs/content/template-plan.mdx +3 -3
- package/package.json +1 -1
- package/src/a2a/activity.ts +371 -0
- package/src/a2a/client.ts +3 -1
- package/src/a2a/index.ts +21 -0
- package/src/a2a/types.ts +8 -0
- package/src/agent/model-config.ts +19 -23
- package/src/agent/production-agent.ts +167 -100
- package/src/agent/types.ts +16 -1
- package/src/client/chat/tool-call-display.tsx +190 -35
- package/src/client/chat-model-groups.ts +67 -27
- package/src/client/sharing/ShareButton.tsx +1 -27
- package/src/client/sharing/ShareDialog.tsx +0 -16
- package/src/client/sharing/useShareButtonController.ts +0 -7
- package/src/client/sharing/useShareDialogController.ts +0 -2
- package/src/client/sse-event-processor.ts +85 -1
- package/src/ingestion/figma-node-to-html.ts +20 -99
- package/src/ingestion/figma-paint-math.ts +371 -0
- package/src/ingestion/index.ts +20 -0
- package/src/localization/default-messages.ts +6 -0
- package/src/scripts/agent-engines/list-agent-engines.ts +1 -18
- package/src/scripts/call-agent.ts +49 -6
- package/src/server/agent-chat-plugin.ts +50 -10
- package/src/templates/workspace-core/.agents/skills/a2a-protocol/SKILL.md +16 -0
- package/corpus/core/src/observability/hosted-model-experiment.ts +0 -118
- package/dist/observability/hosted-model-experiment.d.ts +0 -39
- package/dist/observability/hosted-model-experiment.d.ts.map +0 -1
- package/dist/observability/hosted-model-experiment.js +0 -90
- package/dist/observability/hosted-model-experiment.js.map +0 -1
- package/src/observability/hosted-model-experiment.ts +0 -118
|
@@ -40,34 +40,64 @@ function addCurrentModel(
|
|
|
40
40
|
return next;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
const MODEL_COST_ORDER = [
|
|
44
|
+
"luna",
|
|
45
|
+
"terra",
|
|
46
|
+
"sol",
|
|
47
|
+
"haiku",
|
|
48
|
+
"sonnet",
|
|
49
|
+
"opus",
|
|
50
|
+
"fable",
|
|
51
|
+
"flash",
|
|
52
|
+
"pro",
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
55
|
+
function modelCostRank(model: string): number {
|
|
56
|
+
const normalized = model.toLowerCase();
|
|
57
|
+
const rank = MODEL_COST_ORDER.findIndex((tier) => normalized.includes(tier));
|
|
58
|
+
return rank === -1 ? MODEL_COST_ORDER.length : rank;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function sortModelsByCost(models: readonly string[]): string[] {
|
|
62
|
+
return [...models].sort((a, b) => modelCostRank(a) - modelCostRank(b));
|
|
63
|
+
}
|
|
64
|
+
|
|
43
65
|
function groupBuilderModels(models: readonly string[]): EngineModelGroup[] {
|
|
44
|
-
const claude =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
(model) =>
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
66
|
+
const claude = sortModelsByCost(
|
|
67
|
+
models.filter((model) => model.startsWith("claude-")),
|
|
68
|
+
);
|
|
69
|
+
const openai = sortModelsByCost(
|
|
70
|
+
models.filter((model) => model.startsWith("gpt-")),
|
|
71
|
+
);
|
|
72
|
+
const gemini = sortModelsByCost(
|
|
73
|
+
models.filter((model) => model.startsWith("gemini-")),
|
|
74
|
+
);
|
|
75
|
+
const other = sortModelsByCost(
|
|
76
|
+
models.filter(
|
|
77
|
+
(model) =>
|
|
78
|
+
!model.startsWith("claude-") &&
|
|
79
|
+
!model.startsWith("gpt-") &&
|
|
80
|
+
!model.startsWith("gemini-"),
|
|
81
|
+
),
|
|
52
82
|
);
|
|
53
83
|
|
|
54
84
|
return [
|
|
55
|
-
...(
|
|
85
|
+
...(openai.length
|
|
56
86
|
? [
|
|
57
87
|
{
|
|
58
88
|
engine: "builder",
|
|
59
|
-
label: "
|
|
60
|
-
models:
|
|
89
|
+
label: "OpenAI",
|
|
90
|
+
models: openai,
|
|
61
91
|
configured: true,
|
|
62
92
|
},
|
|
63
93
|
]
|
|
64
94
|
: []),
|
|
65
|
-
...(
|
|
95
|
+
...(claude.length
|
|
66
96
|
? [
|
|
67
97
|
{
|
|
68
98
|
engine: "builder",
|
|
69
|
-
label: "
|
|
70
|
-
models:
|
|
99
|
+
label: "Claude",
|
|
100
|
+
models: claude,
|
|
71
101
|
configured: true,
|
|
72
102
|
},
|
|
73
103
|
]
|
|
@@ -115,16 +145,24 @@ function shouldShowDirectEngine(
|
|
|
115
145
|
return true;
|
|
116
146
|
}
|
|
117
147
|
|
|
118
|
-
function
|
|
148
|
+
function modelPickerEngineRank(engine: ChatModelEngineEntry): number {
|
|
149
|
+
if (engine.name === "ai-sdk:openai" || engine.label === "OpenAI") return 0;
|
|
150
|
+
if (
|
|
151
|
+
engine.name === "anthropic" ||
|
|
152
|
+
engine.name === "ai-sdk:anthropic" ||
|
|
153
|
+
engine.label === "Claude"
|
|
154
|
+
) {
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
if (engine.name === "ai-sdk:openrouter") return 100;
|
|
158
|
+
return 2;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function sortModelPickerEngines(
|
|
119
162
|
a: ChatModelEngineEntry,
|
|
120
163
|
b: ChatModelEngineEntry,
|
|
121
164
|
): number {
|
|
122
|
-
|
|
123
|
-
const bIsOpenRouter = b.name === "ai-sdk:openrouter";
|
|
124
|
-
if (aIsOpenRouter === bIsOpenRouter) return 0;
|
|
125
|
-
if (aIsOpenRouter) return 1;
|
|
126
|
-
if (bIsOpenRouter) return -1;
|
|
127
|
-
return 0;
|
|
165
|
+
return modelPickerEngineRank(a) - modelPickerEngineRank(b);
|
|
128
166
|
}
|
|
129
167
|
|
|
130
168
|
export function buildChatModelGroups({
|
|
@@ -150,17 +188,19 @@ export function buildChatModelGroups({
|
|
|
150
188
|
return engines
|
|
151
189
|
.filter((engine) => engine.packageInstalled !== false)
|
|
152
190
|
.filter((engine) => shouldShowDirectEngine(engine, currentEngineName))
|
|
153
|
-
.sort(
|
|
191
|
+
.sort(sortModelPickerEngines)
|
|
154
192
|
.map((engine) => {
|
|
155
193
|
const requiredEnvVars = engine.requiredEnvVars ?? [];
|
|
156
194
|
return {
|
|
157
195
|
engine: engine.name,
|
|
158
196
|
label: engine.label,
|
|
159
|
-
models:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
197
|
+
models: sortModelsByCost(
|
|
198
|
+
addCurrentModel(
|
|
199
|
+
engine.supportedModels ?? [],
|
|
200
|
+
engine.name,
|
|
201
|
+
currentEngineName,
|
|
202
|
+
currentModel,
|
|
203
|
+
),
|
|
164
204
|
),
|
|
165
205
|
configured:
|
|
166
206
|
requiredEnvVars.length === 0 ||
|
|
@@ -77,7 +77,7 @@ export interface ShareButtonProps {
|
|
|
77
77
|
shareUrlPlacement?: "top" | "bottom";
|
|
78
78
|
/** Whether to render copyable share URL fields. Defaults to true. */
|
|
79
79
|
showShareLinks?: boolean;
|
|
80
|
-
/**
|
|
80
|
+
/** @deprecated The Done action was removed; share popovers dismiss directly. */
|
|
81
81
|
showDoneButton?: boolean;
|
|
82
82
|
/** Optional placeholder shown in the share-URL slot when `shareUrl` is
|
|
83
83
|
* undefined. Use this to explain *why* there's no link yet (e.g. "Publish
|
|
@@ -301,7 +301,6 @@ function SharePanel(
|
|
|
301
301
|
const {
|
|
302
302
|
inviteEmail,
|
|
303
303
|
setInviteEmail: onInviteEmailChange,
|
|
304
|
-
handleOpenChange,
|
|
305
304
|
activeShareTab,
|
|
306
305
|
handleShareTabChange,
|
|
307
306
|
data,
|
|
@@ -326,7 +325,6 @@ function SharePanel(
|
|
|
326
325
|
handleAdd,
|
|
327
326
|
handleChangeRole,
|
|
328
327
|
handleRemove,
|
|
329
|
-
handleDone,
|
|
330
328
|
} = controller;
|
|
331
329
|
const hasInviteEmail = inviteEmail.trim().length > 0;
|
|
332
330
|
|
|
@@ -367,7 +365,6 @@ function SharePanel(
|
|
|
367
365
|
(Boolean(props.shareUrl) ||
|
|
368
366
|
Boolean(props.shareUrlPlaceholder) ||
|
|
369
367
|
Boolean(props.secondaryShareUrl));
|
|
370
|
-
const showDoneButton = props.showDoneButton ?? true;
|
|
371
368
|
const shareUrlPlacement = props.shareUrlPlacement ?? "bottom";
|
|
372
369
|
const extraTabs = props.shareTabs?.tabs ?? [];
|
|
373
370
|
const hasTabs = extraTabs.length > 0;
|
|
@@ -392,17 +389,6 @@ function SharePanel(
|
|
|
392
389
|
<div className="mb-4 h-7 rounded-md bg-muted animate-pulse" />
|
|
393
390
|
<div className="mb-2 text-sm font-semibold">{generalAccessLabel}</div>
|
|
394
391
|
<div className="mb-4 h-9 rounded-md bg-muted animate-pulse" />
|
|
395
|
-
{showDoneButton ? (
|
|
396
|
-
<div className="mt-2 flex justify-end">
|
|
397
|
-
<button
|
|
398
|
-
type="button"
|
|
399
|
-
onClick={() => handleOpenChange(false)}
|
|
400
|
-
className={BUTTON_PRIMARY_SM}
|
|
401
|
-
>
|
|
402
|
-
Done
|
|
403
|
-
</button>
|
|
404
|
-
</div>
|
|
405
|
-
) : null}
|
|
406
392
|
</div>
|
|
407
393
|
) : (
|
|
408
394
|
<div>
|
|
@@ -579,18 +565,6 @@ function SharePanel(
|
|
|
579
565
|
{showShareLinks && shareUrlPlacement === "bottom" ? shareLinks : null}
|
|
580
566
|
|
|
581
567
|
{props.shareFooterContent}
|
|
582
|
-
|
|
583
|
-
{showDoneButton ? (
|
|
584
|
-
<div className="mt-2 flex justify-end">
|
|
585
|
-
<button
|
|
586
|
-
type="button"
|
|
587
|
-
onClick={handleDone}
|
|
588
|
-
className={BUTTON_PRIMARY_SM}
|
|
589
|
-
>
|
|
590
|
-
Done
|
|
591
|
-
</button>
|
|
592
|
-
</div>
|
|
593
|
-
) : null}
|
|
594
568
|
</div>
|
|
595
569
|
);
|
|
596
570
|
|
|
@@ -61,10 +61,6 @@ const BUTTON_OUTLINE_SM = cn(
|
|
|
61
61
|
BUTTON_BASE,
|
|
62
62
|
"!h-9 !px-3 border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
63
63
|
);
|
|
64
|
-
const BUTTON_PRIMARY_SM = cn(
|
|
65
|
-
BUTTON_BASE,
|
|
66
|
-
"!h-9 !px-4 bg-primary text-primary-foreground hover:bg-primary/90",
|
|
67
|
-
);
|
|
68
64
|
const BUTTON_GHOST_ICON = cn(
|
|
69
65
|
BUTTON_BASE,
|
|
70
66
|
"!h-8 !w-8 !p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
|
@@ -171,18 +167,6 @@ export function ShareDialog({
|
|
|
171
167
|
? (embedTabContent ?? <DefaultEmbedBody controller={controller} />)
|
|
172
168
|
: null}
|
|
173
169
|
</div>
|
|
174
|
-
|
|
175
|
-
<div className="flex justify-end border-t border-border px-5 py-3">
|
|
176
|
-
<ActionButton
|
|
177
|
-
type="button"
|
|
178
|
-
intent="primary"
|
|
179
|
-
emphasis="solid"
|
|
180
|
-
onPress={controller.close}
|
|
181
|
-
className={BUTTON_PRIMARY_SM}
|
|
182
|
-
>
|
|
183
|
-
{controller.labels.done}
|
|
184
|
-
</ActionButton>
|
|
185
|
-
</div>
|
|
186
170
|
</DesignSystemDialog>
|
|
187
171
|
);
|
|
188
172
|
}
|
|
@@ -105,7 +105,6 @@ export interface ShareButtonController {
|
|
|
105
105
|
handleAdd: () => void;
|
|
106
106
|
handleChangeRole: (share: ShareButtonShare, role: ShareButtonRole) => void;
|
|
107
107
|
handleRemove: (share: ShareButtonShare) => void;
|
|
108
|
-
handleDone: () => void;
|
|
109
108
|
}
|
|
110
109
|
|
|
111
110
|
export function useShareButtonController(
|
|
@@ -547,11 +546,6 @@ export function useShareButtonController(
|
|
|
547
546
|
],
|
|
548
547
|
);
|
|
549
548
|
|
|
550
|
-
const handleDone = useCallback(() => {
|
|
551
|
-
if (canManage && inviteEmail.trim()) handleAdd();
|
|
552
|
-
handleOpenChange(false);
|
|
553
|
-
}, [canManage, handleAdd, handleOpenChange, inviteEmail]);
|
|
554
|
-
|
|
555
549
|
return {
|
|
556
550
|
open,
|
|
557
551
|
handleOpenChange,
|
|
@@ -585,7 +579,6 @@ export function useShareButtonController(
|
|
|
585
579
|
handleAdd,
|
|
586
580
|
handleChangeRole,
|
|
587
581
|
handleRemove,
|
|
588
|
-
handleDone,
|
|
589
582
|
};
|
|
590
583
|
}
|
|
591
584
|
|
|
@@ -71,7 +71,6 @@ export interface ShareDialogController {
|
|
|
71
71
|
tabs: Array<{ value: ShareDialogTab; label: string }>;
|
|
72
72
|
labels: {
|
|
73
73
|
close: string;
|
|
74
|
-
done: string;
|
|
75
74
|
shareOptions: string;
|
|
76
75
|
generalAccess: string;
|
|
77
76
|
shareLink: string;
|
|
@@ -407,7 +406,6 @@ export function useShareDialogController({
|
|
|
407
406
|
],
|
|
408
407
|
labels: {
|
|
409
408
|
close: t("share.close"),
|
|
410
|
-
done: t("share.done"),
|
|
411
409
|
shareOptions: t("share.shareOptions"),
|
|
412
410
|
generalAccess: t("share.generalAccess"),
|
|
413
411
|
shareLink: t("share.shareLink"),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ChatModelRunResult } from "@assistant-ui/react";
|
|
2
2
|
|
|
3
|
+
import type { A2AAgentActivitySnapshot } from "../a2a/activity.js";
|
|
3
4
|
import type { ActionChatUIConfig } from "../action-ui.js";
|
|
4
5
|
import {
|
|
5
6
|
LLM_MISSING_CREDENTIALS_ERROR_CODE,
|
|
@@ -74,6 +75,12 @@ export interface SSEEvent {
|
|
|
74
75
|
seq?: number;
|
|
75
76
|
agent?: string;
|
|
76
77
|
status?: string;
|
|
78
|
+
state?: string;
|
|
79
|
+
elapsedSeconds?: number;
|
|
80
|
+
detail?: string;
|
|
81
|
+
agentCallId?: string;
|
|
82
|
+
durationMs?: number;
|
|
83
|
+
snapshot?: A2AAgentActivitySnapshot;
|
|
77
84
|
reason?: string;
|
|
78
85
|
// Agent task fields
|
|
79
86
|
taskId?: string;
|
|
@@ -100,6 +107,12 @@ export type AgentAutoContinueReason =
|
|
|
100
107
|
|
|
101
108
|
export type AgentActivityTrailEntry = { label: string; tool?: string };
|
|
102
109
|
|
|
110
|
+
export interface AgentCallProgress {
|
|
111
|
+
state: string;
|
|
112
|
+
elapsedSeconds: number;
|
|
113
|
+
detail?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
103
116
|
export interface AgentAutoContinueErrorInfo {
|
|
104
117
|
message: string;
|
|
105
118
|
details?: string;
|
|
@@ -1365,7 +1378,7 @@ export function processEvent(
|
|
|
1365
1378
|
if (ev.type === "agent_call") {
|
|
1366
1379
|
const agentName = ev.agent ?? "agent";
|
|
1367
1380
|
if (ev.status === "start") {
|
|
1368
|
-
const toolCallId = `tc_${++toolCallCounter.value}`;
|
|
1381
|
+
const toolCallId = ev.agentCallId ?? `tc_${++toolCallCounter.value}`;
|
|
1369
1382
|
content.push({
|
|
1370
1383
|
type: "tool-call",
|
|
1371
1384
|
toolCallId,
|
|
@@ -1380,9 +1393,16 @@ export function processEvent(
|
|
|
1380
1393
|
if (
|
|
1381
1394
|
part.type === "tool-call" &&
|
|
1382
1395
|
part.toolName === `agent:${agentName}` &&
|
|
1396
|
+
(!ev.agentCallId || part.toolCallId === ev.agentCallId) &&
|
|
1383
1397
|
part.result === undefined
|
|
1384
1398
|
) {
|
|
1385
1399
|
part.result = ev.status === "error" ? "Error calling agent" : "Done";
|
|
1400
|
+
part.structuredMeta = {
|
|
1401
|
+
...part.structuredMeta,
|
|
1402
|
+
...(ev.durationMs != null
|
|
1403
|
+
? { agentDurationMs: ev.durationMs }
|
|
1404
|
+
: {}),
|
|
1405
|
+
};
|
|
1386
1406
|
break;
|
|
1387
1407
|
}
|
|
1388
1408
|
}
|
|
@@ -1401,6 +1421,7 @@ export function processEvent(
|
|
|
1401
1421
|
if (
|
|
1402
1422
|
part.type === "tool-call" &&
|
|
1403
1423
|
part.toolName === `agent:${agentName}` &&
|
|
1424
|
+
(!ev.agentCallId || part.toolCallId === ev.agentCallId) &&
|
|
1404
1425
|
part.result === undefined
|
|
1405
1426
|
) {
|
|
1406
1427
|
part.argsText += ev.text ?? "";
|
|
@@ -1413,6 +1434,69 @@ export function processEvent(
|
|
|
1413
1434
|
};
|
|
1414
1435
|
}
|
|
1415
1436
|
|
|
1437
|
+
if (ev.type === "agent_call_progress") {
|
|
1438
|
+
const agentName = ev.agent ?? "agent";
|
|
1439
|
+
if (typeof ev.state !== "string") {
|
|
1440
|
+
return { action: "continue" };
|
|
1441
|
+
}
|
|
1442
|
+
const elapsedSeconds =
|
|
1443
|
+
typeof ev.elapsedSeconds === "number" &&
|
|
1444
|
+
Number.isFinite(ev.elapsedSeconds) &&
|
|
1445
|
+
ev.elapsedSeconds >= 0
|
|
1446
|
+
? ev.elapsedSeconds
|
|
1447
|
+
: 0;
|
|
1448
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
1449
|
+
const part = content[i];
|
|
1450
|
+
if (
|
|
1451
|
+
part.type === "tool-call" &&
|
|
1452
|
+
part.toolName === `agent:${agentName}` &&
|
|
1453
|
+
(!ev.agentCallId || part.toolCallId === ev.agentCallId) &&
|
|
1454
|
+
part.result === undefined
|
|
1455
|
+
) {
|
|
1456
|
+
part.structuredMeta = {
|
|
1457
|
+
...part.structuredMeta,
|
|
1458
|
+
agentProgress: {
|
|
1459
|
+
state: ev.state,
|
|
1460
|
+
elapsedSeconds,
|
|
1461
|
+
...(ev.detail ? { detail: ev.detail } : {}),
|
|
1462
|
+
} satisfies AgentCallProgress,
|
|
1463
|
+
};
|
|
1464
|
+
break;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
return {
|
|
1468
|
+
action: "yield",
|
|
1469
|
+
result: { content: contentSnapshot(content) } as ChatModelRunResult,
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
if (ev.type === "agent_call_activity" && ev.snapshot) {
|
|
1474
|
+
const agentName = ev.agent ?? "agent";
|
|
1475
|
+
for (let i = content.length - 1; i >= 0; i--) {
|
|
1476
|
+
const part = content[i];
|
|
1477
|
+
if (
|
|
1478
|
+
part.type === "tool-call" &&
|
|
1479
|
+
part.toolName === `agent:${agentName}` &&
|
|
1480
|
+
(!ev.agentCallId || part.toolCallId === ev.agentCallId)
|
|
1481
|
+
) {
|
|
1482
|
+
const previous = part.structuredMeta?.agentActivity as
|
|
1483
|
+
| A2AAgentActivitySnapshot
|
|
1484
|
+
| undefined;
|
|
1485
|
+
if (!previous || ev.snapshot.sequence >= previous.sequence) {
|
|
1486
|
+
part.structuredMeta = {
|
|
1487
|
+
...part.structuredMeta,
|
|
1488
|
+
agentActivity: ev.snapshot,
|
|
1489
|
+
};
|
|
1490
|
+
}
|
|
1491
|
+
break;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
return {
|
|
1495
|
+
action: "yield",
|
|
1496
|
+
result: { content: contentSnapshot(content) } as ChatModelRunResult,
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1416
1500
|
// ─── Agent task events (sub-agent chips) ─────────────────────────
|
|
1417
1501
|
// These events are dispatched as CustomEvents so AgentTaskCard components
|
|
1418
1502
|
// can listen for updates to their specific taskId.
|
|
@@ -62,6 +62,15 @@
|
|
|
62
62
|
* mismatch.
|
|
63
63
|
*/
|
|
64
64
|
|
|
65
|
+
import {
|
|
66
|
+
cssBlendMode,
|
|
67
|
+
gradientAngleDegrees as gradientAngleDegreesMath,
|
|
68
|
+
remapLinearStopPosition as remapLinearStopPositionMath,
|
|
69
|
+
resolveGradientHandles,
|
|
70
|
+
vectorLength,
|
|
71
|
+
type GradientHandles,
|
|
72
|
+
} from "./figma-paint-math.js";
|
|
73
|
+
|
|
65
74
|
export interface FigmaColor {
|
|
66
75
|
r: number;
|
|
67
76
|
g: number;
|
|
@@ -422,16 +431,8 @@ class FidelityTracker {
|
|
|
422
431
|
// Gradient angle / position derivation
|
|
423
432
|
// ---------------------------------------------------------------------------
|
|
424
433
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
end: { x: number; y: number };
|
|
428
|
-
width: { x: number; y: number };
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
function resolveGradientGeometry(paint: FigmaPaint): GradientGeometry | null {
|
|
432
|
-
const handles = paint.gradientHandlePositions;
|
|
433
|
-
if (!handles || handles.length < 3) return null;
|
|
434
|
-
return { start: handles[0]!, end: handles[1]!, width: handles[2]! };
|
|
434
|
+
function resolveGradientGeometry(paint: FigmaPaint): GradientHandles | null {
|
|
435
|
+
return resolveGradientHandles(paint.gradientHandlePositions);
|
|
435
436
|
}
|
|
436
437
|
|
|
437
438
|
/**
|
|
@@ -453,13 +454,7 @@ export function gradientAngleDegrees(
|
|
|
453
454
|
paint: FigmaPaint,
|
|
454
455
|
box: { width: number; height: number },
|
|
455
456
|
): number | null {
|
|
456
|
-
|
|
457
|
-
if (!geometry) return null;
|
|
458
|
-
const dx = (geometry.end.x - geometry.start.x) * box.width;
|
|
459
|
-
const dy = (geometry.end.y - geometry.start.y) * box.height;
|
|
460
|
-
const angleRad = Math.atan2(dy, dx);
|
|
461
|
-
const angleDeg = (angleRad * 180) / Math.PI + 90;
|
|
462
|
-
return ((angleDeg % 360) + 360) % 360;
|
|
457
|
+
return gradientAngleDegreesMath(paint, box);
|
|
463
458
|
}
|
|
464
459
|
|
|
465
460
|
function gradientStopsCss(
|
|
@@ -478,59 +473,12 @@ function gradientStopsCss(
|
|
|
478
473
|
.join(", ");
|
|
479
474
|
}
|
|
480
475
|
|
|
481
|
-
/**
|
|
482
|
-
* CSS `linear-gradient(angle, ...)` always stretches its 0%/100% stops
|
|
483
|
-
* across the box's FULL diagonal extent at that angle (the CSS spec's
|
|
484
|
-
* "gradient line" always spans corner-to-corner) -- it has no way to say
|
|
485
|
-
* "start partway in, end partway in" the way Figma's actual gradient handles
|
|
486
|
-
* can (a designer can drag the start/end handles anywhere, including short
|
|
487
|
-
* of the shape's edges, or past them). Figma's own stop positions are
|
|
488
|
-
* fractions of the literal start-handle-to-end-handle distance, which only
|
|
489
|
-
* happens to coincide with the CSS full-box span when the handles are
|
|
490
|
-
* dragged exactly corner-to-corner -- a common case, but far from the only
|
|
491
|
-
* one, and the divergence gets worse the more the box's aspect ratio departs
|
|
492
|
-
* from square (rotated/skewed handles included, e.g. gradientTransform-authored
|
|
493
|
-
* paints). This projects each Figma stop's real pixel position onto the same
|
|
494
|
-
* angle CSS will use and re-expresses it as a percentage of the CSS line's
|
|
495
|
-
* length, so a partial/offset gradient renders at the same actual pixel
|
|
496
|
-
* positions Figma draws it at instead of silently stretching to fill the box.
|
|
497
|
-
*/
|
|
498
476
|
function remapLinearStopPosition(
|
|
499
|
-
geometry:
|
|
477
|
+
geometry: GradientHandles,
|
|
500
478
|
box: { width: number; height: number },
|
|
501
479
|
angleDeg: number,
|
|
502
480
|
): (position: number) => number {
|
|
503
|
-
|
|
504
|
-
const ux = Math.sin(angleRad);
|
|
505
|
-
const uy = -Math.cos(angleRad);
|
|
506
|
-
const lineLength = box.width * Math.abs(ux) + box.height * Math.abs(uy);
|
|
507
|
-
if (lineLength < 1e-6) return (position) => position;
|
|
508
|
-
const startPx = {
|
|
509
|
-
x: geometry.start.x * box.width,
|
|
510
|
-
y: geometry.start.y * box.height,
|
|
511
|
-
};
|
|
512
|
-
const endPx = {
|
|
513
|
-
x: geometry.end.x * box.width,
|
|
514
|
-
y: geometry.end.y * box.height,
|
|
515
|
-
};
|
|
516
|
-
const centerX = box.width / 2;
|
|
517
|
-
const centerY = box.height / 2;
|
|
518
|
-
return (position: number) => {
|
|
519
|
-
const pointX = startPx.x + position * (endPx.x - startPx.x);
|
|
520
|
-
const pointY = startPx.y + position * (endPx.y - startPx.y);
|
|
521
|
-
const projected = (pointX - centerX) * ux + (pointY - centerY) * uy;
|
|
522
|
-
return (projected + lineLength / 2) / lineLength;
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function vectorLength(
|
|
527
|
-
from: { x: number; y: number },
|
|
528
|
-
to: { x: number; y: number },
|
|
529
|
-
box: { width: number; height: number },
|
|
530
|
-
): number {
|
|
531
|
-
const dx = (to.x - from.x) * box.width;
|
|
532
|
-
const dy = (to.y - from.y) * box.height;
|
|
533
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
481
|
+
return remapLinearStopPositionMath(geometry, box, angleDeg);
|
|
534
482
|
}
|
|
535
483
|
|
|
536
484
|
/**
|
|
@@ -960,49 +908,22 @@ function buildEffects(
|
|
|
960
908
|
// Blend modes
|
|
961
909
|
// ---------------------------------------------------------------------------
|
|
962
910
|
|
|
963
|
-
const CSS_BLEND_MODES = new Set([
|
|
964
|
-
"multiply",
|
|
965
|
-
"screen",
|
|
966
|
-
"overlay",
|
|
967
|
-
"darken",
|
|
968
|
-
"lighten",
|
|
969
|
-
"color-dodge",
|
|
970
|
-
"color-burn",
|
|
971
|
-
"hard-light",
|
|
972
|
-
"soft-light",
|
|
973
|
-
"difference",
|
|
974
|
-
"exclusion",
|
|
975
|
-
"hue",
|
|
976
|
-
"saturation",
|
|
977
|
-
"color",
|
|
978
|
-
"luminosity",
|
|
979
|
-
]);
|
|
980
|
-
|
|
981
|
-
const FIGMA_ONLY_BLEND_MODE_FALLBACK: Record<string, string> = {
|
|
982
|
-
LINEAR_BURN: "multiply",
|
|
983
|
-
LINEAR_DODGE: "plus-lighter",
|
|
984
|
-
LIGHTER: "plus-lighter",
|
|
985
|
-
DARKER: "darken",
|
|
986
|
-
};
|
|
987
|
-
|
|
988
911
|
function buildBlendMode(
|
|
989
912
|
node: FigmaNode,
|
|
990
913
|
tracker: FidelityTracker,
|
|
991
914
|
): string | undefined {
|
|
992
915
|
const mode = node.blendMode;
|
|
993
|
-
if (!mode
|
|
994
|
-
const
|
|
995
|
-
if (
|
|
996
|
-
|
|
997
|
-
if (fallback) {
|
|
916
|
+
if (!mode) return undefined;
|
|
917
|
+
const result = cssBlendMode(mode);
|
|
918
|
+
if (!result) return undefined;
|
|
919
|
+
if (result.verdict === "approximated") {
|
|
998
920
|
tracker.record(
|
|
999
921
|
node,
|
|
1000
922
|
"approximated",
|
|
1001
|
-
`Figma blend mode "${mode}" has no CSS equivalent; approximated as mix-blend-mode: ${
|
|
923
|
+
`Figma blend mode "${mode}" has no CSS equivalent; approximated as mix-blend-mode: ${result.cssMode}.`,
|
|
1002
924
|
);
|
|
1003
|
-
return fallback;
|
|
1004
925
|
}
|
|
1005
|
-
return
|
|
926
|
+
return result.cssMode;
|
|
1006
927
|
}
|
|
1007
928
|
|
|
1008
929
|
// ---------------------------------------------------------------------------
|