@agent-native/core 0.221.0-same-host-mcp-20261027-20261027081850 → 0.221.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/server.js +4 -4
- package/dist/a2a/task-lifecycle.d.ts +12 -12
- package/dist/a2a/task-lifecycle.js +10 -12
- package/dist/a2a/task-store.js +81 -228
- package/dist/action-caller.d.ts +3 -0
- package/dist/action-caller.js +8 -0
- package/dist/action.d.ts +1 -0
- package/dist/agent/engine/ai-sdk-engine.js +3 -3
- package/dist/agent/engine/anthropic-engine.js +3 -3
- package/dist/agent/engine/credential-owner.d.ts +3 -0
- package/dist/agent/engine/credential-owner.js +9 -0
- package/dist/agent/engine/registry.js +28 -2
- package/dist/agent/harness/acp-adapter.d.ts +1 -0
- package/dist/agent/harness/acp-adapter.js +36 -5
- package/dist/agent/harness/background.d.ts +5 -1
- package/dist/agent/harness/background.js +4 -3
- package/dist/agent/harness/lifecycle.d.ts +2 -0
- package/dist/agent/harness/lifecycle.js +452 -84
- package/dist/agent/harness/run-policy.d.ts +5 -0
- package/dist/agent/harness/run-policy.js +70 -0
- package/dist/agent/harness/runner.js +89 -73
- package/dist/agent/harness/store.d.ts +10 -1
- package/dist/agent/harness/store.js +91 -12
- package/dist/agent/harness/turn-driver.d.ts +12 -0
- package/dist/agent/harness/turn-driver.js +42 -0
- package/dist/agent/harness/types.d.ts +11 -0
- package/dist/agent/production-agent.d.ts +9 -0
- package/dist/agent/production-agent.js +153 -41
- package/dist/agent/run-manager.d.ts +4 -0
- package/dist/agent/run-manager.js +23 -7
- package/dist/agent/run-store.d.ts +3 -1
- package/dist/agent/run-store.fencing.native-harness.fixture.test.support.js +34 -0
- package/dist/agent/run-store.fencing.worker.test.support.d.ts +1 -0
- package/dist/agent/{run-store.fencing.worker.js → run-store.fencing.worker.test.support.js} +337 -4
- package/dist/agent/run-store.js +89 -17
- package/dist/app-config/clips.d.ts +10 -0
- package/dist/app-config/clips.js +24 -0
- package/dist/app-config/index.d.ts +1 -1
- package/dist/app-config/index.js +1 -1
- package/dist/app-config/schema.d.ts +1 -0
- package/dist/appearance/actions/set-theme-family.js +16 -2
- package/dist/appearance/theme-family.d.ts +11 -1
- package/dist/appearance/theme-family.js +21 -2
- package/dist/automations/outside-origin.d.ts +13 -0
- package/dist/automations/outside-origin.js +23 -0
- package/dist/automations/service.d.ts +4 -2
- package/dist/automations/service.js +11 -8
- package/dist/cli/code-agent-executor.js +5 -16
- package/dist/cli/create.d.ts +11 -2
- package/dist/cli/create.js +121 -32
- package/dist/cli/skills-content/turn-into-app-skill.d.ts +4 -3
- package/dist/cli/skills-content/turn-into-app-skill.js +143 -36
- package/dist/cli/skills.d.ts +3 -0
- package/dist/cli/skills.js +4 -1
- package/dist/cli/template-sync.js +4 -4
- package/dist/cli/upgrade.d.ts +1 -0
- package/dist/cli/upgrade.js +207 -2
- package/dist/client/chat/agentkit-agent-native.js +23 -3
- package/dist/client/mcp-approval.d.ts +53 -0
- package/dist/client/mcp-approval.js +81 -0
- package/dist/client/onboarding/use-onboarding.js +6 -4
- package/dist/client/resources/mcp-integration-catalog.js +19 -0
- package/dist/client/theme-family.d.ts +2 -1
- package/dist/client/theme-family.js +271 -32
- package/dist/client/theme.js +3 -2
- package/dist/code-agents/background-controller.js +1 -13
- package/dist/code-agents/prompt-attachments.d.ts +11 -0
- package/dist/code-agents/prompt-attachments.js +103 -6
- package/dist/collab/awareness-store.d.ts +8 -0
- package/dist/collab/awareness-store.js +9 -1
- package/dist/collab/index.d.ts +1 -1
- package/dist/collab/index.js +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/config.d.ts +13 -3
- package/dist/config.js +64 -1
- package/dist/db/client.d.ts +8 -6
- package/dist/db/client.js +56 -17
- package/dist/db/create-get-db.js +6 -1
- package/dist/db/index.d.ts +2 -1
- package/dist/db/index.js +1 -0
- package/dist/db/schema-snapshot.generated.js +9 -2
- package/dist/db/sql.d.ts +28 -0
- package/dist/db/sql.js +186 -0
- package/dist/decisions/actions/decide.d.ts +4 -0
- package/dist/decisions/actions/decide.js +7 -0
- package/dist/decisions/decide.d.ts +1 -0
- package/dist/decisions/decide.js +21 -9
- package/dist/decisions/index.d.ts +4 -1
- package/dist/decisions/index.js +3 -0
- package/dist/decisions/response.d.ts +1 -0
- package/dist/decisions/response.js +36 -11
- package/dist/decisions/types.d.ts +5 -0
- package/dist/decisions/validation.js +6 -3
- package/dist/deploy/build.js +11 -5
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/file-upload/attachment-text.d.ts +71 -0
- package/dist/file-upload/attachment-text.js +209 -0
- package/dist/file-upload/downscale-inline-image.d.ts +4 -0
- package/dist/file-upload/downscale-inline-image.js +27 -0
- package/dist/file-upload/inline-attachment-limits.d.ts +4 -0
- package/dist/file-upload/inline-attachment-limits.js +20 -1
- package/dist/file-upload/owned-attachment.d.ts +13 -1
- package/dist/file-upload/owned-attachment.js +52 -15
- package/dist/file-upload/pre-upload-attachments.js +74 -12
- package/dist/file-upload/registry.d.ts +1 -0
- package/dist/file-upload/registry.js +15 -7
- package/dist/file-upload/status.d.ts +19 -0
- package/dist/file-upload/status.js +49 -0
- package/dist/file-upload/thread-image-history.js +10 -2
- package/dist/index.browser.d.ts +1 -0
- package/dist/index.browser.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/ingestion/media.js +11 -5
- package/dist/jobs/actions/run-automation-now.js +2 -2
- package/dist/jobs/background-automation-runner.js +4 -4
- package/dist/jobs/frontmatter.d.ts +1 -1
- package/dist/jobs/frontmatter.js +5 -2
- package/dist/jobs/run-now.d.ts +2 -0
- package/dist/jobs/run-now.js +1 -1
- package/dist/jobs/scheduler.d.ts +2 -0
- package/dist/jobs/scheduler.js +1 -1
- package/dist/localization/automation-outcome-messages.js +22 -22
- package/dist/localization/core-messages/supplemental/ar-SA.js +1 -0
- package/dist/localization/core-messages/supplemental/de-DE.js +1 -0
- package/dist/localization/core-messages/supplemental/en-US.js +1 -0
- package/dist/localization/core-messages/supplemental/es-ES.js +1 -0
- package/dist/localization/core-messages/supplemental/fr-FR.js +1 -0
- package/dist/localization/core-messages/supplemental/hi-IN.js +1 -0
- package/dist/localization/core-messages/supplemental/ja-JP.js +1 -0
- package/dist/localization/core-messages/supplemental/ko-KR.js +1 -0
- package/dist/localization/core-messages/supplemental/pt-BR.js +1 -0
- package/dist/localization/core-messages/supplemental/zh-CN.js +1 -0
- package/dist/localization/core-messages/supplemental/zh-TW.js +1 -0
- package/dist/localization/mcp-approval-messages.d.ts +7 -1
- package/dist/localization/mcp-approval-messages.js +66 -0
- package/dist/localization/mcp-settings-messages.d.ts +1 -0
- package/dist/mcp/action-eligibility.d.ts +1 -0
- package/dist/mcp/action-eligibility.js +10 -5
- package/dist/mcp/analytics.d.ts +2 -0
- package/dist/mcp/analytics.js +10 -2
- package/dist/mcp/approval-route.d.ts +7 -0
- package/dist/mcp/approval-route.js +41 -16
- package/dist/mcp/approval-summary.d.ts +12 -2
- package/dist/mcp/approval-summary.js +128 -23
- package/dist/mcp/approval-time.d.ts +13 -3
- package/dist/mcp/approval-time.js +49 -5
- package/dist/mcp/build-server.d.ts +12 -1
- package/dist/mcp/build-server.js +157 -155
- package/dist/mcp/builtin-tools.d.ts +1 -0
- package/dist/mcp/builtin-tools.js +30 -14
- package/dist/mcp/direct-action-call.js +72 -27
- package/dist/mcp/embed-app.js +11 -6
- package/dist/mcp/embed-redaction.d.ts +10 -13
- package/dist/mcp/embed-redaction.js +227 -40
- package/dist/mcp/execute-action-call.d.ts +3 -2
- package/dist/mcp/execute-action-call.js +1 -4
- package/dist/mcp/framework-tools.d.ts +2 -2
- package/dist/mcp/oauth-route.js +102 -6
- package/dist/mcp/screen-memory-stdio.d.ts +3 -3
- package/dist/mcp/server.js +6 -0
- package/dist/mcp-client/oauth-routes.js +12 -2
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/failure-context.js +1 -0
- package/dist/observability/traces.js +11 -1
- package/dist/onboarding/first-run-builder-credits-experiment.d.ts +12 -0
- package/dist/onboarding/first-run-builder-credits-experiment.js +91 -0
- package/dist/org/index.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 +12 -12
- package/dist/server/action-approval.d.ts +2 -2
- package/dist/server/action-approval.js +17 -10
- package/dist/server/action-discovery.js +2 -122
- package/dist/server/action-routes.d.ts +0 -1
- package/dist/server/action-routes.js +138 -58
- package/dist/server/agent-chat/action-filters-a2a.d.ts +1 -0
- package/dist/server/agent-chat/action-filters-a2a.js +11 -1
- package/dist/server/agent-chat/framework-prompts.d.ts +1 -0
- package/dist/server/agent-chat/framework-prompts.js +22 -1
- package/dist/server/agent-chat/mcp-options.d.ts +7 -0
- package/dist/server/agent-chat/mcp-options.js +1 -0
- package/dist/server/agent-chat/plugin-options.d.ts +23 -0
- package/dist/server/agent-chat/prompt-resources.d.ts +4 -2
- package/dist/server/agent-chat/prompt-resources.js +78 -32
- package/dist/server/agent-chat-plugin.js +214 -125
- package/dist/server/agent-engine-api-key-route.d.ts +2 -2
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/agent-run-context.js +4 -0
- package/dist/server/attachment-actions.d.ts +14 -7
- package/dist/server/attachment-actions.js +310 -65
- package/dist/server/attribution.d.ts +2 -0
- package/dist/server/auth.d.ts +2 -1
- package/dist/server/auth.js +84 -17
- package/dist/server/better-auth-instance.js +46 -12
- package/dist/server/builder-api-auth.d.ts +1 -0
- package/dist/server/builder-api-auth.js +8 -0
- package/dist/server/builder-browser.d.ts +5 -1
- package/dist/server/builder-browser.js +80 -4
- package/dist/server/cli-wrapper-flags.d.ts +27 -0
- package/dist/server/cli-wrapper-flags.js +500 -0
- package/dist/server/consent-route.d.ts +3 -0
- package/dist/server/consent-route.js +29 -10
- package/dist/server/core-routes-plugin.js +72 -60
- package/dist/server/credential-provider.js +26 -11
- package/dist/server/edge.d.ts +3 -2
- package/dist/server/edge.js +3 -2
- package/dist/server/embed-request-origin.d.ts +4 -0
- package/dist/server/embed-request-origin.js +28 -0
- package/dist/server/embed-route.js +4 -2
- package/dist/server/embed-session.d.ts +16 -4
- package/dist/server/embed-session.js +253 -145
- package/dist/server/embedded.d.ts +2 -1
- package/dist/server/embedded.js +9 -5
- package/dist/server/filesystem-action-entry.d.ts +15 -1
- package/dist/server/filesystem-action-entry.js +153 -23
- package/dist/server/first-touch-route.d.ts +1 -1
- package/dist/server/google-oauth.d.ts +7 -0
- package/dist/server/google-oauth.js +33 -6
- package/dist/server/index.d.ts +11 -6
- package/dist/server/index.js +8 -3
- package/dist/server/magic-link-attribution.d.ts +2 -0
- package/dist/server/magic-link-attribution.js +8 -2
- package/dist/server/mcp-signup-attribution.d.ts +23 -0
- package/dist/server/mcp-signup-attribution.js +135 -0
- package/dist/server/prompts/framework-core.js +2 -1
- package/dist/server/prompts/shared-rules.d.ts +2 -0
- package/dist/server/prompts/shared-rules.js +2 -0
- package/dist/server/realtime-voice.d.ts +65 -2
- package/dist/server/realtime-voice.js +235 -36
- package/dist/server/release-migrations.js +37 -10
- package/dist/server/request-context.d.ts +17 -0
- package/dist/server/request-context.js +4 -0
- package/dist/server/request-origin.d.ts +4 -6
- package/dist/server/request-origin.js +26 -28
- package/dist/server/session-resolution-unavailable.d.ts +22 -0
- package/dist/server/session-resolution-unavailable.js +65 -0
- package/dist/server/short-lived-token.d.ts +10 -2
- package/dist/server/short-lived-token.js +12 -4
- package/dist/server/ui-action-capability.js +18 -4
- package/dist/shared/first-run-builder-credits-experiment.d.ts +13 -0
- package/dist/shared/first-run-builder-credits-experiment.js +22 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +1 -0
- package/dist/shared/mcp-approval-review.d.ts +19 -0
- package/dist/shared/mcp-approval-review.js +29 -0
- package/dist/shared/reasoning-effort.d.ts +4 -0
- package/dist/shared/reasoning-effort.js +20 -0
- package/dist/sharing/access.d.ts +11 -2
- package/dist/sharing/access.js +12 -7
- package/dist/state-machine/index.d.ts +5 -8
- package/dist/state-machine/index.js +6 -2
- package/dist/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +48 -18
- package/dist/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +7 -6
- package/dist/templates/builder-code-starter/template-layer.json +1 -0
- package/dist/templates/chat/.agents/skills/storing-data/SKILL.md +18 -0
- package/dist/templates/chat/app/components/chat/ChatRouteContent.tsx +18 -4
- package/dist/templates/chat/app/components/home/HomePage.tsx +28 -69
- package/dist/templates/chat/app/components/layout/Layout.tsx +46 -14
- package/dist/templates/chat/app/i18n/ar-SA.ts +0 -4
- package/dist/templates/chat/app/i18n/de-DE.ts +0 -5
- package/dist/templates/chat/app/i18n/en-US.ts +0 -4
- package/dist/templates/chat/app/i18n/es-ES.ts +0 -5
- package/dist/templates/chat/app/i18n/fr-FR.ts +0 -5
- package/dist/templates/chat/app/i18n/hi-IN.ts +0 -5
- package/dist/templates/chat/app/i18n/ja-JP.ts +0 -5
- package/dist/templates/chat/app/i18n/ko-KR.ts +0 -5
- package/dist/templates/chat/app/i18n/pt-BR.ts +0 -5
- package/dist/templates/chat/app/i18n/zh-CN.ts +0 -4
- package/dist/templates/chat/app/i18n/zh-TW.ts +0 -4
- package/dist/templates/chat/app/lib/chat-paths.ts +36 -13
- package/dist/templates/chat/package.json +1 -0
- package/dist/templates/chat/server/plugins/agent-chat.ts +2 -1
- package/dist/templates/default/.agents/skills/storing-data/SKILL.md +18 -0
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +123 -33
- package/dist/templates/headless/.agents/skills/storing-data/SKILL.md +18 -0
- package/dist/templates/workspace-core/.agents/skills/storing-data/SKILL.md +18 -0
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +34 -29
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +12 -5
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +3 -2
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/references/where-it-runs.md +93 -0
- package/dist/tracking/registry.js +25 -0
- package/dist/triggers/actions/manage-automation.js +6 -2
- package/dist/triggers/actions.js +14 -2
- package/dist/triggers/index.d.ts +1 -0
- package/dist/triggers/index.js +1 -0
- package/dist/vite/client.js +5 -4
- package/docs/content/authentication.mdx +2 -0
- package/docs/content/components.mdx +1 -1
- package/docs/content/decisions.mdx +1 -1
- package/docs/content/recurring-jobs.mdx +15 -0
- package/docs/content/template-chat-developers.mdx +1 -1
- package/docs/content/template-chat-features.mdx +4 -4
- package/docs/content/turn-into-app.mdx +18 -10
- package/package.json +6 -4
- package/src/templates/builder-code-starter/app/components/layout/Layout.tsx.patch +48 -18
- package/src/templates/builder-code-starter/server/plugins/agent-chat.ts.patch +7 -6
- package/src/templates/builder-code-starter/template-layer.json +1 -0
- package/src/templates/chat/.agents/skills/storing-data/SKILL.md +18 -0
- package/src/templates/chat/app/components/chat/ChatRouteContent.tsx +18 -4
- package/src/templates/chat/app/components/home/HomePage.tsx +28 -69
- package/src/templates/chat/app/components/layout/Layout.tsx +46 -14
- package/src/templates/chat/app/i18n/ar-SA.ts +0 -4
- package/src/templates/chat/app/i18n/de-DE.ts +0 -5
- package/src/templates/chat/app/i18n/en-US.ts +0 -4
- package/src/templates/chat/app/i18n/es-ES.ts +0 -5
- package/src/templates/chat/app/i18n/fr-FR.ts +0 -5
- package/src/templates/chat/app/i18n/hi-IN.ts +0 -5
- package/src/templates/chat/app/i18n/ja-JP.ts +0 -5
- package/src/templates/chat/app/i18n/ko-KR.ts +0 -5
- package/src/templates/chat/app/i18n/pt-BR.ts +0 -5
- package/src/templates/chat/app/i18n/zh-CN.ts +0 -4
- package/src/templates/chat/app/i18n/zh-TW.ts +0 -4
- package/src/templates/chat/app/lib/chat-paths.ts +36 -13
- package/src/templates/chat/package.json +1 -0
- package/src/templates/chat/server/plugins/agent-chat.ts +2 -1
- package/src/templates/default/.agents/skills/storing-data/SKILL.md +18 -0
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +123 -33
- package/src/templates/headless/.agents/skills/storing-data/SKILL.md +18 -0
- package/src/templates/workspace-core/.agents/skills/storing-data/SKILL.md +18 -0
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +34 -29
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/fresh-project.md +12 -5
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/review-loop.md +3 -2
- package/src/templates/workspace-core/.agents/skills/turn-into-app/references/where-it-runs.md +93 -0
- package/dist/automations/mcp-origin.d.ts +0 -2
- package/dist/automations/mcp-origin.js +0 -10
- /package/dist/agent/{run-store.fencing.worker.d.ts → run-store.fencing.native-harness.fixture.test.support.d.ts} +0 -0
package/dist/a2a/server.js
CHANGED
|
@@ -13,7 +13,7 @@ import { readDeployCredentialEnv } from "../server/credential-provider.js";
|
|
|
13
13
|
import { getH3App } from "../server/framework-request-handler.js";
|
|
14
14
|
import { publicFrameworkPath } from "../server/framework-route-prefix.js";
|
|
15
15
|
import { readBody } from "../server/h3-helpers.js";
|
|
16
|
-
import {
|
|
16
|
+
import { hasSameOriginBrowserEvidence } from "../server/request-origin.js";
|
|
17
17
|
import { generateAgentCard } from "./agent-card.js";
|
|
18
18
|
import { addAgentProfileExamples } from "./app-profile.js";
|
|
19
19
|
import { canonicalA2AAudience } from "./audience.js";
|
|
@@ -577,8 +577,8 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
|
|
|
577
577
|
setResponseStatus(event, 404);
|
|
578
578
|
return { error: "Approval not found" };
|
|
579
579
|
}
|
|
580
|
-
const {
|
|
581
|
-
const session = await
|
|
580
|
+
const { getBrowserCookieSession } = await import("../server/auth.js");
|
|
581
|
+
const session = await getBrowserCookieSession(event);
|
|
582
582
|
if (!session?.email) {
|
|
583
583
|
setResponseStatus(event, 401);
|
|
584
584
|
return { error: "Sign in to review this approval" };
|
|
@@ -613,7 +613,7 @@ export function mountA2A(nitroApp, config, routePrefix = "/_agent-native") {
|
|
|
613
613
|
setResponseStatus(event, 405);
|
|
614
614
|
return { error: "Method not allowed" };
|
|
615
615
|
}
|
|
616
|
-
if (!
|
|
616
|
+
if (!hasSameOriginBrowserEvidence(event)) {
|
|
617
617
|
setResponseStatus(event, 403);
|
|
618
618
|
return { error: "Cross-origin approval denied" };
|
|
619
619
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type SqlFragment } from "../db/sql.js";
|
|
2
2
|
import type { TaskState } from "./types.js";
|
|
3
|
-
export declare const a2aTaskMachine:
|
|
4
|
-
export declare const a2aApprovalMachine:
|
|
3
|
+
export declare const a2aTaskMachine: import("../state-machine/index.js").SqlMachine<"canceled" | "completed" | "failed" | "input-required" | "processing" | "submitted" | "working", "cancel" | "claimForProcessing" | "completeApproval" | "completeProcessing" | "failApproval" | "failProcessing" | "failStale" | "failStuckProcessing" | "failStuckQueued" | "overwriteAsCanceled" | "overwriteAsCompleted" | "overwriteAsFailed" | "overwriteAsInputRequired" | "overwriteAsProcessing" | "overwriteAsSubmitted" | "overwriteAsWorking" | "requireInput" | "resumeAfterApproval" | "retryStuck">;
|
|
4
|
+
export declare const a2aApprovalMachine: import("../state-machine/index.js").SqlMachine<"completed" | "failed" | "pending" | "processing", "claim" | "complete" | "fail" | "reclaim">;
|
|
5
5
|
export type A2ATaskStatus = (typeof a2aTaskMachine.states)[number];
|
|
6
6
|
export type A2ATaskEvent = (typeof a2aTaskMachine.events)[number];
|
|
7
7
|
export type A2AApprovalStatus = (typeof a2aApprovalMachine.states)[number];
|
|
8
8
|
export type A2AApprovalEvent = (typeof a2aApprovalMachine.events)[number];
|
|
9
9
|
type Mutual<A, B> = [A] extends [B] ? ([B] extends [A] ? true : false) : false;
|
|
10
10
|
export declare const taskStatesMatchTaskState: Mutual<A2ATaskStatus, TaskState>;
|
|
11
|
-
/**
|
|
12
|
-
export declare function taskIn(event: A2ATaskEvent):
|
|
13
|
-
/**
|
|
14
|
-
export declare function taskTarget(event: A2ATaskEvent):
|
|
15
|
-
/**
|
|
16
|
-
export declare function taskSql(state: A2ATaskStatus):
|
|
17
|
-
export declare function approvalIn(event: A2AApprovalEvent):
|
|
18
|
-
export declare function approvalTarget(event: A2AApprovalEvent):
|
|
19
|
-
export declare function approvalSql(state: A2AApprovalStatus):
|
|
11
|
+
/** Bound source states for an event's `IN` predicate. */
|
|
12
|
+
export declare function taskIn(event: A2ATaskEvent): SqlFragment;
|
|
13
|
+
/** Bound state value for the state an event lands in. */
|
|
14
|
+
export declare function taskTarget(event: A2ATaskEvent): SqlFragment;
|
|
15
|
+
/** Bound state value for single-state WHERE and SELECT predicates. */
|
|
16
|
+
export declare function taskSql(state: A2ATaskStatus): SqlFragment;
|
|
17
|
+
export declare function approvalIn(event: A2AApprovalEvent): SqlFragment;
|
|
18
|
+
export declare function approvalTarget(event: A2AApprovalEvent): SqlFragment;
|
|
19
|
+
export declare function approvalSql(state: A2AApprovalStatus): SqlFragment;
|
|
20
20
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { sql } from "../db/sql.js";
|
|
1
2
|
import { defineMachine } from "../state-machine/index.js";
|
|
2
3
|
/**
|
|
3
4
|
* Lifecycles of `a2a_tasks.status_state` and `a2a_approvals.status`.
|
|
@@ -95,27 +96,24 @@ function targetOf(machine, event) {
|
|
|
95
96
|
}
|
|
96
97
|
return machine.transition(from, event);
|
|
97
98
|
}
|
|
98
|
-
/**
|
|
99
|
+
/** Bound source states for an event's `IN` predicate. */
|
|
99
100
|
export function taskIn(event) {
|
|
100
|
-
return a2aTaskMachine.
|
|
101
|
+
return a2aTaskMachine.sqlIn(event);
|
|
101
102
|
}
|
|
102
|
-
/**
|
|
103
|
+
/** Bound state value for the state an event lands in. */
|
|
103
104
|
export function taskTarget(event) {
|
|
104
|
-
return
|
|
105
|
+
return sql `${sql.value(targetOf(a2aTaskMachine, event))}`;
|
|
105
106
|
}
|
|
106
|
-
/**
|
|
107
|
+
/** Bound state value for single-state WHERE and SELECT predicates. */
|
|
107
108
|
export function taskSql(state) {
|
|
108
|
-
return
|
|
109
|
+
return sql `${sql.value(a2aTaskMachine.parseState(state))}`;
|
|
109
110
|
}
|
|
110
111
|
export function approvalIn(event) {
|
|
111
|
-
return a2aApprovalMachine.
|
|
112
|
+
return a2aApprovalMachine.sqlIn(event);
|
|
112
113
|
}
|
|
113
114
|
export function approvalTarget(event) {
|
|
114
|
-
return
|
|
115
|
+
return sql `${sql.value(targetOf(a2aApprovalMachine, event))}`;
|
|
115
116
|
}
|
|
116
117
|
export function approvalSql(state) {
|
|
117
|
-
return
|
|
118
|
-
}
|
|
119
|
-
function sqlLiteral(machine, state) {
|
|
120
|
-
return `'${machine.parseState(state)}'`;
|
|
118
|
+
return sql `${sql.value(a2aApprovalMachine.parseState(state))}`;
|
|
121
119
|
}
|
package/dist/a2a/task-store.js
CHANGED
|
@@ -2,6 +2,7 @@ import crypto from "crypto";
|
|
|
2
2
|
import { currentExecutionFence, withFencedExecutionWrite, } from "../agent/execution-fence.js";
|
|
3
3
|
import { getDbExec } from "../db/client.js";
|
|
4
4
|
import { ensureTableExists, ensureColumnExists, ensureIndexExists, } from "../db/ddl-guard.js";
|
|
5
|
+
import { sql } from "../db/sql.js";
|
|
5
6
|
import { defineStore } from "../db/store-registry.js";
|
|
6
7
|
import { assertA2APersistablePayload } from "./persistence-safety.js";
|
|
7
8
|
import { a2aApprovalMachine, a2aTaskMachine, approvalSql, approvalTarget, taskIn, taskSql, taskTarget, } from "./task-lifecycle.js";
|
|
@@ -127,22 +128,7 @@ export async function createA2AApproval(input) {
|
|
|
127
128
|
const id = crypto.randomUUID();
|
|
128
129
|
const now = Date.now();
|
|
129
130
|
const expiresAt = now + (input.ttlMs ?? 15 * 60_000);
|
|
130
|
-
await withFencedExecutionWrite((tx) => tx.execute({
|
|
131
|
-
sql: `INSERT INTO a2a_approvals (id, task_id, owner_email, org_id, tool_name, tool_input, approval_key, call_id, status, expires_at, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ${approvalSql(a2aApprovalMachine.initial)}, ?, ?, ?)`,
|
|
132
|
-
args: [
|
|
133
|
-
id,
|
|
134
|
-
input.taskId,
|
|
135
|
-
input.ownerEmail,
|
|
136
|
-
input.orgId ?? null,
|
|
137
|
-
input.tool,
|
|
138
|
-
JSON.stringify(input.toolInput ?? {}),
|
|
139
|
-
input.approvalKey,
|
|
140
|
-
input.callId,
|
|
141
|
-
expiresAt,
|
|
142
|
-
now,
|
|
143
|
-
now,
|
|
144
|
-
],
|
|
145
|
-
}), { threadId: a2aTaskLeaseThreadId(input.taskId), turnId: input.taskId });
|
|
131
|
+
await withFencedExecutionWrite((tx) => tx.execute(sql `INSERT INTO a2a_approvals (id, task_id, owner_email, org_id, tool_name, tool_input, approval_key, call_id, status, expires_at, created_at, updated_at) VALUES (${sql.value(id)}, ${sql.value(input.taskId)}, ${sql.value(input.ownerEmail)}, ${sql.value(input.orgId ?? null)}, ${sql.value(input.tool)}, ${sql.value(JSON.stringify(input.toolInput ?? {}))}, ${sql.value(input.approvalKey)}, ${sql.value(input.callId)}, ${approvalSql(a2aApprovalMachine.initial)}, ${sql.value(expiresAt)}, ${sql.value(now)}, ${sql.value(now)})`), { threadId: a2aTaskLeaseThreadId(input.taskId), turnId: input.taskId });
|
|
146
132
|
return {
|
|
147
133
|
id,
|
|
148
134
|
taskId: input.taskId,
|
|
@@ -180,16 +166,10 @@ export async function claimA2AApproval(id, ownerEmail, orgId) {
|
|
|
180
166
|
}
|
|
181
167
|
try {
|
|
182
168
|
return await withFencedExecutionWrite(async (tx) => {
|
|
183
|
-
const approvalUpdate = await tx.execute({
|
|
184
|
-
sql: `UPDATE a2a_approvals SET status = ${approvalTarget("claim")}, updated_at = ? WHERE id = ? AND owner_email = ? AND ((status = ${approvalSql("pending")} AND expires_at > ?) OR status = ${approvalSql("processing")}) AND (org_id IS NULL OR org_id = ?)`,
|
|
185
|
-
args: [now, id, ownerEmail, now, orgId ?? null],
|
|
186
|
-
});
|
|
169
|
+
const approvalUpdate = await tx.execute(sql `UPDATE a2a_approvals SET status = ${approvalTarget("claim")}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND owner_email = ${sql.value(ownerEmail)} AND ((status = ${approvalSql("pending")} AND expires_at > ${sql.value(now)}) OR status = ${approvalSql("processing")}) AND (org_id IS NULL OR org_id = ${sql.value(orgId ?? null)})`);
|
|
187
170
|
if (getAffectedRowCount(approvalUpdate) === 0)
|
|
188
171
|
throw new ClaimRejected();
|
|
189
|
-
const { rows } = await tx.execute({
|
|
190
|
-
sql: `SELECT * FROM a2a_approvals WHERE id = ? AND owner_email = ? AND status = ${approvalSql("processing")}`,
|
|
191
|
-
args: [id, ownerEmail],
|
|
192
|
-
});
|
|
172
|
+
const { rows } = await tx.execute(sql `SELECT * FROM a2a_approvals WHERE id = ${sql.value(id)} AND owner_email = ${sql.value(ownerEmail)} AND status = ${approvalSql("processing")}`);
|
|
193
173
|
if (!rows[0])
|
|
194
174
|
throw new ClaimRejected();
|
|
195
175
|
const approval = approvalFromRow(rows[0]);
|
|
@@ -198,16 +178,7 @@ export async function claimA2AApproval(id, ownerEmail, orgId) {
|
|
|
198
178
|
role: "agent",
|
|
199
179
|
parts: [{ type: "text", text: "Approved action is running." }],
|
|
200
180
|
};
|
|
201
|
-
const taskUpdate = await tx.execute({
|
|
202
|
-
sql: `UPDATE a2a_tasks SET status_state = ${taskTarget("resumeAfterApproval")}, status_message = ?, status_timestamp = ?, updated_at = ? WHERE id = ? AND owner_email = ? AND status_state IN (${taskIn("resumeAfterApproval")})`,
|
|
203
|
-
args: [
|
|
204
|
-
JSON.stringify(runningMessage),
|
|
205
|
-
timestamp,
|
|
206
|
-
now,
|
|
207
|
-
approval.taskId,
|
|
208
|
-
ownerEmail,
|
|
209
|
-
],
|
|
210
|
-
});
|
|
181
|
+
const taskUpdate = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${taskTarget("resumeAfterApproval")}, status_message = ${sql.value(JSON.stringify(runningMessage))}, status_timestamp = ${sql.value(timestamp)}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(approval.taskId)} AND owner_email = ${sql.value(ownerEmail)} AND status_state IN ${taskIn("resumeAfterApproval")}`);
|
|
211
182
|
if (getAffectedRowCount(taskUpdate) === 0)
|
|
212
183
|
throw new ClaimRejected();
|
|
213
184
|
return approval;
|
|
@@ -232,10 +203,7 @@ export async function settleA2AApproval(id, status, resultText) {
|
|
|
232
203
|
}
|
|
233
204
|
await ensureTable();
|
|
234
205
|
const client = getDbExec();
|
|
235
|
-
const { rows: approvalRows } = await client.execute({
|
|
236
|
-
sql: `SELECT task_id FROM a2a_approvals WHERE id = ? AND status = ${approvalSql("processing")}`,
|
|
237
|
-
args: [id],
|
|
238
|
-
});
|
|
206
|
+
const { rows: approvalRows } = await client.execute(sql `SELECT task_id FROM a2a_approvals WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
|
|
239
207
|
if (!approvalRows[0])
|
|
240
208
|
throw new Error("Approval is not processing");
|
|
241
209
|
const taskId = String(approvalRows[0].task_id);
|
|
@@ -246,17 +214,11 @@ export async function settleA2AApproval(id, status, resultText) {
|
|
|
246
214
|
parts: [{ type: "text", text: settledText }],
|
|
247
215
|
};
|
|
248
216
|
await withFencedExecutionWrite(async (tx) => {
|
|
249
|
-
const { rows } = await tx.execute({
|
|
250
|
-
sql: `SELECT task_id FROM a2a_approvals WHERE id = ? AND status = ${approvalSql("processing")}`,
|
|
251
|
-
args: [id],
|
|
252
|
-
});
|
|
217
|
+
const { rows } = await tx.execute(sql `SELECT task_id FROM a2a_approvals WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
|
|
253
218
|
if (!rows[0])
|
|
254
219
|
throw new Error("Approval is not processing");
|
|
255
220
|
const taskId = String(rows[0].task_id);
|
|
256
|
-
const { rows: taskRows } = await tx.execute({
|
|
257
|
-
sql: `SELECT history FROM a2a_tasks WHERE id = ? AND status_state = ${taskSql("working")}`,
|
|
258
|
-
args: [taskId],
|
|
259
|
-
});
|
|
221
|
+
const { rows: taskRows } = await tx.execute(sql `SELECT history FROM a2a_tasks WHERE id = ${sql.value(taskId)} AND status_state = ${taskSql("working")}`);
|
|
260
222
|
if (!taskRows[0]) {
|
|
261
223
|
throw new Error("Approval task is no longer awaiting settlement");
|
|
262
224
|
}
|
|
@@ -264,24 +226,11 @@ export async function settleA2AApproval(id, status, resultText) {
|
|
|
264
226
|
history.push(message);
|
|
265
227
|
assertA2APersistablePayload(history, "A2A task history");
|
|
266
228
|
const timestamp = new Date(now).toISOString();
|
|
267
|
-
const taskUpdate = await tx.execute({
|
|
268
|
-
sql: `UPDATE a2a_tasks SET status_state = ?, status_message = ?, status_timestamp = ?, history = ?, updated_at = ? WHERE id = ? AND status_state = ${taskSql("working")}`,
|
|
269
|
-
args: [
|
|
270
|
-
settledStatus,
|
|
271
|
-
JSON.stringify(message),
|
|
272
|
-
timestamp,
|
|
273
|
-
JSON.stringify(history),
|
|
274
|
-
now,
|
|
275
|
-
taskId,
|
|
276
|
-
],
|
|
277
|
-
});
|
|
229
|
+
const taskUpdate = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${sql.value(settledStatus)}, status_message = ${sql.value(JSON.stringify(message))}, status_timestamp = ${sql.value(timestamp)}, history = ${sql.value(JSON.stringify(history))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(taskId)} AND status_state = ${taskSql("working")}`);
|
|
278
230
|
if (getAffectedRowCount(taskUpdate) === 0) {
|
|
279
231
|
throw new Error("Approval task settlement lost its state claim");
|
|
280
232
|
}
|
|
281
|
-
const approvalUpdate = await tx.execute({
|
|
282
|
-
sql: `UPDATE a2a_approvals SET status = ?, result = ?, updated_at = ? WHERE id = ? AND status = ${approvalSql("processing")}`,
|
|
283
|
-
args: [settledStatus, settledText, now, id],
|
|
284
|
-
});
|
|
233
|
+
const approvalUpdate = await tx.execute(sql `UPDATE a2a_approvals SET status = ${sql.value(settledStatus)}, result = ${sql.value(settledText)}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND status = ${approvalSql("processing")}`);
|
|
285
234
|
if (getAffectedRowCount(approvalUpdate) === 0) {
|
|
286
235
|
throw new Error("Approval settlement lost its state claim");
|
|
287
236
|
}
|
|
@@ -299,10 +248,7 @@ export async function pauseProcessingA2ATask(id, message) {
|
|
|
299
248
|
assertA2APersistablePayload(message, "A2A task status message");
|
|
300
249
|
await ensureTable();
|
|
301
250
|
return withFencedExecutionWrite(async (tx) => {
|
|
302
|
-
const { rows } = await tx.execute({
|
|
303
|
-
sql: `SELECT * FROM a2a_tasks WHERE id = ? AND status_state = ${taskSql("processing")}`,
|
|
304
|
-
args: [id],
|
|
305
|
-
});
|
|
251
|
+
const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)} AND status_state = ${taskSql("processing")}`);
|
|
306
252
|
if (!rows[0])
|
|
307
253
|
return null;
|
|
308
254
|
const task = taskFromRow(rows[0]);
|
|
@@ -310,16 +256,7 @@ export async function pauseProcessingA2ATask(id, message) {
|
|
|
310
256
|
assertA2APersistablePayload(task.history, "A2A task history");
|
|
311
257
|
const now = Date.now();
|
|
312
258
|
const timestamp = new Date(now).toISOString();
|
|
313
|
-
const result = await tx.execute({
|
|
314
|
-
sql: `UPDATE a2a_tasks SET status_state = ${taskTarget("requireInput")}, status_message = ?, status_timestamp = ?, history = ?, updated_at = ? WHERE id = ? AND status_state = ${taskSql("processing")}`,
|
|
315
|
-
args: [
|
|
316
|
-
JSON.stringify(message),
|
|
317
|
-
timestamp,
|
|
318
|
-
JSON.stringify(task.history ?? []),
|
|
319
|
-
now,
|
|
320
|
-
id,
|
|
321
|
-
],
|
|
322
|
-
});
|
|
259
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${taskTarget("requireInput")}, status_message = ${sql.value(JSON.stringify(message))}, status_timestamp = ${sql.value(timestamp)}, history = ${sql.value(JSON.stringify(task.history ?? []))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)} AND status_state = ${taskSql("processing")}`);
|
|
323
260
|
if (getAffectedRowCount(result) === 0)
|
|
324
261
|
return null;
|
|
325
262
|
task.status = { state: "input-required", message, timestamp };
|
|
@@ -432,10 +369,7 @@ export async function createOrReuseTask(message, contextId, metadata, ownerEmail
|
|
|
432
369
|
const reused = task.id !== id;
|
|
433
370
|
if (reused &&
|
|
434
371
|
(task.status.state === "failed" || task.status.state === "canceled")) {
|
|
435
|
-
await client.execute({
|
|
436
|
-
sql: `UPDATE a2a_tasks SET idempotency_key = NULL, updated_at = ? WHERE id = ? AND idempotency_key = ? AND status_state IN (${taskSql("failed")}, ${taskSql("canceled")})`,
|
|
437
|
-
args: [Date.now(), task.id, idempotencyKey],
|
|
438
|
-
});
|
|
372
|
+
await client.execute(sql `UPDATE a2a_tasks SET idempotency_key = NULL, updated_at = ${sql.value(Date.now())} WHERE id = ${sql.value(task.id)} AND idempotency_key = ${sql.value(idempotencyKey)} AND status_state IN (${taskSql("failed")}, ${taskSql("canceled")})`);
|
|
439
373
|
continue;
|
|
440
374
|
}
|
|
441
375
|
return { task, reused };
|
|
@@ -444,11 +378,8 @@ export async function createOrReuseTask(message, contextId, metadata, ownerEmail
|
|
|
444
378
|
}
|
|
445
379
|
function taskAccessPredicate(scope) {
|
|
446
380
|
if (!scope)
|
|
447
|
-
return
|
|
448
|
-
return {
|
|
449
|
-
sql: " AND LOWER(COALESCE(owner_email, '')) = LOWER(?) AND LOWER(COALESCE(owner_scope, '')) = LOWER(?)",
|
|
450
|
-
args: [scope.ownerEmail, scope.ownerScope ?? ""],
|
|
451
|
-
};
|
|
381
|
+
return sql ``;
|
|
382
|
+
return sql ` AND LOWER(COALESCE(owner_email, '')) = LOWER(${sql.value(scope.ownerEmail)}) AND LOWER(COALESCE(owner_scope, '')) = LOWER(${sql.value(scope.ownerScope ?? "")})`;
|
|
452
383
|
}
|
|
453
384
|
export async function getTaskOwner(id) {
|
|
454
385
|
return (await getTaskOwnership(id)).ownerEmail;
|
|
@@ -474,16 +405,13 @@ export async function claimA2ATaskForProcessing(id) {
|
|
|
474
405
|
const now = Date.now();
|
|
475
406
|
const timestamp = new Date().toISOString();
|
|
476
407
|
return withFencedExecutionWrite(async (tx) => {
|
|
477
|
-
const { rows } = await tx.execute(
|
|
478
|
-
sql: `UPDATE a2a_tasks
|
|
408
|
+
const { rows } = await tx.execute(sql `UPDATE a2a_tasks
|
|
479
409
|
SET status_state = ${taskTarget("claimForProcessing")},
|
|
480
|
-
status_timestamp =
|
|
481
|
-
updated_at =
|
|
482
|
-
WHERE id =
|
|
483
|
-
AND status_state IN
|
|
484
|
-
RETURNING
|
|
485
|
-
args: [timestamp, now, id],
|
|
486
|
-
});
|
|
410
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
411
|
+
updated_at = ${sql.value(now)}
|
|
412
|
+
WHERE id = ${sql.value(id)}
|
|
413
|
+
AND status_state IN ${taskIn("claimForProcessing")}
|
|
414
|
+
RETURNING *`);
|
|
487
415
|
return rows.length > 0 ? taskFromRow(rows[0]) : null;
|
|
488
416
|
}, { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
489
417
|
}
|
|
@@ -509,26 +437,20 @@ export async function touchQueuedA2ATaskDispatch(id) {
|
|
|
509
437
|
await ensureTable();
|
|
510
438
|
const client = getDbExec();
|
|
511
439
|
const now = Date.now();
|
|
512
|
-
const result = await client.execute(
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
AND status_state IN (${taskIn("claimForProcessing")})`,
|
|
517
|
-
args: [now, id],
|
|
518
|
-
});
|
|
440
|
+
const result = await client.execute(sql `UPDATE a2a_tasks
|
|
441
|
+
SET updated_at = ${sql.value(now)}
|
|
442
|
+
WHERE id = ${sql.value(id)}
|
|
443
|
+
AND status_state IN ${taskIn("claimForProcessing")}`);
|
|
519
444
|
const affected = getAffectedRowCount(result);
|
|
520
445
|
return affected !== 0;
|
|
521
446
|
}
|
|
522
447
|
export async function touchProcessingA2ATask(id) {
|
|
523
448
|
await ensureTable();
|
|
524
449
|
const now = Date.now();
|
|
525
|
-
const result = await withFencedExecutionWrite((tx) => tx.execute(
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
AND status_state = ${taskSql("processing")}`,
|
|
530
|
-
args: [now, id],
|
|
531
|
-
}), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
450
|
+
const result = await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
|
|
451
|
+
SET updated_at = ${sql.value(now)}
|
|
452
|
+
WHERE id = ${sql.value(id)}
|
|
453
|
+
AND status_state = ${taskSql("processing")}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
532
454
|
const affected = getAffectedRowCount(result);
|
|
533
455
|
return affected !== 0;
|
|
534
456
|
}
|
|
@@ -536,16 +458,13 @@ export async function resetStuckA2ATaskForRetry(id, processingCutoff) {
|
|
|
536
458
|
await ensureTable();
|
|
537
459
|
const now = Date.now();
|
|
538
460
|
const timestamp = new Date().toISOString();
|
|
539
|
-
const result = await withFencedExecutionWrite((tx) => tx.execute(
|
|
540
|
-
sql: `UPDATE a2a_tasks
|
|
461
|
+
const result = await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
|
|
541
462
|
SET status_state = ${taskTarget("retryStuck")},
|
|
542
|
-
status_timestamp =
|
|
543
|
-
updated_at =
|
|
544
|
-
WHERE id =
|
|
463
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
464
|
+
updated_at = ${sql.value(now)}
|
|
465
|
+
WHERE id = ${sql.value(id)}
|
|
545
466
|
AND status_state = ${taskSql("processing")}
|
|
546
|
-
AND updated_at <=
|
|
547
|
-
args: [timestamp, now, id, processingCutoff],
|
|
548
|
-
}), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
467
|
+
AND updated_at <= ${sql.value(processingCutoff)}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
549
468
|
const affected = getAffectedRowCount(result);
|
|
550
469
|
return affected !== 0;
|
|
551
470
|
}
|
|
@@ -562,31 +481,19 @@ export async function failStuckA2ATask(id, processingCutoff, reason, createdAtCu
|
|
|
562
481
|
parts: [{ type: "text", text: reason }],
|
|
563
482
|
};
|
|
564
483
|
const ageCondition = createdAtCutoff !== undefined
|
|
565
|
-
? `AND (updated_at <=
|
|
566
|
-
: `AND updated_at <=
|
|
484
|
+
? sql `AND (updated_at <= ${sql.value(processingCutoff)} OR created_at <= ${sql.value(createdAtCutoff)})`
|
|
485
|
+
: sql `AND updated_at <= ${sql.value(processingCutoff)}`;
|
|
567
486
|
return withDbTransaction(client, async (tx) => {
|
|
568
487
|
const leaseThreadId = a2aTaskLeaseThreadId(id);
|
|
569
488
|
await lockTaskExecutionLease(tx, leaseThreadId, id);
|
|
570
|
-
const result = await tx.execute(
|
|
571
|
-
sql: `UPDATE a2a_tasks
|
|
489
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks
|
|
572
490
|
SET status_state = ${taskTarget("failStuckProcessing")},
|
|
573
|
-
status_message =
|
|
574
|
-
status_timestamp =
|
|
575
|
-
updated_at =
|
|
576
|
-
WHERE id =
|
|
491
|
+
status_message = ${sql.value(JSON.stringify(message))},
|
|
492
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
493
|
+
updated_at = ${sql.value(now)}
|
|
494
|
+
WHERE id = ${sql.value(id)}
|
|
577
495
|
AND status_state = ${taskSql("processing")}
|
|
578
|
-
${ageCondition}
|
|
579
|
-
args: createdAtCutoff !== undefined
|
|
580
|
-
? [
|
|
581
|
-
JSON.stringify(message),
|
|
582
|
-
timestamp,
|
|
583
|
-
now,
|
|
584
|
-
id,
|
|
585
|
-
processingCutoff,
|
|
586
|
-
createdAtCutoff,
|
|
587
|
-
]
|
|
588
|
-
: [JSON.stringify(message), timestamp, now, id, processingCutoff],
|
|
589
|
-
});
|
|
496
|
+
${ageCondition}`);
|
|
590
497
|
const affected = getAffectedRowCount(result);
|
|
591
498
|
if (affected === 1) {
|
|
592
499
|
await revokeTaskExecutionLease(tx, leaseThreadId, id);
|
|
@@ -609,17 +516,14 @@ export async function failStuckQueuedA2ATask(id, createdAtCutoff, reason) {
|
|
|
609
516
|
return withDbTransaction(client, async (tx) => {
|
|
610
517
|
const leaseThreadId = a2aTaskLeaseThreadId(id);
|
|
611
518
|
await lockTaskExecutionLease(tx, leaseThreadId, id);
|
|
612
|
-
const result = await tx.execute(
|
|
613
|
-
sql: `UPDATE a2a_tasks
|
|
519
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks
|
|
614
520
|
SET status_state = ${taskTarget("failStuckQueued")},
|
|
615
|
-
status_message =
|
|
616
|
-
status_timestamp =
|
|
617
|
-
updated_at =
|
|
618
|
-
WHERE id =
|
|
619
|
-
AND status_state IN
|
|
620
|
-
AND created_at <=
|
|
621
|
-
args: [JSON.stringify(message), timestamp, now, id, createdAtCutoff],
|
|
622
|
-
});
|
|
521
|
+
status_message = ${sql.value(JSON.stringify(message))},
|
|
522
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
523
|
+
updated_at = ${sql.value(now)}
|
|
524
|
+
WHERE id = ${sql.value(id)}
|
|
525
|
+
AND status_state IN ${taskIn("failStuckQueued")}
|
|
526
|
+
AND created_at <= ${sql.value(createdAtCutoff)}`);
|
|
623
527
|
const affected = getAffectedRowCount(result);
|
|
624
528
|
if (affected === 1) {
|
|
625
529
|
await revokeTaskExecutionLease(tx, leaseThreadId, id);
|
|
@@ -644,25 +548,15 @@ export async function failStaleA2ATask(id, staleBefore, reason, errorCode) {
|
|
|
644
548
|
return withDbTransaction(client, async (tx) => {
|
|
645
549
|
const leaseThreadId = a2aTaskLeaseThreadId(id);
|
|
646
550
|
await lockTaskExecutionLease(tx, leaseThreadId, id);
|
|
647
|
-
const result = await tx.execute(
|
|
648
|
-
sql: `UPDATE a2a_tasks
|
|
551
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks
|
|
649
552
|
SET status_state = ${taskTarget("failStale")},
|
|
650
|
-
status_message =
|
|
651
|
-
status_timestamp =
|
|
652
|
-
updated_at =
|
|
653
|
-
WHERE id =
|
|
654
|
-
AND status_state IN
|
|
655
|
-
AND created_at <
|
|
656
|
-
AND updated_at <
|
|
657
|
-
args: [
|
|
658
|
-
JSON.stringify(message),
|
|
659
|
-
timestamp,
|
|
660
|
-
now,
|
|
661
|
-
id,
|
|
662
|
-
staleBefore,
|
|
663
|
-
staleBefore,
|
|
664
|
-
],
|
|
665
|
-
});
|
|
553
|
+
status_message = ${sql.value(JSON.stringify(message))},
|
|
554
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
555
|
+
updated_at = ${sql.value(now)}
|
|
556
|
+
WHERE id = ${sql.value(id)}
|
|
557
|
+
AND status_state IN ${taskIn("failStale")}
|
|
558
|
+
AND created_at < ${sql.value(staleBefore)}
|
|
559
|
+
AND updated_at < ${sql.value(staleBefore)}`);
|
|
666
560
|
const affected = getAffectedRowCount(result);
|
|
667
561
|
if (affected === 1) {
|
|
668
562
|
await revokeTaskExecutionLease(tx, leaseThreadId, id);
|
|
@@ -674,10 +568,7 @@ export async function getTask(id, accessScope) {
|
|
|
674
568
|
await ensureTable();
|
|
675
569
|
const client = getDbExec();
|
|
676
570
|
const predicate = taskAccessPredicate(accessScope);
|
|
677
|
-
const { rows } = await client.execute({
|
|
678
|
-
sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
|
|
679
|
-
args: [id, ...predicate.args],
|
|
680
|
-
});
|
|
571
|
+
const { rows } = await client.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
|
|
681
572
|
if (rows.length === 0)
|
|
682
573
|
return null;
|
|
683
574
|
return taskFromRow(rows[0]);
|
|
@@ -688,10 +579,7 @@ export async function updateTask(id, update, accessScope) {
|
|
|
688
579
|
await ensureTable();
|
|
689
580
|
const predicate = taskAccessPredicate(accessScope);
|
|
690
581
|
return withFencedExecutionWrite(async (tx) => {
|
|
691
|
-
const { rows } = await tx.execute({
|
|
692
|
-
sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
|
|
693
|
-
args: [id, ...predicate.args],
|
|
694
|
-
});
|
|
582
|
+
const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
|
|
695
583
|
if (rows.length === 0)
|
|
696
584
|
return null;
|
|
697
585
|
const task = taskFromRow(rows[0]);
|
|
@@ -712,27 +600,12 @@ export async function updateTask(id, update, accessScope) {
|
|
|
712
600
|
assertA2APersistablePayload(task.status.message, "A2A task status message");
|
|
713
601
|
assertA2APersistablePayload(task.history, "A2A task history");
|
|
714
602
|
assertA2APersistablePayload(task.artifacts, "A2A task artifacts");
|
|
715
|
-
const result = await tx.execute({
|
|
716
|
-
sql: `UPDATE a2a_tasks SET status_state = ?, status_message = ?, status_timestamp = ?, history = ?, artifacts = ?, updated_at = ? WHERE id = ?${predicate.sql} AND status_state <> ${taskSql("canceled")}`,
|
|
717
|
-
args: [
|
|
718
|
-
task.status.state,
|
|
719
|
-
task.status.message ? JSON.stringify(task.status.message) : null,
|
|
720
|
-
task.status.timestamp,
|
|
721
|
-
JSON.stringify(task.history),
|
|
722
|
-
JSON.stringify(task.artifacts),
|
|
723
|
-
now,
|
|
724
|
-
id,
|
|
725
|
-
...predicate.args,
|
|
726
|
-
],
|
|
727
|
-
});
|
|
603
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks SET status_state = ${sql.value(task.status.state)}, status_message = ${sql.value(task.status.message ? JSON.stringify(task.status.message) : null)}, status_timestamp = ${sql.value(task.status.timestamp)}, history = ${sql.value(JSON.stringify(task.history))}, artifacts = ${sql.value(JSON.stringify(task.artifacts))}, updated_at = ${sql.value(now)} WHERE id = ${sql.value(id)}${predicate} AND status_state <> ${taskSql("canceled")}`);
|
|
728
604
|
if (getAffectedRowCount(result) === 1)
|
|
729
605
|
return task;
|
|
730
606
|
// Zero rows: the task is missing, outside the access scope, or canceled.
|
|
731
607
|
// Only a canceled row is a cancel win; the others stay null.
|
|
732
|
-
const { rows: current } = await tx.execute({
|
|
733
|
-
sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql}`,
|
|
734
|
-
args: [id, ...predicate.args],
|
|
735
|
-
});
|
|
608
|
+
const { rows: current } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate}`);
|
|
736
609
|
if (current[0]) {
|
|
737
610
|
const stored = taskFromRow(current[0]);
|
|
738
611
|
if (stored.status.state === "canceled") {
|
|
@@ -752,23 +625,17 @@ export async function cancelA2ATask(id, accessScope) {
|
|
|
752
625
|
return withDbTransaction(client, async (tx) => {
|
|
753
626
|
const leaseThreadId = a2aTaskLeaseThreadId(id);
|
|
754
627
|
await lockTaskExecutionLease(tx, leaseThreadId, id);
|
|
755
|
-
const { rows } = await tx.execute({
|
|
756
|
-
sql: `SELECT * FROM a2a_tasks WHERE id = ?${predicate.sql} FOR UPDATE`,
|
|
757
|
-
args: [id, ...predicate.args],
|
|
758
|
-
});
|
|
628
|
+
const { rows } = await tx.execute(sql `SELECT * FROM a2a_tasks WHERE id = ${sql.value(id)}${predicate} FOR UPDATE`);
|
|
759
629
|
if (!rows[0])
|
|
760
630
|
return { status: "not_found" };
|
|
761
631
|
// The row lock from FOR UPDATE means the guarded UPDATE below sees this
|
|
762
632
|
// same state, so a zero-row update always means "not cancelable".
|
|
763
633
|
const current = taskFromRow(rows[0]);
|
|
764
634
|
const timestamp = new Date().toISOString();
|
|
765
|
-
const result = await tx.execute(
|
|
766
|
-
sql
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
AND status_state IN (${taskIn("cancel")})`,
|
|
770
|
-
args: [timestamp, Date.now(), id, ...predicate.args],
|
|
771
|
-
});
|
|
635
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks
|
|
636
|
+
SET status_state = ${taskTarget("cancel")}, status_timestamp = ${sql.value(timestamp)}, updated_at = ${sql.value(Date.now())}
|
|
637
|
+
WHERE id = ${sql.value(id)}${predicate}
|
|
638
|
+
AND status_state IN ${taskIn("cancel")}`);
|
|
772
639
|
if (getAffectedRowCount(result) !== 1) {
|
|
773
640
|
return { status: "not_cancelable", state: current.status.state };
|
|
774
641
|
}
|
|
@@ -821,26 +688,15 @@ export async function settleProcessingA2ATask(id, update) {
|
|
|
821
688
|
assertA2APersistablePayload(task.status.message, "A2A task status message");
|
|
822
689
|
assertA2APersistablePayload(task.history, "A2A task history");
|
|
823
690
|
assertA2APersistablePayload(task.artifacts, "A2A task artifacts");
|
|
824
|
-
const result = await tx.execute(
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
AND status_state = ${taskSql("processing")}`,
|
|
834
|
-
args: [
|
|
835
|
-
task.status.state,
|
|
836
|
-
task.status.message ? JSON.stringify(task.status.message) : null,
|
|
837
|
-
task.status.timestamp,
|
|
838
|
-
JSON.stringify(task.history),
|
|
839
|
-
JSON.stringify(task.artifacts),
|
|
840
|
-
now,
|
|
841
|
-
id,
|
|
842
|
-
],
|
|
843
|
-
});
|
|
691
|
+
const result = await tx.execute(sql `UPDATE a2a_tasks
|
|
692
|
+
SET status_state = ${sql.value(task.status.state)},
|
|
693
|
+
status_message = ${sql.value(task.status.message ? JSON.stringify(task.status.message) : null)},
|
|
694
|
+
status_timestamp = ${sql.value(task.status.timestamp)},
|
|
695
|
+
history = ${sql.value(JSON.stringify(task.history))},
|
|
696
|
+
artifacts = ${sql.value(JSON.stringify(task.artifacts))},
|
|
697
|
+
updated_at = ${sql.value(now)}
|
|
698
|
+
WHERE id = ${sql.value(id)}
|
|
699
|
+
AND status_state = ${taskSql("processing")}`);
|
|
844
700
|
const affected = getAffectedRowCount(result);
|
|
845
701
|
if (affected === 0)
|
|
846
702
|
return null;
|
|
@@ -852,15 +708,12 @@ export async function updateTaskStatusMessage(id, message) {
|
|
|
852
708
|
await ensureTable();
|
|
853
709
|
const now = Date.now();
|
|
854
710
|
const timestamp = new Date().toISOString();
|
|
855
|
-
await withFencedExecutionWrite((tx) => tx.execute(
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
AND status_state IN (${taskIn("failStale")})`,
|
|
862
|
-
args: [JSON.stringify(message), timestamp, now, id],
|
|
863
|
-
}), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
711
|
+
await withFencedExecutionWrite((tx) => tx.execute(sql `UPDATE a2a_tasks
|
|
712
|
+
SET status_message = ${sql.value(JSON.stringify(message))},
|
|
713
|
+
status_timestamp = ${sql.value(timestamp)},
|
|
714
|
+
updated_at = ${sql.value(now)}
|
|
715
|
+
WHERE id = ${sql.value(id)}
|
|
716
|
+
AND status_state IN ${taskIn("failStale")}`), { threadId: a2aTaskLeaseThreadId(id), turnId: id });
|
|
864
717
|
}
|
|
865
718
|
export async function listTasksPage(contextId, options = {}) {
|
|
866
719
|
await ensureTable();
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Classify provenance for approval policy; this does not authenticate a caller. */
|
|
2
|
+
export function isOutsideAgentCall(ctx) {
|
|
3
|
+
// CLI defaults to outside because coding agents drive it; Alice's decision is pending.
|
|
4
|
+
// Automation has no trusted origin in ctx yet; #8070's mcpManaged is job frontmatter.
|
|
5
|
+
return (ctx?.networkProtocol !== undefined ||
|
|
6
|
+
ctx?.automation !== undefined ||
|
|
7
|
+
(ctx?.caller !== "frontend" && ctx?.caller !== "tool"));
|
|
8
|
+
}
|
package/dist/action.d.ts
CHANGED
|
@@ -369,6 +369,7 @@ export interface ActionMcpAppResourceConfig {
|
|
|
369
369
|
title?: string;
|
|
370
370
|
description?: string;
|
|
371
371
|
html: string | ActionMcpAppHtmlBuilder;
|
|
372
|
+
requiresEmbedSession?: boolean;
|
|
372
373
|
mimeType?: typeof MCP_APP_MIME_TYPE;
|
|
373
374
|
_meta?: Record<string, unknown>;
|
|
374
375
|
csp?: ActionMcpAppCsp | ActionMcpAppCspBuilder;
|