@hunsu/protocol 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +157 -0
  2. package/dist/command-decoder.d.ts +5 -0
  3. package/dist/command-decoder.js +329 -0
  4. package/dist/constants.d.ts +15 -0
  5. package/dist/constants.js +15 -0
  6. package/dist/decoder-helpers.d.ts +58 -0
  7. package/dist/decoder-helpers.js +1757 -0
  8. package/dist/errors.d.ts +14 -0
  9. package/dist/errors.js +28 -0
  10. package/dist/event-decoder.d.ts +5 -0
  11. package/dist/event-decoder.js +232 -0
  12. package/dist/index.d.ts +10 -0
  13. package/dist/index.js +10 -0
  14. package/dist/lifecycle.d.ts +67 -0
  15. package/dist/lifecycle.js +271 -0
  16. package/dist/model.d.ts +1058 -0
  17. package/dist/model.js +1 -0
  18. package/dist/primitives.d.ts +59 -0
  19. package/dist/primitives.js +135 -0
  20. package/dist/projection.d.ts +8 -0
  21. package/dist/projection.js +875 -0
  22. package/dist/prompt-template.d.ts +12 -0
  23. package/dist/prompt-template.js +83 -0
  24. package/dist/protocol-validation.d.ts +36 -0
  25. package/dist/protocol-validation.js +1139 -0
  26. package/dist/result.d.ts +20 -0
  27. package/dist/result.js +21 -0
  28. package/dist/workflow-helpers.d.ts +31 -0
  29. package/dist/workflow-helpers.js +193 -0
  30. package/dist/workflow.d.ts +10 -0
  31. package/dist/workflow.js +594 -0
  32. package/package.json +30 -0
  33. package/src/command-decoder.ts +292 -0
  34. package/src/constants.ts +27 -0
  35. package/src/decoder-helpers.ts +1672 -0
  36. package/src/errors.ts +38 -0
  37. package/src/event-decoder.ts +225 -0
  38. package/src/index.ts +43 -0
  39. package/src/lifecycle.ts +403 -0
  40. package/src/model.ts +1233 -0
  41. package/src/primitives.ts +196 -0
  42. package/src/projection.ts +1081 -0
  43. package/src/prompt-template.ts +97 -0
  44. package/src/protocol-validation.ts +1252 -0
  45. package/src/result.ts +35 -0
  46. package/src/workflow-helpers.ts +239 -0
  47. package/src/workflow.ts +753 -0
package/src/errors.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { err, type Result } from "./result.ts";
2
+
3
+ export class DomainInvariantError extends Error {
4
+ constructor(message: string) {
5
+ super(message);
6
+ this.name = "DomainInvariantError";
7
+ }
8
+ }
9
+
10
+ export type DomainWorkflowError = {
11
+ type: "DomainWorkflowError";
12
+ message: string;
13
+ };
14
+
15
+ export function workflowError(message: string): Result<never, DomainWorkflowError> {
16
+ return err({ type: "DomainWorkflowError", message });
17
+ }
18
+
19
+ export function toDomainWorkflowError(error: unknown): DomainWorkflowError {
20
+ return {
21
+ type: "DomainWorkflowError",
22
+ message: error instanceof Error ? error.message : String(error)
23
+ };
24
+ }
25
+
26
+ export function unwrapWorkflowResult<T>(result: Result<T, DomainWorkflowError>): T {
27
+ if (result.ok) {
28
+ return result.value;
29
+ }
30
+ throw new DomainInvariantError(result.error.message);
31
+ }
32
+
33
+ export function unwrapDomainModelResult<T>(result: Result<T, { message: string }>): T {
34
+ if (result.ok) {
35
+ return result.value;
36
+ }
37
+ throw new DomainInvariantError(result.error.message);
38
+ }
@@ -0,0 +1,225 @@
1
+ import {
2
+ workflowError,
3
+ type DomainWorkflowError
4
+ } from "./errors.ts";
5
+ import type {
6
+ DomainEvent
7
+ } from "./model.ts";
8
+ import {
9
+ makeDestinationId,
10
+ makeTeamName,
11
+ makeFailureReason,
12
+ makeHunsuId,
13
+ makeLineId,
14
+ makeMoveId,
15
+ makeRequestId,
16
+ makeSkillDraftId
17
+ } from "./primitives.ts";
18
+ import { ok, type Result } from "./result.ts";
19
+ import {
20
+ decodeArtifactRecord,
21
+ decodeDestinationSeed,
22
+ decodeDestinationSeedArray,
23
+ decodeHubPackageLock,
24
+ decodeHunsuOrigin,
25
+ decodeHunsuRecord,
26
+ decodeLineRecord,
27
+ decodeMoveRecord,
28
+ decodeNonEmptyText,
29
+ decodeOptionalAt,
30
+ decodeOptionalMoveId,
31
+ decodeOptionalNonEmptyText,
32
+ decodeRecord,
33
+ decodeRequestRecord,
34
+ decodeSkillBinding,
35
+ decodeSkillDraftRecord,
36
+ decodeNodeRecord,
37
+ type HarnessDecoder
38
+ } from "./decoder-helpers.ts";
39
+
40
+ export function decodeDomainEvent(value: unknown, decodeHarness: HarnessDecoder): Result<DomainEvent, DomainWorkflowError> {
41
+ const event = decodeRecord(value, "DomainEvent");
42
+ if (!event.ok) {
43
+ return event;
44
+ }
45
+ switch (event.value.type) {
46
+ case "HunsuOriginRegistered": {
47
+ const origin = decodeHunsuOrigin(event.value.origin, "event.origin");
48
+ if (!origin.ok) return origin;
49
+ const at = decodeOptionalAt(event.value.at, "event.at");
50
+ if (!at.ok) return at;
51
+ return ok({ type: "HunsuOriginRegistered", origin: origin.value, at: at.value });
52
+ }
53
+ case "InitialTeamCreated": {
54
+ const request = decodeRequestRecord(event.value.request, "event.request");
55
+ if (!request.ok) return request;
56
+ const line = decodeLineRecord(event.value.line, "event.line");
57
+ if (!line.ok) return line;
58
+ const destinations = decodeDestinationSeedArray(event.value.destinations, "event.destinations");
59
+ if (!destinations.ok) return destinations;
60
+ const harness = event.value.harness === undefined ? ok(undefined) : decodeHarness(event.value.harness);
61
+ if (!harness.ok) return harness;
62
+ const harnessLock = decodeHubPackageLock(event.value.harnessLock, "event.harnessLock", ["team"]);
63
+ if (!harnessLock.ok) return harnessLock;
64
+ const at = decodeOptionalAt(event.value.at, "event.at");
65
+ if (!at.ok) return at;
66
+ return ok({
67
+ type: "InitialTeamCreated",
68
+ request: request.value,
69
+ line: line.value,
70
+ destinations: destinations.value,
71
+ harness: harness.value,
72
+ harnessLock: harnessLock.value,
73
+ at: at.value
74
+ });
75
+ }
76
+ case "RequestCreated": {
77
+ const request = decodeRequestRecord(event.value.request, "event.request");
78
+ return request.ok ? ok({ type: "RequestCreated", request: request.value }) : request;
79
+ }
80
+ case "DestinationDeclared": {
81
+ const requestId = primitive(makeRequestId(event.value.requestId));
82
+ if (!requestId.ok) return requestId;
83
+ const destination = decodeDestinationSeed(event.value.destination, "event.destination");
84
+ if (!destination.ok) return destination;
85
+ const at = decodeOptionalAt(event.value.at, "event.at");
86
+ if (!at.ok) return at;
87
+ return ok({ type: "DestinationDeclared", requestId: requestId.value, destination: destination.value, at: at.value });
88
+ }
89
+ case "HarnessSeeded": {
90
+ const requestId = primitive(makeRequestId(event.value.requestId));
91
+ if (!requestId.ok) return requestId;
92
+ const harness = decodeHarness(event.value.harness);
93
+ if (!harness.ok) return harness;
94
+ const at = decodeOptionalAt(event.value.at, "event.at");
95
+ if (!at.ok) return at;
96
+ return ok({ type: "HarnessSeeded", requestId: requestId.value, harness: harness.value, at: at.value });
97
+ }
98
+ case "LineStarted": {
99
+ const line = decodeLineRecord(event.value.line, "event.line");
100
+ return line.ok ? ok({ type: "LineStarted", line: line.value }) : line;
101
+ }
102
+ case "SkillDraftCreated": {
103
+ const draft = decodeSkillDraftRecord(event.value.draft, "event.draft");
104
+ return draft.ok ? ok({ type: "SkillDraftCreated", draft: draft.value }) : draft;
105
+ }
106
+ case "SkillDraftAccepted": {
107
+ const draftId = primitive(makeSkillDraftId(event.value.draftId));
108
+ if (!draftId.ok) return draftId;
109
+ const skill = decodeSkillBinding(event.value.skill, "event.skill");
110
+ if (!skill.ok) return skill;
111
+ const at = decodeOptionalAt(event.value.at, "event.at");
112
+ if (!at.ok) return at;
113
+ return ok({ type: "SkillDraftAccepted", draftId: draftId.value, skill: skill.value, at: at.value });
114
+ }
115
+ case "SkillDraftDiscarded": {
116
+ const draftId = primitive(makeSkillDraftId(event.value.draftId));
117
+ if (!draftId.ok) return draftId;
118
+ const at = decodeOptionalAt(event.value.at, "event.at");
119
+ if (!at.ok) return at;
120
+ return ok({ type: "SkillDraftDiscarded", draftId: draftId.value, at: at.value });
121
+ }
122
+ case "NodeCreated": {
123
+ const node = decodeNodeRecord(event.value.node, "event.node", decodeHarness);
124
+ return node.ok ? ok({ type: "NodeCreated", node: node.value }) : node;
125
+ }
126
+ case "LinePaused":
127
+ case "LineResumed": {
128
+ const lineId = primitive(makeLineId(event.value.lineId));
129
+ if (!lineId.ok) return lineId;
130
+ const at = decodeOptionalAt(event.value.at, "event.at");
131
+ if (!at.ok) return at;
132
+ return ok({ type: event.value.type, lineId: lineId.value, at: at.value });
133
+ }
134
+ case "LineAccepted":
135
+ case "LineRejected": {
136
+ const lineId = primitive(makeLineId(event.value.lineId));
137
+ if (!lineId.ok) return lineId;
138
+ const reason = decodeOptionalNonEmptyText(event.value.reason, "event.reason");
139
+ if (!reason.ok) return reason;
140
+ const at = decodeOptionalAt(event.value.at, "event.at");
141
+ if (!at.ok) return at;
142
+ return ok({ type: event.value.type, lineId: lineId.value, reason: reason.value, at: at.value });
143
+ }
144
+ case "DestinationClaimed":
145
+ case "DestinationWorkStarted": {
146
+ const destinationId = primitive(makeDestinationId(event.value.destinationId));
147
+ if (!destinationId.ok) return destinationId;
148
+ const actor = decodeNonEmptyText(event.value.actor, "event.actor");
149
+ if (!actor.ok) return actor;
150
+ const at = decodeOptionalAt(event.value.at, "event.at");
151
+ if (!at.ok) return at;
152
+ return ok({ type: event.value.type, destinationId: destinationId.value, actor: actor.value, at: at.value });
153
+ }
154
+ case "DestinationBlocked": {
155
+ const destinationId = primitive(makeDestinationId(event.value.destinationId));
156
+ if (!destinationId.ok) return destinationId;
157
+ const reason = primitive(makeFailureReason(event.value.reason, "event.reason"));
158
+ if (!reason.ok) return reason;
159
+ const actor = decodeNonEmptyText(event.value.actor, "event.actor");
160
+ if (!actor.ok) return actor;
161
+ const at = decodeOptionalAt(event.value.at, "event.at");
162
+ if (!at.ok) return at;
163
+ return ok({ type: "DestinationBlocked", destinationId: destinationId.value, reason: reason.value, actor: actor.value, at: at.value });
164
+ }
165
+ case "MoveRecorded": {
166
+ const move = decodeMoveRecord(event.value.move, "event.move", decodeHarness);
167
+ return move.ok ? ok({ type: "MoveRecorded", move: move.value }) : move;
168
+ }
169
+ case "DestinationReached": {
170
+ const destinationId = primitive(makeDestinationId(event.value.destinationId));
171
+ if (!destinationId.ok) return destinationId;
172
+ const moveId = primitive(makeMoveId(event.value.moveId));
173
+ if (!moveId.ok) return moveId;
174
+ const at = decodeOptionalAt(event.value.at, "event.at");
175
+ if (!at.ok) return at;
176
+ return ok({ type: "DestinationReached", destinationId: destinationId.value, moveId: moveId.value, at: at.value });
177
+ }
178
+ case "HunsuRecorded": {
179
+ const hunsu = decodeHunsuRecord(event.value.hunsu, "event.hunsu", decodeHarness);
180
+ return hunsu.ok ? ok({ type: "HunsuRecorded", hunsu: hunsu.value }) : hunsu;
181
+ }
182
+ case "LineForkedByHunsu": {
183
+ const hunsuId = primitive(makeHunsuId(event.value.hunsuId));
184
+ if (!hunsuId.ok) return hunsuId;
185
+ const fromLineId = primitive(makeLineId(event.value.fromLineId));
186
+ if (!fromLineId.ok) return fromLineId;
187
+ const newLineId = primitive(makeLineId(event.value.newLineId));
188
+ if (!newLineId.ok) return newLineId;
189
+ const rawNewTeamName = event.value.newTeamName ?? event.value.newTeamName;
190
+ const newTeamName = rawNewTeamName === undefined
191
+ ? ok(undefined)
192
+ : primitive(makeTeamName(rawNewTeamName, rawNewTeamName === event.value.newTeamName ? "event.newTeamName" : "event.newTeamName"));
193
+ if (!newTeamName.ok) return newTeamName;
194
+ const fromMoveId = decodeOptionalMoveId(event.value.fromMoveId);
195
+ if (!fromMoveId.ok) return fromMoveId;
196
+ const requestId = primitive(makeRequestId(event.value.requestId));
197
+ if (!requestId.ok) return requestId;
198
+ const at = decodeOptionalAt(event.value.at, "event.at");
199
+ if (!at.ok) return at;
200
+ return ok({
201
+ type: "LineForkedByHunsu",
202
+ hunsuId: hunsuId.value,
203
+ fromLineId: fromLineId.value,
204
+ newLineId: newLineId.value,
205
+ newTeamName: newTeamName.value,
206
+ fromMoveId: fromMoveId.value,
207
+ requestId: requestId.value,
208
+ at: at.value
209
+ });
210
+ }
211
+ case "ArtifactRecorded": {
212
+ const artifact = decodeArtifactRecord(event.value.artifact, "event.artifact");
213
+ if (!artifact.ok) return artifact;
214
+ const at = decodeOptionalAt(event.value.at, "event.at");
215
+ if (!at.ok) return at;
216
+ return ok({ type: "ArtifactRecorded", artifact: artifact.value, at: at.value });
217
+ }
218
+ default:
219
+ return workflowError(`Unsupported Hunsu domain event type: ${String(event.value.type)}`);
220
+ }
221
+ }
222
+
223
+ function primitive<T>(result: Result<T, { message: string }>): Result<T, DomainWorkflowError> {
224
+ return result.ok ? ok(result.value) : workflowError(result.error.message);
225
+ }
package/src/index.ts ADDED
@@ -0,0 +1,43 @@
1
+ export * from "./model.ts";
2
+ export * from "./errors.ts";
3
+ export {
4
+ cloneHarnessPlanner,
5
+ cloneHarnessEntity,
6
+ composeHarnessSnapshot,
7
+ cloneHarness,
8
+ createDefaultHarness,
9
+ createDefaultManagerConfig,
10
+ createDefaultMemberConfig,
11
+ DEFAULT_MANAGER_PROMPT,
12
+ DEFAULT_TEAM_PROMPT,
13
+ DEFAULT_MEMBER_APPROVAL,
14
+ DEFAULT_MEMBER_EXECUTION,
15
+ getHarnessExecutor,
16
+ getHarnessMember,
17
+ getHarnessTeam,
18
+ harnessPlannerFromSnapshot,
19
+ harnessEntityFromSnapshot,
20
+ harnessSnapshotForTeam,
21
+ getHarnessMemberConfig,
22
+ isExecutableHarness,
23
+ memberConfigFromMemberEntity,
24
+ rootHarnessSnapshot,
25
+ updateHarnessTeamPromptTemplate,
26
+ updateHarnessMemberConfig,
27
+ validateManagerConfig,
28
+ validateMemberConfig,
29
+ validateHarnessEntity,
30
+ validateHarnessPlanner,
31
+ validateHarness,
32
+ validateExecutableHarness
33
+ } from "./protocol-validation.ts";
34
+ export * from "./workflow.ts";
35
+ export { nextTeamName } from "./workflow-helpers.ts";
36
+ export * from "./result.ts";
37
+ export * from "./primitives.ts";
38
+ export * from "./prompt-template.ts";
39
+ export * from "./lifecycle.ts";
40
+ export {
41
+ decodeArtifactActionDefinition,
42
+ decodeArtifactActionDefinitionArray
43
+ } from "./decoder-helpers.ts";