@k2b/cloud 0.42.0 → 0.44.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/package.json +13 -5
- package/scripts/app-favicon.ts +7 -6
- package/scripts/build.ts +3 -0
- package/scripts/installable-assets.ts +61 -0
- package/scripts/preload.ts +3 -0
- package/src/_internal/app-access-path.ts +12 -0
- package/src/_internal/app-access-request.ts +13 -0
- package/src/_internal/app-access-resources.ts +141 -0
- package/src/_internal/app-event-catalog.ts +40 -0
- package/src/_internal/app-event-schemas.ts +127 -0
- package/src/_internal/application-package.ts +40 -0
- package/src/_internal/built-in-app-ids.json +27 -0
- package/src/_internal/capabilities.ts +185 -12
- package/src/_internal/capability-origin.ts +4 -0
- package/src/_internal/capability-streams.ts +10 -5
- package/src/_internal/define-app.ts +159 -45
- package/src/_internal/installable-assets.ts +90 -0
- package/src/_internal/installable-head.ts +22 -0
- package/src/_internal/object-store-area.ts +9 -0
- package/src/_internal/object-store-config.ts +101 -0
- package/src/_internal/object-store-key.ts +14 -0
- package/src/_internal/page-responses.ts +34 -3
- package/src/_internal/process-identity.ts +7 -2
- package/src/_internal/registry-validation.ts +15 -1
- package/src/_internal/registry.ts +44 -1
- package/src/_internal/runtime-context.ts +9 -1
- package/src/_internal/runtime-watcher.ts +8 -0
- package/src/_internal/status-preserving-ssr.ts +12 -1
- package/src/access/AppAccessEditor.browser-fixture.ts +429 -0
- package/src/access/AppAccessEditor.browser-frame.tsx +68 -0
- package/src/access/AppAccessEditor.browser-harness.tsx +65 -0
- package/src/access/AppAccessEditor.tsx +380 -0
- package/src/access/PermissionEditor.browser-harness.tsx +22 -2
- package/src/access/PermissionEditor.tsx +386 -77
- package/src/access/PrincipalAvatar.tsx +63 -0
- package/src/access/PrincipalPicker.tsx +29 -8
- package/src/access/ResourceApiKeys.tsx +3 -4
- package/src/access/app-access-adapter.ts +51 -0
- package/src/access/app-access-messages.ts +172 -0
- package/src/access/messages.ts +14 -0
- package/src/access/ui.ts +4 -1
- package/src/account/Avatar.tsx +21 -3
- package/src/account/ProfilePictureDialog.tsx +699 -0
- package/src/account/profile-picture-messages.ts +269 -0
- package/src/account/ui.ts +8 -1
- package/src/ai/admin.ts +3 -0
- package/src/ai/app-frame.ts +12 -0
- package/src/ai/application-tasks.ts +101 -0
- package/src/ai/assistant-models.ts +126 -64
- package/src/ai/capabilities.ts +19 -4
- package/src/ai/capability-execution.ts +5 -2
- package/src/ai/chart-block.ts +63 -30
- package/src/ai/chat/chart-block.tsx +12 -3
- package/src/ai/chat/composer-adapter.ts +8 -7
- package/src/ai/chat/message-actions.tsx +1 -1
- package/src/ai/chat/message-utils.ts +2 -2
- package/src/ai/chat/presentation.tsx +22 -1
- package/src/ai/chat-quotas.ts +5 -4
- package/src/ai/chat-tasks.ts +2 -2
- package/src/ai/client/controller.ts +11 -10
- package/src/ai/client/projection.ts +3 -3
- package/src/ai/code-capability-routes.ts +1 -0
- package/src/ai/compaction.ts +3 -3
- package/src/ai/credentials.ts +13 -114
- package/src/ai/default-tool-contracts.ts +4 -3
- package/src/ai/dictation-runtime.ts +4 -4
- package/src/ai/enrich.ts +2 -2
- package/src/ai/executor.ts +38 -27
- package/src/ai/http.ts +17 -29
- package/src/ai/index.ts +11 -5
- package/src/ai/inference-calls.ts +6 -4
- package/src/ai/maintenance.ts +1 -1
- package/src/ai/memory-learning-runs.ts +5 -5
- package/src/ai/memory-learning.ts +3 -3
- package/src/ai/message-queue.ts +1 -2
- package/src/ai/migrate.ts +75 -42
- package/src/ai/model-access-migrate.ts +3 -17
- package/src/ai/model-access.ts +44 -85
- package/src/ai/model-card.tsx +134 -0
- package/src/ai/model-catalog.ts +359 -0
- package/src/ai/model-chooser-messages.ts +88 -0
- package/src/ai/model-chooser.tsx +577 -0
- package/src/ai/model-delete.ts +234 -0
- package/src/ai/model-fixture.ts +39 -0
- package/src/ai/model-icon.tsx +36 -0
- package/src/ai/model-overview.ts +53 -0
- package/src/ai/model-usage.ts +45 -0
- package/src/ai/openai-api-messages.ts +0 -4
- package/src/ai/openai-api-slots.ts +10 -2
- package/src/ai/openai-api.ts +83 -16
- package/src/ai/personal-agent.ts +1 -1
- package/src/ai/prefs.ts +12 -10
- package/src/ai/projects-routes.ts +2 -1
- package/src/ai/projects.ts +13 -12
- package/src/ai/protocol.ts +2 -2
- package/src/ai/provider-connections.ts +161 -0
- package/src/ai/provider-errors.ts +138 -0
- package/src/ai/provider-fetch.ts +4 -0
- package/src/ai/provider-retry.ts +1 -1
- package/src/ai/provider.ts +2 -1
- package/src/ai/quota-limits.ts +36 -0
- package/src/ai/quota-provider.ts +11 -2
- package/src/ai/quota-report.ts +7 -4
- package/src/ai/quotas-migrate.ts +1 -0
- package/src/ai/quotas.ts +19 -8
- package/src/ai/recent-resources.ts +6 -0
- package/src/ai/request-headers.ts +14 -87
- package/src/ai/resource-refs.ts +6 -2
- package/src/ai/routes.ts +17 -18
- package/src/ai/runtime.ts +50 -22
- package/src/ai/settings.ts +93 -580
- package/src/ai/store.ts +45 -23
- package/src/ai/stream.ts +1 -1
- package/src/ai/structured-runs.ts +2 -2
- package/src/ai/structured.ts +29 -46
- package/src/ai/task-contracts.ts +25 -5
- package/src/ai/task-execution.ts +15 -6
- package/src/ai/task-model.ts +9 -0
- package/src/ai/transcription.ts +37 -21
- package/src/ai/turn-failure.ts +24 -2
- package/src/ai/types.ts +50 -62
- package/src/ai/ui.tsx +13 -0
- package/src/ai/usage.ts +8 -8
- package/src/ai/validate.ts +8 -7
- package/src/ai/view-block.ts +2 -2
- package/src/api/accounts-entities.ts +40 -16
- package/src/api/admin-ai-quotas.ts +34 -56
- package/src/api/admin-ai-usage.ts +1 -1
- package/src/api/admin-ai.ts +173 -0
- package/src/api/admin-core-settings.ts +68 -244
- package/src/api/admin-directory-shares.ts +55 -0
- package/src/api/admin-identity.ts +81 -2
- package/src/api/app-access.ts +85 -0
- package/src/api/app-approval.ts +3 -1
- package/src/api/app-event-delivery.ts +51 -0
- package/src/api/app-events.ts +123 -0
- package/src/api/app-resource-access.ts +48 -0
- package/src/api/auth/account-mismatch.ts +24 -0
- package/src/api/auth.ts +26 -3
- package/src/api/capabilities.ts +127 -15
- package/src/api/capability-streams.ts +2 -5
- package/src/api/identity-child-invocation.ts +145 -0
- package/src/api/index.ts +11 -2
- package/src/api/mcp.ts +180 -5
- package/src/api/me.ts +38 -17
- package/src/api/pwa-phone.ts +87 -48
- package/src/api/pwa.ts +34 -8
- package/src/api/resource-links.ts +83 -6
- package/src/api/resource-resolve.ts +50 -0
- package/src/api/search/schemas.ts +3 -1
- package/src/api/search.ts +9 -7
- package/src/api/widgets.ts +1 -0
- package/src/app-pwa/authority.ts +75 -0
- package/src/app-pwa/contracts.ts +177 -0
- package/src/app-pwa/core-query-error.ts +20 -0
- package/src/app-pwa/index.ts +23 -0
- package/src/app-pwa/protocol.ts +27 -0
- package/src/app-pwa/schema.ts +59 -0
- package/src/app-pwa/service.ts +861 -0
- package/src/app-pwa/transaction.ts +338 -0
- package/src/app-pwa/transport-input.ts +57 -0
- package/src/app-pwa/transport.ts +235 -0
- package/src/approvals/messages.ts +2 -2
- package/src/browser/app-access-recovery.ts +44 -0
- package/src/browser/app-session.ts +14 -3
- package/src/browser/cloud-id.ts +86 -0
- package/src/browser/live-websocket.ts +5 -0
- package/src/browser/pwa-drafts.ts +57 -0
- package/src/browser/resource-clipboard.ts +4 -0
- package/src/browser/resource-links.ts +52 -0
- package/src/browser/resource-picker.tsx +3 -2
- package/src/capabilities/calendar-sources.ts +302 -0
- package/src/capabilities/executions.ts +10 -3
- package/src/capabilities/migrate.ts +4 -0
- package/src/capabilities/nested.ts +43 -0
- package/src/capabilities/server-invoke.ts +202 -0
- package/src/capabilities/server.ts +26 -187
- package/src/capabilities/testing.ts +5 -2
- package/src/cli/access.ts +6 -5
- package/src/cli/account.ts +57 -0
- package/src/cli/admin/agents.ts +66 -0
- package/src/cli/admin/ai-models.ts +199 -0
- package/src/cli/admin/ai-quotas.ts +6 -102
- package/src/cli/admin/ai-usage.ts +4 -4
- package/src/cli/admin/app-credentials.ts +5 -3
- package/src/cli/admin/index.ts +7 -3
- package/src/cli/app-access.ts +60 -0
- package/src/cli/apps.ts +89 -26
- package/src/cli/avatar.ts +64 -0
- package/src/cli/capabilities.ts +22 -1
- package/src/cli/events.ts +320 -0
- package/src/cli/index.ts +1 -1
- package/src/config/env.ts +40 -0
- package/src/contracts/app-access.ts +52 -5
- package/src/contracts/app-approval.ts +8 -1
- package/src/contracts/app-details.ts +89 -0
- package/src/contracts/app-events.ts +51 -0
- package/src/contracts/app.ts +24 -5
- package/src/contracts/calendar-source.ts +274 -0
- package/src/contracts/calendar-view.ts +35 -0
- package/src/contracts/capabilities.ts +164 -3
- package/src/contracts/geo-admin.ts +2 -0
- package/src/contracts/geo-route.ts +0 -11
- package/src/contracts/geo.ts +14 -2
- package/src/contracts/index.ts +6 -0
- package/src/contracts/installable.ts +40 -0
- package/src/contracts/notification-types.ts +36 -9
- package/src/contracts/profile.ts +32 -0
- package/src/contracts/pwa-builds.ts +14 -0
- package/src/contracts/pwa-location.ts +38 -0
- package/src/contracts/pwa.ts +24 -3
- package/src/contracts/registry.ts +8 -0
- package/src/contracts/resource-clipboard.ts +35 -0
- package/src/contracts/resource-pages.ts +140 -0
- package/src/contracts/resource-resolution.ts +13 -0
- package/src/contracts/shared.ts +4 -0
- package/src/contracts/user-notifications.ts +2 -0
- package/src/events/app-event-delivery.ts +100 -0
- package/src/events/app-events.testing.ts +65 -0
- package/src/events/app-events.ts +134 -0
- package/src/events/core-user-created.ts +24 -0
- package/src/events/index.ts +9 -0
- package/src/events/testing.ts +2 -0
- package/src/index.ts +2 -1
- package/src/server/api/respond.ts +8 -3
- package/src/server/index.ts +1 -0
- package/src/server/middleware/app-access.ts +7 -6
- package/src/server/middleware/auth.ts +168 -66
- package/src/server/middleware/index.ts +1 -0
- package/src/server/middleware/invocation.ts +4 -2
- package/src/server/middleware/workload.ts +3 -3
- package/src/server/oauth-scope.ts +10 -0
- package/src/server/public-storage.ts +106 -0
- package/src/server/services/access.ts +8 -0
- package/src/services/accounts/app.ts +35 -3
- package/src/services/accounts/avatar.ts +342 -35
- package/src/services/accounts/base-group.ts +4 -5
- package/src/services/accounts/directory-shares.ts +157 -0
- package/src/services/accounts/entities.ts +50 -6
- package/src/services/accounts/groups.ts +3 -1
- package/src/services/accounts/identities.ts +64 -12
- package/src/services/accounts/local-groups.ts +1 -1
- package/src/services/accounts/users.ts +23 -15
- package/src/services/app-access-management.ts +519 -0
- package/src/services/app-access.ts +25 -7
- package/src/services/app-approval.ts +15 -4
- package/src/services/app-details.ts +224 -0
- package/src/services/app-discovery.ts +2 -1
- package/src/services/app-event-shapes.ts +139 -0
- package/src/services/app-events/accept.ts +116 -0
- package/src/services/app-events/admin.ts +250 -0
- package/src/services/app-events/declarations.ts +187 -0
- package/src/services/app-events/deliver.ts +218 -0
- package/src/services/app-events.ts +92 -0
- package/src/services/config-conflict.ts +11 -0
- package/src/services/core-user-events.ts +1 -0
- package/src/services/freeipa-config.ts +9 -0
- package/src/services/geo/admin.ts +4 -1
- package/src/services/geo/ledger.ts +47 -14
- package/src/services/geo/route-chain.ts +40 -18
- package/src/services/geo/route-estimate.ts +19 -0
- package/src/services/geo/route-plan.ts +0 -2
- package/src/services/geo/route-service.ts +57 -39
- package/src/services/geo/service.ts +51 -25
- package/src/services/identity/core-origin.ts +12 -0
- package/src/services/identity/index.ts +2 -1
- package/src/services/identity/invocation-actor.ts +50 -2
- package/src/services/identity/invocation-authority.ts +38 -1
- package/src/services/identity/invocation-token.ts +255 -50
- package/src/services/identity/issue-invocation.ts +9 -1
- package/src/services/identity/models-only-auth.ts +13 -4
- package/src/services/identity/nested-invocation.ts +128 -0
- package/src/services/image-metadata.ts +65 -1
- package/src/services/index.ts +24 -1
- package/src/services/ipa/sync.ts +6 -2
- package/src/services/ipa/users.ts +4 -1
- package/src/services/mandates/policy.ts +19 -12
- package/src/services/notifications/browser.ts +4 -0
- package/src/services/notifications/catalog.ts +5 -2
- package/src/services/notifications/platform.ts +7 -2
- package/src/services/notifications/user.ts +18 -7
- package/src/services/oauth-tokens.ts +28 -2
- package/src/services/object-store.ts +217 -0
- package/src/services/providers/local/users.ts +5 -0
- package/src/services/pwa-devices.ts +147 -37
- package/src/services/service-account-credentials.ts +5 -2
- package/src/services/session/index.ts +14 -0
- package/src/services/settings/core-settings.ts +91 -47
- package/src/services/settings/index.ts +8 -0
- package/src/services/settings/versions.ts +26 -0
- package/src/shared/ai-models.ts +274 -0
- package/src/shared/ai-quotas.ts +2 -2
- package/src/shared/ai-usage.ts +2 -2
- package/src/shared/index.ts +2 -0
- package/src/shared-text/documents.ts +25 -8
- package/src/shared-text/log.ts +1 -1
- package/src/shared-text/text-diff.ts +75 -0
- package/src/ssr/AdminArea.tsx +131 -0
- package/src/ssr/AdminLayout.tsx +11 -3
- package/src/ssr/AdminSidebar.tsx +7 -7
- package/src/ssr/AppAccessDenied.tsx +114 -0
- package/src/ssr/AppBadge.tsx +14 -0
- package/src/ssr/AppLaunchpadPanel.tsx +1 -1
- package/src/ssr/AppPwaRuntime.island.tsx +82 -0
- package/src/ssr/CloudShell.island.tsx +25 -4
- package/src/ssr/Layout.tsx +15 -7
- package/src/ssr/PwaLayout.tsx +73 -8
- package/src/ssr/PwaPartCount.island.tsx +23 -0
- package/src/ssr/PwaRuntime.island.tsx +85 -6
- package/src/ssr/SettingsSaveOutcome.tsx +58 -0
- package/src/ssr/SettingsSaveStatus.island.tsx +16 -0
- package/src/ssr/ShellRuntime.island.tsx +5 -0
- package/src/ssr/__snapshots__/Layout.unchanged.render.test.tsx.snap +3 -3
- package/src/ssr/__snapshots__/LayoutHelp.ssr.render.test.tsx.snap +1 -1
- package/src/ssr/admin-active-link.ts +16 -0
- package/src/ssr/admin-navigation.ts +26 -20
- package/src/ssr/app-badges.ts +31 -7
- package/src/ssr/app-pwa-document.tsx +16 -0
- package/src/ssr/app-pwa-messages.ts +17 -0
- package/src/ssr/index.ts +8 -0
- package/src/ssr/layout-context.ts +1 -1
- package/src/ssr/page-trail-runtime.ts +3 -1
- package/src/ssr/platform-messages.ts +9 -1
- package/src/ssr/pwa-messages.ts +10 -2
- package/src/ssr/rail-navigation.ts +5 -1
- package/src/ssr/settings-draft.ts +153 -0
- package/src/ssr/shell-data.tsx +2 -0
- package/src/styles/global.css +1 -0
- package/src/styles/profile-picture.css +270 -0
- package/src/styles/utilities-navigation.css +6 -0
- package/src/workflows/ai/policy.ts +49 -0
- package/src/workflows/ai/runtime.ts +131 -21
- package/src/workflows/ai/store.ts +283 -35
- package/src/workflows/ai/types.ts +8 -2
- package/src/workflows/ai-actions.ts +148 -120
- package/src/workflows/authoring.ts +31 -0
- package/src/workflows/contracts.ts +1 -0
- package/src/workflows/definition.ts +2 -0
- package/src/workflows/editor.ts +15 -0
- package/src/workflows/index.ts +2 -1
- package/src/workflows/language/compiler.ts +34 -3
- package/src/workflows/runtime/executor.ts +132 -33
- package/src/workflows/runtime/index.ts +2 -0
- package/src/workflows/runtime/ports.ts +5 -1
- package/src/workflows/store/actions.ts +1 -1
- package/src/workflows/store/definitions.ts +5 -0
- package/src/workflows/store/runs.ts +5 -3
- package/src/workflows/store/worker.ts +7 -2
- package/src/ai/model-pricing.ts +0 -43
- package/src/ai/model-request-settings.ts +0 -98
- package/src/ai/settings-messages.ts +0 -129
- package/src/shared/ai-model-request-settings.ts +0 -21
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { assertAiTaskRequestSize } from "../ai/task-contracts";
|
|
1
2
|
import type { AiResolvedModel } from "../ai/types";
|
|
3
|
+
import { type AiModelRequest, AiModelRequestSchema, type AiResolvedModelRef } from "../shared/ai-models";
|
|
4
|
+
import { WorkflowAiAdmissionError, type WorkflowAiScope, workflowAiModelHash } from "./ai/policy";
|
|
2
5
|
import type { WorkflowAiRequestInput, WorkflowAiTask } from "./ai/types";
|
|
3
6
|
import type { WorkflowFieldSchema, WorkflowJsonValue } from "./contracts";
|
|
4
7
|
import type { WorkflowActionContext, WorkflowActionResult, WorkflowPlannedEffect } from "./definition";
|
|
@@ -7,7 +10,14 @@ import { workflowAction } from "./definition";
|
|
|
7
10
|
const text = (description: string, optional = false, maxLength = 20_000) =>
|
|
8
11
|
({ kind: "string", minLength: 1, maxLength, optional, description }) as const;
|
|
9
12
|
const identifier = (description: string) => ({ kind: "string", format: "identifier", minLength: 1, maxLength: 120, description }) as const;
|
|
10
|
-
const model =
|
|
13
|
+
const model = {
|
|
14
|
+
kind: "union",
|
|
15
|
+
optional: true,
|
|
16
|
+
variants: [
|
|
17
|
+
{ kind: "object", properties: { class: { kind: "string", enum: ["fast", "balanced", "thorough", "maximum"] } } },
|
|
18
|
+
{ kind: "object", properties: { id: text("Explicit model variant ID.", false, 241) } },
|
|
19
|
+
],
|
|
20
|
+
} as const satisfies WorkflowFieldSchema;
|
|
11
21
|
const prompt = text("Instructions for the AI task.");
|
|
12
22
|
const choices = {
|
|
13
23
|
kind: "array",
|
|
@@ -58,10 +68,13 @@ type WorkflowAiActionDependencies = {
|
|
|
58
68
|
stepKey: string;
|
|
59
69
|
effectKey: string;
|
|
60
70
|
request: WorkflowAiRequestInput;
|
|
61
|
-
|
|
71
|
+
modelId: string;
|
|
72
|
+
modelRef?: AiResolvedModelRef;
|
|
73
|
+
modelConfigHash?: string;
|
|
74
|
+
scope?: WorkflowAiScope;
|
|
62
75
|
}): Promise<{ task: WorkflowAiTask; created: boolean }>;
|
|
63
76
|
exists(effectKey: string): Promise<boolean>;
|
|
64
|
-
resolveModel(
|
|
77
|
+
resolveModel(model?: AiModelRequest): Promise<AiResolvedModel>;
|
|
65
78
|
submit(taskId: string): Promise<void>;
|
|
66
79
|
};
|
|
67
80
|
|
|
@@ -83,7 +96,11 @@ const dependencies = async (): Promise<WorkflowAiActionDependencies> => {
|
|
|
83
96
|
const failureCode = (error: unknown): string => {
|
|
84
97
|
const code =
|
|
85
98
|
(error as { aiError?: { code?: unknown }; code?: unknown } | null)?.aiError?.code ?? (error as { code?: unknown } | null)?.code;
|
|
86
|
-
return typeof code === "string"
|
|
99
|
+
return typeof code === "string"
|
|
100
|
+
? code.startsWith("WORKFLOW_AI_")
|
|
101
|
+
? code
|
|
102
|
+
: `WORKFLOW_AI_${code.toUpperCase()}`
|
|
103
|
+
: "WORKFLOW_AI_UNAVAILABLE";
|
|
87
104
|
};
|
|
88
105
|
|
|
89
106
|
const taskResult = (task: WorkflowAiTask): WorkflowActionResult<WorkflowJsonValue> | null => {
|
|
@@ -105,6 +122,7 @@ export const runWorkflowAiAction = async (
|
|
|
105
122
|
ctx: Pick<WorkflowActionContext, "runId" | "stepKey" | "effectKey">,
|
|
106
123
|
request: WorkflowAiRequestInput,
|
|
107
124
|
injected?: WorkflowAiActionDependencies,
|
|
125
|
+
scope?: () => Promise<WorkflowAiScope>,
|
|
108
126
|
): Promise<WorkflowActionResult<WorkflowJsonValue>> => {
|
|
109
127
|
const deps = injected ?? (await dependencies());
|
|
110
128
|
try {
|
|
@@ -113,14 +131,17 @@ export const runWorkflowAiAction = async (
|
|
|
113
131
|
if (terminal) return terminal;
|
|
114
132
|
|
|
115
133
|
if (!task) {
|
|
116
|
-
|
|
134
|
+
assertAiTaskRequestSize(request);
|
|
135
|
+
const resolved = await deps.resolveModel(request.model);
|
|
117
136
|
task = (
|
|
118
137
|
await deps.create({
|
|
119
138
|
runId: ctx.runId,
|
|
120
139
|
stepKey: ctx.stepKey,
|
|
121
140
|
effectKey: ctx.effectKey,
|
|
122
141
|
request,
|
|
123
|
-
|
|
142
|
+
modelId: resolved.profile.id,
|
|
143
|
+
modelRef: resolved.model,
|
|
144
|
+
...(scope ? { scope: await scope(), modelConfigHash: workflowAiModelHash(resolved.profile) } : {}),
|
|
124
145
|
})
|
|
125
146
|
).task;
|
|
126
147
|
const racedTerminal = taskResult(task);
|
|
@@ -134,7 +155,7 @@ export const runWorkflowAiAction = async (
|
|
|
134
155
|
state: "failed",
|
|
135
156
|
code: failureCode(error),
|
|
136
157
|
message: error instanceof Error ? error.message : "Workflow AI task is unavailable.",
|
|
137
|
-
retryable: failureCode(error) === "WORKFLOW_AI_UNAVAILABLE",
|
|
158
|
+
retryable: error instanceof WorkflowAiAdmissionError ? error.retryable : failureCode(error) === "WORKFLOW_AI_UNAVAILABLE",
|
|
138
159
|
};
|
|
139
160
|
}
|
|
140
161
|
};
|
|
@@ -149,124 +170,131 @@ export const workflowAiActionCost = async (
|
|
|
149
170
|
|
|
150
171
|
const planWorkflowAiAction = async (summary: string): Promise<WorkflowPlannedEffect> => ({
|
|
151
172
|
summary,
|
|
173
|
+
outputUnavailable: true,
|
|
152
174
|
issues: ["AI output is not available during a dry run."],
|
|
153
175
|
});
|
|
154
176
|
|
|
155
|
-
export const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
kind: "
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
177
|
+
export const createWorkflowAiActions = (options?: { scope(ctx: WorkflowActionContext): Promise<WorkflowAiScope> }) => {
|
|
178
|
+
const run = (ctx: WorkflowActionContext, request: WorkflowAiRequestInput) =>
|
|
179
|
+
runWorkflowAiAction(ctx, request, undefined, options ? () => options.scope(ctx) : undefined);
|
|
180
|
+
return {
|
|
181
|
+
aiExtractData: workflowAction.idempotent<typeof extractDataConfig, WorkflowJsonValue>({
|
|
182
|
+
label: "AI extract structured data",
|
|
183
|
+
description: "Extracts one bounded, validated object from supplied input.",
|
|
184
|
+
outputType: "core.value",
|
|
185
|
+
config: extractDataConfig,
|
|
186
|
+
cost: (ctx) => (ctx.invocation.mode === "dryRun" ? { maxAiCalls: 1 } : workflowAiActionCost(ctx)),
|
|
187
|
+
plan: () => planWorkflowAiAction("Extract structured data with AI."),
|
|
188
|
+
run: (ctx, values) =>
|
|
189
|
+
run(ctx, {
|
|
190
|
+
kind: "extract_data",
|
|
191
|
+
input: values.input,
|
|
192
|
+
prompt: values.prompt,
|
|
193
|
+
fields: values.fields,
|
|
194
|
+
...(values.model ? { model: AiModelRequestSchema.parse(values.model) } : {}),
|
|
195
|
+
}),
|
|
196
|
+
}),
|
|
197
|
+
aiGenerateText: workflowAction.idempotent({
|
|
198
|
+
label: "AI generate text",
|
|
199
|
+
description: "Generates one bounded text value without performing a domain action.",
|
|
200
|
+
outputType: "core.text",
|
|
201
|
+
config: {
|
|
202
|
+
kind: "object",
|
|
203
|
+
properties: {
|
|
204
|
+
prompt,
|
|
205
|
+
input: { kind: "value", optional: true, description: "Optional JSON input supplied separately from the prompt." },
|
|
206
|
+
model,
|
|
207
|
+
maxOutputChars: {
|
|
208
|
+
kind: "number",
|
|
209
|
+
integer: true,
|
|
210
|
+
minimum: 1,
|
|
211
|
+
maximum: 20_000,
|
|
212
|
+
optional: true,
|
|
213
|
+
description: "Maximum generated text length. Defaults to 4000 characters.",
|
|
214
|
+
},
|
|
215
|
+
saveAs: identifier("Variable name for the generated text."),
|
|
189
216
|
},
|
|
190
|
-
saveAs: identifier("Variable name for the generated text."),
|
|
191
217
|
},
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
saveAs: identifier("Variable name for the selected choice."),
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
cost: (ctx) => workflowAiActionCost(ctx),
|
|
219
|
-
plan: () => planWorkflowAiAction("Classify one value with AI."),
|
|
220
|
-
run: (ctx, values) =>
|
|
221
|
-
runWorkflowAiAction(ctx, {
|
|
222
|
-
kind: "classify",
|
|
223
|
-
input: values.input,
|
|
224
|
-
prompt: values.prompt,
|
|
225
|
-
choices: values.choices,
|
|
226
|
-
...(values.model ? { modelProfileId: values.model } : {}),
|
|
227
|
-
}),
|
|
228
|
-
}),
|
|
229
|
-
aiClassifyMany: workflowAction.idempotent({
|
|
230
|
-
label: "AI classify many",
|
|
231
|
-
description: "Returns a unique subset of the declared choices in their declared order.",
|
|
232
|
-
outputType: "core.textArray",
|
|
233
|
-
config: {
|
|
234
|
-
kind: "object",
|
|
235
|
-
properties: {
|
|
236
|
-
input: { kind: "value", description: "Bounded JSON value to classify." },
|
|
237
|
-
prompt,
|
|
238
|
-
choices,
|
|
239
|
-
minChoices: {
|
|
240
|
-
kind: "number",
|
|
241
|
-
integer: true,
|
|
242
|
-
minimum: 0,
|
|
243
|
-
maximum: 50,
|
|
244
|
-
optional: true,
|
|
245
|
-
description: "Minimum number of choices. Defaults to zero.",
|
|
218
|
+
cost: (ctx) => (ctx.invocation.mode === "dryRun" ? { maxAiCalls: 1 } : workflowAiActionCost(ctx)),
|
|
219
|
+
plan: () => planWorkflowAiAction("Generate text with AI."),
|
|
220
|
+
run: (ctx, values) =>
|
|
221
|
+
run(ctx, {
|
|
222
|
+
kind: "generate_text",
|
|
223
|
+
prompt: values.prompt,
|
|
224
|
+
...(values.input === undefined ? {} : { input: values.input }),
|
|
225
|
+
...(values.model ? { model: AiModelRequestSchema.parse(values.model) } : {}),
|
|
226
|
+
...(values.maxOutputChars === undefined ? {} : { maxOutputChars: values.maxOutputChars }),
|
|
227
|
+
}),
|
|
228
|
+
}),
|
|
229
|
+
aiClassify: workflowAction.idempotent({
|
|
230
|
+
label: "AI classify",
|
|
231
|
+
description: "Returns exactly one value from the declared choices.",
|
|
232
|
+
outputType: "core.text",
|
|
233
|
+
config: {
|
|
234
|
+
kind: "object",
|
|
235
|
+
properties: {
|
|
236
|
+
input: { kind: "value", description: "Bounded JSON value to classify." },
|
|
237
|
+
prompt,
|
|
238
|
+
choices,
|
|
239
|
+
model,
|
|
240
|
+
saveAs: identifier("Variable name for the selected choice."),
|
|
246
241
|
},
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
242
|
+
},
|
|
243
|
+
cost: (ctx) => (ctx.invocation.mode === "dryRun" ? { maxAiCalls: 1 } : workflowAiActionCost(ctx)),
|
|
244
|
+
plan: () => planWorkflowAiAction("Classify one value with AI."),
|
|
245
|
+
run: (ctx, values) =>
|
|
246
|
+
run(ctx, {
|
|
247
|
+
kind: "classify",
|
|
248
|
+
input: values.input,
|
|
249
|
+
prompt: values.prompt,
|
|
250
|
+
choices: values.choices,
|
|
251
|
+
...(values.model ? { model: AiModelRequestSchema.parse(values.model) } : {}),
|
|
252
|
+
}),
|
|
253
|
+
}),
|
|
254
|
+
aiClassifyMany: workflowAction.idempotent({
|
|
255
|
+
label: "AI classify many",
|
|
256
|
+
description: "Returns a unique subset of the declared choices in their declared order.",
|
|
257
|
+
outputType: "core.textArray",
|
|
258
|
+
config: {
|
|
259
|
+
kind: "object",
|
|
260
|
+
properties: {
|
|
261
|
+
input: { kind: "value", description: "Bounded JSON value to classify." },
|
|
262
|
+
prompt,
|
|
263
|
+
choices,
|
|
264
|
+
minChoices: {
|
|
265
|
+
kind: "number",
|
|
266
|
+
integer: true,
|
|
267
|
+
minimum: 0,
|
|
268
|
+
maximum: 50,
|
|
269
|
+
optional: true,
|
|
270
|
+
description: "Minimum number of choices. Defaults to zero.",
|
|
271
|
+
},
|
|
272
|
+
maxChoices: {
|
|
273
|
+
kind: "number",
|
|
274
|
+
integer: true,
|
|
275
|
+
minimum: 0,
|
|
276
|
+
maximum: 50,
|
|
277
|
+
optional: true,
|
|
278
|
+
description: "Maximum number of choices. Defaults to all declared choices.",
|
|
279
|
+
},
|
|
280
|
+
model,
|
|
281
|
+
saveAs: identifier("Variable name for the selected choices."),
|
|
254
282
|
},
|
|
255
|
-
model,
|
|
256
|
-
saveAs: identifier("Variable name for the selected choices."),
|
|
257
283
|
},
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
}
|
|
272
|
-
}
|
|
284
|
+
cost: (ctx) => (ctx.invocation.mode === "dryRun" ? { maxAiCalls: 1 } : workflowAiActionCost(ctx)),
|
|
285
|
+
plan: () => planWorkflowAiAction("Classify multiple values with AI."),
|
|
286
|
+
run: (ctx, values) =>
|
|
287
|
+
run(ctx, {
|
|
288
|
+
kind: "classify_many",
|
|
289
|
+
input: values.input,
|
|
290
|
+
prompt: values.prompt,
|
|
291
|
+
choices: values.choices,
|
|
292
|
+
...(values.minChoices === undefined ? {} : { minChoices: values.minChoices }),
|
|
293
|
+
...(values.maxChoices === undefined ? {} : { maxChoices: values.maxChoices }),
|
|
294
|
+
...(values.model ? { model: AiModelRequestSchema.parse(values.model) } : {}),
|
|
295
|
+
}),
|
|
296
|
+
}),
|
|
297
|
+
} as const;
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export const AI_WORKFLOW_ACTIONS = createWorkflowAiActions();
|
|
@@ -64,6 +64,37 @@ export const buildWorkflowManifestCompletions = (
|
|
|
64
64
|
): WorkflowCompletionItem[] => {
|
|
65
65
|
const manifest = workflows.manifest;
|
|
66
66
|
const context = workflowCompletionContext(source, caret);
|
|
67
|
+
const indentation = context.line.match(/^\s*/)?.[0].length ?? 0;
|
|
68
|
+
const preceding = source
|
|
69
|
+
.slice(0, context.caret - context.line.length)
|
|
70
|
+
.trimEnd()
|
|
71
|
+
.split("\n");
|
|
72
|
+
const parent = preceding.findLast((line) => line.trim() && (line.match(/^\s*/)?.[0].length ?? 0) < indentation);
|
|
73
|
+
const inlineCondition = /^\s*(?:-\s*)?(?:if|not):\s*[A-Za-z]*$/.test(context.line);
|
|
74
|
+
const parentCondition = /^(\s*(?:-\s*)?)(?:if|all|any|not):\s*$/.exec(parent ?? "");
|
|
75
|
+
const blockCondition =
|
|
76
|
+
!context.key && /^\s*(?:-\s*)?[A-Za-z]*$/.test(context.line) && parentCondition && indentation > parentCondition[1]!.length;
|
|
77
|
+
if (inlineCondition || blockCondition) {
|
|
78
|
+
return [
|
|
79
|
+
"equals",
|
|
80
|
+
"notEquals",
|
|
81
|
+
"includes",
|
|
82
|
+
"textEquals",
|
|
83
|
+
"contains",
|
|
84
|
+
"startsWith",
|
|
85
|
+
"endsWith",
|
|
86
|
+
"greaterThan",
|
|
87
|
+
"lessThan",
|
|
88
|
+
"atLeast",
|
|
89
|
+
"atMost",
|
|
90
|
+
"exists",
|
|
91
|
+
"all",
|
|
92
|
+
"any",
|
|
93
|
+
"not",
|
|
94
|
+
].map((operator) =>
|
|
95
|
+
workflowCompletionItem(context, "keyword", operator, inlineCondition ? `{ ${operator}: [] }` : `${operator}: `, "Workflow condition"),
|
|
96
|
+
);
|
|
97
|
+
}
|
|
67
98
|
if (context.key === "type") {
|
|
68
99
|
return manifest.inputs.map((input) => workflowCompletionItem(context, "literal", input.kind, input.kind, input.description));
|
|
69
100
|
}
|
|
@@ -107,6 +107,7 @@ export type WorkflowIrTrigger = {
|
|
|
107
107
|
|
|
108
108
|
export type WorkflowCondition =
|
|
109
109
|
| { operator: "equals" | "notEquals"; operands: [WorkflowJsonValue, WorkflowJsonValue] }
|
|
110
|
+
| { operator: "greaterThan" | "lessThan" | "atLeast" | "atMost"; operands: [WorkflowJsonValue, WorkflowJsonValue] }
|
|
110
111
|
| { operator: "includes"; operands: [WorkflowJsonValue, WorkflowJsonValue] }
|
|
111
112
|
| { operator: "textEquals" | "contains" | "startsWith" | "endsWith"; operands: [WorkflowJsonValue, WorkflowJsonValue] }
|
|
112
113
|
| { operator: "exists"; reference: string }
|
|
@@ -144,6 +144,8 @@ export type WorkflowPlannedEffect = {
|
|
|
144
144
|
* that cannot tell a planned record from a real one will act on a fiction.
|
|
145
145
|
*/
|
|
146
146
|
output?: WorkflowJsonValue;
|
|
147
|
+
/** Omit the planned output when it cannot be predicted; explain why in `issues`. */
|
|
148
|
+
outputUnavailable?: true;
|
|
147
149
|
/** Why the plan is not fully determined — surfaced in the dry-run view. */
|
|
148
150
|
issues?: string[];
|
|
149
151
|
};
|
package/src/workflows/editor.ts
CHANGED
|
@@ -77,6 +77,21 @@ export const createWorkflowYamlHighlighter = (workflows?: DefinedWorkflowModule)
|
|
|
77
77
|
"required",
|
|
78
78
|
"with",
|
|
79
79
|
"if",
|
|
80
|
+
"equals",
|
|
81
|
+
"notEquals",
|
|
82
|
+
"includes",
|
|
83
|
+
"textEquals",
|
|
84
|
+
"contains",
|
|
85
|
+
"startsWith",
|
|
86
|
+
"endsWith",
|
|
87
|
+
"greaterThan",
|
|
88
|
+
"lessThan",
|
|
89
|
+
"atLeast",
|
|
90
|
+
"atMost",
|
|
91
|
+
"exists",
|
|
92
|
+
"all",
|
|
93
|
+
"any",
|
|
94
|
+
"not",
|
|
80
95
|
"then",
|
|
81
96
|
"else",
|
|
82
97
|
"switch",
|
package/src/workflows/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { WorkflowAiBudget, WorkflowAiScope } from "./ai/policy";
|
|
2
|
+
export { AI_WORKFLOW_ACTIONS, createWorkflowAiActions } from "./ai-actions";
|
|
2
3
|
export {
|
|
3
4
|
buildWorkflowManifestCompletions,
|
|
4
5
|
type WorkflowCompletionContext,
|
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
} from "../contracts";
|
|
15
15
|
import type { DefinedWorkflowModule } from "../module";
|
|
16
16
|
import { hashWorkflowJson, hashWorkflowSource, normalizeWorkflowJson } from "./canonical";
|
|
17
|
+
import { parseWorkflowValueString } from "./expressions";
|
|
17
18
|
import { validateWorkflowField, workflowDiagnostic, workflowRecord } from "./schema";
|
|
18
19
|
import { parseWorkflowYaml } from "./strict-yaml";
|
|
19
20
|
|
|
@@ -212,9 +213,23 @@ const compileCondition = (
|
|
|
212
213
|
const operators = Object.keys(value);
|
|
213
214
|
if (
|
|
214
215
|
operators.length !== 1 ||
|
|
215
|
-
![
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
![
|
|
217
|
+
"equals",
|
|
218
|
+
"notEquals",
|
|
219
|
+
"includes",
|
|
220
|
+
"textEquals",
|
|
221
|
+
"contains",
|
|
222
|
+
"startsWith",
|
|
223
|
+
"endsWith",
|
|
224
|
+
"greaterThan",
|
|
225
|
+
"lessThan",
|
|
226
|
+
"atLeast",
|
|
227
|
+
"atMost",
|
|
228
|
+
"exists",
|
|
229
|
+
"all",
|
|
230
|
+
"any",
|
|
231
|
+
"not",
|
|
232
|
+
].includes(operators[0]!)
|
|
218
233
|
) {
|
|
219
234
|
addDiagnostic(context, "condition.operator", "Condition must contain exactly one supported operator", path);
|
|
220
235
|
return undefined;
|
|
@@ -247,6 +262,22 @@ const compileCondition = (
|
|
|
247
262
|
addDiagnostic(context, "condition.operands", `${operator} requires exactly two operands`, [...path, operator]);
|
|
248
263
|
return undefined;
|
|
249
264
|
}
|
|
265
|
+
if (operator === "greaterThan" || operator === "lessThan" || operator === "atLeast" || operator === "atMost") {
|
|
266
|
+
operand.forEach((value, index) => {
|
|
267
|
+
const expression = typeof value === "string" ? parseWorkflowValueString(value) : undefined;
|
|
268
|
+
if (
|
|
269
|
+
(typeof value !== "number" || !Number.isFinite(value)) &&
|
|
270
|
+
(expression?.kind !== "expression" || expression.expression.kind !== "reference")
|
|
271
|
+
) {
|
|
272
|
+
addDiagnostic(context, "condition.type", `${operator} operand ${index + 1} must be a finite number or reference`, [
|
|
273
|
+
...path,
|
|
274
|
+
operator,
|
|
275
|
+
index,
|
|
276
|
+
]);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
return { operator, operands: [normalizeWorkflowJson(operand[0]!), normalizeWorkflowJson(operand[1]!)] };
|
|
280
|
+
}
|
|
250
281
|
return {
|
|
251
282
|
operator: operator as "equals" | "notEquals" | "includes" | "textEquals" | "contains" | "startsWith" | "endsWith",
|
|
252
283
|
operands: [normalizeWorkflowJson(operand[0]!), normalizeWorkflowJson(operand[1]!)],
|