@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.
- package/agent-native.eject.json +1 -0
- package/dist/agent/approval-key.d.ts +2 -0
- package/dist/agent/approval-key.js +12 -0
- package/dist/agent/context-xray/tokenize.js +12 -3
- package/dist/agent/engine/translate-anthropic.js +4 -0
- package/dist/agent/engine/types.d.ts +2 -0
- package/dist/agent/production-agent.d.ts +20 -5
- package/dist/agent/production-agent.js +227 -34
- package/dist/agent/run-manager.js +57 -11
- package/dist/agent/run-store.d.ts +10 -0
- package/dist/agent/run-store.js +49 -4
- package/dist/agent/thread-data-builder.d.ts +2 -0
- package/dist/agent/thread-data-builder.js +288 -14
- package/dist/agent/tool-approval-store.d.ts +3 -1
- package/dist/agent/tool-approval-store.js +26 -12
- package/dist/agent/tool-call-journal.d.ts +1 -1
- package/dist/agent/tool-call-journal.js +5 -3
- package/dist/agent/types.d.ts +7 -0
- package/dist/client/chat/agentkit-agent-native.js +18 -0
- package/dist/client/chat/agentkit-protocol.js +56 -5
- package/dist/client/chat/runtime.d.ts +10 -0
- package/dist/client/chat/runtime.js +257 -26
- package/dist/client/sse-event-processor.d.ts +22 -0
- package/dist/client/sse-event-processor.js +91 -11
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/connections/catalog.d.ts +24 -1
- package/dist/connections/catalog.js +12 -0
- package/dist/data-programs/schema.d.ts +1 -0
- package/dist/data-programs/schema.js +3 -0
- package/dist/data-programs/store.js +2 -1
- package/dist/deploy/build.js +16 -14
- package/dist/eject/workspace-connections.js +1 -0
- package/dist/extensions/fetch-tool.js +114 -23
- package/dist/extensions/schema.d.ts +1 -0
- package/dist/extensions/schema.js +3 -0
- package/dist/extensions/store.js +2 -1
- package/dist/extensions/web-content.d.ts +5 -1
- package/dist/extensions/web-content.js +24 -6
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +11 -11
- package/dist/provider-api/actions/provider-api.d.ts +9 -9
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.d.ts +2 -0
- package/dist/provider-api/index.js +95 -12
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/auth.js +1 -0
- package/dist/server/core-routes-plugin.js +1 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.d.ts +1 -1
- package/dist/server/workspace-provider-oauth.js +2 -0
- package/dist/shared/context-status.js +1 -1
- package/dist/shared/optional-peer-ssr.d.ts +2 -0
- package/dist/shared/optional-peer-ssr.js +123 -0
- package/dist/shared/tool-inputs.d.ts +2 -0
- package/dist/shared/tool-inputs.js +56 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/tracking/index.d.ts +1 -0
- package/dist/tracking/index.js +1 -0
- package/dist/vite/client.js +46 -3
- package/dist/workspace-connections/store.d.ts +3 -1
- package/dist/workspace-connections/store.js +18 -8
- package/dist/workspace-files/constants.d.ts +3 -0
- package/dist/workspace-files/constants.js +3 -0
- package/dist/workspace-files/store.d.ts +2 -3
- package/dist/workspace-files/store.js +2 -3
- package/docs/content/automations.mdx +19 -13
- package/package.json +3 -3
- 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
|
|
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
|
|
1083
|
+
const retryOnce = async (write) => {
|
|
1070
1084
|
try {
|
|
1071
|
-
await
|
|
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
|
|
1095
|
+
await write();
|
|
1082
1096
|
}
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
|
|
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
|
-
|
|
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?: {
|
package/dist/agent/run-store.js
CHANGED
|
@@ -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,
|
|
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
|
-
(!
|
|
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":
|