@k2b/cloud 0.41.0 → 0.42.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 +6 -5
- package/src/_internal/bounded-json.ts +14 -2
- package/src/_internal/capabilities.ts +87 -8
- package/src/_internal/capability-reviews.ts +6 -0
- package/src/_internal/capability-timeout.ts +71 -0
- package/src/_internal/define-app.ts +145 -89
- package/src/_internal/http-drain.ts +56 -0
- package/src/_internal/registry-validation.ts +3 -0
- package/src/_internal/runtime-context.ts +1 -0
- package/src/_internal/status-preserving-ssr.ts +2 -0
- package/src/access/PermissionEditor.tsx +16 -17
- package/src/access/PrincipalPicker.tsx +45 -10
- package/src/access/messages.ts +8 -0
- package/src/access/principal-label.ts +18 -0
- package/src/access/ui.ts +1 -0
- package/src/account/EntitySearch.tsx +5 -4
- package/src/ai/action-review.ts +2 -1
- package/src/ai/app-skill-store.ts +1 -1
- package/src/ai/capabilities.ts +21 -3
- package/src/ai/capability-execution.ts +14 -12
- package/src/ai/chat/action-card.ts +7 -1
- package/src/ai/chat/action-messages.ts +14 -0
- package/src/ai/chat/action-question.browser-harness.tsx +12 -0
- package/src/ai/chat/action-question.tsx +202 -22
- package/src/ai/chat/action-text.ts +1 -1
- package/src/ai/chat-tasks.ts +2 -1
- package/src/ai/client/controller.ts +150 -32
- package/src/ai/client/transport.ts +14 -2
- package/src/ai/code-capability-routes.ts +27 -23
- package/src/ai/code-runtime-tools.ts +14 -16
- package/src/ai/code-source-tools.ts +16 -18
- package/src/ai/executor.ts +56 -21
- package/src/ai/fetch-file-tool.ts +67 -76
- package/src/ai/http.ts +1 -0
- package/src/ai/migrate.ts +13 -0
- package/src/ai/open-questions.ts +4 -8
- package/src/ai/projects.ts +1 -2
- package/src/ai/protocol.ts +2 -2
- package/src/ai/recent-resources.ts +12 -5
- package/src/ai/review-content.ts +77 -0
- package/src/ai/routes.ts +69 -31
- package/src/ai/runtime.ts +1 -0
- package/src/ai/skill-tool.ts +17 -6
- package/src/ai/skills-routes.ts +72 -27
- package/src/ai/skills.ts +139 -60
- package/src/ai/store.ts +168 -33
- package/src/ai/types.ts +10 -3
- package/src/ai/usage.ts +2 -2
- package/src/api/admin-core-settings.ts +15 -2
- package/src/api/admin-geo.ts +54 -0
- package/src/api/admin-linux-identities.ts +6 -3
- package/src/api/admin-outgoing-mail.ts +29 -15
- package/src/api/approvals-loader.ts +3 -3
- package/src/api/approvals.ts +51 -0
- package/src/api/apps.ts +4 -2
- package/src/api/capabilities.ts +258 -181
- package/src/api/capability-streams.ts +21 -13
- package/src/api/cli-plugins.ts +4 -1
- package/src/api/geo-glyphs.ts +11 -0
- package/src/api/geo.ts +128 -0
- package/src/api/help.ts +12 -4
- package/src/api/index.ts +5 -0
- package/src/api/mcp.ts +46 -38
- package/src/api/me-panel-consent.ts +8 -5
- package/src/api/search.ts +21 -14
- package/src/api/sync-ops.ts +19 -13
- package/src/api/widgets.ts +42 -18
- package/src/approvals/Approvals.tsx +5 -3
- package/src/browser/CloudResourceSearch.browser-harness.tsx +53 -1
- package/src/browser/CloudResourceSearch.tsx +3 -13
- package/src/browser/PanelLeaveNotice.tsx +18 -0
- package/src/browser/navigation-search.ts +78 -25
- package/src/browser/panel-leave.ts +69 -0
- package/src/browser/panel-messages.ts +12 -0
- package/src/browser/panel-slot.ts +173 -24
- package/src/browser/panel.ts +3 -0
- package/src/browser/resource-search-messages.ts +2 -0
- package/src/capabilities/client.ts +28 -1
- package/src/capabilities/executions.ts +22 -3
- package/src/capabilities/geo-client.ts +57 -0
- package/src/capabilities/response.ts +2 -1
- package/src/capabilities/review-storage.ts +24 -0
- package/src/capabilities/reviews.ts +17 -3
- package/src/capabilities/server.ts +36 -16
- package/src/cli/access.ts +15 -23
- package/src/cli/admin/linux.ts +13 -2
- package/src/cli/admin/outgoing-mail.ts +26 -4
- package/src/cli/capabilities.ts +19 -0
- package/src/config/env.ts +0 -6
- package/src/contracts/app-access.ts +48 -0
- package/src/contracts/app.ts +4 -1
- package/src/contracts/approvals.ts +2 -2
- package/src/contracts/avatar.ts +186 -0
- package/src/contracts/capabilities.ts +148 -54
- package/src/contracts/geo-admin.ts +127 -0
- package/src/contracts/geo-map.ts +19 -0
- package/src/contracts/geo-route.ts +168 -0
- package/src/contracts/geo.ts +248 -0
- package/src/contracts/index.ts +4 -0
- package/src/contracts/outgoing-mail.ts +17 -4
- package/src/contracts/registry.ts +2 -0
- package/src/events/app-access.ts +68 -0
- package/src/events/live-delivery.ts +128 -0
- package/src/events/live.ts +14 -130
- package/src/geo/CloudMap.tsx +95 -0
- package/src/geo/map-messages.ts +17 -0
- package/src/geo/ui.ts +1 -0
- package/src/index.ts +2 -0
- package/src/server/client-ip.ts +36 -0
- package/src/server/index.ts +3 -4
- package/src/server/middleware/app-access.ts +312 -0
- package/src/server/middleware/auth.ts +1 -1
- package/src/server/middleware/invocation.ts +11 -0
- package/src/server/middleware/rate-limit.ts +4 -4
- package/src/server/services/access.ts +13 -9
- package/src/server/services/index.ts +0 -2
- package/src/server/services/services.ts +0 -2
- package/src/services/accounts/posix.ts +21 -7
- package/src/services/allowed-network-fetch.ts +16 -10
- package/src/services/app-access-metrics.ts +24 -0
- package/src/services/app-access.ts +123 -0
- package/src/services/app-discovery.ts +27 -0
- package/src/services/approvals/content.ts +40 -0
- package/src/services/approvals/index.ts +14 -6
- package/src/services/approvals/list.ts +6 -11
- package/src/services/approvals/question.ts +11 -7
- package/src/services/downstream-budget.ts +87 -0
- package/src/services/geo/admin.ts +262 -0
- package/src/services/geo/bucket.ts +67 -0
- package/src/services/geo/cache.ts +57 -0
- package/src/services/geo/costs.ts +5 -0
- package/src/services/geo/errors.ts +41 -0
- package/src/services/geo/fixtures/README.md +17 -0
- package/src/services/geo/fixtures/along.json +355 -0
- package/src/services/geo/fixtures/autocomplete.json +218 -0
- package/src/services/geo/fixtures/geocode.json +129 -0
- package/src/services/geo/fixtures/places.json +355 -0
- package/src/services/geo/fixtures/reverse.json +61 -0
- package/src/services/geo/fixtures/routing.json +57 -0
- package/src/services/geo/geoapify-route.ts +93 -0
- package/src/services/geo/geoapify.ts +281 -0
- package/src/services/geo/ledger.ts +122 -0
- package/src/services/geo/map.ts +160 -0
- package/src/services/geo/migrate.ts +25 -0
- package/src/services/geo/polyline.ts +184 -0
- package/src/services/geo/route-chain.ts +145 -0
- package/src/services/geo/route-costs.ts +9 -0
- package/src/services/geo/route-geometry.ts +39 -0
- package/src/services/geo/route-plan.ts +172 -0
- package/src/services/geo/route-service.ts +433 -0
- package/src/services/geo/service.ts +300 -0
- package/src/services/geo/settings.ts +49 -0
- package/src/services/help/index.ts +16 -7
- package/src/services/help/types.ts +6 -1
- package/src/services/identity/invocation-actor.ts +20 -2
- package/src/services/identity/issue-invocation.ts +67 -0
- package/src/services/identity/key-ring.ts +5 -3
- package/src/services/identity/runtime-config.ts +23 -0
- package/src/services/index.ts +9 -0
- package/src/services/mandates/index.ts +40 -3
- package/src/services/network-security.ts +6 -3
- package/src/services/network-transport.ts +99 -0
- package/src/services/notifications/catalog.ts +3 -2
- package/src/services/notifications/runtime.ts +1 -0
- package/src/services/notifications/web-push-transport.ts +45 -38
- package/src/services/outgoing-mail/dispatcher.ts +6 -1
- package/src/services/outgoing-mail/index.ts +55 -1
- package/src/services/outgoing-mail/messages.ts +82 -3
- package/src/services/outgoing-mail/resolve-host.ts +2 -2
- package/src/services/outgoing-mail/retention.ts +13 -1
- package/src/services/outgoing-mail/store.ts +36 -6
- package/src/services/outgoing-mail/test-send.ts +34 -4
- package/src/services/outgoing-mail/transport.ts +1 -1
- package/src/services/pdf/gotenberg.ts +11 -38
- package/src/services/pdf/template-preview.ts +1 -1
- package/src/services/public-http.ts +28 -40
- package/src/services/settings/app.ts +4 -1
- package/src/services/settings/core-settings.ts +88 -0
- package/src/services/settings/defaults.ts +8 -2
- package/src/services/settings/errors.ts +11 -0
- package/src/services/settings/geo-budget.ts +40 -0
- package/src/services/settings/index.ts +4 -3
- package/src/services/settings/store.ts +25 -17
- package/src/services/weather/geo.ts +29 -111
- package/src/services/weather/index.ts +4 -3
- package/src/services/weather/locations.ts +8 -5
- package/src/services/weather/migrate.ts +1 -0
- package/src/services/weather/settings.ts +0 -16
- package/src/shared/__snapshots__/avatar-art.test.ts.snap +5 -0
- package/src/shared/avatar-art.ts +400 -0
- package/src/shared/index.ts +2 -0
- package/src/shared/network-address.ts +22 -3
- package/src/shared/template-rendering.ts +36 -4
- package/src/shared-text/documents.ts +1 -1
- package/src/shared-text/index.ts +2 -0
- package/src/shared-text/log.ts +51 -3
- package/src/shared-text/snapshots.ts +340 -0
- package/src/ssr/AdminLayout.tsx +4 -2
- package/src/ssr/CloudShell.island.tsx +6 -0
- package/src/ssr/Layout.tsx +65 -15
- package/src/ssr/LayoutHelp.browser-harness.tsx +1 -1
- package/src/ssr/LayoutHelp.tsx +3 -2
- package/src/ssr/PanelRuntime.island.tsx +11 -7
- package/src/ssr/PwaLayout.tsx +2 -2
- package/src/ssr/RailApps.tsx +6 -0
- package/src/ssr/ShellRuntime.island.tsx +23 -7
- package/src/ssr/__snapshots__/Layout.unchanged.render.test.tsx.snap +151 -0
- package/src/ssr/__snapshots__/LayoutHelp.ssr.render.test.tsx.snap +6 -6
- package/src/ssr/admin-navigation.ts +1 -0
- package/src/ssr/app-badges.ts +6 -1
- package/src/ssr/compact-shell.browser-harness.ts +44 -5
- package/src/ssr/help.ts +3 -2
- package/src/ssr/index.ts +1 -1
- package/src/ssr/layout-context.ts +2 -0
- package/src/ssr/mobile-menu-history.ts +4 -0
- package/src/ssr/page-swap-fixture/Column.island.tsx +15 -0
- package/src/ssr/page-swap-fixture/ProviderProbe.island.tsx +31 -0
- package/src/ssr/page-swap.browser-harness.tsx +177 -0
- package/src/ssr/page-swap.ts +28 -0
- package/src/ssr/page-trail-runtime.ts +32 -13
- package/src/ssr/panel-consent.ts +2 -2
- package/src/ssr/panel-slot.browser-harness.tsx +3 -0
- package/src/ssr/platform-messages.ts +8 -0
- package/src/ssr/runtime.ts +17 -0
- package/src/ssr/shell-data.tsx +10 -2
- package/src/styles/global.css +70 -6
- package/src/server/services/geo.ts +0 -215
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
export * from "./capability-streams";
|
|
9
9
|
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import type { RequestAuthority } from "../server/middleware/auth";
|
|
11
12
|
import { CommandPathSchema } from "./commands";
|
|
12
13
|
import type { AccessSubject, RequestActor, User } from "./shared";
|
|
13
14
|
|
|
@@ -177,6 +178,9 @@ export type CapabilityReach = (typeof CAPABILITY_REACHES)[number];
|
|
|
177
178
|
export const CAPABILITY_ACTION_OUTCOMES = ["running", "done", "rejected", "not_run", "unknown"] as const;
|
|
178
179
|
export type CapabilityActionOutcome = (typeof CAPABILITY_ACTION_OUTCOMES)[number];
|
|
179
180
|
export const CAPABILITY_MAX_REVIEW_BYTES = 32 * 1024;
|
|
181
|
+
/** Full review text and metadata, separate from the compact card and ordinary capability results. */
|
|
182
|
+
export const CAPABILITY_MAX_REVIEW_CONTENT_BYTES = 16 * 1024 * 1024;
|
|
183
|
+
export const CAPABILITY_MAX_REVIEW_RESPONSE_BYTES = CAPABILITY_MAX_REVIEW_CONTENT_BYTES + CAPABILITY_MAX_REVIEW_BYTES + 11;
|
|
180
184
|
export const CapabilityActionPolicySchema = z.union([
|
|
181
185
|
z.object({ silent: z.enum(CAPABILITY_REACHES), routines: z.literal(false).optional() }).strict(),
|
|
182
186
|
z.object({ ask: z.enum(CAPABILITY_ASK_REASONS) }).strict(),
|
|
@@ -188,12 +192,12 @@ const reviewLine = (max: number, min = 1) =>
|
|
|
188
192
|
.string()
|
|
189
193
|
.min(min)
|
|
190
194
|
.max(max)
|
|
191
|
-
.refine((text) => !/[\p{Cc}\p{Cf}\u2028\u2029]/u.test(text), "Contains unsafe characters");
|
|
195
|
+
.refine((text) => !/[\p{Cc}\p{Cf}\p{Cs}\u2028\u2029]/u.test(text), "Contains unsafe characters");
|
|
192
196
|
const reviewBlock = (max: number) =>
|
|
193
197
|
z
|
|
194
198
|
.string()
|
|
195
199
|
.max(max)
|
|
196
|
-
.refine((text) => !/[\p{Cc}\p{Cf}\u2028\u2029]/u.test(text.replace(/[\n\t]/g, "")), "Contains unsafe characters");
|
|
200
|
+
.refine((text) => !/[\p{Cc}\p{Cf}\p{Cs}\u2028\u2029]/u.test(text.replace(/[\n\t]/g, "")), "Contains unsafe characters");
|
|
197
201
|
export const CapabilityPersonSchema = z
|
|
198
202
|
.object({ name: reviewLine(200).optional(), address: reviewLine(320).optional(), userId: z.uuid().optional() })
|
|
199
203
|
.strict()
|
|
@@ -432,60 +436,143 @@ export const CapabilityPreviewSchema = z.discriminatedUnion("kind", [
|
|
|
432
436
|
.strict(),
|
|
433
437
|
]);
|
|
434
438
|
export type CapabilityPreview = z.infer<typeof CapabilityPreviewSchema>;
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
439
|
+
/** Complete passive content; no attachment bytes, HTML, omitted entries, or silently shortened strings. */
|
|
440
|
+
// Construct complete review validators in pure calls: unrelated browser consumers of resource refs do not need them.
|
|
441
|
+
export const CapabilityReviewContentSchema = /* @__PURE__ */ (() => {
|
|
442
|
+
const fullReviewPerson = z
|
|
443
|
+
.object({
|
|
444
|
+
name: z.string().max(200).optional(),
|
|
445
|
+
address: z.string().max(320).optional(),
|
|
446
|
+
userId: z.uuid().optional(),
|
|
447
|
+
})
|
|
448
|
+
.strict()
|
|
449
|
+
.refine((person) => person.name !== undefined || person.address !== undefined, "A person needs a name or address");
|
|
450
|
+
return z
|
|
451
|
+
.discriminatedUnion("kind", [
|
|
452
|
+
z
|
|
453
|
+
.object({
|
|
454
|
+
kind: z.literal("message"),
|
|
455
|
+
baseRevision: z.number().int().nonnegative().optional(),
|
|
456
|
+
from: fullReviewPerson.optional(),
|
|
457
|
+
to: z.array(fullReviewPerson).max(600),
|
|
458
|
+
cc: z.array(fullReviewPerson).max(600).optional(),
|
|
459
|
+
bcc: z.array(fullReviewPerson).max(600).optional(),
|
|
460
|
+
subject: z.string().max(998),
|
|
461
|
+
body: z.string().max(CAPABILITY_MAX_REVIEW_CONTENT_BYTES),
|
|
462
|
+
format: z.literal("plain"),
|
|
463
|
+
attachments: z
|
|
464
|
+
.array(
|
|
465
|
+
z
|
|
466
|
+
.object({
|
|
467
|
+
name: z.string().min(1).max(255),
|
|
468
|
+
size: z.number().int().nonnegative().optional(),
|
|
469
|
+
ref: CloudResourceRefSchema.optional(),
|
|
470
|
+
})
|
|
471
|
+
.strict(),
|
|
472
|
+
)
|
|
473
|
+
.max(202)
|
|
474
|
+
.optional(),
|
|
475
|
+
sendAt: reviewTime.optional(),
|
|
476
|
+
warnings: z.array(z.string().max(300)).max(6).optional(),
|
|
477
|
+
})
|
|
478
|
+
.strict(),
|
|
479
|
+
z
|
|
480
|
+
.object({
|
|
481
|
+
kind: z.literal("page"),
|
|
482
|
+
baseRevision: z.number().int().nonnegative().optional(),
|
|
483
|
+
title: z.string().max(200),
|
|
484
|
+
place: z.string().max(200).optional(),
|
|
485
|
+
body: z.string().max(CAPABILITY_MAX_REVIEW_CONTENT_BYTES),
|
|
486
|
+
format: z.literal("plain"),
|
|
487
|
+
})
|
|
488
|
+
.strict(),
|
|
489
|
+
])
|
|
490
|
+
.superRefine((content, ctx) => {
|
|
491
|
+
if (content.kind === "message" && content.to.length + (content.cc?.length ?? 0) + (content.bcc?.length ?? 0) > 600)
|
|
492
|
+
ctx.addIssue({ code: "custom", message: "Full review content exceeds 600 recipients" });
|
|
493
|
+
if (new TextEncoder().encode(JSON.stringify(content)).byteLength > CAPABILITY_MAX_REVIEW_CONTENT_BYTES)
|
|
494
|
+
ctx.addIssue({ code: "custom", message: "Full review content exceeds 16 MiB" });
|
|
495
|
+
});
|
|
496
|
+
})();
|
|
497
|
+
export type CapabilityReviewContent = z.infer<typeof CapabilityReviewContentSchema>;
|
|
498
|
+
/** Cloud supplies this after storing a review. It is a locator, never an authorization token. */
|
|
499
|
+
export const CapabilityReviewContentRefSchema = /* @__PURE__ */ (() =>
|
|
500
|
+
z
|
|
501
|
+
.object({
|
|
502
|
+
href: z
|
|
503
|
+
.string()
|
|
504
|
+
.regex(
|
|
505
|
+
/^\/api\/approvals\/(?:[a-fA-F0-9-]{36}\/content|conversations\/[a-fA-F0-9-]{36}\/turns\/[a-fA-F0-9-]{36}\/reviews\/(?!\.{1,2}$)(?:[A-Za-z0-9_!~*'().-]|%[A-Fa-f0-9]{2})+)$/,
|
|
506
|
+
)
|
|
507
|
+
.max(2048),
|
|
508
|
+
digest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
509
|
+
})
|
|
510
|
+
.strict())();
|
|
511
|
+
export type CapabilityReviewContentRef = z.infer<typeof CapabilityReviewContentRefSchema>;
|
|
512
|
+
export const CapabilityActionCallReviewSchema = /* @__PURE__ */ (() =>
|
|
513
|
+
z
|
|
514
|
+
.object({
|
|
515
|
+
locale: z.string(),
|
|
516
|
+
sentence: z
|
|
517
|
+
.object({
|
|
518
|
+
action: reviewTemplate,
|
|
519
|
+
running: reviewTemplate,
|
|
520
|
+
done: reviewTemplate,
|
|
521
|
+
confirm: reviewTemplate,
|
|
522
|
+
decline: reviewTemplate,
|
|
523
|
+
rejected: reviewTemplate.optional(),
|
|
524
|
+
notRun: reviewTemplate.optional(),
|
|
525
|
+
short: reviewTemplate.refine((text) => text.length <= 60, "short exceeds 60 characters").optional(),
|
|
526
|
+
})
|
|
527
|
+
.strict(),
|
|
528
|
+
slots: reviewSlots.readonly(),
|
|
529
|
+
preview: CapabilityPreviewSchema.optional(),
|
|
530
|
+
content: CapabilityReviewContentSchema.optional(),
|
|
531
|
+
consequences: z.array(CapabilityConsequenceSchema).max(6).optional(),
|
|
532
|
+
ask: z.enum(CAPABILITY_ASK_REASONS).optional(),
|
|
533
|
+
reach: z.enum(CAPABILITY_REACHES).optional(),
|
|
534
|
+
effects: z.number().int().min(1).max(1000).optional(),
|
|
535
|
+
check: z
|
|
536
|
+
.object({ query: CapabilityLocalIdSchema, input: z.record(z.string(), z.unknown()) })
|
|
537
|
+
.strict()
|
|
538
|
+
.optional(),
|
|
539
|
+
scope: z.string().min(1).max(200).optional(),
|
|
540
|
+
links: z.array(CapabilitySemanticLinkSchema).max(10).optional(),
|
|
541
|
+
})
|
|
542
|
+
.strict()
|
|
543
|
+
.superRefine((review, ctx) => {
|
|
544
|
+
for (const [form, text] of Object.entries(review.sentence)) {
|
|
545
|
+
if (text === undefined) continue;
|
|
546
|
+
const complete = form === "action" || form === "running" || form === "done";
|
|
547
|
+
for (const message of capabilitySentenceIssues(text, review.slots, complete, form === "action"))
|
|
548
|
+
ctx.addIssue({ code: "custom", path: ["sentence", form], message });
|
|
549
|
+
if ((form === "confirm" || form === "decline") && [...text.matchAll(/\{[a-z][A-Za-z0-9]{0,31}\}/g)].length > 1)
|
|
550
|
+
ctx.addIssue({ code: "custom", path: ["sentence", form], message: "Buttons name at most one slot" });
|
|
551
|
+
}
|
|
552
|
+
}))();
|
|
474
553
|
export type CapabilityActionCallReview = z.infer<typeof CapabilityActionCallReviewSchema>;
|
|
475
554
|
export type CapabilityActionReviewData = CapabilityActionCallReview | CapabilityActionReview;
|
|
476
|
-
export const CapabilityActionReviewDataSchema =
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
555
|
+
export const CapabilityActionReviewDataSchema = /* @__PURE__ */ (() =>
|
|
556
|
+
z
|
|
557
|
+
.unknown()
|
|
558
|
+
.transform((value, ctx) => {
|
|
559
|
+
const schema =
|
|
560
|
+
value !== null && typeof value === "object" && Object.hasOwn(value, "sentence")
|
|
561
|
+
? CapabilityActionCallReviewSchema
|
|
562
|
+
: CapabilityActionReviewSchema;
|
|
563
|
+
const parsed = schema.safeParse(value);
|
|
564
|
+
if (parsed.success) return parsed.data;
|
|
565
|
+
for (const issue of parsed.error.issues) ctx.addIssue({ code: "custom", path: issue.path, message: issue.message });
|
|
566
|
+
return z.NEVER;
|
|
567
|
+
})
|
|
568
|
+
.pipe(z.union([CapabilityActionCallReviewSchema, CapabilityActionReviewSchema])))();
|
|
569
|
+
/** Compact Cloud presentation. Providers return the strict review above, never a client-supplied content locator. */
|
|
570
|
+
export const CapabilityActionReviewPresentationSchema = /* @__PURE__ */ (() =>
|
|
571
|
+
z.union([
|
|
572
|
+
CapabilityActionCallReviewSchema.safeExtend({ contentRef: CapabilityReviewContentRefSchema.optional() }),
|
|
573
|
+
CapabilityActionReviewSchema,
|
|
574
|
+
]))();
|
|
575
|
+
export type CapabilityActionReviewPresentation = z.infer<typeof CapabilityActionReviewPresentationSchema>;
|
|
489
576
|
export const CapabilityActionReceiptSchema = z
|
|
490
577
|
.object({ ...sentenceShape, preview: CapabilityPreviewSchema.optional() })
|
|
491
578
|
.strict()
|
|
@@ -676,6 +763,12 @@ export const UniversalSearchDataSchema = z.array(CloudResourceViewSchema).max(10
|
|
|
676
763
|
export type UniversalSearchData = z.infer<typeof UniversalSearchDataSchema>;
|
|
677
764
|
|
|
678
765
|
export type CapabilityExecutionContext = {
|
|
766
|
+
/**
|
|
767
|
+
* Resolved request authority, supplied by the framework for execution, review
|
|
768
|
+
* and streams. Optional for existing in-process callers; authority-aware
|
|
769
|
+
* services fail closed when it is absent. Preserve its credential limits.
|
|
770
|
+
*/
|
|
771
|
+
authority?: RequestAuthority;
|
|
679
772
|
actor: RequestActor;
|
|
680
773
|
accessSubject: AccessSubject;
|
|
681
774
|
user: User | null;
|
|
@@ -695,6 +788,7 @@ export type CapabilityExecutionContext = {
|
|
|
695
788
|
requestId: string;
|
|
696
789
|
/** Cloud surface that invoked this capability. */
|
|
697
790
|
origin: CapabilityOrigin;
|
|
791
|
+
/** Caller cancellation or shared dispatch deadline; forward it to expensive work. */
|
|
698
792
|
signal: AbortSignal;
|
|
699
793
|
};
|
|
700
794
|
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/** Geoapify plans in the order the administration offers them. */
|
|
4
|
+
export const GEO_PLAN_IDS = ["free", "api10", "api25", "api50", "api100", "api250", "custom"] as const;
|
|
5
|
+
export type GeoPlanId = (typeof GEO_PLAN_IDS)[number];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Ledger function groups in display order. Every paid geo call reserves under one of these groups;
|
|
9
|
+
* the administration shows one share line per group.
|
|
10
|
+
*/
|
|
11
|
+
export const GEO_USAGE_GROUPS = ["tiles", "places", "route", "address"] as const;
|
|
12
|
+
export type GeoUsageGroup = (typeof GEO_USAGE_GROUPS)[number];
|
|
13
|
+
|
|
14
|
+
/** Largest credit value a geo budget setting accepts (stored as thousandths in a bigint ledger). */
|
|
15
|
+
export const GEO_MAX_CREDITS = Math.floor(Number.MAX_SAFE_INTEGER / 1000);
|
|
16
|
+
/** Largest custom request rate the token bucket accepts. */
|
|
17
|
+
export const GEO_MAX_RPS = Math.floor(Number.MAX_SAFE_INTEGER / 9000);
|
|
18
|
+
/** Upper bound of a pasted provider key; Geoapify keys are 32 characters. */
|
|
19
|
+
export const GEO_MAX_KEY_LENGTH = 256;
|
|
20
|
+
|
|
21
|
+
export type GeoAdminPerson = { id: string; name: string };
|
|
22
|
+
|
|
23
|
+
export type GeoAdminKey = {
|
|
24
|
+
/** `unreadable`: a stored key exists but this installation cannot decrypt it; geo is off until it is replaced or removed. */
|
|
25
|
+
state: "none" | "set" | "unreadable";
|
|
26
|
+
setAt: string | null;
|
|
27
|
+
setBy: GeoAdminPerson | null;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type GeoAdminBudget = {
|
|
31
|
+
plan: GeoPlanId;
|
|
32
|
+
customRps: number;
|
|
33
|
+
customDailyCredits: number;
|
|
34
|
+
monthlyCredits: number;
|
|
35
|
+
personDailyCredits: number;
|
|
36
|
+
/** Budget settings whose stored value cannot be read; saving the form replaces them. */
|
|
37
|
+
unreadable: Array<GeoBudgetField | "plan">;
|
|
38
|
+
changedAt: string | null;
|
|
39
|
+
changedBy: GeoAdminPerson | null;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type GeoAdminStatus = {
|
|
43
|
+
key: GeoAdminKey;
|
|
44
|
+
budget: GeoAdminBudget;
|
|
45
|
+
plans: Record<Exclude<GeoPlanId, "custom">, { dailyCredits: number; rps: number }>;
|
|
46
|
+
/** `app.timezone`: dates on the page and the budget periods use it. */
|
|
47
|
+
timezone: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type GeoAdminUsage = {
|
|
51
|
+
/** Credits. Values may carry fractions (a map tile costs 0.25). */
|
|
52
|
+
month: { period: string; used: number; limit: number; resetsAt: string };
|
|
53
|
+
/** Cloud-wide use today against the provider's daily allowance of the selected plan. */
|
|
54
|
+
today: { period: string; used: number; allowance: number; resetsAt: string };
|
|
55
|
+
shares: Array<{ group: GeoUsageGroup; credits: number }>;
|
|
56
|
+
/** Access subjects whose use today reached the per-person daily limit. */
|
|
57
|
+
peopleAtLimit: number;
|
|
58
|
+
timezone: string;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const GeoKeyInputSchema = z.object({ apiKey: z.string().max(GEO_MAX_KEY_LENGTH * 4) }).strict();
|
|
62
|
+
|
|
63
|
+
export const GeoBudgetInputSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
plan: z.enum(GEO_PLAN_IDS),
|
|
66
|
+
customRps: z.unknown(),
|
|
67
|
+
customDailyCredits: z.unknown(),
|
|
68
|
+
monthlyCredits: z.unknown(),
|
|
69
|
+
personDailyCredits: z.unknown(),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
export type GeoBudgetInput = z.infer<typeof GeoBudgetInputSchema>;
|
|
73
|
+
export type GeoBudgetField = "customRps" | "customDailyCredits" | "monthlyCredits" | "personDailyCredits";
|
|
74
|
+
|
|
75
|
+
/** Stable field error codes; the page renders their text. */
|
|
76
|
+
export const GeoBudgetFieldErrorSchema = z.discriminatedUnion("code", [
|
|
77
|
+
z.object({ code: z.literal("not_whole_number") }),
|
|
78
|
+
z.object({ code: z.literal("too_small"), min: z.number() }),
|
|
79
|
+
z.object({ code: z.literal("too_large"), max: z.number() }),
|
|
80
|
+
z.object({ code: z.literal("above_monthly"), max: z.number() }),
|
|
81
|
+
]);
|
|
82
|
+
export type GeoBudgetFieldError = z.infer<typeof GeoBudgetFieldErrorSchema>;
|
|
83
|
+
/** The 400 answer of a refused budget save. */
|
|
84
|
+
export const GeoBudgetRefusalSchema = z.object({
|
|
85
|
+
code: z.literal("geo_budget_invalid"),
|
|
86
|
+
errors: z.partialRecord(z.enum(["customRps", "customDailyCredits", "monthlyCredits", "personDailyCredits"]), GeoBudgetFieldErrorSchema),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export type GeoKeyError =
|
|
90
|
+
| { code: "geo_key_missing" }
|
|
91
|
+
| { code: "geo_key_malformed" }
|
|
92
|
+
| { code: "geo_key_rejected" }
|
|
93
|
+
| { code: "geo_key_unverified" };
|
|
94
|
+
|
|
95
|
+
/** Validate one budget number; `null` when it is acceptable. */
|
|
96
|
+
const checkNumber = (value: unknown, min: number, max: number): GeoBudgetFieldError | null => {
|
|
97
|
+
if (typeof value !== "number" || !Number.isInteger(value)) return { code: "not_whole_number" };
|
|
98
|
+
if (value < min) return { code: "too_small", min };
|
|
99
|
+
if (value > max) return { code: "too_large", max };
|
|
100
|
+
return null;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/** Check the whole form before anything is written; the same rules as the settings registry plus the pair rule. */
|
|
104
|
+
export const validateGeoBudget = (input: GeoBudgetInput) => {
|
|
105
|
+
const errors: Partial<Record<GeoBudgetField, GeoBudgetFieldError>> = {};
|
|
106
|
+
const fields: Array<[GeoBudgetField, number, number]> = [
|
|
107
|
+
["monthlyCredits", 0, GEO_MAX_CREDITS],
|
|
108
|
+
["personDailyCredits", 0, GEO_MAX_CREDITS],
|
|
109
|
+
];
|
|
110
|
+
if (input.plan === "custom") fields.push(["customRps", 1, GEO_MAX_RPS], ["customDailyCredits", 1, GEO_MAX_CREDITS]);
|
|
111
|
+
for (const [field, min, max] of fields) {
|
|
112
|
+
const error = checkNumber(input[field], min, max);
|
|
113
|
+
if (error) errors[field] = error;
|
|
114
|
+
}
|
|
115
|
+
const month = input.monthlyCredits,
|
|
116
|
+
day = input.personDailyCredits;
|
|
117
|
+
if (!errors.monthlyCredits && !errors.personDailyCredits && typeof month === "number" && typeof day === "number" && day > month)
|
|
118
|
+
errors.personDailyCredits = { code: "above_monthly", max: month };
|
|
119
|
+
return errors;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/** Shape check before the provider sees a key: printable ASCII without spaces, as Geoapify issues them. */
|
|
123
|
+
export const geoKeyProblem = (apiKey: string): "geo_key_missing" | "geo_key_malformed" | null => {
|
|
124
|
+
if (!apiKey) return "geo_key_missing";
|
|
125
|
+
if (apiKey.length > GEO_MAX_KEY_LENGTH || !/^[\x21-\x7e]+$/.test(apiKey)) return "geo_key_malformed";
|
|
126
|
+
return null;
|
|
127
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const GeoMapStyleInputSchema = z
|
|
4
|
+
.object({
|
|
5
|
+
theme: z.enum(["light", "dark"]).default("light").describe("Map appearance; labels use the request locale."),
|
|
6
|
+
})
|
|
7
|
+
.strict();
|
|
8
|
+
export const GeoMapStyleDataSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
styleUrl: z.string().startsWith("/api/geo/style?"),
|
|
11
|
+
attribution: z.array(z.object({ label: z.string(), href: z.url() }).strict()),
|
|
12
|
+
})
|
|
13
|
+
.strict();
|
|
14
|
+
export const geoMapContract = { style: { id: "map.style", input: GeoMapStyleInputSchema, data: GeoMapStyleDataSchema } } as const;
|
|
15
|
+
|
|
16
|
+
// This is a transport memory budget, not an asserted provider maximum. At Free's
|
|
17
|
+
// 20 tile requests/s and 10 s deadline, buffered tile bodies occupy at most 200 MiB.
|
|
18
|
+
export const GEO_MAX_TILE_BYTES = 1024 * 1024;
|
|
19
|
+
export const GEO_MAP_MAX_ZOOM = 14;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { GEO_MAX_POLYLINE_CHARS, GeoAddressSchema, GeoGeocodeInputSchema, GeoPointSchema, GeoProvenanceSchema } from "./geo";
|
|
3
|
+
|
|
4
|
+
export const GEO_ROUTE_MAX_STOPS = 26;
|
|
5
|
+
export const GeoRouteDistanceAllowanceSchema = z
|
|
6
|
+
.number()
|
|
7
|
+
.int()
|
|
8
|
+
.min(1)
|
|
9
|
+
.max(1_000_000_000)
|
|
10
|
+
.describe(
|
|
11
|
+
"Reference distance allowance in meters per leg; defaults to 500000. The whole chain reserves at this allowance. This is not a guaranteed provider bill ceiling. A larger actual route is charged and stops the chain.",
|
|
12
|
+
);
|
|
13
|
+
const stopId = z.string().min(1).max(100).describe("Stable stop ID, unique within this route.");
|
|
14
|
+
export const GeoRouteOptionsSchema = z
|
|
15
|
+
.object({
|
|
16
|
+
mode: z.enum(["car", "bike", "walk"]).optional().describe("Travel mode; defaults to car."),
|
|
17
|
+
avoid: z
|
|
18
|
+
.array(z.enum(["tolls", "ferries", "highways"]))
|
|
19
|
+
.max(3)
|
|
20
|
+
.optional()
|
|
21
|
+
.describe("Preferences, not prohibitions; tolls/highways require car. Each preference costs extra."),
|
|
22
|
+
})
|
|
23
|
+
.strict();
|
|
24
|
+
export const GeoRouteStopSchema = z
|
|
25
|
+
.object({
|
|
26
|
+
id: stopId,
|
|
27
|
+
label: z.string().max(300).optional().describe("Optional display label."),
|
|
28
|
+
point: GeoPointSchema.optional().describe("Known coordinates; choose point or address."),
|
|
29
|
+
address: GeoGeocodeInputSchema.optional().describe("Address to resolve; choose address or point. Ambiguity returns candidates."),
|
|
30
|
+
})
|
|
31
|
+
.strict();
|
|
32
|
+
export const GeoRouteResolvedStopSchema = z
|
|
33
|
+
.object({
|
|
34
|
+
id: stopId,
|
|
35
|
+
label: z.string().max(300).optional().describe("Optional display label."),
|
|
36
|
+
point: GeoPointSchema.describe("Resolved stop coordinates."),
|
|
37
|
+
address: GeoAddressSchema.optional().describe("Resolved address, when this stop was geocoded."),
|
|
38
|
+
})
|
|
39
|
+
.strict();
|
|
40
|
+
export const GeoRouteLegOptionsSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
fromStopId: stopId,
|
|
43
|
+
toStopId: stopId,
|
|
44
|
+
options: GeoRouteOptionsSchema.describe("Override only the supplied options for this adjacent pair."),
|
|
45
|
+
})
|
|
46
|
+
.strict();
|
|
47
|
+
export const GeoRoutePlanSchema = z
|
|
48
|
+
.object({
|
|
49
|
+
distanceAllowanceMeters: GeoRouteDistanceAllowanceSchema.optional(),
|
|
50
|
+
stops: z.array(GeoRouteStopSchema).min(2).max(GEO_ROUTE_MAX_STOPS).describe("2–26 stops in travel order, with unique IDs."),
|
|
51
|
+
options: GeoRouteOptionsSchema.optional().describe("Default options for the route."),
|
|
52
|
+
legOptions: z
|
|
53
|
+
.array(GeoRouteLegOptionsSchema)
|
|
54
|
+
.max(25)
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Options for adjacent stop pairs; on move/optimization each override travels with its departure stop."),
|
|
57
|
+
optimize: z.boolean().optional().describe("Optimize intermediate stops; start and destination stay fixed."),
|
|
58
|
+
})
|
|
59
|
+
.strict();
|
|
60
|
+
const geometry = z.string().min(2).max(GEO_MAX_POLYLINE_CHARS);
|
|
61
|
+
export const GeoRouteLegSchema = z
|
|
62
|
+
.object({
|
|
63
|
+
fromStopId: stopId,
|
|
64
|
+
toStopId: stopId,
|
|
65
|
+
options: GeoRouteOptionsSchema.describe("Travel options; mode and avoid override only supplied fields."),
|
|
66
|
+
distanceMeters: z.number().nonnegative().describe("Travel distance in meters."),
|
|
67
|
+
durationSeconds: z.number().nonnegative().describe("Estimated travel duration in seconds, without live traffic."),
|
|
68
|
+
polyline6: geometry.describe("Encoded route geometry at precision six."),
|
|
69
|
+
simplificationToleranceMeters: z.number().nonnegative().describe("Conservative geometry simplification tolerance in meters."),
|
|
70
|
+
provenance: GeoProvenanceSchema.describe("Provider provenance and required attribution."),
|
|
71
|
+
})
|
|
72
|
+
.strict();
|
|
73
|
+
export const GeoRouteSchema = z
|
|
74
|
+
.object({
|
|
75
|
+
distanceAllowanceMeters: GeoRouteDistanceAllowanceSchema,
|
|
76
|
+
stops: z.array(GeoRouteResolvedStopSchema).min(2).max(GEO_ROUTE_MAX_STOPS).describe("Resolved stops in current travel order."),
|
|
77
|
+
options: GeoRouteOptionsSchema.describe("Travel options; mode and avoid override only supplied fields."),
|
|
78
|
+
legs: z.array(GeoRouteLegSchema).min(1).max(25).describe("Independent stopover legs in travel order."),
|
|
79
|
+
distanceMeters: z.number().nonnegative().describe("Travel distance in meters."),
|
|
80
|
+
durationSeconds: z.number().nonnegative().describe("Estimated travel duration in seconds, without live traffic."),
|
|
81
|
+
polyline6: geometry.describe("Encoded route geometry at precision six."),
|
|
82
|
+
simplificationToleranceMeters: z.number().nonnegative().describe("Conservative geometry simplification tolerance in meters."),
|
|
83
|
+
inputHash: z
|
|
84
|
+
.string()
|
|
85
|
+
.regex(/^[a-f0-9]{64}$/)
|
|
86
|
+
.describe("SHA-256 fingerprint of the resolved route input; preserve when updating."),
|
|
87
|
+
provenance: GeoProvenanceSchema.describe("Provider provenance and required attribution."),
|
|
88
|
+
})
|
|
89
|
+
.strict()
|
|
90
|
+
.describe("Self-contained stateless route; preserve stops, legs, options and provenance when saving.");
|
|
91
|
+
export const GeoRouteChangesSchema = z.discriminatedUnion("type", [
|
|
92
|
+
z
|
|
93
|
+
.object({
|
|
94
|
+
type: z.literal("insert").describe("Insert one stop."),
|
|
95
|
+
stop: GeoRouteStopSchema.describe("New stop to insert."),
|
|
96
|
+
afterStopId: stopId.optional().describe("Insert after this stop; omit to compare up to three best candidate gaps."),
|
|
97
|
+
})
|
|
98
|
+
.strict(),
|
|
99
|
+
z
|
|
100
|
+
.object({
|
|
101
|
+
type: z.literal("move").describe("Move an existing stop to a new index."),
|
|
102
|
+
stopId,
|
|
103
|
+
toIndex: z.number().int().min(0).max(25).describe("Zero-based destination index in the final stop order."),
|
|
104
|
+
})
|
|
105
|
+
.strict(),
|
|
106
|
+
z.object({ type: z.literal("optimize").describe("Optimize intermediate stop order while fixing start and destination.") }).strict(),
|
|
107
|
+
z
|
|
108
|
+
.object({
|
|
109
|
+
type: z.literal("options").describe("Change route defaults or one leg."),
|
|
110
|
+
options: GeoRouteOptionsSchema.describe("Travel options; mode and avoid override only supplied fields."),
|
|
111
|
+
leg: z
|
|
112
|
+
.object({ fromStopId: stopId, toStopId: stopId })
|
|
113
|
+
.strict()
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("Change just this adjacent pair; omit to change route defaults and clear leg overrides."),
|
|
116
|
+
})
|
|
117
|
+
.strict(),
|
|
118
|
+
]);
|
|
119
|
+
export const GeoRouteCalculateInputSchema = z.object({ plan: GeoRoutePlanSchema.describe("Route stops and travel preferences.") }).strict();
|
|
120
|
+
export const GeoRouteCalculateDataSchema = z.object({ route: GeoRouteSchema }).strict();
|
|
121
|
+
export const GeoRouteUpdateInputSchema = z
|
|
122
|
+
.object({
|
|
123
|
+
route: GeoRouteSchema,
|
|
124
|
+
changes: GeoRouteChangesSchema.describe("One stateless route edit to preview."),
|
|
125
|
+
distanceAllowanceMeters: GeoRouteDistanceAllowanceSchema.optional(),
|
|
126
|
+
})
|
|
127
|
+
.strict();
|
|
128
|
+
export const GeoRouteUpdateDataSchema = z
|
|
129
|
+
.object({
|
|
130
|
+
route: GeoRouteSchema,
|
|
131
|
+
before: z
|
|
132
|
+
.object({
|
|
133
|
+
stopIds: z.array(stopId).min(2).max(26),
|
|
134
|
+
distanceMeters: z.number().nonnegative().describe("Travel distance in meters."),
|
|
135
|
+
durationSeconds: z.number().nonnegative(),
|
|
136
|
+
})
|
|
137
|
+
.strict(),
|
|
138
|
+
after: z
|
|
139
|
+
.object({
|
|
140
|
+
stopIds: z.array(stopId).min(2).max(26),
|
|
141
|
+
distanceMeters: z.number().nonnegative().describe("Travel distance in meters."),
|
|
142
|
+
durationSeconds: z.number().nonnegative(),
|
|
143
|
+
})
|
|
144
|
+
.strict(),
|
|
145
|
+
delta: z.object({ distanceMeters: z.number(), durationSeconds: z.number() }).strict(),
|
|
146
|
+
insertion: z
|
|
147
|
+
.object({ afterStopId: stopId, candidateGaps: z.number().int().min(1).max(3), exhaustive: z.boolean() })
|
|
148
|
+
.strict()
|
|
149
|
+
.optional()
|
|
150
|
+
.describe("Best insertion is a three-gap heuristic when there are more than three gaps."),
|
|
151
|
+
})
|
|
152
|
+
.strict();
|
|
153
|
+
export type GeoRouteOptions = z.infer<typeof GeoRouteOptionsSchema>;
|
|
154
|
+
export type GeoRouteStop = z.infer<typeof GeoRouteStopSchema>;
|
|
155
|
+
export type GeoRouteResolvedStop = z.infer<typeof GeoRouteResolvedStopSchema>;
|
|
156
|
+
export type GeoRouteLegOptions = z.infer<typeof GeoRouteLegOptionsSchema>;
|
|
157
|
+
export type GeoRoutePlan = z.infer<typeof GeoRoutePlanSchema>;
|
|
158
|
+
export type GeoRouteLeg = z.infer<typeof GeoRouteLegSchema>;
|
|
159
|
+
export type GeoRoute = z.infer<typeof GeoRouteSchema>;
|
|
160
|
+
export type GeoRouteChanges = z.infer<typeof GeoRouteChangesSchema>;
|
|
161
|
+
export type GeoRouteCalculateInput = z.infer<typeof GeoRouteCalculateInputSchema>;
|
|
162
|
+
export type GeoRouteCalculateData = z.infer<typeof GeoRouteCalculateDataSchema>;
|
|
163
|
+
export type GeoRouteUpdateInput = z.infer<typeof GeoRouteUpdateInputSchema>;
|
|
164
|
+
export type GeoRouteUpdateData = z.infer<typeof GeoRouteUpdateDataSchema>;
|
|
165
|
+
export const geoRouteContract = {
|
|
166
|
+
calculateRoute: { id: "route.calculate", input: GeoRouteCalculateInputSchema, data: GeoRouteCalculateDataSchema },
|
|
167
|
+
updateRoute: { id: "route.update", input: GeoRouteUpdateInputSchema, data: GeoRouteUpdateDataSchema },
|
|
168
|
+
} as const;
|