@agent-native/core 0.209.0 → 0.209.1-nightly-20261015093558
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/dist/a2a/task-store.d.ts +1 -0
- package/dist/a2a/task-store.js +63 -62
- package/dist/action-call-classification.d.ts +15 -0
- package/dist/action-call-classification.js +24 -0
- package/dist/action-input-coercion.d.ts +10 -0
- package/dist/action-input-coercion.js +77 -0
- package/dist/action.d.ts +19 -1
- package/dist/action.js +37 -74
- package/dist/agent/engine/ai-sdk-engine.js +21 -4
- package/dist/agent/engine/continuation-dispatch-retry.d.ts +3 -0
- package/dist/agent/engine/continuation-dispatch-retry.js +53 -6
- package/dist/agent/harness/store.d.ts +1 -0
- package/dist/agent/harness/store.js +14 -16
- package/dist/agent/observational-memory/store.d.ts +1 -0
- package/dist/agent/observational-memory/store.js +28 -24
- package/dist/agent/production-agent.d.ts +16 -1
- package/dist/agent/production-agent.js +63 -10
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +61 -56
- package/dist/agent/tool-approval-store.d.ts +2 -0
- package/dist/agent/tool-approval-store.js +31 -29
- package/dist/app-config/migration.d.ts +1 -0
- package/dist/app-config/migration.js +4 -0
- package/dist/app-config/schema.d.ts +1 -0
- package/dist/application-state/store.d.ts +1 -0
- package/dist/application-state/store.js +36 -25
- package/dist/audit/store.d.ts +1 -0
- package/dist/audit/store.js +26 -28
- package/dist/browser-sessions/store.d.ts +1 -0
- package/dist/browser-sessions/store.js +15 -17
- package/dist/chat-threads/store.d.ts +1 -0
- package/dist/chat-threads/store.js +26 -19
- package/dist/checkpoints/store.d.ts +1 -0
- package/dist/checkpoints/store.js +19 -18
- package/dist/client/agent-sidebar-state.d.ts +1 -1
- package/dist/client/agent-sidebar-state.js +97 -5
- package/dist/coding-tools/run-code.js +5 -2
- package/dist/coding-tools/sandbox/executions-store.d.ts +1 -0
- package/dist/coding-tools/sandbox/executions-store.js +29 -30
- package/dist/collab/awareness-store.d.ts +1 -0
- package/dist/collab/awareness-store.js +15 -19
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/storage.d.ts +1 -0
- package/dist/collab/storage.js +25 -24
- package/dist/data-programs/store.d.ts +1 -0
- package/dist/data-programs/store.js +25 -24
- package/dist/db/client.d.ts +1 -1
- package/dist/db/client.js +10 -30
- package/dist/db/ddl-guard.js +11 -3
- package/dist/db/index.d.ts +1 -1
- package/dist/db/index.js +1 -1
- package/dist/db/migration-policy.d.ts +2 -0
- package/dist/db/migration-policy.js +4 -0
- package/dist/db/runtime-facts.d.ts +11 -0
- package/dist/db/runtime-facts.js +41 -0
- package/dist/db/schema-catalog.d.ts +17 -0
- package/dist/db/schema-catalog.js +156 -0
- package/dist/db/store-registry.d.ts +85 -0
- package/dist/db/store-registry.generated.d.ts +2 -0
- package/dist/db/store-registry.generated.js +273 -0
- package/dist/db/store-registry.js +354 -0
- package/dist/db/widen-columns.js +7 -2
- package/dist/email-catalog/log.d.ts +1 -0
- package/dist/email-catalog/log.js +37 -25
- package/dist/extensions/slots/store.d.ts +1 -0
- package/dist/extensions/slots/store.js +20 -21
- package/dist/extensions/store.d.ts +1 -0
- package/dist/extensions/store.js +41 -26
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/guards/identity-columns-registered.js +5 -0
- package/dist/guards/release-schema-complete.d.ts +7 -13
- package/dist/guards/release-schema-complete.js +67 -32
- package/dist/guards/store-migrations-lock.d.ts +18 -0
- package/dist/guards/store-migrations-lock.js +49 -0
- package/dist/guards/store-registry-codegen.d.ts +16 -0
- package/dist/guards/store-registry-codegen.js +90 -0
- package/dist/history/store.d.ts +1 -0
- package/dist/history/store.js +20 -18
- package/dist/identity/retired-emails.d.ts +1 -0
- package/dist/identity/retired-emails.js +14 -13
- package/dist/integrations/a2a-continuations-store.d.ts +1 -0
- package/dist/integrations/a2a-continuations-store.js +46 -33
- package/dist/integrations/awaiting-input-store.d.ts +1 -0
- package/dist/integrations/awaiting-input-store.js +15 -19
- package/dist/integrations/computer-supervision-store.d.ts +1 -0
- package/dist/integrations/computer-supervision-store.js +15 -21
- package/dist/integrations/config-store.d.ts +1 -0
- package/dist/integrations/config-store.js +14 -16
- package/dist/integrations/controls-store.d.ts +1 -0
- package/dist/integrations/controls-store.js +15 -16
- package/dist/integrations/identity-links-store.d.ts +1 -0
- package/dist/integrations/identity-links-store.js +14 -21
- package/dist/integrations/installations-store.d.ts +1 -0
- package/dist/integrations/installations-store.js +15 -23
- package/dist/integrations/integration-campaigns-store.d.ts +1 -0
- package/dist/integrations/integration-campaigns-store.js +16 -23
- package/dist/integrations/pending-tasks-store.d.ts +1 -0
- package/dist/integrations/pending-tasks-store.js +16 -18
- package/dist/integrations/remote-commands-store.d.ts +1 -0
- package/dist/integrations/remote-commands-store.js +14 -16
- package/dist/integrations/remote-devices-store.d.ts +1 -0
- package/dist/integrations/remote-devices-store.js +39 -38
- package/dist/integrations/remote-push-store.d.ts +1 -0
- package/dist/integrations/remote-push-store.js +25 -24
- package/dist/integrations/remote-run-events-store.d.ts +1 -0
- package/dist/integrations/remote-run-events-store.js +17 -16
- package/dist/integrations/scope-store.d.ts +1 -0
- package/dist/integrations/scope-store.js +18 -36
- package/dist/integrations/thread-mapping-store.d.ts +1 -0
- package/dist/integrations/thread-mapping-store.js +25 -24
- package/dist/integrations/usage-budget-store.d.ts +1 -0
- package/dist/integrations/usage-budget-store.js +40 -49
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/automation-work-evidence.js +7 -3
- package/dist/jobs/run-history.d.ts +1 -0
- package/dist/jobs/run-history.js +38 -40
- package/dist/jobs/scheduler-health.d.ts +1 -0
- package/dist/jobs/scheduler-health.js +28 -30
- package/dist/mcp/approval-store.d.ts +1 -0
- package/dist/mcp/approval-store.js +23 -24
- package/dist/mcp/connect-store.d.ts +1 -0
- package/dist/mcp/connect-store.js +50 -49
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.js +24 -23
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/mcp-client/oauth-routes.js +20 -13
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/notifications/store.d.ts +1 -0
- package/dist/notifications/store.js +14 -16
- package/dist/oauth-tokens/store.d.ts +1 -0
- package/dist/oauth-tokens/store.js +45 -31
- package/dist/observability/store.d.ts +1 -0
- package/dist/observability/store.js +24 -26
- package/dist/org/index.d.ts +1 -1
- package/dist/org/service-principal-policy.d.ts +1 -0
- package/dist/org/service-principal-policy.js +29 -28
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/store.d.ts +1 -0
- package/dist/progress/store.js +27 -29
- package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
- package/dist/provider-api/actions/provider-api.d.ts +14 -9
- package/dist/provider-api/actions/provider-api.js +16 -1
- package/dist/provider-api/actions/staged-datasets.js +10 -2
- package/dist/provider-api/corpus-jobs-store.d.ts +1 -0
- package/dist/provider-api/corpus-jobs-store.js +81 -79
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/corpus-jobs.js +43 -6
- package/dist/provider-api/custom-registry.d.ts +1 -0
- package/dist/provider-api/custom-registry.js +23 -17
- package/dist/provider-api/index.js +34 -2
- package/dist/provider-api/quota-governor.d.ts +1 -0
- package/dist/provider-api/quota-governor.js +33 -26
- package/dist/provider-api/staged-datasets-store.d.ts +57 -0
- package/dist/provider-api/staged-datasets-store.js +311 -149
- package/dist/provider-api/staging.js +14 -4
- package/dist/resource-changes/store.d.ts +1 -0
- package/dist/resource-changes/store.js +8 -7
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/resources/store.d.ts +1 -0
- package/dist/resources/store.js +92 -56
- package/dist/review/store.d.ts +1 -0
- package/dist/review/store.js +27 -25
- package/dist/review/suggestions/store.d.ts +1 -0
- package/dist/review/suggestions/store.js +56 -50
- package/dist/search/index-store.d.ts +2 -2
- package/dist/search/index-store.js +6 -7
- package/dist/secrets/storage.d.ts +1 -0
- package/dist/secrets/storage.js +18 -17
- package/dist/server/action-discovery.js +6 -0
- package/dist/server/agent-chat/action-filters-a2a.js +11 -0
- package/dist/server/agent-chat/framework-prompts.js +6 -2
- package/dist/server/agent-chat-plugin.js +8 -16
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +2 -2
- package/dist/server/agent-teams-run-queue.d.ts +1 -0
- package/dist/server/agent-teams-run-queue.js +21 -20
- package/dist/server/auth.d.ts +1 -0
- package/dist/server/auth.js +20 -17
- package/dist/server/embed-session.d.ts +1 -0
- package/dist/server/embed-session.js +34 -33
- package/dist/server/filesystem-action-entry.d.ts +7 -0
- package/dist/server/filesystem-action-entry.js +35 -0
- package/dist/server/google-oauth.d.ts +8 -0
- package/dist/server/google-oauth.js +8 -5
- package/dist/server/identity-sso-store.d.ts +1 -0
- package/dist/server/identity-sso-store.js +18 -27
- package/dist/server/poll.d.ts +2 -0
- package/dist/server/poll.js +74 -29
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/recap-image-store.d.ts +1 -0
- package/dist/server/recap-image-store.js +15 -14
- package/dist/server/release-migrations.js +54 -49
- package/dist/server/release-schema.d.ts +8 -27
- package/dist/server/release-schema.js +41 -314
- package/dist/server/request-context.d.ts +3 -0
- package/dist/server/self-dispatch.d.ts +9 -0
- package/dist/server/self-dispatch.js +20 -1
- package/dist/settings/store.d.ts +1 -0
- package/dist/settings/store.js +33 -23
- package/dist/shared/analytics-events.js +1 -0
- package/dist/sharing/access-request-store.d.ts +1 -0
- package/dist/sharing/access-request-store.js +17 -16
- package/dist/sharing/indexes.js +1 -0
- package/dist/templates/chat/.agents/skills/storing-data/SKILL.md +2 -2
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +2 -2
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +5 -0
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/chat-run-health.md +50 -0
- package/dist/templates/headless/.agents/skills/storing-data/SKILL.md +2 -2
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -2
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/dist/triggers/event-queue.js +1 -0
- package/dist/triggers/webhook-store.d.ts +1 -0
- package/dist/triggers/webhook-store.js +14 -18
- package/dist/usage/alerts-store.d.ts +1 -0
- package/dist/usage/alerts-store.js +47 -48
- package/dist/usage/store.d.ts +1 -0
- package/dist/usage/store.js +67 -59
- package/dist/workspace-connections/groups.d.ts +1 -0
- package/dist/workspace-connections/groups.js +30 -42
- package/dist/workspace-connections/store.d.ts +1 -0
- package/dist/workspace-connections/store.js +17 -19
- package/docs/content/create-with-an-agent.mdx +160 -0
- package/docs/content/getting-started.mdx +3 -0
- package/docs/content/integrations.mdx +6 -2
- package/docs/content/template-clips-features.mdx +1 -1
- package/docs/content/tracking.mdx +1 -1
- package/package.json +4 -4
- package/src/templates/chat/.agents/skills/storing-data/SKILL.md +2 -2
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +2 -2
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +5 -0
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/chat-run-health.md +50 -0
- package/src/templates/headless/.agents/skills/storing-data/SKILL.md +2 -2
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +2 -2
|
@@ -1,20 +1,50 @@
|
|
|
1
|
+
import { SelfDispatchHttpError } from "../../server/self-dispatch.js";
|
|
2
|
+
// These statuses mean the endpoint is shedding load, not that the handoff is
|
|
3
|
+
// dead. They are waited out with jittered backoff instead of spending the short
|
|
4
|
+
// fixed attempt cap, which deferred the chunk to the sweep's multi-minute gap.
|
|
5
|
+
const OVERLOAD_STATUSES = new Set([429, 502, 503, 504, 520]);
|
|
6
|
+
const OVERLOAD_BACKOFF_BASE_MS = 1_000;
|
|
7
|
+
const OVERLOAD_BACKOFF_CAP_MS = 30_000;
|
|
8
|
+
const RETRY_AFTER_CLAMP_MS = 60_000;
|
|
9
|
+
// Full jitter can draw ~0 forever, so the wait budget alone never drains.
|
|
10
|
+
const MAX_OVERLOAD_RETRIES = 8;
|
|
11
|
+
/** Delay before the next try, or null when waiting any longer is pointless. */
|
|
12
|
+
function overloadBackoffMs(err, retriesSoFar, waitedMs, budgetMs, random) {
|
|
13
|
+
if (retriesSoFar >= MAX_OVERLOAD_RETRIES)
|
|
14
|
+
return null;
|
|
15
|
+
const remainingMs = budgetMs - waitedMs;
|
|
16
|
+
if (remainingMs <= 0)
|
|
17
|
+
return null;
|
|
18
|
+
const retryAfterMs = Math.min(err.retryAfterMs ?? 0, RETRY_AFTER_CLAMP_MS);
|
|
19
|
+
// The server asked for longer than this run can wait; the sweep owns it.
|
|
20
|
+
if (retryAfterMs > remainingMs)
|
|
21
|
+
return null;
|
|
22
|
+
const ceilingMs = Math.min(OVERLOAD_BACKOFF_CAP_MS, OVERLOAD_BACKOFF_BASE_MS * 2 ** retriesSoFar);
|
|
23
|
+
return Math.min(Math.max(random() * ceilingMs, retryAfterMs), remainingMs);
|
|
24
|
+
}
|
|
1
25
|
export async function attemptContinuationDispatch(params) {
|
|
2
|
-
const { event, backgroundContinuationCount, nextRunId, nextRowInserted, continuationDispatchPath, dispatchBody, dispatchBudget, isLoopProtectionDispatchError, maxNestedSelfDispatchDepth, deps: d, } = params;
|
|
26
|
+
const { event, backgroundContinuationCount, nextRunId, nextRowInserted, continuationDispatchPath, dispatchBody, dispatchBudget, isLoopProtectionDispatchError, maxNestedSelfDispatchDepth, deps: d, random = Math.random, now = Date.now, } = params;
|
|
3
27
|
const maxDispatchAttempts = dispatchBudget.maxDispatchAttempts;
|
|
4
28
|
const dispatchResponseTimeoutMs = dispatchBudget.dispatchResponseTimeoutMs;
|
|
29
|
+
const overloadWaitBudgetMs = dispatchBudget.overloadWaitBudgetMs;
|
|
5
30
|
let dispatched = false;
|
|
6
31
|
let lastDispatchErr;
|
|
7
32
|
const nestedDepthExceeded = backgroundContinuationCount >= maxNestedSelfDispatchDepth;
|
|
8
33
|
if (nestedDepthExceeded) {
|
|
9
34
|
lastDispatchErr = new Error(`proactive nested-dispatch depth cap reached (backgroundContinuationCount=${backgroundContinuationCount} >= MAX_NESTED_SELF_DISPATCH_DEPTH=${maxNestedSelfDispatchDepth}) — deferring to the unclaimed-background-run sweep instead of risking Netlify loop protection`);
|
|
10
35
|
}
|
|
11
|
-
|
|
36
|
+
const startedAt = now();
|
|
37
|
+
// Overload retries are paid for by the wait budget, not the attempt cap.
|
|
38
|
+
let overloadRetries = 0;
|
|
39
|
+
let overloadWaitedMs = 0;
|
|
40
|
+
let failedAttempts = 0;
|
|
41
|
+
let nextBackoffMs = 0;
|
|
42
|
+
for (let attempt = 0; !nestedDepthExceeded &&
|
|
43
|
+
attempt < maxDispatchAttempts + overloadRetries &&
|
|
44
|
+
!dispatched; attempt++) {
|
|
12
45
|
try {
|
|
13
46
|
if (attempt > 0) {
|
|
14
|
-
|
|
15
|
-
? Math.min(500 * 2 ** (attempt - 1), dispatchBudget.backoffCapMs)
|
|
16
|
-
: 500 * 2 ** attempt;
|
|
17
|
-
await d.sleep(backoffMs);
|
|
47
|
+
await d.sleep(nextBackoffMs);
|
|
18
48
|
if (nextRowInserted) {
|
|
19
49
|
await d.updateRunHeartbeat(nextRunId).catch(() => { });
|
|
20
50
|
}
|
|
@@ -46,6 +76,23 @@ export async function attemptContinuationDispatch(params) {
|
|
|
46
76
|
if (isLoopProtectionDispatchError(dispatchErr)) {
|
|
47
77
|
break;
|
|
48
78
|
}
|
|
79
|
+
if (dispatchErr instanceof SelfDispatchHttpError &&
|
|
80
|
+
OVERLOAD_STATUSES.has(dispatchErr.httpStatus)) {
|
|
81
|
+
const backoffMs = overloadBackoffMs(dispatchErr, overloadRetries,
|
|
82
|
+
// Slow overload responses spend the same host time as the sleeps.
|
|
83
|
+
Math.max(overloadWaitedMs, now() - startedAt), overloadWaitBudgetMs, random);
|
|
84
|
+
if (backoffMs === null)
|
|
85
|
+
break;
|
|
86
|
+
overloadRetries++;
|
|
87
|
+
overloadWaitedMs += backoffMs;
|
|
88
|
+
nextBackoffMs = backoffMs;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
failedAttempts++;
|
|
92
|
+
nextBackoffMs = Number.isFinite(dispatchBudget.backoffCapMs)
|
|
93
|
+
? Math.min(500 * 2 ** (failedAttempts - 1), dispatchBudget.backoffCapMs)
|
|
94
|
+
: 500 * 2 ** failedAttempts;
|
|
95
|
+
}
|
|
49
96
|
}
|
|
50
97
|
}
|
|
51
98
|
return { dispatched, lastDispatchErr, nestedDepthExceeded };
|
|
@@ -38,6 +38,7 @@ export interface SaveAgentHarnessSessionInput {
|
|
|
38
38
|
expectedGeneration?: number;
|
|
39
39
|
existingSession?: StoredAgentHarnessSession | null;
|
|
40
40
|
}
|
|
41
|
+
export declare const agentHarnessSessionsStore: import("../../db/store-registry.js").Store;
|
|
41
42
|
export declare function ensureAgentHarnessSessionTables(): Promise<void>;
|
|
42
43
|
export declare function saveAgentHarnessSession(input: SaveAgentHarnessSessionInput): Promise<StoredAgentHarnessSession>;
|
|
43
44
|
export declare function updateAgentHarnessSession(id: string, patch: Partial<Omit<SaveAgentHarnessSessionInput, "id">>): Promise<StoredAgentHarnessSession | null>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getDbExec } from "../../db/client.js";
|
|
2
2
|
import { ensureColumnExists, ensureIndexExists, ensureTableExists, } from "../../db/ddl-guard.js";
|
|
3
|
-
import {
|
|
3
|
+
import { defineStore } from "../../db/store-registry.js";
|
|
4
4
|
export class AgentHarnessSessionConflictError extends Error {
|
|
5
5
|
constructor(sessionId) {
|
|
6
6
|
super(`Harness session ${sessionId} changed concurrently; retry the operation.`);
|
|
@@ -12,11 +12,13 @@ export function isAgentHarnessSessionConflictError(error) {
|
|
|
12
12
|
(error instanceof Error &&
|
|
13
13
|
error.name === "AgentHarnessSessionConflictError"));
|
|
14
14
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
export const agentHarnessSessionsStore = defineStore({
|
|
16
|
+
id: "agent_harness_sessions",
|
|
17
|
+
migrations: [
|
|
18
|
+
{
|
|
19
|
+
name: "baseline",
|
|
20
|
+
run: async () => {
|
|
21
|
+
const createSql = `
|
|
20
22
|
CREATE TABLE IF NOT EXISTS agent_harness_sessions (
|
|
21
23
|
id TEXT PRIMARY KEY,
|
|
22
24
|
harness_name TEXT NOT NULL,
|
|
@@ -36,7 +38,6 @@ export async function ensureAgentHarnessSessionTables() {
|
|
|
36
38
|
stopped_at BIGINT
|
|
37
39
|
)
|
|
38
40
|
`;
|
|
39
|
-
{
|
|
40
41
|
await ensureTableExists("agent_harness_sessions", createSql);
|
|
41
42
|
for (const col of [
|
|
42
43
|
"run_id",
|
|
@@ -55,15 +56,12 @@ export async function ensureAgentHarnessSessionTables() {
|
|
|
55
56
|
await ensureIndexExists("idx_agent_harness_sessions_thread", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_thread ON agent_harness_sessions(thread_id, updated_at)`);
|
|
56
57
|
await ensureIndexExists("idx_agent_harness_sessions_status", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_status ON agent_harness_sessions(status, updated_at)`);
|
|
57
58
|
await ensureIndexExists("idx_agent_harness_sessions_owner", `CREATE INDEX IF NOT EXISTS idx_agent_harness_sessions_owner ON agent_harness_sessions(owner_email, updated_at)`);
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
initPromise = retainRequestDbPoolScope(initPromiseWithRequestDbPoolScope);
|
|
65
|
-
}
|
|
66
|
-
return initPromise;
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
export function ensureAgentHarnessSessionTables() {
|
|
64
|
+
return agentHarnessSessionsStore.ready();
|
|
67
65
|
}
|
|
68
66
|
export async function saveAgentHarnessSession(input) {
|
|
69
67
|
await ensureAgentHarnessSessionTables();
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* runtime even before the migration plugin is registered.
|
|
13
13
|
*/
|
|
14
14
|
import type { ObservationalMemoryEntry, ObservationalMemoryOwner, ObservationalMemoryTier } from "./types.js";
|
|
15
|
+
export declare const observationalMemoryStore: import("../../db/store-registry.js").Store;
|
|
15
16
|
export declare function ensureTable(): Promise<void>;
|
|
16
17
|
export declare function __resetObservationalMemoryTableCache(): void;
|
|
17
18
|
export interface InsertObservationalMemoryInput extends ObservationalMemoryOwner {
|
|
@@ -13,15 +13,16 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { getDbExec } from "../../db/client.js";
|
|
15
15
|
import { ensureTableExists, ensureIndexExists } from "../../db/ddl-guard.js";
|
|
16
|
-
import {
|
|
16
|
+
import { defineStore } from "../../db/store-registry.js";
|
|
17
17
|
import { widenIntColumnsToBigInt } from "../../db/widen-columns.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
export const observationalMemoryStore = defineStore({
|
|
19
|
+
id: "observational_memory",
|
|
20
|
+
migrations: [
|
|
21
|
+
{
|
|
22
|
+
name: "baseline",
|
|
23
|
+
run: async () => {
|
|
24
|
+
const integerType = "BIGINT";
|
|
25
|
+
const createSql = `CREATE TABLE IF NOT EXISTS observational_memory (
|
|
25
26
|
id TEXT PRIMARY KEY,
|
|
26
27
|
thread_id TEXT NOT NULL,
|
|
27
28
|
tier TEXT NOT NULL,
|
|
@@ -36,26 +37,29 @@ export async function ensureTable() {
|
|
|
36
37
|
org_id TEXT,
|
|
37
38
|
visibility TEXT NOT NULL DEFAULT 'private'
|
|
38
39
|
)`;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
await widenIntColumnsToBigInt("observational_memory", [
|
|
42
|
-
"created_at",
|
|
43
|
-
"updated_at",
|
|
44
|
-
]);
|
|
45
|
-
await ensureIndexExists("observational_memory_thread_tier_idx", `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
|
|
40
|
+
await ensureTableExists("observational_memory", createSql);
|
|
41
|
+
await ensureIndexExists("observational_memory_thread_tier_idx", `CREATE INDEX IF NOT EXISTS observational_memory_thread_tier_idx
|
|
46
42
|
ON observational_memory(thread_id, tier, created_at)`);
|
|
47
|
-
|
|
43
|
+
await ensureIndexExists("observational_memory_thread_owner_idx", `CREATE INDEX IF NOT EXISTS observational_memory_thread_owner_idx
|
|
48
44
|
ON observational_memory(thread_id, owner_email)`);
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "widen-bigint",
|
|
49
|
+
run: async () => {
|
|
50
|
+
await widenIntColumnsToBigInt("observational_memory", [
|
|
51
|
+
"created_at",
|
|
52
|
+
"updated_at",
|
|
53
|
+
]);
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
export function ensureTable() {
|
|
59
|
+
return observationalMemoryStore.ready();
|
|
56
60
|
}
|
|
57
61
|
export function __resetObservationalMemoryTableCache() {
|
|
58
|
-
|
|
62
|
+
observationalMemoryStore.reset();
|
|
59
63
|
}
|
|
60
64
|
function entryId() {
|
|
61
65
|
return `om-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
@@ -187,6 +187,8 @@ export interface ActionEntry {
|
|
|
187
187
|
persistInBrowser?: boolean;
|
|
188
188
|
changeResource?: (input: any, result: any) => import("../action.js").ActionChangeResource | null | undefined;
|
|
189
189
|
parallelSafe?: boolean;
|
|
190
|
+
/** See `ActionDefinition.retrySafe`. */
|
|
191
|
+
retrySafe?: boolean | ((input: any) => boolean);
|
|
190
192
|
dedupe?: boolean;
|
|
191
193
|
toolCallable?: boolean;
|
|
192
194
|
agentDiscoveryAvailable?: (context?: import("../action.js").ActionRunContext) => boolean | Promise<boolean>;
|
|
@@ -357,7 +359,12 @@ export interface ProductionAgentOptions {
|
|
|
357
359
|
runNoProgressTimeoutMs?: number;
|
|
358
360
|
durableBackgroundRuns?: boolean;
|
|
359
361
|
onRunStart?: (send: (event: AgentChatEvent) => void, threadId: string, runId: string) => void | Promise<void>;
|
|
360
|
-
|
|
362
|
+
/**
|
|
363
|
+
* Called when the run's engine, model, and effort resolve, and again before
|
|
364
|
+
* each model call, because a call can run on a rate-limit fallback model or
|
|
365
|
+
* at the lower effort an empty-response retry steps down to.
|
|
366
|
+
*/
|
|
367
|
+
onEngineResolved?: (engine: AgentEngine, model: string, reasoningEffort: ReasoningEffort | undefined) => void;
|
|
361
368
|
resolveOwnerEmail?: (event: any) => string | Promise<string>;
|
|
362
369
|
finalResponseGuard?: AgentLoopFinalResponseGuard;
|
|
363
370
|
skipFilesContext?: boolean;
|
|
@@ -674,6 +681,12 @@ export declare function runAgentLoop(opts: {
|
|
|
674
681
|
unknownWriteToolNames?: Set<string>;
|
|
675
682
|
internalContinuation?: boolean;
|
|
676
683
|
onModelInput?: ModelInputObserver;
|
|
684
|
+
/**
|
|
685
|
+
* The model and effort each model call uses. Either can change mid-run: a
|
|
686
|
+
* rate limit falls back to another model, and an empty response steps effort
|
|
687
|
+
* down.
|
|
688
|
+
*/
|
|
689
|
+
onModelSettings?: (model: string, reasoningEffort: ReasoningEffort | undefined) => void;
|
|
677
690
|
onUsage?: (usage: AgentLoopUsage) => void;
|
|
678
691
|
onOutcome?: (outcome: AgentLoopOutcome) => void;
|
|
679
692
|
ownerEmail?: string | null;
|
|
@@ -864,6 +877,8 @@ export interface ContinuationDispatchBudget {
|
|
|
864
877
|
maxDispatchAttempts: number;
|
|
865
878
|
dispatchResponseTimeoutMs: number;
|
|
866
879
|
backoffCapMs: number;
|
|
880
|
+
/** Total sleep allowed while the target answers 429/502/503/504/520. */
|
|
881
|
+
overloadWaitBudgetMs: number;
|
|
867
882
|
}
|
|
868
883
|
export declare function resolveContinuationDispatchBudget(opts: {
|
|
869
884
|
chainViaDurableBackground: boolean;
|
|
@@ -5,7 +5,7 @@ import Ajv2020 from "ajv/dist/2020.js";
|
|
|
5
5
|
import { defineEventHandler, getHeader, setResponseHeader, setResponseStatus, getMethod, } from "h3";
|
|
6
6
|
import "../authorization/check-action.js";
|
|
7
7
|
import { parseA2AAgentActivityPart } from "../a2a/activity.js";
|
|
8
|
-
import { actionCallEmitsChange, actionCallIsReadOnly, actionChangeResource, } from "../action-call-classification.js";
|
|
8
|
+
import { actionCallEmitsChange, actionCallIsReadOnly, actionCallIsRetrySafe, actionChangeResource, } from "../action-call-classification.js";
|
|
9
9
|
import { ACTION_CHAT_UI_RECORD_CHANGE_RENDERER, normalizeActionChangeResult, } from "../action-ui.js";
|
|
10
10
|
import { AgentConnectionRequiredError, describeToolParameterSignature, isActionContractError, runActionWithExecutionOutcome, isActionHiddenFromEveryAgentSurface, isAgentActionStopError, isAgentConnectionRequiredError, stripUnsupportedSchemaKeywords, } from "../action.js";
|
|
11
11
|
import { getAppConfig } from "../app-config/index.js";
|
|
@@ -4584,6 +4584,7 @@ export async function runAgentLoop(opts) {
|
|
|
4584
4584
|
: effectiveReasoningEffort,
|
|
4585
4585
|
providerOptions,
|
|
4586
4586
|
};
|
|
4587
|
+
opts.onModelSettings?.(model, effectiveReasoningEffort);
|
|
4587
4588
|
usage.llmCalls = (usage.llmCalls ?? 0) + 1;
|
|
4588
4589
|
notifyModelInputObserver(opts.onModelInput, engineMessages);
|
|
4589
4590
|
const eventStream = engine.stream(streamOpts);
|
|
@@ -4952,7 +4953,7 @@ export async function runAgentLoop(opts) {
|
|
|
4952
4953
|
fallbackModelAttempted = true;
|
|
4953
4954
|
send({
|
|
4954
4955
|
type: "activity",
|
|
4955
|
-
label:
|
|
4956
|
+
label: "Model is rate limited — switching to a backup model",
|
|
4956
4957
|
});
|
|
4957
4958
|
send({ type: "clear" });
|
|
4958
4959
|
model = fallbackModel;
|
|
@@ -4961,7 +4962,9 @@ export async function runAgentLoop(opts) {
|
|
|
4961
4962
|
usage.cacheReadTokens = 0;
|
|
4962
4963
|
usage.cacheWriteTokens = 0;
|
|
4963
4964
|
usage.model = fallbackModel;
|
|
4964
|
-
|
|
4965
|
+
// The sibling shares the throttled quota, so it gets this one
|
|
4966
|
+
// attempt; a fresh retry budget only re-hits the same limit.
|
|
4967
|
+
retry = maxRetriesForError(err) - 1;
|
|
4965
4968
|
continue;
|
|
4966
4969
|
}
|
|
4967
4970
|
}
|
|
@@ -5322,6 +5325,9 @@ export async function runAgentLoop(opts) {
|
|
|
5322
5325
|
const actionIsReadOnly = actionEntry
|
|
5323
5326
|
? actionCallIsReadOnly(actionEntry, toolCall.input, false)
|
|
5324
5327
|
: false;
|
|
5328
|
+
const actionRetrySafe = actionEntry
|
|
5329
|
+
? actionCallIsRetrySafe(actionEntry, toolCall.input)
|
|
5330
|
+
: false;
|
|
5325
5331
|
const repeatGuardStopFromThisCall = noteRepeatedToolCall(toolCall.name, toolCall.input, toolCall.id);
|
|
5326
5332
|
const rollbackRepeatedToolCall = () => {
|
|
5327
5333
|
const repeatKey = toolCallCacheKey(toolCall.name, toolCall.input);
|
|
@@ -5355,6 +5361,14 @@ export async function runAgentLoop(opts) {
|
|
|
5355
5361
|
const emitToolDone = (event) => {
|
|
5356
5362
|
if (event.outcomeUnknown) {
|
|
5357
5363
|
unknownWriteToolNames.add(toolCall.name);
|
|
5364
|
+
}
|
|
5365
|
+
// A write that errored after it was invoked may still have committed,
|
|
5366
|
+
// retry-safe or not, so cached reads of its target are stale.
|
|
5367
|
+
if (event.outcomeUnknown ||
|
|
5368
|
+
(event.isError &&
|
|
5369
|
+
actionInvoked &&
|
|
5370
|
+
!actionIsReadOnly &&
|
|
5371
|
+
!actionRefused)) {
|
|
5358
5372
|
readOnlyToolResultCache.clear();
|
|
5359
5373
|
duplicateReadOnlyToolCalls.clear();
|
|
5360
5374
|
}
|
|
@@ -5784,8 +5798,8 @@ export async function runAgentLoop(opts) {
|
|
|
5784
5798
|
});
|
|
5785
5799
|
recordToolResult(result, true);
|
|
5786
5800
|
requestedActionStop ??= {
|
|
5787
|
-
message: `I stopped
|
|
5788
|
-
`Check
|
|
5801
|
+
message: `I stopped before running ${toolCall.name} again. ${priorInterruptions === 1 ? "An earlier attempt" : `${priorInterruptions} earlier attempts`} may have already saved changes and I could not confirm the result. ` +
|
|
5802
|
+
`Check what was saved, then reply "continue" and I will verify it before doing anything else.`,
|
|
5789
5803
|
errorCode: "write_tool_outcome_unknown",
|
|
5790
5804
|
};
|
|
5791
5805
|
return {
|
|
@@ -5930,6 +5944,10 @@ export async function runAgentLoop(opts) {
|
|
|
5930
5944
|
let result;
|
|
5931
5945
|
let chatUIResult;
|
|
5932
5946
|
let isError = false;
|
|
5947
|
+
// A deadline or abort after invocation leaves a zombie that may still
|
|
5948
|
+
// commit, so a retry-safe action stays blocked for it; an error the
|
|
5949
|
+
// handler returned does not.
|
|
5950
|
+
let toolResultLost = false;
|
|
5933
5951
|
let toolErrorCode;
|
|
5934
5952
|
let mcpApp;
|
|
5935
5953
|
let toolResultImages;
|
|
@@ -6001,7 +6019,7 @@ export async function runAgentLoop(opts) {
|
|
|
6001
6019
|
...(opts.turnId ? { turnId: opts.turnId } : {}),
|
|
6002
6020
|
};
|
|
6003
6021
|
actionInvoked = true;
|
|
6004
|
-
return runActionWithExecutionOutcome(actionEntry.run, toolCall.input, actionContext, actionExecutionOutcome);
|
|
6022
|
+
return runActionWithExecutionOutcome(actionEntry.run, toolCall.input, actionContext, actionExecutionOutcome, actionEntry);
|
|
6005
6023
|
};
|
|
6006
6024
|
const actionPromise = Promise.resolve(runWithRequestContext({
|
|
6007
6025
|
...(requestContext ?? {}),
|
|
@@ -6179,6 +6197,9 @@ export async function runAgentLoop(opts) {
|
|
|
6179
6197
|
}
|
|
6180
6198
|
catch (err) {
|
|
6181
6199
|
actionRefused = actionExecutionOutcome.refused;
|
|
6200
|
+
toolResultLost =
|
|
6201
|
+
signal.aborted ||
|
|
6202
|
+
isToolCallTimeoutResult(String(err?.message ?? err));
|
|
6182
6203
|
toolErrorCode = isActionContractError(err)
|
|
6183
6204
|
? err.errorCode
|
|
6184
6205
|
: undefined;
|
|
@@ -6286,7 +6307,10 @@ export async function runAgentLoop(opts) {
|
|
|
6286
6307
|
...(isError ? { isError: true } : {}),
|
|
6287
6308
|
...(toolErrorCode ? { errorCode: toolErrorCode } : {}),
|
|
6288
6309
|
...(isError
|
|
6289
|
-
? actionInvoked &&
|
|
6310
|
+
? actionInvoked &&
|
|
6311
|
+
!actionIsReadOnly &&
|
|
6312
|
+
!actionRefused &&
|
|
6313
|
+
(!actionRetrySafe || toolResultLost)
|
|
6290
6314
|
? { outcomeUnknown: true }
|
|
6291
6315
|
: { completedSideEffect: false }
|
|
6292
6316
|
: receipt
|
|
@@ -7389,6 +7413,9 @@ export function resolveContinuationDispatchBudget(opts) {
|
|
|
7389
7413
|
maxDispatchAttempts: 3,
|
|
7390
7414
|
dispatchResponseTimeoutMs: 15_000,
|
|
7391
7415
|
backoffCapMs: Infinity,
|
|
7416
|
+
// Durable-background chaining is entered from the foreground function,
|
|
7417
|
+
// which a host kills about 60s in, so it waits no longer than that tier.
|
|
7418
|
+
overloadWaitBudgetMs: 10_000,
|
|
7392
7419
|
};
|
|
7393
7420
|
}
|
|
7394
7421
|
if (opts.workerProvenInBackgroundFunction) {
|
|
@@ -7396,12 +7423,17 @@ export function resolveContinuationDispatchBudget(opts) {
|
|
|
7396
7423
|
maxDispatchAttempts: 5,
|
|
7397
7424
|
dispatchResponseTimeoutMs: 15_000,
|
|
7398
7425
|
backoffCapMs: 4_000,
|
|
7426
|
+
// The chain starts 2 minutes before the 15-minute background budget;
|
|
7427
|
+
// five hung dispatches plus backoff already take about 82s of that.
|
|
7428
|
+
overloadWaitBudgetMs: 30_000,
|
|
7399
7429
|
};
|
|
7400
7430
|
}
|
|
7431
|
+
// A hosted foreground function is killed soon after its soft timeout.
|
|
7401
7432
|
return {
|
|
7402
7433
|
maxDispatchAttempts: 2,
|
|
7403
7434
|
dispatchResponseTimeoutMs: 10_000,
|
|
7404
7435
|
backoffCapMs: Infinity,
|
|
7436
|
+
overloadWaitBudgetMs: 10_000,
|
|
7405
7437
|
};
|
|
7406
7438
|
}
|
|
7407
7439
|
export function isLoopProtectionDispatchError(err) {
|
|
@@ -8539,7 +8571,7 @@ export function createProductionAgentHandler(options) {
|
|
|
8539
8571
|
configuredEffort: options.reasoningEffort,
|
|
8540
8572
|
});
|
|
8541
8573
|
const modelSupportsVision = isAgentModelVisionCapable(effectiveModel, engine.capabilities.vision === true);
|
|
8542
|
-
options.onEngineResolved?.(engine, effectiveModel);
|
|
8574
|
+
options.onEngineResolved?.(engine, effectiveModel, reasoningEffort);
|
|
8543
8575
|
console.log(`[agent-chat] resolved engine=${engine.name} model=${effectiveModel} requestModel=${requestModel ?? "(none)"} requestEngine=${requestEngine ?? "(none)"} modelSource=${modelSelectionSource} engineDefault=${engine.defaultModel} effort=${reasoningEffort ?? "unset"} turnId=${requestTurnId ?? "(none)"}`);
|
|
8544
8576
|
if (!(await isResolvedEngineUsableForRequest(engine, {
|
|
8545
8577
|
apiKey: effectiveApiKey,
|
|
@@ -9792,9 +9824,26 @@ export function createProductionAgentHandler(options) {
|
|
|
9792
9824
|
: "") +
|
|
9793
9825
|
`\n</custom-agent-profile>`;
|
|
9794
9826
|
let responseText = "";
|
|
9795
|
-
|
|
9827
|
+
// A profile is its own model conversation running beside
|
|
9828
|
+
// others, so it gets its own run context: its model and effort
|
|
9829
|
+
// never stand in for another loop's, and it starts with
|
|
9830
|
+
// nothing read, since the run's reads are what the run's
|
|
9831
|
+
// model saw. New per-conversation fields reset here too.
|
|
9832
|
+
const profileRun = {
|
|
9833
|
+
...getRequestRunContext(),
|
|
9834
|
+
model: profile.model ?? model,
|
|
9835
|
+
reasoningEffort,
|
|
9836
|
+
toolSearchReads: undefined,
|
|
9837
|
+
extensionContentReads: undefined,
|
|
9838
|
+
extensionExcerptReads: undefined,
|
|
9839
|
+
};
|
|
9840
|
+
const profileLoopOpts = {
|
|
9796
9841
|
engine,
|
|
9797
9842
|
model: profile.model ?? model,
|
|
9843
|
+
onModelSettings: (loopModel, effort) => {
|
|
9844
|
+
profileRun.model = loopModel;
|
|
9845
|
+
profileRun.reasoningEffort = effort;
|
|
9846
|
+
},
|
|
9798
9847
|
systemPrompt: profilePrompt,
|
|
9799
9848
|
tools: requestTools,
|
|
9800
9849
|
availableTools: availableRequestTools,
|
|
@@ -9848,7 +9897,8 @@ export function createProductionAgentHandler(options) {
|
|
|
9848
9897
|
...(resolvedRunSoftTimeoutMs > 0
|
|
9849
9898
|
? { runSoftTimeoutMs: resolvedRunSoftTimeoutMs }
|
|
9850
9899
|
: {}),
|
|
9851
|
-
}
|
|
9900
|
+
};
|
|
9901
|
+
const subUsage = await runWithRequestContext({ ...getRequestContext(), run: profileRun }, () => runAgentLoop(profileLoopOpts));
|
|
9852
9902
|
await control.flushEvents();
|
|
9853
9903
|
try {
|
|
9854
9904
|
const ownerEmail = options.resolveOwnerEmail
|
|
@@ -9968,6 +10018,9 @@ export function createProductionAgentHandler(options) {
|
|
|
9968
10018
|
const agentLoopOpts = {
|
|
9969
10019
|
engine,
|
|
9970
10020
|
model: effectiveModel,
|
|
10021
|
+
// Custom agent profile loops report into their own run context
|
|
10022
|
+
// copies, so only this loop sets the run's model and effort.
|
|
10023
|
+
onModelSettings: (model, effort) => options.onEngineResolved?.(engine, model, effort),
|
|
9971
10024
|
runId,
|
|
9972
10025
|
followUpSuggestions: true,
|
|
9973
10026
|
systemPrompt: requestSystemPrompt,
|
|
@@ -97,6 +97,7 @@ export declare class AgentTurnInitiatorMismatchError extends Error {
|
|
|
97
97
|
export declare class AgentTurnInitiatorUnavailableError extends Error {
|
|
98
98
|
constructor(threadId: string, turnId: string);
|
|
99
99
|
}
|
|
100
|
+
export declare const agentRunsStore: import("../db/store-registry.js").Store;
|
|
100
101
|
export declare function ensureRunTables(): Promise<void>;
|
|
101
102
|
/**
|
|
102
103
|
* Persist a zombie tool-call completion to the ledger. Called by the detached
|