@agent-native/core 0.203.0-nightly-20261007064822 → 0.203.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/agent/engine/builder-engine.d.ts +1 -1
  2. package/dist/agent/model-config.d.ts +2 -2
  3. package/dist/agent/model-config.js +0 -2
  4. package/dist/agent/thread-data-builder.d.ts +6 -0
  5. package/dist/agent/thread-data-builder.js +747 -25
  6. package/dist/agent/thread-message-projection.d.ts +20 -0
  7. package/dist/agent/thread-message-projection.js +300 -0
  8. package/dist/automation/index.d.ts +1 -1
  9. package/dist/chat-threads/store.d.ts +4 -1
  10. package/dist/chat-threads/store.js +92 -17
  11. package/dist/cli/skills-content/turn-into-app-skill.d.ts +10 -4
  12. package/dist/cli/skills-content/turn-into-app-skill.js +2454 -705
  13. package/dist/cli/skills.d.ts +6 -0
  14. package/dist/cli/skills.js +8 -2
  15. package/dist/client/chat/agentkit-agent-native.js +839 -89
  16. package/dist/client/chat/agentkit-protocol.js +67 -17
  17. package/dist/collab/routes.d.ts +2 -2
  18. package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
  19. package/dist/mcp/build-server.d.ts +5 -1
  20. package/dist/mcp/build-server.js +56 -13
  21. package/dist/mcp/embed-app.js +6 -1
  22. package/dist/notifications/routes.d.ts +1 -1
  23. package/dist/observability/routes.d.ts +3 -3
  24. package/dist/org/index.d.ts +2 -2
  25. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  26. package/dist/resources/handlers.d.ts +1 -1
  27. package/dist/server/agent-chat/mcp-options.d.ts +4 -0
  28. package/dist/server/agent-chat-plugin.js +97 -22
  29. package/dist/server/agent-engine-default-model-route.d.ts +2 -2
  30. package/dist/server/onboarding-html.js +1 -1
  31. package/dist/server/realtime-token.d.ts +1 -1
  32. package/dist/server/transcribe-voice.d.ts +1 -1
  33. package/dist/shared/embed-auth.js +5 -4
  34. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  35. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -24
  36. package/dist/templates/factory/.agents/skills/review-latest-feedback/references/deployment-recovery.md +53 -0
  37. package/dist/templates/factory/.agents/skills/review-latest-feedback/references/documentation-proof.md +7 -0
  38. package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +284 -461
  39. package/dist/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
  40. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +65 -90
  41. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/local-run-and-deploy.md +161 -0
  42. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +384 -0
  43. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/source-brief.md +116 -0
  44. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/spreadsheet-source.md +206 -190
  45. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-archetypes.md +381 -0
  46. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-direction.md +323 -0
  47. package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/ui-palettes.md +564 -0
  48. package/dist/triggers/actions/manage-automation.d.ts +7 -7
  49. package/docs/content/observability.mdx +136 -0
  50. package/package.json +4 -4
  51. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -24
  52. package/src/templates/factory/.agents/skills/review-latest-feedback/references/deployment-recovery.md +53 -0
  53. package/src/templates/factory/.agents/skills/review-latest-feedback/references/documentation-proof.md +7 -0
  54. package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +284 -461
  55. package/src/templates/workspace-core/.agents/skills/turn-into-app/agents/openai.yaml +2 -2
  56. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +65 -90
  57. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/local-run-and-deploy.md +161 -0
  58. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +384 -0
  59. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/source-brief.md +116 -0
  60. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/spreadsheet-source.md +206 -190
  61. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-archetypes.md +381 -0
  62. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-direction.md +323 -0
  63. package/src/templates/workspace-core/.agents/skills/turn-into-app/references/ui-palettes.md +564 -0
@@ -790,6 +790,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
790
790
  }
791
791
  const sessions = new Map();
792
792
  const runs = new Map();
793
+ const runtimeRunAliases = new Map();
793
794
  const disposedSessions = new WeakSet();
794
795
  let retentionTimer;
795
796
  let disposed = false;
@@ -805,6 +806,53 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
805
806
  const parsed = Date.parse(value);
806
807
  return Number.isFinite(parsed) ? parsed : Date.now();
807
808
  }
809
+ function runtimeRunAliasKey(threadId, runtimeRunId) {
810
+ return JSON.stringify([threadId, runtimeRunId]);
811
+ }
812
+ function findRun(threadId, runId) {
813
+ const run = runs.get(runId);
814
+ if (run?.threadId === threadId)
815
+ return run;
816
+ const aliasKey = runtimeRunAliasKey(threadId, runId);
817
+ const aliasedRun = runtimeRunAliases.get(aliasKey);
818
+ if (!aliasedRun)
819
+ return undefined;
820
+ if (runs.get(aliasedRun.runId) !== aliasedRun) {
821
+ runtimeRunAliases.delete(aliasKey);
822
+ return undefined;
823
+ }
824
+ return aliasedRun;
825
+ }
826
+ function indexRun(run, runtimeRunId = run.turn.runId ?? run.runId) {
827
+ const existingRun = runs.get(run.runId);
828
+ if (existingRun && existingRun !== run) {
829
+ throw new Error(`Duplicate AgentKit run id: ${run.runId}`);
830
+ }
831
+ if (runtimeRunId && runtimeRunId !== run.runId) {
832
+ const conflictingRun = runs.get(runtimeRunId);
833
+ if (conflictingRun?.threadId === run.threadId) {
834
+ throw new Error(`Runtime run id ${runtimeRunId} conflicts with an AgentKit run id.`);
835
+ }
836
+ const aliasKey = runtimeRunAliasKey(run.threadId, runtimeRunId);
837
+ const previousRun = runtimeRunAliases.get(aliasKey);
838
+ if (previousRun &&
839
+ previousRun !== run &&
840
+ runs.get(previousRun.runId) === previousRun &&
841
+ !previousRun.terminal) {
842
+ throw new Error(`Runtime run id ${runtimeRunId} is already owned by active AgentKit run ${previousRun.runId}.`);
843
+ }
844
+ runtimeRunAliases.set(aliasKey, run);
845
+ }
846
+ runs.set(run.runId, run);
847
+ }
848
+ function removeRun(run) {
849
+ if (runs.get(run.runId) === run)
850
+ runs.delete(run.runId);
851
+ for (const [aliasKey, aliasedRun] of runtimeRunAliases) {
852
+ if (aliasedRun === run)
853
+ runtimeRunAliases.delete(aliasKey);
854
+ }
855
+ }
808
856
  function touchRun(run) {
809
857
  run.lastAccessedAtMs = timeMs();
810
858
  }
@@ -840,7 +888,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
840
888
  for (const run of evictable) {
841
889
  if (run.terminalAtMs !== undefined &&
842
890
  referenceTimeMs - run.terminalAtMs >= retainedRunTtlMs) {
843
- runs.delete(run.runId);
891
+ removeRun(run);
844
892
  }
845
893
  }
846
894
  const retainedCompleted = [...runs.values()]
@@ -851,7 +899,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
851
899
  while (retainedCompleted.length > maxRetainedRuns) {
852
900
  const run = retainedCompleted.shift();
853
901
  if (run)
854
- runs.delete(run.runId);
902
+ removeRun(run);
855
903
  }
856
904
  scheduleRetentionSweep(referenceTimeMs);
857
905
  }
@@ -1046,7 +1094,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
1046
1094
  ...(runAuthority ? { restoredWithoutStream: true } : {}),
1047
1095
  listeners: new Set(),
1048
1096
  };
1049
- runs.set(input.runId, run);
1097
+ indexRun(run, input.runId);
1050
1098
  append(run, {
1051
1099
  type: "run.started",
1052
1100
  agentId: runtime.id,
@@ -2367,6 +2415,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2367
2415
  run.successorWaitStartedAtMs = undefined;
2368
2416
  }
2369
2417
  run.turn = resumed;
2418
+ indexRun(run, resumed.runId);
2370
2419
  }
2371
2420
  function ensurePump(run) {
2372
2421
  if (run.pumpPromise || run.streamClosed || run.terminal || !run.turn)
@@ -2574,7 +2623,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2574
2623
  throw new Error("The AgentKit adapter was disposed during turn creation.");
2575
2624
  }
2576
2625
  pruneRetainedRuns(run.lastAccessedAtMs);
2577
- runs.set(runId, run);
2626
+ indexRun(run, turn.runId);
2578
2627
  append(run, {
2579
2628
  type: "run.started",
2580
2629
  agentId: runtime.id,
@@ -2586,10 +2635,11 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2586
2635
  },
2587
2636
  async *subscribeToRun(input) {
2588
2637
  pruneRetainedRuns();
2589
- let run = runs.get(input.runId);
2590
- if (!run || run.threadId !== input.threadId) {
2591
- if (run)
2638
+ let run = findRun(input.threadId, input.runId);
2639
+ if (!run) {
2640
+ if (runs.has(input.runId)) {
2592
2641
  throw new Error(`Unknown AgentKit run: ${input.runId}`);
2642
+ }
2593
2643
  run = await restoreRunFromRuntime(input);
2594
2644
  }
2595
2645
  touchRun(run);
@@ -2598,8 +2648,8 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2598
2648
  },
2599
2649
  async getRun(input) {
2600
2650
  pruneRetainedRuns();
2601
- const run = runs.get(input.runId);
2602
- if (!run || run.threadId !== input.threadId)
2651
+ const run = findRun(input.threadId, input.runId);
2652
+ if (!run)
2603
2653
  return null;
2604
2654
  touchRun(run);
2605
2655
  return {
@@ -2617,8 +2667,8 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2617
2667
  },
2618
2668
  async cancelRun(input) {
2619
2669
  pruneRetainedRuns();
2620
- let run = runs.get(input.runId);
2621
- if (run && run.threadId !== input.threadId) {
2670
+ let run = findRun(input.threadId, input.runId);
2671
+ if (!run && runs.has(input.runId)) {
2622
2672
  throw new Error(`Unknown AgentKit run: ${input.runId}`);
2623
2673
  }
2624
2674
  if (!run) {
@@ -2634,7 +2684,6 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2634
2684
  }
2635
2685
  }
2636
2686
  run = await restoreRunFromRuntime(input);
2637
- runs.set(input.runId, run);
2638
2687
  }
2639
2688
  touchRun(run);
2640
2689
  if (run.terminal)
@@ -2799,8 +2848,8 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2799
2848
  if (runtime.capabilities.tools?.approvals) {
2800
2849
  const resumeRun = async (input) => {
2801
2850
  pruneRetainedRuns();
2802
- const run = runs.get(input.runId);
2803
- if (!run || run.threadId !== input.threadId) {
2851
+ const run = findRun(input.threadId, input.runId);
2852
+ if (!run) {
2804
2853
  throw new Error(`Unknown AgentKit run: ${input.runId}`);
2805
2854
  }
2806
2855
  touchRun(run);
@@ -2895,7 +2944,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2895
2944
  run.pendingApprovalId = undefined;
2896
2945
  run.terminal = true;
2897
2946
  run.terminalAtMs = timeMs();
2898
- runs.set(nextRunId, replacementRun);
2947
+ indexRun(replacementRun, nextTurn.runId);
2899
2948
  append(replacementRun, {
2900
2949
  type: "run.started",
2901
2950
  agentId: runtime.id,
@@ -2938,8 +2987,8 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
2938
2987
  if (runtime.capabilities.rich?.connectionRequests) {
2939
2988
  transport.resolveConnectionRequest = async (input) => {
2940
2989
  pruneRetainedRuns();
2941
- const run = runs.get(input.runId);
2942
- if (!run || run.threadId !== input.threadId) {
2990
+ const run = findRun(input.threadId, input.runId);
2991
+ if (!run) {
2943
2992
  throw new Error(`Unknown AgentKit run: ${input.runId}`);
2944
2993
  }
2945
2994
  touchRun(run);
@@ -3006,6 +3055,7 @@ export function createAgentKitProtocolAdapter(runtime, options = {}) {
3006
3055
  run.waitingForContinuation = false;
3007
3056
  run.pendingConnectionRequestId = undefined;
3008
3057
  run.turn = nextTurn;
3058
+ indexRun(run, nextTurn.runId);
3009
3059
  run.streamClosed = false;
3010
3060
  update(input.response.status);
3011
3061
  append(run, { type: "run.status", status: "running" });
@@ -8,16 +8,16 @@ 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;
16
16
  }>>;
17
17
  export declare const postCollabText: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
18
18
  ok?: undefined;
19
- error: string;
20
19
  text?: undefined;
20
+ error: string;
21
21
  } | {
22
22
  error?: undefined;
23
23
  ok: boolean;
@@ -11,9 +11,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
11
11
  enabled?: undefined;
12
12
  nextRun?: undefined;
13
13
  } | {
14
- deleted?: undefined;
15
14
  name: string;
16
15
  enabled: boolean;
17
16
  nextRun: string;
17
+ deleted?: undefined;
18
18
  }>;
19
19
  export default _default;
@@ -31,7 +31,7 @@ export interface MCPConfig {
31
31
  * no-op. See `external-agents` skill, "Dev vs production tool surface".
32
32
  */
33
33
  productionActions?: Record<string, ActionEntry>;
34
- /** Hidden from tool discovery; used only when minting scoped widget tickets. */
34
+ /** Unlisted from this MCP surface; used only when minting scoped widget tickets. */
35
35
  widgetReadActions?: Record<string, ActionEntry>;
36
36
  askAgent?: (message: string) => Promise<string>;
37
37
  builtinCrossAppTools?: boolean;
@@ -61,6 +61,10 @@ export interface MCPConfig {
61
61
  widgetReadPublicActions?: readonly string[];
62
62
  /** Unlisted authenticated reads available only through a scoped widget ticket. */
63
63
  widgetReadPrivateActions?: readonly string[];
64
+ /** Authenticated reads surfaced on other agent profiles, but only scoped here. */
65
+ widgetReadAuthenticatedActions?: readonly string[];
66
+ /** Omit the one shared resource title when tools have distinct invocation labels. */
67
+ widgetResourceTitle?: string | false;
64
68
  keyToolNames?: readonly string[];
65
69
  toolDescriptions?: Record<string, string>;
66
70
  toolParameterDescriptions?: Record<string, Record<string, string>>;
@@ -122,10 +122,10 @@ export function isMcpAppsInlineEnabled(identity) {
122
122
  }
123
123
  return false;
124
124
  }
125
- function isActionVisibleForOAuthScope(entry, scopes) {
125
+ function isActionVisibleForOAuthScope(entry, scopes, readOnlyOverride = false) {
126
126
  if (!scopes)
127
127
  return true;
128
- const required = entry.readOnly === true ? "mcp:read" : "mcp:write";
128
+ const required = entry.readOnly === true || readOnlyOverride ? "mcp:read" : "mcp:write";
129
129
  return hasMcpOAuthScope(scopes, required);
130
130
  }
131
131
  const TOOL_SEARCH_TOOL_NAME = "tool-search";
@@ -168,7 +168,11 @@ export function selectMcpActionSurface(config, requestMeta) {
168
168
  export function selectMcpDirectoryWidgetReadActions(profile, actions) {
169
169
  if (!profile)
170
170
  return undefined;
171
- return Object.fromEntries((profile.widgetReadPrivateActions ?? [])
171
+ const names = new Set([
172
+ ...(profile.widgetReadPrivateActions ?? []),
173
+ ...(profile.widgetReadAuthenticatedActions ?? []),
174
+ ]);
175
+ return Object.fromEntries([...names]
172
176
  .map((name) => [name, actions[name]])
173
177
  .filter((entry) => Boolean(entry[1])));
174
178
  }
@@ -225,9 +229,11 @@ export function validateMcpDirectoryProfile(config, sourceActions = config.produ
225
229
  const widgetReadOnlyActions = new Set(profile?.widgetReadOnlyActions ?? []);
226
230
  const widgetReadPublicActions = new Set(profile?.widgetReadPublicActions ?? []);
227
231
  const widgetReadPrivateActions = new Set(profile?.widgetReadPrivateActions ?? []);
228
- const unprofiledWidgetReadAction = Object.keys(config.widgetReadActions ?? {}).find((name) => !widgetReadPrivateActions.has(name));
232
+ const widgetReadAuthenticatedActions = new Set(profile?.widgetReadAuthenticatedActions ?? []);
233
+ const unprofiledWidgetReadAction = Object.keys(config.widgetReadActions ?? {}).find((name) => !widgetReadPrivateActions.has(name) &&
234
+ !widgetReadAuthenticatedActions.has(name));
229
235
  if (unprofiledWidgetReadAction) {
230
- throw new McpDirectoryProfileValidationError(`[agent-native] MCP directory hidden widget read "${unprofiledWidgetReadAction}" must be listed in widgetReadPrivateActions.`);
236
+ throw new McpDirectoryProfileValidationError(`[agent-native] MCP directory widget read "${unprofiledWidgetReadAction}" must be listed in its scoped read category.`);
231
237
  }
232
238
  const widgetTargetNames = Object.keys(profile?.widgetTargets ?? {});
233
239
  if (profile && profile.widgets !== false && profile.widgetTargets) {
@@ -241,8 +247,10 @@ export function validateMcpDirectoryProfile(config, sourceActions = config.produ
241
247
  }
242
248
  }
243
249
  for (const name of widgetReadOnlyActions) {
244
- const entry = actions[name];
245
- if (!names.includes(name) ||
250
+ const entry = actions[name] ?? config.widgetReadActions?.[name];
251
+ if ((!names.includes(name) &&
252
+ !widgetReadAuthenticatedActions.has(name) &&
253
+ !widgetReadPrivateActions.has(name)) ||
246
254
  !profile?.widgetReadActionArguments?.[name] ||
247
255
  !entry ||
248
256
  entry.http === false ||
@@ -276,17 +284,34 @@ export function validateMcpDirectoryProfile(config, sourceActions = config.produ
276
284
  throw new McpDirectoryProfileValidationError(`[agent-native] MCP directory hidden widget read "${name}" must be an unlisted, authenticated, read-only GET action hidden from every agent tool surface.`);
277
285
  }
278
286
  }
287
+ for (const name of widgetReadAuthenticatedActions) {
288
+ const entry = actions[name] ?? config.widgetReadActions?.[name];
289
+ if (names.includes(name) ||
290
+ !profile?.widgetReadActionArguments?.[name] ||
291
+ !entry ||
292
+ (entry.readOnly !== true && !widgetReadOnlyActions.has(name)) ||
293
+ entry.http === false ||
294
+ entry.http?.method !== "GET" ||
295
+ entry.requiresAuth === false ||
296
+ isActionHiddenFromEveryAgentSurface(entry)) {
297
+ throw new McpDirectoryProfileValidationError(`[agent-native] MCP directory scoped authenticated widget read "${name}" must be unlisted, authenticated, read-only, and available on another agent surface.`);
298
+ }
299
+ }
279
300
  for (const [name, argumentMap] of Object.entries(profile?.widgetReadActionArguments ?? {})) {
280
301
  const scopedPrivateRead = widgetReadPrivateActions.has(name);
302
+ const scopedAuthenticatedRead = widgetReadAuthenticatedActions.has(name);
281
303
  const entry = actions[name] ?? config.widgetReadActions?.[name];
282
304
  const scopedPublicRead = widgetReadPublicActions.has(name);
283
- if ((!names.includes(name) && !scopedPublicRead && !scopedPrivateRead) ||
305
+ if ((!names.includes(name) &&
306
+ !scopedPublicRead &&
307
+ !scopedPrivateRead &&
308
+ !scopedAuthenticatedRead) ||
284
309
  !entry ||
285
310
  (entry.readOnly !== true && !widgetReadOnlyActions.has(name)) ||
286
311
  entry.http === false ||
287
312
  entry.http?.method !== "GET" ||
288
313
  (entry.requiresAuth === false && !scopedPublicRead) ||
289
- Object.keys(argumentMap).length === 0 ||
314
+ (Object.keys(argumentMap).length === 0 && !scopedAuthenticatedRead) ||
290
315
  Object.entries(argumentMap).some(([argumentName, argument]) => !MCP_DIRECTORY_WIDGET_ARGUMENT.test(argumentName) ||
291
316
  (typeof argument === "string"
292
317
  ? !MCP_DIRECTORY_WIDGET_ARGUMENT.test(argument)
@@ -822,15 +847,19 @@ function mcpDirectoryWidgetCapabilityForTool(config, resource, toolName, args, r
822
847
  for (const [actionName, argumentMap] of Object.entries(profile.widgetReadActionArguments ?? {})) {
823
848
  const scopedPublicRead = profile.widgetReadPublicActions?.includes(actionName);
824
849
  const scopedPrivateRead = profile.widgetReadPrivateActions?.includes(actionName);
850
+ const scopedAuthenticatedRead = profile.widgetReadAuthenticatedActions?.includes(actionName);
825
851
  const entry = actions[actionName] ??
826
- (scopedPrivateRead ? config.widgetReadActions?.[actionName] : undefined);
852
+ (scopedPrivateRead || scopedAuthenticatedRead
853
+ ? config.widgetReadActions?.[actionName]
854
+ : undefined);
827
855
  if (!entry ||
828
856
  (!profile.connectorCatalog.includes(actionName) &&
829
857
  !scopedPublicRead &&
830
- !scopedPrivateRead) ||
858
+ !scopedPrivateRead &&
859
+ !scopedAuthenticatedRead) ||
831
860
  (entry.readOnly !== true &&
832
861
  !profile.widgetReadOnlyActions?.includes(actionName)) ||
833
- !isActionVisibleForOAuthScope(entry, oauthScopes) ||
862
+ !isActionVisibleForOAuthScope(entry, oauthScopes, profile.widgetReadOnlyActions?.includes(actionName) === true) ||
834
863
  entry.http === false ||
835
864
  entry.http?.method !== "GET" ||
836
865
  (entry.requiresAuth === false && !scopedPublicRead)) {
@@ -1348,12 +1377,26 @@ async function getMcpAppResources(config, actions, identity, requestMeta) {
1348
1377
  if (config.catalogMode !== "directory")
1349
1378
  return resolved;
1350
1379
  const seenUris = new Set();
1351
- return resolved.filter((resource) => {
1380
+ const unique = resolved.filter((resource) => {
1352
1381
  if (seenUris.has(resource.uri))
1353
1382
  return false;
1354
1383
  seenUris.add(resource.uri);
1355
1384
  return true;
1356
1385
  });
1386
+ const resourceTitle = config.directoryProfile?.widgetResourceTitle;
1387
+ if (resourceTitle === undefined)
1388
+ return unique;
1389
+ return unique.map((resource) => {
1390
+ const titled = { ...resource };
1391
+ if (resourceTitle === false) {
1392
+ titled.name = config.title ?? config.appId ?? resource.name;
1393
+ delete titled.title;
1394
+ }
1395
+ else {
1396
+ titled.title = resourceTitle;
1397
+ }
1398
+ return titled;
1399
+ });
1357
1400
  }
1358
1401
  function renderMcpAppHtml(resource, actionName, config, requestMeta) {
1359
1402
  if (typeof resource.html === "function") {
@@ -1839,7 +1839,8 @@ export function embedApp(options = {}) {
1839
1839
 
1840
1840
  function updateTitle(data) {
1841
1841
  const record = objectValue(data);
1842
- const label = record.label || record.app || record.view || body.dataset.appTitle || "App";
1842
+ const openLink = objectValue(toolResponseMetadata["agent-native/openLink"]);
1843
+ const label = record.label || openLink.label || record.app || record.view || body.dataset.appTitle || "App";
1843
1844
  titleEl.textContent = String(label);
1844
1845
  }
1845
1846
 
@@ -1888,6 +1889,9 @@ export function embedApp(options = {}) {
1888
1889
  toolResultData = objectValue(data);
1889
1890
  openUrl = openLinkFrom(params, data);
1890
1891
  openStartUrl = embedStartUrlFrom(params, data);
1892
+ const openLinkLabel = objectValue(
1893
+ toolResponseMetadata["agent-native/openLink"],
1894
+ ).label;
1891
1895
  // set_globals fires constantly, and this sync calls notifyHostHeight/
1892
1896
  // sendHostContext which the host echoes back as another set_globals — an
1893
1897
  // infinite storm. Only do the host round-trips + (re)launch when something
@@ -1900,6 +1904,7 @@ export function embedApp(options = {}) {
1900
1904
  toolResponseMetadata["agent-native/widgetSource"],
1901
1905
  openUrl,
1902
1906
  openStartUrl,
1907
+ openLinkLabel,
1903
1908
  bridge.displayMode,
1904
1909
  bridge.theme,
1905
1910
  bridge.locale
@@ -16,6 +16,6 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
16
16
  } | {
17
17
  count?: undefined;
18
18
  updated?: undefined;
19
- error?: undefined;
20
19
  ok: boolean;
20
+ error?: undefined;
21
21
  }>>;
@@ -34,18 +34,18 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
34
34
  id?: undefined;
35
35
  ok?: undefined;
36
36
  } | {
37
- error?: undefined;
38
37
  message?: undefined;
39
38
  summary: import("./types.js").TraceSummary;
40
39
  spans: import("./types.js").TraceSpan[];
41
40
  id?: undefined;
41
+ error?: undefined;
42
42
  ok?: undefined;
43
43
  } | {
44
- error?: undefined;
45
44
  message?: undefined;
46
45
  summary?: undefined;
47
46
  spans?: undefined;
48
47
  id: string;
48
+ error?: undefined;
49
49
  ok?: undefined;
50
50
  } | {
51
51
  message?: undefined;
@@ -55,10 +55,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
55
55
  error: any;
56
56
  ok?: undefined;
57
57
  } | {
58
- error?: undefined;
59
58
  message?: undefined;
60
59
  summary?: undefined;
61
60
  spans?: undefined;
62
61
  id?: undefined;
62
+ error?: undefined;
63
63
  ok: boolean;
64
64
  }>>;
@@ -177,10 +177,10 @@ export declare const getMyOrgHandler: import("h3").EventHandlerWithFetch<import(
177
177
  soloDeploymentAdmin: boolean | undefined;
178
178
  }>>;
179
179
  export declare const createOrgHandler: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
180
- role?: undefined;
181
- id?: undefined;
182
180
  name?: undefined;
183
181
  success: boolean;
182
+ id?: undefined;
183
+ role?: undefined;
184
184
  } | {
185
185
  success?: undefined;
186
186
  id: string;
@@ -311,7 +311,6 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
311
311
  notes?: string | undefined;
312
312
  scope?: "org" | "user" | undefined;
313
313
  }, {
314
- message?: undefined;
315
314
  deleted?: undefined;
316
315
  found?: undefined;
317
316
  providers: {
@@ -328,8 +327,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
328
327
  registered?: undefined;
329
328
  id?: undefined;
330
329
  label?: undefined;
331
- } | {
332
330
  message?: undefined;
331
+ } | {
333
332
  deleted?: undefined;
334
333
  count?: undefined;
335
334
  providers?: undefined;
@@ -338,8 +337,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
338
337
  registered?: undefined;
339
338
  id?: undefined;
340
339
  label?: undefined;
341
- } | {
342
340
  message?: undefined;
341
+ } | {
343
342
  deleted?: undefined;
344
343
  count?: undefined;
345
344
  providers?: undefined;
@@ -348,8 +347,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
348
347
  id: string;
349
348
  registered?: undefined;
350
349
  label?: undefined;
351
- } | {
352
350
  message?: undefined;
351
+ } | {
353
352
  count?: undefined;
354
353
  found?: undefined;
355
354
  providers?: undefined;
@@ -358,6 +357,7 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
358
357
  id: string;
359
358
  registered?: undefined;
360
359
  label?: undefined;
360
+ message?: undefined;
361
361
  } | {
362
362
  deleted?: undefined;
363
363
  count?: undefined;
@@ -39,8 +39,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
39
39
  error: string;
40
40
  }>;
41
41
  export declare function handleDeleteResource(event: any): Promise<{
42
- ok?: undefined;
43
42
  error: string;
43
+ ok?: undefined;
44
44
  } | {
45
45
  error?: undefined;
46
46
  ok: boolean;
@@ -23,6 +23,10 @@ export interface AgentChatMcpOptions {
23
23
  widgetReadPublicActions?: readonly string[];
24
24
  /** Unlisted authenticated reads available only through a scoped widget ticket. */
25
25
  widgetReadPrivateActions?: readonly string[];
26
+ /** Authenticated reads surfaced on other agent profiles, but only scoped here. */
27
+ widgetReadAuthenticatedActions?: readonly string[];
28
+ /** Omit the one shared resource title when tools have distinct invocation labels. */
29
+ widgetResourceTitle?: string | false;
26
30
  keyToolNames?: readonly string[];
27
31
  toolDescriptions?: Record<string, string>;
28
32
  toolParameterDescriptions?: Record<string, Record<string, string>>;