@agent-native/core 0.157.5 → 0.157.7

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 (109) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/agent-native.config.ts +5 -0
  3. package/corpus/templates/analytics/netlify.toml +1 -0
  4. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +23 -5
  5. package/corpus/templates/analytics/server/plugins/agent-chat.ts +4 -0
  6. package/corpus/templates/assets/netlify.toml +3 -0
  7. package/corpus/templates/brain/netlify.toml +3 -0
  8. package/corpus/templates/calendar/agent-native.config.ts +5 -0
  9. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -1
  10. package/corpus/templates/calendar/netlify.toml +3 -0
  11. package/corpus/templates/chat/agent-native.config.ts +5 -0
  12. package/corpus/templates/chat/netlify.toml +3 -0
  13. package/corpus/templates/clips/actions/create-meeting.ts +19 -1
  14. package/corpus/templates/clips/actions/lib/meeting-content.ts +28 -0
  15. package/corpus/templates/clips/actions/list-meetings.ts +33 -11
  16. package/corpus/templates/clips/app/components/meetings/bullet-link.tsx +48 -25
  17. package/corpus/templates/clips/app/components/meetings/canvas-editor.tsx +7 -6
  18. package/corpus/templates/clips/app/components/meetings/transcript-bubbles.tsx +388 -178
  19. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +7 -13
  20. package/corpus/templates/clips/app/components/transcript/transcript-segment-row.tsx +98 -0
  21. package/corpus/templates/clips/app/i18n/en-US.ts +5 -0
  22. package/corpus/templates/clips/app/lib/meeting-history-query.ts +11 -0
  23. package/corpus/templates/clips/app/lib/public-meeting.ts +4 -0
  24. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +49 -31
  25. package/corpus/templates/clips/app/routes/_app.meetings._index.tsx +47 -21
  26. package/corpus/templates/clips/app/routes/share.meeting.$meetingId.tsx +15 -1
  27. package/corpus/templates/clips/netlify.toml +8 -4
  28. package/corpus/templates/clips/server/routes/api/public-meeting.get.ts +10 -0
  29. package/corpus/templates/clips/shared/transcript-segments.ts +20 -2
  30. package/corpus/templates/content/netlify.toml +3 -0
  31. package/corpus/templates/design/app/i18n-data.ts +2 -0
  32. package/corpus/templates/design/netlify.toml +3 -0
  33. package/corpus/templates/dispatch/netlify.toml +3 -0
  34. package/corpus/templates/factory/netlify.toml +3 -0
  35. package/corpus/templates/forms/netlify.toml +3 -0
  36. package/corpus/templates/macros/netlify.toml +3 -0
  37. package/corpus/templates/mail/agent-native.config.ts +5 -0
  38. package/corpus/templates/mail/netlify.toml +3 -0
  39. package/corpus/templates/plan/netlify.toml +3 -0
  40. package/corpus/templates/slides/netlify.toml +3 -0
  41. package/dist/agent/harness/acp-adapter.js +17 -2
  42. package/dist/agent/harness/ai-sdk-adapter.js +14 -3
  43. package/dist/agent/harness/background.js +10 -5
  44. package/dist/agent/harness/hosted.d.ts +20 -0
  45. package/dist/agent/harness/hosted.js +100 -0
  46. package/dist/agent/harness/runner.js +100 -77
  47. package/dist/agent/observational-memory/observer.js +12 -0
  48. package/dist/agent/production-agent.d.ts +3 -0
  49. package/dist/agent/production-agent.js +74 -4
  50. package/dist/agent/thread-data-builder.d.ts +12 -0
  51. package/dist/agent/thread-data-builder.js +23 -0
  52. package/dist/agent/types.d.ts +6 -0
  53. package/dist/client/AgentPanel.d.ts +5 -1
  54. package/dist/client/AgentPanel.js +113 -17
  55. package/dist/client/AgentTaskCard.d.ts +2 -2
  56. package/dist/client/AgentTaskCard.js +8 -22
  57. package/dist/client/AssistantChat.d.ts +8 -0
  58. package/dist/client/AssistantChat.js +106 -59
  59. package/dist/client/MultiTabAssistantChat.js +50 -6
  60. package/dist/client/NewWorkspaceAppFlow.js +7 -1
  61. package/dist/client/agent-chat-adapter.d.ts +6 -0
  62. package/dist/client/agent-chat-adapter.js +36 -8
  63. package/dist/client/app-chat-sidebar.d.ts +5 -0
  64. package/dist/client/app-chat-sidebar.js +53 -9
  65. package/dist/client/chat/composer-draft.d.ts +4 -0
  66. package/dist/client/chat/composer-draft.js +63 -0
  67. package/dist/client/chat-first/apps-rail.js +10 -1
  68. package/dist/client/chat-first/primary-nav.js +10 -5
  69. package/dist/client/frame-protocol.d.ts +1 -0
  70. package/dist/client/hooks/index.d.ts +1 -1
  71. package/dist/client/hooks/index.js +1 -1
  72. package/dist/client/i18n.js +5 -2
  73. package/dist/client/progress/RunsTray.js +129 -16
  74. package/dist/client/settings/SettingsRow.js +1 -1
  75. package/dist/client/use-chat-threads.js +11 -6
  76. package/dist/collab/routes.d.ts +1 -1
  77. package/dist/collab/struct-routes.d.ts +1 -1
  78. package/dist/config.d.ts +11 -0
  79. package/dist/config.js +52 -0
  80. package/dist/deploy/build.js +28 -11
  81. package/dist/extensions/actions.js +22 -1
  82. package/dist/hosted-harness/actions/get-hosted-harness-config.d.ts +2 -0
  83. package/dist/hosted-harness/actions/get-hosted-harness-config.js +13 -0
  84. package/dist/hosted-harness/actions/set-hosted-harness-enabled.d.ts +4 -0
  85. package/dist/hosted-harness/actions/set-hosted-harness-enabled.js +32 -0
  86. package/dist/localization/default-messages.d.ts +4 -1
  87. package/dist/localization/default-messages.js +5 -2
  88. package/dist/observability/routes.d.ts +5 -5
  89. package/dist/provider-api/actions/custom-provider-registration.d.ts +6 -6
  90. package/dist/provider-api/actions/provider-api.d.ts +4 -4
  91. package/dist/resources/handlers.d.ts +1 -1
  92. package/dist/secrets/routes.d.ts +9 -9
  93. package/dist/server/action-discovery.js +12 -0
  94. package/dist/server/agent-chat-plugin.js +24 -4
  95. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  96. package/dist/server/agent-teams.d.ts +20 -12
  97. package/dist/server/agent-teams.js +69 -35
  98. package/dist/server/hosted-harness-policy.d.ts +17 -0
  99. package/dist/server/hosted-harness-policy.js +38 -0
  100. package/dist/server/realtime-token.d.ts +1 -1
  101. package/dist/server/request-context.d.ts +4 -0
  102. package/dist/server/transcribe-voice.d.ts +1 -1
  103. package/dist/styles/agent-native.css +39 -0
  104. package/dist/templates/chat/agent-native.config.ts +5 -0
  105. package/dist/templates/chat/netlify.toml +3 -0
  106. package/dist/vite/action-types-plugin.js +8 -0
  107. package/package.json +4 -2
  108. package/src/templates/chat/agent-native.config.ts +5 -0
  109. package/src/templates/chat/netlify.toml +3 -0
package/dist/config.js CHANGED
@@ -30,6 +30,7 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
30
30
  const instructionsValue = input.instructions;
31
31
  const translationsValue = input.translations;
32
32
  const changelogValue = input.changelog;
33
+ const harnessValue = input.harness;
33
34
  const normalized = {
34
35
  ...(input.version === undefined
35
36
  ? {}
@@ -57,6 +58,9 @@ export function normalizeAgentNativeConfig(input, source = "agent-native config"
57
58
  if (changelogValue !== undefined) {
58
59
  normalized.changelog = normalizeChangelogConfig(changelogValue, `${source}.changelog`);
59
60
  }
61
+ if (harnessValue !== undefined) {
62
+ normalized.harness = normalizeHarnessConfig(harnessValue, `${source}.harness`);
63
+ }
60
64
  return normalized;
61
65
  }
62
66
  export function mergeAgentNativeConfigs(base, override) {
@@ -128,6 +132,7 @@ export function mergeAgentNativeConfigs(base, override) {
128
132
  ...override.changelog,
129
133
  }
130
134
  : undefined,
135
+ harness: mergeHarnessSettings(base.harness, override.harness),
131
136
  };
132
137
  }
133
138
  export function resolveAgentNativeConfig(input, context) {
@@ -254,6 +259,47 @@ function normalizeChangelogConfig(value, source) {
254
259
  }
255
260
  return value.enabled === undefined ? {} : { enabled: value.enabled };
256
261
  }
262
+ function normalizeHarnessConfig(value, source) {
263
+ if (typeof value === "boolean")
264
+ return value;
265
+ if (!isRecord(value)) {
266
+ throw new Error(`${source} must be a boolean or object`);
267
+ }
268
+ if ("enabled" in value || "ui" in value) {
269
+ throw new Error(`${source} must be true or an object with runtimes`);
270
+ }
271
+ const runtimes = value.runtimes;
272
+ if (runtimes !== undefined) {
273
+ if (!Array.isArray(runtimes) ||
274
+ runtimes.some((runtime) => !isAgentNativeHarnessRuntime(runtime))) {
275
+ throw new Error(`${source}.runtimes must contain only "claude-code", "codex", "pi", or "opencode"`);
276
+ }
277
+ }
278
+ return {
279
+ ...(runtimes === undefined
280
+ ? {}
281
+ : { runtimes: [...new Set(runtimes)] }),
282
+ };
283
+ }
284
+ function mergeHarnessSettings(base, override) {
285
+ if (override === undefined)
286
+ return base;
287
+ if (typeof override === "boolean")
288
+ return override;
289
+ if (typeof base !== "object" || base === null)
290
+ return override;
291
+ if (base.runtimes === undefined && override.runtimes === undefined) {
292
+ return {};
293
+ }
294
+ return {
295
+ runtimes: [
296
+ ...new Set([
297
+ ...(base.runtimes ?? []),
298
+ ...(override.runtimes ?? []),
299
+ ]),
300
+ ],
301
+ };
302
+ }
257
303
  function normalizeRelativeFilePath(value, source) {
258
304
  const normalized = value.trim().replaceAll("\\", "/");
259
305
  if (!normalized ||
@@ -286,6 +332,12 @@ function isFirstRunMode(value) {
286
332
  value === "connect" ||
287
333
  value === "connect-and-integrations");
288
334
  }
335
+ function isAgentNativeHarnessRuntime(value) {
336
+ return (value === "claude-code" ||
337
+ value === "codex" ||
338
+ value === "pi" ||
339
+ value === "opencode");
340
+ }
289
341
  function isRecord(value) {
290
342
  return !!value && typeof value === "object" && !Array.isArray(value);
291
343
  }
@@ -2918,14 +2918,34 @@ export function bundleYjsRuntimeForServerlessOutput(serverDir, projectCwd) {
2918
2918
  });
2919
2919
  return bareImports;
2920
2920
  }
2921
- // Netlify's hard limit is 250MB unzipped per function; a bundle this far under
2922
- // it still leaves room for growth, and today's server functions land near 70MB
2923
- // once the dead weight is out. Apps that legitimately ship the browser runtime
2924
- // get its ~85MB on top, so the budget stays a regression signal rather than a
2925
- // tax on Chromium-backed templates.
2921
+ // Netlify's hard limit is 250MB unzipped per function; keep 10MB of headroom
2922
+ // for packaging variance so a passing guard does not sit on the platform edge.
2926
2923
  const NETLIFY_FUNCTION_SIZE_BUDGET_BYTES = 120 * 1024 * 1024;
2924
+ const NETLIFY_FUNCTION_HARD_LIMIT_BYTES = 240 * 1024 * 1024;
2927
2925
  const NETLIFY_BROWSER_RUNTIME_SIZE_ALLOWANCE_BYTES = 100 * 1024 * 1024;
2928
- function reportNetlifyFunctionSizes(projectCwd, internalDir, failures) {
2926
+ // Clips intentionally ships ffmpeg-static for server-side frame extraction,
2927
+ // WebM seekability, filmstrips, and audio-only transcription. Keep that known
2928
+ // runtime payload separate from the ordinary bundle-growth budget.
2929
+ const NETLIFY_FFMPEG_RUNTIME_SIZE_ALLOWANCE_BYTES = 80 * 1024 * 1024;
2930
+ function hasBundledFfmpegStaticRuntime(functionDir) {
2931
+ if (!fs.existsSync(functionDir))
2932
+ return false;
2933
+ const binaryName = FFMPEG_STATIC_BINARY_NAMES[0];
2934
+ return fs.existsSync(path.join(functionDir, "node_modules", FFMPEG_STATIC_PACKAGE_NAME, binaryName));
2935
+ }
2936
+ function hasBundledServerlessBrowserRuntime(functionDir) {
2937
+ return fs.existsSync(path.join(functionDir, "node_modules", "@sparticuz", "chromium", "bin", "chromium.br"));
2938
+ }
2939
+ function netlifyFunctionSizeBudget(functionDir) {
2940
+ const allowance = (hasBundledServerlessBrowserRuntime(functionDir)
2941
+ ? NETLIFY_BROWSER_RUNTIME_SIZE_ALLOWANCE_BYTES
2942
+ : 0) +
2943
+ (hasBundledFfmpegStaticRuntime(functionDir)
2944
+ ? NETLIFY_FFMPEG_RUNTIME_SIZE_ALLOWANCE_BYTES
2945
+ : 0);
2946
+ return Math.min(NETLIFY_FUNCTION_SIZE_BUDGET_BYTES + allowance, NETLIFY_FUNCTION_HARD_LIMIT_BYTES);
2947
+ }
2948
+ function reportNetlifyFunctionSizes(internalDir, failures) {
2929
2949
  if (!fs.existsSync(internalDir))
2930
2950
  return;
2931
2951
  const functions = fs
@@ -2947,11 +2967,8 @@ function reportNetlifyFunctionSizes(projectCwd, internalDir, failures) {
2947
2967
  console.log(`[deploy] Netlify functions: ${functions.length} (${functions
2948
2968
  .map((fn) => `${fn.name} ${toMb(fn.size)}MB`)
2949
2969
  .join(", ")}) — ${toMb(total)}MB uploaded in total.`);
2950
- const budget = NETLIFY_FUNCTION_SIZE_BUDGET_BYTES +
2951
- (findServerlessBrowserRuntimeConsumer(projectCwd)
2952
- ? NETLIFY_BROWSER_RUNTIME_SIZE_ALLOWANCE_BYTES
2953
- : 0);
2954
2970
  for (const fn of functions) {
2971
+ const budget = netlifyFunctionSizeBudget(fn.dir);
2955
2972
  if (fn.size <= budget)
2956
2973
  continue;
2957
2974
  // node_modules is always the biggest child and names nothing useful; the
@@ -3113,7 +3130,7 @@ export function assertSingleTemplateNetlifyBuildOutput(projectCwd) {
3113
3130
  }
3114
3131
  }
3115
3132
  }
3116
- reportNetlifyFunctionSizes(projectCwd, internalDir, failures);
3133
+ reportNetlifyFunctionSizes(internalDir, failures);
3117
3134
  if (failures.length > 0) {
3118
3135
  throw new Error("[deploy] Netlify deploy guard failed; refusing to publish an output " +
3119
3136
  "that would likely serve Netlify 404s or blow the function size limit:\n" +
@@ -1242,6 +1242,27 @@ async function summarizeExtensionForAgentRead(row, hiddenIds, includeContent, fo
1242
1242
  const fingerprint = contentFingerprint(row.content);
1243
1243
  if (contentQuery) {
1244
1244
  const summary = await summarizeExtension(row, hiddenIds, false);
1245
+ // The whole-body read below is deduped per run, but this branch returned
1246
+ // above it, so a repeated excerpt request re-sent bytes already in context.
1247
+ // One production turn spent 48 of 110 reads re-fetching the same spans.
1248
+ const excerptCtx = getRequestRunContext();
1249
+ const excerpts = excerptCtx
1250
+ ? (excerptCtx.extensionExcerptReads ??= {})
1251
+ : undefined;
1252
+ const excerptKey = `${row.id}:${fingerprint}:${contentContextChars}:${contentQuery}`;
1253
+ if (excerpts?.[excerptKey]) {
1254
+ return {
1255
+ ...summary,
1256
+ contentOmitted: {
1257
+ reason: "identical-excerpt-already-returned-this-run",
1258
+ contentHash: fingerprint,
1259
+ contentLength: row.content.length,
1260
+ next: 'These exact excerpts were already returned earlier in this run and the body has not changed. Use them to call update-extension with operation="edit"; use a different contentQuery only for a source area you have not read yet.',
1261
+ },
1262
+ };
1263
+ }
1264
+ if (excerpts)
1265
+ excerpts[excerptKey] = true;
1245
1266
  return {
1246
1267
  ...summary,
1247
1268
  contentMatches: findExtensionContentMatches(row.content, contentQuery, contentContextChars),
@@ -1266,7 +1287,7 @@ async function summarizeExtensionForAgentRead(row, hiddenIds, includeContent, fo
1266
1287
  contentHash: fingerprint,
1267
1288
  contentLength: row.content.length,
1268
1289
  inlineContentLimit: LARGE_EXTENSION_INLINE_CONTENT_MAX_CHARS,
1269
- next: "Call get-extension again with contentQuery set to the relevant function, variable, section marker, or literal text. Use forceContent=true only for a broad rewrite that truly needs the entire body.",
1290
+ next: `Call get-extension again with contentQuery set to the relevant function, variable, section marker, or literal text. If you expect to read more than about three separate areas of this ${row.content.length}-char body, call get-extension once with forceContent=true instead — repeated excerpt reads of the same file cost more context than one whole read.`,
1270
1291
  },
1271
1292
  };
1272
1293
  }
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<Record<string, never>, import("../../server/hosted-harness-policy.js").HostedHarnessPolicy>;
2
+ export default _default;
@@ -0,0 +1,13 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { hostedHarnessStatusForClient, resolveHostedHarnessPolicy, } from "../../server/hosted-harness-policy.js";
4
+ export default defineAction({
5
+ description: "Return whether this app's hosted tools-only harness is enabled for the current organization and which runtimes are available.",
6
+ schema: z.object({}),
7
+ http: { method: "GET" },
8
+ agentTool: false,
9
+ run: async (_args, context) => hostedHarnessStatusForClient(await resolveHostedHarnessPolicy({
10
+ orgId: context?.orgId,
11
+ userEmail: context?.userEmail,
12
+ })),
13
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("../../action.js").ActionDefinition<{
2
+ enabled: boolean;
3
+ }, import("../../server/hosted-harness-policy.js").HostedHarnessPolicy>;
4
+ export default _default;
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+ import { defineAction } from "../../action.js";
3
+ import { HOSTED_HARNESS_ORG_SETTING_KEY } from "../../agent/harness/hosted.js";
4
+ import { getOrgRoleForEmail } from "../../mcp/actions/service-token-access.js";
5
+ import { canManageOrg } from "../../org/permissions.js";
6
+ import { hostedHarnessStatusForClient, resolveHostedHarnessPolicy, } from "../../server/hosted-harness-policy.js";
7
+ import { putOrgSetting } from "../../settings/org-settings.js";
8
+ export default defineAction({
9
+ description: "Enable or disable the hosted tools-only harness for the current organization. Organization owners and admins only.",
10
+ schema: z.object({ enabled: z.boolean() }),
11
+ http: { method: "POST" },
12
+ agentTool: false,
13
+ run: async (args, context) => {
14
+ const email = context?.userEmail?.trim().toLowerCase();
15
+ const orgId = context?.orgId?.trim();
16
+ if (!email)
17
+ throw new Error("Sign in to manage hosted harnesses.");
18
+ if (!orgId)
19
+ throw new Error("Select an organization to manage harnesses.");
20
+ const role = await getOrgRoleForEmail(orgId, email);
21
+ if (!canManageOrg(role)) {
22
+ throw new Error("Only organization owners and admins can manage hosted harnesses.");
23
+ }
24
+ await putOrgSetting(orgId, HOSTED_HARNESS_ORG_SETTING_KEY, {
25
+ enabled: args.enabled,
26
+ });
27
+ return hostedHarnessStatusForClient(await resolveHostedHarnessPolicy({
28
+ orgId,
29
+ userEmail: email,
30
+ }));
31
+ },
32
+ });
@@ -733,6 +733,9 @@ declare const messages: {
733
733
  statusDone: string;
734
734
  statusFailed: string;
735
735
  statusStopped: string;
736
+ statusNeedsApproval: string;
737
+ statusNeedsInput: string;
738
+ statusPaused: string;
736
739
  updatedJustNow: string;
737
740
  finishedJustNow: string;
738
741
  updatedMinutes: string;
@@ -743,7 +746,7 @@ declare const messages: {
743
746
  finishedDate: string;
744
747
  };
745
748
  agentTask: {
746
- backgroundTask: string;
749
+ spawnedAgent: string;
747
750
  stop: string;
748
751
  openThread: string;
749
752
  };
@@ -739,6 +739,9 @@ const messages = {
739
739
  statusDone: "Done",
740
740
  statusFailed: "Failed",
741
741
  statusStopped: "Stopped",
742
+ statusNeedsApproval: "Needs approval",
743
+ statusNeedsInput: "Needs input",
744
+ statusPaused: "Paused",
742
745
  updatedJustNow: "Updated just now",
743
746
  finishedJustNow: "Finished just now",
744
747
  updatedMinutes: "Updated {{count}}m ago",
@@ -749,8 +752,8 @@ const messages = {
749
752
  finishedDate: "Finished {{date}}",
750
753
  },
751
754
  agentTask: {
752
- backgroundTask: "Background task",
753
- stop: "Stop background task",
755
+ spawnedAgent: "Spawned agent",
756
+ stop: "Stop spawned agent",
754
757
  openThread: "Open task thread",
755
758
  },
756
759
  codeRequired: {
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
+ error?: undefined;
45
+ ok?: undefined;
44
46
  summary: import("./types.js").TraceSummary;
45
47
  spans: import("./types.js").TraceSpan[];
46
48
  id?: undefined;
49
+ } | {
47
50
  error?: undefined;
48
51
  ok?: undefined;
49
- } | {
50
52
  summary?: undefined;
51
53
  spans?: undefined;
52
54
  id: string;
53
- error?: undefined;
54
- ok?: undefined;
55
55
  } | {
56
+ ok?: undefined;
56
57
  summary?: undefined;
57
58
  spans?: undefined;
58
59
  id?: undefined;
59
60
  error: any;
60
- ok?: undefined;
61
61
  } | {
62
+ error?: undefined;
62
63
  summary?: undefined;
63
64
  spans?: undefined;
64
65
  id?: undefined;
65
- error?: undefined;
66
66
  ok: boolean;
67
67
  }>>;
@@ -75,8 +75,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
75
75
  user: "user";
76
76
  }>>;
77
77
  }, z.core.$strip>>, {
78
- id?: undefined;
79
78
  message?: undefined;
79
+ id?: undefined;
80
+ provider?: undefined;
80
81
  deleted?: undefined;
81
82
  providers: {
82
83
  id: string;
@@ -88,14 +89,13 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
88
89
  updatedAt: number;
89
90
  }[];
90
91
  count: number;
91
- provider?: undefined;
92
92
  found?: undefined;
93
93
  registered?: undefined;
94
94
  label?: undefined;
95
95
  } | {
96
- id?: undefined;
97
96
  message?: undefined;
98
97
  count?: undefined;
98
+ id?: undefined;
99
99
  deleted?: undefined;
100
100
  providers?: undefined;
101
101
  found: boolean;
@@ -105,9 +105,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
105
105
  } | {
106
106
  message?: undefined;
107
107
  count?: undefined;
108
+ provider?: undefined;
108
109
  deleted?: undefined;
109
110
  providers?: undefined;
110
- provider?: undefined;
111
111
  found: boolean;
112
112
  id: string;
113
113
  registered?: undefined;
@@ -115,8 +115,8 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
115
115
  } | {
116
116
  message?: undefined;
117
117
  count?: undefined;
118
- providers?: undefined;
119
118
  provider?: undefined;
119
+ providers?: undefined;
120
120
  found?: undefined;
121
121
  deleted: boolean;
122
122
  id: string;
@@ -124,9 +124,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
124
124
  label?: undefined;
125
125
  } | {
126
126
  count?: undefined;
127
+ provider?: undefined;
127
128
  deleted?: undefined;
128
129
  providers?: undefined;
129
- provider?: undefined;
130
130
  found?: undefined;
131
131
  registered: boolean;
132
132
  id: string;
@@ -313,7 +313,6 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
313
313
  }, {
314
314
  deleted?: undefined;
315
315
  id?: undefined;
316
- provider?: undefined;
317
316
  providers: {
318
317
  id: string;
319
318
  label: string;
@@ -324,6 +323,7 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
324
323
  updatedAt: number;
325
324
  }[];
326
325
  count: number;
326
+ provider?: undefined;
327
327
  found?: undefined;
328
328
  registered?: undefined;
329
329
  label?: undefined;
@@ -340,18 +340,18 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
340
340
  message?: undefined;
341
341
  } | {
342
342
  deleted?: undefined;
343
- provider?: undefined;
344
343
  providers?: undefined;
345
344
  count?: undefined;
345
+ provider?: undefined;
346
346
  found: boolean;
347
347
  id: string;
348
348
  registered?: undefined;
349
349
  label?: undefined;
350
350
  message?: undefined;
351
351
  } | {
352
- provider?: undefined;
353
352
  providers?: undefined;
354
353
  count?: undefined;
354
+ provider?: undefined;
355
355
  found?: undefined;
356
356
  deleted: boolean;
357
357
  id: string;
@@ -360,9 +360,9 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
360
360
  message?: undefined;
361
361
  } | {
362
362
  deleted?: undefined;
363
- provider?: undefined;
364
363
  providers?: undefined;
365
364
  count?: undefined;
365
+ provider?: undefined;
366
366
  found?: undefined;
367
367
  registered: boolean;
368
368
  id: string;
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
48
48
  }>;
49
49
  /** DELETE /_agent-native/resources/:id — delete a resource */
50
50
  export declare function handleDeleteResource(event: any): Promise<{
51
- ok?: undefined;
52
51
  error: string;
52
+ ok?: undefined;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -34,37 +34,37 @@ export declare function createListSecretsHandler(): import("h3").EventHandlerWit
34
34
  /** POST /_agent-native/secrets/:key — write a secret. */
35
35
  export declare function createWriteSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
36
36
  error: string;
37
- status?: undefined;
38
37
  ok?: undefined;
38
+ status?: undefined;
39
39
  } | {
40
+ error?: undefined;
40
41
  ok: boolean;
41
42
  status: string;
42
- error?: undefined;
43
43
  } | {
44
+ ok?: undefined;
44
45
  error: string;
45
46
  removed?: undefined;
46
- ok?: undefined;
47
47
  } | {
48
+ error?: undefined;
48
49
  ok: boolean;
49
50
  removed: boolean;
50
- error?: undefined;
51
51
  }>>;
52
52
  /**
53
53
  * POST /_agent-native/secrets/:key/test — validate an optional candidate value
54
54
  * or the current stored value without changing anything.
55
55
  */
56
56
  export declare function createTestSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
57
+ ok?: undefined;
57
58
  error: string;
58
59
  note?: undefined;
59
- ok?: undefined;
60
60
  } | {
61
+ error?: undefined;
61
62
  ok: boolean;
62
63
  note?: undefined;
63
- error?: undefined;
64
64
  } | {
65
+ error?: undefined;
65
66
  ok: boolean;
66
67
  note: string;
67
- error?: undefined;
68
68
  } | {
69
69
  note?: undefined;
70
70
  ok: boolean;
@@ -95,11 +95,11 @@ export interface AdHocSecretPayload {
95
95
  export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
96
96
  error: string;
97
97
  } | {
98
+ error?: undefined;
98
99
  ok: boolean;
99
100
  key: string;
100
- error?: undefined;
101
101
  } | {
102
+ error?: undefined;
102
103
  ok: boolean;
103
104
  removed: boolean;
104
- error?: undefined;
105
105
  }>>;
@@ -529,6 +529,10 @@ export const ALWAYS_ON_CORE_ACTIONS = new Set([
529
529
  "revoke-org-service-token",
530
530
  "list-mcp-tools",
531
531
  "call-mcp-tool",
532
+ // Hosted harness capability/policy routes are UI-facing and deliberately
533
+ // never enter the model's action surface (`agentTool: false`).
534
+ "get-hosted-harness-config",
535
+ "set-hosted-harness-enabled",
532
536
  ]);
533
537
  export async function mergeCoreSharingActions(registry) {
534
538
  const entries = [
@@ -592,6 +596,14 @@ export async function mergeCoreSharingActions(registry) {
592
596
  "get-feature-flags",
593
597
  () => import("../feature-flags/actions/get-feature-flags.js"),
594
598
  ],
599
+ [
600
+ "get-hosted-harness-config",
601
+ () => import("../hosted-harness/actions/get-hosted-harness-config.js"),
602
+ ],
603
+ [
604
+ "set-hosted-harness-enabled",
605
+ () => import("../hosted-harness/actions/set-hosted-harness-enabled.js"),
606
+ ],
595
607
  [
596
608
  "list-feature-flags",
597
609
  () => import("../feature-flags/actions/list-feature-flags.js"),
@@ -12,6 +12,7 @@ import { AGENT_CHAT_BACKGROUND_RUN_FIELD, AGENT_CHAT_PROCESS_RUN_PATH, backgroun
12
12
  import { resolveEngine, createAnthropicEngine, getStoredModelForEngine, normalizeModelForEngine, resolveDelegatedRunModel, getAgentEngineEntry, isAgentEnginePackageInstalled, isStoredEngineUsableForRequest, listAgentEngines, registerBuiltinEngines, } from "../agent/engine/index.js";
13
13
  import { SYSTEM_PROMPT_CACHE_SPLIT } from "../agent/engine/prompt-cache.js";
14
14
  import { PROVIDER_TO_ENV } from "../agent/engine/provider-env-vars.js";
15
+ import { hostedHarnessSystemPrompt } from "../agent/harness/hosted.js";
15
16
  import { createProductionAgentHandler, actionsToEngineTools, executeAgentToolCall, filterActionsByAllowedNames, readPersistedActionSurface, toolCallCacheKey, getActiveRunForThreadAsync, abortRunDurably, abortTurnDurably, subscribeToRun, } from "../agent/production-agent.js";
16
17
  import { callerHasRunAccess, callerHasThreadAccess, } from "../agent/run-ownership.js";
17
18
  import { markTurnAborted, readBackgroundRunClaim } from "../agent/run-store.js";
@@ -44,6 +45,7 @@ import { captureError } from "./capture-error.js";
44
45
  import { getH3App, markDefaultPluginProvided, trackPluginInit, } from "./framework-request-handler.js";
45
46
  import { getOrigin } from "./google-oauth.js";
46
47
  import { readBody } from "./h3-helpers.js";
48
+ import { loadHostedHarnessConfig } from "./hosted-harness-policy.js";
47
49
  import { startIntervalJob } from "./interval-job.js";
48
50
  import { getModelFamilyOverlay } from "./prompts/index.js";
49
51
  import { mountRealtimeVoiceRoutes } from "./realtime-voice.js";
@@ -309,6 +311,7 @@ export function createAgentChatPlugin(options) {
309
311
  // `/runs/active` reaps the requested run on demand, and the periodic
310
312
  // recovery sweep below handles abandoned runs with no connected client.
311
313
  const env = process.env.NODE_ENV;
314
+ const hostedHarnessConfig = await loadHostedHarnessConfig();
312
315
  // AGENT_MODE=production forces production agent constraints even in dev
313
316
  const canToggle = (env === "development" || env === "test") &&
314
317
  process.env.AGENT_MODE !== "production";
@@ -2694,6 +2697,13 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2694
2697
  const codeEditingSurfaceRestriction = shouldBlockInProductCodeEditing(event)
2695
2698
  ? APP_RENDERED_CHAT_NO_DIRECT_CODE_PROMPT
2696
2699
  : "";
2700
+ const hostedHarnessRuntime = getRequestRunContext()?.hostedHarnessRuntime;
2701
+ const hostedHarnessPromptNote = hostedHarnessRuntime
2702
+ ? hostedHarnessSystemPrompt(hostedHarnessRuntime)
2703
+ : "";
2704
+ const requestProdCodeExecPromptNote = hostedHarnessRuntime
2705
+ ? ""
2706
+ : prodCodeExecPromptNote;
2697
2707
  // Per-model overlay: nudge GPT/Gemini engines toward our behavioral norms.
2698
2708
  const modelOverlay = resolveModelOverlay();
2699
2709
  // Stable-first ordering: base prompt / schema / extra come before
@@ -2705,7 +2715,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2705
2715
  // `SYSTEM_PROMPT_CACHE_SPLIT` marks where the cacheable prefix ends,
2706
2716
  // so everything after it can change without a cache write.
2707
2717
  if (leanPrompt) {
2708
- const leanRunPolicyPrompt = buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, prodCodeExecPromptNote);
2718
+ const leanRunPolicyPrompt = buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction, `${requestProdCodeExecPromptNote}${hostedHarnessPromptNote ? `\n\n${hostedHarnessPromptNote}` : ""}`);
2709
2719
  const resources = await loadResourcesForPrompt(owner, true, options?.appId, undefined, { disabledFrameworkGroups });
2710
2720
  await emitContextXraySystemSections(event, {
2711
2721
  frameworkPrompt: requestLeanPrompt.slice(0, Math.max(0, requestLeanPrompt.length - requestLeanActionsPrompt.length)),
@@ -2740,20 +2750,26 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
2740
2750
  extra,
2741
2751
  modelOverlay,
2742
2752
  runtimeContext,
2743
- additionalFramework: codeEditingSurfaceRestriction + prodCodeExecPromptNote,
2753
+ additionalFramework: codeEditingSurfaceRestriction +
2754
+ requestProdCodeExecPromptNote +
2755
+ (hostedHarnessPromptNote ? `\n\n${hostedHarnessPromptNote}` : ""),
2744
2756
  });
2745
2757
  return setSystemPromptOnContext(requestBasePrompt +
2746
2758
  SYSTEM_PROMPT_CACHE_SPLIT +
2747
2759
  resources +
2748
2760
  schemaBlock +
2749
2761
  codeEditingSurfaceRestriction +
2750
- prodCodeExecPromptNote +
2762
+ requestProdCodeExecPromptNote +
2763
+ (hostedHarnessPromptNote
2764
+ ? `\n\n${hostedHarnessPromptNote}`
2765
+ : "") +
2751
2766
  extra +
2752
2767
  modelOverlay +
2753
2768
  runtimeContext);
2754
2769
  },
2755
2770
  model: options?.model,
2756
2771
  appId: options?.appId,
2772
+ hostedHarnessConfig,
2757
2773
  apiKey: options?.apiKey,
2758
2774
  ...resolveInteractiveAgentRunOptions(options),
2759
2775
  finalResponseGuard: options?.finalResponseGuard,
@@ -4692,9 +4708,13 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
4692
4708
  // `prodHandler.systemPrompt` then steers source changes to a
4693
4709
  // separate agent surface such as Builder or the dev frame.
4694
4710
  const blockInProductCodeEditing = shouldBlockInProductCodeEditing(event);
4711
+ const hostedHarnessRequest = getHeader(event, "x-agent-native-hosted-harness") === "1";
4695
4712
  const handler = ownerContext.anonymous && anonymousHandler
4696
4713
  ? anonymousHandler
4697
- : !blockInProductCodeEditing && currentDevMode && devHandler
4714
+ : !hostedHarnessRequest &&
4715
+ !blockInProductCodeEditing &&
4716
+ currentDevMode &&
4717
+ devHandler
4698
4718
  ? devHandler
4699
4719
  : prodHandler;
4700
4720
  return handler(event);
@@ -27,10 +27,10 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
+ error?: undefined;
30
31
  ok: boolean;
31
32
  key: string;
32
33
  baseUrlKey?: string;
33
34
  scope: AgentEngineApiKeyScope;
34
- error?: undefined;
35
35
  }>>;
36
36
  export {};