@agent-native/core 0.208.0 → 0.209.0-nightly-20261014070126

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 (74) hide show
  1. package/agent-native.eject.json +1 -0
  2. package/dist/agent/approval-key.d.ts +2 -0
  3. package/dist/agent/approval-key.js +12 -0
  4. package/dist/agent/context-xray/tokenize.js +12 -3
  5. package/dist/agent/engine/translate-anthropic.js +4 -0
  6. package/dist/agent/engine/types.d.ts +2 -0
  7. package/dist/agent/production-agent.d.ts +20 -5
  8. package/dist/agent/production-agent.js +227 -34
  9. package/dist/agent/run-manager.js +57 -11
  10. package/dist/agent/run-store.d.ts +10 -0
  11. package/dist/agent/run-store.js +49 -4
  12. package/dist/agent/thread-data-builder.d.ts +2 -0
  13. package/dist/agent/thread-data-builder.js +288 -14
  14. package/dist/agent/tool-approval-store.d.ts +3 -1
  15. package/dist/agent/tool-approval-store.js +26 -12
  16. package/dist/agent/tool-call-journal.d.ts +1 -1
  17. package/dist/agent/tool-call-journal.js +5 -3
  18. package/dist/agent/types.d.ts +7 -0
  19. package/dist/client/chat/agentkit-agent-native.js +18 -0
  20. package/dist/client/chat/agentkit-protocol.js +56 -5
  21. package/dist/client/chat/runtime.d.ts +10 -0
  22. package/dist/client/chat/runtime.js +257 -26
  23. package/dist/client/sse-event-processor.d.ts +22 -0
  24. package/dist/client/sse-event-processor.js +91 -11
  25. package/dist/collab/struct-routes.d.ts +1 -1
  26. package/dist/connections/catalog.d.ts +24 -1
  27. package/dist/connections/catalog.js +12 -0
  28. package/dist/data-programs/schema.d.ts +1 -0
  29. package/dist/data-programs/schema.js +3 -0
  30. package/dist/data-programs/store.js +2 -1
  31. package/dist/deploy/build.js +16 -14
  32. package/dist/eject/workspace-connections.js +1 -0
  33. package/dist/extensions/fetch-tool.js +114 -23
  34. package/dist/extensions/schema.d.ts +1 -0
  35. package/dist/extensions/schema.js +3 -0
  36. package/dist/extensions/store.js +2 -1
  37. package/dist/extensions/web-content.d.ts +5 -1
  38. package/dist/extensions/web-content.js +24 -6
  39. package/dist/file-upload/actions/upload-image.d.ts +1 -1
  40. package/dist/notifications/routes.d.ts +1 -1
  41. package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
  42. package/dist/provider-api/actions/provider-api.d.ts +9 -9
  43. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  44. package/dist/provider-api/index.d.ts +2 -0
  45. package/dist/provider-api/index.js +95 -12
  46. package/dist/resources/handlers.d.ts +1 -1
  47. package/dist/server/agent-engine-default-model-route.d.ts +2 -2
  48. package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
  49. package/dist/server/auth.js +1 -0
  50. package/dist/server/core-routes-plugin.js +1 -0
  51. package/dist/server/index.d.ts +2 -1
  52. package/dist/server/index.js +2 -1
  53. package/dist/server/realtime-token.d.ts +1 -1
  54. package/dist/server/transcribe-voice.d.ts +1 -1
  55. package/dist/server/workspace-provider-oauth.d.ts +1 -1
  56. package/dist/server/workspace-provider-oauth.js +2 -0
  57. package/dist/shared/context-status.js +1 -1
  58. package/dist/shared/optional-peer-ssr.d.ts +2 -0
  59. package/dist/shared/optional-peer-ssr.js +123 -0
  60. package/dist/shared/tool-inputs.d.ts +2 -0
  61. package/dist/shared/tool-inputs.js +56 -0
  62. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  63. package/dist/tracking/index.d.ts +1 -0
  64. package/dist/tracking/index.js +1 -0
  65. package/dist/vite/client.js +46 -3
  66. package/dist/workspace-connections/store.d.ts +3 -1
  67. package/dist/workspace-connections/store.js +18 -8
  68. package/dist/workspace-files/constants.d.ts +3 -0
  69. package/dist/workspace-files/constants.js +3 -0
  70. package/dist/workspace-files/store.d.ts +2 -3
  71. package/dist/workspace-files/store.js +2 -3
  72. package/docs/content/automations.mdx +19 -13
  73. package/package.json +3 -3
  74. package/src/eject/workspace-connections.ts +1 -0
@@ -10,7 +10,7 @@ import { classifyTerminalErrorCode, describeErrorWithCauses, isProviderConnectio
10
10
  import { runErrorTelemetryProperties } from "./engine/error-telemetry.js";
11
11
  import { getAgentEngineEntry } from "./engine/registry.js";
12
12
  import { EngineError } from "./engine/types.js";
13
- import { insertRun, insertRunEvent, updateRunStatusIfRunning, markRunAborted, getRunAbortState, getRunStatus, getRunEventsSince, getCurrentTurnRunEventsForThread, getRunById, getRunByThread, getRunTurnRef, markTurnAborted, cleanupOldRuns, updateRunHeartbeat, bumpRunProgress, setRunInFlightMarker, reapIfStale, reapUnclaimedBackgroundRun, shouldRedispatchUnclaimedBackgroundRun, reconcileTerminalRunFromEvents, ensureTerminalRunEvent, getLastTerminalRunEvent, resolveErroredRunTerminalEvent, setRunError, setRunTerminalReason, persistRunCheckpointEvent, recordRunDiagnostic, RUN_DIAG_STAGE, terminalEventForAbortReason, RUN_RECORD_MISSING_ERROR_EVENT, RUN_RECORD_MISSING_GRACE_MS, RUN_TERMINAL_LOOKUP_FAILED_ERROR_EVENT, UNKNOWN_RUN_STATUS_ERROR_EVENT, } from "./run-store.js";
13
+ import { insertRun, insertRunEvent, insertRunEvents, updateRunStatusIfRunning, markRunAborted, getRunAbortState, getRunStatus, getRunEventsSince, getCurrentTurnRunEventsForThread, getRunById, getRunByThread, getRunTurnRef, markTurnAborted, cleanupOldRuns, updateRunHeartbeat, bumpRunProgress, setRunInFlightMarker, reapIfStale, reapUnclaimedBackgroundRun, shouldRedispatchUnclaimedBackgroundRun, reconcileTerminalRunFromEvents, ensureTerminalRunEvent, getLastTerminalRunEvent, resolveErroredRunTerminalEvent, setRunError, setRunTerminalReason, persistRunCheckpointEvent, recordRunDiagnostic, RUN_DIAG_STAGE, terminalEventForAbortReason, RUN_RECORD_MISSING_ERROR_EVENT, RUN_RECORD_MISSING_GRACE_MS, RUN_TERMINAL_LOOKUP_FAILED_ERROR_EVENT, UNKNOWN_RUN_STATUS_ERROR_EVENT, } from "./run-store.js";
14
14
  import { isContinuationTerminalReason } from "./types.js";
15
15
  const activeRuns = new Map();
16
16
  const threadToRun = new Map();
@@ -232,6 +232,11 @@ function isTerminalRunEvent(event) {
232
232
  event.type === "loop_limit" ||
233
233
  event.type === "auto_continue");
234
234
  }
235
+ function isBatchableRunEvent(event) {
236
+ return (event.type !== "tool_start" &&
237
+ event.type !== "tool_done" &&
238
+ !isTerminalRunEvent(event));
239
+ }
235
240
  /**
236
241
  * A tool result with no later assistant text is an unfinished turn, not a
237
242
  * successful terminal response. Keep this predicate beside the run-manager's
@@ -256,6 +261,8 @@ export function endsAfterToolResultWithoutAssistantFinal(run) {
256
261
  continue;
257
262
  }
258
263
  if (event.type === "tool_done") {
264
+ if (event.approvalPause === true)
265
+ return false;
259
266
  toolResultAfterLastAssistantText =
260
267
  event.isError === true ||
261
268
  (event.chatUI === undefined && event.mcpApp === undefined);
@@ -570,6 +577,10 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
570
577
  throw error;
571
578
  });
572
579
  let persistenceChain = Promise.resolve();
580
+ // Streamed deltas arrive hundreds per tool call, and a write tool waits for
581
+ // every queued event to persist first; one round trip per event put tens of
582
+ // seconds between the model finishing and the tool starting.
583
+ let openEventBatch = null;
573
584
  const PROGRESS_BUMP_INTERVAL_MS = 1_000;
574
585
  let lastProgressBumpAt = 0;
575
586
  let progressWriteInFlight = null;
@@ -1029,18 +1040,20 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1029
1040
  },
1030
1041
  });
1031
1042
  };
1032
- const persistRunEvent = async (runEvent, eventData) => {
1043
+ const persistEventHook = options?.persistEvent;
1044
+ const persistRunEvent = async (runEvent, eventData, eventAt) => {
1033
1045
  if (runEvent.event.type === "tool_start")
1034
1046
  await insertRunPromise;
1035
1047
  const write = () => runEvent.event.type === "tool_start" ||
1036
1048
  runEvent.event.type === "tool_done"
1037
1049
  ? insertRunEvent(runId, runEvent.seq, eventData, {
1050
+ eventAt,
1038
1051
  toolInputSource: "execution",
1039
1052
  ...(runEvent.event.type === "tool_start"
1040
1053
  ? { requireInserted: true }
1041
1054
  : {}),
1042
1055
  })
1043
- : insertRunEvent(runId, runEvent.seq, eventData);
1056
+ : insertRunEvent(runId, runEvent.seq, eventData, { eventAt });
1044
1057
  return options?.persistEvent
1045
1058
  ? options.persistEvent(write, {
1046
1059
  terminal: isTerminalRunEvent(runEvent.event),
@@ -1052,6 +1065,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1052
1065
  };
1053
1066
  const emitRunEvent = (runEvent, options) => {
1054
1067
  const eventData = JSON.stringify(runEvent.event);
1068
+ const eventAt = Date.now();
1055
1069
  run.events.push(runEvent);
1056
1070
  for (const subscriber of run.subscribers) {
1057
1071
  try {
@@ -1066,9 +1080,9 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1066
1080
  lastRealProgressAt = Date.now();
1067
1081
  bumpProgressIfDue();
1068
1082
  }
1069
- const thisInsert = persistenceChain.then(async () => {
1083
+ const retryOnce = async (write) => {
1070
1084
  try {
1071
- await persistRunEvent(runEvent, eventData);
1085
+ await write();
1072
1086
  }
1073
1087
  catch (error) {
1074
1088
  if (!eventPersistenceErrorCaptured) {
@@ -1078,11 +1092,36 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1078
1092
  eventType: runEvent.event.type,
1079
1093
  });
1080
1094
  }
1081
- await persistRunEvent(runEvent, eventData);
1095
+ await write();
1082
1096
  }
1083
- });
1084
- persistenceChain = thisInsert;
1085
- const persistence = thisInsert;
1097
+ };
1098
+ let persistence;
1099
+ if (isBatchableRunEvent(runEvent.event) && !persistEventHook) {
1100
+ if (!openEventBatch) {
1101
+ const batch = {
1102
+ events: [],
1103
+ write: persistenceChain.then(() => {
1104
+ if (openEventBatch === batch)
1105
+ openEventBatch = null;
1106
+ return retryOnce(() => insertRunEvents(runId, batch.events));
1107
+ }),
1108
+ };
1109
+ openEventBatch = batch;
1110
+ persistenceChain = batch.write;
1111
+ }
1112
+ openEventBatch.events.push({
1113
+ seq: runEvent.seq,
1114
+ eventAt,
1115
+ eventData,
1116
+ });
1117
+ persistence = openEventBatch.write;
1118
+ }
1119
+ else {
1120
+ // Anything emitted after this event must not persist before it.
1121
+ openEventBatch = null;
1122
+ persistence = persistenceChain.then(() => retryOnce(() => persistRunEvent(runEvent, eventData, eventAt)));
1123
+ persistenceChain = persistence;
1124
+ }
1086
1125
  if (!options?.surfacePersistenceError) {
1087
1126
  persistence.catch(() => { });
1088
1127
  }
@@ -1092,7 +1131,14 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1092
1131
  const send = (event) => {
1093
1132
  if (run.status === "aborted" && abort.signal.aborted)
1094
1133
  return;
1095
- const runEvent = { seq: run.events.length, event };
1134
+ // Explicit false distinguishes current completions from legacy pauses.
1135
+ const normalizedEvent = event.type === "tool_done" && event.approvalPause === undefined
1136
+ ? { ...event, approvalPause: false }
1137
+ : event;
1138
+ const runEvent = {
1139
+ seq: run.events.length,
1140
+ event: normalizedEvent,
1141
+ };
1096
1142
  if (isTerminalRunEvent(event)) {
1097
1143
  pendingTerminalEvent = runEvent;
1098
1144
  return;
@@ -1275,7 +1321,7 @@ export function startRun(runId, threadId, runFn, onComplete, options) {
1275
1321
  console.error("[run-manager] terminal event persistence error:", err instanceof Error ? err.message : err);
1276
1322
  if (!eventPersistenceError) {
1277
1323
  try {
1278
- await persistRunEvent(terminal, JSON.stringify(terminal.event));
1324
+ await persistRunEvent(terminal, JSON.stringify(terminal.event), Date.now());
1279
1325
  terminalPersistenceError = null;
1280
1326
  }
1281
1327
  catch (retryError) {
@@ -285,7 +285,17 @@ export declare class AgentRunEventNotPersistedError extends Error {
285
285
  export declare function insertRunEvent(runId: string, seq: number, eventData: string, options?: {
286
286
  toolInputSource?: "execution";
287
287
  requireInserted?: boolean;
288
+ eventAt?: number;
288
289
  }): Promise<void>;
290
+ /**
291
+ * Same guarantees as `insertRunEvent` without execution-input fingerprints,
292
+ * so tool_start/tool_done must keep going through `insertRunEvent`.
293
+ */
294
+ export declare function insertRunEvents(runId: string, events: ReadonlyArray<{
295
+ seq: number;
296
+ eventAt: number;
297
+ eventData: string;
298
+ }>): Promise<void>;
289
299
  export declare const CHECKPOINT_TERMINAL_EVENT_SEQ = 1000000000;
290
300
  export declare function persistRunCheckpointEvent(runId: string, event: AgentChatEvent, terminalReason: string): Promise<void>;
291
301
  export declare function getRunEventsSince(runId: string, fromSeq: number, opts?: {
@@ -9,10 +9,11 @@ import { lockAndAssertServicePrincipalMayStartRun, prepareServicePrincipalRunSta
9
9
  import { captureError } from "../server/capture-error.js";
10
10
  import { assertNoInlineImageBytes, stripInlineBytes, stripInlineBytesFromJson, } from "../shared/inline-bytes.js";
11
11
  import { isRequestedStopAbortReason } from "./abort-reasons.js";
12
+ import { approvalKeyForHistory } from "./approval-key.js";
12
13
  import { admitAutoContinue, admitManualContinue, } from "./auto-continue.js";
13
14
  import { AGENT_CHAT_RECOVERY_OF_RUN_FIELD } from "./durable-background.js";
14
15
  import { LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "./engine/credential-errors.js";
15
- import { isConsistentToolCallInputFingerprint, isRedactedToolCallInput, toolCallInputFingerprint, } from "./tool-call-journal.js";
16
+ import { isConsistentToolCallInputFingerprint, isUnavailableToolCallInput, toolCallInputFingerprint, } from "./tool-call-journal.js";
16
17
  import { CONTINUATION_REASONS, isContinuationTerminalReason } from "./types.js";
17
18
  let _initPromise;
18
19
  export const RUN_STALE_MS = 15_000;
@@ -1864,9 +1865,15 @@ export async function getRunAbortState(runId) {
1864
1865
  }
1865
1866
  function persistedRunEventData(eventData, inputSource) {
1866
1867
  const stripped = stripInlineBytesFromJson(eventData, "placeholder");
1868
+ const original = JSON.parse(eventData);
1869
+ if (original.type === "approval_required") {
1870
+ return JSON.stringify({
1871
+ ...JSON.parse(stripped),
1872
+ approvalKey: approvalKeyForHistory(original.approvalKey),
1873
+ });
1874
+ }
1867
1875
  if (stripped === eventData && inputSource !== "execution")
1868
1876
  return eventData;
1869
- const original = JSON.parse(eventData);
1870
1877
  if ((original.type !== "tool_start" && original.type !== "tool_done") ||
1871
1878
  original.input === undefined ||
1872
1879
  inputSource !== "execution" ||
@@ -1910,7 +1917,7 @@ export async function insertRunEvent(runId, seq, eventData, options) {
1910
1917
  args: [
1911
1918
  runId,
1912
1919
  seq,
1913
- Date.now(),
1920
+ options?.eventAt ?? Date.now(),
1914
1921
  storedEventData,
1915
1922
  ...(options?.requireInserted ? [] : [runId]),
1916
1923
  ],
@@ -1918,6 +1925,42 @@ export async function insertRunEvent(runId, seq, eventData, options) {
1918
1925
  if (options?.requireInserted && rowsAffected !== 1)
1919
1926
  throw new AgentRunEventNotPersistedError(runId, seq);
1920
1927
  }
1928
+ // Stays well under PostgreSQL's 65,535 bind-parameter limit at 4 per row.
1929
+ const RUN_EVENT_BATCH_ROWS = 500;
1930
+ /**
1931
+ * Same guarantees as `insertRunEvent` without execution-input fingerprints,
1932
+ * so tool_start/tool_done must keep going through `insertRunEvent`.
1933
+ */
1934
+ export async function insertRunEvents(runId, events) {
1935
+ if (events.length === 0)
1936
+ return;
1937
+ await ensureRunTables();
1938
+ const client = getDbExec();
1939
+ for (let start = 0; start < events.length; start += RUN_EVENT_BATCH_ROWS) {
1940
+ const chunk = events.slice(start, start + RUN_EVENT_BATCH_ROWS);
1941
+ await client.execute({
1942
+ sql: `INSERT INTO agent_run_events (run_id, seq, event_at, event_data)
1943
+ SELECT v.run_id, v.seq, v.event_at, v.event_data
1944
+ FROM (VALUES ${chunk
1945
+ .map(() => "(CAST(? AS TEXT), CAST(? AS BIGINT), CAST(? AS BIGINT), CAST(? AS TEXT))")
1946
+ .join(", ")}) AS v(run_id, seq, event_at, event_data)
1947
+ WHERE NOT EXISTS (
1948
+ SELECT 1 FROM agent_runs
1949
+ WHERE id = ? AND status <> 'running'
1950
+ )
1951
+ ON CONFLICT (run_id, seq) DO NOTHING`,
1952
+ args: [
1953
+ ...chunk.flatMap(({ seq, eventAt, eventData }) => [
1954
+ runId,
1955
+ seq,
1956
+ eventAt,
1957
+ persistedRunEventData(eventData),
1958
+ ]),
1959
+ runId,
1960
+ ],
1961
+ });
1962
+ }
1963
+ }
1921
1964
  export const CHECKPOINT_TERMINAL_EVENT_SEQ = 1_000_000_000;
1922
1965
  export async function persistRunCheckpointEvent(runId, event, terminalReason) {
1923
1966
  await insertRunEvent(runId, CHECKPOINT_TERMINAL_EVENT_SEQ, JSON.stringify(event));
@@ -2219,11 +2262,13 @@ function isReadableJournalEvent(value) {
2219
2262
  (typeof value.inputStoredFingerprint === "string" &&
2220
2263
  /^[a-f0-9]{64}$/.test(value.inputStoredFingerprint))) &&
2221
2264
  isConsistentToolCallInputFingerprint(value.input, value.inputFingerprint, value.inputStoredFingerprint) &&
2222
- (!isRedactedToolCallInput(value.input) ||
2265
+ (!isUnavailableToolCallInput(value.input) ||
2223
2266
  value.inputFingerprint !== undefined) &&
2224
2267
  (type === "tool_start"
2225
2268
  ? Object.hasOwn(value, "input")
2226
2269
  : ["isError", "completedSideEffect", "replayed"].every((field) => value[field] === undefined || typeof value[field] === "boolean") &&
2270
+ (value.approvalPause === undefined ||
2271
+ typeof value.approvalPause === "boolean") &&
2227
2272
  (value.outcomeUnknown === undefined ||
2228
2273
  value.outcomeUnknown === true)));
2229
2274
  case "suggestions":
@@ -15,6 +15,8 @@ interface ContentPart {
15
15
  args?: Record<string, unknown>;
16
16
  result?: string;
17
17
  isError?: boolean;
18
+ approvalPause?: true;
19
+ approvalAskId?: string;
18
20
  outcome?: "unknown";
19
21
  completedSideEffect?: boolean;
20
22
  artifacts?: ArtifactReceipt[];