@agent-native/core 0.214.0 → 0.217.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/action.js +54 -1
- package/dist/agent/actions/disconnect-chatgpt-subscription.js +5 -0
- package/dist/agent/actions/get-agentkit-capabilities.js +3 -3
- package/dist/agent/actions/manage-builder-connection.js +5 -0
- package/dist/agent/actions/manage-provider-key-policy.js +5 -0
- package/dist/agent/actions/manage-provider-models.js +5 -0
- package/dist/agent/actions/manage-service-providers.js +5 -0
- package/dist/agent/actions/select-chatgpt-subscription-account.js +5 -0
- package/dist/agent/context-xray/actions/context-evict.js +5 -0
- package/dist/agent/context-xray/actions/context-pin.js +5 -0
- package/dist/agent/context-xray/actions/context-report.js +5 -0
- package/dist/agent/context-xray/actions/context-restore.js +5 -0
- package/dist/agent/execution-fence.d.ts +1 -0
- package/dist/agent/execution-fence.js +5 -0
- package/dist/agent/production-agent.d.ts +35 -2
- package/dist/agent/production-agent.js +629 -32
- package/dist/agent/run-manager.d.ts +2 -0
- package/dist/agent/run-manager.js +397 -115
- package/dist/agent/run-slot-lock.d.ts +2 -0
- package/dist/agent/run-slot-lock.js +6 -0
- package/dist/agent/run-store.d.ts +5 -0
- package/dist/agent/run-store.js +423 -156
- package/dist/agent/thread-data-builder.js +27 -5
- package/dist/agent/types.d.ts +6 -12
- package/dist/agentkit/capabilities.d.ts +1 -1
- package/dist/app-config/analytics.js +1 -1
- package/dist/application-state/store.d.ts +5 -0
- package/dist/application-state/store.js +26 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/chat-threads/schema-migrations.js +17 -0
- package/dist/chat-threads/store.d.ts +21 -1
- package/dist/chat-threads/store.js +223 -41
- package/dist/cli/skills-content/turn-into-app-skill.d.ts +1 -1
- package/dist/cli/skills-content/turn-into-app-skill.js +20 -18
- package/dist/cli/templates-meta.js +14 -0
- package/dist/client/analytics-session.d.ts +7 -0
- package/dist/client/analytics-session.js +27 -1
- package/dist/client/analytics.js +276 -31
- package/dist/client/chat/agentkit-agent-native.js +79 -3
- package/dist/client/chat/agentkit-protocol.js +80 -42
- package/dist/client/chat/runtime.d.ts +5 -1
- package/dist/client/chat/runtime.js +46 -3
- package/dist/client/consent.d.ts +48 -0
- package/dist/client/consent.js +413 -0
- package/dist/client/onboarding/index.d.ts +1 -0
- package/dist/client/onboarding/index.js +1 -0
- package/dist/client/onboarding/use-onboarding-checklist.d.ts +23 -0
- package/dist/client/onboarding/use-onboarding-checklist.js +115 -0
- package/dist/client/review/use-review.d.ts +2 -0
- package/dist/client/review/use-review.js +28 -1
- package/dist/client/session-replay.d.ts +1 -1
- package/dist/client/session-replay.js +142 -3
- package/dist/client/sharing/useResourceAccessGate.d.ts +3 -2
- package/dist/client/sharing/useResourceAccessGate.js +9 -1
- package/dist/client/use-chat-thread-list.d.ts +2 -0
- package/dist/client/use-chat-thread-list.js +12 -2
- package/dist/client/use-chat-threads.d.ts +1 -0
- package/dist/client/use-chat-threads.js +2 -0
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/connections/catalog.d.ts +5 -5
- package/dist/connections/catalog.js +22 -3
- package/dist/data-widgets/index.d.ts +36 -2
- package/dist/data-widgets/index.js +94 -6
- package/dist/db/migrations.js +4 -1
- package/dist/db/schema-snapshot.generated.js +8 -1
- package/dist/feature-flags/actions/set-feature-flag.js +5 -0
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/store.d.ts +12 -0
- package/dist/feature-flags/store.js +79 -7
- package/dist/file-upload/actions/manage-file-storage.js +5 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.js +5 -0
- package/dist/history/actions/create-resource-version.js +5 -0
- package/dist/history/actions/restore-resource-version.js +5 -0
- package/dist/ingestion/index.d.ts +1 -1
- package/dist/ingestion/index.js +1 -1
- package/dist/ingestion/pptx.d.ts +11 -0
- package/dist/ingestion/pptx.js +81 -1
- package/dist/integrations/actions/manage-messaging-channel.js +5 -0
- package/dist/jobs/actions/manage-recurring-job.d.ts +1 -1
- package/dist/jobs/scheduler.js +17 -1
- package/dist/labs/actions/set-lab.js +5 -0
- package/dist/localization/actions/set-localization-preference.js +5 -0
- package/dist/localization/consent-banner-messages.d.ts +16 -0
- package/dist/localization/consent-banner-messages.js +149 -0
- package/dist/localization/core-messages.js +4 -0
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +2 -0
- package/dist/mcp/screen-memory-stdio.d.ts +7 -7
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/observability/actions/save-observability-instruction-update.js +5 -0
- package/dist/observability/actions/save-observability-review-summary.js +5 -0
- package/dist/observability/routes.d.ts +6 -6
- package/dist/onboarding/index.d.ts +2 -1
- package/dist/onboarding/index.js +1 -0
- package/dist/onboarding/plugin.js +55 -46
- package/dist/onboarding/status.d.ts +15 -0
- package/dist/onboarding/status.js +59 -0
- package/dist/onboarding/types.d.ts +12 -0
- package/dist/onboarding/types.js +2 -1
- package/dist/org/workspace-app-access.js +19 -9
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/provider-api/index.js +9 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/review/actions/consume-review-feedback.js +5 -0
- package/dist/review/actions/create-review-comment.js +5 -0
- package/dist/review/actions/delete-review-comment.js +5 -0
- package/dist/review/actions/react-to-review-comment.js +5 -0
- package/dist/review/actions/reply-review-comment.js +5 -0
- package/dist/review/actions/resolve-review-thread.js +5 -0
- package/dist/review/actions/send-review-thread-to-agent.js +5 -0
- package/dist/review/actions/set-review-status.js +5 -0
- package/dist/review/actions/set-review-thread-muted.js +5 -0
- package/dist/review/actions/set-review-thread-unread.js +5 -0
- package/dist/review/actions/set-review-threads-unread.js +5 -0
- package/dist/review/actions/update-review-comment-anchor.js +5 -0
- package/dist/review/actions/update-review-comment.js +5 -0
- package/dist/review/suggestions/actions.js +60 -21
- package/dist/review/suggestions/store.d.ts +2 -0
- package/dist/review/suggestions/store.js +28 -0
- package/dist/secrets/actions/delete-api-key.js +5 -0
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-capabilities.js +13 -6
- package/dist/server/agent-chat/context-tools.js +63 -2
- package/dist/server/agent-chat-plugin.d.ts +2 -0
- package/dist/server/agent-chat-plugin.js +242 -54
- 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/analytics.d.ts +0 -1
- package/dist/server/analytics.js +81 -20
- package/dist/server/application-state-maintenance.d.ts +2 -0
- package/dist/server/application-state-maintenance.js +2 -0
- package/dist/server/attribution.d.ts +14 -0
- package/dist/server/attribution.js +62 -2
- package/dist/server/auth.js +7 -0
- package/dist/server/builder-api-auth.d.ts +7 -0
- package/dist/server/builder-api-auth.js +24 -0
- package/dist/server/builder-oauth.d.ts +5 -1
- package/dist/server/builder-oauth.js +5 -0
- package/dist/server/consent-route.d.ts +41 -0
- package/dist/server/consent-route.js +102 -0
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/first-touch-route.d.ts +39 -0
- package/dist/server/first-touch-route.js +115 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -1
- package/dist/server/queued-submission-inbox-drain.d.ts +9 -0
- package/dist/server/queued-submission-inbox-drain.js +12 -0
- package/dist/server/request-origin.d.ts +6 -0
- package/dist/server/request-origin.js +12 -0
- package/dist/settings/org-settings.d.ts +2 -1
- package/dist/settings/org-settings.js +4 -1
- package/dist/settings/store.d.ts +8 -0
- package/dist/settings/store.js +14 -5
- package/dist/shared/consent.d.ts +33 -0
- package/dist/shared/consent.js +149 -0
- package/dist/shared/first-touch-persistence.d.ts +31 -0
- package/dist/shared/first-touch-persistence.js +53 -0
- package/dist/sharing/actions/set-resource-visibility.js +5 -0
- package/dist/sharing/actions/share-resource.js +5 -0
- package/dist/sharing/actions/unshare-resource.js +5 -0
- package/dist/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/dist/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/dist/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
- package/dist/triggers/actions/manage-automation.d.ts +4 -4
- package/dist/usage/actions/get-usage-metrics.js +27 -4
- package/dist/usage/actions/manage-usage-alert.js +5 -0
- package/dist/vite/client.js +8 -6
- package/dist/workspace-connections/actions/bulk-update-workspace-user-groups.js +5 -0
- package/dist/workspace-connections/actions/delete-workspace-user-group.js +5 -0
- package/dist/workspace-connections/actions/upsert-workspace-user-group.js +5 -0
- package/docs/content/actions-access-control.mdx +8 -8
- package/docs/content/actions-defining.mdx +9 -8
- package/docs/content/deployment-environment-variables.mdx +1 -1
- package/docs/content/environment-variables.mdx +1 -1
- package/docs/content/template-design-developers.mdx +9 -9
- package/docs/content/template-design-features.mdx +1 -3
- package/docs/content/turn-into-app.mdx +4 -0
- package/package.json +6 -3
- package/src/templates/chat/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/default/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +36 -80
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/channel-inventory.md +54 -16
- package/src/templates/factory/.agents/skills/review-latest-feedback/references/slack-reaction-replies.md +50 -73
- package/src/templates/headless/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/actions/references/action-fields.md +1 -1
- package/src/templates/workspace-core/.agents/skills/turn-into-app/SKILL.md +20 -18
|
@@ -27,43 +27,43 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
27
27
|
thumbsUpRate: number;
|
|
28
28
|
avgEvalScore: number;
|
|
29
29
|
} | {
|
|
30
|
+
ok?: undefined;
|
|
30
31
|
error: string;
|
|
31
32
|
message: string;
|
|
32
33
|
summary?: undefined;
|
|
33
34
|
spans?: undefined;
|
|
34
|
-
ok?: undefined;
|
|
35
35
|
} | {
|
|
36
|
+
ok?: undefined;
|
|
36
37
|
message?: undefined;
|
|
37
38
|
summary: import("./types.js").TraceSummary;
|
|
38
39
|
spans: import("./types.js").TraceSpan[];
|
|
39
40
|
error?: undefined;
|
|
40
|
-
ok?: undefined;
|
|
41
41
|
} | {
|
|
42
|
+
ok?: undefined;
|
|
42
43
|
message?: undefined;
|
|
43
44
|
summary?: undefined;
|
|
44
45
|
spans?: undefined;
|
|
45
46
|
traceMissing: true;
|
|
46
47
|
id: string;
|
|
47
48
|
error?: undefined;
|
|
48
|
-
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
+
ok?: undefined;
|
|
50
51
|
message?: undefined;
|
|
51
52
|
summary?: undefined;
|
|
52
53
|
spans?: undefined;
|
|
53
54
|
traceMissing?: undefined;
|
|
54
55
|
id: string;
|
|
55
56
|
error?: undefined;
|
|
56
|
-
ok?: undefined;
|
|
57
57
|
} | {
|
|
58
|
+
ok?: undefined;
|
|
58
59
|
message?: undefined;
|
|
59
60
|
summary?: undefined;
|
|
60
61
|
spans?: undefined;
|
|
61
62
|
error: any;
|
|
62
|
-
ok?: undefined;
|
|
63
63
|
} | {
|
|
64
64
|
message?: undefined;
|
|
65
65
|
summary?: undefined;
|
|
66
66
|
spans?: undefined;
|
|
67
|
-
error?: undefined;
|
|
68
67
|
ok: boolean;
|
|
68
|
+
error?: undefined;
|
|
69
69
|
}>>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { registerOnboardingStep, listOnboardingSteps } from "./registry.js";
|
|
2
|
-
export
|
|
2
|
+
export { DEFAULT_ONBOARDING_CHECKLIST } from "./types.js";
|
|
3
|
+
export type { OnboardingStep, OnboardingMethod, OnboardingMethodBadge, OnboardingFormField, OnboardingStepStatus, OnboardingResolveContext, OnboardingCapability, OnboardingAppProfile, WorkspaceBuilderIncludedServiceId, WorkspaceBuilderOnlyServiceId, WorkspaceProviderServiceId, WorkspaceServiceId, } from "./types.js";
|
|
3
4
|
export { WORKSPACE_SERVICES, workspaceServiceForCapability, type WorkspaceService, type WorkspaceServiceKind, } from "./workspace-services.js";
|
|
4
5
|
export { getOnboardingAppProfile, resolveOnboardingAppId, } from "./app-profile.js";
|
|
5
6
|
export { getOnboardingAppProfileForId } from "./app-profile-data.js";
|
package/dist/onboarding/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { registerOnboardingStep, listOnboardingSteps } from "./registry.js";
|
|
2
|
+
export { DEFAULT_ONBOARDING_CHECKLIST } from "./types.js";
|
|
2
3
|
export { WORKSPACE_SERVICES, workspaceServiceForCapability, } from "./workspace-services.js";
|
|
3
4
|
export { getOnboardingAppProfile, resolveOnboardingAppId, } from "./app-profile.js";
|
|
4
5
|
export { getOnboardingAppProfileForId } from "./app-profile-data.js";
|
|
@@ -11,11 +11,10 @@ import { getOnboardingRoleCategory, getOnboardingRoleTextForAnalytics, onboardin
|
|
|
11
11
|
import { getUserProfile, updateUserOnboardingRole, } from "../user-profile/store.js";
|
|
12
12
|
import { getOnboardingAppProfile } from "./app-profile.js";
|
|
13
13
|
import { registerDefaultOnboardingSteps } from "./default-steps.js";
|
|
14
|
-
import { listOnboardingSteps } from "./registry.js";
|
|
15
14
|
import { SHARED_ONBOARDING_COOKIE, SHARED_ONBOARDING_COOKIE_MAX_AGE, decodeSharedOnboardingCookie, encodeSharedOnboardingCookie, hashOnboardingEmail, } from "./shared-cookie.js";
|
|
15
|
+
import { getOnboardingStepStatuses, isValidOnboardingChecklistName, onboardingDismissedKey, onboardingOverrideKey, readOnboardingDismissed, } from "./status.js";
|
|
16
|
+
import { DEFAULT_ONBOARDING_CHECKLIST, } from "./types.js";
|
|
16
17
|
const ONBOARDING_PREFIX = "/_agent-native/onboarding";
|
|
17
|
-
const OVERRIDE_KEY_PREFIX = "onboarding:override:";
|
|
18
|
-
const DISMISSED_KEY = "onboarding:dismissed";
|
|
19
18
|
async function resolveOnboardingContext(event) {
|
|
20
19
|
const { getSession } = await import("../server/auth.js");
|
|
21
20
|
const session = await getSession(event);
|
|
@@ -27,35 +26,15 @@ async function resolveOnboardingContext(event) {
|
|
|
27
26
|
orgId: session.orgId ?? null,
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
let complete = false;
|
|
42
|
-
if (!options.preview) {
|
|
43
|
-
complete = (await step.isComplete(context)) === true;
|
|
44
|
-
if (!complete) {
|
|
45
|
-
complete = await hasOverride(context.sessionId, step.id);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return {
|
|
49
|
-
id: step.id,
|
|
50
|
-
title: step.title,
|
|
51
|
-
description: step.description,
|
|
52
|
-
order: step.order,
|
|
53
|
-
required: step.required ?? false,
|
|
54
|
-
complete,
|
|
55
|
-
methods: step.methods,
|
|
56
|
-
};
|
|
57
|
-
}));
|
|
58
|
-
return serialized.filter((step) => step !== null);
|
|
29
|
+
/** `undefined` when the request names no checklist; `null` when the name is invalid. */
|
|
30
|
+
function readChecklistParam(event) {
|
|
31
|
+
const raw = getQuery(event).checklist;
|
|
32
|
+
if (raw === undefined)
|
|
33
|
+
return undefined;
|
|
34
|
+
if (typeof raw !== "string" || !isValidOnboardingChecklistName(raw)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return raw;
|
|
59
38
|
}
|
|
60
39
|
function withOnboardingRequestContext(context, fn) {
|
|
61
40
|
return runWithRequestContext({
|
|
@@ -73,9 +52,10 @@ function roleTrackingProperties(role) {
|
|
|
73
52
|
function allRequiredComplete(statuses) {
|
|
74
53
|
return statuses.filter((s) => s.required).every((s) => s.complete);
|
|
75
54
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
55
|
+
// A progress checklist has no required steps, so "required complete" would be
|
|
56
|
+
// vacuously true while steps are still open.
|
|
57
|
+
function allStepsComplete(statuses) {
|
|
58
|
+
return statuses.length > 0 && statuses.every((s) => s.complete);
|
|
79
59
|
}
|
|
80
60
|
async function resolveSharedCompletionEnabled() {
|
|
81
61
|
if (!getAppConfig().onboarding.sharedCompletion.enabled)
|
|
@@ -104,10 +84,15 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
104
84
|
setResponseStatus(event, 405);
|
|
105
85
|
return { error: "Method not allowed" };
|
|
106
86
|
}
|
|
87
|
+
const checklist = readChecklistParam(event);
|
|
88
|
+
if (checklist === null) {
|
|
89
|
+
setResponseStatus(event, 400);
|
|
90
|
+
return { error: "Invalid checklist" };
|
|
91
|
+
}
|
|
107
92
|
const context = await resolveOnboardingContext(event);
|
|
108
93
|
const query = getQuery(event);
|
|
109
94
|
const preview = query.preview === "1" || query.preview === 1;
|
|
110
|
-
return withOnboardingRequestContext(context, () =>
|
|
95
|
+
return withOnboardingRequestContext(context, () => getOnboardingStepStatuses(context, { preview, checklist }));
|
|
111
96
|
}
|
|
112
97
|
const [id, action] = trimmed.split("/");
|
|
113
98
|
if (action === "complete") {
|
|
@@ -120,7 +105,7 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
120
105
|
return { error: "id required" };
|
|
121
106
|
}
|
|
122
107
|
const { sessionId } = await resolveOnboardingContext(event);
|
|
123
|
-
await appStatePut(sessionId,
|
|
108
|
+
await appStatePut(sessionId, onboardingOverrideKey(id), { complete: true }, { requestSource: "agent" });
|
|
124
109
|
return { ok: true, id };
|
|
125
110
|
}
|
|
126
111
|
return;
|
|
@@ -130,8 +115,14 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
130
115
|
setResponseStatus(event, 405);
|
|
131
116
|
return { error: "Method not allowed" };
|
|
132
117
|
}
|
|
118
|
+
const requested = readChecklistParam(event);
|
|
119
|
+
if (requested === null) {
|
|
120
|
+
setResponseStatus(event, 400);
|
|
121
|
+
return { error: "Invalid checklist" };
|
|
122
|
+
}
|
|
123
|
+
const checklist = requested ?? DEFAULT_ONBOARDING_CHECKLIST;
|
|
133
124
|
const { sessionId } = await resolveOnboardingContext(event);
|
|
134
|
-
await appStatePut(sessionId,
|
|
125
|
+
await appStatePut(sessionId, onboardingDismissedKey(checklist), { dismissed: true, at: new Date().toISOString() }, { requestSource: "agent" });
|
|
135
126
|
return { ok: true };
|
|
136
127
|
}));
|
|
137
128
|
getH3App(nitroApp).use(`${ONBOARDING_PREFIX}/reopen`, defineEventHandler(async (event) => {
|
|
@@ -139,8 +130,14 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
139
130
|
setResponseStatus(event, 405);
|
|
140
131
|
return { error: "Method not allowed" };
|
|
141
132
|
}
|
|
133
|
+
const requested = readChecklistParam(event);
|
|
134
|
+
if (requested === null) {
|
|
135
|
+
setResponseStatus(event, 400);
|
|
136
|
+
return { error: "Invalid checklist" };
|
|
137
|
+
}
|
|
138
|
+
const checklist = requested ?? DEFAULT_ONBOARDING_CHECKLIST;
|
|
142
139
|
const { sessionId } = await resolveOnboardingContext(event);
|
|
143
|
-
await appStatePut(sessionId,
|
|
140
|
+
await appStatePut(sessionId, onboardingDismissedKey(checklist), { dismissed: false, at: new Date().toISOString() }, { requestSource: "agent" });
|
|
144
141
|
return { ok: true };
|
|
145
142
|
}));
|
|
146
143
|
getH3App(nitroApp).use(`${ONBOARDING_PREFIX}/dismissed`, defineEventHandler(async (event) => {
|
|
@@ -148,15 +145,22 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
148
145
|
setResponseStatus(event, 405);
|
|
149
146
|
return { error: "Method not allowed" };
|
|
150
147
|
}
|
|
148
|
+
const checklist = readChecklistParam(event);
|
|
149
|
+
if (checklist === null) {
|
|
150
|
+
setResponseStatus(event, 400);
|
|
151
|
+
return { error: "Invalid checklist" };
|
|
152
|
+
}
|
|
151
153
|
const context = await resolveOnboardingContext(event);
|
|
152
154
|
return withOnboardingRequestContext(context, async () => {
|
|
153
|
-
const [statuses,
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
const [statuses, dismissed] = await Promise.all([
|
|
156
|
+
getOnboardingStepStatuses(context, { checklist }),
|
|
157
|
+
readOnboardingDismissed(context.sessionId, checklist),
|
|
156
158
|
]);
|
|
157
159
|
return {
|
|
158
|
-
dismissed
|
|
159
|
-
allComplete:
|
|
160
|
+
dismissed,
|
|
161
|
+
allComplete: checklist === undefined
|
|
162
|
+
? allRequiredComplete(statuses)
|
|
163
|
+
: allStepsComplete(statuses),
|
|
160
164
|
};
|
|
161
165
|
});
|
|
162
166
|
}));
|
|
@@ -172,13 +176,18 @@ export function createOnboardingPlugin(options = {}) {
|
|
|
172
176
|
setResponseStatus(event, 405);
|
|
173
177
|
return { error: "Method not allowed" };
|
|
174
178
|
}
|
|
179
|
+
const checklist = readChecklistParam(event);
|
|
180
|
+
if (checklist === null) {
|
|
181
|
+
setResponseStatus(event, 400);
|
|
182
|
+
return { error: "Invalid checklist" };
|
|
183
|
+
}
|
|
175
184
|
const context = await resolveOnboardingContext(event);
|
|
176
185
|
const query = getQuery(event);
|
|
177
186
|
const preview = query.preview === "1" || query.preview === 1;
|
|
178
187
|
return withOnboardingRequestContext(context, async () => {
|
|
179
188
|
const [steps, dismissed] = await Promise.all([
|
|
180
|
-
|
|
181
|
-
|
|
189
|
+
getOnboardingStepStatuses(context, { preview, checklist }),
|
|
190
|
+
readOnboardingDismissed(context.sessionId, checklist ?? DEFAULT_ONBOARDING_CHECKLIST),
|
|
182
191
|
]);
|
|
183
192
|
return {
|
|
184
193
|
steps,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type OnboardingResolveContext, type OnboardingStepStatus } from "./types.js";
|
|
2
|
+
export declare function isValidOnboardingChecklistName(name: string): boolean;
|
|
3
|
+
/** The setup checklist keeps its original key so existing dismissals survive. */
|
|
4
|
+
export declare function onboardingDismissedKey(checklist: string): string;
|
|
5
|
+
export declare function onboardingOverrideKey(stepId: string): string;
|
|
6
|
+
export declare function readOnboardingDismissed(sessionId: string, checklist?: string): Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Resolves the steps of one checklist. A failing `isAvailable`, `isComplete`,
|
|
9
|
+
* or override read rejects instead of reporting a step as incomplete, so
|
|
10
|
+
* callers can tell "could not check" from "not done".
|
|
11
|
+
*/
|
|
12
|
+
export declare function getOnboardingStepStatuses(context: OnboardingResolveContext, options?: {
|
|
13
|
+
preview?: boolean;
|
|
14
|
+
checklist?: string;
|
|
15
|
+
}): Promise<OnboardingStepStatus[]>;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { appStateGet } from "../application-state/store.js";
|
|
2
|
+
import { listOnboardingSteps } from "./registry.js";
|
|
3
|
+
import { DEFAULT_ONBOARDING_CHECKLIST, } from "./types.js";
|
|
4
|
+
const OVERRIDE_KEY_PREFIX = "onboarding:override:";
|
|
5
|
+
const DISMISSED_KEY = "onboarding:dismissed";
|
|
6
|
+
const CHECKLIST_NAME_PATTERN = /^[a-z][a-z0-9-]{0,39}$/;
|
|
7
|
+
export function isValidOnboardingChecklistName(name) {
|
|
8
|
+
return CHECKLIST_NAME_PATTERN.test(name);
|
|
9
|
+
}
|
|
10
|
+
/** The setup checklist keeps its original key so existing dismissals survive. */
|
|
11
|
+
export function onboardingDismissedKey(checklist) {
|
|
12
|
+
return checklist === DEFAULT_ONBOARDING_CHECKLIST
|
|
13
|
+
? DISMISSED_KEY
|
|
14
|
+
: `${DISMISSED_KEY}:${checklist}`;
|
|
15
|
+
}
|
|
16
|
+
export function onboardingOverrideKey(stepId) {
|
|
17
|
+
return `${OVERRIDE_KEY_PREFIX}${stepId}`;
|
|
18
|
+
}
|
|
19
|
+
async function hasOverride(sessionId, stepId) {
|
|
20
|
+
const val = await appStateGet(sessionId, onboardingOverrideKey(stepId));
|
|
21
|
+
return !!(val && val.complete);
|
|
22
|
+
}
|
|
23
|
+
export async function readOnboardingDismissed(sessionId, checklist = DEFAULT_ONBOARDING_CHECKLIST) {
|
|
24
|
+
const value = await appStateGet(sessionId, onboardingDismissedKey(checklist));
|
|
25
|
+
return !!(value && value.dismissed);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolves the steps of one checklist. A failing `isAvailable`, `isComplete`,
|
|
29
|
+
* or override read rejects instead of reporting a step as incomplete, so
|
|
30
|
+
* callers can tell "could not check" from "not done".
|
|
31
|
+
*/
|
|
32
|
+
export async function getOnboardingStepStatuses(context, options = {}) {
|
|
33
|
+
const checklist = options.checklist ?? DEFAULT_ONBOARDING_CHECKLIST;
|
|
34
|
+
const steps = listOnboardingSteps().filter((step) => (step.checklist ?? DEFAULT_ONBOARDING_CHECKLIST) === checklist);
|
|
35
|
+
const serialized = await Promise.all(steps.map(async (step) => {
|
|
36
|
+
if (!options.preview && step.isAvailable) {
|
|
37
|
+
if (!(await step.isAvailable(context)))
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
let complete = false;
|
|
41
|
+
if (!options.preview) {
|
|
42
|
+
complete = (await step.isComplete(context)) === true;
|
|
43
|
+
if (!complete) {
|
|
44
|
+
complete = await hasOverride(context.sessionId, step.id);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
id: step.id,
|
|
49
|
+
title: step.title,
|
|
50
|
+
description: step.description,
|
|
51
|
+
order: step.order,
|
|
52
|
+
required: step.required ?? false,
|
|
53
|
+
complete,
|
|
54
|
+
...(step.href ? { href: step.href } : {}),
|
|
55
|
+
methods: step.methods,
|
|
56
|
+
};
|
|
57
|
+
}));
|
|
58
|
+
return serialized.filter((step) => step !== null);
|
|
59
|
+
}
|
|
@@ -45,12 +45,23 @@ export type OnboardingMethod = (OnboardingMethodBase & {
|
|
|
45
45
|
*/
|
|
46
46
|
kind: "file-storage";
|
|
47
47
|
});
|
|
48
|
+
/** The checklist a step belongs to when it does not name one: credential and connection setup. */
|
|
49
|
+
export declare const DEFAULT_ONBOARDING_CHECKLIST = "setup";
|
|
48
50
|
export interface OnboardingStep {
|
|
49
51
|
id: string;
|
|
50
52
|
title: string;
|
|
51
53
|
description: string;
|
|
52
54
|
order: number;
|
|
53
55
|
required?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Named checklist the step belongs to. The setup checklist (the default)
|
|
58
|
+
* and a progress checklist such as `getting-started` never share rows:
|
|
59
|
+
* each is served only when asked for by name.
|
|
60
|
+
*/
|
|
61
|
+
checklist?: string;
|
|
62
|
+
/** In-app path a progress row opens so the user can complete the step. */
|
|
63
|
+
href?: string;
|
|
64
|
+
/** Progress steps that need no setup form pass an empty list. */
|
|
54
65
|
methods: OnboardingMethod[];
|
|
55
66
|
isAvailable?: (context?: OnboardingResolveContext) => boolean | Promise<boolean>;
|
|
56
67
|
isComplete: (context?: OnboardingResolveContext) => boolean | Promise<boolean>;
|
|
@@ -67,6 +78,7 @@ export interface OnboardingStepStatus {
|
|
|
67
78
|
order: number;
|
|
68
79
|
required: boolean;
|
|
69
80
|
complete: boolean;
|
|
81
|
+
href?: string;
|
|
70
82
|
methods: OnboardingMethod[];
|
|
71
83
|
}
|
|
72
84
|
/** Services whose provider is picked per service (`manage-service-providers`). */
|
package/dist/onboarding/types.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
/** The checklist a step belongs to when it does not name one: credential and connection setup. */
|
|
2
|
+
export const DEFAULT_ONBOARDING_CHECKLIST = "setup";
|
|
@@ -232,24 +232,28 @@ async function resolveHostedWorkspaceAppAuth(configuredDirectory, context, email
|
|
|
232
232
|
const audience = canonicalA2AAudience(configuredDirectory);
|
|
233
233
|
let stage = "org-domain-lookup-failed";
|
|
234
234
|
try {
|
|
235
|
+
const requestContext = getRequestContext();
|
|
236
|
+
const delegatedMember = requestContext?.a2aIdentityAssurance === "org-member";
|
|
235
237
|
const orgDomain = orgId ? await cachedOrgDomain(orgId) : null;
|
|
236
238
|
const normalizedOrgDomain = orgDomain?.trim() || undefined;
|
|
237
239
|
if (orgId && !normalizedOrgDomain) {
|
|
238
240
|
return workspaceAppAccessUnavailable("org-domain-missing", { audience });
|
|
239
241
|
}
|
|
240
|
-
stage = "
|
|
241
|
-
const
|
|
242
|
+
stage = "token-signing-failed";
|
|
243
|
+
const deploymentSecret = readDeployCredentialEnv("A2A_SECRET")?.trim();
|
|
244
|
+
if (orgId && (delegatedMember || deploymentSecret)) {
|
|
245
|
+
stage = "org-a2a-secret-lookup-failed";
|
|
246
|
+
}
|
|
247
|
+
const orgSecret = orgId && (delegatedMember || deploymentSecret)
|
|
242
248
|
? (await cachedOrgA2ASecret(orgId))?.trim() || undefined
|
|
243
249
|
: undefined;
|
|
244
|
-
|
|
245
|
-
const signingSecret = orgSecret
|
|
250
|
+
stage = "token-signing-failed";
|
|
251
|
+
const signingSecret = delegatedMember ? orgSecret : deploymentSecret;
|
|
246
252
|
if (!signingSecret) {
|
|
247
253
|
return workspaceAppAccessUnavailable("a2a-secret-missing", { audience });
|
|
248
254
|
}
|
|
249
|
-
stage = "token-signing-failed";
|
|
250
|
-
const requestContext = getRequestContext();
|
|
251
255
|
let token;
|
|
252
|
-
if (
|
|
256
|
+
if (delegatedMember) {
|
|
253
257
|
if (!orgId ||
|
|
254
258
|
!normalizedOrgDomain ||
|
|
255
259
|
requestContext.orgId?.trim() !== orgId ||
|
|
@@ -273,9 +277,15 @@ async function resolveHostedWorkspaceAppAuth(configuredDirectory, context, email
|
|
|
273
277
|
token = await signA2AOrgMemberDelegationToken(email, normalizedOrgDomain, orgSecret, audience);
|
|
274
278
|
}
|
|
275
279
|
else {
|
|
276
|
-
|
|
280
|
+
if (orgSecret && orgSecret === deploymentSecret) {
|
|
281
|
+
return workspaceAppAccessUnavailable("token-signing-failed", {
|
|
282
|
+
audience,
|
|
283
|
+
detail: "Organization and deployment A2A secrets must differ for user identity.",
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
token = await signA2AToken(email, normalizedOrgDomain, undefined, {
|
|
277
287
|
expiresIn: "1m",
|
|
278
|
-
preferGlobalSecret:
|
|
288
|
+
preferGlobalSecret: true,
|
|
279
289
|
audience,
|
|
280
290
|
extraClaims: {
|
|
281
291
|
jti: randomUUID(),
|
|
@@ -76,7 +76,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
78
|
message?: undefined;
|
|
79
|
-
|
|
79
|
+
id?: undefined;
|
|
80
|
+
provider?: undefined;
|
|
81
|
+
deleted?: undefined;
|
|
80
82
|
providers: {
|
|
81
83
|
id: string;
|
|
82
84
|
label: string;
|
|
@@ -87,47 +89,45 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
87
89
|
updatedAt: number;
|
|
88
90
|
}[];
|
|
89
91
|
count: number;
|
|
90
|
-
|
|
91
|
-
deleted?: undefined;
|
|
92
|
+
found?: undefined;
|
|
92
93
|
registered?: undefined;
|
|
93
|
-
id?: undefined;
|
|
94
94
|
label?: undefined;
|
|
95
95
|
} | {
|
|
96
96
|
message?: undefined;
|
|
97
|
-
|
|
97
|
+
id?: undefined;
|
|
98
98
|
count?: undefined;
|
|
99
|
+
deleted?: undefined;
|
|
100
|
+
providers?: undefined;
|
|
99
101
|
found: boolean;
|
|
100
102
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
101
|
-
deleted?: undefined;
|
|
102
103
|
registered?: undefined;
|
|
103
|
-
id?: undefined;
|
|
104
104
|
label?: undefined;
|
|
105
105
|
} | {
|
|
106
106
|
message?: undefined;
|
|
107
|
-
providers?: undefined;
|
|
108
|
-
count?: undefined;
|
|
109
107
|
provider?: undefined;
|
|
108
|
+
count?: undefined;
|
|
109
|
+
deleted?: undefined;
|
|
110
|
+
providers?: undefined;
|
|
110
111
|
found: boolean;
|
|
111
112
|
id: string;
|
|
112
|
-
deleted?: undefined;
|
|
113
113
|
registered?: undefined;
|
|
114
114
|
label?: undefined;
|
|
115
115
|
} | {
|
|
116
116
|
message?: undefined;
|
|
117
|
-
found?: undefined;
|
|
118
|
-
providers?: undefined;
|
|
119
|
-
count?: undefined;
|
|
120
117
|
provider?: undefined;
|
|
118
|
+
count?: undefined;
|
|
119
|
+
providers?: undefined;
|
|
120
|
+
found?: undefined;
|
|
121
121
|
deleted: boolean;
|
|
122
122
|
id: string;
|
|
123
123
|
registered?: undefined;
|
|
124
124
|
label?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
found?: undefined;
|
|
127
|
-
providers?: undefined;
|
|
128
|
-
count?: undefined;
|
|
129
126
|
provider?: undefined;
|
|
127
|
+
count?: undefined;
|
|
130
128
|
deleted?: undefined;
|
|
129
|
+
providers?: undefined;
|
|
130
|
+
found?: undefined;
|
|
131
131
|
registered: boolean;
|
|
132
132
|
id: string;
|
|
133
133
|
label: string;
|
|
@@ -317,8 +317,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
317
317
|
scope?: "org" | "user" | undefined;
|
|
318
318
|
}, {
|
|
319
319
|
id?: undefined;
|
|
320
|
-
found?: undefined;
|
|
321
320
|
deleted?: undefined;
|
|
321
|
+
provider?: undefined;
|
|
322
322
|
providers: {
|
|
323
323
|
id: string;
|
|
324
324
|
label: string;
|
|
@@ -329,15 +329,15 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
329
329
|
updatedAt: number;
|
|
330
330
|
}[];
|
|
331
331
|
count: number;
|
|
332
|
-
|
|
332
|
+
found?: undefined;
|
|
333
333
|
registered?: undefined;
|
|
334
334
|
label?: undefined;
|
|
335
335
|
message?: undefined;
|
|
336
336
|
} | {
|
|
337
337
|
id?: undefined;
|
|
338
338
|
deleted?: undefined;
|
|
339
|
-
providers?: undefined;
|
|
340
339
|
count?: undefined;
|
|
340
|
+
providers?: undefined;
|
|
341
341
|
found: boolean;
|
|
342
342
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
343
343
|
registered?: undefined;
|
|
@@ -345,30 +345,30 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
345
345
|
message?: undefined;
|
|
346
346
|
} | {
|
|
347
347
|
deleted?: undefined;
|
|
348
|
-
providers?: undefined;
|
|
349
|
-
count?: undefined;
|
|
350
348
|
provider?: undefined;
|
|
349
|
+
count?: undefined;
|
|
350
|
+
providers?: undefined;
|
|
351
351
|
found: boolean;
|
|
352
352
|
id: string;
|
|
353
353
|
registered?: undefined;
|
|
354
354
|
label?: undefined;
|
|
355
355
|
message?: undefined;
|
|
356
356
|
} | {
|
|
357
|
-
found?: undefined;
|
|
358
|
-
providers?: undefined;
|
|
359
|
-
count?: undefined;
|
|
360
357
|
provider?: undefined;
|
|
358
|
+
count?: undefined;
|
|
359
|
+
providers?: undefined;
|
|
360
|
+
found?: undefined;
|
|
361
361
|
deleted: boolean;
|
|
362
362
|
id: string;
|
|
363
363
|
registered?: undefined;
|
|
364
364
|
label?: undefined;
|
|
365
365
|
message?: undefined;
|
|
366
366
|
} | {
|
|
367
|
-
found?: undefined;
|
|
368
367
|
deleted?: undefined;
|
|
369
|
-
providers?: undefined;
|
|
370
|
-
count?: undefined;
|
|
371
368
|
provider?: undefined;
|
|
369
|
+
count?: undefined;
|
|
370
|
+
providers?: undefined;
|
|
371
|
+
found?: undefined;
|
|
372
372
|
registered: boolean;
|
|
373
373
|
id: string;
|
|
374
374
|
label: string;
|
|
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
73
73
|
offset?: unknown;
|
|
74
74
|
limit?: unknown;
|
|
75
75
|
}, {
|
|
76
|
+
deleted?: undefined;
|
|
76
77
|
jobs: {
|
|
77
78
|
id: string;
|
|
78
79
|
name: string;
|
|
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
83
84
|
updatedAt: string;
|
|
84
85
|
}[];
|
|
85
86
|
total: number;
|
|
86
|
-
deleted?: undefined;
|
|
87
87
|
jobId?: undefined;
|
|
88
88
|
} | {
|
|
89
89
|
jobs?: undefined;
|
|
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
91
91
|
deleted: boolean;
|
|
92
92
|
jobId: string;
|
|
93
93
|
} | {
|
|
94
|
+
deleted?: undefined;
|
|
94
95
|
jobs?: undefined;
|
|
95
96
|
total?: undefined;
|
|
96
|
-
deleted?: undefined;
|
|
97
97
|
jobId?: undefined;
|
|
98
98
|
hits: Record<string, unknown>[];
|
|
99
99
|
offset: number;
|
|
@@ -787,7 +787,14 @@ const PROVIDER_CONFIGS = {
|
|
|
787
787
|
docsUrls: ["https://developers.google.com/drive/api/reference/rest/v3"],
|
|
788
788
|
specUrls: ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"],
|
|
789
789
|
allowedHostSuffixes: ["googleapis.com"],
|
|
790
|
-
templateUses: [
|
|
790
|
+
templateUses: [
|
|
791
|
+
"brain",
|
|
792
|
+
"content",
|
|
793
|
+
"slides",
|
|
794
|
+
"slides-2",
|
|
795
|
+
"dispatch",
|
|
796
|
+
"analytics",
|
|
797
|
+
],
|
|
791
798
|
examples: [
|
|
792
799
|
{ label: "List files", method: "GET", path: "/files" },
|
|
793
800
|
{ label: "Get file metadata", method: "GET", path: "/files/{fileId}" },
|
|
@@ -843,7 +850,7 @@ const PROVIDER_CONFIGS = {
|
|
|
843
850
|
],
|
|
844
851
|
specUrls: ["https://slides.googleapis.com/$discovery/rest?version=v1"],
|
|
845
852
|
allowedHostSuffixes: ["googleapis.com"],
|
|
846
|
-
templateUses: ["brain", "content", "slides", "dispatch"],
|
|
853
|
+
templateUses: ["brain", "content", "slides", "slides-2", "dispatch"],
|
|
847
854
|
examples: [
|
|
848
855
|
{
|
|
849
856
|
label: "Get presentation with slides and speaker notes",
|
|
@@ -39,8 +39,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
39
39
|
error: string;
|
|
40
40
|
}>;
|
|
41
41
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
42
|
-
error: string;
|
|
43
42
|
ok?: undefined;
|
|
43
|
+
error: string;
|
|
44
44
|
} | {
|
|
45
45
|
error?: undefined;
|
|
46
46
|
ok: boolean;
|
|
@@ -10,6 +10,11 @@ const schema = z.object({
|
|
|
10
10
|
export default defineAction({
|
|
11
11
|
description: "Mark review feedback as consumed by the agent or reviewer workflow.",
|
|
12
12
|
schema,
|
|
13
|
+
mcpAnnotations: {
|
|
14
|
+
readOnlyHint: false,
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
openWorldHint: false,
|
|
17
|
+
},
|
|
13
18
|
run: async (args, ctx) => {
|
|
14
19
|
const actionCtx = ctx;
|
|
15
20
|
await assertReviewableResourceAccess(args.resourceType, args.resourceId, actionCtx, "editor");
|
|
@@ -40,6 +40,11 @@ const schema = z.object({
|
|
|
40
40
|
export default defineAction({
|
|
41
41
|
description: "Create an inline comment, annotation, or review thread for a resource. Body text supports inline Markdown without headings.",
|
|
42
42
|
schema,
|
|
43
|
+
mcpAnnotations: {
|
|
44
|
+
readOnlyHint: false,
|
|
45
|
+
destructiveHint: false,
|
|
46
|
+
openWorldHint: true,
|
|
47
|
+
},
|
|
43
48
|
run: async (args, ctx) => {
|
|
44
49
|
const actionCtx = ctx;
|
|
45
50
|
const access = await assertReviewableResourceAccess(args.resourceType, args.resourceId, actionCtx, "commenter");
|
|
@@ -12,6 +12,11 @@ const schema = z.object({
|
|
|
12
12
|
export default defineAction({
|
|
13
13
|
description: "Soft-delete a review comment.",
|
|
14
14
|
schema,
|
|
15
|
+
mcpAnnotations: {
|
|
16
|
+
readOnlyHint: false,
|
|
17
|
+
destructiveHint: true,
|
|
18
|
+
openWorldHint: false,
|
|
19
|
+
},
|
|
15
20
|
run: async (args, ctx) => {
|
|
16
21
|
const actionCtx = ctx;
|
|
17
22
|
const scope = {
|