@k2b/cloud 0.46.0 → 0.47.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.
Files changed (68) hide show
  1. package/package.json +8 -4
  2. package/scripts/build.ts +5 -1
  3. package/scripts/preload.ts +5 -1
  4. package/src/_internal/define-app.ts +38 -0
  5. package/src/_internal/heartbeat.ts +19 -0
  6. package/src/_internal/postgres-application-name.ts +11 -0
  7. package/src/_internal/process-sync.ts +9 -0
  8. package/src/_internal/readiness.ts +6 -1
  9. package/src/_internal/resource-principals.ts +4 -34
  10. package/src/_internal/workload-credential.ts +153 -0
  11. package/src/_internal/workload-protocol.ts +36 -0
  12. package/src/ai/application-tasks.ts +5 -2
  13. package/src/ai/chart-block.ts +36 -711
  14. package/src/ai/default-tool-contracts.ts +21 -259
  15. package/src/api/admin-app-keys.ts +66 -0
  16. package/src/api/admin-core-settings.ts +2 -0
  17. package/src/api/admin-identity.ts +27 -1
  18. package/src/api/admin-settings-env.ts +120 -0
  19. package/src/api/capabilities.ts +9 -3
  20. package/src/api/index.ts +3 -0
  21. package/src/api/settings-ops.ts +35 -0
  22. package/src/app-key.ts +125 -0
  23. package/src/browser/CloudResourceSearch.tsx +48 -41
  24. package/src/capabilities/discussion-providers.ts +3 -2
  25. package/src/capabilities/resource-readers.ts +13 -2
  26. package/src/capabilities/response.ts +4 -1
  27. package/src/capabilities/server-invoke.ts +46 -28
  28. package/src/capabilities/server.ts +1 -1
  29. package/src/capabilities/types.ts +1 -1
  30. package/src/cli/admin/app-credentials.ts +32 -7
  31. package/src/cli/admin/app-keys.ts +226 -0
  32. package/src/cli/admin/index.ts +7 -1
  33. package/src/cli/admin/settings.ts +62 -0
  34. package/src/config/define-env.ts +63 -8
  35. package/src/config/env.ts +27 -21
  36. package/src/config/index.ts +12 -1
  37. package/src/config/workflow-ai.ts +28 -0
  38. package/src/contracts/settings-env.ts +21 -0
  39. package/src/contracts/settings-types.ts +6 -0
  40. package/src/index.ts +9 -0
  41. package/src/runtime/clients.ts +72 -0
  42. package/src/runtime/connections.ts +37 -0
  43. package/src/runtime/resolve-connections.ts +91 -0
  44. package/src/server/client-ip.ts +1 -1
  45. package/src/services/app-keys.ts +298 -0
  46. package/src/services/gateway.ts +6 -0
  47. package/src/services/identity/index.ts +3 -0
  48. package/src/services/identity/resource-readers.ts +80 -0
  49. package/src/services/identity/runtime-config.ts +14 -6
  50. package/src/services/identity/workload-runtime.ts +253 -0
  51. package/src/services/index.ts +4 -1
  52. package/src/services/outgoing-mail/resolve-host.ts +5 -4
  53. package/src/services/service-account-credentials.ts +63 -21
  54. package/src/services/settings/api.ts +3 -3
  55. package/src/services/settings/binding.ts +45 -0
  56. package/src/services/settings/core-settings.ts +99 -1
  57. package/src/services/settings/defaults.ts +16 -2
  58. package/src/services/settings/env-status.ts +69 -0
  59. package/src/services/settings/index.ts +69 -26
  60. package/src/services/settings/store.ts +73 -8
  61. package/src/services/settings/validation.ts +40 -0
  62. package/src/shared/index.ts +11 -10
  63. package/src/shared/markdown/extensions/tables.ts +10 -1
  64. package/src/start.ts +36 -0
  65. package/src/workflows/ai/index.ts +1 -0
  66. package/src/workflows/ai/runtime.ts +16 -8
  67. package/src/workflows/ai/settings.ts +5 -0
  68. package/src/shared/markdown/formula.ts +0 -1283
package/src/start.ts ADDED
@@ -0,0 +1,36 @@
1
+ // Keep this entry independent of the platform barrel and application modules.
2
+ import { initializeClients } from "./runtime/clients";
3
+ import { bindConnections, hasConnections } from "./runtime/connections";
4
+ import { resolveConnections } from "./runtime/resolve-connections";
5
+
6
+ export type PlatformStartOptions = {
7
+ appId: string;
8
+ /** Core and Gateway always use infrastructure environment values. */
9
+ source?: "env";
10
+ };
11
+
12
+ /** Initialize before importing any application module, also in dev and data workers. */
13
+ export const initializePlatform = async ({ appId, source }: PlatformStartOptions): Promise<void> => {
14
+ if (!/^[a-z][a-z0-9-]{0,79}$/.test(appId)) throw new Error("Platform start requires a valid appId");
15
+ if (hasConnections()) throw new Error("Platform has already started");
16
+ if (appId === "core" || appId === "gateway") source = "env";
17
+ // Slice 6b seam: validate the app key and fetch missing values from Core here,
18
+ // then pass the typed response to resolveConnections({ appId, core }).
19
+ // A present key must never silently fall back to the legacy env mode.
20
+ if (source !== "env" && (process.env.CLOUD_APP_KEY?.trim() || process.env.CLOUD_APP_KEY_FILE?.trim())) {
21
+ throw new Error("Core connection bootstrap is not available yet");
22
+ }
23
+ const resolved = resolveConnections({ appId });
24
+ bindConnections(resolved);
25
+ try {
26
+ await initializeClients();
27
+ } catch (error) {
28
+ bindConnections(undefined);
29
+ throw error;
30
+ }
31
+ };
32
+
33
+ export const startPlatform = async <T>({ load, ...options }: PlatformStartOptions & { load: () => Promise<T> }): Promise<T> => {
34
+ await initializePlatform(options);
35
+ return load();
36
+ };
@@ -1,4 +1,5 @@
1
1
  export { startWorkflowAiRuntime, stopWorkflowAiRuntime, submitWorkflowAiTask, type WorkflowAiRuntimeOptions } from "./runtime";
2
+ export { getWorkflowAiBudget } from "./settings";
2
3
  export {
3
4
  createWorkflowAiTask,
4
5
  getWorkflowAiTask,
@@ -7,8 +7,10 @@ import { resolveAiWorkflowModel, runAiStructured } from "../../ai/structured";
7
7
  import { executeAiTask } from "../../ai/task-execution";
8
8
  import { resolveApplicationAiTaskModel } from "../../ai/task-model";
9
9
  import { isAiSettingsError } from "../../ai/validate";
10
- import { env } from "../../config/env";
10
+ import { DEFAULT_WORKFLOW_AI_BUDGET } from "../../config/workflow-ai";
11
+ import { coreSettings } from "../../services/settings/api";
11
12
  import { WorkflowAiAdmissionError, workflowAiModelHash } from "./policy";
13
+ import { getWorkflowAiBudget } from "./settings";
12
14
 
13
15
  import {
14
16
  claimWorkflowAiTask,
@@ -44,13 +46,14 @@ export type WorkflowAiProcessOptions = Required<Omit<WorkflowAiRuntimeOptions, "
44
46
  attemptTimeoutMs?: number;
45
47
  };
46
48
 
49
+ let workerBudget = DEFAULT_WORKFLOW_AI_BUDGET;
47
50
  const workflowAiJob = lazySync((sync) =>
48
51
  sync.job<{ taskId: string }>({
49
52
  id: WORKFLOW_AI_JOB_ID,
50
53
  whenFull: "reject",
51
54
  owner: "cloud",
52
55
  delivery: {
53
- maxInFlight: env.WORKFLOW_AI_BUDGET.globalConcurrent,
56
+ maxInFlight: workerBudget.globalConcurrent,
54
57
  ackWaitMs: 30_000,
55
58
  maxAttempts: MAX_ATTEMPTS,
56
59
  backoffMs: [1_000, 2_000],
@@ -137,6 +140,7 @@ export const processWorkflowAiTask = async (
137
140
  ctx: { signal: AbortSignal; heartbeat(): Promise<void> },
138
141
  options: WorkflowAiProcessOptions,
139
142
  ): Promise<void> => {
143
+ const attemptTimeoutMs = options.attemptTimeoutMs ?? (await coreSettings.get<number>("ai.workflow_attempt_timeout_ms"));
140
144
  const task = await claimWorkflowAiTask(taskId);
141
145
  if (!task) {
142
146
  const terminal = await getWorkflowAiTask(taskId);
@@ -150,7 +154,7 @@ export const processWorkflowAiTask = async (
150
154
  const deadline = setTimeout(() => {
151
155
  timedOut = true;
152
156
  controller.abort(new Error("Workflow AI attempt deadline exceeded. Retry the workflow or inspect the provider."));
153
- }, options.attemptTimeoutMs ?? env.WORKFLOW_AI_ATTEMPT_TIMEOUT_MS);
157
+ }, attemptTimeoutMs);
154
158
  let canceled = false;
155
159
  let monitorError: unknown;
156
160
  let checking = false;
@@ -230,9 +234,12 @@ let recovery: Promise<void> | null = null;
230
234
  let shutdown: AbortController | null = null;
231
235
 
232
236
  const recover = (): Promise<void> => {
233
- recovery ??= expireWorkflowAiTasks(env.WORKFLOW_AI_QUEUE_TIMEOUT_MS).finally(() => {
234
- recovery = null;
235
- });
237
+ recovery ??= coreSettings
238
+ .get<number>("ai.workflow_queue_timeout_ms")
239
+ .then((timeout) => expireWorkflowAiTasks(timeout))
240
+ .finally(() => {
241
+ recovery = null;
242
+ });
236
243
  return recovery;
237
244
  };
238
245
 
@@ -242,14 +249,15 @@ export const startWorkflowAiRuntime = async (input: WorkflowAiRuntimeOptions = {
242
249
  runStructured: input.runStructured ?? runAiStructured,
243
250
  maxAttempts: MAX_ATTEMPTS,
244
251
  cancelPollMs: input.cancelPollMs ?? DEFAULT_CANCEL_POLL_MS,
245
- attemptTimeoutMs: input.attemptTimeoutMs ?? env.WORKFLOW_AI_ATTEMPT_TIMEOUT_MS,
252
+ attemptTimeoutMs: input.attemptTimeoutMs,
246
253
  };
254
+ workerBudget = await getWorkflowAiBudget();
247
255
  const next = workflowAiJob();
248
256
  activeJob = next;
249
257
  const controller = new AbortController();
250
258
  shutdown = controller;
251
259
  try {
252
- activeWorker = await next.process({ concurrency: env.WORKFLOW_AI_BUDGET.globalConcurrent }, async (context) => {
260
+ activeWorker = await next.process({ concurrency: workerBudget.globalConcurrent }, async (context) => {
253
261
  try {
254
262
  await processWorkflowAiTask(
255
263
  context.input.taskId,
@@ -0,0 +1,5 @@
1
+ import { workflowAiBudgetSchema } from "../../config/workflow-ai";
2
+ import { coreSettings } from "../../services/settings/api";
3
+
4
+ export const getWorkflowAiBudget = async () =>
5
+ workflowAiBudgetSchema.parse(JSON.parse(await coreSettings.get<string>("ai.workflow_budget")));