@agent-native/core 0.206.0 → 0.206.1-nightly-20261009213000

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 (93) hide show
  1. package/dist/action.d.ts +2 -0
  2. package/dist/agent/default-agent-engine.js +25 -0
  3. package/dist/agent/durable-background.d.ts +2 -0
  4. package/dist/agent/durable-background.js +2 -0
  5. package/dist/agent/engine/error-detail.d.ts +1 -0
  6. package/dist/agent/engine/error-detail.js +6 -1
  7. package/dist/agent/engine/tool-call-journal-seed.d.ts +1 -1
  8. package/dist/agent/engine/tool-call-journal-seed.js +47 -11
  9. package/dist/agent/engine/translate-anthropic.d.ts +9 -0
  10. package/dist/agent/engine/translate-anthropic.js +18 -3
  11. package/dist/agent/production-agent.d.ts +6 -4
  12. package/dist/agent/production-agent.js +126 -85
  13. package/dist/agent/run-store.js +15 -3
  14. package/dist/agent/thread-data-builder.js +1 -2
  15. package/dist/agent/types.d.ts +1 -0
  16. package/dist/automation/index.d.ts +1 -1
  17. package/dist/chat-threads/store.js +6 -2
  18. package/dist/cli/design-connect.d.ts +1 -0
  19. package/dist/cli/design-connect.js +72 -19
  20. package/dist/client/analytics.js +48 -58
  21. package/dist/client/chat/agentkit-agent-native.js +11 -10
  22. package/dist/client/chat/agentkit-protocol.js +5 -1
  23. package/dist/client/chat/runtime.d.ts +4 -1
  24. package/dist/client/chat/runtime.js +135 -43
  25. package/dist/client/session-replay-endpoint.d.ts +1 -0
  26. package/dist/client/session-replay-endpoint.js +35 -0
  27. package/dist/client/session-replay.js +2 -24
  28. package/dist/client/sharing/share-controller-helpers.d.ts +1 -1
  29. package/dist/client/sharing/share-controller-helpers.js +2 -1
  30. package/dist/client/sharing/useShareButtonController.js +2 -9
  31. package/dist/client/use-action.d.ts +1 -0
  32. package/dist/client/use-action.js +2 -1
  33. package/dist/deploy/build.js +1 -1
  34. package/dist/deploy/workspace-deploy.js +65 -6
  35. package/dist/file-upload/actions/upload-image.d.ts +2 -2
  36. package/dist/file-upload/registry.d.ts +7 -1
  37. package/dist/file-upload/registry.js +25 -7
  38. package/dist/mcp/build-server.d.ts +6 -0
  39. package/dist/mcp/build-server.js +97 -28
  40. package/dist/mcp/embed-app.js +9 -8
  41. package/dist/mcp/screen-memory-stdio.d.ts +7 -7
  42. package/dist/notifications/routes.d.ts +3 -3
  43. package/dist/observability/metrics.d.ts +5 -0
  44. package/dist/observability/metrics.js +62 -7
  45. package/dist/observability/routes.d.ts +4 -4
  46. package/dist/org/handlers.d.ts +1 -1
  47. package/dist/org/index.d.ts +1 -1
  48. package/dist/provider-api/actions/custom-provider-registration.d.ts +13 -13
  49. package/dist/provider-api/actions/provider-api.d.ts +5 -5
  50. package/dist/scripts/docs/search.d.ts +1 -0
  51. package/dist/scripts/docs/search.js +17 -4
  52. package/dist/secrets/index.d.ts +1 -1
  53. package/dist/secrets/index.js +1 -1
  54. package/dist/secrets/storage.d.ts +1 -0
  55. package/dist/secrets/storage.js +8 -0
  56. package/dist/server/action-routes.js +62 -29
  57. package/dist/server/agent-chat/mcp-options.d.ts +2 -0
  58. package/dist/server/agent-chat/prompt-resources.js +2 -2
  59. package/dist/server/agent-engine-api-key-route.d.ts +2 -1
  60. package/dist/server/agent-engine-api-key-route.js +66 -2
  61. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  62. package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
  63. package/dist/server/agent-run-context.js +21 -1
  64. package/dist/server/agent-teams-run-queue.js +2 -1
  65. package/dist/server/agents-bundle.js +1 -1
  66. package/dist/server/auth.js +1 -0
  67. package/dist/server/core-routes-plugin.js +12 -0
  68. package/dist/server/embed-session.js +15 -1
  69. package/dist/server/http-response-telemetry.js +37 -8
  70. package/dist/server/realtime-token.d.ts +1 -1
  71. package/dist/shared/embed-auth.d.ts +4 -0
  72. package/dist/shared/embed-auth.js +156 -23
  73. package/dist/shared/inline-bytes.d.ts +29 -0
  74. package/dist/shared/inline-bytes.js +170 -0
  75. package/dist/shared/mcp-embed-headers.d.ts +1 -1
  76. package/dist/shared/mcp-embed-headers.js +1 -1
  77. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  78. package/dist/sharing/actions/list-resource-shares.js +10 -4
  79. package/dist/sharing/actions/set-resource-visibility.js +3 -1
  80. package/dist/sharing/actions/share-resource.js +4 -2
  81. package/dist/sharing/actions/unshare-resource.js +3 -1
  82. package/dist/sharing/widget-grant.d.ts +19 -0
  83. package/dist/sharing/widget-grant.js +55 -0
  84. package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +20 -21
  85. package/dist/testing.d.ts +1 -0
  86. package/dist/testing.js +1 -0
  87. package/dist/tracking/registry.d.ts +3 -2
  88. package/dist/tracking/registry.js +12 -3
  89. package/dist/vite/client.js +6 -1
  90. package/docs/content/observability.mdx +15 -10
  91. package/docs/content/tracking.mdx +1 -1
  92. package/package.json +4 -4
  93. package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +20 -21
package/dist/action.d.ts CHANGED
@@ -38,6 +38,8 @@ export interface ActionRunContext {
38
38
  actionName?: string;
39
39
  /** Present only on frontend GETs authorized by a scoped directory-widget read capability. */
40
40
  mcpDirectoryWidgetReadOnly?: true;
41
+ /** Present only on frontend calls authorized by a scoped directory-widget capability: the resource IDs it is bound to. */
42
+ mcpDirectoryWidgetResourceIds?: Record<string, string>;
41
43
  /** Present only on frontend mutations authorized by a scoped directory-widget write capability. */
42
44
  mcpDirectoryWidgetWrite?: {
43
45
  appId: string;
@@ -11,6 +11,7 @@ import { getRequestOrgId, getRequestUserEmail, } from "../server/request-context
11
11
  import { getOrgSetting, putOrgSetting } from "../settings/org-settings.js";
12
12
  import { getSetting } from "../settings/store.js";
13
13
  import { getUserSetting, putUserSetting } from "../settings/user-settings.js";
14
+ import { track } from "../tracking/registry.js";
14
15
  import { canUpdateAgentAppModelDefaultSettings } from "./app-model-defaults.js";
15
16
  export const DEFAULT_AGENT_ENGINE_SETTING_KEY = "agent-engine";
16
17
  /** Audit target type for default-model changes and refused attempts. */
@@ -98,6 +99,7 @@ async function writeScopedRow(authority, value) {
98
99
  * stores only that scope and records the change.
99
100
  */
100
101
  export async function writeDefaultAgentEngineSelection(authority, selection, meta) {
102
+ const previous = await readDefaultAgentEngineSettingDetailed(authority);
101
103
  await writeScopedRow(authority, {
102
104
  engine: selection.engine,
103
105
  model: selection.model,
@@ -112,12 +114,25 @@ export async function writeDefaultAgentEngineSelection(authority, selection, met
112
114
  operation: "set",
113
115
  selection,
114
116
  });
117
+ track("llm_default_model_changed", {
118
+ engine: selection.engine,
119
+ model: selection.model,
120
+ ...(typeof previous.value?.engine === "string"
121
+ ? { previous_engine: previous.value.engine }
122
+ : {}),
123
+ ...(typeof previous.value?.model === "string"
124
+ ? { previous_model: previous.value.model }
125
+ : {}),
126
+ scope: authority.scope,
127
+ operation: "set",
128
+ }, { userId: authority.userEmail });
115
129
  }
116
130
  /**
117
131
  * Clear the default for the authority's scope. Writes a cleared marker rather
118
132
  * than deleting the row; see {@link readDefaultAgentEngineSettingDetailed}.
119
133
  */
120
134
  export async function clearDefaultAgentEngineSelection(authority, meta) {
135
+ const previous = await readDefaultAgentEngineSettingDetailed(authority);
121
136
  await writeScopedRow(authority, {
122
137
  cleared: true,
123
138
  updatedAt: Date.now(),
@@ -130,6 +145,16 @@ export async function clearDefaultAgentEngineSelection(authority, meta) {
130
145
  status: "success",
131
146
  operation: "clear",
132
147
  });
148
+ track("llm_default_model_changed", {
149
+ ...(typeof previous.value?.engine === "string"
150
+ ? { previous_engine: previous.value.engine }
151
+ : {}),
152
+ ...(typeof previous.value?.model === "string"
153
+ ? { previous_model: previous.value.model }
154
+ : {}),
155
+ scope: authority.scope,
156
+ operation: "reset",
157
+ }, { userId: authority.userEmail });
133
158
  }
134
159
  /** Record a refused change so owners and admins can see who tried. */
135
160
  export async function recordDefaultAgentEngineRefusal(ctx, authority, operation, meta, selection) {
@@ -51,6 +51,8 @@ export declare const AGENT_CHAT_DURABLE_BACKGROUND_ENV = "AGENT_CHAT_DURABLE_BAC
51
51
  * verifies the HMAC token before invoking the handler.
52
52
  */
53
53
  export declare const AGENT_CHAT_BACKGROUND_RUN_FIELD = "__backgroundRun";
54
+ /** Analytics-only source context captured before the run leaves its browser request. */
55
+ export declare const AGENT_CHAT_BROWSER_SESSION_ID_FIELD = "__agentNativeBrowserSessionId";
54
56
  export declare function isHostedRuntimeForDurableBackground(): boolean;
55
57
  export declare function isNetlifyHostedRuntimeForDurableBackground(): boolean;
56
58
  export declare function isInBackgroundFunctionRuntime(): boolean;
@@ -131,6 +131,8 @@ export const AGENT_CHAT_DURABLE_BACKGROUND_ENV = "AGENT_CHAT_DURABLE_BACKGROUND"
131
131
  * verifies the HMAC token before invoking the handler.
132
132
  */
133
133
  export const AGENT_CHAT_BACKGROUND_RUN_FIELD = "__backgroundRun";
134
+ /** Analytics-only source context captured before the run leaves its browser request. */
135
+ export const AGENT_CHAT_BROWSER_SESSION_ID_FIELD = "__agentNativeBrowserSessionId";
134
136
  export function isHostedRuntimeForDurableBackground() {
135
137
  if (process.env.NETLIFY_LOCAL === "true")
136
138
  return false;
@@ -16,6 +16,7 @@ export interface ProviderErrorClassification {
16
16
  providerRetryable?: boolean;
17
17
  retryAfterMs?: number;
18
18
  }
19
+ export declare function isInvalidAttachmentProviderMessage(message: string): boolean;
19
20
  export declare function extractRetryAfterMs(err: unknown): number | undefined;
20
21
  export declare function classifyProviderError(err: unknown, timedOut?: boolean): ProviderErrorClassification;
21
22
  /**
@@ -90,7 +90,12 @@ export function isContextOverflowCode(code) {
90
90
  const MAX_RETRY_AFTER_MS = 60_000;
91
91
  const PROVIDER_ATTACHMENT_FIELD_PATTERN = /\b(?:images?|files?|attachments?|media)[_-](?:url|data|source|type|format|size|input|content)\b|\b(?:images?|files?)\s+(?:url|data|source|type|format|size|content)\b|\b(?:url|data|source|type|format|size|input|content)\b.{0,40}\b(?:images?|files?|attachments?|media)\b|\bmime[\s_-]?type\b/gi;
92
92
  const PROVIDER_ATTACHMENT_REJECTION_PATTERN = /\b(?:invalid|unsupported|not supported|does not support|too large|too big|too long|exceeds?|over(?:sized|size| the)? limit|maximum (?:allowed )?(?:size|length)|(?:size|length) limit|malformed)\b/i;
93
- function isInvalidAttachmentProviderMessage(message) {
93
+ // Phrasings Anthropic, OpenAI, Google, and the Builder gateway use for an
94
+ // image they refused. Specific enough to classify without a status code.
95
+ const PROVIDER_IMAGE_REJECTION_PATTERN = /\bimage exceeds \d+(?:\.\d+)?\s*mb\b|\b(?:could not|unable to) process (?:the )?(?:input )?image\b|\binvalid image\b|\bunsupported image\b|\bimage (?:is )?too (?:large|big)\b|\bprovided image is not valid\b/i;
96
+ export function isInvalidAttachmentProviderMessage(message) {
97
+ if (PROVIDER_IMAGE_REJECTION_PATTERN.test(message))
98
+ return true;
94
99
  for (const match of message.matchAll(PROVIDER_ATTACHMENT_FIELD_PATTERN)) {
95
100
  const index = match.index ?? 0;
96
101
  const start = Math.max(0, index - 100);
@@ -36,7 +36,7 @@ export type PriorTurnToolCallJournalRead = {
36
36
  export declare function loadPriorTurnToolCallJournal(threadId: string | undefined, turnId?: string): Promise<PriorTurnToolCallJournalRead>;
37
37
  export declare const JOURNALED_TOOL_REPLAY_PREFIX = "(Already completed in an earlier interrupted attempt - not re-run to avoid a duplicate side effect.)\n\n";
38
38
  export declare const RECOVERED_TOOL_REPLAY_PREFIX = "(Recovered from prior interrupted chunk \u2014 action already completed.)\n\n";
39
- export declare function loadedSkillPagesContext(results: readonly PriorTurnToolResultSummary[], allowedSlugs: ReadonlySet<string>): string;
39
+ export declare function loadedSkillPagesContext(results: readonly PriorTurnToolResultSummary[], threadPages: ReadonlyMap<string, string>, currentSkillBodies: ReadonlyMap<string, string>, isInHistory?: (slug: string, page: string) => boolean): string;
40
40
  export declare function seedRepeatedToolCallCountsFromJournal(calls: readonly PriorTurnToolCallSequenceEntry[], keyForCall: (name: string, input: unknown) => string, isResurfacedReadOnlyDuplicate: (name: string, result: string) => boolean): Map<string, number>;
41
41
  export declare function seedRepeatedToolErrorCountsFromJournal(calls: readonly PriorTurnToolCallSequenceEntry[], keyForCall: (name: string, input: unknown) => string, normalizeError: (error: string) => string): {
42
42
  sameArguments: Map<string, number>;
@@ -91,8 +91,9 @@ export async function loadPriorTurnToolCallJournal(threadId, turnId) {
91
91
  }
92
92
  export const JOURNALED_TOOL_REPLAY_PREFIX = "(Already completed in an earlier interrupted attempt - not re-run to avoid a duplicate side effect.)\n\n";
93
93
  export const RECOVERED_TOOL_REPLAY_PREFIX = "(Recovered from prior interrupted chunk — action already completed.)\n\n";
94
- const LOADED_SKILL_CONTEXT_MAX_CHARS = 24_000;
95
- export function loadedSkillPagesContext(results, allowedSlugs) {
94
+ const LOADED_SKILL_CONTEXT_MAX_CHARS = 40_000;
95
+ const OMITTED_NOTICE_RESERVE_CHARS = 1_000;
96
+ export function loadedSkillPagesContext(results, threadPages, currentSkillBodies, isInHistory = () => false) {
96
97
  const pages = new Map();
97
98
  for (const result of results) {
98
99
  if (result.name !== "docs-search" || result.isError)
@@ -101,37 +102,72 @@ export function loadedSkillPagesContext(results, allowedSlugs) {
101
102
  ? result.input
102
103
  : null;
103
104
  const slug = input?.slug;
105
+ const currentBody = typeof slug === "string" ? currentSkillBodies.get(slug) : undefined;
106
+ // A journaled read may predate a skill edit or have been truncated; only
107
+ // reuse it if it still holds the skill's current body.
104
108
  if (typeof slug !== "string" ||
105
109
  !slug.startsWith("skill-") ||
106
- !allowedSlugs.has(slug) ||
110
+ currentBody === undefined ||
107
111
  !result.content.startsWith("# Skill:") ||
108
- result.content.includes("Doc not found:")) {
112
+ result.content.includes("Doc not found:") ||
113
+ !result.content.includes(currentBody.trim())) {
109
114
  continue;
110
115
  }
111
116
  pages.delete(slug);
112
117
  pages.set(slug, result.content);
113
118
  }
119
+ const merged = new Map(threadPages);
120
+ for (const [slug, page] of pages) {
121
+ merged.delete(slug);
122
+ merged.set(slug, page);
123
+ }
124
+ for (const [slug, page] of merged) {
125
+ if (isInHistory(slug, page))
126
+ merged.delete(slug);
127
+ }
128
+ return renderLoadedSkillPages(merged);
129
+ }
130
+ // Newest reads win the budget: they are likeliest to apply to the current task.
131
+ function renderLoadedSkillPages(pages) {
114
132
  if (pages.size === 0)
115
133
  return "";
116
- const opening = "<already-loaded-skills>These skill pages were already read earlier in this turn. Reuse them instead of calling docs-search again. If a page is marked truncated, read only when missing detail matters.\n";
134
+ const opening = "<already-loaded-skills>These skill pages were already read earlier in this conversation. Reuse them instead of calling docs-search again. If a page is marked truncated or listed as omitted, read it with docs-search when missing detail matters.\n";
117
135
  const closing = "\n</already-loaded-skills>";
118
- let remaining = LOADED_SKILL_CONTEXT_MAX_CHARS - opening.length - closing.length;
136
+ let remaining = LOADED_SKILL_CONTEXT_MAX_CHARS -
137
+ opening.length -
138
+ closing.length -
139
+ OMITTED_NOTICE_RESERVE_CHARS;
119
140
  const blocks = [];
120
- for (const [slug, page] of pages) {
141
+ const entries = [...pages].reverse();
142
+ let omitted = [];
143
+ for (const [index, [slug, page]] of entries.entries()) {
121
144
  const heading = `\n## ${slug}\n`;
122
- if (remaining <= heading.length)
145
+ if (remaining <= heading.length) {
146
+ omitted = entries.slice(index).map(([omittedSlug]) => omittedSlug);
123
147
  break;
148
+ }
124
149
  const truncated = page.length > remaining - heading.length;
125
150
  const marker = truncated
126
- ? "\n[Skill page truncated to fit continuation context.]"
151
+ ? "\n[Skill page truncated to fit loaded-skill context.]"
127
152
  : "";
128
153
  const body = page.slice(0, Math.max(0, remaining - heading.length - marker.length));
129
154
  blocks.push(`${heading}${body}${marker}`);
130
155
  remaining -= heading.length + body.length + marker.length;
131
- if (truncated)
156
+ if (truncated) {
157
+ omitted = entries.slice(index + 1).map(([omittedSlug]) => omittedSlug);
132
158
  break;
159
+ }
160
+ }
161
+ if (blocks.length === 0)
162
+ return "";
163
+ if (omitted.length > 0) {
164
+ const prefix = "\n[Omitted to fit loaded-skill context; read with docs-search if needed: ";
165
+ const names = omitted
166
+ .join(", ")
167
+ .slice(0, OMITTED_NOTICE_RESERVE_CHARS - prefix.length - 4);
168
+ blocks.push(`${prefix}${names}]`);
133
169
  }
134
- return blocks.length > 0 ? `${opening}${blocks.join("\n")}${closing}` : "";
170
+ return `${opening}${blocks.join("\n")}${closing}`;
135
171
  }
136
172
  export function seedRepeatedToolCallCountsFromJournal(calls, keyForCall, isResurfacedReadOnlyDuplicate) {
137
173
  const counts = new Map();
@@ -10,6 +10,15 @@ export declare function unmatchedToolResultReplayText(part: {
10
10
  content: unknown;
11
11
  isError?: boolean;
12
12
  }): string;
13
+ /**
14
+ * Identity of a synthetic interrupted tool result in engine messages, thread
15
+ * data, and the client (`client/sse-event-processor.ts` matches it verbatim).
16
+ * The model never sees it bare: replay rewrites it to an error whose outcome
17
+ * is unknown, or the model treats it as "did not run" and repeats a write that
18
+ * may have landed.
19
+ */
20
+ export declare const INTERRUPTED_TOOL_RESULT_MARKER = "Interrupted before this tool returned a result.";
21
+ export declare function isInterruptedToolResult(content: unknown): boolean;
13
22
  export declare function backfillEngineMessagesToolResults(messages: EngineMessage[]): EngineMessage[];
14
23
  export declare function engineMessageToAnthropic(msg: EngineMessage, opts?: {
15
24
  builderGateway?: boolean;
@@ -74,13 +74,27 @@ export function unmatchedToolResultReplayText(part) {
74
74
  const err = part.isError ? " isError=true" : "";
75
75
  return `${UNMATCHED_TOOL_RESULT_REPLAY_PREFIX} [tool_use_id=${part.toolCallId}${err}] ${body}`;
76
76
  }
77
+ /**
78
+ * Identity of a synthetic interrupted tool result in engine messages, thread
79
+ * data, and the client (`client/sse-event-processor.ts` matches it verbatim).
80
+ * The model never sees it bare: replay rewrites it to an error whose outcome
81
+ * is unknown, or the model treats it as "did not run" and repeats a write that
82
+ * may have landed.
83
+ */
84
+ export const INTERRUPTED_TOOL_RESULT_MARKER = "Interrupted before this tool returned a result.";
85
+ const INTERRUPTED_TOOL_RESULT_FOR_MODEL = `${INTERRUPTED_TOOL_RESULT_MARKER} Its outcome is UNKNOWN: the tool may have run. Verify the current state before repeating any write.`;
86
+ export function isInterruptedToolResult(content) {
87
+ return (typeof content === "string" &&
88
+ content.startsWith(INTERRUPTED_TOOL_RESULT_MARKER));
89
+ }
77
90
  function interruptedToolResultPart(part) {
78
91
  return {
79
92
  type: "tool-result",
80
93
  toolCallId: part.id,
81
94
  toolName: part.name,
82
95
  toolInput: stringifyToolUseInputForGateway(part.input),
83
- content: "Interrupted before this tool returned a result.",
96
+ content: INTERRUPTED_TOOL_RESULT_FOR_MODEL,
97
+ isError: true,
84
98
  };
85
99
  }
86
100
  export function backfillEngineMessagesToolResults(messages) {
@@ -167,13 +181,14 @@ export function backfillEngineMessagesToolResults(messages) {
167
181
  const toolInput = typeof part.toolInput === "string" && part.toolInput.length > 0
168
182
  ? part.toolInput
169
183
  : stringifyToolUseInputForGateway(pendingLookup?.input ?? lookup?.input);
184
+ const interrupted = part.content === INTERRUPTED_TOOL_RESULT_MARKER;
170
185
  const filled = {
171
186
  type: "tool-result",
172
187
  toolCallId: part.toolCallId,
173
188
  toolName,
174
189
  toolInput,
175
- content: part.content,
176
- ...(part.isError ? { isError: true } : {}),
190
+ content: interrupted ? INTERRUPTED_TOOL_RESULT_FOR_MODEL : part.content,
191
+ ...(part.isError || interrupted ? { isError: true } : {}),
177
192
  ...(part.images && part.images.length > 0
178
193
  ? { images: part.images }
179
194
  : {}),
@@ -10,6 +10,7 @@ import { type BuilderGatewayAuth } from "../server/credential-provider.js";
10
10
  import { fireInternalDispatch } from "../server/self-dispatch.js";
11
11
  import { type RefusedTurnRetryContext } from "../shared/agent-chat-run-not-started.js";
12
12
  import { type ContextStatus } from "../shared/context-status.js";
13
+ import { DurableAttachmentReferenceRequiredError } from "../shared/inline-bytes.js";
13
14
  import { type ReasoningEffort } from "../shared/reasoning-effort.js";
14
15
  import type { TrackingMeta } from "../tracking/registry.js";
15
16
  import { type ResolveEngineConfig } from "./engine/index.js";
@@ -355,12 +356,10 @@ export declare function resolveAgentOwnerEmail(options: Pick<ProductionAgentOpti
355
356
  export declare function runCompletionCallbackWithDatabaseRetry(callback: () => void | Promise<void>, options?: {
356
357
  sleep?: (ms: number) => Promise<void>;
357
358
  }): Promise<void>;
359
+ export declare function normalizeLoadedSkillSlugs(value: unknown): string[];
358
360
  export declare function resolveSourceSweepToolCallThreshold(): number;
359
361
  declare function generateRunId(): string;
360
- export declare class DurableAttachmentReferenceRequiredError extends Error {
361
- readonly code = "attachment_storage_required";
362
- constructor();
363
- }
362
+ export { DurableAttachmentReferenceRequiredError };
364
363
  export declare function serializeDurableDispatchPayload(body: Record<string, unknown>): string;
365
364
  /** Check if an error is transient and should be retried
366
365
  * @internal exported for unit tests only
@@ -650,6 +649,7 @@ export declare function runAgentLoop(opts: {
650
649
  finalResponseGuardRequestText?: string;
651
650
  threadId?: string;
652
651
  turnId?: string;
652
+ loadedSkillSlugs?: readonly string[];
653
653
  runSoftTimeoutMs?: number;
654
654
  toolLimits?: {
655
655
  timeoutMs?: number;
@@ -778,6 +778,8 @@ export declare function resolvePriorContinuationState(backgroundRunMarker: Recor
778
778
  };
779
779
  export declare function resolvePriorContinuationReason(backgroundRunMarker: Record<string, unknown> | null | undefined, body: Record<string, unknown>): string | undefined;
780
780
  declare function readTurnStartedAt(threadId: string, turnId: string): Promise<number | null>;
781
+ /** @internal exported for unit tests only */
782
+ export declare function queuedPromotionAttachments(attachments: unknown[]): AgentChatAttachment[];
781
783
  declare function emitRunText(run: ActiveRun, text: string): Promise<void>;
782
784
  export interface ChainServerDrivenContinuationDeps {
783
785
  countRunsForTurn?: typeof countRunsForTurn;