@agent-native/core 0.196.0-nightly-20260928165326 → 0.196.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.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/CHANGELOG.md +17 -0
- package/corpus/templates/assets/CHANGELOG.md +18 -0
- package/corpus/templates/brain/CHANGELOG.md +6 -0
- package/corpus/templates/calendar/CHANGELOG.md +4 -0
- package/corpus/templates/clips/CHANGELOG.md +19 -0
- package/corpus/templates/clips/actions/create-recording-agent-link.ts +8 -2
- package/corpus/templates/clips/actions/update-recording.ts +5 -1
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +10 -3
- package/corpus/templates/clips/changelog/2026-09-28-agent-links-stay-valid-when-clip-details-change.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-28-password-changes-immediately-invalidate-old-recording-links.md +6 -0
- package/corpus/templates/clips/changelog/2026-09-28-password-protected-recording-links-stop-working-when-the-pas.md +6 -0
- package/corpus/templates/clips/server/db/schema.ts +3 -0
- package/corpus/templates/clips/server/lib/player-video-url.ts +9 -1
- package/corpus/templates/clips/server/lib/public-agent-context.ts +12 -4
- package/corpus/templates/clips/server/lib/share-password.ts +25 -0
- package/corpus/templates/clips/server/plugins/db.ts +36 -0
- package/corpus/templates/clips/server/routes/[...page].get.ts +8 -1
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +33 -6
- package/corpus/templates/clips/server/routes/api/thumbnail/[recordingId].get.ts +34 -6
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +26 -5
- package/corpus/templates/content/CHANGELOG.md +1 -0
- package/corpus/templates/crm/CHANGELOG.md +12 -0
- package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +265 -3
- package/corpus/templates/design/CHANGELOG.md +21 -0
- package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +463 -6
- package/corpus/templates/design/app/pages/Index.tsx +1 -1
- package/corpus/templates/design/changelog/2026-09-27-auto-focused-app-fields-no-longer-interrupt-canvas-shortcuts.md +6 -0
- package/corpus/templates/design/changelog/2026-09-28-model-picker-loads-available-models.md +6 -0
- package/corpus/templates/design/changelog/2026-09-28-template-menus-stay-available-on-hover.md +6 -0
- package/corpus/templates/dispatch/CHANGELOG.md +18 -0
- package/corpus/templates/forms/CHANGELOG.md +6 -0
- package/corpus/templates/mail/.env.example +1 -1
- package/corpus/templates/mail/CHANGELOG.md +33 -0
- package/corpus/templates/mail/changelog/2026-09-28-fixed-inbox-loading-stalls-and-showed-progress-during-google-2.md +6 -0
- package/corpus/templates/mail/changelog/2026-09-28-fixed-inbox-loading-stalls-and-showed-progress-during-google.md +6 -0
- package/corpus/templates/mail/server/db/schema.ts +7 -0
- package/corpus/templates/mail/server/lib/ai-filter-backfill.ts +4 -0
- package/corpus/templates/mail/server/lib/jobs.ts +5 -2
- package/corpus/templates/mail/server/plugins/db.ts +16 -0
- package/corpus/templates/mail/server/plugins/mail-jobs.ts +355 -44
- package/corpus/templates/slides/CHANGELOG.md +28 -0
- package/corpus/templates/slides/app/pages/Index.tsx +1 -1
- package/corpus/templates/slides/changelog/2026-09-28-model-picker-loads-available-models.md +6 -0
- package/corpus/templates/slides/changelog/2026-09-28-template-menus-stay-available-on-hover.md +6 -0
- package/dist/client/auth/AuthPage.js +3 -2
- package/dist/client/org/OrgSwitcher.js +37 -25
- package/dist/client/settings/UsageSection.js +3 -3
- package/dist/client/use-action.js +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/jobs/background-automation-runner.d.ts +2 -0
- package/dist/jobs/background-automation-runner.js +20 -1
- package/dist/jobs/sweep-hooks.d.ts +6 -2
- package/dist/jobs/sweep-hooks.js +17 -9
- package/dist/localization/core-messages/ar-SA.js +2 -2
- package/dist/localization/core-messages/de-DE.js +2 -2
- package/dist/localization/core-messages/en-US.d.ts +2 -2
- package/dist/localization/core-messages/en-US.js +2 -2
- package/dist/localization/core-messages/es-ES.js +2 -2
- package/dist/localization/core-messages/fr-FR.js +2 -2
- package/dist/localization/core-messages/hi-IN.js +2 -2
- package/dist/localization/core-messages/ja-JP.js +2 -2
- package/dist/localization/core-messages/ko-KR.js +2 -2
- package/dist/localization/core-messages/pt-BR.js +2 -2
- package/dist/localization/core-messages/zh-CN.js +2 -2
- package/dist/localization/core-messages/zh-TW.js +2 -2
- package/dist/localization/core-messages.d.ts +2 -2
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +6 -6
- package/dist/org/handlers.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +7 -7
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +4 -4
- package/dist/server/agent-chat-plugin.js +6 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/index.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/triggers/dispatcher.js +167 -36
- package/dist/triggers/event-queue.d.ts +18 -1
- package/dist/triggers/event-queue.js +143 -10
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { ActionButton, Avatar, TextField, } from "@agent-native/toolkit/design-system";
|
|
3
3
|
import { ResourceIcon } from "@agent-native/toolkit/icons";
|
|
4
|
-
import { IconArrowUpRight, IconBriefcase, IconChartBar, IconCheck, IconChevronLeft, IconChevronRight, IconDownload, IconExternalLink, IconAlertCircle, IconKey, IconLoader2, IconLogout, IconPlus, IconPresentation, IconSelector, IconSettings,
|
|
4
|
+
import { IconArrowUpRight, IconBriefcase, IconChartBar, IconCheck, IconChevronLeft, IconChevronRight, IconDownload, IconExternalLink, IconAlertCircle, IconKey, IconLoader2, IconLogout, IconPlus, IconPresentation, IconSelector, IconSettings, IconUsersGroup, } from "@tabler/icons-react";
|
|
5
5
|
import { useEffect, useMemo, useRef, useState, } from "react";
|
|
6
6
|
import { Link, useNavigate } from "react-router";
|
|
7
7
|
import { setBrowserDemoModeEnabled } from "../../demo/browser-state.js";
|
|
@@ -32,9 +32,9 @@ export function BuilderCreditNotice({ compact = false, className, }) {
|
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
34
|
const quotaLabel = builderCreditStatus.data.period === "daily"
|
|
35
|
-
? t("agentChat.usage.
|
|
35
|
+
? t("agentChat.usage.dailyDefaultLimit")
|
|
36
36
|
: builderCreditStatus.data.period === "monthly"
|
|
37
|
-
? t("agentChat.usage.
|
|
37
|
+
? t("agentChat.usage.monthlyLimit")
|
|
38
38
|
: null;
|
|
39
39
|
const title = [t("agentChat.billing.builderCreditLimitTitle"), quotaLabel]
|
|
40
40
|
.filter((label) => label !== null)
|
|
@@ -71,11 +71,11 @@ const ITEM_ICON_CLASS = "size-3.5 shrink-0 text-muted-foreground";
|
|
|
71
71
|
const TRIGGER_CLASS = "flex w-full min-w-0 items-center gap-2 rounded-md border-0 bg-transparent px-1.5 py-1 text-start text-foreground hover:bg-accent/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-60 data-[state=open]:bg-accent/60 cursor-pointer";
|
|
72
72
|
const COMPACT_TRIGGER_CLASS = "flex items-center justify-center rounded-md border-0 bg-transparent p-1 text-foreground hover:bg-accent/60 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-60 data-[state=open]:bg-accent/60 cursor-pointer";
|
|
73
73
|
const AVATAR_CLASS = "shrink-0 rounded-full border border-border bg-accent text-[11px] font-semibold text-muted-foreground";
|
|
74
|
-
function ReservedOrgSwitcherSpace({ className }) {
|
|
75
|
-
return _jsx("div", { "aria-hidden": "true", className:
|
|
74
|
+
function ReservedOrgSwitcherSpace({ className, compact, }) {
|
|
75
|
+
return (_jsx("div", { "aria-hidden": "true", className: cn("h-8", !compact && "flex-1", className) }));
|
|
76
76
|
}
|
|
77
77
|
function OrgSwitcherLoadingPlaceholder({ className, compact, label, }) {
|
|
78
|
-
return (_jsx("button", { type: "button", disabled: true, "aria-label": label, className: cn(compact ? COMPACT_TRIGGER_CLASS : TRIGGER_CLASS, "animate-pulse", className), children: compact ? (_jsx("span", { className: "size-6 rounded-full bg-muted-foreground/20" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "size-7 shrink-0 rounded-full bg-muted-foreground/20" }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [_jsx("span", { className: "h-3 w-3/4 rounded-sm bg-muted-foreground/20" }), _jsx("span", { className: "h-2.5 w-1/2 rounded-sm bg-muted-foreground/15" })] }), _jsx(IconSelector, { className: "size-3.5 shrink-0 opacity-30" })] })) }));
|
|
78
|
+
return (_jsx("button", { type: "button", disabled: true, "aria-label": label, className: cn(compact ? COMPACT_TRIGGER_CLASS : TRIGGER_CLASS, !compact && "flex-1", "animate-pulse", className), children: compact ? (_jsx("span", { className: "size-6 rounded-full bg-muted-foreground/20" })) : (_jsxs(_Fragment, { children: [_jsx("span", { className: "size-7 shrink-0 rounded-full bg-muted-foreground/20" }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [_jsx("span", { className: "h-3 w-3/4 rounded-sm bg-muted-foreground/20" }), _jsx("span", { className: "h-2.5 w-1/2 rounded-sm bg-muted-foreground/15" })] }), _jsx(IconSelector, { className: "size-3.5 shrink-0 opacity-30" })] })) }));
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
81
|
* Account menu for app sidebars. The trigger shows the signed-in person's
|
|
@@ -84,7 +84,7 @@ function OrgSwitcherLoadingPlaceholder({ className, compact, label, }) {
|
|
|
84
84
|
* downloads, and Log out. Renders nothing in dev / no-auth mode.
|
|
85
85
|
*/
|
|
86
86
|
export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact, hideBuilderCreditNotice, utilityLinks, }) {
|
|
87
|
-
const { data: org, isLoading } = useOrg();
|
|
87
|
+
const { data: org, isLoading, dataUpdatedAt } = useOrg();
|
|
88
88
|
const { session } = useSession();
|
|
89
89
|
const { enabled: demoModeEnabled } = useDemoModeStatus();
|
|
90
90
|
const t = useT();
|
|
@@ -115,6 +115,25 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact,
|
|
|
115
115
|
?.querySelector('[role="menuitem"]:not([data-disabled])')
|
|
116
116
|
?.focus();
|
|
117
117
|
}, [view]);
|
|
118
|
+
// Accounts that picked the retired "Personal" choice have `orgId: null`
|
|
119
|
+
// stored while still holding memberships, which strands them outside the
|
|
120
|
+
// org-scoped Builder.io connection and vault credentials. Move them back.
|
|
121
|
+
// A failed switch retries on the next org fetch, not on the next render:
|
|
122
|
+
// the mutation's state changes would otherwise re-run this in a tight loop.
|
|
123
|
+
const personalRecoveryRef = useRef(false);
|
|
124
|
+
const firstMembershipId = org?.orgs?.[0]?.orgId ?? null;
|
|
125
|
+
const switchOrgMutate = switchOrg.mutate;
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (org?.orgId || !firstMembershipId || personalRecoveryRef.current) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
personalRecoveryRef.current = true;
|
|
131
|
+
switchOrgMutate(firstMembershipId, {
|
|
132
|
+
onError: () => {
|
|
133
|
+
personalRecoveryRef.current = false;
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}, [org?.orgId, firstMembershipId, switchOrgMutate, dataUpdatedAt]);
|
|
118
137
|
const showView = (next) => {
|
|
119
138
|
viewChangedRef.current = true;
|
|
120
139
|
setView(next);
|
|
@@ -152,13 +171,13 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact,
|
|
|
152
171
|
const orgCount = orgs.length;
|
|
153
172
|
const hasAny = orgCount > 0 || pendingInvitations.length > 0 || domainMatches.length > 0;
|
|
154
173
|
if (!hasAny && !org.email) {
|
|
155
|
-
return reserveSpace ? (_jsx(ReservedOrgSwitcherSpace, { className: className })) : null;
|
|
174
|
+
return reserveSpace ? (_jsx(ReservedOrgSwitcherSpace, { className: className, compact: compact })) : null;
|
|
156
175
|
}
|
|
157
176
|
if (hideWhenSingle &&
|
|
158
177
|
orgCount < 2 &&
|
|
159
178
|
pendingInvitations.length === 0 &&
|
|
160
179
|
domainMatches.length === 0) {
|
|
161
|
-
return reserveSpace ? (_jsx(ReservedOrgSwitcherSpace, { className: className })) : null;
|
|
180
|
+
return reserveSpace ? (_jsx(ReservedOrgSwitcherSpace, { className: className, compact: compact })) : null;
|
|
162
181
|
}
|
|
163
182
|
const inOrg = !!org.orgId;
|
|
164
183
|
const organizationLabel = org.orgName ?? t("agentChat.accountMenu.personal");
|
|
@@ -187,29 +206,22 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact,
|
|
|
187
206
|
const avatar = (_jsx(Avatar, { name: displayName, src: avatarUrl, fallback: initials(displayName), className: cn(AVATAR_CLASS, compact ? "size-6" : "size-7") }));
|
|
188
207
|
const trigger = compact ? (_jsx("button", { type: "button", "aria-label": triggerLabel, className: cn(COMPACT_TRIGGER_CLASS, className), children: avatar })) : (_jsxs("button", { type: "button", "aria-label": triggerLabel, className: cn(TRIGGER_CLASS, className), children: [avatar, _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx("span", { className: "truncate text-[13px] font-medium leading-tight", children: displayName }), _jsxs("span", { className: "flex min-w-0 items-center gap-1 text-xs leading-tight text-muted-foreground", children: [inOrg && org.icon ? (_jsx(ResourceIcon, { value: org.icon, size: 12, resolveImageUrl: (image) => image.authority === "url" ? image.assetId : undefined, fallback: _jsx(IconBriefcase, { className: "size-3 shrink-0" }) })) : null, _jsx("span", { className: "truncate", children: organizationLabel }), demoModeEnabled && (_jsxs("span", { className: "inline-flex shrink-0 items-center gap-0.5 rounded-full bg-primary/10 px-1.5 text-[10px] font-medium text-primary", children: [_jsx(IconPresentation, { className: "size-3", "aria-hidden": "true" }), t("agentChat.accountMenu.demoMode")] }))] })] }), _jsx(IconSelector, { className: "size-3.5 shrink-0 text-muted-foreground" })] }));
|
|
189
208
|
const selectOrg = (orgId) => {
|
|
190
|
-
if (orgId ===
|
|
209
|
+
if (orgId === org.orgId) {
|
|
191
210
|
setOpen(false);
|
|
192
211
|
return;
|
|
193
212
|
}
|
|
194
|
-
// `null` switches to Personal, which the server stores as an explicit
|
|
195
|
-
// choice rather than falling back to the first membership.
|
|
196
213
|
switchOrg.mutate(orgId, { onSuccess: () => setOpen(false) });
|
|
197
214
|
};
|
|
198
215
|
const isSwitchingTo = (orgId) => switchOrg.isPending && switchOrg.variables === orgId;
|
|
199
|
-
const mainItems = (_jsxs(_Fragment, { children: [!demoModeEnabled && org.email ? (_jsx(DropdownMenuLabel, { className: "truncate text-xs font-normal text-muted-foreground", children: org.email })) : null, demoModeEnabled && (_jsxs(_Fragment, { children: [_jsxs("div", { role: "status", className: "mx-1 mb-1 rounded-md border border-primary/20 bg-primary/5 px-2 py-1.5 text-[11px]", children: [_jsxs("div", { className: "flex items-center gap-1.5 font-medium text-primary", children: [_jsx(IconPresentation, { className: "size-3.5 shrink-0", "aria-hidden": "true" }), t("agentChat.accountMenu.demoModeOn")] }), _jsx("p", { className: "mt-0.5 leading-snug text-muted-foreground", children: t("agentChat.accountMenu.demoModeDescription") })] }), _jsxs(DropdownMenuItem, { className: ITEM_CLASS, onSelect: () => setBrowserDemoModeEnabled(false), children: [_jsx(IconPresentation, { className: ITEM_ICON_CLASS }), _jsx("span", { className: "flex-1", children: t("agentChat.accountMenu.turnOffDemoMode") })] }), _jsx(DropdownMenuSeparator, {})] })),
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return;
|
|
204
|
-
event.preventDefault();
|
|
205
|
-
selectOrg(o.orgId);
|
|
206
|
-
}, children: [_jsx(ResourceIcon, { value: o.icon, size: 14, resolveImageUrl: (image) => image.authority === "url" ? image.assetId : undefined, fallback: _jsx(IconBriefcase, { className: ITEM_ICON_CLASS }) }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: o.orgName }), isSwitchingTo(o.orgId) ? (_jsx(IconLoader2, { className: cn(ITEM_ICON_CLASS, "animate-spin") })) : current ? (_jsx(IconCheck, { className: ITEM_ICON_CLASS })) : null] }, o.orgId));
|
|
207
|
-
}), _jsxs(DropdownMenuItem, { className: ITEM_CLASS, disabled: switchOrg.isPending && inOrg, onSelect: (event) => {
|
|
208
|
-
if (!inOrg)
|
|
216
|
+
const mainItems = (_jsxs(_Fragment, { children: [!demoModeEnabled && org.email ? (_jsx(DropdownMenuLabel, { className: "truncate text-xs font-normal text-muted-foreground", children: org.email })) : null, demoModeEnabled && (_jsxs(_Fragment, { children: [_jsxs("div", { role: "status", className: "mx-1 mb-1 rounded-md border border-primary/20 bg-primary/5 px-2 py-1.5 text-[11px]", children: [_jsxs("div", { className: "flex items-center gap-1.5 font-medium text-primary", children: [_jsx(IconPresentation, { className: "size-3.5 shrink-0", "aria-hidden": "true" }), t("agentChat.accountMenu.demoModeOn")] }), _jsx("p", { className: "mt-0.5 leading-snug text-muted-foreground", children: t("agentChat.accountMenu.demoModeDescription") })] }), _jsxs(DropdownMenuItem, { className: ITEM_CLASS, onSelect: () => setBrowserDemoModeEnabled(false), children: [_jsx(IconPresentation, { className: ITEM_ICON_CLASS }), _jsx("span", { className: "flex-1", children: t("agentChat.accountMenu.turnOffDemoMode") })] }), _jsx(DropdownMenuSeparator, {})] })), _jsx(DropdownMenuGroup, { children: orgs.map((o) => {
|
|
217
|
+
const current = o.orgId === org.orgId;
|
|
218
|
+
return (_jsxs(DropdownMenuItem, { className: ITEM_CLASS, disabled: switchOrg.isPending && !current, onSelect: (event) => {
|
|
219
|
+
if (current)
|
|
209
220
|
return;
|
|
210
221
|
event.preventDefault();
|
|
211
|
-
selectOrg(
|
|
212
|
-
}, children: [_jsx(
|
|
222
|
+
selectOrg(o.orgId);
|
|
223
|
+
}, children: [_jsx(ResourceIcon, { value: o.icon, size: 14, resolveImageUrl: (image) => image.authority === "url" ? image.assetId : undefined, fallback: _jsx(IconBriefcase, { className: ITEM_ICON_CLASS }) }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: o.orgName }), isSwitchingTo(o.orgId) ? (_jsx(IconLoader2, { className: cn(ITEM_ICON_CLASS, "animate-spin") })) : current ? (_jsx(IconCheck, { className: ITEM_ICON_CLASS })) : null] }, o.orgId));
|
|
224
|
+
}) }), pendingInvitations.length > 0 && (_jsxs(DropdownMenuGroup, { children: [_jsx(DropdownMenuLabel, { className: "pb-0.5 text-[11px] font-normal text-muted-foreground", children: t("agentChat.accountMenu.invitations") }), pendingInvitations.map((inv) => (_jsxs(DropdownMenuItem, { className: cn(ITEM_CLASS, "flex-col items-stretch gap-1"), disabled: acceptInvitation.isPending, onSelect: (event) => {
|
|
213
225
|
event.preventDefault();
|
|
214
226
|
acceptInvitation.mutate(inv.id, {
|
|
215
227
|
onSuccess: () => setOpen(false),
|
|
@@ -245,7 +257,7 @@ export function OrgSwitcher({ className, hideWhenSingle, reserveSpace, compact,
|
|
|
245
257
|
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: "flex size-3.5 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-3.5", children: link.icon ?? _jsx(IconExternalLink, {}) }), _jsx("span", { className: "flex-1", children: link.label }), link.external && (_jsx(IconArrowUpRight, { className: cn(ITEM_ICON_CLASS, "rtl:-scale-x-100") }))] }));
|
|
246
258
|
return (_jsx(DropdownMenuItem, { asChild: true, className: ITEM_CLASS, children: link.external ? (_jsx("a", { href: link.href, target: "_blank", rel: "noopener noreferrer", children: content })) : (_jsx(Link, { to: link.href, children: content })) }, link.id));
|
|
247
259
|
}) })] }));
|
|
248
|
-
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: cn("flex min-w-0 flex-col gap-1.5", compact && "items-center"), children: [!hideBuilderCreditNotice && _jsx(BuilderCreditNotice, { compact: compact }), _jsxs(DropdownMenu, { open: open, onOpenChange: handleOpenChange, children: [compact ? (_jsx(TooltipProvider, { delayDuration: 0, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: trigger }) }), _jsxs(TooltipContent, { side: "right", children: [_jsx("span", { className: "block font-medium", children: displayName }), _jsx("span", { className: "block opacity-70", children: organizationLabel })] })] }) })) : (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsx(DropdownMenuContent, { ref: contentRef, side: "top", align: "start", sideOffset: 6, collisionPadding: 12, "aria-label": t("agentChat.accountMenu.label"), className: "w-[max(15.5rem,var(--radix-dropdown-menu-trigger-width))] max-w-[calc(100vw-1.5rem)]", onCloseAutoFocus: (event) => {
|
|
260
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: cn("flex min-w-0 flex-col gap-1.5", !compact && "flex-1", compact && "items-center"), children: [!hideBuilderCreditNotice && _jsx(BuilderCreditNotice, { compact: compact }), _jsxs(DropdownMenu, { open: open, onOpenChange: handleOpenChange, children: [compact ? (_jsx(TooltipProvider, { delayDuration: 0, children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: trigger }) }), _jsxs(TooltipContent, { side: "right", children: [_jsx("span", { className: "block font-medium", children: displayName }), _jsx("span", { className: "block opacity-70", children: organizationLabel })] })] }) })) : (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsx(DropdownMenuContent, { ref: contentRef, side: "top", align: "start", sideOffset: 6, collisionPadding: 12, "aria-label": t("agentChat.accountMenu.label"), className: "w-[max(15.5rem,var(--radix-dropdown-menu-trigger-width))] max-w-[calc(100vw-1.5rem)]", onCloseAutoFocus: (event) => {
|
|
249
261
|
if (!openingDialogRef.current)
|
|
250
262
|
return;
|
|
251
263
|
openingDialogRef.current = false;
|
|
@@ -175,10 +175,10 @@ export function BuilderCreditUsageSkeleton() {
|
|
|
175
175
|
export function BuilderCreditUsagePanel({ usage, }) {
|
|
176
176
|
const t = useT();
|
|
177
177
|
const quotaLabel = usage.quota.period === "daily"
|
|
178
|
-
? t("agentChat.usage.
|
|
179
|
-
defaultValue: "
|
|
178
|
+
? t("agentChat.usage.dailyDefaultLimit", {
|
|
179
|
+
defaultValue: "Default daily limit",
|
|
180
180
|
})
|
|
181
|
-
: t("agentChat.usage.
|
|
181
|
+
: t("agentChat.usage.monthlyLimit", { defaultValue: "Monthly limit" });
|
|
182
182
|
const canAddCredits = usage.quota.remaining === 0;
|
|
183
183
|
const used = usage.quota.used.toLocaleString(undefined, {
|
|
184
184
|
maximumFractionDigits: 2,
|
|
@@ -20,7 +20,7 @@ function isActionTimeout(error) {
|
|
|
20
20
|
error.timedOut === true);
|
|
21
21
|
}
|
|
22
22
|
function isRetryableActionStatus(status) {
|
|
23
|
-
return status === 429 || status === 502 || status === 503
|
|
23
|
+
return status === 429 || status === 502 || status === 503;
|
|
24
24
|
}
|
|
25
25
|
function actionErrorStatus(error) {
|
|
26
26
|
const status = error?.status;
|
|
@@ -38,19 +38,19 @@ export declare const postAwareness: import("h3").EventHandlerWithFetch<import("h
|
|
|
38
38
|
error: string;
|
|
39
39
|
states?: undefined;
|
|
40
40
|
} | {
|
|
41
|
+
error?: undefined;
|
|
41
42
|
states: {
|
|
42
43
|
clientId: number;
|
|
43
44
|
state: string;
|
|
44
45
|
}[];
|
|
45
|
-
error?: undefined;
|
|
46
46
|
}>>;
|
|
47
47
|
export declare const getActiveUsers: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
48
48
|
error: string;
|
|
49
49
|
users?: undefined;
|
|
50
50
|
} | {
|
|
51
|
+
error?: undefined;
|
|
51
52
|
users: {
|
|
52
53
|
clientId: number;
|
|
53
54
|
lastSeen: number;
|
|
54
55
|
}[];
|
|
55
|
-
error?: undefined;
|
|
56
56
|
}>>;
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
8
8
|
state: string;
|
|
9
9
|
}>>;
|
|
10
10
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
11
|
-
error: string;
|
|
12
11
|
ok?: undefined;
|
|
12
|
+
error: string;
|
|
13
13
|
} | {
|
|
14
14
|
error?: undefined;
|
|
15
15
|
ok: boolean;
|
|
@@ -38,6 +38,8 @@ export interface BackgroundAutomationRunOptions {
|
|
|
38
38
|
actionCaller?: ActionCaller;
|
|
39
39
|
actionAutomation?: ActionAutomationContext;
|
|
40
40
|
historyId?: string;
|
|
41
|
+
hardTimeoutMs?: number;
|
|
42
|
+
hardDeadlineAt?: number;
|
|
41
43
|
noProgressTimeoutMs?: number;
|
|
42
44
|
backgroundNoProgressTimeoutMs?: number;
|
|
43
45
|
}
|
|
@@ -140,6 +140,11 @@ export function backgroundRunCutOffReason(run) {
|
|
|
140
140
|
function uniqueToolNames(names) {
|
|
141
141
|
return [...new Set(names)];
|
|
142
142
|
}
|
|
143
|
+
function assertHardDeadline(deadlineAt) {
|
|
144
|
+
if (deadlineAt !== undefined && Date.now() >= deadlineAt) {
|
|
145
|
+
throw new BackgroundAutomationRunError("Background automation time budget expired during setup.", "background_automation_hard_timeout");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
143
148
|
function assertRequestedMcpToolsAvailable(automation, actions) {
|
|
144
149
|
const requested = automation.meta.mcpTools ?? [];
|
|
145
150
|
const missing = requested.filter((toolName) => !actions[toolName]);
|
|
@@ -153,6 +158,7 @@ function createRunId(prefix) {
|
|
|
153
158
|
}
|
|
154
159
|
export async function runBackgroundAutomation(options, deps) {
|
|
155
160
|
const { automation } = options;
|
|
161
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
156
162
|
let historyId = null;
|
|
157
163
|
if (options.historyId) {
|
|
158
164
|
historyId = options.historyId;
|
|
@@ -297,7 +303,9 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
297
303
|
userEmail: ownerEmail,
|
|
298
304
|
orgId,
|
|
299
305
|
}, async () => {
|
|
306
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
300
307
|
const baseActions = await deps.getActions(automation);
|
|
308
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
301
309
|
assertRequestedMcpToolsAvailable(automation, baseActions);
|
|
302
310
|
const configuredInitialTools = deps.getInitialToolNames?.(automation);
|
|
303
311
|
const initialToolNames = configuredInitialTools
|
|
@@ -311,7 +319,9 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
311
319
|
: baseActions;
|
|
312
320
|
const availableTools = actionsToEngineTools(actions);
|
|
313
321
|
const tools = filterInitialEngineTools(availableTools, initialToolNames);
|
|
322
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
314
323
|
const ownerApiKey = await resolveOwnerEngineApiKey({ ownerEmail });
|
|
324
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
315
325
|
const apiKey = ownerApiKey.apiKey ?? deps.apiKey;
|
|
316
326
|
const apiKeyProvenance = ownerApiKey.apiKey
|
|
317
327
|
? ownerApiKey.credentialProvenance
|
|
@@ -328,26 +338,32 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
328
338
|
appId: deps.appId,
|
|
329
339
|
credentialIdentity: { userEmail: ownerEmail, orgId },
|
|
330
340
|
}));
|
|
341
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
331
342
|
const modelCandidate = automation.meta.model ??
|
|
332
343
|
deps.model ??
|
|
333
344
|
(await getStoredModelForEngine(engine, { appId: deps.appId })) ??
|
|
334
345
|
engine.defaultModel;
|
|
335
346
|
const model = normalizeModelForEngine(engine, modelCandidate);
|
|
347
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
336
348
|
const systemPrompt = await deps.getSystemPrompt(ownerEmail);
|
|
349
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
337
350
|
const thread = await createThread(ownerEmail, {
|
|
338
351
|
title: threadTitle,
|
|
339
352
|
orgId: orgId ?? null,
|
|
340
353
|
});
|
|
354
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
341
355
|
const runId = createRunId(options.runIdPrefix);
|
|
342
356
|
if (runIdRef)
|
|
343
357
|
runIdRef.current = runId;
|
|
344
358
|
await recordRunThread(historyId, thread.id, runId);
|
|
345
|
-
|
|
359
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
360
|
+
const maxHardTimeoutMs = Math.min(options.hardTimeoutMs ?? Number.POSITIVE_INFINITY, resolveBackgroundRunHardTimeoutMs());
|
|
346
361
|
const softTimeoutMs = resolveBackgroundAutomationSoftTimeoutMs();
|
|
347
362
|
const usageRef = { current: null };
|
|
348
363
|
let responseText = "";
|
|
349
364
|
let hardAbortTimer = null;
|
|
350
365
|
let hardTimedOut = false;
|
|
366
|
+
assertHardDeadline(options.hardDeadlineAt);
|
|
351
367
|
await insertRun(runId, thread.id, undefined, {
|
|
352
368
|
dispatchMode: "background",
|
|
353
369
|
});
|
|
@@ -355,6 +371,9 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
355
371
|
if (!claimedOwnRun) {
|
|
356
372
|
throw new Error(`Background automation "${automation.name}" (run "${runId}") could not claim its own freshly-inserted run row`);
|
|
357
373
|
}
|
|
374
|
+
const hardTimeoutMs = Math.min(maxHardTimeoutMs, options.hardDeadlineAt === undefined
|
|
375
|
+
? Number.POSITIVE_INFINITY
|
|
376
|
+
: Math.max(1, options.hardDeadlineAt - Date.now()));
|
|
358
377
|
await new Promise((resolve, reject) => {
|
|
359
378
|
const activeRun = startRun(runId, thread.id, async (send, signal, control) => {
|
|
360
379
|
const loopOpts = {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const RECURRING_SWEEP_BUDGET_MS = 90000;
|
|
2
|
+
export interface RecurringSweepContext {
|
|
3
|
+
deadlineAt: number;
|
|
4
|
+
}
|
|
5
|
+
export type RecurringSweepHandler = (context: RecurringSweepContext) => Promise<void>;
|
|
2
6
|
export declare function registerRecurringSweepHandler(id: string, handler: RecurringSweepHandler): () => void;
|
|
3
7
|
export declare function hasRecurringSweepHandler(id: string): boolean;
|
|
4
|
-
export declare function runRecurringSweepHandlers(): Promise<{
|
|
8
|
+
export declare function runRecurringSweepHandlers(context: RecurringSweepContext): Promise<{
|
|
5
9
|
registered: number;
|
|
6
10
|
failed: string[];
|
|
7
11
|
}>;
|
package/dist/jobs/sweep-hooks.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const RECURRING_SWEEP_BUDGET_MS = 90_000;
|
|
1
2
|
const handlers = new Map();
|
|
2
3
|
export function registerRecurringSweepHandler(id, handler) {
|
|
3
4
|
const key = id.trim();
|
|
@@ -12,17 +13,24 @@ export function registerRecurringSweepHandler(id, handler) {
|
|
|
12
13
|
export function hasRecurringSweepHandler(id) {
|
|
13
14
|
return handlers.has(id);
|
|
14
15
|
}
|
|
15
|
-
export async function runRecurringSweepHandlers() {
|
|
16
|
-
const failed = [];
|
|
16
|
+
export async function runRecurringSweepHandlers(context) {
|
|
17
17
|
const snapshot = [...handlers.entries()];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const outcomes = await Promise.allSettled(snapshot.map(async ([id, handler]) => {
|
|
19
|
+
if (Date.now() >= context.deadlineAt) {
|
|
20
|
+
throw new Error("Recurring sweep deadline elapsed before handler start.");
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
await handler(context);
|
|
23
|
+
if (Date.now() > context.deadlineAt) {
|
|
24
|
+
throw new Error("Recurring sweep handler exceeded its deadline.");
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
return id;
|
|
27
|
+
}));
|
|
28
|
+
const failed = outcomes.flatMap((outcome, index) => {
|
|
29
|
+
if (outcome.status === "fulfilled")
|
|
30
|
+
return [];
|
|
31
|
+
const id = snapshot[index][0];
|
|
32
|
+
console.error(`[recurring-sweep] handler ${id} failed:`, outcome.reason);
|
|
33
|
+
return [id];
|
|
34
|
+
});
|
|
27
35
|
return { registered: snapshot.length, failed };
|
|
28
36
|
}
|
|
@@ -1112,8 +1112,8 @@ const messages = {
|
|
|
1112
1112
|
"usage.copyInviteLink": "نسخ رابط الدعوة",
|
|
1113
1113
|
"usage.inviteLinkCopied": "تم نسخ رابط الدعوة",
|
|
1114
1114
|
"usage.creditBalance": "رصيد مساحة العمل",
|
|
1115
|
-
"usage.
|
|
1116
|
-
"usage.
|
|
1115
|
+
"usage.monthlyLimit": "الحد الشهري",
|
|
1116
|
+
"usage.dailyDefaultLimit": "الحد اليومي الافتراضي",
|
|
1117
1117
|
"usage.creditUsedOfLimit": "استخدام {{used}} من {{limit}}",
|
|
1118
1118
|
"usage.creditRemaining": "المتبقي {{amount}}",
|
|
1119
1119
|
"usage.creditUsageUnavailable": "تعذّر تحميل استخدام أرصدة Builder.",
|
|
@@ -1076,8 +1076,8 @@ const messages = {
|
|
|
1076
1076
|
"usage.copyInviteLink": "Einladungslink kopieren",
|
|
1077
1077
|
"usage.inviteLinkCopied": "Einladungslink kopiert",
|
|
1078
1078
|
"usage.creditBalance": "Workspace-Guthaben",
|
|
1079
|
-
"usage.
|
|
1080
|
-
"usage.
|
|
1079
|
+
"usage.monthlyLimit": "Monatliches Limit",
|
|
1080
|
+
"usage.dailyDefaultLimit": "Tägliches Standardlimit",
|
|
1081
1081
|
"usage.creditUsedOfLimit": "{{used}} von {{limit}} verbraucht",
|
|
1082
1082
|
"usage.creditRemaining": "{{amount}} verbleibend",
|
|
1083
1083
|
"usage.creditUsageUnavailable": "Der Builder-Credit-Verbrauch konnte nicht geladen werden.",
|
|
@@ -1076,8 +1076,8 @@ declare const messages: {
|
|
|
1076
1076
|
readonly "usage.copyInviteLink": "Copy invite link";
|
|
1077
1077
|
readonly "usage.inviteLinkCopied": "Invite link copied";
|
|
1078
1078
|
readonly "usage.creditBalance": "Workspace balance";
|
|
1079
|
-
readonly "usage.
|
|
1080
|
-
readonly "usage.
|
|
1079
|
+
readonly "usage.monthlyLimit": "Monthly limit";
|
|
1080
|
+
readonly "usage.dailyDefaultLimit": "Default daily limit";
|
|
1081
1081
|
readonly "usage.creditUsedOfLimit": "{{used}} of {{limit}} used";
|
|
1082
1082
|
readonly "usage.creditRemaining": "{{amount}} remaining";
|
|
1083
1083
|
readonly "usage.creditUsageUnavailable": "Builder credit usage couldn’t be loaded.";
|
|
@@ -1076,8 +1076,8 @@ const messages = {
|
|
|
1076
1076
|
"usage.copyInviteLink": "Copy invite link",
|
|
1077
1077
|
"usage.inviteLinkCopied": "Invite link copied",
|
|
1078
1078
|
"usage.creditBalance": "Workspace balance",
|
|
1079
|
-
"usage.
|
|
1080
|
-
"usage.
|
|
1079
|
+
"usage.monthlyLimit": "Monthly limit",
|
|
1080
|
+
"usage.dailyDefaultLimit": "Default daily limit",
|
|
1081
1081
|
"usage.creditUsedOfLimit": "{{used}} of {{limit}} used",
|
|
1082
1082
|
"usage.creditRemaining": "{{amount}} remaining",
|
|
1083
1083
|
"usage.creditUsageUnavailable": "Builder credit usage couldn’t be loaded.",
|
|
@@ -1085,8 +1085,8 @@ const messages = {
|
|
|
1085
1085
|
"usage.copyInviteLink": "Copiar enlace de invitación",
|
|
1086
1086
|
"usage.inviteLinkCopied": "Enlace de invitación copiado",
|
|
1087
1087
|
"usage.creditBalance": "Saldo del espacio de trabajo",
|
|
1088
|
-
"usage.
|
|
1089
|
-
"usage.
|
|
1088
|
+
"usage.monthlyLimit": "Límite mensual",
|
|
1089
|
+
"usage.dailyDefaultLimit": "Límite diario predeterminado",
|
|
1090
1090
|
"usage.creditUsedOfLimit": "{{used}} de {{limit}} usados",
|
|
1091
1091
|
"usage.creditRemaining": "Quedan {{amount}}",
|
|
1092
1092
|
"usage.creditUsageUnavailable": "No se pudo cargar el uso de créditos de Builder.",
|
|
@@ -1085,8 +1085,8 @@ const messages = {
|
|
|
1085
1085
|
"usage.copyInviteLink": "Copier le lien d’invitation",
|
|
1086
1086
|
"usage.inviteLinkCopied": "Lien d’invitation copié",
|
|
1087
1087
|
"usage.creditBalance": "Solde de l’espace de travail",
|
|
1088
|
-
"usage.
|
|
1089
|
-
"usage.
|
|
1088
|
+
"usage.monthlyLimit": "Limite mensuelle",
|
|
1089
|
+
"usage.dailyDefaultLimit": "Limite quotidien par défaut",
|
|
1090
1090
|
"usage.creditUsedOfLimit": "{{used}} sur {{limit}} utilisés",
|
|
1091
1091
|
"usage.creditRemaining": "{{amount}} restants",
|
|
1092
1092
|
"usage.creditUsageUnavailable": "Impossible de charger l’utilisation des crédits Builder.",
|
|
@@ -1076,8 +1076,8 @@ const messages = {
|
|
|
1076
1076
|
"usage.copyInviteLink": "आमंत्रण लिंक कॉपी करें",
|
|
1077
1077
|
"usage.inviteLinkCopied": "आमंत्रण लिंक कॉपी हो गया",
|
|
1078
1078
|
"usage.creditBalance": "वर्कस्पेस बैलेंस",
|
|
1079
|
-
"usage.
|
|
1080
|
-
"usage.
|
|
1079
|
+
"usage.monthlyLimit": "मासिक सीमा",
|
|
1080
|
+
"usage.dailyDefaultLimit": "डिफ़ॉल्ट दैनिक सीमा",
|
|
1081
1081
|
"usage.creditUsedOfLimit": "{{limit}} में से {{used}} उपयोग किए",
|
|
1082
1082
|
"usage.creditRemaining": "{{amount}} शेष",
|
|
1083
1083
|
"usage.creditUsageUnavailable": "Builder क्रेडिट उपयोग लोड नहीं हो सका।",
|
|
@@ -1068,8 +1068,8 @@ const messages = {
|
|
|
1068
1068
|
"usage.copyInviteLink": "招待リンクをコピー",
|
|
1069
1069
|
"usage.inviteLinkCopied": "招待リンクをコピーしました",
|
|
1070
1070
|
"usage.creditBalance": "ワークスペース残高",
|
|
1071
|
-
"usage.
|
|
1072
|
-
"usage.
|
|
1071
|
+
"usage.monthlyLimit": "月間上限",
|
|
1072
|
+
"usage.dailyDefaultLimit": "デフォルトの日次上限",
|
|
1073
1073
|
"usage.creditUsedOfLimit": "{{limit}} 中 {{used}} を使用",
|
|
1074
1074
|
"usage.creditRemaining": "残り {{amount}}",
|
|
1075
1075
|
"usage.creditUsageUnavailable": "Builder クレジットの使用状況を読み込めませんでした。",
|
|
@@ -1068,8 +1068,8 @@ const messages = {
|
|
|
1068
1068
|
"usage.copyInviteLink": "초대 링크 복사",
|
|
1069
1069
|
"usage.inviteLinkCopied": "초대 링크를 복사했습니다",
|
|
1070
1070
|
"usage.creditBalance": "워크스페이스 잔액",
|
|
1071
|
-
"usage.
|
|
1072
|
-
"usage.
|
|
1071
|
+
"usage.monthlyLimit": "월간 한도",
|
|
1072
|
+
"usage.dailyDefaultLimit": "기본 일일 한도",
|
|
1073
1073
|
"usage.creditUsedOfLimit": "{{limit}} 중 {{used}} 사용",
|
|
1074
1074
|
"usage.creditRemaining": "{{amount}} 남음",
|
|
1075
1075
|
"usage.creditUsageUnavailable": "Builder 크레딧 사용량을 불러오지 못했습니다.",
|
|
@@ -1085,8 +1085,8 @@ const messages = {
|
|
|
1085
1085
|
"usage.copyInviteLink": "Copiar link de convite",
|
|
1086
1086
|
"usage.inviteLinkCopied": "Link de convite copiado",
|
|
1087
1087
|
"usage.creditBalance": "Saldo do workspace",
|
|
1088
|
-
"usage.
|
|
1089
|
-
"usage.
|
|
1088
|
+
"usage.monthlyLimit": "Limite mensal",
|
|
1089
|
+
"usage.dailyDefaultLimit": "Limite diário padrão",
|
|
1090
1090
|
"usage.creditUsedOfLimit": "{{used}} de {{limit}} usados",
|
|
1091
1091
|
"usage.creditRemaining": "{{amount}} restantes",
|
|
1092
1092
|
"usage.creditUsageUnavailable": "Não foi possível carregar o uso de créditos do Builder.",
|
|
@@ -1068,8 +1068,8 @@ const messages = {
|
|
|
1068
1068
|
"usage.copyInviteLink": "复制邀请链接",
|
|
1069
1069
|
"usage.inviteLinkCopied": "邀请链接已复制",
|
|
1070
1070
|
"usage.creditBalance": "工作区余额",
|
|
1071
|
-
"usage.
|
|
1072
|
-
"usage.
|
|
1071
|
+
"usage.monthlyLimit": "月度限额",
|
|
1072
|
+
"usage.dailyDefaultLimit": "默认每日限额",
|
|
1073
1073
|
"usage.creditUsedOfLimit": "已使用 {{used}} / {{limit}}",
|
|
1074
1074
|
"usage.creditRemaining": "剩余 {{amount}}",
|
|
1075
1075
|
"usage.creditUsageUnavailable": "无法加载 Builder 积分使用情况。",
|
|
@@ -1068,8 +1068,8 @@ const messages = {
|
|
|
1068
1068
|
"usage.copyInviteLink": "複製邀請連結",
|
|
1069
1069
|
"usage.inviteLinkCopied": "邀請連結已複製",
|
|
1070
1070
|
"usage.creditBalance": "工作區餘額",
|
|
1071
|
-
"usage.
|
|
1072
|
-
"usage.
|
|
1071
|
+
"usage.monthlyLimit": "每月上限",
|
|
1072
|
+
"usage.dailyDefaultLimit": "預設每日上限",
|
|
1073
1073
|
"usage.creditUsedOfLimit": "已使用 {{used}} / {{limit}}",
|
|
1074
1074
|
"usage.creditRemaining": "剩餘 {{amount}}",
|
|
1075
1075
|
"usage.creditUsageUnavailable": "無法載入 Builder 點數使用情況。",
|
|
@@ -1078,8 +1078,8 @@ export declare const englishAgentChatMessages: {
|
|
|
1078
1078
|
readonly "usage.copyInviteLink": "Copy invite link";
|
|
1079
1079
|
readonly "usage.inviteLinkCopied": "Invite link copied";
|
|
1080
1080
|
readonly "usage.creditBalance": "Workspace balance";
|
|
1081
|
-
readonly "usage.
|
|
1082
|
-
readonly "usage.
|
|
1081
|
+
readonly "usage.monthlyLimit": "Monthly limit";
|
|
1082
|
+
readonly "usage.dailyDefaultLimit": "Default daily limit";
|
|
1083
1083
|
readonly "usage.creditUsedOfLimit": "{{used}} of {{limit}} used";
|
|
1084
1084
|
readonly "usage.creditRemaining": "{{amount}} remaining";
|
|
1085
1085
|
readonly "usage.creditUsageUnavailable": "Builder credit usage couldn’t be loaded.";
|