@agent-native/core 0.201.1 → 0.202.0-nightly-20261006033736
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/automation/index.d.ts +1 -1
- package/dist/client/analytics/index.d.ts +1 -1
- package/dist/client/analytics/index.js +1 -1
- package/dist/client/analytics.d.ts +23 -3
- package/dist/client/analytics.js +189 -46
- package/dist/client/client-status-requests.d.ts +4 -1
- package/dist/client/client-status-requests.js +21 -5
- package/dist/client/embed-auth.d.ts +6 -0
- package/dist/client/embed-auth.js +13 -0
- package/dist/client/session-replay.js +48 -22
- package/dist/client/sharing/index.d.ts +2 -0
- package/dist/client/sharing/index.js +2 -0
- package/dist/client/sharing/useAccessRequestReview.d.ts +80 -0
- package/dist/client/sharing/useAccessRequestReview.js +100 -0
- package/dist/client/sharing/useResourceAccessGate.d.ts +57 -0
- package/dist/client/sharing/useResourceAccessGate.js +76 -0
- package/dist/client/use-agent-engine-configured.d.ts +2 -0
- package/dist/client/use-agent-engine-configured.js +4 -1
- package/dist/email-catalog/registry.d.ts +1 -1
- package/dist/email-catalog/registry.js +1 -1
- package/dist/email-catalog/system-emails.d.ts +2 -2
- package/dist/email-catalog/system-emails.js +47 -2
- package/dist/email-catalog/templates.d.ts +5 -1
- package/dist/email-catalog/templates.js +11 -1
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/framework-tools.js +6 -0
- package/dist/identity/rekey.js +9 -0
- package/dist/jobs/run-history.d.ts +27 -8
- package/dist/jobs/run-history.js +17 -10
- package/dist/jobs/scheduler.js +39 -10
- package/dist/mcp/build-server.d.ts +1 -0
- package/dist/mcp/build-server.js +30 -7
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/routes.d.ts +7 -7
- package/dist/org/index.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +10 -10
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/review/suggestions/actions.js +14 -35
- package/dist/review/suggestions/store.d.ts +0 -1
- package/dist/review/suggestions/store.js +0 -7
- package/dist/secrets/routes.d.ts +11 -11
- package/dist/server/action-discovery.js +24 -0
- package/dist/server/agent-access.js +7 -3
- package/dist/server/agent-chat/mcp-options.d.ts +1 -0
- 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 +1 -1
- package/dist/server/attribution.d.ts +33 -1
- package/dist/server/attribution.js +93 -21
- package/dist/server/auth.js +35 -11
- package/dist/server/email-templates.d.ts +34 -0
- package/dist/server/email-templates.js +40 -0
- package/dist/server/magic-link-attribution.js +2 -1
- package/dist/server/onboarding-html.js +35 -67
- package/dist/server/release-schema.js +4 -0
- package/dist/server/short-lived-token.d.ts +7 -0
- package/dist/server/short-lived-token.js +59 -0
- package/dist/shared/analytics-anonymous-id.d.ts +1 -0
- package/dist/shared/analytics-anonymous-id.js +1 -1
- package/dist/shared/attribution-source.d.ts +30 -0
- package/dist/shared/attribution-source.js +65 -0
- package/dist/sharing/access-request-store.d.ts +96 -0
- package/dist/sharing/access-request-store.js +213 -0
- package/dist/sharing/access-requests.d.ts +113 -0
- package/dist/sharing/access-requests.js +490 -0
- package/dist/sharing/access.d.ts +36 -2
- package/dist/sharing/access.js +74 -12
- package/dist/sharing/actions/approve-resource-access-request.d.ts +10 -0
- package/dist/sharing/actions/approve-resource-access-request.js +15 -0
- package/dist/sharing/actions/decline-resource-access-request.d.ts +7 -0
- package/dist/sharing/actions/decline-resource-access-request.js +14 -0
- package/dist/sharing/actions/get-resource-access-request.d.ts +4 -0
- package/dist/sharing/actions/get-resource-access-request.js +13 -0
- package/dist/sharing/actions/get-resource-access-status.d.ts +5 -0
- package/dist/sharing/actions/get-resource-access-status.js +19 -0
- package/dist/sharing/actions/list-resource-access-requests.d.ts +5 -0
- package/dist/sharing/actions/list-resource-access-requests.js +16 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/sharing/actions/request-resource-access.d.ts +6 -0
- package/dist/sharing/actions/request-resource-access.js +17 -0
- package/dist/sharing/actions/share-resource.d.ts +1 -1
- package/dist/sharing/actions/share-resource.js +18 -144
- package/dist/sharing/grant.d.ts +49 -0
- package/dist/sharing/grant.js +195 -0
- package/dist/sharing/index.d.ts +2 -1
- package/dist/sharing/index.js +2 -1
- package/dist/sharing/registry.d.ts +36 -0
- package/dist/templates/chat/server/plugins/auth.ts +2 -2
- package/dist/templates/default/app/routes/access-requests.$requestId.tsx +7 -0
- package/dist/templates/default/server/plugins/auth.ts +2 -2
- package/dist/vite/action-types-plugin.js +24 -0
- package/package.json +11 -3
- package/src/templates/chat/server/plugins/auth.ts +2 -2
- package/src/templates/default/app/routes/access-requests.$requestId.tsx +7 -0
- package/src/templates/default/server/plugins/auth.ts +2 -2
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { ResourceAccessRequestFailure } from "./useResourceAccessGate.js";
|
|
2
|
+
export type AccessRequestRole = "viewer" | "commenter" | "editor" | "admin";
|
|
3
|
+
/** One access request, as someone who manages access reviews it. */
|
|
4
|
+
export interface AccessRequestReview {
|
|
5
|
+
id: string;
|
|
6
|
+
generation: number;
|
|
7
|
+
state: "pending" | "approved" | "declined";
|
|
8
|
+
requester: {
|
|
9
|
+
email: string;
|
|
10
|
+
name: string | null;
|
|
11
|
+
};
|
|
12
|
+
note: string | null;
|
|
13
|
+
requestedAt: string;
|
|
14
|
+
decidedAt: string | null;
|
|
15
|
+
grantedRole: AccessRequestRole | null;
|
|
16
|
+
resource: {
|
|
17
|
+
type: string;
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
title: string;
|
|
21
|
+
path: string | null;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface AccessRequestDecisionFailure extends ResourceAccessRequestFailure {
|
|
25
|
+
/**
|
|
26
|
+
* Why the server refused, such as a sharing rule. Absent for unexpected
|
|
27
|
+
* failures, whose server message isn't meant for people.
|
|
28
|
+
*/
|
|
29
|
+
message: string | null;
|
|
30
|
+
}
|
|
31
|
+
type DecidedRequest = Pick<AccessRequestReview, "id" | "generation" | "requester">;
|
|
32
|
+
export interface AccessRequestDecisions {
|
|
33
|
+
approve: (request: DecidedRequest, role: AccessRequestRole) => Promise<void>;
|
|
34
|
+
decline: (request: DecidedRequest) => Promise<void>;
|
|
35
|
+
/** The request a decision is in flight for. */
|
|
36
|
+
pendingId: string | null;
|
|
37
|
+
error: AccessRequestDecisionFailure | null;
|
|
38
|
+
/** An allowed request whose requester couldn't be emailed. */
|
|
39
|
+
unemailed: Pick<AccessRequestReview, "id" | "requester"> | null;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Allow and Decline, shared by the approval page and the Share panels. A
|
|
43
|
+
* decision someone else already made calls `onStale`, so the caller reloads
|
|
44
|
+
* instead of offering the same outdated request again.
|
|
45
|
+
*/
|
|
46
|
+
export declare function useAccessRequestDecisions(onStale: () => unknown): AccessRequestDecisions;
|
|
47
|
+
export interface AccessRequestReviewController {
|
|
48
|
+
review: AccessRequestReview | undefined;
|
|
49
|
+
isLoading: boolean;
|
|
50
|
+
/** The viewer isn't signed in. */
|
|
51
|
+
isSignedOut: boolean;
|
|
52
|
+
/** The request doesn't exist, or the viewer can't manage its resource. */
|
|
53
|
+
isUnavailable: boolean;
|
|
54
|
+
/** Reading the request failed for another reason; retry with `refetch`. */
|
|
55
|
+
isError: boolean;
|
|
56
|
+
refetch: () => Promise<unknown>;
|
|
57
|
+
decisions: AccessRequestDecisions;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Loads one access request for its approval page. Opening the page only
|
|
61
|
+
* reads; Allow and Decline are explicit calls on `decisions`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function useAccessRequestReview(requestId: string): AccessRequestReviewController;
|
|
64
|
+
export interface ResourceAccessRequestsController {
|
|
65
|
+
/** The newest pending requests. */
|
|
66
|
+
requests: AccessRequestReview[];
|
|
67
|
+
/** Older pending requests exist beyond `requests`. */
|
|
68
|
+
hasMore: boolean;
|
|
69
|
+
isLoading: boolean;
|
|
70
|
+
isError: boolean;
|
|
71
|
+
refetch: () => Promise<unknown>;
|
|
72
|
+
decisions: AccessRequestDecisions;
|
|
73
|
+
}
|
|
74
|
+
/** Pending access requests for one resource, for its Share panel. */
|
|
75
|
+
export declare function useResourceAccessRequests({ resourceType, resourceId, enabled, }: {
|
|
76
|
+
resourceType: string;
|
|
77
|
+
resourceId: string;
|
|
78
|
+
enabled?: boolean;
|
|
79
|
+
}): ResourceAccessRequestsController;
|
|
80
|
+
export {};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
3
|
+
function decisionFailure(error) {
|
|
4
|
+
if (!error)
|
|
5
|
+
return null;
|
|
6
|
+
const failure = error;
|
|
7
|
+
const refused = failure.status === 400 || failure.status === 403;
|
|
8
|
+
return {
|
|
9
|
+
errorCode: typeof failure.errorCode === "string" ? failure.errorCode : null,
|
|
10
|
+
message: refused && typeof failure.actionMessage === "string"
|
|
11
|
+
? failure.actionMessage
|
|
12
|
+
: null,
|
|
13
|
+
retryAt: typeof failure.details?.retryAt === "string"
|
|
14
|
+
? failure.details.retryAt
|
|
15
|
+
: null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Allow and Decline, shared by the approval page and the Share panels. A
|
|
20
|
+
* decision someone else already made calls `onStale`, so the caller reloads
|
|
21
|
+
* instead of offering the same outdated request again.
|
|
22
|
+
*/
|
|
23
|
+
export function useAccessRequestDecisions(onStale) {
|
|
24
|
+
const { mutateAsync: approveAsync } = useActionMutation("approve-resource-access-request");
|
|
25
|
+
const { mutateAsync: declineAsync } = useActionMutation("decline-resource-access-request");
|
|
26
|
+
const [pendingId, setPendingId] = useState(null);
|
|
27
|
+
const [error, setError] = useState(null);
|
|
28
|
+
const [unemailed, setUnemailed] = useState(null);
|
|
29
|
+
const decide = useCallback(async (requestId, run) => {
|
|
30
|
+
setPendingId(requestId);
|
|
31
|
+
setError(null);
|
|
32
|
+
setUnemailed(null);
|
|
33
|
+
try {
|
|
34
|
+
await run();
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
setError(err);
|
|
38
|
+
if (err.errorCode === "access_request_stale") {
|
|
39
|
+
void onStale();
|
|
40
|
+
}
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
setPendingId((current) => (current === requestId ? null : current));
|
|
45
|
+
}
|
|
46
|
+
}, [onStale]);
|
|
47
|
+
const approve = useCallback((request, role) => decide(request.id, async () => {
|
|
48
|
+
const result = await approveAsync({
|
|
49
|
+
requestId: request.id,
|
|
50
|
+
generation: request.generation,
|
|
51
|
+
role,
|
|
52
|
+
});
|
|
53
|
+
if (result?.email === "failed") {
|
|
54
|
+
setUnemailed({ id: request.id, requester: request.requester });
|
|
55
|
+
}
|
|
56
|
+
}), [approveAsync, decide]);
|
|
57
|
+
const decline = useCallback((request) => decide(request.id, () => declineAsync({ requestId: request.id, generation: request.generation })), [declineAsync, decide]);
|
|
58
|
+
return {
|
|
59
|
+
approve,
|
|
60
|
+
decline,
|
|
61
|
+
pendingId,
|
|
62
|
+
error: decisionFailure(error),
|
|
63
|
+
unemailed,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Loads one access request for its approval page. Opening the page only
|
|
68
|
+
* reads; Allow and Decline are explicit calls on `decisions`.
|
|
69
|
+
*/
|
|
70
|
+
export function useAccessRequestReview(requestId) {
|
|
71
|
+
const params = useMemo(() => ({ requestId }), [requestId]);
|
|
72
|
+
const query = useActionQuery("get-resource-access-request", params, { enabled: Boolean(requestId), retry: false });
|
|
73
|
+
const decisions = useAccessRequestDecisions(query.refetch);
|
|
74
|
+
const status = query.error?.status;
|
|
75
|
+
const isSignedOut = query.isError && status === 401;
|
|
76
|
+
const isUnavailable = query.isError && status === 404;
|
|
77
|
+
return {
|
|
78
|
+
review: query.data,
|
|
79
|
+
isLoading: query.isLoading,
|
|
80
|
+
isSignedOut,
|
|
81
|
+
isUnavailable,
|
|
82
|
+
isError: query.isError && !isSignedOut && !isUnavailable,
|
|
83
|
+
refetch: query.refetch,
|
|
84
|
+
decisions,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/** Pending access requests for one resource, for its Share panel. */
|
|
88
|
+
export function useResourceAccessRequests({ resourceType, resourceId, enabled = true, }) {
|
|
89
|
+
const params = useMemo(() => ({ resourceType, resourceId }), [resourceId, resourceType]);
|
|
90
|
+
const query = useActionQuery("list-resource-access-requests", params, { enabled, retry: false });
|
|
91
|
+
const decisions = useAccessRequestDecisions(query.refetch);
|
|
92
|
+
return {
|
|
93
|
+
requests: query.data?.requests ?? [],
|
|
94
|
+
hasMore: query.data?.hasMore ?? false,
|
|
95
|
+
isLoading: query.isLoading,
|
|
96
|
+
isError: query.isError,
|
|
97
|
+
refetch: query.refetch,
|
|
98
|
+
decisions,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Mirrors the server's `ResourceAccessState`. */
|
|
2
|
+
export type ResourceAccessGateState = "allowed" | "trashed" | "denied" | "missing" | "signed-out";
|
|
3
|
+
export type ResourceAccessGateRole = "owner" | "admin" | "editor" | "commenter" | "viewer";
|
|
4
|
+
/** The viewer's own open request for access. */
|
|
5
|
+
export interface ResourceAccessGateRequest {
|
|
6
|
+
state: "pending";
|
|
7
|
+
requestedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ResourceAccessGateStatus {
|
|
10
|
+
state: ResourceAccessGateState;
|
|
11
|
+
/** The viewer's role, only when they can open the resource. */
|
|
12
|
+
role?: ResourceAccessGateRole;
|
|
13
|
+
/** Whether the viewer can ask for access now. Only for `denied`. */
|
|
14
|
+
canRequest?: boolean;
|
|
15
|
+
/** The viewer's open request. Only for `denied`. */
|
|
16
|
+
request?: ResourceAccessGateRequest;
|
|
17
|
+
}
|
|
18
|
+
/** Why asking for access failed, for the screen to explain. */
|
|
19
|
+
export interface ResourceAccessRequestFailure {
|
|
20
|
+
/** The server's error code, such as `access_request_rate_limited`. */
|
|
21
|
+
errorCode: string | null;
|
|
22
|
+
/** When the viewer can try again, if the server said. */
|
|
23
|
+
retryAt: string | null;
|
|
24
|
+
}
|
|
25
|
+
export interface ResourceAccessGateOptions {
|
|
26
|
+
resourceType: string;
|
|
27
|
+
resourceId: string;
|
|
28
|
+
enabled?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Called once when the status says the viewer can open the resource: either
|
|
31
|
+
* the read that failed should be tried again, or the owner shared it while
|
|
32
|
+
* this screen was open. The status is checked again whenever the window
|
|
33
|
+
* regains focus, including switching back from another browser window, and
|
|
34
|
+
* every half minute while the viewer's request is open.
|
|
35
|
+
*/
|
|
36
|
+
onAccessGranted?: () => void;
|
|
37
|
+
}
|
|
38
|
+
export interface ResourceAccessGateController {
|
|
39
|
+
status: ResourceAccessGateStatus | undefined;
|
|
40
|
+
isLoading: boolean;
|
|
41
|
+
isError: boolean;
|
|
42
|
+
refetch: () => Promise<unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Asks the owner for access, with an optional note. Resolves once the
|
|
45
|
+
* request is stored and the status shows it; rejects when it fails, with
|
|
46
|
+
* the reason in `requestError`.
|
|
47
|
+
*/
|
|
48
|
+
requestAccess: (note?: string) => Promise<void>;
|
|
49
|
+
isRequesting: boolean;
|
|
50
|
+
requestError: ResourceAccessRequestFailure | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Asks the server what a link the viewer couldn't open should say. Use it
|
|
54
|
+
* after a resource read fails with 403 or 404, then render the matching
|
|
55
|
+
* access screen.
|
|
56
|
+
*/
|
|
57
|
+
export declare function useResourceAccessGate({ resourceType, resourceId, enabled, onAccessGranted, }: ResourceAccessGateOptions): ResourceAccessGateController;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { forgetAuthFailures } from "../embed-auth.js";
|
|
3
|
+
import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
4
|
+
// While a request is open, approving it should open the resource without a
|
|
5
|
+
// manual reload, even when the window never loses focus.
|
|
6
|
+
const PENDING_REQUEST_POLL_MS = 30_000;
|
|
7
|
+
function requestFailure(error) {
|
|
8
|
+
const failure = error;
|
|
9
|
+
return {
|
|
10
|
+
errorCode: typeof failure.errorCode === "string" ? failure.errorCode : null,
|
|
11
|
+
retryAt: typeof failure.details?.retryAt === "string"
|
|
12
|
+
? failure.details.retryAt
|
|
13
|
+
: null,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Asks the server what a link the viewer couldn't open should say. Use it
|
|
18
|
+
* after a resource read fails with 403 or 404, then render the matching
|
|
19
|
+
* access screen.
|
|
20
|
+
*/
|
|
21
|
+
export function useResourceAccessGate({ resourceType, resourceId, enabled = true, onAccessGranted, }) {
|
|
22
|
+
const params = useMemo(() => ({ resourceType, resourceId }), [resourceId, resourceType]);
|
|
23
|
+
const query = useActionQuery("get-resource-access-status", params, {
|
|
24
|
+
enabled,
|
|
25
|
+
refetchOnWindowFocus: "always",
|
|
26
|
+
staleTime: 0,
|
|
27
|
+
refetchInterval: (current) => current.state.data?.request ? PENDING_REQUEST_POLL_MS : false,
|
|
28
|
+
});
|
|
29
|
+
const request = useActionMutation("request-resource-access");
|
|
30
|
+
const state = query.data?.state;
|
|
31
|
+
const onAccessGrantedRef = useRef(onAccessGranted);
|
|
32
|
+
onAccessGrantedRef.current = onAccessGranted;
|
|
33
|
+
const refetchRef = useRef(query.refetch);
|
|
34
|
+
refetchRef.current = query.refetch;
|
|
35
|
+
const target = `${resourceType}:${resourceId}`;
|
|
36
|
+
const lastSeenRef = useRef(null);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (!state)
|
|
39
|
+
return;
|
|
40
|
+
const previous = lastSeenRef.current?.target === target ? lastSeenRef.current.state : null;
|
|
41
|
+
lastSeenRef.current = { target, state };
|
|
42
|
+
if (state === "allowed" && previous !== "allowed") {
|
|
43
|
+
forgetAuthFailures();
|
|
44
|
+
onAccessGrantedRef.current?.();
|
|
45
|
+
}
|
|
46
|
+
}, [target, state]);
|
|
47
|
+
// React Query refetches when the tab becomes visible, but not when focus
|
|
48
|
+
// returns from another window that left this tab visible, such as the
|
|
49
|
+
// owner's window beside it.
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (!enabled)
|
|
52
|
+
return;
|
|
53
|
+
const refetch = () => void refetchRef.current({ cancelRefetch: false });
|
|
54
|
+
window.addEventListener("focus", refetch);
|
|
55
|
+
return () => window.removeEventListener("focus", refetch);
|
|
56
|
+
}, [enabled]);
|
|
57
|
+
const { mutateAsync: requestAsync } = request;
|
|
58
|
+
const requestAccess = useCallback(async (note) => {
|
|
59
|
+
const trimmed = note?.trim();
|
|
60
|
+
await requestAsync({
|
|
61
|
+
resourceType,
|
|
62
|
+
resourceId,
|
|
63
|
+
...(trimmed ? { note: trimmed } : {}),
|
|
64
|
+
});
|
|
65
|
+
await refetchRef.current({ cancelRefetch: false });
|
|
66
|
+
}, [requestAsync, resourceId, resourceType]);
|
|
67
|
+
return {
|
|
68
|
+
status: query.data,
|
|
69
|
+
isLoading: query.isLoading,
|
|
70
|
+
isError: query.isError,
|
|
71
|
+
refetch: query.refetch,
|
|
72
|
+
requestAccess,
|
|
73
|
+
isRequesting: request.isPending,
|
|
74
|
+
requestError: request.error ? requestFailure(request.error) : null,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -16,6 +16,8 @@ export interface UseAgentEngineConfiguredResult {
|
|
|
16
16
|
export interface FetchAgentEngineConfiguredStateOptions {
|
|
17
17
|
/** Kept for API compatibility; readiness always comes from chatEligible. */
|
|
18
18
|
missingFallback?: boolean;
|
|
19
|
+
/** Starts a new status read instead of joining an older in-flight probe. */
|
|
20
|
+
fresh?: boolean;
|
|
19
21
|
timeoutMs?: number;
|
|
20
22
|
}
|
|
21
23
|
export interface UseAgentEngineConfiguredOptions {
|
|
@@ -49,7 +49,10 @@ export async function fetchAgentEngineConfiguredState(enabled = true, options) {
|
|
|
49
49
|
const timeoutMs = typeof options?.timeoutMs === "number" && options.timeoutMs > 0
|
|
50
50
|
? options.timeoutMs
|
|
51
51
|
: undefined;
|
|
52
|
-
|
|
52
|
+
let engineResult = await waitForStatus(fetchAgentEngineStatus({ fresh: options?.fresh }), "/_agent-native/agent-engine/status", timeoutMs);
|
|
53
|
+
while (engineResult.state === "unavailable" && engineResult.stale) {
|
|
54
|
+
engineResult = await waitForStatus(fetchAgentEngineStatus(), "/_agent-native/agent-engine/status", timeoutMs);
|
|
55
|
+
}
|
|
53
56
|
if (engineResult.state !== "available" ||
|
|
54
57
|
!hasChatEligibleFlag(engineResult.value)) {
|
|
55
58
|
// A reachable legacy server may expose only the broad `configured` flag.
|
|
@@ -26,6 +26,6 @@ export declare function renderTransactionalEmailPreview(id: string): RenderedEma
|
|
|
26
26
|
* synchronous `renderTransactionalEmailPreview` cannot.
|
|
27
27
|
*/
|
|
28
28
|
export declare function renderTransactionalEmailPreviewAsync(id: string): Promise<RenderedEmailMessage>;
|
|
29
|
-
export { CORE_RESOURCE_SHARED_EMAIL_ID, overrideTransactionalEmail, removeTransactionalEmailOverride, type CoreTransactionalEmailArgs, type CoreTransactionalEmailId, type CoreTransactionalEmailProps, type TransactionalEmailOverride, type TransactionalEmailOverrideResult, } from "./templates.js";
|
|
29
|
+
export { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, overrideTransactionalEmail, removeTransactionalEmailOverride, type CoreTransactionalEmailArgs, type CoreTransactionalEmailId, type CoreTransactionalEmailProps, type TransactionalEmailOverride, type TransactionalEmailOverrideResult, } from "./templates.js";
|
|
30
30
|
export { escapeEmailHtml } from "../server/email-template.js";
|
|
31
31
|
export declare function resetTransactionalEmailRegistry(): void;
|
|
@@ -104,7 +104,7 @@ export async function renderTransactionalEmailPreviewAsync(id) {
|
|
|
104
104
|
? definition.previewAsync()
|
|
105
105
|
: definition.preview();
|
|
106
106
|
}
|
|
107
|
-
export { CORE_RESOURCE_SHARED_EMAIL_ID, overrideTransactionalEmail, removeTransactionalEmailOverride, } from "./templates.js";
|
|
107
|
+
export { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, overrideTransactionalEmail, removeTransactionalEmailOverride, } from "./templates.js";
|
|
108
108
|
export { escapeEmailHtml } from "../server/email-template.js";
|
|
109
109
|
export function resetTransactionalEmailRegistry() {
|
|
110
110
|
registry.clear();
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID } from "./templates.js";
|
|
2
|
-
export { CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, };
|
|
1
|
+
import { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID } from "./templates.js";
|
|
2
|
+
export { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, };
|
|
3
3
|
export declare function registerCoreSystemEmails(): void;
|
|
@@ -2,10 +2,10 @@ import { BILLING_NOTICE_MESSAGES } from "../localization/billing-notice-messages
|
|
|
2
2
|
import { resolveEmailBrandApp } from "../server/email-templates.js";
|
|
3
3
|
import { builderSubscriptionUpgradeUrl } from "../shared/builder-link-tracking.js";
|
|
4
4
|
import { defineTransactionalEmail } from "./registry.js";
|
|
5
|
-
import { CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, renderDefaultTransactionalEmail, renderTransactionalEmail, } from "./templates.js";
|
|
5
|
+
import { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, renderDefaultTransactionalEmail, renderTransactionalEmail, } from "./templates.js";
|
|
6
6
|
const SAMPLE_URL = "https://example.com/accept/sample-token";
|
|
7
7
|
const SAMPLE_EMAIL = "sam.rivera@example.com";
|
|
8
|
-
export { CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, };
|
|
8
|
+
export { CORE_ACCESS_GRANTED_EMAIL_ID, CORE_ACCESS_REQUESTED_EMAIL_ID, CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID, CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID, CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID, CORE_INVITE_EMAIL_ID, CORE_MAGIC_LINK_EMAIL_ID, CORE_RESET_PASSWORD_EMAIL_ID, CORE_RESOURCE_SHARED_EMAIL_ID, CORE_VERIFY_SIGNUP_EMAIL_ID, };
|
|
9
9
|
function corePreview(id, sample) {
|
|
10
10
|
return {
|
|
11
11
|
preview: () => renderDefaultTransactionalEmail(id, sample()),
|
|
@@ -130,6 +130,51 @@ export function registerCoreSystemEmails() {
|
|
|
130
130
|
app: resolveEmailBrandApp(),
|
|
131
131
|
})),
|
|
132
132
|
});
|
|
133
|
+
defineTransactionalEmail({
|
|
134
|
+
id: CORE_ACCESS_REQUESTED_EMAIL_ID,
|
|
135
|
+
app: "core",
|
|
136
|
+
name: "Access requested",
|
|
137
|
+
trigger: "A signed-in person who can't open a resource asks for access, in an app whose resource type takes requests. Asking again while the request is pending sends nothing.",
|
|
138
|
+
recipientLabel: "Owner and admins",
|
|
139
|
+
recipient: "The resource owner and each person with admin on it. Synthetic QA addresses are skipped.",
|
|
140
|
+
senderLabel: "Default, resource-branded",
|
|
141
|
+
sender: "The configured EMAIL_FROM, with reply-to set to the requester's signed-in address. A resource registration can set the brand name and logo.",
|
|
142
|
+
...corePreview(CORE_ACCESS_REQUESTED_EMAIL_ID, () => ({
|
|
143
|
+
recipientEmail: SAMPLE_EMAIL,
|
|
144
|
+
requester: { name: "Alex Chen", email: "alex.chen@example.com" },
|
|
145
|
+
resource: {
|
|
146
|
+
type: "document",
|
|
147
|
+
label: "Document",
|
|
148
|
+
title: "Launch plan",
|
|
149
|
+
url: SAMPLE_URL,
|
|
150
|
+
},
|
|
151
|
+
reviewUrl: SAMPLE_URL,
|
|
152
|
+
note: "I'm presenting the rollout on Friday.",
|
|
153
|
+
app: resolveEmailBrandApp(),
|
|
154
|
+
})),
|
|
155
|
+
});
|
|
156
|
+
defineTransactionalEmail({
|
|
157
|
+
id: CORE_ACCESS_GRANTED_EMAIL_ID,
|
|
158
|
+
app: "core",
|
|
159
|
+
name: "Access granted",
|
|
160
|
+
trigger: "Someone who manages access to a resource allows a pending access request.",
|
|
161
|
+
recipientLabel: "Requester",
|
|
162
|
+
recipient: "The signed-in address that asked for access. Synthetic QA addresses are skipped.",
|
|
163
|
+
senderLabel: "Default, resource-branded",
|
|
164
|
+
sender: "The configured EMAIL_FROM. A resource registration can set the brand name and logo.",
|
|
165
|
+
...corePreview(CORE_ACCESS_GRANTED_EMAIL_ID, () => ({
|
|
166
|
+
recipientEmail: SAMPLE_EMAIL,
|
|
167
|
+
approver: { name: "Alex Chen", email: "alex.chen@example.com" },
|
|
168
|
+
resource: {
|
|
169
|
+
type: "document",
|
|
170
|
+
label: "Document",
|
|
171
|
+
title: "Launch plan",
|
|
172
|
+
url: SAMPLE_URL,
|
|
173
|
+
},
|
|
174
|
+
role: "viewer",
|
|
175
|
+
app: resolveEmailBrandApp(),
|
|
176
|
+
})),
|
|
177
|
+
});
|
|
133
178
|
defineTransactionalEmail({
|
|
134
179
|
id: CORE_MAGIC_LINK_EMAIL_ID,
|
|
135
180
|
app: "core",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ReactElement } from "react";
|
|
2
2
|
import { type EmailTemplateApp } from "../server/email-template.js";
|
|
3
|
-
import { type RenderBuilderCreditLimitEmailArgs, type RenderChangeEmailConfirmationArgs, type RenderChangeEmailVerificationArgs, type RenderedEmailMessage, type RenderInviteEmailArgs, type RenderMagicLinkEmailArgs, type RenderResetPasswordEmailArgs, type RenderResourceSharedEmailArgs, type RenderVerifySignupEmailArgs } from "../server/email-templates.js";
|
|
3
|
+
import { type RenderAccessGrantedEmailArgs, type RenderAccessRequestedEmailArgs, type RenderBuilderCreditLimitEmailArgs, type RenderChangeEmailConfirmationArgs, type RenderChangeEmailVerificationArgs, type RenderedEmailMessage, type RenderInviteEmailArgs, type RenderMagicLinkEmailArgs, type RenderResetPasswordEmailArgs, type RenderResourceSharedEmailArgs, type RenderVerifySignupEmailArgs } from "../server/email-templates.js";
|
|
4
4
|
export declare const CORE_INVITE_EMAIL_ID = "core.organization-invite";
|
|
5
5
|
export declare const CORE_VERIFY_SIGNUP_EMAIL_ID = "core.verify-signup";
|
|
6
6
|
export declare const CORE_RESET_PASSWORD_EMAIL_ID = "core.reset-password";
|
|
@@ -9,6 +9,8 @@ export declare const CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID = "core.change-emai
|
|
|
9
9
|
export declare const CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID = "core.change-email-verification";
|
|
10
10
|
export declare const CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID = "core.builder-credit-limit";
|
|
11
11
|
export declare const CORE_RESOURCE_SHARED_EMAIL_ID = "core.resource-shared";
|
|
12
|
+
export declare const CORE_ACCESS_REQUESTED_EMAIL_ID = "core.access-requested";
|
|
13
|
+
export declare const CORE_ACCESS_GRANTED_EMAIL_ID = "core.access-granted";
|
|
12
14
|
/**
|
|
13
15
|
* Data each framework email is rendered from, keyed by catalog id. An
|
|
14
16
|
* override receives these values raw — escape them before interpolating into
|
|
@@ -23,6 +25,8 @@ export interface CoreTransactionalEmailArgs {
|
|
|
23
25
|
[CORE_INVITE_EMAIL_ID]: RenderInviteEmailArgs;
|
|
24
26
|
[CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID]: RenderBuilderCreditLimitEmailArgs;
|
|
25
27
|
[CORE_RESOURCE_SHARED_EMAIL_ID]: RenderResourceSharedEmailArgs;
|
|
28
|
+
[CORE_ACCESS_REQUESTED_EMAIL_ID]: RenderAccessRequestedEmailArgs;
|
|
29
|
+
[CORE_ACCESS_GRANTED_EMAIL_ID]: RenderAccessGrantedEmailArgs;
|
|
26
30
|
}
|
|
27
31
|
export type CoreTransactionalEmailId = keyof CoreTransactionalEmailArgs;
|
|
28
32
|
export type CoreTransactionalEmailProps<Id extends CoreTransactionalEmailId> = CoreTransactionalEmailArgs[Id] & {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { emailHtmlToText, } from "../server/email-template.js";
|
|
2
|
-
import { renderBuilderCreditLimitEmail, renderChangeEmailConfirmationEmail, renderChangeEmailVerificationEmail, renderInviteEmail, renderMagicLinkEmail, renderResetPasswordEmail, renderResourceSharedEmail, renderVerifySignupEmail, resolveEmailApp, resolveEmailBrandApp, } from "../server/email-templates.js";
|
|
2
|
+
import { renderAccessGrantedEmail, renderAccessRequestedEmail, renderBuilderCreditLimitEmail, renderChangeEmailConfirmationEmail, renderChangeEmailVerificationEmail, renderInviteEmail, renderMagicLinkEmail, renderResetPasswordEmail, renderResourceSharedEmail, renderVerifySignupEmail, resolveEmailApp, resolveEmailBrandApp, } from "../server/email-templates.js";
|
|
3
3
|
export const CORE_INVITE_EMAIL_ID = "core.organization-invite";
|
|
4
4
|
export const CORE_VERIFY_SIGNUP_EMAIL_ID = "core.verify-signup";
|
|
5
5
|
export const CORE_RESET_PASSWORD_EMAIL_ID = "core.reset-password";
|
|
@@ -8,6 +8,8 @@ export const CORE_CHANGE_EMAIL_CONFIRMATION_EMAIL_ID = "core.change-email-confir
|
|
|
8
8
|
export const CORE_CHANGE_EMAIL_VERIFICATION_EMAIL_ID = "core.change-email-verification";
|
|
9
9
|
export const CORE_BUILDER_CREDIT_LIMIT_EMAIL_ID = "core.builder-credit-limit";
|
|
10
10
|
export const CORE_RESOURCE_SHARED_EMAIL_ID = "core.resource-shared";
|
|
11
|
+
export const CORE_ACCESS_REQUESTED_EMAIL_ID = "core.access-requested";
|
|
12
|
+
export const CORE_ACCESS_GRANTED_EMAIL_ID = "core.access-granted";
|
|
11
13
|
const CORE_EMAIL_DEFAULTS = {
|
|
12
14
|
[CORE_VERIFY_SIGNUP_EMAIL_ID]: {
|
|
13
15
|
render: (args) => renderVerifySignupEmail(args),
|
|
@@ -41,6 +43,14 @@ const CORE_EMAIL_DEFAULTS = {
|
|
|
41
43
|
render: (args) => renderResourceSharedEmail(args),
|
|
42
44
|
app: (args) => args.app,
|
|
43
45
|
},
|
|
46
|
+
[CORE_ACCESS_REQUESTED_EMAIL_ID]: {
|
|
47
|
+
render: (args) => renderAccessRequestedEmail(args),
|
|
48
|
+
app: (args) => args.app,
|
|
49
|
+
},
|
|
50
|
+
[CORE_ACCESS_GRANTED_EMAIL_ID]: {
|
|
51
|
+
render: (args) => renderAccessGrantedEmail(args),
|
|
52
|
+
app: (args) => args.app,
|
|
53
|
+
},
|
|
44
54
|
};
|
|
45
55
|
// Overrides are registered through the public `@agent-native/core` entry and
|
|
46
56
|
// read through relative imports; a module-local map would split in two when
|
package/dist/framework-tools.js
CHANGED
|
@@ -101,6 +101,12 @@ export const CORE_ACTION_GROUPS = {
|
|
|
101
101
|
"share-resource": "sharing",
|
|
102
102
|
"unshare-resource": "sharing",
|
|
103
103
|
"list-resource-shares": "sharing",
|
|
104
|
+
"get-resource-access-status": "sharing",
|
|
105
|
+
"request-resource-access": "sharing",
|
|
106
|
+
"get-resource-access-request": "sharing",
|
|
107
|
+
"list-resource-access-requests": "sharing",
|
|
108
|
+
"approve-resource-access-request": "sharing",
|
|
109
|
+
"decline-resource-access-request": "sharing",
|
|
104
110
|
"set-resource-visibility": "sharing",
|
|
105
111
|
"create-agent-resource-link": "sharing",
|
|
106
112
|
"get-feature-flags": "featureFlags",
|
package/dist/identity/rekey.js
CHANGED
|
@@ -136,6 +136,15 @@ export const IDENTITY_REKEY_COLUMNS = [
|
|
|
136
136
|
{ table: "custom_api_providers", column: "scope_id", mode: "custom-scope" },
|
|
137
137
|
{ table: "staged_datasets", column: "owner_email" },
|
|
138
138
|
{ table: "resources", column: "owner", mode: "owner" },
|
|
139
|
+
// A request under an old address can't be approved for the new one, and a
|
|
140
|
+
// removed member's requests have no one to grant.
|
|
141
|
+
{
|
|
142
|
+
table: "resource_access_requests",
|
|
143
|
+
column: "requester_email",
|
|
144
|
+
emailChange: "delete",
|
|
145
|
+
offboard: "delete",
|
|
146
|
+
},
|
|
147
|
+
{ table: "resource_access_requests", column: "owner_email" },
|
|
139
148
|
{ table: "agent_review_comments", column: "author_email" },
|
|
140
149
|
{ table: "agent_review_comments", column: "owner_email" },
|
|
141
150
|
{ table: "agent_review_notification_deliveries", column: "recipient_email" },
|
|
@@ -15,6 +15,10 @@ export interface AutomationRun {
|
|
|
15
15
|
finishedAt: number | null;
|
|
16
16
|
error: string | null;
|
|
17
17
|
errorCode: string | null;
|
|
18
|
+
/** A queued "Run now" row that a worker claims before it starts. */
|
|
19
|
+
dispatchPending: boolean;
|
|
20
|
+
/** When a worker last claimed this queued dispatch, if ever. */
|
|
21
|
+
claimedAt: number | null;
|
|
18
22
|
}
|
|
19
23
|
export interface StartAutomationRunInput {
|
|
20
24
|
owner: string;
|
|
@@ -28,6 +32,14 @@ export interface StartAutomationRunInput {
|
|
|
28
32
|
threadId?: string | null;
|
|
29
33
|
dispatchPending?: boolean;
|
|
30
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* How long a queued dispatch's claim stays valid before another worker may take
|
|
37
|
+
* it over (`claimAutomationRun`). The stale-lock recovery must leave a row
|
|
38
|
+
* inside this lease to its own worker.
|
|
39
|
+
*/
|
|
40
|
+
export declare function automationRunClaimLeaseMs(): number;
|
|
41
|
+
/** How many runs each automation retains; pruning bounds unfinished rows to this. */
|
|
42
|
+
export declare const RUNS_RETAINED_PER_AUTOMATION = 50;
|
|
31
43
|
export declare const AUTOMATION_RUN_MIGRATIONS: MigrationEntry[];
|
|
32
44
|
export declare function runAutomationRunMigrations(nitroApp: unknown): Promise<void>;
|
|
33
45
|
export declare function ensureTable(): Promise<void>;
|
|
@@ -50,15 +62,22 @@ export declare function processPendingAutomationFailureAlerts(options?: {
|
|
|
50
62
|
uncertain: number;
|
|
51
63
|
failed: number;
|
|
52
64
|
}>;
|
|
53
|
-
export
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
options?: {
|
|
65
|
+
export interface FinishAutomationRunOptions {
|
|
66
|
+
/**
|
|
67
|
+
* `notify: false` records the run without queueing the owner email. Used for
|
|
68
|
+
* the early failures of a streak that will pause: the owner is told once,
|
|
69
|
+
* by the run that pauses it.
|
|
70
|
+
*/
|
|
60
71
|
notify?: boolean;
|
|
61
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Finish only if the stored claim still equals this snapshot. The stale-lock
|
|
74
|
+
* recovery passes the `claimedAt` it read, so a worker that claims the run
|
|
75
|
+
* between that read and this write keeps its run instead of losing it to a
|
|
76
|
+
* stale terminal write.
|
|
77
|
+
*/
|
|
78
|
+
expectedClaimedAt?: number | null;
|
|
79
|
+
}
|
|
80
|
+
export declare function finishAutomationRun(id: string, status: Exclude<AutomationRunStatus, "running">, error?: string, errorCode?: string, options?: FinishAutomationRunOptions): Promise<void>;
|
|
62
81
|
export declare function attachAutomationRunThread(id: string, threadId: string, runId: string): Promise<void>;
|
|
63
82
|
export declare function deleteAutomationRuns(owner: string, automation: string): Promise<void>;
|
|
64
83
|
export declare function listAutomationRuns(options: {
|