@xemahq/kernel-contracts 0.1.0 → 0.2.1
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/LICENSE +201 -0
- package/dist/agent-tool-inquiry/index.d.ts +2 -0
- package/dist/agent-tool-inquiry/index.d.ts.map +1 -0
- package/dist/agent-tool-inquiry/index.js +18 -0
- package/dist/agent-tool-inquiry/index.js.map +1 -0
- package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.d.ts +43 -0
- package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.d.ts.map +1 -0
- package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.js +32 -0
- package/dist/agent-tool-inquiry/lib/agent-tool-inquiry.js.map +1 -0
- package/dist/agent-workspace/awp-spec.json +1 -1
- package/dist/app-runtime/index.d.ts +9 -0
- package/dist/app-runtime/index.d.ts.map +1 -0
- package/dist/app-runtime/index.js +25 -0
- package/dist/app-runtime/index.js.map +1 -0
- package/dist/app-runtime/lib/app-client.d.ts +11 -0
- package/dist/app-runtime/lib/app-client.d.ts.map +1 -0
- package/dist/app-runtime/lib/app-client.js +23 -0
- package/dist/app-runtime/lib/app-client.js.map +1 -0
- package/dist/app-runtime/lib/app-lockfile.d.ts +12 -0
- package/dist/app-runtime/lib/app-lockfile.d.ts.map +1 -0
- package/dist/app-runtime/lib/app-lockfile.js +17 -0
- package/dist/app-runtime/lib/app-lockfile.js.map +1 -0
- package/dist/app-runtime/lib/app.d.ts +26 -0
- package/dist/app-runtime/lib/app.d.ts.map +1 -0
- package/dist/app-runtime/lib/app.js +31 -0
- package/dist/app-runtime/lib/app.js.map +1 -0
- package/dist/app-runtime/lib/audience-policy.d.ts +31 -0
- package/dist/app-runtime/lib/audience-policy.d.ts.map +1 -0
- package/dist/app-runtime/lib/audience-policy.js +38 -0
- package/dist/app-runtime/lib/audience-policy.js.map +1 -0
- package/dist/app-runtime/lib/biome-install.d.ts +9 -0
- package/dist/app-runtime/lib/biome-install.d.ts.map +1 -0
- package/dist/app-runtime/lib/biome-install.js +13 -0
- package/dist/app-runtime/lib/biome-install.js.map +1 -0
- package/dist/app-runtime/lib/branding-config.d.ts +9 -0
- package/dist/app-runtime/lib/branding-config.d.ts.map +1 -0
- package/dist/app-runtime/lib/branding-config.js +24 -0
- package/dist/app-runtime/lib/branding-config.js.map +1 -0
- package/dist/app-runtime/lib/delegated-session.d.ts +15 -0
- package/dist/app-runtime/lib/delegated-session.d.ts.map +1 -0
- package/dist/app-runtime/lib/delegated-session.js +29 -0
- package/dist/app-runtime/lib/delegated-session.js.map +1 -0
- package/dist/app-runtime/lib/external-subject.d.ts +9 -0
- package/dist/app-runtime/lib/external-subject.d.ts.map +1 -0
- package/dist/app-runtime/lib/external-subject.js +19 -0
- package/dist/app-runtime/lib/external-subject.js.map +1 -0
- package/dist/connector/index.d.ts +9 -0
- package/dist/connector/index.d.ts.map +1 -0
- package/dist/connector/index.js +25 -0
- package/dist/connector/index.js.map +1 -0
- package/dist/connector/lib/adapter-kind.d.ts +8 -0
- package/dist/connector/lib/adapter-kind.d.ts.map +1 -0
- package/dist/connector/lib/adapter-kind.js +14 -0
- package/dist/connector/lib/adapter-kind.js.map +1 -0
- package/dist/connector/lib/capability-refs.d.ts +14 -0
- package/dist/connector/lib/capability-refs.d.ts.map +1 -0
- package/dist/connector/lib/capability-refs.js +15 -0
- package/dist/connector/lib/capability-refs.js.map +1 -0
- package/dist/connector/lib/capability.d.ts +18 -0
- package/dist/connector/lib/capability.d.ts.map +1 -0
- package/dist/connector/lib/capability.js +24 -0
- package/dist/connector/lib/capability.js.map +1 -0
- package/dist/connector/lib/credential-kind.d.ts +42 -0
- package/dist/connector/lib/credential-kind.d.ts.map +1 -0
- package/dist/connector/lib/credential-kind.js +26 -0
- package/dist/connector/lib/credential-kind.js.map +1 -0
- package/dist/connector/lib/envelope-schema.d.ts +6 -0
- package/dist/connector/lib/envelope-schema.d.ts.map +1 -0
- package/dist/connector/lib/envelope-schema.js +150 -0
- package/dist/connector/lib/envelope-schema.js.map +1 -0
- package/dist/connector/lib/filter-expr-schema.d.ts +4 -0
- package/dist/connector/lib/filter-expr-schema.d.ts.map +1 -0
- package/dist/connector/lib/filter-expr-schema.js +65 -0
- package/dist/connector/lib/filter-expr-schema.js.map +1 -0
- package/dist/connector/lib/filter-expr-validate.d.ts +10 -0
- package/dist/connector/lib/filter-expr-validate.d.ts.map +1 -0
- package/dist/connector/lib/filter-expr-validate.js +58 -0
- package/dist/connector/lib/filter-expr-validate.js.map +1 -0
- package/dist/connector/lib/filter-expr.d.ts +49 -0
- package/dist/connector/lib/filter-expr.d.ts.map +1 -0
- package/dist/connector/lib/filter-expr.js +135 -0
- package/dist/connector/lib/filter-expr.js.map +1 -0
- package/dist/connector/lib/onboarding-manifest.d.ts +45 -0
- package/dist/connector/lib/onboarding-manifest.d.ts.map +1 -0
- package/dist/connector/lib/onboarding-manifest.js +30 -0
- package/dist/connector/lib/onboarding-manifest.js.map +1 -0
- package/dist/document-render/index.d.ts +7 -0
- package/dist/document-render/index.d.ts.map +1 -0
- package/dist/document-render/index.js +23 -0
- package/dist/document-render/index.js.map +1 -0
- package/dist/document-render/lib/measure-layout.d.ts +44 -0
- package/dist/document-render/lib/measure-layout.d.ts.map +1 -0
- package/dist/document-render/lib/measure-layout.js +16 -0
- package/dist/document-render/lib/measure-layout.js.map +1 -0
- package/dist/document-render/lib/render-enums.d.ts +18 -0
- package/dist/document-render/lib/render-enums.d.ts.map +1 -0
- package/dist/document-render/lib/render-enums.js +24 -0
- package/dist/document-render/lib/render-enums.js.map +1 -0
- package/dist/document-render/lib/render-record.d.ts +22 -0
- package/dist/document-render/lib/render-record.d.ts.map +1 -0
- package/dist/document-render/lib/render-record.js +3 -0
- package/dist/document-render/lib/render-record.js.map +1 -0
- package/dist/document-render/lib/render-request.d.ts +24 -0
- package/dist/document-render/lib/render-request.d.ts.map +1 -0
- package/dist/document-render/lib/render-request.js +12 -0
- package/dist/document-render/lib/render-request.js.map +1 -0
- package/dist/document-render/lib/render-source.d.ts +43 -0
- package/dist/document-render/lib/render-source.d.ts.map +1 -0
- package/dist/document-render/lib/render-source.js +31 -0
- package/dist/document-render/lib/render-source.js.map +1 -0
- package/dist/document-render/lib/xema-prompt.d.ts +11 -0
- package/dist/document-render/lib/xema-prompt.d.ts.map +1 -0
- package/dist/document-render/lib/xema-prompt.js +46 -0
- package/dist/document-render/lib/xema-prompt.js.map +1 -0
- package/dist/inquiry/index.d.ts +7 -0
- package/dist/inquiry/index.d.ts.map +1 -0
- package/dist/inquiry/index.js +23 -0
- package/dist/inquiry/index.js.map +1 -0
- package/dist/inquiry/lib/enums.d.ts +36 -0
- package/dist/inquiry/lib/enums.d.ts.map +1 -0
- package/dist/inquiry/lib/enums.js +45 -0
- package/dist/inquiry/lib/enums.js.map +1 -0
- package/dist/inquiry/lib/inquiry.d.ts +332 -0
- package/dist/inquiry/lib/inquiry.d.ts.map +1 -0
- package/dist/inquiry/lib/inquiry.js +102 -0
- package/dist/inquiry/lib/inquiry.js.map +1 -0
- package/dist/inquiry/lib/kind-registry.d.ts +14 -0
- package/dist/inquiry/lib/kind-registry.d.ts.map +1 -0
- package/dist/inquiry/lib/kind-registry.js +24 -0
- package/dist/inquiry/lib/kind-registry.js.map +1 -0
- package/dist/inquiry/lib/policy.d.ts +19 -0
- package/dist/inquiry/lib/policy.d.ts.map +1 -0
- package/dist/inquiry/lib/policy.js +21 -0
- package/dist/inquiry/lib/policy.js.map +1 -0
- package/dist/inquiry/lib/recipient.d.ts +111 -0
- package/dist/inquiry/lib/recipient.d.ts.map +1 -0
- package/dist/inquiry/lib/recipient.js +64 -0
- package/dist/inquiry/lib/recipient.js.map +1 -0
- package/dist/inquiry/lib/workflow-verdict-evaluator.d.ts +15 -0
- package/dist/inquiry/lib/workflow-verdict-evaluator.d.ts.map +1 -0
- package/dist/inquiry/lib/workflow-verdict-evaluator.js +145 -0
- package/dist/inquiry/lib/workflow-verdict-evaluator.js.map +1 -0
- package/dist/org-database/index.d.ts +5 -0
- package/dist/org-database/index.d.ts.map +1 -0
- package/dist/org-database/index.js +21 -0
- package/dist/org-database/index.js.map +1 -0
- package/dist/org-database/lib/db-result-event.d.ts +24 -0
- package/dist/org-database/lib/db-result-event.d.ts.map +1 -0
- package/dist/org-database/lib/db-result-event.js +3 -0
- package/dist/org-database/lib/db-result-event.js.map +1 -0
- package/dist/org-database/lib/driver.d.ts +43 -0
- package/dist/org-database/lib/driver.d.ts.map +1 -0
- package/dist/org-database/lib/driver.js +3 -0
- package/dist/org-database/lib/driver.js.map +1 -0
- package/dist/org-database/lib/enums.d.ts +41 -0
- package/dist/org-database/lib/enums.d.ts.map +1 -0
- package/dist/org-database/lib/enums.js +51 -0
- package/dist/org-database/lib/enums.js.map +1 -0
- package/dist/org-database/lib/migration-runner.d.ts +15 -0
- package/dist/org-database/lib/migration-runner.d.ts.map +1 -0
- package/dist/org-database/lib/migration-runner.js +3 -0
- package/dist/org-database/lib/migration-runner.js.map +1 -0
- package/dist/project-kit/index.d.ts +2 -0
- package/dist/project-kit/index.d.ts.map +1 -0
- package/dist/project-kit/index.js +18 -0
- package/dist/project-kit/index.js.map +1 -0
- package/dist/project-kit/lib/project-kit.d.ts +63 -0
- package/dist/project-kit/lib/project-kit.d.ts.map +1 -0
- package/dist/project-kit/lib/project-kit.js +32 -0
- package/dist/project-kit/lib/project-kit.js.map +1 -0
- package/dist/provisioning/index.d.ts +2 -0
- package/dist/provisioning/index.d.ts.map +1 -0
- package/dist/provisioning/index.js +18 -0
- package/dist/provisioning/index.js.map +1 -0
- package/dist/provisioning/lib/provisioning.d.ts +256 -0
- package/dist/provisioning/lib/provisioning.d.ts.map +1 -0
- package/dist/provisioning/lib/provisioning.js +221 -0
- package/dist/provisioning/lib/provisioning.js.map +1 -0
- package/dist/worker-runtime/index.d.ts +6 -0
- package/dist/worker-runtime/index.d.ts.map +1 -0
- package/dist/worker-runtime/index.js +22 -0
- package/dist/worker-runtime/index.js.map +1 -0
- package/dist/worker-runtime/lib/capabilities.d.ts +22 -0
- package/dist/worker-runtime/lib/capabilities.d.ts.map +1 -0
- package/dist/worker-runtime/lib/capabilities.js +3 -0
- package/dist/worker-runtime/lib/capabilities.js.map +1 -0
- package/dist/worker-runtime/lib/enums.d.ts +10 -0
- package/dist/worker-runtime/lib/enums.d.ts.map +1 -0
- package/dist/worker-runtime/lib/enums.js +15 -0
- package/dist/worker-runtime/lib/enums.js.map +1 -0
- package/dist/worker-runtime/lib/messages.d.ts +33 -0
- package/dist/worker-runtime/lib/messages.d.ts.map +1 -0
- package/dist/worker-runtime/lib/messages.js +3 -0
- package/dist/worker-runtime/lib/messages.js.map +1 -0
- package/dist/worker-runtime/lib/runtime.d.ts +35 -0
- package/dist/worker-runtime/lib/runtime.d.ts.map +1 -0
- package/dist/worker-runtime/lib/runtime.js +3 -0
- package/dist/worker-runtime/lib/runtime.js.map +1 -0
- package/dist/worker-runtime/lib/schemas.d.ts +87 -0
- package/dist/worker-runtime/lib/schemas.d.ts.map +1 -0
- package/dist/worker-runtime/lib/schemas.js +57 -0
- package/dist/worker-runtime/lib/schemas.js.map +1 -0
- package/dist/workspace-storage/index.d.ts +4 -0
- package/dist/workspace-storage/index.d.ts.map +1 -0
- package/dist/workspace-storage/index.js +20 -0
- package/dist/workspace-storage/index.js.map +1 -0
- package/dist/workspace-storage/lib/enums.d.ts +34 -0
- package/dist/workspace-storage/lib/enums.d.ts.map +1 -0
- package/dist/workspace-storage/lib/enums.js +42 -0
- package/dist/workspace-storage/lib/enums.js.map +1 -0
- package/dist/workspace-storage/lib/schemas.d.ts +56 -0
- package/dist/workspace-storage/lib/schemas.d.ts.map +1 -0
- package/dist/workspace-storage/lib/schemas.js +59 -0
- package/dist/workspace-storage/lib/schemas.js.map +1 -0
- package/dist/workspace-storage/lib/types.d.ts +71 -0
- package/dist/workspace-storage/lib/types.d.ts.map +1 -0
- package/dist/workspace-storage/lib/types.js +3 -0
- package/dist/workspace-storage/lib/types.js.map +1 -0
- package/package.json +22 -153
- package/src/agent-composition/lib/composition-workspace.ts +1 -1
- package/src/agent-tool-inquiry/index.ts +16 -0
- package/src/agent-tool-inquiry/lib/agent-tool-inquiry.ts +82 -0
- package/src/agent-workspace/lib/workspace-spec.ts +1 -1
- package/src/app-runtime/index.ts +8 -0
- package/src/app-runtime/lib/app-client.ts +44 -0
- package/src/app-runtime/lib/app-lockfile.ts +54 -0
- package/src/app-runtime/lib/app.ts +84 -0
- package/src/app-runtime/lib/audience-policy.ts +87 -0
- package/src/app-runtime/lib/biome-install.ts +29 -0
- package/src/app-runtime/lib/branding-config.ts +54 -0
- package/src/app-runtime/lib/delegated-session.ts +69 -0
- package/src/app-runtime/lib/external-subject.ts +34 -0
- package/src/connector/index.ts +8 -0
- package/src/connector/lib/adapter-kind.ts +37 -0
- package/src/connector/lib/capability-refs.ts +29 -0
- package/src/connector/lib/capability.ts +38 -0
- package/src/connector/lib/credential-kind.ts +120 -0
- package/src/connector/lib/envelope-schema.ts +256 -0
- package/src/connector/lib/filter-expr-schema.ts +75 -0
- package/src/connector/lib/filter-expr-validate.ts +91 -0
- package/src/connector/lib/filter-expr.ts +208 -0
- package/src/connector/lib/onboarding-manifest.ts +167 -0
- package/src/document-render/index.ts +25 -0
- package/src/document-render/lib/measure-layout.ts +61 -0
- package/src/document-render/lib/render-enums.ts +49 -0
- package/src/document-render/lib/render-record.ts +38 -0
- package/src/document-render/lib/render-request.ts +16 -0
- package/src/document-render/lib/render-source.ts +44 -0
- package/src/document-render/lib/xema-prompt.ts +100 -0
- package/src/inquiry/index.ts +23 -0
- package/src/inquiry/lib/enums.ts +103 -0
- package/src/inquiry/lib/inquiry.ts +182 -0
- package/src/inquiry/lib/kind-registry.ts +57 -0
- package/src/inquiry/lib/policy.ts +27 -0
- package/src/inquiry/lib/recipient.ts +188 -0
- package/src/inquiry/lib/workflow-verdict-evaluator.ts +220 -0
- package/src/org-database/index.ts +4 -0
- package/src/org-database/lib/db-result-event.ts +59 -0
- package/src/org-database/lib/driver.ts +47 -0
- package/src/org-database/lib/enums.ts +51 -0
- package/src/org-database/lib/migration-runner.ts +17 -0
- package/src/project-kit/index.ts +17 -0
- package/src/project-kit/lib/project-kit.ts +227 -0
- package/src/provisioning/index.ts +17 -0
- package/src/provisioning/lib/provisioning.ts +499 -0
- package/src/worker-runtime/index.ts +14 -0
- package/src/worker-runtime/lib/capabilities.ts +58 -0
- package/src/worker-runtime/lib/enums.ts +33 -0
- package/src/worker-runtime/lib/messages.ts +49 -0
- package/src/worker-runtime/lib/runtime.ts +109 -0
- package/src/worker-runtime/lib/schemas.ts +72 -0
- package/src/workflow/lib/activity-outputs.ts +1 -1
- package/src/workflow/lib/compiled-run.ts +1 -1
- package/src/workflow/lib/compiled-workspace-manifest.ts +1 -1
- package/src/workflow/lib/model-ref.ts +1 -1
- package/src/workflow/lib/workspace-manifest-enums.ts +1 -1
- package/src/workspace-storage/index.ts +12 -0
- package/src/workspace-storage/lib/enums.ts +78 -0
- package/src/workspace-storage/lib/schemas.ts +75 -0
- package/src/workspace-storage/lib/types.ts +145 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { RenderFormat, RenderStatus } from './render-enums';
|
|
2
|
+
import type { RenderSource } from './render-source';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The persistent record returned by `GET /renders/:id` (and embedded in
|
|
6
|
+
* `POST /renders` responses). Once `status === READY`, `downloadUrl` is a
|
|
7
|
+
* pre-signed URL the FE can navigate to directly.
|
|
8
|
+
*/
|
|
9
|
+
export interface RenderRecordDto {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly format: RenderFormat;
|
|
12
|
+
readonly status: RenderStatus;
|
|
13
|
+
readonly source: RenderSource;
|
|
14
|
+
readonly downloadUrl: string | null;
|
|
15
|
+
readonly failureReason: string | null;
|
|
16
|
+
/** ISO-8601 timestamp. */
|
|
17
|
+
readonly createdAt: string;
|
|
18
|
+
/** ISO-8601 timestamp; null until terminal. */
|
|
19
|
+
readonly completedAt: string | null;
|
|
20
|
+
/** Convenience: byte size of the rendered file when READY. */
|
|
21
|
+
readonly byteSize: number | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* SSE event payload streamed from `GET /renders/:id/stream`. The FE
|
|
26
|
+
* subscribes once after `POST /renders` and tears down on terminal
|
|
27
|
+
* status. Progress percent is best-effort and may be null for fast
|
|
28
|
+
* renders that flip QUEUED → RUNNING → READY without a measurable
|
|
29
|
+
* mid-state.
|
|
30
|
+
*/
|
|
31
|
+
export interface RenderProgressEventDto {
|
|
32
|
+
readonly renderId: string;
|
|
33
|
+
readonly status: RenderStatus;
|
|
34
|
+
readonly progressPercent: number | null;
|
|
35
|
+
readonly message: string | null;
|
|
36
|
+
readonly downloadUrl: string | null;
|
|
37
|
+
readonly failureReason: string | null;
|
|
38
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { RenderFormat } from './render-enums';
|
|
4
|
+
import { RenderSourceSchema } from './render-source';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Request body for `POST /renders`. `idempotencyKey` deduplicates retries
|
|
8
|
+
* from the same caller — when present, repeat POSTs return the existing
|
|
9
|
+
* record instead of enqueueing duplicate work.
|
|
10
|
+
*/
|
|
11
|
+
export const RenderRequestSchema = z.object({
|
|
12
|
+
source: RenderSourceSchema,
|
|
13
|
+
format: z.enum(RenderFormat),
|
|
14
|
+
idempotencyKey: z.string().min(1).max(200).optional(),
|
|
15
|
+
});
|
|
16
|
+
export type RenderRequestDto = z.infer<typeof RenderRequestSchema>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { RenderSourceKind } from './render-enums';
|
|
4
|
+
|
|
5
|
+
export const PageRenderSourceSchema = z.object({
|
|
6
|
+
kind: z.literal(RenderSourceKind.PAGE),
|
|
7
|
+
pageId: z.string().min(1),
|
|
8
|
+
/** Omit for the latest published version. */
|
|
9
|
+
version: z.number().int().min(1).optional(),
|
|
10
|
+
});
|
|
11
|
+
export type PageRenderSource = z.infer<typeof PageRenderSourceSchema>;
|
|
12
|
+
|
|
13
|
+
export const DesignSystemBuilderExportRenderSourceSchema = z.object({
|
|
14
|
+
kind: z.literal(RenderSourceKind.DESIGN_SYSTEM_BUILDER_EXPORT),
|
|
15
|
+
designSystemBuildId: z.string().min(1),
|
|
16
|
+
});
|
|
17
|
+
export type DesignSystemBuilderExportRenderSource = z.infer<
|
|
18
|
+
typeof DesignSystemBuilderExportRenderSourceSchema
|
|
19
|
+
>;
|
|
20
|
+
|
|
21
|
+
export const WorkflowDeliverableRenderSourceSchema = z.object({
|
|
22
|
+
kind: z.literal(RenderSourceKind.WORKFLOW_DELIVERABLE),
|
|
23
|
+
artifactId: z.string().min(1),
|
|
24
|
+
versionId: z.string().min(1),
|
|
25
|
+
});
|
|
26
|
+
export type WorkflowDeliverableRenderSource = z.infer<
|
|
27
|
+
typeof WorkflowDeliverableRenderSourceSchema
|
|
28
|
+
>;
|
|
29
|
+
|
|
30
|
+
export const InlineHtmlRenderSourceSchema = z.object({
|
|
31
|
+
kind: z.literal(RenderSourceKind.INLINE_HTML),
|
|
32
|
+
/** Full HTML document. Must include the A4 template CSS to paginate. */
|
|
33
|
+
html: z.string().min(1).max(2_000_000),
|
|
34
|
+
title: z.string().max(200).optional(),
|
|
35
|
+
});
|
|
36
|
+
export type InlineHtmlRenderSource = z.infer<typeof InlineHtmlRenderSourceSchema>;
|
|
37
|
+
|
|
38
|
+
export const RenderSourceSchema = z.discriminatedUnion('kind', [
|
|
39
|
+
PageRenderSourceSchema,
|
|
40
|
+
DesignSystemBuilderExportRenderSourceSchema,
|
|
41
|
+
WorkflowDeliverableRenderSourceSchema,
|
|
42
|
+
InlineHtmlRenderSourceSchema,
|
|
43
|
+
]);
|
|
44
|
+
export type RenderSource = z.infer<typeof RenderSourceSchema>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// Inline "Ask Buddy" prompt blocks — the `xema-prompt` fenced-code contract.
|
|
3
|
+
//
|
|
4
|
+
// A user can drop an instruction for the Document Buddy agent *inside* a
|
|
5
|
+
// MARKDOWN_DOCUMENT, at the exact spot the work belongs, as a fenced code
|
|
6
|
+
// block whose info string is `xema-prompt`:
|
|
7
|
+
//
|
|
8
|
+
// ```xema-prompt
|
|
9
|
+
// Rewrite the section above to be tighter; keep the table.
|
|
10
|
+
// ```
|
|
11
|
+
//
|
|
12
|
+
// The block is an instruction to the agent, never document content — it
|
|
13
|
+
// must never reach the Paged.js preview, the exported PDF, or the DOCX.
|
|
14
|
+
// This module is the single source of truth for that contract, shared by:
|
|
15
|
+
// - the render pipeline (PDF/DOCX/measure) — strips blocks before render;
|
|
16
|
+
// - the Monaco "Ask Buddy" editor — inserts blocks and locates them for
|
|
17
|
+
// the inline Run affordance (the file is frontend-bridged).
|
|
18
|
+
//
|
|
19
|
+
// Pure string utilities. Zero runtime deps so the file bridges cleanly.
|
|
20
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
21
|
+
|
|
22
|
+
/** Fenced-code-block info string that marks an inline "Ask Buddy" prompt. */
|
|
23
|
+
export const XEMA_PROMPT_FENCE = 'xema-prompt';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Matches a whole `xema-prompt` fenced block: an opening fence (3+
|
|
27
|
+
* backticks or tildes, up to 3 spaces of indent) whose info string is
|
|
28
|
+
* `xema-prompt`, the body, and the matching closing fence. Global +
|
|
29
|
+
* multiline so every block in the document is removed; the trailing
|
|
30
|
+
* newline is consumed so no blank gap is left behind.
|
|
31
|
+
*/
|
|
32
|
+
export const XEMA_PROMPT_BLOCK_RE = new RegExp(
|
|
33
|
+
'^ {0,3}(`{3,}|~{3,})[ \\t]*' +
|
|
34
|
+
XEMA_PROMPT_FENCE +
|
|
35
|
+
'[^\\n]*\\n[\\s\\S]*?^ {0,3}\\1[ \\t]*$\\n?',
|
|
36
|
+
'gm',
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/** Remove every inline "Ask Buddy" prompt block from markdown source. */
|
|
40
|
+
export function stripXemaPromptBlocks(markdown: string): string {
|
|
41
|
+
return markdown.replace(XEMA_PROMPT_BLOCK_RE, '');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build a canonical `xema-prompt` block (3 backticks) carrying an
|
|
46
|
+
* optional instruction. Used by the Monaco editor's `/ask` completion so
|
|
47
|
+
* the inserted block always matches what the strip + locate logic
|
|
48
|
+
* expects. Ends with a newline so the block sits on its own lines.
|
|
49
|
+
*/
|
|
50
|
+
export function buildXemaPromptBlock(instruction = ''): string {
|
|
51
|
+
return '```' + XEMA_PROMPT_FENCE + '\n' + instruction + '\n```\n';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A located `xema-prompt` block, with 1-based inclusive line bounds. */
|
|
55
|
+
export interface XemaPromptBlockRange {
|
|
56
|
+
/** 1-based line of the opening fence. */
|
|
57
|
+
readonly startLine: number;
|
|
58
|
+
/** 1-based line of the closing fence. */
|
|
59
|
+
readonly endLine: number;
|
|
60
|
+
/** Instruction text between the fences (may be empty / whitespace). */
|
|
61
|
+
readonly instruction: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Locate every `xema-prompt` block in `text`, returning 1-based line
|
|
66
|
+
* ranges. Drives the Monaco "Ask Buddy" CodeLens — the editor renders a
|
|
67
|
+
* Run affordance over each range. Unterminated blocks (no closing fence)
|
|
68
|
+
* are skipped: they are still being typed and carry no actionable lens.
|
|
69
|
+
*/
|
|
70
|
+
export function findXemaPromptBlockRanges(text: string): XemaPromptBlockRange[] {
|
|
71
|
+
const lines = text.split('\n');
|
|
72
|
+
const openRe = new RegExp(
|
|
73
|
+
'^ {0,3}(`{3,}|~{3,})[ \\t]*' + XEMA_PROMPT_FENCE + '[^\\n]*$',
|
|
74
|
+
);
|
|
75
|
+
const ranges: XemaPromptBlockRange[] = [];
|
|
76
|
+
let i = 0;
|
|
77
|
+
while (i < lines.length) {
|
|
78
|
+
const open = openRe.exec(lines[i] ?? '');
|
|
79
|
+
if (!open) {
|
|
80
|
+
i += 1;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
const fence = open[1] ?? '```';
|
|
84
|
+
const closeRe = new RegExp('^ {0,3}' + fence + '[ \\t]*$');
|
|
85
|
+
let j = i + 1;
|
|
86
|
+
while (j < lines.length && !closeRe.test(lines[j] ?? '')) {
|
|
87
|
+
j += 1;
|
|
88
|
+
}
|
|
89
|
+
if (j >= lines.length) {
|
|
90
|
+
break; // unterminated block — no actionable lens
|
|
91
|
+
}
|
|
92
|
+
ranges.push({
|
|
93
|
+
startLine: i + 1,
|
|
94
|
+
endLine: j + 1,
|
|
95
|
+
instruction: lines.slice(i + 1, j).join('\n'),
|
|
96
|
+
});
|
|
97
|
+
i = j + 1;
|
|
98
|
+
}
|
|
99
|
+
return ranges;
|
|
100
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// @xemahq/inquiry-contracts — Kernel layer
|
|
3
|
+
//
|
|
4
|
+
// Abstract types for the Inquiry primitive: "ask one or more recipients
|
|
5
|
+
// (humans, agents, endpoints) a typed prompt, validate replies against a
|
|
6
|
+
// kind-specific schema, aggregate per a policy, return a verdict."
|
|
7
|
+
//
|
|
8
|
+
// Runtime-agnostic. Pure types + Zod schemas. Zero framework / persistence /
|
|
9
|
+
// workflow-runtime imports. The plan-of-record lives at
|
|
10
|
+
// .claude/plans/i-think-what-we-ve-transient-zebra.md.
|
|
11
|
+
//
|
|
12
|
+
// Per-kind prompt + reply Zod schemas live in their own contract packages
|
|
13
|
+
// (`@xemahq/decision-gate-contracts`, `@xemahq/agent-tool-inquiry-
|
|
14
|
+
// contracts`) and are registered with this package's `KindSchemaRegistry`
|
|
15
|
+
// at the engine boundary.
|
|
16
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
17
|
+
|
|
18
|
+
export * from './lib/enums';
|
|
19
|
+
export * from './lib/recipient';
|
|
20
|
+
export * from './lib/policy';
|
|
21
|
+
export * from './lib/inquiry';
|
|
22
|
+
export * from './lib/kind-registry';
|
|
23
|
+
export * from './lib/workflow-verdict-evaluator';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discriminator on the inquiry row. Determines which Zod schemas apply to
|
|
3
|
+
* the `prompt` and `reply` payloads. Future kinds (e.g. TOOL_PROMPT,
|
|
4
|
+
* CONFIRMATION) extend this enum without breaking existing rows.
|
|
5
|
+
*
|
|
6
|
+
* `REVIEW` is the comment-only review surface — pins one or more
|
|
7
|
+
* artifact versions and asks recipients to leave free-form commentary.
|
|
8
|
+
* No approve/reject verdict, no policy aggregation, no terminal
|
|
9
|
+
* "approved/rejected" outcome. Compose with DECISION_GATE when both
|
|
10
|
+
* review-and-gate semantics are needed.
|
|
11
|
+
*/
|
|
12
|
+
export enum InquiryKind {
|
|
13
|
+
DECISION_GATE = 'decision_gate',
|
|
14
|
+
AGENT_TOOL_INQUIRY = 'agent_tool_inquiry',
|
|
15
|
+
REVIEW = 'review',
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Lifecycle states. Once an inquiry is non-PENDING, no further replies are
|
|
20
|
+
* accepted; reply ingest returns 409.
|
|
21
|
+
*/
|
|
22
|
+
export enum InquiryStatus {
|
|
23
|
+
PENDING = 'pending',
|
|
24
|
+
RESOLVED = 'resolved',
|
|
25
|
+
EXPIRED = 'expired',
|
|
26
|
+
CANCELLED = 'cancelled',
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Source of a recipient's reply. Discriminates the `target` payload shape
|
|
31
|
+
* on `Recipient` and the `submittedBy` attribution on `InquiryReply`.
|
|
32
|
+
*
|
|
33
|
+
* `IDENTITY_GROUP` is an *authoring* kind: it is never persisted as a
|
|
34
|
+
* recipient row. The engine resolves it at inquiry-create time against
|
|
35
|
+
* the identity-system group registry (recursive members) and replaces it
|
|
36
|
+
* with N concrete `HUMAN` recipients. From the moment the inquiry exists
|
|
37
|
+
* the wire payload is identical to today's recipient list. Resolution is
|
|
38
|
+
* snapshot-at-create — later membership changes do not affect the
|
|
39
|
+
* inquiry.
|
|
40
|
+
*
|
|
41
|
+
* `WORKFLOW` is a non-human responder: the engine dispatches a child
|
|
42
|
+
* workflow (slug + inputs) and maps its outputs to a verdict. Same
|
|
43
|
+
* uniform reply contract as `HUMAN`/`AGENT`/`ENDPOINT`. Useful for
|
|
44
|
+
* "approval-as-workflow" — e.g. compliance-review.workflow.yaml as a
|
|
45
|
+
* recipient that produces approve/reject after running its own gates.
|
|
46
|
+
*/
|
|
47
|
+
export enum RecipientKind {
|
|
48
|
+
HUMAN = 'human',
|
|
49
|
+
AGENT = 'agent',
|
|
50
|
+
ENDPOINT = 'endpoint',
|
|
51
|
+
IDENTITY_GROUP = 'identity_group',
|
|
52
|
+
WORKFLOW = 'workflow',
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Per-recipient lifecycle. The engine flips PENDING → REPLIED atomically
|
|
57
|
+
* under `SELECT … FOR UPDATE` so concurrent reply attempts can't both win.
|
|
58
|
+
* SKIPPED is set when the policy short-circuits (e.g. quorum reached);
|
|
59
|
+
* ERRORED when a non-human decider activity exhausted its retries.
|
|
60
|
+
*/
|
|
61
|
+
export enum InquiryRecipientStatus {
|
|
62
|
+
PENDING = 'pending',
|
|
63
|
+
REPLIED = 'replied',
|
|
64
|
+
SKIPPED = 'skipped',
|
|
65
|
+
ERRORED = 'errored',
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Aggregation rules applied across recipients' replies. Discriminated union
|
|
70
|
+
* shapes live in `./policy.ts`. The decider workflow short-circuits as soon
|
|
71
|
+
* as the policy is provably decided (e.g. M_OF_N approves once `m`
|
|
72
|
+
* approvals are in; rejects once remaining recipients can no longer reach
|
|
73
|
+
* `m`).
|
|
74
|
+
*/
|
|
75
|
+
export enum ReplyPolicyKind {
|
|
76
|
+
SINGLE = 'single',
|
|
77
|
+
M_OF_N = 'm_of_n',
|
|
78
|
+
ALL_OF = 'all_of',
|
|
79
|
+
ANY_OF = 'any_of',
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Action when the inquiry's deadline passes with no terminal verdict.
|
|
84
|
+
*
|
|
85
|
+
* - `REJECT` / `APPROVE` — auto-decide on timeout. For DECISION_GATE this
|
|
86
|
+
* becomes `EXPIRED_REJECTED` / `EXPIRED_APPROVED`. For
|
|
87
|
+
* AGENT_TOOL_INQUIRY only `REJECT` is meaningful (the activity returns
|
|
88
|
+
* `null`, which aborts the tool); `APPROVE` is rejected by the
|
|
89
|
+
* schema for that kind.
|
|
90
|
+
* - `ESCALATE` — instead of auto-deciding, advance to the next level in
|
|
91
|
+
* the inquiry's `escalationChain`. Pending recipients are marked
|
|
92
|
+
* skipped(`escalation_timeout`); the next level's recipients are
|
|
93
|
+
* inserted as fresh PENDING rows; `expiresAt` resets to
|
|
94
|
+
* `now + nextLevel.timeoutSeconds`. When the chain is exhausted,
|
|
95
|
+
* `escalationChain[].onExhaustion` (or the inquiry's
|
|
96
|
+
* `onEscalationExhaustion` field) decides the final action — defaults
|
|
97
|
+
* to REJECT so a misconfigured chain never silently approves.
|
|
98
|
+
*/
|
|
99
|
+
export enum InquiryTimeoutAction {
|
|
100
|
+
REJECT = 'reject',
|
|
101
|
+
APPROVE = 'approve',
|
|
102
|
+
ESCALATE = 'escalate',
|
|
103
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
InquiryKind,
|
|
5
|
+
InquiryRecipientStatus,
|
|
6
|
+
InquiryStatus,
|
|
7
|
+
InquiryTimeoutAction,
|
|
8
|
+
RecipientKind,
|
|
9
|
+
} from './enums';
|
|
10
|
+
import { ReplyPolicySchema } from './policy';
|
|
11
|
+
import { RecipientSchema } from './recipient';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One step in an inquiry's escalation chain. When the inquiry's
|
|
15
|
+
* `onTimeout === ESCALATE` and the deadline passes, the engine advances
|
|
16
|
+
* to the next step: marks all PENDING recipients as
|
|
17
|
+
* `skipped(reason='escalation_timeout')`, inserts the step's recipients
|
|
18
|
+
* as fresh PENDING rows, and resets the deadline to
|
|
19
|
+
* `now + timeoutSeconds`. The step's `policy` (when present) replaces
|
|
20
|
+
* the inquiry's policy for that level so escalations can demand a
|
|
21
|
+
* different aggregation rule than the original ask.
|
|
22
|
+
*
|
|
23
|
+
* `recipients` MUST be non-empty. The chain is linear; each step is
|
|
24
|
+
* tried in order. When the chain is exhausted, the inquiry's
|
|
25
|
+
* `onEscalationExhaustion` field decides the final action — defaults
|
|
26
|
+
* to `REJECT` when omitted so a misconfigured chain never silently
|
|
27
|
+
* approves.
|
|
28
|
+
*/
|
|
29
|
+
export const EscalationStepSchema = z.object({
|
|
30
|
+
recipients: z.array(RecipientSchema).min(1),
|
|
31
|
+
policy: ReplyPolicySchema.optional(),
|
|
32
|
+
timeoutSeconds: z.number().int().positive(),
|
|
33
|
+
});
|
|
34
|
+
export type EscalationStep = z.infer<typeof EscalationStepSchema>;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Wire-shape of an Inquiry envelope. The `prompt` and `verdict` fields
|
|
38
|
+
* are kind-discriminated JSON — their shapes are owned by the per-kind
|
|
39
|
+
* contract packages (see `KindSchemaRegistry`).
|
|
40
|
+
*
|
|
41
|
+
* Engine + worker import this for cross-process consistency. The
|
|
42
|
+
* persisted model on the engine side mirrors these field names but stores
|
|
43
|
+
* `prompt`/`policy`/`verdict` as JSON columns; the engine validates the
|
|
44
|
+
* payload against the kind-registered Zod schemas at the controller
|
|
45
|
+
* boundary.
|
|
46
|
+
*/
|
|
47
|
+
export const InquirySchema = z.object({
|
|
48
|
+
id: z.string().min(1),
|
|
49
|
+
orgId: z.string().min(1),
|
|
50
|
+
projectId: z.string().min(1),
|
|
51
|
+
workflowRunId: z.string().min(1),
|
|
52
|
+
jobRunId: z.string().min(1),
|
|
53
|
+
kind: z.nativeEnum(InquiryKind),
|
|
54
|
+
title: z.string(),
|
|
55
|
+
prompt: z.record(z.string(), z.unknown()),
|
|
56
|
+
policy: ReplyPolicySchema,
|
|
57
|
+
status: z.nativeEnum(InquiryStatus),
|
|
58
|
+
expiresAtIso: z.string(),
|
|
59
|
+
onTimeout: z.nativeEnum(InquiryTimeoutAction),
|
|
60
|
+
/**
|
|
61
|
+
* Escalation chain — linear list of recipient sets, each tried in
|
|
62
|
+
* order on deadline-passed (`onTimeout === ESCALATE`). Empty when
|
|
63
|
+
* `onTimeout !== ESCALATE`. Validated at create time.
|
|
64
|
+
*/
|
|
65
|
+
escalationChain: z.array(EscalationStepSchema),
|
|
66
|
+
/**
|
|
67
|
+
* Action when the escalation chain is exhausted (i.e. the final
|
|
68
|
+
* step's deadline passes with no terminal verdict). Closed set:
|
|
69
|
+
* `REJECT` (default) or `APPROVE`. `ESCALATE` is rejected here at
|
|
70
|
+
* the schema level — would be a runtime infinite loop.
|
|
71
|
+
*/
|
|
72
|
+
onEscalationExhaustion: z.enum(['reject', 'approve']),
|
|
73
|
+
/**
|
|
74
|
+
* Zero-based pointer into `escalationChain`. Bumped each time the
|
|
75
|
+
* engine advances. `0` means "still on the original recipients";
|
|
76
|
+
* `1` means "currently on chain[0]"; etc. (i.e. it counts how many
|
|
77
|
+
* escalations have fired, NOT which slot of the chain is active).
|
|
78
|
+
*/
|
|
79
|
+
currentEscalationLevel: z.number().int().nonnegative(),
|
|
80
|
+
verdict: z.record(z.string(), z.unknown()).nullable(),
|
|
81
|
+
resolvedAtIso: z.string().nullable(),
|
|
82
|
+
cancelledAtIso: z.string().nullable(),
|
|
83
|
+
createdAtIso: z.string(),
|
|
84
|
+
updatedAtIso: z.string(),
|
|
85
|
+
recipients: z.array(
|
|
86
|
+
z.object({
|
|
87
|
+
id: z.string().min(1),
|
|
88
|
+
ord: z.number().int().nonnegative(),
|
|
89
|
+
kind: z.nativeEnum(RecipientKind),
|
|
90
|
+
target: z.record(z.string(), z.unknown()),
|
|
91
|
+
status: z.nativeEnum(InquiryRecipientStatus),
|
|
92
|
+
replyId: z.string().nullable(),
|
|
93
|
+
mandatory: z.boolean(),
|
|
94
|
+
}),
|
|
95
|
+
),
|
|
96
|
+
replies: z
|
|
97
|
+
.array(
|
|
98
|
+
z.object({
|
|
99
|
+
id: z.string().min(1),
|
|
100
|
+
recipientId: z.string().min(1),
|
|
101
|
+
payload: z.record(z.string(), z.unknown()),
|
|
102
|
+
submittedBy: z.string().min(1),
|
|
103
|
+
submittedAtIso: z.string(),
|
|
104
|
+
}),
|
|
105
|
+
)
|
|
106
|
+
.optional(),
|
|
107
|
+
});
|
|
108
|
+
export type Inquiry = z.infer<typeof InquirySchema>;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Caller-supplied input for `POST /inquiries`. The engine generates the
|
|
112
|
+
* recipient IDs and timestamps. `id` is caller-supplied so the engine is
|
|
113
|
+
* idempotent on retry — a duplicate POST returns the existing row.
|
|
114
|
+
*/
|
|
115
|
+
export const CreateInquiryInputSchema = z
|
|
116
|
+
.object({
|
|
117
|
+
id: z.string().min(1),
|
|
118
|
+
orgId: z.string().min(1),
|
|
119
|
+
projectId: z.string().min(1),
|
|
120
|
+
workflowRunId: z.string().min(1),
|
|
121
|
+
jobRunId: z.string().min(1),
|
|
122
|
+
kind: z.nativeEnum(InquiryKind),
|
|
123
|
+
title: z.string(),
|
|
124
|
+
prompt: z.record(z.string(), z.unknown()),
|
|
125
|
+
policy: ReplyPolicySchema,
|
|
126
|
+
recipients: z.array(RecipientSchema).min(1),
|
|
127
|
+
expiresAtIso: z.string(),
|
|
128
|
+
onTimeout: z.nativeEnum(InquiryTimeoutAction),
|
|
129
|
+
escalationChain: z.array(EscalationStepSchema).optional(),
|
|
130
|
+
onEscalationExhaustion: z.enum(['reject', 'approve']).optional(),
|
|
131
|
+
})
|
|
132
|
+
.superRefine((value, ctx) => {
|
|
133
|
+
// ESCALATE without a chain is meaningless — would have to fall back
|
|
134
|
+
// to REJECT/APPROVE on the first timeout, defeating the point.
|
|
135
|
+
if (
|
|
136
|
+
value.onTimeout === InquiryTimeoutAction.ESCALATE &&
|
|
137
|
+
(value.escalationChain === undefined || value.escalationChain.length === 0)
|
|
138
|
+
) {
|
|
139
|
+
ctx.addIssue({
|
|
140
|
+
code: z.ZodIssueCode.custom,
|
|
141
|
+
path: ['escalationChain'],
|
|
142
|
+
message:
|
|
143
|
+
'onTimeout=ESCALATE requires a non-empty escalationChain. Configure at least one escalation step or change onTimeout.',
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
// A chain on a non-escalating inquiry is dead weight; flag it so the
|
|
147
|
+
// workflow author notices the misconfiguration.
|
|
148
|
+
if (
|
|
149
|
+
value.onTimeout !== InquiryTimeoutAction.ESCALATE &&
|
|
150
|
+
value.escalationChain !== undefined &&
|
|
151
|
+
value.escalationChain.length > 0
|
|
152
|
+
) {
|
|
153
|
+
ctx.addIssue({
|
|
154
|
+
code: z.ZodIssueCode.custom,
|
|
155
|
+
path: ['escalationChain'],
|
|
156
|
+
message: `escalationChain is set but onTimeout=${value.onTimeout} — change onTimeout to ESCALATE or remove the chain.`,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
export type CreateInquiryInput = z.infer<typeof CreateInquiryInputSchema>;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Reply submitted by one recipient. Engine validates `payload` against the
|
|
164
|
+
* kind-specific reply schema before insert; per-recipient idempotency is
|
|
165
|
+
* enforced via `SELECT … FOR UPDATE` on the recipient row.
|
|
166
|
+
*/
|
|
167
|
+
export const InquiryReplySchema = z.object({
|
|
168
|
+
id: z.string().min(1),
|
|
169
|
+
inquiryId: z.string().min(1),
|
|
170
|
+
recipientId: z.string().min(1),
|
|
171
|
+
payload: z.record(z.string(), z.unknown()),
|
|
172
|
+
submittedBy: z.string().min(1),
|
|
173
|
+
submittedAtIso: z.string(),
|
|
174
|
+
});
|
|
175
|
+
export type InquiryReply = z.infer<typeof InquiryReplySchema>;
|
|
176
|
+
|
|
177
|
+
export const SubmitReplyInputSchema = z.object({
|
|
178
|
+
recipientId: z.string().min(1),
|
|
179
|
+
payload: z.record(z.string(), z.unknown()),
|
|
180
|
+
submittedBy: z.string().min(1),
|
|
181
|
+
});
|
|
182
|
+
export type SubmitReplyInput = z.infer<typeof SubmitReplyInputSchema>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import type { InquiryKind } from './enums';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Per-kind schema pair. Engine + bridge use these to validate `prompt` on
|
|
7
|
+
* inquiry creation and `payload` on reply submission. Each consumer of an
|
|
8
|
+
* `InquiryKind` registers its schemas at module init.
|
|
9
|
+
*
|
|
10
|
+
* The registry is intentionally NOT auto-populated here — populating it
|
|
11
|
+
* would create a hard dependency from this package to every kind's
|
|
12
|
+
* contract package, defeating the point of keeping per-kind contracts in
|
|
13
|
+
* their own packages. Instead, the engine imports each contract package
|
|
14
|
+
* and calls `registerInquiryKind` at boot.
|
|
15
|
+
*/
|
|
16
|
+
export interface InquiryKindSchemas {
|
|
17
|
+
readonly promptSchema: z.ZodType<unknown>;
|
|
18
|
+
readonly replySchema: z.ZodType<unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Optional verdict shape — only relevant for kinds that aggregate
|
|
21
|
+
* across recipients (e.g. DECISION_GATE). For per-reply kinds (e.g.
|
|
22
|
+
* AGENT_TOOL_INQUIRY with policy=SINGLE), this can be omitted; the
|
|
23
|
+
* verdict is just the first reply's payload.
|
|
24
|
+
*/
|
|
25
|
+
readonly verdictSchema?: z.ZodType<unknown>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* In-process registry. The engine has one instance bound at module init;
|
|
30
|
+
* the worker has another. Tests construct their own registries.
|
|
31
|
+
*/
|
|
32
|
+
export class InquiryKindSchemaRegistry {
|
|
33
|
+
private readonly entries = new Map<InquiryKind, InquiryKindSchemas>();
|
|
34
|
+
|
|
35
|
+
register(kind: InquiryKind, schemas: InquiryKindSchemas): void {
|
|
36
|
+
if (this.entries.has(kind)) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
`InquiryKindSchemaRegistry: kind '${kind}' is already registered`,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
this.entries.set(kind, schemas);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get(kind: InquiryKind): InquiryKindSchemas {
|
|
45
|
+
const schemas = this.entries.get(kind);
|
|
46
|
+
if (!schemas) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
`InquiryKindSchemaRegistry: no schemas registered for kind '${kind}'`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return schemas;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
has(kind: InquiryKind): boolean {
|
|
55
|
+
return this.entries.has(kind);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import { ReplyPolicyKind } from './enums';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What to do when an agent or endpoint recipient submits an ABSTAIN
|
|
7
|
+
* verdict. `skip` (default) ignores the recipient's vote and waits for the
|
|
8
|
+
* remaining recipients; `reject_implicit` treats abstention as a rejection
|
|
9
|
+
* for purposes of M_OF_N / ALL_OF arithmetic. Without this knob, a flaky
|
|
10
|
+
* LLM can silently sink an inquiry by abstaining.
|
|
11
|
+
*/
|
|
12
|
+
export enum AbstainTreatment {
|
|
13
|
+
SKIP = 'skip',
|
|
14
|
+
REJECT_IMPLICIT = 'reject_implicit',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ReplyPolicySchema = z.discriminatedUnion('kind', [
|
|
18
|
+
z.object({ kind: z.literal(ReplyPolicyKind.SINGLE) }),
|
|
19
|
+
z.object({
|
|
20
|
+
kind: z.literal(ReplyPolicyKind.M_OF_N),
|
|
21
|
+
m: z.number().int().positive(),
|
|
22
|
+
abstainTreatment: z.nativeEnum(AbstainTreatment).optional(),
|
|
23
|
+
}),
|
|
24
|
+
z.object({ kind: z.literal(ReplyPolicyKind.ALL_OF) }),
|
|
25
|
+
z.object({ kind: z.literal(ReplyPolicyKind.ANY_OF) }),
|
|
26
|
+
]);
|
|
27
|
+
export type ReplyPolicy = z.infer<typeof ReplyPolicySchema>;
|