@agent-native/core 0.155.0 → 0.157.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 +1 -1
- package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +19 -4
- package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +7 -2
- package/corpus/templates/assets/app/components/asset/AssetPreviewDialog.tsx +3 -1
- package/corpus/templates/assets/app/global.css +4 -0
- package/corpus/templates/assets/app/i18n-data.ts +21 -1
- package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +18 -15
- package/corpus/templates/brain/app/routes/sources.tsx +1 -2
- package/corpus/templates/calendar/app/hooks/use-bookings.ts +12 -2
- package/corpus/templates/calendar/app/pages/BookingLinksPage.tsx +64 -2
- package/corpus/templates/calendar/server/handlers/bookings.ts +219 -93
- package/corpus/templates/calendar/server/plugins/auth.ts +0 -2
- package/corpus/templates/clips/actions/create-folder.ts +7 -1
- package/corpus/templates/clips/actions/create-meeting.ts +6 -2
- package/corpus/templates/clips/actions/create-recording.ts +5 -3
- package/corpus/templates/clips/actions/finalize-recording.ts +97 -65
- package/corpus/templates/clips/actions/import-loom-recording.ts +5 -3
- package/corpus/templates/clips/actions/request-recording-access.ts +272 -0
- package/corpus/templates/clips/actions/stitch-recordings.ts +5 -3
- package/corpus/templates/clips/app/components/meetings/share-meeting-dialog.tsx +38 -63
- package/corpus/templates/clips/app/components/player/share-dialog.tsx +177 -134
- package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +3 -21
- package/corpus/templates/clips/app/components/sharing/share-ui.tsx +13 -30
- package/corpus/templates/clips/app/i18n/en-US.ts +10 -0
- package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +5 -5
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +24 -17
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +151 -20
- package/corpus/templates/clips/changelog/2026-08-14-long-resumable-uploads-now-abort-cleanly-and-show-errors.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-14-standardized-share-popovers.md +6 -0
- package/corpus/templates/clips/chrome-extension/public/manifest.json +11 -3
- package/corpus/templates/clips/chrome-extension/src/github-preview-content.ts +37 -8
- package/corpus/templates/clips/chrome-extension/src/github-preview.ts +3 -3
- package/corpus/templates/clips/chrome-extension/src/offscreen.ts +8 -25
- package/corpus/templates/clips/desktop/src/app.tsx +24 -0
- package/corpus/templates/clips/desktop/src/lib/media-capture-constraints.ts +42 -13
- package/corpus/templates/clips/desktop/src/lib/recorder.ts +11 -18
- package/corpus/templates/clips/desktop/src/overlays/onboarding.tsx +1 -0
- package/corpus/templates/clips/desktop/src/shared/config.ts +1 -0
- package/corpus/templates/clips/desktop/src/styles.css +24 -9
- package/corpus/templates/clips/desktop/src-tauri/Cargo.toml +3 -0
- package/corpus/templates/clips/desktop/src-tauri/src/config.rs +8 -0
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen/custom_capture.rs +154 -176
- package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +115 -31
- package/corpus/templates/clips/desktop/src-tauri/src/rewind_clip.rs +7 -0
- package/corpus/templates/clips/server/db/index.ts +1 -0
- package/corpus/templates/clips/server/db/schema.ts +1 -0
- package/corpus/templates/clips/server/lib/calendar-event-meetings.ts +6 -1
- package/corpus/templates/clips/server/lib/emails.ts +23 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +55 -0
- package/corpus/templates/clips/server/lib/recordings.ts +2 -1
- package/corpus/templates/clips/server/lib/resumable-upload-cleanup.ts +49 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +34 -7
- package/corpus/templates/clips/server/lib/upload-interruption.ts +15 -1
- package/corpus/templates/clips/server/lib/upload-lease.ts +94 -9
- package/corpus/templates/clips/server/routes/api/agent-context.json.get.ts +82 -7
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +1 -0
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +71 -12
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +4 -3
- package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +19 -0
- package/corpus/templates/clips/server/routes/api/uploads/reap.post.ts +8 -1
- package/corpus/templates/clips/shared/recording-link.ts +4 -0
- package/corpus/templates/clips/shared/share-loader-response.ts +2 -1
- package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +7 -16
- package/corpus/templates/factory/AGENTS.md +5 -1
- package/corpus/templates/factory/README.md +6 -2
- package/corpus/templates/factory/actions/view-screen.ts +15 -0
- package/corpus/templates/factory/app/components/factory/FactoryAgentsView.tsx +58 -189
- package/corpus/templates/factory/app/components/layout/Header.tsx +1 -0
- package/corpus/templates/factory/app/components/layout/Layout.tsx +1 -1
- package/corpus/templates/factory/app/components/layout/Sidebar.tsx +7 -0
- package/corpus/templates/factory/app/hooks/use-navigation-state.ts +3 -0
- package/corpus/templates/factory/app/i18n/en-US.ts +3 -1
- package/corpus/templates/factory/app/routes/agents.tsx +9 -0
- package/corpus/templates/mail/server/plugins/auth.ts +0 -2
- package/corpus/templates/plan/app/components/plan/LocalCodebasePicker.tsx +50 -14
- package/corpus/templates/plan/app/pages/PlansPage.tsx +9 -19
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +98 -29
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +45 -91
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +94 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +17 -29
- package/corpus/templates/slides/app/components/editor/HistoryPanel.tsx +7 -1
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +1 -1
- package/corpus/templates/slides/app/context/DeckContext.tsx +108 -19
- package/corpus/templates/slides/app/global.css +7 -40
- package/corpus/templates/slides/app/i18n/en-US.ts +4 -0
- package/corpus/templates/slides/app/lib/editor-shortcuts.ts +46 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +143 -45
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/production-agent.d.ts +30 -0
- package/dist/agent/production-agent.js +100 -8
- package/dist/agent/types.d.ts +9 -0
- package/dist/client/AgentPanel.d.ts +13 -1
- package/dist/client/AgentPanel.js +22 -17
- package/dist/client/AssistantChat.d.ts +15 -1
- package/dist/client/AssistantChat.js +135 -48
- package/dist/client/HighlightedCodeBlock.js +12 -2
- package/dist/client/MultiTabAssistantChat.js +44 -27
- package/dist/client/agent-chat/index.d.ts +1 -0
- package/dist/client/agent-chat/index.js +1 -0
- package/dist/client/chat/markdown-renderer.js +20 -5
- package/dist/client/chat/message-components.d.ts +2 -2
- package/dist/client/chat/message-components.js +69 -35
- package/dist/client/chat/run-recovery.d.ts +4 -1
- package/dist/client/chat/run-recovery.js +62 -30
- package/dist/client/chat/tool-call-display.d.ts +12 -3
- package/dist/client/chat/tool-call-display.js +79 -40
- package/dist/client/chat/widgets/DataChartRenderer.js +3 -1
- package/dist/client/chat/widgets/DataChartWidget.js +8 -2
- package/dist/client/chat/widgets/DataInsightsWidget.js +3 -1
- package/dist/client/chat/widgets/DataTableWidget.js +23 -9
- package/dist/client/chat/widgets/builtin-tool-renderers.js +3 -1
- package/dist/client/chat-first/apps-rail.js +1 -1
- package/dist/client/components/ui/message-scroller.d.ts +1 -1
- package/dist/client/components/ui/message-scroller.js +7 -3
- package/dist/client/composer/runtime-adapters.js +3 -2
- package/dist/client/context-xray/ContextMeter.js +5 -1
- package/dist/client/context-xray/ContextXRayPanel.js +5 -5
- package/dist/client/error-format.d.ts +4 -0
- package/dist/client/error-format.js +93 -5
- package/dist/client/i18n.js +83 -17
- package/dist/client/observability/ThumbsFeedback.js +10 -8
- package/dist/client/settings/AccountSettingsCard.js +48 -19
- package/dist/client/sharing/ShareButton.d.ts +1 -2
- package/dist/client/sharing/ShareButton.js +151 -81
- package/dist/client/sharing/ShareDialog.js +5 -4
- package/dist/client/use-chat-threads.js +10 -14
- package/dist/coding-tools/run-code.js +2 -1
- package/dist/coding-tools/sandbox/background.d.ts +1 -0
- package/dist/coding-tools/sandbox/background.js +8 -1
- package/dist/coding-tools/sandbox/executions-store.d.ts +2 -0
- package/dist/coding-tools/sandbox/executions-store.js +41 -3
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.d.ts +3 -0
- package/dist/localization/core-messages/ar-SA.js +541 -0
- package/dist/localization/core-messages/de-DE.d.ts +3 -0
- package/dist/localization/core-messages/de-DE.js +513 -0
- package/dist/localization/core-messages/en-US.d.ts +513 -0
- package/dist/localization/core-messages/en-US.js +513 -0
- package/dist/localization/core-messages/es-ES.d.ts +3 -0
- package/dist/localization/core-messages/es-ES.js +520 -0
- package/dist/localization/core-messages/fr-FR.d.ts +3 -0
- package/dist/localization/core-messages/fr-FR.js +520 -0
- package/dist/localization/core-messages/hi-IN.d.ts +3 -0
- package/dist/localization/core-messages/hi-IN.js +513 -0
- package/dist/localization/core-messages/ja-JP.d.ts +3 -0
- package/dist/localization/core-messages/ja-JP.js +506 -0
- package/dist/localization/core-messages/ko-KR.d.ts +3 -0
- package/dist/localization/core-messages/ko-KR.js +506 -0
- package/dist/localization/core-messages/pt-BR.d.ts +3 -0
- package/dist/localization/core-messages/pt-BR.js +520 -0
- package/dist/localization/core-messages/zh-CN.d.ts +3 -0
- package/dist/localization/core-messages/zh-CN.js +506 -0
- package/dist/localization/core-messages/zh-TW.d.ts +3 -0
- package/dist/localization/core-messages/zh-TW.js +506 -0
- package/dist/localization/core-messages.d.ts +524 -0
- package/dist/localization/core-messages.js +124 -0
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.js +3 -0
- package/dist/notifications/routes.d.ts +1 -1
- 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 +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +15 -15
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat/plugin-options.d.ts +7 -2
- package/dist/server/agent-chat-plugin.d.ts +10 -0
- package/dist/server/agent-chat-plugin.js +144 -41
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-run-context.d.ts +7 -1
- package/dist/server/agent-run-context.js +9 -2
- package/dist/server/agent-teams-run-queue.d.ts +3 -0
- package/dist/server/agent-teams.js +38 -9
- package/dist/server/auth-marketing.d.ts +1 -0
- package/dist/server/auth-marketing.js +0 -2
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +18 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/onboarding-html.d.ts +1 -0
- package/dist/server/onboarding-html.js +2 -88
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/request-context.d.ts +7 -0
- package/dist/server/request-context.js +15 -0
- package/dist/shared/markdown-block-split.d.ts +16 -0
- package/dist/shared/markdown-block-split.js +81 -5
- package/dist/styles/agent-native.css +13 -0
- package/dist/voice/voice-cleanup-prompt.js +1 -0
- package/docs/content/agent-surfaces.mdx +30 -0
- package/package.json +2 -2
- package/corpus/templates/clips/shared/mic-audio-cleanup.ts +0 -350
|
@@ -255,6 +255,29 @@ export interface ActionEntry {
|
|
|
255
255
|
/** @deprecated Use `ActionEntry` instead */
|
|
256
256
|
export type ScriptEntry = ActionEntry;
|
|
257
257
|
export type AgentExecutionMode = "act" | "plan";
|
|
258
|
+
export interface AgentActionSurface {
|
|
259
|
+
allowedActionNames: readonly string[];
|
|
260
|
+
}
|
|
261
|
+
export interface AgentActionSurfaceDetails {
|
|
262
|
+
event: any;
|
|
263
|
+
ownerEmail: string | null;
|
|
264
|
+
orgId: string | null;
|
|
265
|
+
threadId?: string;
|
|
266
|
+
mode: AgentExecutionMode;
|
|
267
|
+
internalContinuation: boolean;
|
|
268
|
+
availableActionNames: readonly string[];
|
|
269
|
+
}
|
|
270
|
+
/** Read a persisted allowlist while preserving legacy absence and failing
|
|
271
|
+
* closed when the field is present but malformed. */
|
|
272
|
+
export declare function readPersistedAllowedActionNames(value: unknown): string[] | undefined;
|
|
273
|
+
export interface PersistedActionSurface {
|
|
274
|
+
orgId: string | null;
|
|
275
|
+
allowedActionNames: string[];
|
|
276
|
+
}
|
|
277
|
+
/** Read a nested persisted action surface. An absent envelope is legacy;
|
|
278
|
+
* a present but invalid envelope is an explicit org-less, empty surface. */
|
|
279
|
+
export declare function readPersistedActionSurface(value: unknown, propertyName: string): PersistedActionSurface | undefined;
|
|
280
|
+
export declare function filterActionsByAllowedNames(actions: Record<string, ActionEntry>, allowedActionNames: readonly string[]): Record<string, ActionEntry>;
|
|
258
281
|
export declare const PLAN_MODE_SYSTEM_PROMPT = "## Plan Mode Active\n\nYou are in Plan mode. This turn is for research, clarification, and a proposed approach only.\n\nHard rules:\n- Use only read-only tools. Do not edit files, write resources, run mutating bash commands, mutate SQL rows, navigate the UI, send notifications, create jobs, create tools, send messages or tasks to external agents, or change external systems.\n- If a needed detail is unclear, ask a concise clarifying question before proposing a plan.\n- When ready, present a concrete plan with the files/tools you expect to touch, the intended changes, validation steps, and notable risks.\n- Do not treat approval as implicit while Plan mode is still active. Tell the user to switch to Act mode with the mode selector or /act before implementation.";
|
|
259
282
|
export declare function isPlanModeToolCallAllowed(name: string, input: unknown, entry: ActionEntry): boolean;
|
|
260
283
|
export declare function createPlanModeActionRegistry(actions: Record<string, ActionEntry>): Record<string, ActionEntry>;
|
|
@@ -314,6 +337,13 @@ export interface ProductionAgentOptions {
|
|
|
314
337
|
displayMessage?: string;
|
|
315
338
|
attachments?: AgentChatAttachment[];
|
|
316
339
|
}>;
|
|
340
|
+
/**
|
|
341
|
+
* Resolve the exact action registry exposed to one interactive agent-chat
|
|
342
|
+
* request. Returned names are a hard allowlist: omitted actions are absent
|
|
343
|
+
* from both the provider schemas and the searchable registry. When set, all
|
|
344
|
+
* allowed actions are loaded directly on the first model request.
|
|
345
|
+
*/
|
|
346
|
+
resolveActionSurface?: (details: AgentActionSurfaceDetails) => AgentActionSurface | Promise<AgentActionSurface>;
|
|
317
347
|
/** Optional per-app agent run chunk budget in milliseconds. Defaults to
|
|
318
348
|
* AGENT_RUN_SOFT_TIMEOUT_MS when set, otherwise no framework-imposed
|
|
319
349
|
* timeout. When reached, the client receives an internal auto-continuation
|
|
@@ -16,7 +16,7 @@ import { completeRun as completeProgressRun, startRun as startProgressRun, updat
|
|
|
16
16
|
import { isRuntimeVisibleScope, parseSkillFrontmatter, } from "../server/agent-chat/skill-frontmatter.js";
|
|
17
17
|
import { canUseDeployCredentialFallbackForRequest, getProviderCredentialAuthFailure, readDeployCredentialEnv, } from "../server/credential-provider.js";
|
|
18
18
|
import { readBody } from "../server/h3-helpers.js";
|
|
19
|
-
import { getRequestRunContext, ensureRequestRunContext, getRequestContext, getRequestOrgId, getRequestUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
19
|
+
import { assertRequestActionSurfaceIsolation, getRequestRunContext, ensureRequestRunContext, getRequestContext, getRequestOrgId, getRequestUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
20
20
|
import { fireInternalDispatch } from "../server/self-dispatch.js";
|
|
21
21
|
import { isReasoningEffort, normalizeReasoningEffortForRequest, stepDownReasoningEffort, } from "../shared/reasoning-effort.js";
|
|
22
22
|
import { actionPreparationContinuationNote } from "./action-continuation-guidance.js";
|
|
@@ -391,6 +391,55 @@ export async function resolveOwnerEngineApiKey(input) {
|
|
|
391
391
|
export async function getOwnerAnthropicApiKey(ownerEmail) {
|
|
392
392
|
return getOwnerApiKey("anthropic", ownerEmail);
|
|
393
393
|
}
|
|
394
|
+
function hasOwn(value, propertyName) {
|
|
395
|
+
return (typeof value === "object" &&
|
|
396
|
+
value !== null &&
|
|
397
|
+
Object.prototype.hasOwnProperty.call(value, propertyName));
|
|
398
|
+
}
|
|
399
|
+
/** Read a persisted allowlist while preserving legacy absence and failing
|
|
400
|
+
* closed when the field is present but malformed. */
|
|
401
|
+
export function readPersistedAllowedActionNames(value) {
|
|
402
|
+
if (!hasOwn(value, "allowedActionNames"))
|
|
403
|
+
return undefined;
|
|
404
|
+
const names = value.allowedActionNames;
|
|
405
|
+
if (!Array.isArray(names) ||
|
|
406
|
+
!names.every((name) => typeof name === "string")) {
|
|
407
|
+
return [];
|
|
408
|
+
}
|
|
409
|
+
return [...new Set(names)];
|
|
410
|
+
}
|
|
411
|
+
/** Read a nested persisted action surface. An absent envelope is legacy;
|
|
412
|
+
* a present but invalid envelope is an explicit org-less, empty surface. */
|
|
413
|
+
export function readPersistedActionSurface(value, propertyName) {
|
|
414
|
+
if (!hasOwn(value, propertyName))
|
|
415
|
+
return undefined;
|
|
416
|
+
const surface = value[propertyName];
|
|
417
|
+
const allowedActionNames = readPersistedAllowedActionNames(surface) ?? [];
|
|
418
|
+
if (!hasOwn(surface, "orgId")) {
|
|
419
|
+
return { orgId: null, allowedActionNames: [] };
|
|
420
|
+
}
|
|
421
|
+
const orgId = surface.orgId;
|
|
422
|
+
if (orgId !== null &&
|
|
423
|
+
(typeof orgId !== "string" || orgId.trim().length === 0)) {
|
|
424
|
+
return { orgId: null, allowedActionNames: [] };
|
|
425
|
+
}
|
|
426
|
+
return { orgId, allowedActionNames };
|
|
427
|
+
}
|
|
428
|
+
export function filterActionsByAllowedNames(actions, allowedActionNames) {
|
|
429
|
+
const allowedNames = [...new Set(allowedActionNames)];
|
|
430
|
+
const unknownNames = allowedNames.filter((name) => !Object.prototype.hasOwnProperty.call(actions, name));
|
|
431
|
+
if (unknownNames.length > 0) {
|
|
432
|
+
throw new Error(`resolveActionSurface returned unknown action name(s): ${unknownNames.join(", ")}`);
|
|
433
|
+
}
|
|
434
|
+
const filtered = Object.fromEntries(allowedNames.map((name) => [name, actions[name]]));
|
|
435
|
+
// `attachToolSearch` closes over the registry it was originally attached to.
|
|
436
|
+
// Rebind it to this request's filtered registry so explicitly allowing
|
|
437
|
+
// `tool-search` cannot disclose actions that the resolver omitted.
|
|
438
|
+
if (filtered[TOOL_SEARCH_ACTION_NAME]) {
|
|
439
|
+
filtered[TOOL_SEARCH_ACTION_NAME] = createToolSearchEntry(() => filtered);
|
|
440
|
+
}
|
|
441
|
+
return filtered;
|
|
442
|
+
}
|
|
394
443
|
export const PLAN_MODE_SYSTEM_PROMPT = `## Plan Mode Active
|
|
395
444
|
|
|
396
445
|
You are in Plan mode. This turn is for research, clarification, and a proposed approach only.
|
|
@@ -6031,6 +6080,9 @@ export function resolveAgentRequestReasoningEffort({ model, requestEffort, confi
|
|
|
6031
6080
|
return normalizeReasoningEffortForRequest(model, isReasoningEffort(requestEffort) ? requestEffort : configuredEffort);
|
|
6032
6081
|
}
|
|
6033
6082
|
export function createProductionAgentHandler(options) {
|
|
6083
|
+
if (options.resolveActionSurface) {
|
|
6084
|
+
assertRequestActionSurfaceIsolation();
|
|
6085
|
+
}
|
|
6034
6086
|
// Undefined = let each engine pick its own defaultModel at request time.
|
|
6035
6087
|
const configuredModel = options.model;
|
|
6036
6088
|
// Resolve actions — prefer `actions`, fall back to deprecated `scripts`
|
|
@@ -6040,7 +6092,7 @@ export function createProductionAgentHandler(options) {
|
|
|
6040
6092
|
// the settings UI) show up to the LLM without a process restart. MCP tools
|
|
6041
6093
|
// are also scope-filtered per request — a user-scope server added by Alice
|
|
6042
6094
|
// must not appear in Bob's tool list in a shared-process deployment.
|
|
6043
|
-
const
|
|
6095
|
+
const getRequestActions = (actions = resolvedActions) => {
|
|
6044
6096
|
const filtered = {};
|
|
6045
6097
|
for (const [name, entry] of Object.entries(actions)) {
|
|
6046
6098
|
if (name.startsWith("mcp__") && !isMcpToolAllowedForRequest(name)) {
|
|
@@ -6048,8 +6100,9 @@ export function createProductionAgentHandler(options) {
|
|
|
6048
6100
|
}
|
|
6049
6101
|
filtered[name] = entry;
|
|
6050
6102
|
}
|
|
6051
|
-
return
|
|
6103
|
+
return filtered;
|
|
6052
6104
|
};
|
|
6105
|
+
const getEngineTools = (actions) => actionsToEngineTools(getRequestActions(actions));
|
|
6053
6106
|
return defineEventHandler(async (event) => {
|
|
6054
6107
|
// Diagnostic-only setup-timing instrumentation. Captures wall-clock offsets
|
|
6055
6108
|
// from handler entry through the work done BEFORE startRun so a slow pre-run
|
|
@@ -6089,12 +6142,20 @@ export function createProductionAgentHandler(options) {
|
|
|
6089
6142
|
// (the route HMAC-verifies the dispatch before invoking us). When set, we
|
|
6090
6143
|
// run the loop inline with the background soft-timeout, reusing the
|
|
6091
6144
|
// pre-claimed runId/turnId — we must NOT re-claim the slot or re-dispatch.
|
|
6092
|
-
const backgroundRunMarker =
|
|
6145
|
+
const backgroundRunMarker = preInjectedBody &&
|
|
6146
|
+
body[AGENT_CHAT_BACKGROUND_RUN_FIELD] &&
|
|
6093
6147
|
typeof body[AGENT_CHAT_BACKGROUND_RUN_FIELD] === "object" &&
|
|
6094
6148
|
typeof body[AGENT_CHAT_BACKGROUND_RUN_FIELD].runId === "string"
|
|
6095
6149
|
? body[AGENT_CHAT_BACKGROUND_RUN_FIELD]
|
|
6096
6150
|
: null;
|
|
6097
6151
|
const isBackgroundWorker = backgroundRunMarker !== null;
|
|
6152
|
+
// Both fields are internal durable-dispatch artifacts, never client input.
|
|
6153
|
+
// A body marker alone is not proof of worker identity: only the verified
|
|
6154
|
+
// `_process-run` route can install `preInjectedBody` on the event context.
|
|
6155
|
+
if (!isBackgroundWorker) {
|
|
6156
|
+
delete body[AGENT_CHAT_BACKGROUND_RUN_FIELD];
|
|
6157
|
+
delete body.__resolvedActionSurface;
|
|
6158
|
+
}
|
|
6098
6159
|
// DIAGNOSTIC-ONLY: progressive per-stage hang localizer for the bg worker.
|
|
6099
6160
|
// The worker's runId is available EARLY on the marker (the general `runId`
|
|
6100
6161
|
// var resolves much later), so capture it now and emit the LAST setup stage
|
|
@@ -6197,6 +6258,35 @@ export function createProductionAgentHandler(options) {
|
|
|
6197
6258
|
requestAttachments = preparedRequest.attachments;
|
|
6198
6259
|
}
|
|
6199
6260
|
}
|
|
6261
|
+
const availableRequestActions = getRequestActions();
|
|
6262
|
+
let surfacedRequestActions = availableRequestActions;
|
|
6263
|
+
if (options.resolveActionSurface) {
|
|
6264
|
+
const persistedSurface = isBackgroundWorker
|
|
6265
|
+
? readPersistedActionSurface(body, "__resolvedActionSurface")
|
|
6266
|
+
: undefined;
|
|
6267
|
+
const surface = persistedSurface !== undefined
|
|
6268
|
+
? persistedSurface
|
|
6269
|
+
: await options.resolveActionSurface({
|
|
6270
|
+
event,
|
|
6271
|
+
ownerEmail,
|
|
6272
|
+
orgId: getRequestOrgId() ?? null,
|
|
6273
|
+
threadId,
|
|
6274
|
+
mode: requestMode,
|
|
6275
|
+
internalContinuation: Boolean(internalContinuation),
|
|
6276
|
+
availableActionNames: Object.keys(availableRequestActions),
|
|
6277
|
+
});
|
|
6278
|
+
surfacedRequestActions = filterActionsByAllowedNames(availableRequestActions, surface.allowedActionNames);
|
|
6279
|
+
const allowedNames = Object.keys(surfacedRequestActions);
|
|
6280
|
+
const runCtx = ensureRequestRunContext();
|
|
6281
|
+
if (runCtx)
|
|
6282
|
+
runCtx.allowedActionNames = allowedNames;
|
|
6283
|
+
if (!isBackgroundWorker) {
|
|
6284
|
+
body.__resolvedActionSurface = {
|
|
6285
|
+
orgId: getRequestOrgId() ?? null,
|
|
6286
|
+
allowedActionNames: allowedNames,
|
|
6287
|
+
};
|
|
6288
|
+
}
|
|
6289
|
+
}
|
|
6200
6290
|
// DIAGNOSTIC-ONLY: owner/request context prep (resolveAgentOwnerEmail +
|
|
6201
6291
|
// prepareRequest) finished. A worker stuck before this points at the
|
|
6202
6292
|
// owner/request-context awaits.
|
|
@@ -6428,7 +6518,7 @@ export function createProductionAgentHandler(options) {
|
|
|
6428
6518
|
const screenContextThunk = () => (async () => {
|
|
6429
6519
|
const screenStart = Date.now();
|
|
6430
6520
|
try {
|
|
6431
|
-
const viewScreenAction =
|
|
6521
|
+
const viewScreenAction = surfacedRequestActions["view-screen"];
|
|
6432
6522
|
if (viewScreenAction) {
|
|
6433
6523
|
const result = await viewScreenAction.run({}, {
|
|
6434
6524
|
userEmail: getRequestUserEmail(),
|
|
@@ -6667,10 +6757,12 @@ export function createProductionAgentHandler(options) {
|
|
|
6667
6757
|
}
|
|
6668
6758
|
const screenContext = timeBlock + screenBlock + urlBlock + selectionBlock;
|
|
6669
6759
|
const requestActions = requestMode === "plan"
|
|
6670
|
-
? createPlanModeActionRegistry(
|
|
6671
|
-
:
|
|
6760
|
+
? createPlanModeActionRegistry(surfacedRequestActions)
|
|
6761
|
+
: surfacedRequestActions;
|
|
6672
6762
|
const availableRequestTools = getEngineTools(requestActions);
|
|
6673
|
-
const initialRequestTools =
|
|
6763
|
+
const initialRequestTools = options.resolveActionSurface
|
|
6764
|
+
? availableRequestTools
|
|
6765
|
+
: filterInitialEngineTools(availableRequestTools, options.initialToolNames);
|
|
6674
6766
|
const requestTools = requestMode === "plan"
|
|
6675
6767
|
? preloadPlanModeEngineTools({
|
|
6676
6768
|
request: requestMessage,
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -186,6 +186,15 @@ export interface AgentChatRequest {
|
|
|
186
186
|
*/
|
|
187
187
|
payloadRef?: boolean;
|
|
188
188
|
};
|
|
189
|
+
/**
|
|
190
|
+
* Server-resolved action authorization carried across authenticated durable
|
|
191
|
+
* background dispatches. Normal client requests must not trust this field;
|
|
192
|
+
* the foreground handler deletes and replaces it before persistence.
|
|
193
|
+
*/
|
|
194
|
+
__resolvedActionSurface?: {
|
|
195
|
+
orgId: string | null;
|
|
196
|
+
allowedActionNames: string[];
|
|
197
|
+
};
|
|
189
198
|
/**
|
|
190
199
|
* Stable identity for the logical assistant turn this request belongs to.
|
|
191
200
|
* The client sends the SAME turnId for the initial POST and every
|
|
@@ -201,6 +201,18 @@ export interface AgentSidebarProps {
|
|
|
201
201
|
chatViewTransitionHandoff?: boolean;
|
|
202
202
|
/** Namespace for persisted chat state. Use the same key as AgentChatHome. */
|
|
203
203
|
storageKey?: string;
|
|
204
|
+
/** Namespace for the persisted open/closed preference. Defaults to storageKey. */
|
|
205
|
+
openStorageKey?: string;
|
|
206
|
+
/** API base URL used by the chat surface. */
|
|
207
|
+
apiUrl?: string;
|
|
208
|
+
/** Runtime surface identity used for server-side chat capabilities. */
|
|
209
|
+
agentChatSurface?: AgentChatSurfaceKind;
|
|
210
|
+
/** Show the chat thread tab row. Default: true. */
|
|
211
|
+
showTabBar?: MultiTabAssistantChatProps["showTabBar"];
|
|
212
|
+
/** Keep inline app-opening results inside the current app chat. */
|
|
213
|
+
suppressInlineOpenApp?: AssistantChatProps["suppressInlineOpenApp"];
|
|
214
|
+
/** Placeholder shown in the chat composer. */
|
|
215
|
+
composerPlaceholder?: AssistantChatProps["composerPlaceholder"];
|
|
204
216
|
/** Open the sidebar when a chat run is active or reconnects. */
|
|
205
217
|
openOnChatRunning?: boolean;
|
|
206
218
|
/** Called when the user selects the full-view action from the chat sidebar. */
|
|
@@ -222,7 +234,7 @@ export interface AgentSidebarProps {
|
|
|
222
234
|
* Wraps app content with a toggleable agent sidebar.
|
|
223
235
|
* Use AgentToggleButton in your header to open/close it.
|
|
224
236
|
*/
|
|
225
|
-
export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openOnChatRunning, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
237
|
+
export declare function AgentSidebar({ children, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
226
238
|
/**
|
|
227
239
|
* Focus the agent chat composer input.
|
|
228
240
|
* Opens the sidebar if closed, then focuses the text input.
|
|
@@ -200,6 +200,7 @@ function IconTooltip({ content, children, }) {
|
|
|
200
200
|
return (_jsx(DesignSystemTooltip, { trigger: children, content: normalizeTooltipText(content), placement: "bottom", delayMs: 250, className: "z-[300] overflow-hidden rounded-md border border-border bg-popover px-2 py-1 text-[11px] text-foreground shadow-md" }));
|
|
201
201
|
}
|
|
202
202
|
function ChatLoadingSkeleton({ renderHeader, centerComposerWhenEmpty = false, composerSlot, composerAreaClassName, composerLayoutVariant = "default", }) {
|
|
203
|
+
const t = useT();
|
|
203
204
|
// Provide empty no-op implementations so renderHeader can render the real
|
|
204
205
|
// tab/mode buttons without needing actual chat state.
|
|
205
206
|
const noop = useCallback(() => { }, []);
|
|
@@ -219,7 +220,7 @@ function ChatLoadingSkeleton({ renderHeader, centerComposerWhenEmpty = false, co
|
|
|
219
220
|
toggleHistory: noop,
|
|
220
221
|
};
|
|
221
222
|
if (centerComposerWhenEmpty) {
|
|
222
|
-
return (_jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [renderHeader ? renderHeader(stubProps) : null, _jsxs("div", { "data-agent-empty-state": "centered", className: "relative flex flex-1 flex-col h-full min-h-0 text-foreground", children: [_jsx("div", { className: "agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: _jsx("div", { className: "agent-empty-state sr-only", "aria-busy": "true", children: "
|
|
223
|
+
return (_jsxs("div", { className: "flex flex-col flex-1 min-h-0", children: [renderHeader ? renderHeader(stubProps) : null, _jsxs("div", { "data-agent-empty-state": "centered", className: "relative flex flex-1 flex-col h-full min-h-0 text-foreground", children: [_jsx("div", { className: "agent-chat-scroll flex-1 overflow-y-auto overflow-x-hidden min-h-0", children: _jsx("div", { className: "agent-empty-state sr-only", "aria-busy": "true", children: t("agentChat.empty.loadingChat") }) }), composerSlot, _jsx("div", { className: "agent-composer-stack", children: _jsx("div", { className: cn("agent-composer-area shrink-0 px-3 py-2", composerLayoutVariant !== "default" &&
|
|
223
224
|
`agent-composer-area--${composerLayoutVariant}`, composerAreaClassName), children: _jsxs("div", { className: cn("agent-composer-root flex flex-col rounded-lg border border-input bg-muted/45 transition-colors", composerLayoutVariant !== "default" &&
|
|
224
225
|
`agent-composer-root--${composerLayoutVariant}`), children: [_jsx("div", { className: "px-3 pt-3", children: _jsx("div", { className: "h-5 w-3/5 rounded bg-muted animate-pulse motion-reduce:animate-none" }) }), _jsxs("div", { className: "mt-auto flex items-center gap-2 px-3 py-2", children: [_jsx("div", { className: "h-5 w-5 rounded bg-muted animate-pulse motion-reduce:animate-none" }), _jsx("div", { className: "ml-auto h-4 w-28 rounded bg-muted animate-pulse motion-reduce:animate-none" }), _jsx("div", { className: "h-7 w-7 rounded-md bg-muted animate-pulse motion-reduce:animate-none" })] })] }) }) })] })] }));
|
|
225
226
|
}
|
|
@@ -721,7 +722,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
721
722
|
(activeTabMessageCount <= 0 && activeTab.status === "idle")) {
|
|
722
723
|
return null;
|
|
723
724
|
}
|
|
724
|
-
return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || "
|
|
725
|
+
return (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || t("agentPanel.chat"), shareUrl: getChatThreadShareUrl(activeTab.id), triggerClassName: "h-7 px-2", defaultOpen: onCollapse && shareFromMenuOpen, onOpenChange: onCollapse ? setShareFromMenuOpen : undefined }));
|
|
725
726
|
})(), feedbackEnabled ? (_jsx(FeedbackButton, { variant: "icon", side: "bottom", align: "end", chatSessionId: activeChatSessionId, chatStorageKey: storageKey, open: feedbackOpen, onOpenChange: setFeedbackOpen, trigger: _jsx("button", { type: "button", tabIndex: -1, "aria-hidden": "true", className: "pointer-events-none absolute end-0 top-full h-px w-px opacity-0" }) })) : null, mode === "chat" && (_jsx(IconTooltip, { content: t("agentPanel.newChat"), children: _jsx("button", { onClick: addTab, "aria-label": t("agentPanel.newChat"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), !onCollapse && mode === "cli" && canUseCodeTools && (_jsx(IconTooltip, { content: t("agentPanel.newTerminal"), children: _jsx("button", { onClick: addCliTab, "aria-label": t("agentPanel.newTerminal"), className: "flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", children: _jsx(IconPlus, { size: 14 }) }) })), _jsxs(DropdownMenu, { open: headerMenuOpen, onOpenChange: setHeaderMenuOpen, children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("button", { className: cn("flex h-6 w-6 items-center justify-center rounded text-muted-foreground hover:text-foreground hover:bg-accent/50", (headerMenuOpen || mode === "settings") &&
|
|
726
727
|
"bg-accent text-foreground"), "aria-label": t("agentPanel.panelOptions"), children: _jsx(IconDotsVertical, { size: 14 }) }) }), _jsxs(DropdownMenuContent, { align: "end", sideOffset: 6, className: "w-48", onCloseAutoFocus: (event) => {
|
|
727
728
|
// A sibling overlay owns focus next; restoring it to the menu
|
|
@@ -785,7 +786,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
785
786
|
? tabs.find((tab) => tab.id === activeTabId)
|
|
786
787
|
: undefined;
|
|
787
788
|
const canShareActiveTab = activeTab && (activeTabMessageCount > 0 || activeTab.status !== "idle");
|
|
788
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", "data-agent-page-chat-fade": "", className: "pointer-events-none absolute inset-x-0 top-0 z-50 h-16 bg-gradient-to-b from-background via-background/90 to-transparent opacity-0 transition-opacity duration-150" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-[60] flex justify-end px-3 sm:top-4 sm:px-4", children: _jsxs("div", { className: "pointer-events-auto flex items-center gap-1", children: [canShareActiveTab ? (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || "
|
|
789
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { "aria-hidden": "true", "data-agent-page-chat-fade": "", className: "pointer-events-none absolute inset-x-0 top-0 z-50 h-16 bg-gradient-to-b from-background via-background/90 to-transparent opacity-0 transition-opacity duration-150" }), _jsx("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-[60] flex justify-end px-3 sm:top-4 sm:px-4", children: _jsxs("div", { className: "pointer-events-auto flex items-center gap-1", children: [canShareActiveTab ? (_jsx(ShareButton, { resourceType: "chat_thread", resourceId: activeTab.id, allowedRoles: ["viewer", "editor", "admin"], resourceTitle: activeTab.label || t("agentPanel.chat"), shareUrl: getChatThreadShareUrl(activeTab.id), triggerClassName: "h-8 px-2 border border-border bg-background/95 shadow-sm backdrop-blur hover:bg-accent" })) : null, _jsxs("button", { type: "button", "data-agent-page-new-chat": "", "aria-label": t("agentPanel.newChat"), onClick: () => {
|
|
789
790
|
addTab();
|
|
790
791
|
}, className: "inline-flex h-8 items-center gap-1.5 rounded-md border border-border bg-background/95 px-2.5 text-xs font-medium text-foreground shadow-sm backdrop-blur transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: [_jsx(IconPlus, { size: 14 }), _jsx("span", { children: t("agentPanel.newChat") })] })] }) })] }));
|
|
791
792
|
}, [getChatThreadShareUrl, t]);
|
|
@@ -829,7 +830,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
829
830
|
activeTab?.parentThreadId === tab.id);
|
|
830
831
|
return (_jsxs("div", { role: "button", tabIndex: 0, ref: isActive ? activeTabRefCb : undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer max-w-[150px]", isActive
|
|
831
832
|
? "bg-accent text-foreground"
|
|
832
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
833
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
833
834
|
e.stopPropagation();
|
|
834
835
|
closeTab(tab.id);
|
|
835
836
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -872,7 +873,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
872
873
|
activeTab?.parentThreadId === tab.id);
|
|
873
874
|
return (_jsxs("div", { role: "button", tabIndex: 0, ref: isActive ? activeTabRefCb : undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer max-w-[150px]", isActive
|
|
874
875
|
? "bg-accent text-foreground"
|
|
875
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
876
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
876
877
|
e.stopPropagation();
|
|
877
878
|
closeTab(tab.id);
|
|
878
879
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -890,7 +891,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
890
891
|
? activeTabRefCb
|
|
891
892
|
: undefined, onClick: () => setActiveCliTab(id), onKeyDown: activateOnKeyDown(() => setActiveCliTab(id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2.5 py-1.5 text-[11px] font-medium cursor-pointer", id === activeCliTab
|
|
892
893
|
? "bg-accent text-foreground"
|
|
893
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsxs("span", { children: ["Terminal ", i + 1] }), _jsx("button", { type: "button", "aria-label": "
|
|
894
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsxs("span", { children: ["Terminal ", i + 1] }), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
894
895
|
e.stopPropagation();
|
|
895
896
|
closeCliTab(id);
|
|
896
897
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -908,7 +909,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
908
909
|
? activeTabRefCb
|
|
909
910
|
: undefined, onClick: () => setActiveTabId(tab.id), onKeyDown: activateOnKeyDown(() => setActiveTabId(tab.id)), className: cn("agent-tab relative flex shrink-0 items-center gap-1 rounded-md px-2 py-1 text-[10px] font-medium cursor-pointer max-w-[140px]", tab.id === activeTabId
|
|
910
911
|
? "bg-accent text-foreground"
|
|
911
|
-
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.subAgentName || tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": "
|
|
912
|
+
: "text-muted-foreground hover:bg-accent hover:text-foreground"), children: [_jsx("span", { className: "truncate pe-1", children: tab.subAgentName || tab.label }), tab.status === "running" && (_jsx("span", { className: "h-1 w-1 shrink-0 rounded-full bg-muted-foreground/50 animate-pulse" })), _jsx("button", { type: "button", "aria-label": t("agentPanel.closeTab"), onClick: (e) => {
|
|
912
913
|
e.stopPropagation();
|
|
913
914
|
closeTab(tab.id);
|
|
914
915
|
}, className: "agent-tab-close flex items-center justify-end text-muted-foreground hover:text-foreground", style: {
|
|
@@ -937,6 +938,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
937
938
|
activeTabRefCb,
|
|
938
939
|
activateOnKeyDown,
|
|
939
940
|
closeCliTab,
|
|
941
|
+
t,
|
|
940
942
|
]);
|
|
941
943
|
return (_jsxs("div", { className: cn("agent-panel-root flex flex-1 flex-col min-h-0 h-full text-[13px] leading-[1.2] antialiased", className), style: {
|
|
942
944
|
...AGENT_PANEL_ROOT_STYLE,
|
|
@@ -972,7 +974,7 @@ function AgentPanelInner({ defaultMode = "chat", className, style, apiUrl, empty
|
|
|
972
974
|
? mode === "cli" &&
|
|
973
975
|
cliTabs.map((id) => (_jsx("div", { className: "min-h-0 relative flex-1", style: {
|
|
974
976
|
display: id === activeCliTab ? undefined : "none",
|
|
975
|
-
}, children: _jsx(Suspense, { fallback: _jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground text-sm", children: "
|
|
977
|
+
}, children: _jsx(Suspense, { fallback: _jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground text-sm", children: t("agentPanel.loadingTerminal") }), children: _jsx(AgentTerminal, { command: selectedCli, hideInFrame: false, className: "h-full", style: { background: "transparent" } }) }) }, id)))
|
|
976
978
|
: mode === "cli" && (_jsx("div", { className: "flex flex-1 flex-col items-center justify-center min-h-0 px-6 gap-3", children: _jsx(CodeAccessUnavailablePanel, { title: codeAccessEnabled
|
|
977
979
|
? t("agentPanel.cliRequiresDevMode")
|
|
978
980
|
: codeUnavailableTitle, description: codeAccessEnabled
|
|
@@ -1405,14 +1407,16 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
|
|
|
1405
1407
|
* Wraps app content with a toggleable agent sidebar.
|
|
1406
1408
|
* Use AgentToggleButton in your header to open/close it.
|
|
1407
1409
|
*/
|
|
1408
|
-
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1410
|
+
export function AgentSidebar({ children, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, apiUrl, agentChatSurface, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1411
|
+
const sidebarOpenStorageKey = openStorageKey ?? storageKey;
|
|
1409
1412
|
const onboardingPreviewMode = useOnboardingPreviewMode();
|
|
1410
1413
|
const firstRunOnboardingGateOwnsSurface = useFirstRunOnboardingGateOwnsSurface();
|
|
1411
1414
|
const showFirstRunOnboarding = !firstRunOnboardingGateOwnsSurface &&
|
|
1412
1415
|
!suppressFirstRunOnboarding &&
|
|
1413
1416
|
(SHOW_FIRST_RUN_ONBOARDING || onboardingPreviewMode);
|
|
1414
1417
|
const initialWidth = defaultSidebarWidth ?? sidebarWidth ?? 380;
|
|
1415
|
-
const [open, setOpen] = useState(() => openOnChatRunning ||
|
|
1418
|
+
const [open, setOpen] = useState(() => openOnChatRunning ||
|
|
1419
|
+
getInitialAgentSidebarOpen(defaultOpen, sidebarOpenStorageKey));
|
|
1416
1420
|
const [presentationMode, setPresentationMode] = useState(false);
|
|
1417
1421
|
const [width, setWidth] = useState(initialWidth);
|
|
1418
1422
|
const [isWideDrawer, setIsWideDrawer] = useState(() => {
|
|
@@ -1469,15 +1473,15 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1469
1473
|
const setOpenPersisted = useCallback((next) => {
|
|
1470
1474
|
setOpen((prev) => {
|
|
1471
1475
|
const value = typeof next === "function" ? next(prev) : next;
|
|
1472
|
-
setAgentSidebarOpenPreference(value,
|
|
1476
|
+
setAgentSidebarOpenPreference(value, sidebarOpenStorageKey);
|
|
1473
1477
|
return value;
|
|
1474
1478
|
});
|
|
1475
|
-
}, [
|
|
1479
|
+
}, [sidebarOpenStorageKey]);
|
|
1476
1480
|
const applyUrlOpenOverride = useCallback(() => {
|
|
1477
|
-
const override = consumeAgentSidebarUrlOpenOverride(
|
|
1481
|
+
const override = consumeAgentSidebarUrlOpenOverride(sidebarOpenStorageKey);
|
|
1478
1482
|
if (override !== null)
|
|
1479
1483
|
setOpenPersisted(override);
|
|
1480
|
-
}, [setOpenPersisted,
|
|
1484
|
+
}, [setOpenPersisted, sidebarOpenStorageKey]);
|
|
1481
1485
|
useEffect(() => {
|
|
1482
1486
|
applyUrlOpenOverride();
|
|
1483
1487
|
return subscribeAgentSidebarUrlChanges(applyUrlOpenOverride);
|
|
@@ -1922,11 +1926,11 @@ export function AgentSidebar({ children, emptyStateText = "How can I help you?",
|
|
|
1922
1926
|
? "desktop"
|
|
1923
1927
|
: undefined, "data-agent-sidebar-layout": panelLayout, "data-agent-sidebar-position": position, "data-agent-sidebar-state": panelOpen ? "open" : "closed", "data-agent-sidebar-resizing": isResizing ? "true" : undefined, "data-agent-sidebar-chat-handoff": chatViewTransitionHandoff ? "true" : undefined, style: chatViewTransition
|
|
1924
1928
|
? getAgentChatViewTransitionStyle(panelStyle)
|
|
1925
|
-
: panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, threadFooterSlot: threadFooterSlot, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
|
|
1929
|
+
: panelStyle, inert: sidebarAnimationEnabled && !panelOpen ? true : undefined, "aria-hidden": sidebarAnimationEnabled && !panelOpen ? true : undefined, children: _jsx("div", { className: "agent-sidebar-panel-inner flex min-h-0 flex-1 flex-col", children: _jsx(AgentPanel, { emptyStateText: emptyStateText, suggestions: suggestions, dynamicSuggestions: dynamicSuggestions, composerToolbarSlot: composerToolbarSlot, composerSlot: composerSlot, onComposerTextChange: onComposerTextChange, imageModelMenu: imageModelMenu, threadFooterSlot: threadFooterSlot, apiUrl: apiUrl, agentChatSurface: agentChatSurface, showTabBar: showTabBar, suppressInlineOpenApp: suppressInlineOpenApp, composerPlaceholder: composerPlaceholder, missingApiKeySetupLayout: "sidebar", onCollapse: () => setOpenPersisted(false), onSnapTo75Percent: isMobile ? undefined : snapTo75Percent, isWideDrawer: isMobile ? false : isWideDrawer, onExitWideDrawer: isMobile ? undefined : exitWideDrawer, onFullViewRequest: onFullscreenRequest, storageKey: storageKey, scope: scope, showScopeBadge: showScopeBadge, browserTabId: browserTabId, threadUrlSync: threadUrlSync, agentPageHref: agentPageHref, allowSettingsMode: false, chatOnly: true }) }) }), showResizeHandle && isLeft && (_jsx(ResizeHandle, { position: position, onDrag: handleDrag, onResizeStart: handleResizeStart, onResizeEnd: handleResizeEnd }))] })) : null;
|
|
1926
1930
|
const drawerPlaceholder = wideDrawerEnabled && !presentationMode && panelOpen ? (_jsx("div", { "aria-hidden": "true", className: "agent-sidebar-drawer-placeholder shrink-0", "data-agent-sidebar-placeholder": "true", style: { width: drawerPlaceholderWidth + 1 } })) : null;
|
|
1927
1931
|
return (_jsx(AgentSidebarOnboardingContext.Provider, { value: true, children: _jsxs(RealtimeVoiceModeProvider, { browserTabId: browserTabId, children: [showFirstRunOnboarding && (_jsx(Suspense, { fallback: null, children: _jsx(FirstRunOnboarding, {}) })), _jsxs("div", { className: "agent-sidebar-shell flex min-w-0 flex-1 h-screen overflow-hidden", "data-agent-sidebar-position": position, "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: [isMobile &&
|
|
1928
1932
|
!presentationMode &&
|
|
1929
|
-
(mobileAnimationEnabled ? shouldRenderPanel : open) && (_jsx("div", { className: cn("agent-sidebar-backdrop fixed inset-0 bg-foreground/40", mobileAnimationEnabled && !panelOpen && "pointer-events-none"), "data-agent-sidebar-animation": mobileAnimationEnabled ? "mobile" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", style: { zIndex: SIDEBAR_OVERLAY_Z_INDEX - 1 }, onClick: () => setOpenPersisted(false) })), shouldMountPanel ? _jsx(URLSync, { browserTabId: browserTabId }) : null, isLeft && !presentationMode ? sidebar : null, isLeft && !presentationMode ? drawerPlaceholder : null, _jsx("div", { className: "agent-sidebar-main-surface flex flex-1 flex-col overflow-auto min-w-0", "data-agent-sidebar-main-position": position, "data-agent-sidebar-main-state": !isMobile && !presentationMode && panelOpen ? "open" : "closed", "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: _jsx(ScreenRefreshBoundary, { children: children }) }), !isLeft && !presentationMode ? drawerPlaceholder : null, !isLeft && !presentationMode ? sidebar : null] })] }) }));
|
|
1933
|
+
(mobileAnimationEnabled ? shouldRenderPanel : open) && (_jsx("div", { className: cn("agent-sidebar-backdrop fixed inset-0 bg-foreground/40", mobileAnimationEnabled && !panelOpen && "pointer-events-none"), "data-agent-sidebar-animation": mobileAnimationEnabled ? "mobile" : undefined, "data-agent-sidebar-state": panelOpen ? "open" : "closed", style: { zIndex: SIDEBAR_OVERLAY_Z_INDEX - 1 }, onClick: () => setOpenPersisted(false) })), shouldMountPanel ? _jsx(URLSync, { browserTabId: browserTabId }) : null, isResizing ? (_jsx("div", { "aria-hidden": "true", className: "agent-sidebar-resize-overlay" })) : null, isLeft && !presentationMode ? sidebar : null, isLeft && !presentationMode ? drawerPlaceholder : null, _jsx("div", { className: "agent-sidebar-main-surface flex flex-1 flex-col overflow-auto min-w-0", "data-agent-sidebar-main-position": position, "data-agent-sidebar-main-state": !isMobile && !presentationMode && panelOpen ? "open" : "closed", "data-agent-sidebar-resizing": isResizing ? "true" : undefined, children: _jsx(ScreenRefreshBoundary, { children: children }) }), !isLeft && !presentationMode ? drawerPlaceholder : null, !isLeft && !presentationMode ? sidebar : null] })] }) }));
|
|
1930
1934
|
}
|
|
1931
1935
|
/**
|
|
1932
1936
|
* Focus the agent chat composer input.
|
|
@@ -1957,6 +1961,7 @@ export function focusAgentChat() {
|
|
|
1957
1961
|
* Dispatches a custom event that AgentSidebar listens for.
|
|
1958
1962
|
*/
|
|
1959
1963
|
export function AgentToggleButton({ className }) {
|
|
1964
|
+
const t = useT();
|
|
1960
1965
|
const [open, setOpen] = useState(false);
|
|
1961
1966
|
useEffect(() => {
|
|
1962
1967
|
const handler = (event) => {
|
|
@@ -1972,5 +1977,5 @@ export function AgentToggleButton({ className }) {
|
|
|
1972
1977
|
// own close button.
|
|
1973
1978
|
if (open)
|
|
1974
1979
|
return null;
|
|
1975
|
-
return (_jsx(DesignSystemTooltip, { trigger: _jsx("button", { type: "button", "aria-label": "
|
|
1980
|
+
return (_jsx(DesignSystemTooltip, { trigger: _jsx("button", { type: "button", "aria-label": t("agentPanel.toggleAgent"), onClick: () => window.dispatchEvent(new Event("agent-panel:toggle")), className: cn("inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent/40 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className), children: _jsx(IconMessageDots, { size: 20, "aria-hidden": true }) }), content: t("agentPanel.toggleAgent"), delayMs: 200 }));
|
|
1976
1981
|
}
|
|
@@ -132,11 +132,22 @@ export declare function resolveAssistantChatRunningState({ forceStopped, isRunti
|
|
|
132
132
|
isRunning: boolean;
|
|
133
133
|
showRunningInUI: boolean;
|
|
134
134
|
};
|
|
135
|
-
export declare function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent, }: {
|
|
135
|
+
export declare function resolveAssistantChatRunningStatusLabel({ runningActivityLabel, isAutoResuming, isReconnecting, hasReconnectContent, labels, }: {
|
|
136
136
|
runningActivityLabel: string | null | undefined;
|
|
137
137
|
isAutoResuming: boolean;
|
|
138
138
|
isReconnecting: boolean;
|
|
139
139
|
hasReconnectContent: boolean;
|
|
140
|
+
labels?: {
|
|
141
|
+
thinking: string;
|
|
142
|
+
resuming: string;
|
|
143
|
+
stillWorking: string;
|
|
144
|
+
working?: string;
|
|
145
|
+
contactingModel?: string;
|
|
146
|
+
starting?: (activity: string) => string;
|
|
147
|
+
preparing?: (activity: string) => string;
|
|
148
|
+
writing?: (activity: string) => string;
|
|
149
|
+
stillGenerating?: (activity: string) => string;
|
|
150
|
+
};
|
|
140
151
|
}): string;
|
|
141
152
|
export declare function resolveAssistantChatComposerPlaceholder(composerPlaceholder: string | null | undefined): string;
|
|
142
153
|
export declare function shouldShowGlobalRunningStatus({ showRunningInUI, runningActivityLabel, runningActivityTool, latestMessage, reconnectContent, }: {
|
|
@@ -311,6 +322,8 @@ export interface AssistantChatProps {
|
|
|
311
322
|
composerToolbarSlot?: React.ReactNode;
|
|
312
323
|
/** Optional action rendered beside the voice/send controls. */
|
|
313
324
|
composerExtraActionButton?: React.ReactNode;
|
|
325
|
+
/** Show the framework model picker in the shared composer. Defaults to true. */
|
|
326
|
+
showModelSelector?: boolean;
|
|
314
327
|
/** Disable the composer for capability-gated surfaces while still showing history. */
|
|
315
328
|
composerDisabled?: boolean;
|
|
316
329
|
/** Placeholder to show while the composer is disabled by the host surface. */
|
|
@@ -410,6 +423,7 @@ export interface AssistantChatProps {
|
|
|
410
423
|
onAlwaysAllow?: (approvalKey: string) => void;
|
|
411
424
|
};
|
|
412
425
|
}
|
|
426
|
+
export declare function shouldShowAssistantChatModelSelector(showModelSelector: boolean | undefined): boolean;
|
|
413
427
|
export declare const CHAT_STORAGE_PREFIX = "agent-chat:";
|
|
414
428
|
/** Remove persisted chat for a given tabId (or "default"). */
|
|
415
429
|
export declare function clearChatStorage(tabId?: string): void;
|