@agent-native/core 0.220.0-nightly-20261024033422 → 0.220.0
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/handlers.js +7 -6
- package/dist/a2a/types.d.ts +1 -0
- package/dist/agent/engine/tool-call-journal-seed.js +24 -20
- package/dist/agent/execution-fence.d.ts +1 -1
- package/dist/agent/execution-fence.js +8 -1
- package/dist/agent/production-agent.js +31 -6
- package/dist/agent/reaped-run-thread.js +38 -3
- package/dist/agent/run-migrations.js +22 -0
- package/dist/agent/run-store.d.ts +19 -2
- package/dist/agent/run-store.fencing.worker.js +21 -1
- package/dist/agent/run-store.js +359 -35
- package/dist/agent/tool-approval-store.d.ts +13 -0
- package/dist/agent/tool-approval-store.js +64 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/client/background-agent-session.d.ts +4 -0
- package/dist/client/background-agent-session.js +17 -1
- package/dist/client/chat/runtime.js +38 -6
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/schema-snapshot.generated.js +14 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/jobs/automation-recovery.d.ts +4 -0
- package/dist/jobs/automation-recovery.js +7 -0
- package/dist/jobs/background-automation-runner.js +19 -2
- package/dist/jobs/scheduler.js +3 -1
- package/dist/mcp/org-directory.d.ts +8 -7
- package/dist/mcp/org-directory.js +82 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +7 -7
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +2 -2
- package/dist/secrets/routes.d.ts +10 -10
- package/dist/server/agent-chat-plugin.d.ts +10 -1
- package/dist/server/agent-chat-plugin.js +178 -11
- package/dist/server/agent-discovery.js +11 -49
- 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/usage/store.js +36 -33
- package/package.json +4 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Message as A2AMessage } from "../a2a/types.js";
|
|
2
|
-
import { type ActionEntry, type AgentActionSurfaceDetails, type AgentActionSurfaceResolution } from "../agent/production-agent.js";
|
|
2
|
+
import { type ActionEntry, type AgentActionSurfaceDetails, type AgentActionSurfaceResolution, type AgentLoopUsage } from "../agent/production-agent.js";
|
|
3
3
|
import { type ActiveRun } from "../agent/run-manager.js";
|
|
4
4
|
import { foldAgentChatRunCompletion } from "../agent/thread-data-builder.js";
|
|
5
5
|
import type { AgentChatEvent, AgentChatScope } from "../agent/types.js";
|
|
@@ -79,6 +79,15 @@ export declare function createSerializedA2ATaskStatusWriter(taskId: string, writ
|
|
|
79
79
|
flush: () => Promise<void>;
|
|
80
80
|
};
|
|
81
81
|
export declare function runA2AAgentLoopWithRunManager(runOptions: Parameters<typeof runA2AAgentLoop>[0], pluginOptions: Pick<AgentChatPluginOptions, "delegatedRunPolicy" | "finalResponseGuard" | "runSoftTimeoutMs">, timeoutOptions: Parameters<typeof runA2AAgentLoop>[2], delegatedOptions?: Parameters<typeof runA2AAgentLoop>[3], taskSignal?: AbortSignal): Promise<Awaited<ReturnType<typeof runA2AAgentLoop>>>;
|
|
82
|
+
export declare function runA2AWithUsageLedger<T>(run: Promise<T>, input: {
|
|
83
|
+
usage: AgentLoopUsage;
|
|
84
|
+
ownerEmail: string;
|
|
85
|
+
orgId: string | null;
|
|
86
|
+
appId?: string;
|
|
87
|
+
taskId: string;
|
|
88
|
+
processingAttemptId?: string;
|
|
89
|
+
persistUsage?: (record: import("../usage/store.js").UsageRecord) => Promise<void>;
|
|
90
|
+
}): Promise<T>;
|
|
82
91
|
export declare function resolveA2ARecoverableArtifactSecret(orgId?: string | null | undefined): Promise<string | undefined>;
|
|
83
92
|
export declare function buildLeanRunPolicyPrompt(codeEditingSurfaceRestriction: string, prodCodeExecPromptNote: string): string;
|
|
84
93
|
export declare function filterPromptActionsToSurface(actions: Record<string, ActionEntry>, allowedActionNames?: readonly string[]): Record<string, ActionEntry>;
|
|
@@ -20,15 +20,16 @@ import { SYSTEM_PROMPT_CACHE_SPLIT } from "../agent/engine/prompt-cache.js";
|
|
|
20
20
|
import { PROVIDER_TO_ENV } from "../agent/engine/provider-env-vars.js";
|
|
21
21
|
import { currentExecutionFence, withExecutionFence, } from "../agent/execution-fence.js";
|
|
22
22
|
import { hostedHarnessSystemPrompt } from "../agent/harness/hosted.js";
|
|
23
|
-
import { createProductionAgentHandler, endsAtContinuationBoundary, actionsToEngineTools, executeAgentToolCall, filterActionsByAllowedNames, normalizeAgentActionSurfaceResolution, getActiveRunForThreadAsync, getJevContextCredentials, abortRunDurably, abortRunAndTurnDurably, abortRunAtSafeBoundaryDurably, abortTurnByRefDurably, abortTurnDurably, subscribeToRun, } from "../agent/production-agent.js";
|
|
23
|
+
import { createProductionAgentHandler, endsAtContinuationBoundary, actionsToEngineTools, executeAgentToolCall, filterActionsByAllowedNames, normalizeAgentActionSurfaceResolution, getActiveRunForThreadAsync, getJevContextCredentials, abortRunDurably, abortRunAndTurnDurably, abortRunAtSafeBoundaryDurably, abortTurnByRefDurably, abortTurnDurably, subscribeToRun, mergeAgentLoopUsage, } from "../agent/production-agent.js";
|
|
24
24
|
import { applyProviderModelSelection, providerForEngineName, resolveProviderModelSelectionAtScope, } from "../agent/provider-model-selection.js";
|
|
25
25
|
import { startRun } from "../agent/run-manager.js";
|
|
26
26
|
import { callerHasRunAccess, callerHasThreadAccess, } from "../agent/run-ownership.js";
|
|
27
|
-
import { getRunById, readBackgroundRunClaim } from "../agent/run-store.js";
|
|
27
|
+
import { AgentRunJournalUnreadableError, getRunById, readBackgroundRunClaim, retryRunThreadProjection, } from "../agent/run-store.js";
|
|
28
28
|
import { buildAssistantMessageFromRunJournal } from "../agent/run-thread-projector.js";
|
|
29
29
|
import { buildCurrentTimeUserContext, buildRuntimeContextPrompt, } from "../agent/runtime-context.js";
|
|
30
30
|
import { buildAssistantMessage, buildUserMessage, applySubmittedUserMessage, containsInlineAttachmentPayload, foldAgentChatRunCompletion, extractThreadMeta, foldUnstartedTurnFailure, mergeThreadDataForClientSave, } from "../agent/thread-data-builder.js";
|
|
31
31
|
import { appendThreadDebugHistory } from "../agent/thread-debug-history.js";
|
|
32
|
+
import { denyAgentToolApproval } from "../agent/tool-approval-store.js";
|
|
32
33
|
import { attachToolSearch } from "../agent/tool-search.js";
|
|
33
34
|
import { getAppConfig } from "../app-config/index.js";
|
|
34
35
|
import { readAppStateForCurrentTab } from "../application-state/script-helpers.js";
|
|
@@ -518,6 +519,56 @@ export async function runA2AAgentLoopWithRunManager(runOptions, pluginOptions, t
|
|
|
518
519
|
}
|
|
519
520
|
return result;
|
|
520
521
|
}
|
|
522
|
+
export async function runA2AWithUsageLedger(run, input) {
|
|
523
|
+
const outcome = await run.then((value) => ({ ok: true, value }), (error) => ({ ok: false, error }));
|
|
524
|
+
let usageError;
|
|
525
|
+
let usageFailed = false;
|
|
526
|
+
if (input.usage.usageReported) {
|
|
527
|
+
try {
|
|
528
|
+
const record = {
|
|
529
|
+
ownerEmail: input.ownerEmail,
|
|
530
|
+
inputTokens: input.usage.inputTokens,
|
|
531
|
+
outputTokens: input.usage.outputTokens,
|
|
532
|
+
cacheReadTokens: input.usage.cacheReadTokens,
|
|
533
|
+
cacheWriteTokens: input.usage.cacheWriteTokens,
|
|
534
|
+
builderCreditsUsed: input.usage.builderCreditsUsed,
|
|
535
|
+
engineName: input.usage.engineName,
|
|
536
|
+
model: input.usage.model,
|
|
537
|
+
app: input.appId,
|
|
538
|
+
orgId: input.orgId ?? undefined,
|
|
539
|
+
label: "a2a",
|
|
540
|
+
// A replay in the same lease replaces its receipt; later leases
|
|
541
|
+
// retain their own usage segments under a different ref.
|
|
542
|
+
refId: input.processingAttemptId
|
|
543
|
+
? `${input.taskId}:${input.processingAttemptId}`
|
|
544
|
+
: input.taskId,
|
|
545
|
+
runId: input.taskId,
|
|
546
|
+
threadId: input.taskId,
|
|
547
|
+
taskId: input.taskId,
|
|
548
|
+
};
|
|
549
|
+
if (input.persistUsage) {
|
|
550
|
+
await input.persistUsage(record);
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
const { recordUsage } = await import("../usage/store.js");
|
|
554
|
+
await recordUsage(record);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
catch (error) {
|
|
558
|
+
usageFailed = true;
|
|
559
|
+
usageError = error;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (!outcome.ok) {
|
|
563
|
+
if (usageFailed) {
|
|
564
|
+
throw new AggregateError([outcome.error, usageError], "A2A run and usage persistence both failed.");
|
|
565
|
+
}
|
|
566
|
+
throw outcome.error;
|
|
567
|
+
}
|
|
568
|
+
if (usageFailed)
|
|
569
|
+
throw usageError;
|
|
570
|
+
return outcome.value;
|
|
571
|
+
}
|
|
521
572
|
const A2A_ACTIVITY_CHECKPOINT_MIN_INTERVAL_MS = 2_000;
|
|
522
573
|
export async function resolveA2ARecoverableArtifactSecret(orgId = getRequestOrgId()) {
|
|
523
574
|
const globalSecret = process.env.A2A_SECRET?.trim();
|
|
@@ -827,12 +878,12 @@ export function createAgentChatPlugin(options) {
|
|
|
827
878
|
const initPromise = (async () => {
|
|
828
879
|
const { awaitBootstrap } = await import("./framework-request-handler.js");
|
|
829
880
|
await awaitBootstrap(nitroApp);
|
|
830
|
-
const
|
|
881
|
+
const runtimeAppId = options?.appId ??
|
|
831
882
|
getAppConfig().app.id ??
|
|
832
883
|
getAppConfig().app.template ??
|
|
833
884
|
getAppConfig().app.workspaceId ??
|
|
834
|
-
getAppConfig().app.packageName
|
|
835
|
-
|
|
885
|
+
getAppConfig().app.packageName;
|
|
886
|
+
const appProfileAppId = runtimeAppId ?? "app";
|
|
836
887
|
// Never make route readiness wait on an org-global stale-run sweep.
|
|
837
888
|
// `/runs/active` reaps the requested run on demand, and the periodic
|
|
838
889
|
// recovery sweep below handles abandoned runs with no connected client.
|
|
@@ -2170,6 +2221,14 @@ export function createAgentChatPlugin(options) {
|
|
|
2170
2221
|
const a2aEvents = [];
|
|
2171
2222
|
const a2aToolResults = [];
|
|
2172
2223
|
let a2aOutcome;
|
|
2224
|
+
const a2aUsage = {
|
|
2225
|
+
inputTokens: 0,
|
|
2226
|
+
outputTokens: 0,
|
|
2227
|
+
cacheReadTokens: 0,
|
|
2228
|
+
cacheWriteTokens: 0,
|
|
2229
|
+
engineName: a2aEngine.name,
|
|
2230
|
+
model,
|
|
2231
|
+
};
|
|
2173
2232
|
let lastRecoverableArtifactText = "";
|
|
2174
2233
|
let activityState = createA2AAgentActivityState();
|
|
2175
2234
|
let lastActivityCheckpointAt = 0;
|
|
@@ -2208,7 +2267,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2208
2267
|
correlation.callerThreadId ??
|
|
2209
2268
|
context.taskId;
|
|
2210
2269
|
console.log(`[A2A] Starting agent loop: ${a2aToolSurface.tools.length}/${a2aToolSurface.availableTools.length} initial tools, prompt ${systemPrompt.length} chars`);
|
|
2211
|
-
|
|
2270
|
+
const a2aRun = runA2AAgentLoopWithRunManager({
|
|
2212
2271
|
engine: a2aEngine,
|
|
2213
2272
|
model,
|
|
2214
2273
|
systemPrompt,
|
|
@@ -2224,7 +2283,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2224
2283
|
orgId: getRequestOrgId() ?? null,
|
|
2225
2284
|
// Without it, every action with an `access` policy is refused
|
|
2226
2285
|
// for lack of an application identity.
|
|
2227
|
-
appId:
|
|
2286
|
+
appId: runtimeAppId,
|
|
2228
2287
|
executionMode: "act",
|
|
2229
2288
|
runId: context.taskId,
|
|
2230
2289
|
networkProtocol: "a2a",
|
|
@@ -2238,6 +2297,12 @@ export function createAgentChatPlugin(options) {
|
|
|
2238
2297
|
onOutcome: (outcome) => {
|
|
2239
2298
|
a2aOutcome = outcome;
|
|
2240
2299
|
},
|
|
2300
|
+
onUsage: (usage) => {
|
|
2301
|
+
mergeAgentLoopUsage(a2aUsage, {
|
|
2302
|
+
...usage,
|
|
2303
|
+
usageReported: true,
|
|
2304
|
+
});
|
|
2305
|
+
},
|
|
2241
2306
|
send: (event) => {
|
|
2242
2307
|
a2aEvents.push(event);
|
|
2243
2308
|
const nextActivityState = applyA2AAgentActivityEvent(activityState, event);
|
|
@@ -2317,6 +2382,14 @@ export function createAgentChatPlugin(options) {
|
|
|
2317
2382
|
},
|
|
2318
2383
|
},
|
|
2319
2384
|
}, context.signal);
|
|
2385
|
+
await runA2AWithUsageLedger(a2aRun, {
|
|
2386
|
+
usage: a2aUsage,
|
|
2387
|
+
ownerEmail: userEmail,
|
|
2388
|
+
orgId: getRequestOrgId() ?? null,
|
|
2389
|
+
appId: runtimeAppId,
|
|
2390
|
+
taskId: context.taskId,
|
|
2391
|
+
processingAttemptId: context.processingAttemptId,
|
|
2392
|
+
});
|
|
2320
2393
|
// The continuation can observe terminal output immediately, so make
|
|
2321
2394
|
// its latest mutation checkpoint durable first.
|
|
2322
2395
|
checkpointActivity(true);
|
|
@@ -5260,6 +5333,41 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5260
5333
|
const canViewRun = (runId) => callerHasRunAccess(owner, runId, "viewer", { orgId });
|
|
5261
5334
|
const canEditRun = (runId) => callerHasRunAccess(owner, runId, "editor", { orgId });
|
|
5262
5335
|
const canEditThread = (threadId) => callerHasThreadAccess(owner, threadId, "editor", { orgId });
|
|
5336
|
+
// Route: POST /runs/:id/retry-projection
|
|
5337
|
+
// An editor may retry a pending fold after repairing its source.
|
|
5338
|
+
const retryProjectionMatch = url.match(/\/runs\/([^/?]+)\/retry-projection(?:[/?]|$)/) ||
|
|
5339
|
+
url.match(/^\/([^/?]+)\/retry-projection(?:[/?]|$)/);
|
|
5340
|
+
if (retryProjectionMatch && method === "POST") {
|
|
5341
|
+
const runId = decodeURIComponent(retryProjectionMatch[1]);
|
|
5342
|
+
if (!(await canEditRun(runId))) {
|
|
5343
|
+
setResponseStatus(event, 404);
|
|
5344
|
+
return { error: "Run not found" };
|
|
5345
|
+
}
|
|
5346
|
+
const run = await getRunById(runId);
|
|
5347
|
+
if (!run) {
|
|
5348
|
+
setResponseStatus(event, 404);
|
|
5349
|
+
return { error: "Run not found" };
|
|
5350
|
+
}
|
|
5351
|
+
try {
|
|
5352
|
+
const result = await retryRunThreadProjection(runId);
|
|
5353
|
+
if (result.state === "untracked") {
|
|
5354
|
+
setResponseStatus(event, 404);
|
|
5355
|
+
return { error: "Run not found" };
|
|
5356
|
+
}
|
|
5357
|
+
return { ok: true, ...result };
|
|
5358
|
+
}
|
|
5359
|
+
catch (error) {
|
|
5360
|
+
if (error instanceof AgentRunJournalUnreadableError) {
|
|
5361
|
+
setResponseStatus(event, 422);
|
|
5362
|
+
return {
|
|
5363
|
+
ok: false,
|
|
5364
|
+
error: "Projection source remains unreadable",
|
|
5365
|
+
threadProjectionErrorCode: error.errorCode,
|
|
5366
|
+
};
|
|
5367
|
+
}
|
|
5368
|
+
throw error;
|
|
5369
|
+
}
|
|
5370
|
+
}
|
|
5263
5371
|
// Route: POST /runs/turn/:turnId/abort
|
|
5264
5372
|
// Covers the short window where the client has sent a turn but the
|
|
5265
5373
|
// server has not yet created its background run id.
|
|
@@ -5898,7 +6006,7 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5898
6006
|
const runs = await runWithRequestContext({ userEmail: owner, orgId }, () => listRunsForThread(thread.id, { runIds }));
|
|
5899
6007
|
return {
|
|
5900
6008
|
queriedRunIds: runIds,
|
|
5901
|
-
runs: runs.map(({ id, status, startedAt, completedAt, errorCode, abortReason, terminalReason, }) => ({
|
|
6009
|
+
runs: runs.map(({ id, status, startedAt, completedAt, errorCode, abortReason, terminalReason, threadProjectionErrorCode, }) => ({
|
|
5902
6010
|
id,
|
|
5903
6011
|
status,
|
|
5904
6012
|
startedAt,
|
|
@@ -5906,11 +6014,64 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
5906
6014
|
errorCode,
|
|
5907
6015
|
abortReason,
|
|
5908
6016
|
terminalReason,
|
|
6017
|
+
threadProjectionErrorCode,
|
|
5909
6018
|
})),
|
|
5910
6019
|
};
|
|
5911
6020
|
};
|
|
5912
6021
|
// ── Specific thread: GET/PUT/DELETE /threads/:id ──
|
|
5913
6022
|
if (threadId) {
|
|
6023
|
+
if (method === "POST" &&
|
|
6024
|
+
isThreadSubroute("approval-resolution") &&
|
|
6025
|
+
threadTail.length === 1) {
|
|
6026
|
+
const thread = await resolveThreadAccess(owner, threadId, "editor", { orgId });
|
|
6027
|
+
if (!thread || !threadMatchesRequestedScope(thread)) {
|
|
6028
|
+
return threadNotFound();
|
|
6029
|
+
}
|
|
6030
|
+
const body = await readBody(event);
|
|
6031
|
+
const record = body &&
|
|
6032
|
+
typeof body === "object" &&
|
|
6033
|
+
!Array.isArray(body) &&
|
|
6034
|
+
body;
|
|
6035
|
+
const approvalId = typeof record?.approvalId === "string"
|
|
6036
|
+
? record.approvalId.trim()
|
|
6037
|
+
: "";
|
|
6038
|
+
if (!approvalId || record?.decision !== "deny") {
|
|
6039
|
+
setResponseStatus(event, 400);
|
|
6040
|
+
return { error: "Invalid approval resolution" };
|
|
6041
|
+
}
|
|
6042
|
+
const resolved = await denyAgentToolApproval({
|
|
6043
|
+
approvalId,
|
|
6044
|
+
ownerEmail: owner,
|
|
6045
|
+
orgId,
|
|
6046
|
+
threadId,
|
|
6047
|
+
});
|
|
6048
|
+
if (resolved === "not_applied") {
|
|
6049
|
+
setResponseStatus(event, 409);
|
|
6050
|
+
return {
|
|
6051
|
+
error: "Approval denial could not be applied",
|
|
6052
|
+
code: "approval_denial_not_applied",
|
|
6053
|
+
retryable: false,
|
|
6054
|
+
};
|
|
6055
|
+
}
|
|
6056
|
+
if (resolved === "already_resolved") {
|
|
6057
|
+
setResponseStatus(event, 409);
|
|
6058
|
+
return {
|
|
6059
|
+
error: "Approval is no longer pending",
|
|
6060
|
+
code: "approval_not_pending",
|
|
6061
|
+
retryable: false,
|
|
6062
|
+
};
|
|
6063
|
+
}
|
|
6064
|
+
scheduleQueuedSubmissionInboxDrain({
|
|
6065
|
+
threadId,
|
|
6066
|
+
turnContinues: false,
|
|
6067
|
+
waitUntil: getRequestRunContext()?.waitUntil,
|
|
6068
|
+
drain: drainQueuedSubmissionInbox,
|
|
6069
|
+
onError: (error) => {
|
|
6070
|
+
console.error(`[agent-chat] denied-approval inbox drain failed for ${threadId}:`, error);
|
|
6071
|
+
},
|
|
6072
|
+
});
|
|
6073
|
+
return { ok: true };
|
|
6074
|
+
}
|
|
5914
6075
|
if (method === "GET" &&
|
|
5915
6076
|
threadTail[0] === "queue" &&
|
|
5916
6077
|
threadTail[1] &&
|
|
@@ -7610,6 +7771,9 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
7610
7771
|
console.error("[agent-chat] durable stale-run reap failed:", error);
|
|
7611
7772
|
return null;
|
|
7612
7773
|
});
|
|
7774
|
+
const staleRunReapIncomplete = staleRunsReaped === null ||
|
|
7775
|
+
staleRunsReaped.failed > 0 ||
|
|
7776
|
+
staleRunsReaped.truncated;
|
|
7613
7777
|
const staleAgentTeamRuns = await reconcileStaleAgentTeamRuns(event).catch((error) => {
|
|
7614
7778
|
console.error("[agent-chat] durable Agent Teams reconciliation failed:", error);
|
|
7615
7779
|
return null;
|
|
@@ -7660,7 +7824,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
7660
7824
|
};
|
|
7661
7825
|
}
|
|
7662
7826
|
if (!triggerAvailability.available) {
|
|
7663
|
-
if (
|
|
7827
|
+
if (staleRunReapIncomplete ||
|
|
7828
|
+
appSweepHandlers.failed.length > 0 ||
|
|
7664
7829
|
automationFailureAlerts === null ||
|
|
7665
7830
|
queuedSubmissionDrain === null ||
|
|
7666
7831
|
queuedSubmissionDrain.failed > 0 ||
|
|
@@ -7669,7 +7834,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
7669
7834
|
setResponseStatus(event, 500);
|
|
7670
7835
|
}
|
|
7671
7836
|
return {
|
|
7672
|
-
ok:
|
|
7837
|
+
ok: !staleRunReapIncomplete &&
|
|
7838
|
+
appSweepHandlers.failed.length === 0 &&
|
|
7673
7839
|
automationFailureAlerts !== null &&
|
|
7674
7840
|
queuedSubmissionDrain !== null &&
|
|
7675
7841
|
queuedSubmissionDrain.failed === 0 &&
|
|
@@ -7688,7 +7854,8 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
7688
7854
|
}
|
|
7689
7855
|
try {
|
|
7690
7856
|
await processRecurringJobs(schedulerDeps);
|
|
7691
|
-
if (
|
|
7857
|
+
if (staleRunReapIncomplete ||
|
|
7858
|
+
appSweepHandlers.failed.length > 0 ||
|
|
7692
7859
|
automationFailureAlerts === null ||
|
|
7693
7860
|
queuedSubmissionDrain === null ||
|
|
7694
7861
|
queuedSubmissionDrain.failed > 0 ||
|
|
@@ -577,59 +577,21 @@ function mergeDiscoveredAgent(agentsById, candidate) {
|
|
|
577
577
|
async function discoverOrgDirectoryApps(selfAppId) {
|
|
578
578
|
const selfId = selfAppId ? normalizeAgentId(selfAppId) : undefined;
|
|
579
579
|
try {
|
|
580
|
-
const { fetchOrgAppsResult
|
|
581
|
-
const
|
|
582
|
-
let result = await fetchOrgAppsResult({ selfId });
|
|
583
|
-
let baseUrl = configuredBaseUrl;
|
|
584
|
-
if (result.status === "unavailable" && result.reason === "not-configured") {
|
|
585
|
-
const orgId = getRequestOrgId();
|
|
586
|
-
if (!orgId) {
|
|
587
|
-
return {
|
|
588
|
-
status: "setup-required",
|
|
589
|
-
reason: "organization-not-selected",
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
const { getOrgWorkspaceUrl } = await import("../org/context.js");
|
|
593
|
-
const workspaceUrl = await getOrgWorkspaceUrl(orgId);
|
|
594
|
-
if (!workspaceUrl) {
|
|
595
|
-
return { status: "setup-required", reason: "workspace-url-not-set" };
|
|
596
|
-
}
|
|
597
|
-
let workspaceOrigin;
|
|
598
|
-
try {
|
|
599
|
-
const parsed = new URL(workspaceUrl);
|
|
600
|
-
if ((parsed.protocol !== "http:" && parsed.protocol !== "https:") ||
|
|
601
|
-
parsed.username ||
|
|
602
|
-
parsed.password ||
|
|
603
|
-
parsed.search ||
|
|
604
|
-
parsed.hash ||
|
|
605
|
-
(parsed.pathname !== "/" && parsed.pathname !== "")) {
|
|
606
|
-
return { status: "setup-required", reason: "invalid-workspace-url" };
|
|
607
|
-
}
|
|
608
|
-
workspaceOrigin = parsed.origin;
|
|
609
|
-
}
|
|
610
|
-
catch {
|
|
611
|
-
return { status: "setup-required", reason: "invalid-workspace-url" };
|
|
612
|
-
}
|
|
613
|
-
baseUrl = `${workspaceOrigin}/dispatch`;
|
|
614
|
-
result = await fetchOrgAppsResult({ directoryBaseUrl: baseUrl, selfId });
|
|
615
|
-
}
|
|
616
|
-
if (result.status === "unavailable" &&
|
|
617
|
-
result.reason === "missing-route" &&
|
|
618
|
-
baseUrl) {
|
|
619
|
-
const rootUrl = new URL(baseUrl).origin;
|
|
620
|
-
if (rootUrl !== baseUrl.replace(/\/+$/, "")) {
|
|
621
|
-
result = await fetchOrgAppsResult({
|
|
622
|
-
directoryBaseUrl: rootUrl,
|
|
623
|
-
selfId,
|
|
624
|
-
});
|
|
625
|
-
}
|
|
626
|
-
}
|
|
580
|
+
const { fetchOrgAppsResult } = await import("../mcp/org-directory.js");
|
|
581
|
+
const result = await fetchOrgAppsResult({ selfId });
|
|
627
582
|
if (result.status === "available")
|
|
628
583
|
return result;
|
|
629
584
|
if (result.reason === "authorization")
|
|
630
585
|
return { status: "forbidden" };
|
|
631
|
-
if (result.reason === "not-configured"
|
|
632
|
-
|
|
586
|
+
if (result.reason === "not-configured") {
|
|
587
|
+
return {
|
|
588
|
+
status: "setup-required",
|
|
589
|
+
reason: getRequestOrgId()
|
|
590
|
+
? "workspace-url-not-set"
|
|
591
|
+
: "organization-not-selected",
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
if (result.reason === "invalid-origin") {
|
|
633
595
|
return { status: "setup-required", reason: result.reason };
|
|
634
596
|
}
|
|
635
597
|
return { status: "unavailable", reason: result.reason };
|
|
@@ -8,8 +8,8 @@ export declare const AGENT_ENGINE_API_KEY_ACTION_NAME = "agent-engine-api-key";
|
|
|
8
8
|
* resolveEngine's credential detection.
|
|
9
9
|
*/
|
|
10
10
|
export declare function createAgentEngineDisconnectHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
11
|
-
ok?: undefined;
|
|
12
11
|
error: string;
|
|
12
|
+
ok?: undefined;
|
|
13
13
|
scope?: undefined;
|
|
14
14
|
} | {
|
|
15
15
|
ok: boolean;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare function createAgentEngineOllamaModelsHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
2
|
+
ok?: undefined;
|
|
2
3
|
error: string;
|
|
3
4
|
models?: undefined;
|
|
4
|
-
ok?: undefined;
|
|
5
5
|
} | {
|
|
6
|
+
error?: undefined;
|
|
6
7
|
ok: boolean;
|
|
7
8
|
models: string[];
|
|
8
|
-
error?: undefined;
|
|
9
9
|
}>>;
|
package/dist/usage/store.js
CHANGED
|
@@ -252,48 +252,51 @@ export async function recordUsage(recordOrOwner, inputTokens, outputTokens, mode
|
|
|
252
252
|
const resolvedLabel = label ?? "chat";
|
|
253
253
|
const resolvedRef = refId ?? "";
|
|
254
254
|
const resolvedOrgId = orgId ?? getRequestOrgId() ?? null;
|
|
255
|
-
if (resolvedRef) {
|
|
256
|
-
await client.execute({
|
|
257
|
-
sql: `DELETE FROM token_usage
|
|
258
|
-
WHERE label = ? AND ref_id = ?
|
|
259
|
-
AND (org_id IS NULL OR org_id = ?)`,
|
|
260
|
-
args: [resolvedLabel, resolvedRef, resolvedOrgId],
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
255
|
const resolvedCostSource = costSource ?? (costCentsX100 == null ? "estimated" : "reported");
|
|
264
256
|
const costX100 = resolvedCostSource === "unavailable"
|
|
265
257
|
? 0
|
|
266
258
|
: (costCentsX100 ??
|
|
267
259
|
calculateCost(inTok, outTok, modelName, cacheReadTokens, cacheWriteTokens));
|
|
268
260
|
const id = Date.now() * 1000 + Math.floor(Math.random() * 1000);
|
|
261
|
+
const insertArgs = [
|
|
262
|
+
id,
|
|
263
|
+
ownerEmail,
|
|
264
|
+
inTok,
|
|
265
|
+
outTok,
|
|
266
|
+
cacheReadTokens,
|
|
267
|
+
cacheWriteTokens,
|
|
268
|
+
costX100,
|
|
269
|
+
builderCreditsUsed ?? null,
|
|
270
|
+
engineName ?? null,
|
|
271
|
+
resolvedCostSource,
|
|
272
|
+
modelName,
|
|
273
|
+
resolvedLabel,
|
|
274
|
+
resolvedApp,
|
|
275
|
+
resolvedRef,
|
|
276
|
+
resolvedOrgId,
|
|
277
|
+
runId ?? null,
|
|
278
|
+
threadId ?? null,
|
|
279
|
+
taskId ?? null,
|
|
280
|
+
integrationScopeId ?? null,
|
|
281
|
+
sourcePlatform ?? null,
|
|
282
|
+
sourceId ?? null,
|
|
283
|
+
Date.now(),
|
|
284
|
+
];
|
|
285
|
+
const replaceRefSql = resolvedRef
|
|
286
|
+
? `WITH prior_usage AS (
|
|
287
|
+
DELETE FROM token_usage
|
|
288
|
+
WHERE label = ? AND ref_id = ?
|
|
289
|
+
AND (org_id IS NULL OR org_id = ?)
|
|
290
|
+
RETURNING id
|
|
291
|
+
) `
|
|
292
|
+
: "";
|
|
269
293
|
await client.execute({
|
|
270
|
-
sql:
|
|
294
|
+
sql: `${replaceRefSql}INSERT INTO token_usage
|
|
271
295
|
(id, owner_email, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, builder_credits_used, engine_name, cost_source, model, label, app, ref_id, org_id, run_id, thread_id, task_id, integration_scope_id, source_platform, source_id, created_at)
|
|
272
296
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
273
|
-
args:
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
inTok,
|
|
277
|
-
outTok,
|
|
278
|
-
cacheReadTokens,
|
|
279
|
-
cacheWriteTokens,
|
|
280
|
-
costX100,
|
|
281
|
-
builderCreditsUsed ?? null,
|
|
282
|
-
engineName ?? null,
|
|
283
|
-
resolvedCostSource,
|
|
284
|
-
modelName,
|
|
285
|
-
resolvedLabel,
|
|
286
|
-
resolvedApp,
|
|
287
|
-
resolvedRef,
|
|
288
|
-
resolvedOrgId,
|
|
289
|
-
runId ?? null,
|
|
290
|
-
threadId ?? null,
|
|
291
|
-
taskId ?? null,
|
|
292
|
-
integrationScopeId ?? null,
|
|
293
|
-
sourcePlatform ?? null,
|
|
294
|
-
sourceId ?? null,
|
|
295
|
-
Date.now(),
|
|
296
|
-
],
|
|
297
|
+
args: resolvedRef
|
|
298
|
+
? [resolvedLabel, resolvedRef, resolvedOrgId, ...insertArgs]
|
|
299
|
+
: insertArgs,
|
|
297
300
|
});
|
|
298
301
|
void import("./alerts-store.js")
|
|
299
302
|
.then(({ enqueueUsageAlertEvaluation }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.220.0
|
|
3
|
+
"version": "0.220.0",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -730,8 +730,8 @@
|
|
|
730
730
|
"yaml": "^2.9.0",
|
|
731
731
|
"yjs": "^13.6.33",
|
|
732
732
|
"zod": "^4.3.6",
|
|
733
|
-
"@agent-native/agentkit": "^0.220.0
|
|
734
|
-
"@agent-native/recap-cli": "^0.5.
|
|
733
|
+
"@agent-native/agentkit": "^0.220.0",
|
|
734
|
+
"@agent-native/recap-cli": "^0.5.89"
|
|
735
735
|
},
|
|
736
736
|
"devDependencies": {
|
|
737
737
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
@@ -801,7 +801,7 @@
|
|
|
801
801
|
"xlsx": "^0.18.5"
|
|
802
802
|
},
|
|
803
803
|
"peerDependencies": {
|
|
804
|
-
"@agent-native/core-corpus": "0.
|
|
804
|
+
"@agent-native/core-corpus": ">=0.196.0",
|
|
805
805
|
"@ai-sdk/anthropic": ">=3",
|
|
806
806
|
"@ai-sdk/cohere": ">=3",
|
|
807
807
|
"@ai-sdk/google": ">=3",
|