@mastra/factory 0.13.0-alpha.16 → 0.13.0-alpha.18
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/README.md +123 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -1
- package/dist/boards/define-board.d.ts.map +1 -1
- package/dist/boards/define-board.js +9 -2
- package/dist/boards/define-board.js.map +1 -1
- package/dist/boards/index.d.ts +1 -1
- package/dist/boards/review.d.ts +1 -1
- package/dist/boards/work.d.ts +1 -1
- package/dist/boards/work.js +1 -1
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +7 -0
- package/dist/factory.js.map +1 -1
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +7 -4
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -0
- package/dist/integrations/linear/issue-reconciler.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +2 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +9 -3
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/routes/contracts.d.ts +21 -43
- package/dist/routes/contracts.d.ts.map +1 -1
- package/dist/routes/contracts.js +3 -10
- package/dist/routes/contracts.js.map +1 -1
- package/dist/routes/telemetry.d.ts +13 -0
- package/dist/routes/telemetry.d.ts.map +1 -0
- package/dist/routes/telemetry.js +60 -0
- package/dist/routes/telemetry.js.map +1 -0
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +23 -6
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/index.js +1 -1
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +17 -22
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/tools.js +18 -7
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/transition-service.d.ts.map +1 -1
- package/dist/rules/transition-service.js +2 -1
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/validation.d.ts +5 -0
- package/dist/rules/validation.d.ts.map +1 -1
- package/dist/rules/validation.js +21 -6
- package/dist/rules/validation.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +5 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +8 -0
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/supervisor/health.js +1 -1
- package/dist/supervisor/write-tools.d.ts.map +1 -1
- package/dist/supervisor/write-tools.js +6 -4
- package/dist/supervisor/write-tools.js.map +1 -1
- package/dist/telemetry-types.d.ts +7 -0
- package/dist/telemetry-types.d.ts.map +1 -0
- package/dist/telemetry-types.js +24 -0
- package/dist/telemetry-types.js.map +1 -0
- package/dist/telemetry.d.ts +9 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +47 -0
- package/dist/telemetry.js.map +1 -0
- package/factory-skills/configure-factory-rules/SKILL.md +13 -1
- package/package.json +7 -6
|
@@ -57,27 +57,16 @@ export declare const updateWorkItemBodySchema: z.ZodObject<{
|
|
|
57
57
|
plansPreapproved: z.ZodOptional<z.ZodLiteral<true>>;
|
|
58
58
|
}, z.core.$strip>;
|
|
59
59
|
export declare const transitionBodySchema: z.ZodPipe<z.ZodObject<{
|
|
60
|
-
board: z.
|
|
61
|
-
|
|
62
|
-
work: "work";
|
|
63
|
-
}>;
|
|
64
|
-
stage: z.ZodEnum<{
|
|
65
|
-
intake: "intake";
|
|
66
|
-
triage: "triage";
|
|
67
|
-
planning: "planning";
|
|
68
|
-
execute: "execute";
|
|
69
|
-
review: "review";
|
|
70
|
-
done: "done";
|
|
71
|
-
canceled: "canceled";
|
|
72
|
-
}>;
|
|
60
|
+
board: z.ZodString;
|
|
61
|
+
stage: z.ZodString;
|
|
73
62
|
expectedRevision: z.ZodNumber;
|
|
74
63
|
requestId: z.ZodString;
|
|
75
64
|
cause: z.ZodString;
|
|
76
65
|
reenter: z.ZodOptional<z.ZodUnknown>;
|
|
77
66
|
}, z.core.$strip>, z.ZodTransform<{
|
|
78
67
|
reenter?: boolean | undefined;
|
|
79
|
-
board:
|
|
80
|
-
stage:
|
|
68
|
+
board: string;
|
|
69
|
+
stage: string;
|
|
81
70
|
expectedRevision: number;
|
|
82
71
|
ingress: {
|
|
83
72
|
type: "human";
|
|
@@ -85,8 +74,8 @@ export declare const transitionBodySchema: z.ZodPipe<z.ZodObject<{
|
|
|
85
74
|
};
|
|
86
75
|
cause: string;
|
|
87
76
|
}, {
|
|
88
|
-
board:
|
|
89
|
-
stage:
|
|
77
|
+
board: string;
|
|
78
|
+
stage: string;
|
|
90
79
|
expectedRevision: number;
|
|
91
80
|
requestId: string;
|
|
92
81
|
cause: string;
|
|
@@ -144,14 +133,14 @@ export declare const attentionQuerySchema: z.ZodObject<{
|
|
|
144
133
|
archived: "archived";
|
|
145
134
|
}>>>;
|
|
146
135
|
kind: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
136
|
+
activity: "activity";
|
|
147
137
|
"automation-failed": "automation-failed";
|
|
148
138
|
"automation-proposed": "automation-proposed";
|
|
149
139
|
mention: "mention";
|
|
150
|
-
activity: "activity";
|
|
151
140
|
"supervisor-finding": "supervisor-finding";
|
|
152
141
|
"agent-waiting": "agent-waiting";
|
|
153
142
|
}>>>;
|
|
154
|
-
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"automation-failed" | "automation-proposed" | "mention" | "
|
|
143
|
+
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"activity" | "automation-failed" | "automation-proposed" | "mention" | "supervisor-finding" | "agent-waiting", AttentionStreamPosition | undefined> | undefined, string | undefined>>;
|
|
155
144
|
limit: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<number, string | undefined>>;
|
|
156
145
|
search: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
|
|
157
146
|
}, z.core.$strip>;
|
|
@@ -331,27 +320,16 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
331
320
|
workItemId: z.ZodString;
|
|
332
321
|
}, z.core.$strip>;
|
|
333
322
|
readonly bodySchema: z.ZodPipe<z.ZodObject<{
|
|
334
|
-
board: z.
|
|
335
|
-
|
|
336
|
-
work: "work";
|
|
337
|
-
}>;
|
|
338
|
-
stage: z.ZodEnum<{
|
|
339
|
-
intake: "intake";
|
|
340
|
-
triage: "triage";
|
|
341
|
-
planning: "planning";
|
|
342
|
-
execute: "execute";
|
|
343
|
-
review: "review";
|
|
344
|
-
done: "done";
|
|
345
|
-
canceled: "canceled";
|
|
346
|
-
}>;
|
|
323
|
+
board: z.ZodString;
|
|
324
|
+
stage: z.ZodString;
|
|
347
325
|
expectedRevision: z.ZodNumber;
|
|
348
326
|
requestId: z.ZodString;
|
|
349
327
|
cause: z.ZodString;
|
|
350
328
|
reenter: z.ZodOptional<z.ZodUnknown>;
|
|
351
329
|
}, z.core.$strip>, z.ZodTransform<{
|
|
352
330
|
reenter?: boolean | undefined;
|
|
353
|
-
board:
|
|
354
|
-
stage:
|
|
331
|
+
board: string;
|
|
332
|
+
stage: string;
|
|
355
333
|
expectedRevision: number;
|
|
356
334
|
ingress: {
|
|
357
335
|
type: "human";
|
|
@@ -359,8 +337,8 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
359
337
|
};
|
|
360
338
|
cause: string;
|
|
361
339
|
}, {
|
|
362
|
-
board:
|
|
363
|
-
stage:
|
|
340
|
+
board: string;
|
|
341
|
+
stage: string;
|
|
364
342
|
expectedRevision: number;
|
|
365
343
|
requestId: string;
|
|
366
344
|
cause: string;
|
|
@@ -476,24 +454,24 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
476
454
|
archived: "archived";
|
|
477
455
|
}>>>;
|
|
478
456
|
kind: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
457
|
+
activity: "activity";
|
|
479
458
|
"automation-failed": "automation-failed";
|
|
480
459
|
"automation-proposed": "automation-proposed";
|
|
481
460
|
mention: "mention";
|
|
482
|
-
activity: "activity";
|
|
483
461
|
"supervisor-finding": "supervisor-finding";
|
|
484
462
|
"agent-waiting": "agent-waiting";
|
|
485
463
|
}>>>;
|
|
486
|
-
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"automation-failed" | "automation-proposed" | "mention" | "
|
|
464
|
+
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"activity" | "automation-failed" | "automation-proposed" | "mention" | "supervisor-finding" | "agent-waiting", AttentionStreamPosition | undefined> | undefined, string | undefined>>;
|
|
487
465
|
limit: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<number, string | undefined>>;
|
|
488
466
|
search: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<string | undefined, string | undefined>>;
|
|
489
467
|
}, z.core.$strip>;
|
|
490
468
|
readonly responseSchema: z.ZodObject<{
|
|
491
469
|
items: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
492
470
|
kinds: z.ZodRecord<z.ZodEnum<{
|
|
471
|
+
activity: "activity";
|
|
493
472
|
"automation-failed": "automation-failed";
|
|
494
473
|
"automation-proposed": "automation-proposed";
|
|
495
474
|
mention: "mention";
|
|
496
|
-
activity: "activity";
|
|
497
475
|
"supervisor-finding": "supervisor-finding";
|
|
498
476
|
"agent-waiting": "agent-waiting";
|
|
499
477
|
}>, z.ZodObject<{
|
|
@@ -517,7 +495,7 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
517
495
|
id: z.ZodString;
|
|
518
496
|
}, z.core.$strip>;
|
|
519
497
|
readonly querySchema: z.ZodObject<{
|
|
520
|
-
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"automation-failed" | "automation-proposed" | "mention" | "
|
|
498
|
+
before: z.ZodPipe<z.ZodOptional<z.ZodString>, z.ZodTransform<Map<"activity" | "automation-failed" | "automation-proposed" | "mention" | "supervisor-finding" | "agent-waiting", AttentionStreamPosition | undefined> | undefined, string | undefined>>;
|
|
521
499
|
}, z.core.$strip>;
|
|
522
500
|
readonly responseSchema: z.ZodObject<{
|
|
523
501
|
ok: z.ZodLiteral<true>;
|
|
@@ -532,10 +510,10 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
532
510
|
readonly pathSchema: z.ZodObject<{
|
|
533
511
|
id: z.ZodString;
|
|
534
512
|
kind: z.ZodEnum<{
|
|
513
|
+
activity: "activity";
|
|
535
514
|
"automation-failed": "automation-failed";
|
|
536
515
|
"automation-proposed": "automation-proposed";
|
|
537
516
|
mention: "mention";
|
|
538
|
-
activity: "activity";
|
|
539
517
|
"supervisor-finding": "supervisor-finding";
|
|
540
518
|
"agent-waiting": "agent-waiting";
|
|
541
519
|
}>;
|
|
@@ -553,10 +531,10 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
553
531
|
readonly pathSchema: z.ZodObject<{
|
|
554
532
|
id: z.ZodString;
|
|
555
533
|
kind: z.ZodEnum<{
|
|
534
|
+
activity: "activity";
|
|
556
535
|
"automation-failed": "automation-failed";
|
|
557
536
|
"automation-proposed": "automation-proposed";
|
|
558
537
|
mention: "mention";
|
|
559
|
-
activity: "activity";
|
|
560
538
|
"supervisor-finding": "supervisor-finding";
|
|
561
539
|
"agent-waiting": "agent-waiting";
|
|
562
540
|
}>;
|
|
@@ -574,10 +552,10 @@ export declare const FACTORY_ROUTE_CONTRACTS: {
|
|
|
574
552
|
readonly pathSchema: z.ZodObject<{
|
|
575
553
|
id: z.ZodString;
|
|
576
554
|
kind: z.ZodEnum<{
|
|
555
|
+
activity: "activity";
|
|
577
556
|
"automation-failed": "automation-failed";
|
|
578
557
|
"automation-proposed": "automation-proposed";
|
|
579
558
|
mention: "mention";
|
|
580
|
-
activity: "activity";
|
|
581
559
|
"supervisor-finding": "supervisor-finding";
|
|
582
560
|
"agent-waiting": "agent-waiting";
|
|
583
561
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/routes/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/routes/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC;IACvB,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,YAAY,kFAAkF,CAAC;AA8B5G,eAAO,MAAM,uBAAuB;;;iBAGlC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;iBASoE,CAAC;AAgDzG,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;iBAQnC,CAAC;AAEH,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;iBAUqE,CAAC;AAE3G,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;GAgB5B,CAAC;AAEN,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBASlC,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;iBAG7B,CAAC;AA8CH,eAAO,MAAM,mBAAmB;;;;;;;iBAa9B,CAAC;AAWH,KAAK,uBAAuB,GAAG;IAAE,UAAU,EAAE,IAAI,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AA6ChE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;iBAS/B,CAAC;AAyBH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqMqB,CAAC;AAE1D,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,uBAAuB,CAAC"}
|
package/dist/routes/contracts.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BOARD_IDENTIFIER_RE } from "../rules/validation.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
//#region src/routes/contracts.ts
|
|
3
4
|
const UUID_PATTERN = "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$";
|
|
@@ -76,16 +77,8 @@ const updateWorkItemBodySchema = z.object({
|
|
|
76
77
|
plansPreapproved: z.literal(true).optional()
|
|
77
78
|
}).refine((input) => Object.keys(input).length > 0, { message: "At least one work-item field is required" });
|
|
78
79
|
const transitionBodySchema = z.object({
|
|
79
|
-
board: z.
|
|
80
|
-
stage: z.
|
|
81
|
-
"intake",
|
|
82
|
-
"triage",
|
|
83
|
-
"planning",
|
|
84
|
-
"execute",
|
|
85
|
-
"review",
|
|
86
|
-
"done",
|
|
87
|
-
"canceled"
|
|
88
|
-
]),
|
|
80
|
+
board: z.string().max(128).regex(BOARD_IDENTIFIER_RE),
|
|
81
|
+
stage: z.string().max(128).regex(BOARD_IDENTIFIER_RE),
|
|
89
82
|
expectedRevision: z.number().int().min(1),
|
|
90
83
|
requestId: trimmedUuidSchema,
|
|
91
84
|
cause: nonEmptyTrimmed(256),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.js","names":[],"sources":["../../src/routes/contracts.ts"],"sourcesContent":["import { z } from 'zod';\n\nexport type FactoryRouteContract = {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n path: string;\n description: string;\n pathSchema?: z.ZodType;\n querySchema?: z.ZodType;\n bodySchema?: z.ZodType;\n responseSchema: z.ZodType;\n};\n\nexport const UUID_PATTERN = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$';\nconst uuidSchema = z.string().regex(new RegExp(UUID_PATTERN));\nconst entitySchema = z.record(z.string(), z.unknown());\nconst nonEmptyTrimmed = (max: number) => z.string().trim().min(1).max(max);\nconst rawBoundedTrimmed = (max: number) =>\n z\n .string()\n .max(max)\n .transform(value => value.trim())\n .pipe(z.string().min(1));\nconst trimmedUuidSchema = z.string().trim().regex(new RegExp(UUID_PATTERN));\nconst nullableTrimmed = (max: number) =>\n z.union([\n z\n .string()\n .trim()\n .max(max)\n .transform(value => value || null),\n z.null(),\n ]);\nconst projectPathSchema = z.object({ id: uuidSchema });\nconst projectDecisionPathSchema = z.object({ id: uuidSchema, decisionId: uuidSchema });\nconst workItemPathSchema = z.object({ id: uuidSchema });\nconst transitionPathSchema = z.object({ id: uuidSchema, workItemId: uuidSchema });\n\nconst projectSchema = entitySchema;\nconst projectResponseSchema = z.object({ project: projectSchema });\nconst workItemResponseSchema = z.object({ workItem: entitySchema });\nconst decisionResponseSchema = z.object({ decision: entitySchema });\n\nexport const createProjectBodySchema = z.object({\n name: nonEmptyTrimmed(200),\n description: nullableTrimmed(2_000).optional().default(null),\n});\n\nexport const updateProjectBodySchema = z\n .object({\n name: nonEmptyTrimmed(200).optional(),\n description: nullableTrimmed(2_000).optional(),\n defaultModelId: nullableTrimmed(200).optional(),\n slackWorkItemsEnabled: z.boolean().optional(),\n autoRunEnabled: z.boolean().optional(),\n autoApprovePlans: z.boolean().optional(),\n })\n .refine(input => Object.keys(input).length > 0, { message: 'At least one project field is required' });\n\nconst stagesSchema = z\n .array(\n z\n .string()\n .max(64)\n .regex(/^[a-z0-9][a-z0-9_-]*$/i),\n )\n .min(1)\n .max(16)\n .refine(stages => new Set(stages).size === stages.length, { message: 'Stages must be unique' });\n\nconst externalSourceSchema = z\n .object({\n integrationId: z.string().min(1).max(128),\n type: z.string().min(1).max(128),\n externalId: z.string().min(1).max(512),\n url: z.string().max(2_048).optional(),\n })\n .nullable();\n\nconst sessionSchema = z.object({\n sessionId: z.string().min(1).max(512),\n branch: z.string().min(1).max(512),\n threadId: z.string().min(1).max(512),\n});\n\nconst sessionsSchema = z.record(z.string().min(1).max(64), sessionSchema);\nconst metadataSchema = z\n .union([z.record(z.string(), z.unknown()), z.null()])\n .refine(value => {\n try {\n return JSON.stringify(value).length <= 16 * 1024;\n } catch {\n return false;\n }\n }, 'Metadata exceeds 16 KiB')\n .transform(value => {\n if (value === null) return null;\n const {\n factoryRuleMaterializationKey: _materialization,\n factoryPullRequestReconciliation: _reconciliation,\n ...metadata\n } = value;\n return metadata;\n });\n\nexport const createWorkItemBodySchema = z.object({\n title: rawBoundedTrimmed(500),\n board: z.string().min(1).max(128).optional(),\n externalSource: externalSourceSchema.optional(),\n parentWorkItemId: uuidSchema.nullable().optional(),\n stages: stagesSchema.optional(),\n sessions: sessionsSchema.optional(),\n metadata: metadataSchema.optional(),\n});\n\nexport const updateWorkItemBodySchema = z\n .object({\n title: rawBoundedTrimmed(500).optional(),\n board: z.string().min(1).max(128).optional(),\n parentWorkItemId: uuidSchema.nullable().optional(),\n stages: stagesSchema.optional(),\n sessions: sessionsSchema.optional(),\n metadata: metadataSchema.optional(),\n plansPreapproved: z.literal(true).optional(),\n })\n .refine(input => Object.keys(input).length > 0, { message: 'At least one work-item field is required' });\n\nexport const transitionBodySchema = z\n .object({\n board: z.enum(['work', 'review']),\n stage: z.enum(['intake', 'triage', 'planning', 'execute', 'review', 'done', 'canceled']),\n expectedRevision: z.number().int().min(1),\n requestId: trimmedUuidSchema,\n cause: nonEmptyTrimmed(256),\n reenter: z.unknown().optional(),\n })\n .transform(input => ({\n board: input.board,\n stage: input.stage,\n expectedRevision: input.expectedRevision,\n ingress: { type: 'human' as const, identity: input.requestId },\n cause: input.cause,\n ...(input.reenter === true ? { reenter: true } : {}),\n }));\n\nexport const startWorkItemBodySchema = z.object({\n sessionId: trimmedUuidSchema,\n threadTitle: nonEmptyTrimmed(512),\n kickoffKey: trimmedUuidSchema,\n workItem: z.object({\n id: trimmedUuidSchema,\n role: nonEmptyTrimmed(32),\n input: createWorkItemBodySchema,\n }),\n});\n\nexport const metricsQuerySchema = z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n});\n\nconst decisionStatusSchema = z.enum([\n 'pending',\n 'proposed',\n 'dismissed',\n 'superseded',\n 'leased',\n 'retry',\n 'succeeded',\n 'failed',\n]);\nconst boundedLimitSchema = (defaultValue: number, max: number) =>\n z\n .string()\n .optional()\n .transform(value => {\n const parsed = value ? Number.parseInt(value, 10) : defaultValue;\n return Number.isFinite(parsed) ? Math.max(1, Math.min(max, parsed)) : defaultValue;\n });\nconst decisionCursorSchema = z\n .string()\n .optional()\n .transform((value, context) => {\n if (!value) return undefined;\n try {\n const decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as unknown;\n if (\n !Array.isArray(decoded) ||\n decoded.length !== 2 ||\n typeof decoded[0] !== 'string' ||\n typeof decoded[1] !== 'string'\n ) {\n throw new Error('invalid cursor');\n }\n const createdAt = new Date(decoded[0]);\n if (Number.isNaN(createdAt.getTime()) || !new RegExp(UUID_PATTERN).test(decoded[1])) {\n throw new Error('invalid cursor');\n }\n return { createdAt, id: decoded[1] };\n } catch {\n context.addIssue({ code: 'custom', message: 'Invalid cursor' });\n return z.NEVER;\n }\n });\n\nexport const decisionQuerySchema = z.object({\n statuses: z\n .string()\n .optional()\n .transform(value => {\n if (!value) return undefined;\n const statuses = [...new Set(value.split(',').map(status => status.trim()))].filter(\n status => decisionStatusSchema.safeParse(status).success,\n ) as Array<z.infer<typeof decisionStatusSchema>>;\n return statuses.length > 0 ? statuses : undefined;\n }),\n before: decisionCursorSchema,\n limit: boundedLimitSchema(25, 50),\n});\n\nconst attentionKindSchema = z.enum([\n 'automation-failed',\n 'automation-proposed',\n 'mention',\n 'activity',\n 'supervisor-finding',\n 'agent-waiting',\n]);\ntype AttentionKind = z.infer<typeof attentionKindSchema>;\ntype AttentionStreamPosition = { occurredAt: Date; id: string };\ntype AttentionCursorMap = Map<AttentionKind, AttentionStreamPosition | undefined>;\n\nfunction parseAttentionStreamPosition(value: unknown): AttentionStreamPosition | undefined {\n if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== 'string' || typeof value[1] !== 'string') {\n return undefined;\n }\n const occurredAt = new Date(value[0]);\n if (Number.isNaN(occurredAt.getTime()) || !new RegExp(UUID_PATTERN).test(value[1])) return undefined;\n return { occurredAt, id: value[1] };\n}\n\nconst attentionCursorSchema = z\n .string()\n .optional()\n .transform((value, context) => {\n if (!value) return undefined;\n try {\n const decoded: unknown = JSON.parse(Buffer.from(value, 'base64url').toString('utf8'));\n if (Array.isArray(decoded)) {\n const legacy = parseAttentionStreamPosition(decoded);\n if (!legacy) throw new Error('invalid cursor');\n return new Map<AttentionKind, AttentionStreamPosition | undefined>([['automation-failed', legacy]]);\n }\n if (!decoded || typeof decoded !== 'object') throw new Error('invalid cursor');\n const cursors: AttentionCursorMap = new Map();\n for (const [kind, positionValue] of Object.entries(decoded)) {\n const parsedKind = attentionKindSchema.safeParse(kind);\n if (!parsedKind.success) throw new Error('invalid cursor');\n if (positionValue === null) {\n cursors.set(parsedKind.data, undefined);\n continue;\n }\n const position = parseAttentionStreamPosition(positionValue);\n if (!position) throw new Error('invalid cursor');\n cursors.set(parsedKind.data, position);\n }\n if (cursors.size === 0) throw new Error('invalid cursor');\n return cursors;\n } catch {\n context.addIssue({ code: 'custom', message: 'Invalid cursor' });\n return z.NEVER;\n }\n });\n\nexport const attentionQuerySchema = z.object({\n view: z.enum(['open', 'unread', 'archived']).optional().default('open'),\n kind: z.array(attentionKindSchema).optional(),\n before: attentionCursorSchema,\n limit: boundedLimitSchema(25, 50),\n search: z\n .string()\n .optional()\n .transform(value => value?.trim().toLowerCase().slice(0, 200) || undefined),\n});\n\nconst attentionActionPathSchema = z\n .object({\n id: uuidSchema,\n kind: attentionKindSchema,\n sourceId: z.string().min(1).max(256),\n occurrence: z\n .string()\n .regex(/^(0|[1-9]\\d*)$/)\n .transform((value, context) => {\n const occurrence = Number(value);\n if (Number.isSafeInteger(occurrence)) return occurrence;\n context.addIssue({ code: 'custom', message: 'Invalid occurrence' });\n return z.NEVER;\n }),\n })\n .refine(\n input =>\n input.kind === 'supervisor-finding'\n ? /^[a-z0-9:_-]{1,256}$/i.test(input.sourceId)\n : new RegExp(UUID_PATTERN).test(input.sourceId),\n { message: 'Invalid attention source id', path: ['sourceId'] },\n );\n\nexport const FACTORY_ROUTE_CONTRACTS = {\n projectList: {\n method: 'GET',\n path: '/web/factory/projects',\n description: 'List Factory projects for the current organization',\n responseSchema: z.object({ projects: z.array(projectSchema) }),\n },\n projectCreate: {\n method: 'POST',\n path: '/web/factory/projects',\n description: 'Create a Factory project',\n bodySchema: createProjectBodySchema,\n responseSchema: projectResponseSchema,\n },\n projectGet: {\n method: 'GET',\n path: '/web/factory/projects/:id',\n description: 'Get a Factory project',\n pathSchema: projectPathSchema,\n responseSchema: projectResponseSchema,\n },\n projectUpdate: {\n method: 'PATCH',\n path: '/web/factory/projects/:id',\n description: 'Update a Factory project',\n pathSchema: projectPathSchema,\n bodySchema: updateProjectBodySchema,\n responseSchema: projectResponseSchema,\n },\n projectDelete: {\n method: 'DELETE',\n path: '/web/factory/projects/:id',\n description: 'Delete a Factory project',\n pathSchema: projectPathSchema,\n responseSchema: z.null(),\n },\n metricsGet: {\n method: 'GET',\n path: '/web/factory/projects/:id/metrics',\n description: 'Get Factory project metrics',\n pathSchema: projectPathSchema,\n querySchema: metricsQuerySchema,\n responseSchema: z.object({ metrics: entitySchema }),\n },\n healthThresholdsGet: {\n method: 'GET',\n path: '/web/factory/projects/:id/health/thresholds',\n description: 'Get queue-health thresholds',\n pathSchema: projectPathSchema,\n responseSchema: z.object({ thresholds: z.array(z.number().finite()) }),\n },\n workItemList: {\n method: 'GET',\n path: '/web/factory/projects/:id/work-items',\n description: 'List Factory work items and running sessions',\n pathSchema: projectPathSchema,\n responseSchema: z.object({\n workItems: z.array(entitySchema),\n runningSessionIds: z.array(z.string()),\n parkedSessionIds: z.array(z.string()),\n }),\n },\n workItemCreate: {\n method: 'POST',\n path: '/web/factory/projects/:id/work-items',\n description: 'Create a work item in Intake',\n pathSchema: projectPathSchema,\n bodySchema: createWorkItemBodySchema,\n responseSchema: workItemResponseSchema,\n },\n workItemUpdate: {\n method: 'PATCH',\n path: '/web/factory/work-items/:id',\n description: 'Update non-stage work-item fields',\n pathSchema: workItemPathSchema,\n bodySchema: updateWorkItemBodySchema,\n responseSchema: workItemResponseSchema,\n },\n workItemDelete: {\n method: 'DELETE',\n path: '/web/factory/work-items/:id',\n description: 'Delete a Factory work item',\n pathSchema: workItemPathSchema,\n responseSchema: z.object({ ok: z.literal(true) }),\n },\n workItemTransition: {\n method: 'POST',\n path: '/web/factory/projects/:id/work-items/:workItemId/transition',\n description: 'Transition a work item with its expected revision',\n pathSchema: transitionPathSchema,\n bodySchema: transitionBodySchema,\n responseSchema: entitySchema,\n },\n workItemStart: {\n method: 'POST',\n path: '/web/factory/projects/:id/runs/start',\n description: 'Explicitly start a Factory work-item run',\n pathSchema: projectPathSchema,\n bodySchema: startWorkItemBodySchema,\n responseSchema: entitySchema,\n },\n decisionList: {\n method: 'GET',\n path: '/web/factory/projects/:id/decisions',\n description: 'List Factory decisions',\n pathSchema: projectPathSchema,\n querySchema: decisionQuerySchema,\n responseSchema: z.object({ decisions: z.array(entitySchema), nextCursor: z.string().optional() }),\n },\n decisionApprove: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/approve',\n description: 'Approve a proposed Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n decisionDismiss: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/dismiss',\n description: 'Dismiss a proposed Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n decisionRetry: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/retry',\n description: 'Retry a failed retryable Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n attentionList: {\n method: 'GET',\n path: '/web/factory/projects/:id/attention',\n description: 'List the Factory attention inbox',\n pathSchema: projectPathSchema,\n querySchema: attentionQuerySchema,\n responseSchema: z.object({\n items: z.array(entitySchema),\n kinds: z.record(\n attentionKindSchema,\n z.object({\n open: z.number(),\n unread: z.number(),\n latest: z.object({ key: z.string(), at: z.string(), unread: z.boolean() }).nullable(),\n }),\n ),\n hasMore: z.boolean(),\n nextCursor: z.string().optional(),\n }),\n },\n attentionReadAll: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/read-all',\n description: 'Mark all Factory attention as read',\n pathSchema: projectPathSchema,\n querySchema: z.object({ before: attentionCursorSchema }),\n responseSchema: z.object({ ok: z.literal(true), hasMore: z.boolean(), nextCursor: z.string().optional() }),\n },\n attentionRead: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/read',\n description: 'Mark a Factory attention receipt as read',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n attentionArchive: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/archive',\n description: 'Archive a Factory attention receipt',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n attentionRestore: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/restore',\n description: 'Restore an archived Factory attention receipt',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n supervisorSession: {\n method: 'POST',\n path: '/web/factory/projects/:id/supervisor/session',\n description: 'Get the deterministic Factory supervisor session address',\n pathSchema: projectPathSchema,\n responseSchema: z.object({ sessionId: z.string(), threadId: z.string(), factoryProjectId: uuidSchema }),\n },\n supervisorHealth: {\n method: 'GET',\n path: '/web/factory/projects/:id/supervisor/health',\n description: 'Run the deterministic Factory supervisor health check',\n pathSchema: projectPathSchema,\n responseSchema: z.object({\n checkedAt: z.string(),\n findings: z.array(entitySchema),\n counts: z.record(z.string(), z.number().int().nonnegative()),\n }),\n },\n} as const satisfies Record<string, FactoryRouteContract>;\n\nexport type FactoryRouteContractKey = keyof typeof FACTORY_ROUTE_CONTRACTS;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"contracts.js","names":[],"sources":["../../src/routes/contracts.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport { BOARD_IDENTIFIER_RE, MAX_BOARD_IDENTIFIER_LENGTH } from '../rules/validation.js';\n\nexport type FactoryRouteContract = {\n method: 'GET' | 'POST' | 'PATCH' | 'DELETE';\n path: string;\n description: string;\n pathSchema?: z.ZodType;\n querySchema?: z.ZodType;\n bodySchema?: z.ZodType;\n responseSchema: z.ZodType;\n};\n\nexport const UUID_PATTERN = '^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$';\nconst uuidSchema = z.string().regex(new RegExp(UUID_PATTERN));\nconst entitySchema = z.record(z.string(), z.unknown());\nconst nonEmptyTrimmed = (max: number) => z.string().trim().min(1).max(max);\nconst rawBoundedTrimmed = (max: number) =>\n z\n .string()\n .max(max)\n .transform(value => value.trim())\n .pipe(z.string().min(1));\nconst trimmedUuidSchema = z.string().trim().regex(new RegExp(UUID_PATTERN));\nconst nullableTrimmed = (max: number) =>\n z.union([\n z\n .string()\n .trim()\n .max(max)\n .transform(value => value || null),\n z.null(),\n ]);\nconst projectPathSchema = z.object({ id: uuidSchema });\nconst projectDecisionPathSchema = z.object({ id: uuidSchema, decisionId: uuidSchema });\nconst workItemPathSchema = z.object({ id: uuidSchema });\nconst transitionPathSchema = z.object({ id: uuidSchema, workItemId: uuidSchema });\n\nconst projectSchema = entitySchema;\nconst projectResponseSchema = z.object({ project: projectSchema });\nconst workItemResponseSchema = z.object({ workItem: entitySchema });\nconst decisionResponseSchema = z.object({ decision: entitySchema });\n\nexport const createProjectBodySchema = z.object({\n name: nonEmptyTrimmed(200),\n description: nullableTrimmed(2_000).optional().default(null),\n});\n\nexport const updateProjectBodySchema = z\n .object({\n name: nonEmptyTrimmed(200).optional(),\n description: nullableTrimmed(2_000).optional(),\n defaultModelId: nullableTrimmed(200).optional(),\n slackWorkItemsEnabled: z.boolean().optional(),\n autoRunEnabled: z.boolean().optional(),\n autoApprovePlans: z.boolean().optional(),\n })\n .refine(input => Object.keys(input).length > 0, { message: 'At least one project field is required' });\n\nconst stagesSchema = z\n .array(\n z\n .string()\n .max(64)\n .regex(/^[a-z0-9][a-z0-9_-]*$/i),\n )\n .min(1)\n .max(16)\n .refine(stages => new Set(stages).size === stages.length, { message: 'Stages must be unique' });\n\nconst externalSourceSchema = z\n .object({\n integrationId: z.string().min(1).max(128),\n type: z.string().min(1).max(128),\n externalId: z.string().min(1).max(512),\n url: z.string().max(2_048).optional(),\n })\n .nullable();\n\nconst sessionSchema = z.object({\n sessionId: z.string().min(1).max(512),\n branch: z.string().min(1).max(512),\n threadId: z.string().min(1).max(512),\n});\n\nconst sessionsSchema = z.record(z.string().min(1).max(64), sessionSchema);\nconst metadataSchema = z\n .union([z.record(z.string(), z.unknown()), z.null()])\n .refine(value => {\n try {\n return JSON.stringify(value).length <= 16 * 1024;\n } catch {\n return false;\n }\n }, 'Metadata exceeds 16 KiB')\n .transform(value => {\n if (value === null) return null;\n const {\n factoryRuleMaterializationKey: _materialization,\n factoryPullRequestReconciliation: _reconciliation,\n ...metadata\n } = value;\n return metadata;\n });\n\nexport const createWorkItemBodySchema = z.object({\n title: rawBoundedTrimmed(500),\n board: z.string().min(1).max(128).optional(),\n externalSource: externalSourceSchema.optional(),\n parentWorkItemId: uuidSchema.nullable().optional(),\n stages: stagesSchema.optional(),\n sessions: sessionsSchema.optional(),\n metadata: metadataSchema.optional(),\n});\n\nexport const updateWorkItemBodySchema = z\n .object({\n title: rawBoundedTrimmed(500).optional(),\n board: z.string().min(1).max(128).optional(),\n parentWorkItemId: uuidSchema.nullable().optional(),\n stages: stagesSchema.optional(),\n sessions: sessionsSchema.optional(),\n metadata: metadataSchema.optional(),\n plansPreapproved: z.literal(true).optional(),\n })\n .refine(input => Object.keys(input).length > 0, { message: 'At least one work-item field is required' });\n\nexport const transitionBodySchema = z\n .object({\n board: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n stage: z.string().max(MAX_BOARD_IDENTIFIER_LENGTH).regex(BOARD_IDENTIFIER_RE),\n expectedRevision: z.number().int().min(1),\n requestId: trimmedUuidSchema,\n cause: nonEmptyTrimmed(256),\n reenter: z.unknown().optional(),\n })\n .transform(input => ({\n board: input.board,\n stage: input.stage,\n expectedRevision: input.expectedRevision,\n ingress: { type: 'human' as const, identity: input.requestId },\n cause: input.cause,\n ...(input.reenter === true ? { reenter: true } : {}),\n }));\n\nexport const startWorkItemBodySchema = z.object({\n sessionId: trimmedUuidSchema,\n threadTitle: nonEmptyTrimmed(512),\n kickoffKey: trimmedUuidSchema,\n workItem: z.object({\n id: trimmedUuidSchema,\n role: nonEmptyTrimmed(32),\n input: createWorkItemBodySchema,\n }),\n});\n\nexport const metricsQuerySchema = z.object({\n from: z.string().optional(),\n to: z.string().optional(),\n});\n\nconst decisionStatusSchema = z.enum([\n 'pending',\n 'proposed',\n 'dismissed',\n 'superseded',\n 'leased',\n 'retry',\n 'succeeded',\n 'failed',\n]);\nconst boundedLimitSchema = (defaultValue: number, max: number) =>\n z\n .string()\n .optional()\n .transform(value => {\n const parsed = value ? Number.parseInt(value, 10) : defaultValue;\n return Number.isFinite(parsed) ? Math.max(1, Math.min(max, parsed)) : defaultValue;\n });\nconst decisionCursorSchema = z\n .string()\n .optional()\n .transform((value, context) => {\n if (!value) return undefined;\n try {\n const decoded = JSON.parse(Buffer.from(value, 'base64url').toString('utf8')) as unknown;\n if (\n !Array.isArray(decoded) ||\n decoded.length !== 2 ||\n typeof decoded[0] !== 'string' ||\n typeof decoded[1] !== 'string'\n ) {\n throw new Error('invalid cursor');\n }\n const createdAt = new Date(decoded[0]);\n if (Number.isNaN(createdAt.getTime()) || !new RegExp(UUID_PATTERN).test(decoded[1])) {\n throw new Error('invalid cursor');\n }\n return { createdAt, id: decoded[1] };\n } catch {\n context.addIssue({ code: 'custom', message: 'Invalid cursor' });\n return z.NEVER;\n }\n });\n\nexport const decisionQuerySchema = z.object({\n statuses: z\n .string()\n .optional()\n .transform(value => {\n if (!value) return undefined;\n const statuses = [...new Set(value.split(',').map(status => status.trim()))].filter(\n status => decisionStatusSchema.safeParse(status).success,\n ) as Array<z.infer<typeof decisionStatusSchema>>;\n return statuses.length > 0 ? statuses : undefined;\n }),\n before: decisionCursorSchema,\n limit: boundedLimitSchema(25, 50),\n});\n\nconst attentionKindSchema = z.enum([\n 'automation-failed',\n 'automation-proposed',\n 'mention',\n 'activity',\n 'supervisor-finding',\n 'agent-waiting',\n]);\ntype AttentionKind = z.infer<typeof attentionKindSchema>;\ntype AttentionStreamPosition = { occurredAt: Date; id: string };\ntype AttentionCursorMap = Map<AttentionKind, AttentionStreamPosition | undefined>;\n\nfunction parseAttentionStreamPosition(value: unknown): AttentionStreamPosition | undefined {\n if (!Array.isArray(value) || value.length !== 2 || typeof value[0] !== 'string' || typeof value[1] !== 'string') {\n return undefined;\n }\n const occurredAt = new Date(value[0]);\n if (Number.isNaN(occurredAt.getTime()) || !new RegExp(UUID_PATTERN).test(value[1])) return undefined;\n return { occurredAt, id: value[1] };\n}\n\nconst attentionCursorSchema = z\n .string()\n .optional()\n .transform((value, context) => {\n if (!value) return undefined;\n try {\n const decoded: unknown = JSON.parse(Buffer.from(value, 'base64url').toString('utf8'));\n if (Array.isArray(decoded)) {\n const legacy = parseAttentionStreamPosition(decoded);\n if (!legacy) throw new Error('invalid cursor');\n return new Map<AttentionKind, AttentionStreamPosition | undefined>([['automation-failed', legacy]]);\n }\n if (!decoded || typeof decoded !== 'object') throw new Error('invalid cursor');\n const cursors: AttentionCursorMap = new Map();\n for (const [kind, positionValue] of Object.entries(decoded)) {\n const parsedKind = attentionKindSchema.safeParse(kind);\n if (!parsedKind.success) throw new Error('invalid cursor');\n if (positionValue === null) {\n cursors.set(parsedKind.data, undefined);\n continue;\n }\n const position = parseAttentionStreamPosition(positionValue);\n if (!position) throw new Error('invalid cursor');\n cursors.set(parsedKind.data, position);\n }\n if (cursors.size === 0) throw new Error('invalid cursor');\n return cursors;\n } catch {\n context.addIssue({ code: 'custom', message: 'Invalid cursor' });\n return z.NEVER;\n }\n });\n\nexport const attentionQuerySchema = z.object({\n view: z.enum(['open', 'unread', 'archived']).optional().default('open'),\n kind: z.array(attentionKindSchema).optional(),\n before: attentionCursorSchema,\n limit: boundedLimitSchema(25, 50),\n search: z\n .string()\n .optional()\n .transform(value => value?.trim().toLowerCase().slice(0, 200) || undefined),\n});\n\nconst attentionActionPathSchema = z\n .object({\n id: uuidSchema,\n kind: attentionKindSchema,\n sourceId: z.string().min(1).max(256),\n occurrence: z\n .string()\n .regex(/^(0|[1-9]\\d*)$/)\n .transform((value, context) => {\n const occurrence = Number(value);\n if (Number.isSafeInteger(occurrence)) return occurrence;\n context.addIssue({ code: 'custom', message: 'Invalid occurrence' });\n return z.NEVER;\n }),\n })\n .refine(\n input =>\n input.kind === 'supervisor-finding'\n ? /^[a-z0-9:_-]{1,256}$/i.test(input.sourceId)\n : new RegExp(UUID_PATTERN).test(input.sourceId),\n { message: 'Invalid attention source id', path: ['sourceId'] },\n );\n\nexport const FACTORY_ROUTE_CONTRACTS = {\n projectList: {\n method: 'GET',\n path: '/web/factory/projects',\n description: 'List Factory projects for the current organization',\n responseSchema: z.object({ projects: z.array(projectSchema) }),\n },\n projectCreate: {\n method: 'POST',\n path: '/web/factory/projects',\n description: 'Create a Factory project',\n bodySchema: createProjectBodySchema,\n responseSchema: projectResponseSchema,\n },\n projectGet: {\n method: 'GET',\n path: '/web/factory/projects/:id',\n description: 'Get a Factory project',\n pathSchema: projectPathSchema,\n responseSchema: projectResponseSchema,\n },\n projectUpdate: {\n method: 'PATCH',\n path: '/web/factory/projects/:id',\n description: 'Update a Factory project',\n pathSchema: projectPathSchema,\n bodySchema: updateProjectBodySchema,\n responseSchema: projectResponseSchema,\n },\n projectDelete: {\n method: 'DELETE',\n path: '/web/factory/projects/:id',\n description: 'Delete a Factory project',\n pathSchema: projectPathSchema,\n responseSchema: z.null(),\n },\n metricsGet: {\n method: 'GET',\n path: '/web/factory/projects/:id/metrics',\n description: 'Get Factory project metrics',\n pathSchema: projectPathSchema,\n querySchema: metricsQuerySchema,\n responseSchema: z.object({ metrics: entitySchema }),\n },\n healthThresholdsGet: {\n method: 'GET',\n path: '/web/factory/projects/:id/health/thresholds',\n description: 'Get queue-health thresholds',\n pathSchema: projectPathSchema,\n responseSchema: z.object({ thresholds: z.array(z.number().finite()) }),\n },\n workItemList: {\n method: 'GET',\n path: '/web/factory/projects/:id/work-items',\n description: 'List Factory work items and running sessions',\n pathSchema: projectPathSchema,\n responseSchema: z.object({\n workItems: z.array(entitySchema),\n runningSessionIds: z.array(z.string()),\n parkedSessionIds: z.array(z.string()),\n }),\n },\n workItemCreate: {\n method: 'POST',\n path: '/web/factory/projects/:id/work-items',\n description: 'Create a work item in Intake',\n pathSchema: projectPathSchema,\n bodySchema: createWorkItemBodySchema,\n responseSchema: workItemResponseSchema,\n },\n workItemUpdate: {\n method: 'PATCH',\n path: '/web/factory/work-items/:id',\n description: 'Update non-stage work-item fields',\n pathSchema: workItemPathSchema,\n bodySchema: updateWorkItemBodySchema,\n responseSchema: workItemResponseSchema,\n },\n workItemDelete: {\n method: 'DELETE',\n path: '/web/factory/work-items/:id',\n description: 'Delete a Factory work item',\n pathSchema: workItemPathSchema,\n responseSchema: z.object({ ok: z.literal(true) }),\n },\n workItemTransition: {\n method: 'POST',\n path: '/web/factory/projects/:id/work-items/:workItemId/transition',\n description: 'Transition a work item with its expected revision',\n pathSchema: transitionPathSchema,\n bodySchema: transitionBodySchema,\n responseSchema: entitySchema,\n },\n workItemStart: {\n method: 'POST',\n path: '/web/factory/projects/:id/runs/start',\n description: 'Explicitly start a Factory work-item run',\n pathSchema: projectPathSchema,\n bodySchema: startWorkItemBodySchema,\n responseSchema: entitySchema,\n },\n decisionList: {\n method: 'GET',\n path: '/web/factory/projects/:id/decisions',\n description: 'List Factory decisions',\n pathSchema: projectPathSchema,\n querySchema: decisionQuerySchema,\n responseSchema: z.object({ decisions: z.array(entitySchema), nextCursor: z.string().optional() }),\n },\n decisionApprove: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/approve',\n description: 'Approve a proposed Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n decisionDismiss: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/dismiss',\n description: 'Dismiss a proposed Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n decisionRetry: {\n method: 'POST',\n path: '/web/factory/projects/:id/decisions/:decisionId/retry',\n description: 'Retry a failed retryable Factory decision',\n pathSchema: projectDecisionPathSchema,\n responseSchema: decisionResponseSchema,\n },\n attentionList: {\n method: 'GET',\n path: '/web/factory/projects/:id/attention',\n description: 'List the Factory attention inbox',\n pathSchema: projectPathSchema,\n querySchema: attentionQuerySchema,\n responseSchema: z.object({\n items: z.array(entitySchema),\n kinds: z.record(\n attentionKindSchema,\n z.object({\n open: z.number(),\n unread: z.number(),\n latest: z.object({ key: z.string(), at: z.string(), unread: z.boolean() }).nullable(),\n }),\n ),\n hasMore: z.boolean(),\n nextCursor: z.string().optional(),\n }),\n },\n attentionReadAll: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/read-all',\n description: 'Mark all Factory attention as read',\n pathSchema: projectPathSchema,\n querySchema: z.object({ before: attentionCursorSchema }),\n responseSchema: z.object({ ok: z.literal(true), hasMore: z.boolean(), nextCursor: z.string().optional() }),\n },\n attentionRead: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/read',\n description: 'Mark a Factory attention receipt as read',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n attentionArchive: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/archive',\n description: 'Archive a Factory attention receipt',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n attentionRestore: {\n method: 'POST',\n path: '/web/factory/projects/:id/attention/:kind/:sourceId/:occurrence/restore',\n description: 'Restore an archived Factory attention receipt',\n pathSchema: attentionActionPathSchema,\n responseSchema: z.object({ receipt: entitySchema }),\n },\n supervisorSession: {\n method: 'POST',\n path: '/web/factory/projects/:id/supervisor/session',\n description: 'Get the deterministic Factory supervisor session address',\n pathSchema: projectPathSchema,\n responseSchema: z.object({ sessionId: z.string(), threadId: z.string(), factoryProjectId: uuidSchema }),\n },\n supervisorHealth: {\n method: 'GET',\n path: '/web/factory/projects/:id/supervisor/health',\n description: 'Run the deterministic Factory supervisor health check',\n pathSchema: projectPathSchema,\n responseSchema: z.object({\n checkedAt: z.string(),\n findings: z.array(entitySchema),\n counts: z.record(z.string(), z.number().int().nonnegative()),\n }),\n },\n} as const satisfies Record<string, FactoryRouteContract>;\n\nexport type FactoryRouteContractKey = keyof typeof FACTORY_ROUTE_CONTRACTS;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Route } from './route.js';
|
|
2
|
+
import type { RouteDependencies } from './route.js';
|
|
3
|
+
interface TelemetryRoutesDeps extends RouteDependencies {
|
|
4
|
+
providerName?: string;
|
|
5
|
+
publicOrigin: string;
|
|
6
|
+
allowedOrigins: string[];
|
|
7
|
+
}
|
|
8
|
+
export declare class TelemetryRoutes extends Route<TelemetryRoutesDeps> {
|
|
9
|
+
private readonly budgets;
|
|
10
|
+
routes(): import("@mastra/core/server").ApiRoute[];
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/routes/telemetry.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAepD,UAAU,mBAAoB,SAAQ,iBAAiB;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,qBAAa,eAAgB,SAAQ,KAAK,CAAC,mBAAmB,CAAC;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuD;IAE/E,MAAM;CA6CP"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { captureFactoryWebActivity, isFactoryTelemetryEnabled } from "../telemetry.js";
|
|
2
|
+
import { Route } from "./route.js";
|
|
3
|
+
import { FACTORY_WEB_PAGES } from "../telemetry-types.js";
|
|
4
|
+
import { registerApiRoute } from "@mastra/core/server";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { bodyLimit } from "hono/body-limit";
|
|
7
|
+
//#region src/routes/telemetry.ts
|
|
8
|
+
const activitySchema = z.object({
|
|
9
|
+
activity: z.enum(["page_view", "interaction"]),
|
|
10
|
+
page: z.enum(FACTORY_WEB_PAGES)
|
|
11
|
+
}).strict();
|
|
12
|
+
function localContext(context) {
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
var TelemetryRoutes = class extends Route {
|
|
16
|
+
budgets = /* @__PURE__ */ new Map();
|
|
17
|
+
routes() {
|
|
18
|
+
const limitBody = bodyLimit({ maxSize: 512 });
|
|
19
|
+
const origins = /* @__PURE__ */ new Set([this.deps.publicOrigin, ...this.deps.allowedOrigins]);
|
|
20
|
+
return [registerApiRoute("/web/telemetry/activity", {
|
|
21
|
+
method: "POST",
|
|
22
|
+
middleware: (context, next) => limitBody(localContext(context), next),
|
|
23
|
+
handler: async (context) => {
|
|
24
|
+
const c = localContext(context);
|
|
25
|
+
if (!this.deps.auth.enabled()) return c.body(null, 401);
|
|
26
|
+
await this.deps.auth.ensureUser(c);
|
|
27
|
+
const actor = this.deps.auth.tenant(c);
|
|
28
|
+
if (!actor?.userId) return c.body(null, 401);
|
|
29
|
+
const origin = c.req.header("Origin");
|
|
30
|
+
if (origin && !origins.has(origin)) return c.body(null, 403);
|
|
31
|
+
if (c.req.header("Content-Type")?.split(";")[0]?.trim().toLowerCase() !== "application/json") return c.body(null, 415);
|
|
32
|
+
const parsed = activitySchema.safeParse(await c.req.json().catch(() => void 0));
|
|
33
|
+
if (!parsed.success) return c.body(null, 400);
|
|
34
|
+
if (!isFactoryTelemetryEnabled(this.deps.providerName)) return c.body(null, 204);
|
|
35
|
+
const key = JSON.stringify([actor.orgId, actor.userId]);
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
const previous = this.budgets.get(key);
|
|
38
|
+
if (previous && previous.until > now) {
|
|
39
|
+
if (previous.count >= 60) return c.body(null, 204);
|
|
40
|
+
previous.count += 1;
|
|
41
|
+
} else {
|
|
42
|
+
if (this.budgets.size >= 1e4) {
|
|
43
|
+
for (const [id, budget] of this.budgets) if (budget.until <= now) this.budgets.delete(id);
|
|
44
|
+
if (this.budgets.size >= 1e4) return c.body(null, 204);
|
|
45
|
+
}
|
|
46
|
+
this.budgets.set(key, {
|
|
47
|
+
until: now + 6e4,
|
|
48
|
+
count: 1
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
captureFactoryWebActivity(parsed.data, actor);
|
|
52
|
+
return c.body(null, 204);
|
|
53
|
+
}
|
|
54
|
+
})];
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
//#endregion
|
|
58
|
+
export { TelemetryRoutes };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","names":[],"sources":["../../src/routes/telemetry.ts"],"sourcesContent":["import { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\nimport { bodyLimit } from 'hono/body-limit';\nimport { z } from 'zod';\n\nimport { FACTORY_WEB_PAGES } from '../telemetry-types.js';\nimport { captureFactoryWebActivity, isFactoryTelemetryEnabled } from '../telemetry.js';\nimport { Route } from './route.js';\nimport type { RouteDependencies } from './route.js';\n\nconst activitySchema = z\n .object({\n activity: z.enum(['page_view', 'interaction']),\n page: z.enum(FACTORY_WEB_PAGES),\n })\n .strict();\n\n// Core bundles Hono declarations, so the same runtime Context has distinct\n// nominal request types across the package boundary (as in other route modules).\nfunction localContext(context: unknown): Context {\n return context as Context;\n}\n\ninterface TelemetryRoutesDeps extends RouteDependencies {\n providerName?: string;\n publicOrigin: string;\n allowedOrigins: string[];\n}\n\nexport class TelemetryRoutes extends Route<TelemetryRoutesDeps> {\n private readonly budgets = new Map<string, { until: number; count: number }>();\n\n routes() {\n const limitBody = bodyLimit({ maxSize: 512 });\n const origins = new Set([this.deps.publicOrigin, ...this.deps.allowedOrigins]);\n return [\n registerApiRoute('/web/telemetry/activity', {\n method: 'POST',\n middleware: (context, next) => limitBody(localContext(context), next),\n handler: async context => {\n const c = localContext(context);\n if (!this.deps.auth.enabled()) return c.body(null, 401);\n await this.deps.auth.ensureUser(c);\n const actor = this.deps.auth.tenant(c);\n if (!actor?.userId) return c.body(null, 401);\n const origin = c.req.header('Origin');\n if (origin && !origins.has(origin)) return c.body(null, 403);\n if (c.req.header('Content-Type')?.split(';')[0]?.trim().toLowerCase() !== 'application/json') {\n return c.body(null, 415);\n }\n const parsed = activitySchema.safeParse(await c.req.json().catch(() => undefined));\n if (!parsed.success) return c.body(null, 400);\n if (!isFactoryTelemetryEnabled(this.deps.providerName)) return c.body(null, 204);\n\n // Bound capture rate and memory per process; this is not a distributed\n // quota or a promise of exactly-once delivery.\n const key = JSON.stringify([actor.orgId, actor.userId]);\n const now = Date.now();\n const previous = this.budgets.get(key);\n if (previous && previous.until > now) {\n if (previous.count >= 60) return c.body(null, 204);\n previous.count += 1;\n } else {\n if (this.budgets.size >= 10_000) {\n for (const [id, budget] of this.budgets) {\n if (budget.until <= now) this.budgets.delete(id);\n }\n if (this.budgets.size >= 10_000) return c.body(null, 204);\n }\n this.budgets.set(key, { until: now + 60_000, count: 1 });\n }\n captureFactoryWebActivity(parsed.data, actor);\n return c.body(null, 204);\n },\n }),\n ];\n }\n}\n"],"mappings":";;;;;;;AAUA,MAAM,iBAAiB,EACpB,OAAO;CACN,UAAU,EAAE,KAAK,CAAC,aAAa,aAAa,CAAC;CAC7C,MAAM,EAAE,KAAK,iBAAiB;AAChC,CAAC,CAAC,CACD,OAAO;AAIV,SAAS,aAAa,SAA2B;CAC/C,OAAO;AACT;AAQA,IAAa,kBAAb,cAAqC,MAA2B;CAC9D,0BAA2B,IAAI,IAA8C;CAE7E,SAAS;EACP,MAAM,YAAY,UAAU,EAAE,SAAS,IAAI,CAAC;EAC5C,MAAM,0BAAU,IAAI,IAAI,CAAC,KAAK,KAAK,cAAc,GAAG,KAAK,KAAK,cAAc,CAAC;EAC7E,OAAO,CACL,iBAAiB,2BAA2B;GAC1C,QAAQ;GACR,aAAa,SAAS,SAAS,UAAU,aAAa,OAAO,GAAG,IAAI;GACpE,SAAS,OAAM,YAAW;IACxB,MAAM,IAAI,aAAa,OAAO;IAC9B,IAAI,CAAC,KAAK,KAAK,KAAK,QAAQ,GAAG,OAAO,EAAE,KAAK,MAAM,GAAG;IACtD,MAAM,KAAK,KAAK,KAAK,WAAW,CAAC;IACjC,MAAM,QAAQ,KAAK,KAAK,KAAK,OAAO,CAAC;IACrC,IAAI,CAAC,OAAO,QAAQ,OAAO,EAAE,KAAK,MAAM,GAAG;IAC3C,MAAM,SAAS,EAAE,IAAI,OAAO,QAAQ;IACpC,IAAI,UAAU,CAAC,QAAQ,IAAI,MAAM,GAAG,OAAO,EAAE,KAAK,MAAM,GAAG;IAC3D,IAAI,EAAE,IAAI,OAAO,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY,MAAM,oBACxE,OAAO,EAAE,KAAK,MAAM,GAAG;IAEzB,MAAM,SAAS,eAAe,UAAU,MAAM,EAAE,IAAI,KAAK,CAAC,CAAC,YAAY,KAAA,CAAS,CAAC;IACjF,IAAI,CAAC,OAAO,SAAS,OAAO,EAAE,KAAK,MAAM,GAAG;IAC5C,IAAI,CAAC,0BAA0B,KAAK,KAAK,YAAY,GAAG,OAAO,EAAE,KAAK,MAAM,GAAG;IAI/E,MAAM,MAAM,KAAK,UAAU,CAAC,MAAM,OAAO,MAAM,MAAM,CAAC;IACtD,MAAM,MAAM,KAAK,IAAI;IACrB,MAAM,WAAW,KAAK,QAAQ,IAAI,GAAG;IACrC,IAAI,YAAY,SAAS,QAAQ,KAAK;KACpC,IAAI,SAAS,SAAS,IAAI,OAAO,EAAE,KAAK,MAAM,GAAG;KACjD,SAAS,SAAS;IACpB,OAAO;KACL,IAAI,KAAK,QAAQ,QAAQ,KAAQ;MAC/B,KAAK,MAAM,CAAC,IAAI,WAAW,KAAK,SAC9B,IAAI,OAAO,SAAS,KAAK,KAAK,QAAQ,OAAO,EAAE;MAEjD,IAAI,KAAK,QAAQ,QAAQ,KAAQ,OAAO,EAAE,KAAK,MAAM,GAAG;KAC1D;KACA,KAAK,QAAQ,IAAI,KAAK;MAAE,OAAO,MAAM;MAAQ,OAAO;KAAE,CAAC;IACzD;IACA,0BAA0B,OAAO,MAAM,KAAK;IAC5C,OAAO,EAAE,KAAK,MAAM,GAAG;GACzB;EACF,CAAC,CACH;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAyC,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAyC,MAAM,+BAA+B,CAAC;AAU5G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAIxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,KAAK,EACV,6BAA6B,EAI7B,WAAW,EACX,gBAAgB,EACjB,MAAM,uCAAuC,CAAC;AAG/C,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EAAE,qBAAqB,EAA4C,MAAM,YAAY,CAAC;AA0LlG,KAAK,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,CAAC,CAAC;AA6BjH,MAAM,WAAW,8BAA8B;IAC7C,MAAM,EAAE,6BAA6B,CAAC;IACtC,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gCAAgC;IAC/C,UAAU,EAAE,iBAAiB,CAAC;IAC9B,iBAAiB,EAAE,IAAI,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC;IAChE,OAAO,EAAE,gBAAgB,CAAC;IAC1B,yEAAyE;IACzE,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wFAAwF;IACxF,gBAAgB,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5F,8FAA8F;IAC9F,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7F,oBAAoB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,8BAA8B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,8EAA8E;IAC9E,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAC/B,6BAA6B,CAAC,EAAE,CAAC,KAAK,EAAE;QACtC,KAAK,EAAE,MAAM,CAAC;QACd,gBAAgB,EAAE,MAAM,CAAC;QACzB,QAAQ,EAAE,OAAO,CAAC,qBAAqB,EAAE;YAAE,IAAI,EAAE,sBAAsB,CAAA;SAAE,CAAC,CAAC;KAC5E,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,sFAAsF;IACtF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8EAA8E;IAC9E,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,mCAAmC,CAAC,EAAE,MAAM,CAAC;CAC9C;AA+GD,qBAAa,yBAAyB;;gBAyBxB,OAAO,EAAE,gCAAgC;IA2BrD,KAAK,IAAI,IAAI;IAOP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,OAAO,CAAC,GAAG,OAAa,GAAG,OAAO,CAAC,IAAI,CAAC;CA81B/C;AAED,eAAO,MAAM,0BAA0B;;;;;;;;;;;CAW7B,CAAC"}
|
package/dist/rules/dispatcher.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { assertFactoryDecisionTarget, validateFactoryRuleDecision } from "./validation.js";
|
|
2
|
+
import { boardForWorkItem, resolvePhaseSemantics, workItemPhaseSemantics } from "../boards/semantics.js";
|
|
1
3
|
import { FACTORY_RULE_STAGES, externallyAuthoredWorkItem } from "./types.js";
|
|
2
|
-
import { validateFactoryRuleDecision } from "./validation.js";
|
|
3
|
-
import { resolvePhaseSemantics, workItemPhaseSemantics } from "../boards/semantics.js";
|
|
4
4
|
import { createBoardRegistry } from "../boards/registry.js";
|
|
5
5
|
import "../boards/index.js";
|
|
6
6
|
import { FACTORY_RULE_MATERIALIZATION_KEY } from "../storage/domains/work-items/base.js";
|
|
@@ -428,6 +428,7 @@ var FactoryDecisionDispatcher = class {
|
|
|
428
428
|
switch (decision.type) {
|
|
429
429
|
case "transition": {
|
|
430
430
|
const item = await this.#requireItem(record);
|
|
431
|
+
if (!await this.#storage.getTransitionResultByIngress(record.orgId, record.factoryProjectId, `decision:${record.idempotencyKey}`)) assertFactoryDecisionTarget(decision, this.#boards, item.board ?? void 0);
|
|
431
432
|
const result = await this.#transitionService.transition({
|
|
432
433
|
orgId: record.orgId,
|
|
433
434
|
factoryProjectId: record.factoryProjectId,
|
|
@@ -630,6 +631,19 @@ var FactoryDecisionDispatcher = class {
|
|
|
630
631
|
}
|
|
631
632
|
}
|
|
632
633
|
async #upsertLinkedItem(record, decision, causalChain) {
|
|
634
|
+
const existing = await this.#storage.getByProjectSource({
|
|
635
|
+
orgId: record.orgId,
|
|
636
|
+
factoryProjectId: record.factoryProjectId,
|
|
637
|
+
source: externalSourceForDecision(decision)
|
|
638
|
+
});
|
|
639
|
+
if (existing?.metadata?.["factoryRuleMaterializationKey"] === record.idempotencyKey) for (const suffix of ["destination", "initial-entry"]) {
|
|
640
|
+
const replay = await this.#storage.getTransitionResultByIngress(record.orgId, record.factoryProjectId, `decision:${record.idempotencyKey}:${existing.id}:${suffix}`);
|
|
641
|
+
if (replay?.status === "accepted" && replay.stage === decision.stage) return;
|
|
642
|
+
}
|
|
643
|
+
assertFactoryDecisionTarget(decision, this.#boards);
|
|
644
|
+
const definition = this.#boards.get(decision.board);
|
|
645
|
+
if (!definition) throw new Error("Factory decision target board is not installed.");
|
|
646
|
+
const initialPhase = definition.initialPhase;
|
|
633
647
|
const parentWorkItemId = record.workItemId ?? await this.#resolveLinkedWorkItemParentId?.({
|
|
634
648
|
orgId: record.orgId,
|
|
635
649
|
factoryProjectId: record.factoryProjectId,
|
|
@@ -643,7 +657,8 @@ var FactoryDecisionDispatcher = class {
|
|
|
643
657
|
externalSource: externalSourceForDecision(decision),
|
|
644
658
|
parentWorkItemId,
|
|
645
659
|
title: decision.title,
|
|
646
|
-
|
|
660
|
+
board: decision.board,
|
|
661
|
+
stages: [initialPhase],
|
|
647
662
|
sessions: {},
|
|
648
663
|
metadata: {
|
|
649
664
|
...decision.metadata,
|
|
@@ -652,6 +667,8 @@ var FactoryDecisionDispatcher = class {
|
|
|
652
667
|
},
|
|
653
668
|
reuseMode: "preserve"
|
|
654
669
|
});
|
|
670
|
+
const itemBoard = boardForWorkItem(result.item);
|
|
671
|
+
if (itemBoard !== decision.board) throw new Error(`The work item belongs to board "${itemBoard}", not "${decision.board}".`);
|
|
655
672
|
if (!result.item.parentWorkItemId && parentWorkItemId && parentWorkItemId !== result.item.id) {
|
|
656
673
|
const item = await this.#storage.setParentWorkItemIfMissing({
|
|
657
674
|
orgId: record.orgId,
|
|
@@ -680,7 +697,7 @@ var FactoryDecisionDispatcher = class {
|
|
|
680
697
|
}
|
|
681
698
|
}
|
|
682
699
|
const materializedByDecision = result.item.metadata?.[FACTORY_RULE_MATERIALIZATION_KEY] === record.idempotencyKey;
|
|
683
|
-
if (!materializedByDecision && (decision.stage ===
|
|
700
|
+
if (!materializedByDecision && (decision.stage === initialPhase || !result.item.stages.includes(initialPhase))) return;
|
|
684
701
|
const board = decision.board;
|
|
685
702
|
let expectedRevision = result.item.revision;
|
|
686
703
|
if (materializedByDecision) {
|
|
@@ -689,7 +706,7 @@ var FactoryDecisionDispatcher = class {
|
|
|
689
706
|
factoryProjectId: record.factoryProjectId,
|
|
690
707
|
workItemId: result.item.id,
|
|
691
708
|
board,
|
|
692
|
-
stage:
|
|
709
|
+
stage: initialPhase,
|
|
693
710
|
expectedRevision,
|
|
694
711
|
actor: deferredActor(record),
|
|
695
712
|
ingress: {
|
|
@@ -709,7 +726,7 @@ var FactoryDecisionDispatcher = class {
|
|
|
709
726
|
}
|
|
710
727
|
expectedRevision = initial.revision;
|
|
711
728
|
}
|
|
712
|
-
if (decision.stage ===
|
|
729
|
+
if (decision.stage === initialPhase) return;
|
|
713
730
|
const moved = await this.#transitionService.transition({
|
|
714
731
|
orgId: record.orgId,
|
|
715
732
|
factoryProjectId: record.factoryProjectId,
|